Back to home@uppercrusteve

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 subagent tool 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:

  1. 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 sourceRef pointing back to the exact input item it came from (DOI / arXiv id / file path / user's own numbering).
  2. Solve — dispatch one subagent per sub-question via the harness's built-in subagent tool, in parallel. Subagents do not share the main context, so everything they need is pasted into their prompt. Model routing is inherited: no model / provider is ever passed.
  3. Merge — collect the structured returns and align them: one row per sub-question, conflicts flagged (never adjudicated), a mandatory gap list, sourceRef preserved on every row, and everything written to disk.

Three hard rules the whole package is built around:

RuleHow it is enforced
Nothing gets droppedMERGE_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 inventedWorkers 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 overreachThe 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.jsapply() 只做"确认技能就位 + 归一化配置 + 记一条日志"。技能登记接口 (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(示意)

摘要我没贴,你按标识符自己去取;取不到就别猜。

发生什么:

  1. 检测:显式命令直接启用;不带命令时,"3 个 DOI + 逐篇/对比"也已满足自动建议阈值 (结构特征任一维度 ≥ minTriggerCount=3 且有批量意图词)。
  2. 拆分:产出 5 个小问题的 JSON 清单,每条一个自包含提示(目标 / 输入 / 输出格式含示例行 / 长度上限 / "查不到写未查到"),sourceRef 逐字搬运你的标识符(v2 这类版本后缀保留)。
  3. 确认:先把"拆成 5 条 + 每条标题 + 合并后长什么样"给你看,回"开始"才派发 (confirmSplitPlan = true;想跳过就带 --yes)。
  4. 求解:5 次 harness subagent 调用并行发出,不指定 model / provider(跟随主对话默认 路由);每条按 STATUS / CONFIDENCE / RESULT / GAPS / META 五段返回,原文落盘。
  5. 合并:对齐成对比表(列 > 8 时退化为卡片 + 速览表),⚠️冲突 只标注不裁决, —(未查到)—(未报告) 严格区分,缺失清单必给,每行首列是可回查的 sourceRef
  6. 收尾:告诉你交付物在哪、哪些条没解决、卡在哪、哪几处冲突要你裁决。

交付物落盘(默认 ./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.

keydefaultmeaning
minTriggerCount3structural signals needed before auto-suggesting (clamped to ≥ 2)
maxSubQuestions12split ceiling; beyond it items are grouped by theme (clamped to ≤ 30)
subagentRetryOnFailure1retry 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
confirmSplitPlantrueshow the plan and wait for confirmation before dispatch
autoTriggertruefalse = respond only to the explicit command
maxParallelSubagents4in-flight cap; the rest queue
subagentTimeoutSeconds300soft timeout per item, counts as failed(timeout)
autoMergetruefalse = stop at per-item results until you say "merge"
mergeTableMaxCellChars220cell truncation threshold, pointer to the raw output retained
outputLanguageautodeliverable language (auto follows your request; JSON keys stay English)
groupWhenTooManytruefalse = return needsClarification and ask you to narrow the list
keepRawOutputstruekeep 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.js calls nothing on ctx except an optional, existence-probed logger.
  • 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.