dsh-plugin-prompt-tool 0.1.2 → 0.1.3

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/package.json CHANGED
@@ -1,88 +1,96 @@
1
- {
2
- "name": "dsh-plugin-prompt-tool",
3
- "version": "0.1.2",
4
- "description": "DSH 插件:提示词工具,规范模型的思维链与回答内容,提供 Web UI 编辑 preset.md 与 AGENTS.md,并按 skills 目录注册可开关技能。",
5
- "license": "MIT",
6
- "repository": {
7
- "type": "git",
8
- "url": "git+https://github.com/Czerror/dsh-plugin-prompt-tool.git"
9
- },
10
- "type": "module",
11
- "main": "lib/index.mjs",
12
- "types": "lib/index.d.mts",
13
- "exports": {
14
- ".": {
15
- "types": "./lib/index.d.mts",
16
- "default": "./lib/index.mjs"
17
- },
18
- "./client": "./lib/client.js",
19
- "./package.json": "./package.json"
20
- },
21
- "engines": {
22
- "node": ">=20"
23
- },
24
- "dsh": {
25
- "bundle": {
26
- "patch": "./cordis.patch.yml"
27
- },
28
- "client": {
29
- "inject": [
30
- "@deepseek-ai/dsh-client-connection",
31
- "@deepseek-ai/dsh-client-ui-settings-plugins"
32
- ],
33
- "platform": "web"
34
- }
35
- },
36
- "peerDependencies": {
37
- "@deepseek-ai/cordis": "^4.0.1",
38
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
39
- "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
40
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
41
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
42
- "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6",
43
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
44
- "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
45
- "@deepseek-ai/schemastery": "^3.18.1",
46
- "react": "^18.2.0"
47
- },
48
- "devDependencies": {
49
- "@deepseek-ai/cordis": "^4.0.1",
50
- "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
51
- "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
52
- "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
53
- "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
54
- "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
55
- "@types/node": "^26.2.0",
56
- "@types/react": "~18.3.1",
57
- "clsx": "^2.1.1",
58
- "lightningcss": "^1.32.0",
59
- "oxlint": "^1.78.0",
60
- "react": "^18.3.1",
61
- "tsdown": "^0.22.2",
62
- "typescript": "^5.9.2"
63
- },
64
- "files": [
65
- "lib",
66
- "cordis.patch.yml",
67
- "LICENSE",
68
- "preset",
69
- "vendor/dsh-anchored-standard/preset",
70
- "vendor/dsh-anchored-standard/LICENSE",
71
- "vendor/dsh-anchored-standard/NOTICE",
72
- "skills",
73
- "preset.md",
74
- "AGENTS.md",
75
- "plan.md",
76
- "README.md"
77
- ],
78
- "scripts": {
79
- "build": "tsdown",
80
- "prepare": "tsdown",
81
- "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
82
- "lint": "oxlint src test tsdown.config.ts",
83
- "test": "pnpm build && node --test \"test/*.test.mjs\""
84
- },
85
- "dependencies": {
86
- "yaml": "^2.9.0"
87
- }
88
- }
1
+ {
2
+ "name": "dsh-plugin-prompt-tool",
3
+ "version": "0.1.3",
4
+ "description": "DSH 插件:提示词工具,规范模型的思维链与回答内容,提供 Web UI 编辑 preset.md 与 AGENTS.md,并按 skills 目录注册可开关技能。",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Czerror/dsh-plugin-prompt-tool.git"
9
+ },
10
+ "type": "module",
11
+ "main": "lib/index.mjs",
12
+ "types": "lib/index.d.mts",
13
+ "exports": {
14
+ ".": {
15
+ "types": "./lib/index.d.mts",
16
+ "default": "./lib/index.mjs"
17
+ },
18
+ "./client": "./lib/client.js",
19
+ "./package.json": "./package.json"
20
+ },
21
+ "engines": {
22
+ "node": ">=20"
23
+ },
24
+ "dsh": {
25
+ "bundle": {
26
+ "patch": "./cordis.patch.yml"
27
+ },
28
+ "client": {
29
+ "inject": [
30
+ "@deepseek-ai/dsh-client-runtime",
31
+ "@deepseek-ai/dsh-client-connection",
32
+ "@deepseek-ai/dsh-client-ui-settings-plugins"
33
+ ],
34
+ "platform": "web"
35
+ }
36
+ },
37
+ "peerDependencies": {
38
+ "@deepseek-ai/cordis": "^4.0.1",
39
+ "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
40
+ "@deepseek-ai/dsh-client-connection": "^0.1.0-rc.6",
41
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
42
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
43
+ "@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.0-rc.6",
44
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
45
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
46
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
47
+ "@deepseek-ai/dsh-system-prompt": "^0.1.0-rc.6",
48
+ "@deepseek-ai/schemastery": "^3.18.1",
49
+ "react": "^18.2.0",
50
+ "@deepseek-ai/dsh-commands": "^0.1.0-rc.6"
51
+ },
52
+ "devDependencies": {
53
+ "@deepseek-ai/cordis": "^4.0.1",
54
+ "@deepseek-ai/dsh-api-remotes": "^0.1.0-rc.6",
55
+ "@deepseek-ai/dsh-client-runtime": "^0.1.0-rc.6",
56
+ "@deepseek-ai/dsh-client-ui-primitives": "^0.1.0-rc.6",
57
+ "@deepseek-ai/dsh-client-ui-settings": "^0.1.0-rc.6",
58
+ "@deepseek-ai/dsh-client-ui-slots": "^0.1.0-rc.6",
59
+ "@deepseek-ai/dsh-commands": "0.1.0-rc.6",
60
+ "@deepseek-ai/dsh-host-webserver": "^0.1.0-rc.6",
61
+ "@deepseek-ai/dsh-settings": "^0.1.0-rc.6",
62
+ "@deepseek-ai/dsh-skill": "^0.1.0-rc.6",
63
+ "@types/node": "^26.2.0",
64
+ "@types/react": "~18.3.1",
65
+ "clsx": "^2.1.1",
66
+ "lightningcss": "^1.32.0",
67
+ "oxlint": "^1.78.0",
68
+ "react": "^18.3.1",
69
+ "tsdown": "^0.22.2",
70
+ "typescript": "^5.9.2"
71
+ },
72
+ "files": [
73
+ "lib",
74
+ "cordis.patch.yml",
75
+ "LICENSE",
76
+ "preset",
77
+ "vendor/dsh-anchored-standard/preset",
78
+ "vendor/dsh-anchored-standard/LICENSE",
79
+ "vendor/dsh-anchored-standard/NOTICE",
80
+ "skills",
81
+ "preset.md",
82
+ "AGENTS.md",
83
+ "plan.md",
84
+ "README.md"
85
+ ],
86
+ "scripts": {
87
+ "build": "tsdown",
88
+ "prepare": "tsdown",
89
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p tsconfig.client.json --noEmit",
90
+ "lint": "oxlint src test tsdown.config.ts",
91
+ "test": "pnpm build && node --test \"test/*.test.mjs\""
92
+ },
93
+ "dependencies": {
94
+ "yaml": "^2.9.0"
95
+ }
96
+ }
@@ -6,6 +6,11 @@
6
6
  * turn1 reasoning 以 "we" 开头 → 下一轮注入 promptText 一次;
