dsh-root-planner-preset 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build-patch.mjs CHANGED
@@ -177,7 +177,12 @@ const patch = `# Generated by build-patch.mjs from persona.txt. Do not hand-edit
177
177
  config:
178
178
  provider: fork
179
179
  toolName: subagent_fork
180
- agentPreset: root-planner-worker
180
+ # No agentPreset, on purpose. The fork provider declares
181
+ # inheritsParentContext true and agentPreset false, and configuring a
182
+ # preset for it makes the row throw at activation — which is exactly how
183
+ # the first attempt at this migration made the whole preset fail to load.
184
+ # A forked child inherits its parent's preset: from a worker that is
185
+ # still the worker preset, from the root it is the root preset.
181
186
  - id: tool-subagent-codex
182
187
  name: '@deepseek-ai/dsh-tool-subagent'
183
188
  disabled: true
@@ -319,7 +324,7 @@ const patch = `# Generated by build-patch.mjs from persona.txt. Do not hand-edit
319
324
  config:
320
325
  provider: fork
321
326
  toolName: subagent_fork
322
- agentPreset: root-planner-worker
327
+ # Inherits its parent's preset; see the note on the root preset's fork row.
323
328
  - id: tool-ask-user
324
329
  name: '@deepseek-ai/dsh-tool-ask-user'
325
330
  - id: tool-todo
package/cordis.patch.yml CHANGED
@@ -194,7 +194,12 @@
194
194
  config:
195
195
  provider: fork
196
196
  toolName: subagent_fork
197
- agentPreset: root-planner-worker
197
+ # No agentPreset, on purpose. The fork provider declares
198
+ # inheritsParentContext true and agentPreset false, and configuring a
199
+ # preset for it makes the row throw at activation — which is exactly how
200
+ # the first attempt at this migration made the whole preset fail to load.
201
+ # A forked child inherits its parent's preset: from a worker that is
202
+ # still the worker preset, from the root it is the root preset.
198
203
  - id: tool-subagent-codex
199
204
  name: '@deepseek-ai/dsh-tool-subagent'
200
205
  disabled: true
@@ -407,7 +412,7 @@
407
412
  config:
408
413
  provider: fork
409
414
  toolName: subagent_fork
410
- agentPreset: root-planner-worker
415
+ # Inherits its parent's preset; see the note on the root preset's fork row.
411
416
  - id: tool-ask-user
412
417
  name: '@deepseek-ai/dsh-tool-ask-user'
413
418
  - id: tool-todo
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-root-planner-preset",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "type": "module",
5
5
  "description": "DSH agent preset: the root agent plans and decides, subagent workers read, write and run commands inside their own _agents/ workspace, and nothing outlives its task.",
6
6
  "license": "MIT",
@@ -74,6 +74,19 @@ check(depthPatch?.insert === undefined, 'override is not an insert patch');
74
74
  // whenever the profile re-composes — so its content is the evidence that the
75
75
  // edit was picked up rather than merely written.
76
76
  const composed = yaml.load(readFileSync(COMPOSED, 'utf8'), { schema: loaderSchema });
77
+ // `cordis.yml` is a runtime cache, not a source: its own header calls it "an empty entry
78
+ // list" and says the tree is composed from patches at startup. An empty file therefore
79
+ // means the harness has not rewritten the composition yet on this machine, not that the
80
+ // override is missing. Treating it as failure produced four red checks after a
81
+ // `--dump-config` reset the file — a red that said nothing about the preset.
82
+ if (!Array.isArray(composed) || composed.length === 0) {
83
+ process.stdout.write(
84
+ 'SKIP the composed-profile checks: cordis.yml still holds the empty template that the\n' +
85
+ 'harness rewrites at startup. Start dsh once, then re-run this script.\n',
86
+ );
87
+ process.stdout.write(failures.length === 0 ? '\nALL CHECKS PASSED\n' : `\n${failures.length} CHECK(S) FAILED\n`);
88
+ process.exit(failures.length === 0 ? 0 : 1);
89
+ }
77
90
  const subagentRows = composed.filter((row) => row.id === 'subagent');
