dsh-plugin-split-and-solve
DSH plugin: split batch / multi-subproblem research tasks into small questions and solve them with sub-agents
- Stars
- 0
- Language
- JavaScript
- Created
- Aug 29, 2026
- Updated
- Aug 29, 2026
Introduction
dsh-plugin-split-and-solve(拆而解之)
Split a large research request into independent sub-questions, solve them with the harness's built-in
subagenttool in parallel, then merge the answers into one auditable deliverable.
dsh-plugin · MIT · needs no network, no native deps, no build step
What it is
A DSH plugin whose executable logic is a skill
(skills/split-and-solve/SKILL.md), i.e. markdown instructions that the agent loads on demand.
The Cordis entry point (lib/index.js) is a thin shell: it verifies the skill is present,
normalises configuration against documented defaults, and logs that the plugin is enabled.
The pipeline has three stages and lives entirely on top of harness capabilities (skills / subagents / file writes) — nothing in DSH itself is modified:
- Decompose — turn the request plus its input list into a strict-JSON list of mutually
independent sub-questions. Each carries a self-contained prompt and a
sourceRefpointing back to the exact input item it came from (DOI / arXiv id / file path / user's own numbering). - Solve — dispatch one subagent per sub-question via the harness's built-in
subagenttool, in parallel. Subagents do not share the main context, so everything they need is pasted into their prompt. Model routing is inherited: nomodel/provideris ever passed. - Merge — collect the structured returns and align them: one row per sub-question,
conflicts flagged (never adjudicated), a mandatory gap list,
sourceRefpreserved on every row, and everything written to disk.
Three hard rules the whole package is built around:
| Rule | How it is enforced |
|---|---|
| Nothing gets dropped | MERGE_REPORT.rowsInTable must equal the number of split items; failed items keep a placeholder row and appear in the gap list — they never silently vanish. |
| Nothing is invented | Workers write the literal 未查到 (not found) for anything they could not verify, especially titles, DOIs, dataset sizes, metric values, hyperparameters, versions. The merger may not "reasonably complete" a gap. |
| No overreach | The plan is shown for confirmation before dispatch (default), and subagents inherit the main conversation's model route. |
Why this exists(为什么做这个)
一篇论文,任何 LLM 都能干好:给它摘要、给它全文,让它按"问题 / 方法 / 数据与基准 / 主要指标 / 局限"总结,出来的东西能用。
难的是几十篇。你把 37 个 DOI 一次性贴进对话框,说"逐篇按五栏总结,最后给一张横向对比表"。 模型不会拒绝你,它会非常努力地做完 —— 然后:
- 中段被吞掉:第 3 篇的指标被记到第 12 篇头上,或者第 15 到 22 篇只得到一句"其余类似";
- 越往后越短:前 5 篇每篇 300 字,最后 5 篇每篇 40 字——不是它不想写,是上下文满了;
- 张冠李戴:A 文的 AUROC 被写到 B 文那行,而且它不会告诉你它是从哪一行开始猜的;
- 没人负责冲突:同一个指标在两处出现两个数值,模型倾向于挑一个"看起来更靠谱"的,把矛盾 抹平——而你写论文时恰恰需要知道那里有矛盾。
这些症状的共同原因是一个上下文承担 N 份互不相关的细节。而每一份单独做都很容易。
所以这个插件只做一件事:拆而解之。把大请求拆成 N 个互相独立的小问题,每个丢给一个
harness 自带的子代理(subagent,模型跟随主对话默认路由),并行做完,再由合并器把 N 份结果
对齐成一张表:每行一条、每格都带 sourceRef、矛盾只标注不裁决、没做完的进缺失清单。
主上下文里只留清单、摘要和表格 —— 不溢出、不遗漏、越往后越不塌。
同样的流程覆盖三类高频场景:批量文献精读(N 个 DOI 逐篇五栏总结 + 对比表)、
综述多子问题(提纲 6 块分别成文再串成章)、审稿意见逐条回复(每条意见一个
reply_draft,合并成 point-by-point 回复信 + 待补实验清单)。
Install(两种路径,按事实写)
静态插件在 DSH 里的形态 =
package.json(含dsh.profile.bundles)+lib/index.js导出的 Cordis Plugin 对象({ apply(ctx, config) {} }),并按cordis.patch.yml的字段 (id/name/config/disabled/inject/group/isolate/insert)挂载。 没有独立的 manifest 文件。
A. As a Cordis plugin (full integration: entry + config + skill bundle)
dsh plugin --profile <profile-name> add D:\codingspace\dsh-plugin-split-and-solve
# or, from a git address once published:
dsh plugin --profile <profile-name> add <git-url-of-this-repo>
DSH writes the equivalent patch entry into that profile. If you prefer to mount it by hand,
merge the entry from cordis.patch.yml into your profile's patch file —
it points at lib/index.js and carries every documented config key with its default value.
Honest caveats about path A(写这份骨架时未逐项实测的部分):
package.json里的dsh.profile.bundles: ["skills/split-and-solve"]是本包按"静态插件 = package.json 带有序 bundles"这一约定写的;确切字段名以你本机 DSH 版本为准。cordis.patch.yml的顶层键写作plugins:(profile patch 的常见形态)。若你的 DSH 要求顶层键 为patch:或要求一个裸列表,只改这一行,条目内容不变。insert写作相对入口lib/index.js;若你的 DSH 以绝对路径解析本地插件,改成D:\codingspace\dsh-plugin-split-and-solve\lib\index.js。lib/index.js的apply()只做"确认技能就位 + 归一化配置 + 记一条日志"。技能登记接口 (ctx.skill.add之类)按存在性探测、失败即忽略:本包没有对任何未经确认的 ctx 方法做 硬调用,所以路径 A 不会因为接口猜测而抛错。
验证接线是否成功(不需要跑真实任务):
dsh --dump-config # 确认 patch 条目与 config 段被读入
node -e "require('./lib/index.js').apply({}, {})" && echo entry-ok
npm run check
B. Skill-directory copy (fastest, zero wiring)
Copy skills/split-and-solve/ into your harness's skill directory and make sure the sibling
content/ directory is reachable (the skill reads its full prompt templates from there):
<skills-dir>/split-and-solve/SKILL.md
Skills are auto-discovered from the skill directory: it becomes invocable as /split-and-solve
and the model may invoke it automatically (frontmatter sets user-invocable: true and
disable-model-invocation: false). In this mode lib/index.js is not loaded at all — that is
fine, because it holds no logic. If you take this route, also copy the content/ directory
next to the skill (or keep using this repo in place); without it the skill still runs from its
own summary and says so in the deliverable header.
Usage(用法,中文)
一个简化例子(完整三条端到端示例见 content/examples.md —— 注意其中的
DOI、数据集名与指标数值均为示意,不是真实文献的事实断言):
/split-and-solve 帮我把这 5 篇做 GNN 药物发现的论文逐篇按【问题 / 方法 / 数据与基准 /
主要指标 / 局限】五栏总结,最后给一张横向对比表,另外告诉我哪几篇的可复现性最差:
1. DOI:10.1093/bioinformatics/btaa210(示意)
2. arXiv:2105.03904v2(示意)
3. /data/papers/mol-contrastive-2023.pdf(示意,本地 PDF)
4. DOI:10.1038/s41467-022-30123-4(示意)
5. DOI:10.1145/3459637.3482278(示意)
摘要我没贴,你按标识符自己去取;取不到就别猜。
发生什么:
- 检测:显式命令直接启用;不带命令时,"3 个 DOI + 逐篇/对比"也已满足自动建议阈值
(结构特征任一维度 ≥
minTriggerCount=3 且有批量意图词)。 - 拆分:产出 5 个小问题的 JSON 清单,每条一个自包含提示(目标 / 输入 / 输出格式含示例行 /
长度上限 / "查不到写未查到"),
sourceRef逐字搬运你的标识符(v2这类版本后缀保留)。 - 确认:先把"拆成 5 条 + 每条标题 + 合并后长什么样"给你看,回"开始"才派发
(
confirmSplitPlan = true;想跳过就带--yes)。 - 求解:5 次 harness
subagent调用并行发出,不指定 model / provider(跟随主对话默认 路由);每条按STATUS / CONFIDENCE / RESULT / GAPS / META五段返回,原文落盘。 - 合并:对齐成对比表(列 > 8 时退化为卡片 + 速览表),
⚠️冲突只标注不裁决,—(未查到)与—(未报告)严格区分,缺失清单必给,每行首列是可回查的sourceRef。 - 收尾:告诉你交付物在哪、哪些条没解决、卡在哪、哪几处冲突要你裁决。
交付物落盘(默认 ./split-and-solve-output/<日期>-<主题>/,相对当前会话工作目录):
00-split-plan.json 拆分方案原样
01-merged.md 交付物(对比表 / 分节综述 / 回复信)
02-gaps-and-conflicts.md 冲突清单 + 缺失清单全文
subagent-outputs/ 每个子代理的原样返回(<id>-<sourceRef 安全化>.md)—— 回查唯一依据
显式命令与开关(语义固定;slash 注册形态由 harness 决定,未注册时把这句话当普通文本处理):
/split-and-solve <任务>、/split-and-solve(对上一条启用)、--yes、--group、--no-merge、
--max N、/split-and-solve list、/split-and-solve retry Q03 Q07;
禁用说法:别拆 / 直接答 / no split / just answer / in one go。
Configuration
Defaults and semantics are defined in content/config-defaults.md
and mirrored in cordis.patch.yml's config: block. lib/index.js clamps the same way.
| key | default | meaning |
|---|---|---|
minTriggerCount | 3 | structural signals needed before auto-suggesting (clamped to ≥ 2) |
maxSubQuestions | 12 | split ceiling; beyond it items are grouped by theme (clamped to ≤ 30) |
subagentRetryOnFailure | 1 | retry once per failed/timed-out/empty item, carrying the reason (clamped to ≤ 2) |
outputDir | ./split-and-solve-output/<date>-<topic>/ | deliverable root, relative to the session working directory |
confirmSplitPlan | true | show the plan and wait for confirmation before dispatch |
autoTrigger | true | false = respond only to the explicit command |
maxParallelSubagents | 4 | in-flight cap; the rest queue |
subagentTimeoutSeconds | 300 | soft timeout per item, counts as failed(timeout) |
autoMerge | true | false = stop at per-item results until you say "merge" |
mergeTableMaxCellChars | 220 | cell truncation threshold, pointer to the raw output retained |
outputLanguage | auto | deliverable language (auto follows your request; JSON keys stay English) |
groupWhenTooMany | true | false = return needsClarification and ask you to narrow the list |
keepRawOutputs | true | keep subagent-outputs/ — the only trustworthy raw evidence behind any cell |
Not configurable on purpose: subagents are always dispatched without model / provider, so
they inherit the main conversation's route.
Repository layout
package.json name/version/main/license + keywords + dsh.profile.bundles
cordis.patch.yml Cordis patch entry (id/name/disabled/isolate/insert/config)
lib/index.js Cordis plugin shell — verify + normalise config + log, no logic
skills/split-and-solve/SKILL.md THE executable logic (6 stages, frontmatter-declared skill)
content/ prompt library the skill reads
trigger-rules.md P0–P4 detection, counting rules, false-positive guards, scripts
decompose-prompt.md decomposer prompt (R1–R7, JSON schema, C1–C4, self-check S1–S5)
solve-prompt.md worker prompt (L1–L6, 5-section contract) + dispatch rules
merge-prompt.md merger prompt (M1–M8, B1–B7) + conflict decision table
config-defaults.md config keys, defaults, outputDir expansion, injection points
examples.md three end-to-end examples (all identifiers illustrative)
README.zh.md Chinese draft sections: how it works, three scenarios
LICENSE MIT
.gitignore
split-and-solve-output/ (created at runtime) is git-ignored.
GitHub topic
This repo is intended to carry the GitHub topic dsh-plugin — the same string is the first
entry of keywords in package.json. Topics are repository metadata, not a package.json field,
so after publishing set it explicitly: Repository → About → Topics → dsh-plugin (or
gh repo edit --add-topic dsh-plugin). That is what makes the plugin discoverable by people
browsing the topic, which is how the other local plugins (dsh-skill-picker, dsh-mneme,
free-search) are found today.
Notes
- No runtime dependencies, no build step, no network access from the plugin shell itself.
lib/index.jscalls nothing onctxexcept an optional, existence-probedlogger.- Everything in
content/examples.md(DOIs, arXiv ids, dataset names, metric values) is illustrative — it demonstrates the shape of a run and asserts nothing about real literature.
License
MIT — see LICENSE.