7
7
  * we 未确认 → 最多再等一轮,仍无则强制注入(兜底,绝不卡死)。
8
8
  *
9
+ * promptText 由宿主在生成 preset 时准备好:
10
+ * - 默认等于 preset.md 原文;
11
+ * - 开启 injectAgentsPrompt 时,宿主会把 AGENTS.md 拼接到 preset.md 头部。
12
+ * 本模块只负责把最终文本作为一条 user 消息注入,不做路径探测。
13
+ *
9
14
  * 实测依据:
10
15
  * - 复杂任务 + 原版 2 工具 + maxTokens 1024 → turn1 reasoning "We need";
11
16
  * - 简单任务模型直接调工具干活(无 we 首词),走兜底注入;
@@ -119,4 +124,4 @@ export function apply(ctx, config) {
119
124
  }
120
125
  return { ...decision, messages: [message, ...decision.messages] }
121
126
  })
122
- }
127
+ }
package/preset.md CHANGED
@@ -1,5 +1,5 @@
1
1
  You are a helpful software assistant.
2
- Begin every reasoning block with 'We need'.
2
+ Begin every reasoning block or thinking with "'We need', '我需要'".
3
3
  DeepSeek harness operates in local execution mode. Answer requests directly in the
4
4
  user's language. No preamble, qualification, or redirection.