78
91
  check(subagentRows.length === 1, `exactly one subagent row in the composition (found ${subagentRows.length})`);
79
92
  check(subagentRows[0]?.name === '@deepseek-ai/dsh-subagent', 'the composition row matches the asserted name');
package/verify-patch.mjs CHANGED
@@ -161,26 +161,46 @@ check(
161
161
  const workerDelegation = workerPlugins.find((row) => row.id === 'delegation');
162
162
  const workerDelegationRows = workerDelegation?.config ?? [];
163
163
 
164
- // Loader row id -> the model-facing tool name that row publishes.
164
+ // Loader row id -> the model-facing tool name that row publishes, plus the provider whose
165
+ // capability decides whether a preset may be selected for it.
165
166
  const childTools = [
166
- { id: 'tool-subagent', toolName: 'subagent' },
167
- { id: 'tool-subagent-fork', toolName: 'subagent_fork' },
168
- ].map(({ id, toolName }) => {
167
+ { id: 'tool-subagent', toolName: 'subagent', provider: 'spawn' },
168
+ { id: 'tool-subagent-fork', toolName: 'subagent_fork', provider: 'fork' },
169
+ ].map(({ id, toolName, provider }) => {
169
170
  const row = delegationRows.find((entry) => entry.id === id);
170
171
  check(row !== undefined, `delegation declares ${id}`);
171
172
  check(row?.config?.toolName === toolName, `${id} publishes the tool name ${toolName}`);
172
- check(row?.config?.agentPreset === 'root-planner-worker', `${id} spawns into the worker preset`);
173
+ check(row?.config?.provider === provider, `${id} uses the ${provider} provider`);
173
174
  check(
174
175
  row?.config?.toolFilter === undefined,
175
176
  `${id} carries no toolFilter (DSH 0.2.1 removed it and strips it silently)`,
176
177
  );
177
- // A grandchild must land in the worker preset too, or the tree degrades at depth 2:
178
- // the platform default persona and the full tool list come back one level down.
179
- const nested = workerDelegationRows.find((entry) => entry.id === id);
180
- check(nested?.config?.agentPreset === 'root-planner-worker', `worker ${id} spawns into the worker preset too`);
181
- return { id, toolName };
178
+ // Only the spawn provider supports independent preset selection. A grandchild spawned
179
+ // through it must land in the worker preset too, or the tree degrades at depth 2: the
180
+ // platform default persona and the full tool list come back one level down.
181
+ if (provider === 'spawn') {
182
+ check(row?.config?.agentPreset === 'root-planner-worker', `${id} spawns into the worker preset`);
183
+ const nested = workerDelegationRows.find((entry) => entry.id === id);
184
+ check(nested?.config?.agentPreset === 'root-planner-worker', `worker ${id} spawns into the worker preset too`);
185
+ }
186
+ return { id, toolName, provider };
182
187
  });
183
188
 
189
+ // The fork provider declares `agentPreset: false` together with
190
+ // `inheritsParentContext: true`, and its row throws at activation when a preset is
191
+ // configured for it — which is what made the whole preset fail to load on DSH 0.2.1.
192
+ // Assert the absence in both presets so a later edit cannot reintroduce it.
193
+ for (const [label, rows] of [
194
+ ['the root preset', delegationRows],
195
+ ['the worker preset', workerDelegationRows],
196
+ ]) {
197
+ const fork = rows.find((entry) => entry.id === 'tool-subagent-fork');
198
+ check(
199
+ fork?.config?.agentPreset === undefined,
200
+ `${label} sets no agentPreset on the fork row (the fork provider rejects one)`,
201
+ );
202
+ }
203
+
184
204
  // A subagent is a worker: the curated set keeps the write and shell tools.
185
205
  for (const worker of ['read', 'write', 'edit', 'ops_replace', 'pwsh']) {
186
206
  check(CHILD_TOOLS.includes(worker), `the curated set keeps ${worker} (a subagent must be able to work)`);