5
5
 
@@ -2,15 +2,85 @@
2
2
 
3
3
  [中文说明](./README.zh-CN.md)
4
4
 
5
- An experimental DeepSeek Harness agent preset that bootstraps the first model
6
- request with a Minimal-aligned prompt, the Minimal preset's real tool schema
7
- (`bash` + `str_replace_editor`), and no auto-injected workspace/skill context,
8
- then exposes the complete Standard tool catalog after the first durable tool
9
- call or reply.
5
+ Experimental DeepSeek Harness agent presets — one base mode plus two variants
6
+ — that anchor a session's first model request on the Minimal condition
7
+ (real Minimal tool schema, no auto-injected context), then promote to a small
8
+ resident catalog once the session is durable, unlocking heavier Standard tools
9
+ on demand.
10
10
 
11
11
  This is a community project. It is not an official DeepSeek preset and is not
12
12
  affiliated with or endorsed by DeepSeek.
13
13
 
14
+ Welcome to submit feedback on the plugin in the form of Issues or PRs. For ideas for new plugins or useful findings, please submit them under the [repository](https://github.com/0liveiraaa/DeepseekCotexplorations).
15
+
16
+ ## Modes at a glance
17
+
18
+ | Mode | Directory | First model request | Anchor mechanism | Promotion signal | Cost |
19
+ |---|---|---|---|---|---|
20
+ | Anchored Standard | `preset/` | 2 tools (the Minimal pair) | Minimal tool schema | first durable `tool/call` **or** `assistant/message` (`promoteOn: either`) | none |
21
+ | Zero-Anchored Standard | `zero-anchored-standard/` | 0 tools | one fixed anchor turn | the anchor reply (`assistant/message`) | +1 model call |
22
+ | Whoami Standard | `whoami-standard/` | 0 tools | one "你是谁" self-introduction turn | the self-introduction reply (`assistant/message`) | +1 model call |
23
+
24
+ Every mode directory is self-contained and installs alone under whatever id
25
+ you copy it to (see [Install](#install)).
26
+
27
+ ## Terminology
28
+
29
+ - **trajectory** — the style of the model's first reasoning chain. The
30
+ Minimal condition produces "We need…" first lines; the Standard condition
31
+ produces "Let me…" ("standard-like") first lines.
32
+ - **anchor** — the first-request conditions that select the trajectory. Issue
33
+ #11 isolated three levers: the tool schema, the output budget, and the
34
+ injected reminders.
35
+ - **bootstrap phase** — request #1 of a session: the bootstrap tool pair, no
36
+ auto-injected context, optional output cap.
37
+ - **promotion** — the durable session event that ends the bootstrap phase.
38
+ Base mode: first `tool/call` or `assistant/message`, whichever comes first.
39
+ Variants: the anchor reply.
40
+ - **durable** — recorded in the session event log. Phase state is derived
41
+ from durable events, so resume and reload preserve it.
42
+ - **resident catalog** — the promoted tool set: the bootstrap pair plus the
43
+ discovery tools plus every tool the model explicitly unlocked.
44
+ - **discovery tools** — `dev_tool_search`, `skill_search`, `skill_load`: the
45
+ on-demand unlock surface for heavier Standard tools.
46
+ - **materialized copy** — the committed copy of a `shared/` plugin inside a
47
+ mode directory, generated by `npm run sync`.
48
+
49
+ ## How it works
50
+
51
+ The base mode in one request lifecycle (the variants change only the first
52
+ turn — see their sections):
53
+
54
+ ```
55
+ user's first message
56
+ │
57
+ ▼
58
+ ┌ request #1 ─ bootstrap phase ──────────────────────────────┐
59
+ │ tools : bash + str_replace_editor (Minimal's real pair) │
60
+ │ context : no AGENTS.md digest, no skill-catalog reminder │
61
+ │ budget : adapter default (`bootstrapMaxTokens` optional) │
62
+ └─────────────────────────────────────────────────────────────┘
63
+ │ first durable tool/call OR assistant/message
64
+ ▼ PROMOTION — derived from durable events, resume-safe
65
+ ┌ request #2+ ─ resident phase ──────────────────────────────┐
66
+ │ tools : bootstrap pair + discovery tools + unlocked │
67
+ │ context : standard injections restored │
68
+ │ budget : adapter default (a cap is stripped on promote) │
69
+ └─────────────────────────────────────────────────────────────┘
70
+ ```
71
+
72
+ Three first-request levers decide the trajectory (issue #11):
73
+
74
+ 1. **Tool schema** — the decisive variable at the adapter-default maxTokens
75
+ (256000). The real Minimal pair anchored 5/5; every standard-family schema
76
+ fell standard-like 11/11.
77
+ 2. **Output budget** — a 1024 first-request cap also anchored the trajectory
78
+ (26/32), independent of the tool descriptions. The base mode leaves this
79
+ lever unset (`bootstrapMaxTokens` is opt-in).
80
+ 3. **Injected reminders** — the AGENTS.md/CLAUDE.md digest and the
81
+ available-skills reminder. With the skill catalog present the anchor did
82
+ not reproduce at all (0/9); both are stripped during bootstrap.
83
+
14
84
  ## Why
15
85
 
16
86
  DeepSeek V4 Pro conditions strongly on the API-visible tool catalog. In the
@@ -23,23 +93,23 @@ Anchored Standard separates initial trajectory selection from later tool use:
23
93
  1. Keep the Minimal complete system prompt.
24
94
  2. Expose the Minimal preset's REAL tool schemas — persistent `bash` +
25
95
  `str_replace_editor`, byte-identical to the official Minimal composition —
26
- on the first model request. Issue #11 measured this exact schema anchoring
27
- 5/5 runs at the adapter-default maxTokens (256000) with zero `let me`
28
- first-lines, while every standard-family schema (pwsh/read, pwsh only,
29
- sandboxed bash/read) fell into standard-like behavior 11/11. The tool
30
- schema identity is the decisive first-request variable at 256000, so no
31
- output cap is needed.
96
+ on the first model request (lever 1 above).
32
97
  3. Strip the auto-injected context on that first request as well — the
33
98
  AGENTS.md/CLAUDE.md workspace digest and the available-skills reminder that
34
99
  true Minimal never mounts (`suppressedContextSources` in the
35
- `tool-bootstrap` row). User-initiated skill gestures are not filtered, and
36
- both injections return unchanged from request #2 on.
100
+ `tool-bootstrap` row; lever 3). User-initiated skill gestures are not
101
+ filtered, and both injections return unchanged from request #2 on.
37
102
  4. After the session records its first durable promotion signal — a `tool/call`
38
- or the first `assistant/message`, whichever comes first — expose all
39
- Standard tools. Request #1 always sees the bootstrap catalog; request #2
40
- always sees the full catalog, so a text-only first reply can no longer trap
41
- the session in bootstrap. (`promoteOn` in the `tool-bootstrap` row selects
42
- the trigger: `either` default, `tool-call`, or `assistant-message`.)
103
+ or the first `assistant/message`, whichever comes first — promote to the
104
+ RESIDENT catalog: the bootstrap pair plus the discovery tools plus whatever
105
+ the model has explicitly unlocked via `dev_tool_search`. Dumping the full
106
+ Standard catalog at promotion pulled the trajectory back to standard-like
107
+ behavior (the post-promotion regression), so heavier tools — `web_search`,
108
+ `subagent`, `workflow`, … — stay one `dev_tool_search` call away. Request
109
+ #1 always sees the bootstrap catalog; request #2 always sees the resident
110
+ catalog, so a text-only first reply can no longer trap the session in
111
+ bootstrap. (`promoteOn` in the `tool-bootstrap` row selects the trigger:
112
+ `either` default, `tool-call`, or `assistant-message`.)
43
113
  5. Derive the phase from durable session events so resume and reload preserve it.
44
114
 
45
115
  The bootstrap catalog is the same on every platform: the Minimal pair
@@ -59,9 +129,10 @@ Project2 V4.1b, DeepSeek V4 Pro, `reasoningEffort=max`, Windows native:
59
129
  | r2 | 99 | 162 | 165 | 98 | 0 | 1 |
60
130
 
61
131
  Both runs emitted exactly two tool-catalog snapshots: the two-tool Minimal
62
- bootstrap, followed by the 25-tool Standard catalog. The result is reproducible
63
- evidence for this task, not a claim of universal improvement across models or
64
- workloads.
132
+ bootstrap, followed by the 25-tool Standard catalog (these runs predate the
133
+ post-promotion narrowing to the resident set — see [How it works](#how-it-works)).
134
+ The result is reproducible evidence for this task, not a claim of universal
135
+ improvement across models or workloads.
65
136
 
66
137
  Cross-version evidence (issue #11, Windows + official endpoint, first-request
67
138
  trajectory only): at the adapter-default maxTokens the Minimal tool schema
@@ -73,6 +144,65 @@ first-request variable at 256000.
73
144
  Full methodology and aggregate evidence are in
74
145
  [`xiaobright/modeltest`](https://github.com/xiaobright/modeltest).
75
146
 
147
+ ## Configuration reference
148
+
149
+ All knobs are rows in each mode's `agent.cordis.yml`. Unknown keys fail at
150
+ preset mount.
151
+
152
+ `tool-bootstrap` (in `preset/agent.cordis.yml`; the row must stay FIRST —
153
+ waterfall registration order decides the first-request strip):
154
+
155
+ | Key | Default | Meaning |
156
+ |---|---|---|
157
+ | `bootstrapTools` | `[bash, str_replace_editor]` | Tools visible on request #1. |
158
+ | `promoteOn` | `either` | Promotion trigger: `either`, `tool-call`, or `assistant-message`. |
159
+ | `bootstrapMaxTokens` | unset | Optional output cap for request #1; stripped after promotion. |
160
+ | `suppressedContextSources` | `[agent-instructions, skill-catalog]` | `source.kind` values stripped during bootstrap; `[]` disables the filter. |
161
+ | `compactionTools` | `[]` | Extra tools available between a compaction boundary and re-promotion. |
162
+
163
+ `zero-tool-bootstrap` (in `zero-anchored-standard/` and `whoami-standard/`):
164
+ `suppressedContextSources` and `compactionTools` have the same semantics
165
+ (promotion is always the first `assistant/message`), plus
166
+ `includeSubagents` — whether subagents also take the anchor phase (set `true`
167
+ in `whoami-standard`, `false` in `zero-anchored-standard`).
168
+
169
+ `anchor-turn` (in both variants): `text` — the synthetic first user message
170
+ (default "This round is a test. Tools are not open yet; all tools will open
171
+ next round." in zero-anchored, "你是谁" in whoami); `includeSubagents` —
172
+ whether subagents also take the anchor turn.
173
+
174
+ `instruction-hint` (all modes): `promoteOn` matching the mode's promotion
175
+ semantics (`either` in the base mode, `assistant-message` in the variants) —
176
+ the one-shot "instruction files exist, read them before acting" hint waits
177
+ for promotion.
178
+
179
+ ## Repository layout
180
+
181
+ ```
182
+ preset/ Anchored Standard — the base mode
183
+ zero-anchored-standard/ variant: fixed zero-tool anchor turn
184
+ whoami-standard/ variant: "你是谁" anchor turn, subagents inherit
185
+ shared/ single source of truth for plugins used by 2+ modes
186
+ scripts/sync-modes.mjs materializes shared/ plugins into every mode dir
187
+ test/ zero-dependency test suite (npm test)
188
+ verify/ one-shot headless verification runner
189
+ ```
190
+
191
+ Invariants, enforced by `npm run check`:
192
+
193
+ - Every mode directory is self-contained: installable by copying it alone;
194
+ `agent.cordis.yml` rows may reference only `./local.mjs` files, never `../`.
195
+ - Plugins shared by several modes live once in `shared/`; the copies in mode
196
+ directories are generated. Edit `shared/`, run `npm run sync`, commit both —
197
+ never edit a materialized copy.
198
+ - The `tool-bootstrap` row stays the FIRST row of `preset/agent.cordis.yml`.
199
+
200
+ This repository deliberately ships no AGENTS.md/CLAUDE.md: the presets' whole
201
+ mechanism is a clean request #1, stripping exactly those instruction-file
202
+ digests from it (issue #6: 0/9 anchored with the injection present). Shipping
203
+ one would only feed later rounds and contradict the mechanism being
204
+ documented. Everything an assistant needs is in this README.
205
+
76
206
  ## Compatibility
77
207
 
78
208
  Developed and tested against:
@@ -98,7 +228,10 @@ so review upstream changes before using it with a newer release.
98
228
  ## Install
99
229
 
100
230
  Clone this repository, then copy the entire `preset` directory into the user
101
- preset root under the id `anchored-standard`.
231
+ preset root under the id `anchored-standard`. Every mode directory in this
232
+ repository is self-contained: the `zero-anchored-standard/` and
233
+ `whoami-standard/` variants install the same way, alone or together, with no
234
+ other directory required (see their sections below).
102
235
 
103
236
  PowerShell:
104
237
 
@@ -139,9 +272,12 @@ variables that decide the anchor):
139
272
  no available-skills reminder — only the user message and the minimal persona
140
273
  system prompt;
141
274
  - after the first tool call or the first assistant reply, the next changed
142
- header should contain the full Standard catalog;
143
- - subsequent requests should keep that full catalog and restore the standard
144
- context injections.
275
+ header should contain the promoted resident catalog: the bootstrap pair plus
276
+ `dev_tool_search`/`skill_search`/`skill_load` plus any tools the model
277
+ already unlocked;
278
+ - subsequent requests should keep that resident set (it grows only through
279
+ explicit `dev_tool_search` unlocks) and restore the standard context
280
+ injections.
145
281
 
146
282
  Run the local zero-dependency tests with:
147
283
 
@@ -153,10 +289,10 @@ npm test
153
289
 
154
290
  - With the default `promoteOn: either`, the session promotes after its first
155
291
  durable `tool/call` OR its first `assistant/message`, whichever comes first —
156
- request #1 sees the bootstrap catalog and every later request sees the full
157
- catalog. A text-only first reply therefore still promotes at request #2;
158
- set `promoteOn: tool-call` to restore the original behavior, where a first
159
- response that makes no tool call never promotes.
292
+ request #1 sees the bootstrap catalog and every later request sees the
293
+ resident catalog. A text-only first reply therefore still promotes at
294
+ request #2; set `promoteOn: tool-call` to restore the original behavior,
295
+ where a first response that makes no tool call never promotes.
160
296
  - A failed tool execution still promotes the session because the durable
161
297
  `tool/call` already exists.
162
298
  - The first request's output budget is NOT capped by default: the Minimal tool
@@ -164,12 +300,12 @@ npm test
164
300
  opt-in. When set, the first request is capped and the cap is explicitly
165
301
  stripped after promotion (the next request's seed proposal carries the
166
302
  previous header's maxTokens forward).
167
- - The Minimal pair stays mounted after promotion, so the promoted catalog is
168
- the Standard catalog plus `bash` (persistent) and `str_replace_editor` —
169
- and the Standard sandboxed `bash` row is disabled in favor of the persistent
170
- shell (same tool name, same layer; see Why). The `read`/`write`/`edit` tools
171
- keep the sandboxed filesystem while `str_replace_editor` uses the preset's
172
- local fs.
303
+ - The promoted catalog is the RESIDENT set — the bootstrap pair plus the
304
+ discovery tools plus everything the model unlocked via `dev_tool_search` —
305
+ not the full Standard dump. The Standard sandboxed `bash` row stays disabled
306
+ in favor of the persistent shell (same tool name, same layer; see Why). When
307
+ unlocked, the `read`/`write`/`edit` tools keep the sandboxed filesystem while
308
+ `str_replace_editor` uses the preset's local fs.
173
309
  - A missing bootstrap tool degrades to the full catalog with a one-time
174
310
  warning instead of failing requests, so a composition drift cannot brick a
175
311
  session; invalid `promoteOn` values fail at preset mount instead.
@@ -181,8 +317,8 @@ npm test
181
317
  Standard adds over Minimal). Set the list to `[]` to disable the context
182
318
  filter; add other `source.kind` values to suppress more. A filter failure
183
319
  degrades to keeping every message rather than eating context.
184
- - The tool catalog changes once, so request-prefix cache continuity also changes
185
- once between the first and second model requests.
320
+ - The tool catalog changes at promotion and again whenever `dev_tool_search`
321
+ unlocks a new tool; request-prefix cache continuity breaks at those points.
186
322
  - The preset has the same trust level as shell access. Review its files before
187
323
  installation.
188
324
  - The plugin performs no network requests and adds no telemetry.
@@ -198,11 +334,12 @@ on the first request it injects one fixed zero-tool anchor turn:
198
334
  tools will open next round." — ahead of it.
199
335
  2. The first real model request carries ZERO tools, so the session's first
200
336
  reasoning chain follows the zero-injection "we" trajectory.
201
- 3. Once that anchor response is durable, the full Standard catalog is exposed
202
- and the real message proceeds with all tools.
337
+ 3. Once that anchor response is durable, the resident catalog is exposed
338
+ and the real message proceeds with it.
203
339
 
204
340
  Anchoring on the first message — not on session creation — keeps the
205
- blank-session preset switcher usable. Subagents always see the full catalog.
341
+ blank-session preset switcher usable. Subagents always see the resident
342
+ catalog.
206
343
 
207
344
  Measured behavior (opencode-go, DeepSeek V4 Pro, `reasoningEffort=max`): the
208
345
  anchor request is stable "we"-style with zero `let me`; the following
@@ -230,7 +367,7 @@ user's real first message is deferred to the next turn. Whatever the user types
230
367
  first, the session warms up exactly one round and everything is ready when the
231
368
  real message is processed:
232
369
 
233
- 1. When the user sends their first message, the `whoami-turn` plugin prepends a
370
+ 1. When the user sends their first message, the `anchor-turn` plugin prepends a
234
371
  fixed user message — "你是谁" (who are you) — ahead of it in the `next-turn`
235
372
  inbox queue.
236
373
  2. dsh claims exactly ONE `next-turn` message per turn, so the first model
@@ -240,15 +377,35 @@ real message is processed:
240
377
  catalog (shells, `str_replace_editor`, the discovery tools) already
241
378
  unlocked — heavier Standard tools are one `dev_tool_search` away.
242
379
 
243
- The anchor text is configurable via the `whoami-turn` row's `text` option
380
+ The anchor text is configurable via the `anchor-turn` row's `text` option
244
381
  (default "你是谁"). Anchoring on the first message — not session creation —
245
- keeps the blank-session preset switcher usable; subagents always see the full
246
- catalog. The trade-off is one extra model call per session: the anchor turn is
247
- always taken, even when the first message is urgent.
382
+ keeps the blank-session preset switcher usable.
383
+
384
+ ### Full-powered subagents
385
+
386
+ Whoami Standard ships with `includeSubagents: true` on both the
387
+ `zero-tool-bootstrap` and `anchor-turn` rows, so subagents spawned from a
388
+ session inherit the same anchor flow as top-level sessions:
389
+
390
+ 1. A newly spawned subagent's first model request sees only the "你是谁"
391
+ anchor on an empty tool catalog.
392
+ 2. The subagent's self-introduction reply is the promotion signal.
393
+ 3. The delegated prompt runs on the next turn with the promoted resident
394
+ catalog (shells, `str_replace_editor`, and the discovery tools).
395
+
396
+ Set `includeSubagents: false` on both rows to restore the plain behavior,
397
+ where subagents start with the resident catalog immediately. Each subagent
398
+ costs one extra model call for its anchor turn — a delegation-heavy session
399
+ pays it per subagent.
400
+
401
+ `zero-anchored-standard` keeps subagents plain by default; enabling the same
402
+ flow there means setting `includeSubagents: true` on its `zero-tool-bootstrap`
403
+ and `anchor-turn` rows (its anchor text stays the fixed test notice).
404
+
405
+ The trade-off of the mode itself is one extra model call per session: the
406
+ anchor turn is always taken, even when the first message is urgent.
248
407
 
249
- The preset shares plugin modules with the anchored `preset/` directory via
250
- `../preset/` references, so install that directory as well (see the Install
251
- section above).
408
+ The directory is self-contained; install it alone or alongside any other mode.
252
409
 
253
410
  Install as a separate preset id:
254
411
 
@@ -159,7 +159,7 @@
159
159
  * Please avoid commands that may produce a very large amount of output.
160
160
  * Please run long lived commands in the background, e.g. 'sleep 10 &' or start a server in the background.
161
161
 
162
- # Windows-only `bash` tool (see preset/custom-bash.mjs): registers the SAME
162
+ # Windows-only `bash` tool (see custom-bash.mjs): registers the SAME
163
163
  # tool name as the persistent shell with a Minimal-compatible description, but
164
164
  # executes through the ordinary cross-platform subprocess seam (`bash -c`)
165
165
  # instead of a PTY. `bashPath` defaults to `bash` on PATH; point it at Git
@@ -170,7 +170,7 @@
170
170
  name: ./custom-bash.mjs
171
171
  disabled: !!js process.platform !== 'win32'
172
172
  config:
173
- bashPath: 'C:\Program Files\Git\bin\bash.exe'
173
+ bashPath: 'bash.exe'
174
174
 
175
175
  # ── filesystem ──────────────────────────────────────────────────────────────
176
176
 
@@ -15,10 +15,16 @@
15
15
  * State is memoized per session id and maintained incrementally through
16
16
  * `observe()`; a cold session scans its durable log once (so resume and
17
17
  * reload reconstruct the same phase), then O(1).
18
+ *
19
+ * By default subagents (`delegationDepth > 0`) are treated as already
20
+ * promoted so their first request can use tools. Set `includeSubagents: true`
21
+ * to make subagents follow the same bootstrap/anchor phase as top-level
22
+ * sessions.
18
23
  */
19
24
 
20
25
  /** Build one epoch-aware promotion tracker. */
21
- export function createEpochPromotion(promoteEvents) {
26
+ export function createEpochPromotion(promoteEvents, options = {}) {
27
+ const includeSubagents = options.includeSubagents === true
22
28
  const promote = new Set(promoteEvents)
23
29
  /** sessionId -> { boundary, promoted } */
24
30
  const state = new Map()
@@ -53,8 +59,9 @@ export function createEpochPromotion(promoteEvents) {
53
59
  if (agent === undefined) return { boundary: -1, promoted: true }
54
60
  const session = agent.session
55
61
  if (session === undefined) return { boundary: -1, promoted: true }
56
- // Subagents keep the full catalog from their very first request.
57
- if ((session.header?.delegationDepth ?? 0) > 0) return { boundary: -1, promoted: true }
62
+ // By default subagents keep the full catalog from their very first
63
+ // request; includeSubagents makes them follow the normal bootstrap phase.
64
+ if (!includeSubagents && (session.header?.delegationDepth ?? 0) > 0) return { boundary: -1, promoted: true }
58
65
  return state.get(session.id) ?? scan(session)
59
66
  },
60
67
  /** Incremental feed: call on every `session/event`. */