@menghuan1918/dsh-apollo 0.3.0 → 0.4.0

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.
@@ -1,48 +1,124 @@
1
1
  /**
2
- * `eng-mode-instructions` — preset-scoped prompt section for the eng preset
3
- * (工程模式). Carries the two eng-only behaviors no other surface states:
4
- * - the exit guard contract;
5
- * - the delegation/orchestration policy (when to delegate, write scopes,
6
- * verification, failure handling), moved out of the user-global
7
- * ~/.dsh/AGENTS.md on 2026-09-11.
8
- * Model tiers stay in ~/.dsh/AGENTS.md: they mirror this host's
9
- * `subagent-model-selection.allowedModels` route list, which is local config.
10
- * Everything else — tool mechanics, background-job etiquette, sleep caps —
11
- * lives in the harness system prompt or the tool descriptions, and is
12
- * deliberately NOT repeated here. Dedupe first, inject only the delta.
2
+ * `eng-mode-instructions` — preset-scoped prompt section for 工程模式
3
+ * (`eng`) and 工程(PTC)模式 (`eng-ptc`).
13
4
  *
14
- * Zero imports on purpose (same constraint as the sibling wait-subagent
15
- * plugin): this module loads from the preset directory, where Node's upward
16
- * node_modules walk never reaches the harness install.
5
+ * Carries what no other surface states: the general engineering discipline
6
+ * (moved out of the user-global ~/.dsh/AGENTS.md, which keeps only
7
+ * machine-local conventions), the delegation policy, the subagent model tiers
8
+ * rendered from Apollo settings (`tiers.*`), and the exit guard contract while
9
+ * that switch is on. Tool mechanics, background-job etiquette and run_code
10
+ * syntax live in the harness prompt and tool descriptions and are NOT
11
+ * repeated here.
12
+ *
13
+ * The text is a function re-rendered per request from the live Apollo config,
14
+ * so settings edits apply without remounting; an edit costs the prefix cache
15
+ * once, which is acceptable for rarely changed settings. The row config
16
+ * `ptc: true` (set by eng-ptc) adds a rule for fanning out subagents inside
17
+ * one run_code program (workflow usage is left to the harness tool guidance); run_code mechanics themselves
18
+ * come from the harness `tools:sdk` / `tools:ptc-only` sections.
17
19
  */
18
20
 
21
+ import z from '@deepseek-ai/schemastery'
22
+ import { currentConfig } from '../../../../src/config.js'
23
+
19
24
  export const name = 'eng-mode-instructions'
20
25
 
21
26
  export const inject = ['systemPrompt']
22
27
 
23
- const TEXT = [
24
- '# 工程模式专属',
25
- '',
26
- '工程模式(eng)面向编码与基础设施任务。',
27
- '',
28
- '- 退出守卫:回合结束前仍有运行中的子代理或后台命令时,回合不会关闭——系统注入运行清单提醒,先用 wait_subagent / job_output 等待收取、job_kill 停掉不需要的,处理完毕再收尾。',
29
- '',
30
- '## 委派与编排',
31
- '',
32
- '- 开局侦察:非琐碎任务在陌生或大型代码库上开始时,情况了解(仓库结构、相关模块定位、约定与测试入口)默认立即并行派发快速档侦察子代理,同批在一条消息里一起派;主线程只保留定义任务必需的指令类文件阅读(AGENTS.md、PRD、任务说明)。不要为「写好委派 prompt」而先单线程探索——侦察 prompt 只需目标、边界、交付物,缺的上下文正是侦察要产出的东西。',
33
- '- 默认委派:只读、可并行、无状态的调查一律派出去(含大型/陌生仓库、前端代码、批量排查),同一批独立任务在一条消息里一起派,不在主线程先试一遍。',
34
- '- 转委派阈值:实现/调试中途冒出的新未知,主线程深挖 1–2 轮未收敛立即派出去;开局侦察不适用此阈值。',
35
- '- 实现分层:写入范围互不重叠的独立实现块派子代理并行推进;线性推进、强耦合改动、需要持续控制活状态的调试(活进程、串行打补丁)留主线程。',
36
- '- 扇出用 workflow:同一形状的工作重复多份(审计、迁移、多角度验证、批量修复)即属大型多代理编排,直接写 workflow 脚本一次编排;一两次委派仍用 subagent。',
37
- '- 派发写明目标、写入范围、交付物与验证方式;引用的前置产出给实际文件路径——子代理看不到父对话。',
38
- '- 并行实现子代理的写入范围不得重叠;最终集成、审查、验证由主代理负责;子代理报告是线索不是证据,亲自核对实际变更状态。',
39
- '- 子代理以 error / 空返回收场:先读失败原因,修正路由或重派一次;仍失败且无外部阻塞才主线程接管,并在当轮说明为何接管。',
40
- ].join('\n')
41
-
42
- export function apply(ctx) {
28
+ export const Config = z.object({
29
+ /** Render the PTC variant (eng-ptc). */
30
+ ptc: z.boolean().default(false),
31
+ })
32
+
33
+ const PRINCIPLES = `# Engineering mode
34
+
35
+ For coding and infrastructure work. These are defaults; explicit user instructions take precedence.
36
+
37
+ ## Principles
38
+ - KISS / YAGNI: use the simplest approach that works. Do not add abstractions, indirection, or options the task does not need.
39
+ - Inspect first: read the actual files, run the actual commands, check the actual state, then judge. When evidence and judgment disagree, evidence wins. Look up unfamiliar library/API behavior instead of relying on memory.
40
+ - Fix the root cause: trace a bad value back to the violated assumption; no workarounds that only hide the symptom.
41
+ - One coherent change at a time, each with an observable result and a pass/fail check; do not bundle unrelated edits.
42
+ - Follow existing conventions: match surrounding naming, style, error handling, and patterns; use the project's own build/test/lint commands; read the repo's coding-standards files (if any) before writing code.
43
+ - Think about requirements, approach, and verification; do not draft whole implementations in your reasoning. If your reasoning starts repeating, stop, change angle, or go gather evidence.
44
+
45
+ ## Avoid over-engineering and over-defending
46
+ - Do not add complexity for speculative needs or vanishingly unlikely race/security edge cases. If one seems necessary, first explain the concrete failure mode, its likelihood, and the complexity cost to the user and get agreement; never silently expand scope for theoretical robustness.
47
+ - Validate unknown input once, at the boundary that owns it, and pass settled values inward; do not re-check what a schema, constructor, or type already guarantees.
48
+ - Put try/catch only where the error can actually be handled; never use it to swallow errors or hide failures.
49
+ - Do not extract single-use helpers unless they name a real concept or isolate a genuinely complex boundary.
50
+ - Comment non-obvious constraints and surprising behavior, not what the code already says.
51
+ - Test the real implementation; minimize mocks; do not copy implementation logic into tests.
52
+
53
+ ## Verification and reporting
54
+ - Claim success only with fresh evidence from the changed state. Passing lint does not prove runtime behavior; unit tests do not prove deployment integration.
55
+ - In reports, separate verified, executed-but-unverified, and not executed. Never fake progress.
56
+
57
+ ## Boundaries
58
+ - Changing shared branches such as main or dev needs explicit authorization. Within the task, commits and merges on isolated branches are fine; create worktrees for isolation when useful.
59
+ - Preserve unrelated changes and keep the main worktree clean; recurring local files can go in .git/info/exclude.
60
+ - Commit with the configured global Git identity, never placeholder identities such as bot or agent.
61
+ - Tell the user when you install system packages or download dependencies outside the package manager; ask where to install missing unmanaged dependencies; prefer prebuilt packages over compiling.
62
+ - No filesystem-wide or whole-home-directory searches without asking first.
63
+ - Deviating from these rules needs the user's consent. Before asking, explore the code, tests, and prior decisions yourself; ask only questions whose answers change what you do, each with a recommended answer and why.
64
+
65
+ ## Commands and processes
66
+ - One background job per goal: check job_list first; do not run near-duplicate commands in parallel.
67
+ - Work on data where it already is (including remote mounts) instead of downloading or copying large files.
68
+ - Before killing a process, confirm its full command line and PID with \`pgrep -af <keyword>\`, then \`kill <PID>\`; never pkill / killall.
69
+ - Never sleep longer than 60s at once; for longer waits use stepped probes, sentinel files, or completion notices.
70
+ - Run services that must outlive the turn (dev servers, watchers) under pm2/nohup outside the job registry, and say which ones are still running when you finish.`
71
+
72
+ const DELEGATION_HEAD = `## Delegation
73
+ - Subagents cannot see this conversation: state the goal, write scope, deliverable, and verification, and give real file paths for prior outputs.
74
+ - Opening reconnaissance: when starting non-trivial work in an unfamiliar or large codebase, immediately dispatch fast-tier scouts in parallel (structure, relevant modules, conventions, test entry points), all in one message; the main agent reads only the instruction files that define the task. A scout prompt needs only goal, boundaries, and deliverable.
75
+ - Delegate read-only, parallelizable, stateless investigation by default instead of trying it in the main thread first; when a new unknown appears mid-task and 1–2 rounds of digging do not converge, delegate it.
76
+ - Implementation chunks with non-overlapping write scopes can run in parallel; keep linear work, tightly coupled changes, and debugging that needs live state in the main thread.`
77
+
78
+ const FANOUT_PTC = '- For repeated same-shaped work, dispatch all subagents inside one run_code program, then collect them with wait_subagent.'
79
+
80
+ const DELEGATION_TAIL = `- When you need a subagent's result, wait patiently with wait_subagent. Do not poll or prod it with send_message; send a message only to give it genuinely new information or a correction.
81
+ - The main agent owns integration, review, and final verification. Subagent reports are leads, not evidence: check the actual changes yourself.
82
+ - When a subagent ends in an error or empty result, read why, fix the cause, and re-dispatch once; take over in the main thread only if it fails again without an external blocker, and say why.`
83
+
84
+ const EXIT_GUARD = `## Exit guard
85
+ - If subagents or background commands are still running when the turn would end, the system injects a reminder and the turn continues. Collect them with wait_subagent / job_output, stop unneeded ones with job_kill, then finish.`
86
+
87
+ /** One tier as model-facing argument text; an unset tier inherits the parent route. */
88
+ export function renderTier(tier) {
89
+ if (!tier?.provider || !tier?.model) return 'omit provider / model / reasoning_effort to inherit the parent route'
90
+ const parts = [`provider: \`${tier.provider}\``, `model: \`${tier.model}\``]
91
+ if (tier.reasoningEffort) parts.push(`reasoning_effort: \`${tier.reasoningEffort}\``)
92
+ return parts.join(' · ')
93
+ }
94
+
95
+ /**
96
+ * Render the full section text.
97
+ * @param config - normalized Apollo config (`exitGuard`, `tiers`).
98
+ * @param options - `{ ptc }` from this row's config.
99
+ * @returns the section markdown.
100
+ */
101
+ export function renderInstructions(config, options = {}) {
102
+ const tiers = `## Subagent model tiers
103
+ - Fast tier (exploration, reconnaissance, mechanical analysis, batch triage): ${renderTier(config.tiers?.fast)}
104
+ - Quality tier (complex implementation, debugging, review, design): ${renderTier(config.tiers?.quality)}
105
+ - Start exploration on the fast tier; when coverage falls short or key questions remain, re-dispatch the unresolved part on the quality tier. Escalating means re-dispatching, not modifying an existing subagent.
106
+ - subagent_fork takes no model choice: it keeps the parent route to reuse the prefix cache.`
107
+ const blocks = [
108
+ PRINCIPLES,
109
+ [DELEGATION_HEAD, ...(options.ptc ? [FANOUT_PTC] : []), DELEGATION_TAIL].join('\n'),
110
+ tiers,
111
+ ]
112
+ if (config.exitGuard) blocks.push(EXIT_GUARD)
113
+ return blocks.join('\n\n')
114
+ }
115
+
116
+ export function apply(ctx, config) {
117
+ const options = { ptc: config?.ptc === true }
43
118
  ctx.effect(() => ctx.systemPrompt.section({
44
119
  name: 'eng:mode-instructions',
45
120
  order: 1,
46
- text: TEXT,
121
+ interpolate: false,
122
+ text: () => renderInstructions(currentConfig(ctx), options),
47
123
  }), 'eng-mode-instructions.section()')
48
124
  }
@@ -25,6 +25,8 @@
25
25
  *
26
26
  * `timeout_ms` is ONE shared window over the whole batch (all timers start at
27
27
  * the same instant), matching the semantics same-message parallel calls had.
28
+ * Values below MIN_TIMEOUT_MS (15 minutes) are raised to it: short polling
29
+ * waits only burned turns, since a finishing child notifies the parent anyway.
28
30
  * An id that is not a direct child fails the whole call fast — nobody is
29
31
  * waited for — keeping the contract the single-id version had. A child
30
32
  * dispatched moments ago may not have started its first turn yet: its status
@@ -48,6 +50,9 @@ export const inject = ['tools', 'subagents', 'agents']
48
50
  /** Grace window for a just-dispatched child that has not started running yet. */
49
51
  const START_GRACE_MS = 30_000
50
52
 
53
+ /** Floor for a caller-supplied timeout_ms (15 minutes). */
54
+ const MIN_TIMEOUT_MS = 15 * 60_000
55
+
51
56
  /** Status polling interval while waiting for a not-yet-started child. */
52
57
  const POLL_MS = 250
53
58
 
@@ -70,7 +75,7 @@ export function apply(ctx) {
70
75
 
71
76
  ctx.tools.register({
72
77
  name: 'wait_subagent',
73
- description: 'Wait for one or more background continuable subagents (spawned by subagent or subagent_fork) to finish their current turn. Pass their durable ids as an array in subagent_id — all are awaited concurrently and the result carries one short line per id (done + stop reason); a child\'s closing message arrives as the framework settlement notice immediately after this result; do not expect it here. Blocks until every listed child settles, the optional timeout_ms elapses (one shared window over all ids), or the user interrupts — without timeout_ms, until completion. A just-dispatched child that has not started yet is awaited through a brief startup grace rather than reported as not running. Use it when your next step depends on those results; with independent work remaining, prefer background plus completion notices. Do not pass bash job ids — those use job_output.',
78
+ description: 'Wait for direct subagents (from subagent or subagent_fork) to finish their current turn. Pass every id in subagent_id; all are awaited together and each gets one done line, while its closing message arrives as the settlement notice right after. Use it when your next step needs the results, instead of messaging the child to check on it. Not for bash jobs (use job_output).',
74
79
  parameters: {
75
80
  type: 'object',
76
81
  properties: {
@@ -78,11 +83,11 @@ export function apply(ctx) {
78
83
  type: 'array',
79
84
  items: { type: 'string' },
80
85
  minItems: 1,
81
- description: 'One or more durable subagent ids returned by the subagent or subagent_fork tool call; every id is awaited concurrently.',
86
+ description: 'Durable ids returned by subagent or subagent_fork.',
82
87
  },
83
88
  timeout_ms: {
84
89
  type: 'integer',
85
- description: 'Optional maximum wait in milliseconds applied as one shared window over all ids; omit to wait until every child settles. On expiry the tool returns while some children are still running.',
90
+ description: 'Optional shared wait window in ms; values below 900000 (15 minutes) are raised to 900000. Omit to wait until every child settles.',
86
91
  },
87
92
  },
88
93
  required: ['subagent_id'],
@@ -123,7 +128,7 @@ export function apply(ctx) {
123
128
  const doneLine = (id, info) => `subagent ${id} done (${info && info.stopReason ? info.stopReason : 'completed'}); its closing message follows as the settlement notice.`
124
129
 
125
130
  const startedAt = Date.now()
126
- const capMs = typeof args.timeout_ms === 'number' && args.timeout_ms > 0 ? args.timeout_ms : undefined
131
+ const capMs = typeof args.timeout_ms === 'number' && args.timeout_ms > 0 ? Math.max(args.timeout_ms, MIN_TIMEOUT_MS) : undefined
127
132
 
128
133
  /**
129
134
  * Wait for one child. Resolves with {kind:'settled',info} |
@@ -0,0 +1,186 @@
1
+ # dsh-apollo bundle patch: the `eng-ptc` (工程(PTC)模式) agent preset.
2
+ #
3
+ # A copy of the eng plugins block (presets/eng.patch.yml — read that file for
4
+ # the per-row rationale) with exactly the deltas the upstream `ptc` preset
5
+ # applies to `standard`:
6
+ # - `tool-presentation { mode: ptc }`: every tool is reached through the
7
+ # run_code TypeScript SDK (needs the host `ptc-runtime` row);
8
+ # - `workflow-ptc` and `tool-workflow` disabled: PTC fans out by calling
9
+ # subagent several times inside one run_code program instead;
10
+ # plus `eng-mode-instructions { ptc: true }`, which adds the rule for fanning
11
+ # out subagents inside one run_code program. Preset-local plugins reuse the eng modules.
12
+ # tests/upstream-drift.test.mjs checks this file against both eng and the
13
+ # upstream `ptc` preset; edit eng first, then redo these deltas.
14
+ #
15
+ # `config.id` MUST stay `eng-ptc`: it is the preset identity historical
16
+ # sessions resume by.
17
+
18
+ - insert:
19
+ - id: preset-eng-ptc
20
+ name: '@deepseek-ai/dsh-agent-preset'
21
+ config:
22
+ id: eng-ptc
23
+ name: 工程(PTC)模式
24
+ description: >-
25
+ 工程模式的 PTC 变体:工具经 run_code 的 TypeScript SDK 调用,一个程序组合多步操作;与官方 PTC 模式一致不提供 workflow 工具。
26
+ order: 11
27
+ plugins:
28
+
29
+ - id: persona
30
+ name: '@deepseek-ai/dsh-persona'
31
+ config:
32
+ prefix: >-
33
+ You are a coding agent powered by the {{model}} model.
34
+
35
+ - id: agent-instructions
36
+ name: '@deepseek-ai/dsh-agent-instructions'
37
+ config:
38
+ maxBytes: 65536
39
+
40
+ - id: time-context
41
+ name: '@deepseek-ai/dsh-time-context'
42
+
43
+ - id: tool-bash
44
+ name: '@deepseek-ai/dsh-tool-bash'
45
+ disabled: !!js process.platform === 'win32'
46
+
47
+ - id: tool-pwsh
48
+ name: '@deepseek-ai/dsh-tool-pwsh'
49
+ disabled: !!js process.platform !== 'win32'
50
+
51
+ - id: tool-fs
52
+ name: '@deepseek-ai/dsh-tool-fs'
53
+
54
+ - id: tool-fs-search
55
+ name: '@deepseek-ai/dsh-tool-fs-search'
56
+ config:
57
+ sampleOverCapGlobResults: false
58
+
59
+ - id: tool-jobs
60
+ name: '@deepseek-ai/dsh-tool-jobs'
61
+ config:
62
+ maxConsecutiveWakes: 5000
63
+
64
+ - id: skill-filesystem
65
+ name: '@deepseek-ai/dsh-skill-filesystem'
66
+
67
+ - id: tool-skill
68
+ name: '@deepseek-ai/dsh-tool-skill'
69
+
70
+ - id: planning
71
+ name: cordis:group
72
+ group: true
73
+ isolate:
74
+ planMode: true
75
+ config:
76
+ - id: plan-mode
77
+ name: '@deepseek-ai/dsh-plan-mode'
78
+ config:
79
+ section: |
80
+ You are in plan mode. Stay in plan mode until the user approves your plan through exit_plan_mode or switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
81
+
82
+ Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
83
+
84
+ The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
85
+
86
+ Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
87
+
88
+ Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
89
+
90
+ When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
91
+
92
+ - id: compaction
93
+ name: cordis:group
94
+ group: true
95
+ isolate:
96
+ compaction: true
97
+ toolResultPruner: true
98
+ config:
99
+ - id: compaction-basic
100
+ name: '@deepseek-ai/dsh-compaction-basic'
101
+
102
+ - id: command-compact
103
+ name: '@deepseek-ai/dsh-command-compact'
104
+
105
+ - id: tool-result-pruner
106
+ name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
107
+ config:
108
+ thresholdChars: 16384
109
+ headChars: 8192
110
+ tailChars: 2048
111
+
112
+ - id: delegation
113
+ name: cordis:group
114
+ group: true
115
+ isolate:
116
+ workflowEngine: true
117
+ config:
118
+ - id: tool-subagent-control
119
+ name: '@deepseek-ai/dsh-tool-subagent-control'
120
+
121
+ - id: tool-subagent-list-agents
122
+ name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
123
+
124
+ - id: tool-subagent
125
+ name: '@deepseek-ai/dsh-tool-subagent'
126
+ config:
127
+ provider: spawn
128
+ toolName: subagent
129
+ modelSelectionSettings: true
130
+
131
+ - id: tool-subagent-fork
132
+ name: '@deepseek-ai/dsh-tool-subagent'
133
+ config:
134
+ provider: fork
135
+ toolName: subagent_fork
136
+
137
+ - id: workflow-ptc
138
+ name: '@deepseek-ai/dsh-workflow-ptc'
139
+ disabled: true
140
+ config:
141
+ provider: spawn
142
+
143
+ - id: tool-workflow
144
+ name: '@deepseek-ai/dsh-tool-workflow'
145
+ disabled: true
146
+
147
+ - id: tool-ask-user
148
+ name: '@deepseek-ai/dsh-tool-ask-user'
149
+
150
+ - id: tool-todo
151
+ name: '@deepseek-ai/dsh-tool-todo'
152
+ config:
153
+ allowParallelInProgress: true
154
+
155
+ - id: tool-web
156
+ name: '@deepseek-ai/dsh-tool-web'
157
+ config:
158
+ fetch: true
159
+ searchTimeoutMs: 60000
160
+
161
+ - id: tool-presentation
162
+ name: '@deepseek-ai/dsh-agent-tool-presentation'
163
+ config:
164
+ mode: ptc
165
+
166
+ - id: present
167
+ name: '@deepseek-ai/dsh-tool-present'
168
+
169
+ - id: tool-plugin-manager
170
+ name: '@deepseek-ai/dsh-plugin-manager/tools'
171
+ disabled: true
172
+
173
+ - id: tool-plugin-market
174
+ name: '@deepseek-ai/dsh-plugin-market/tools'
175
+ disabled: true
176
+
177
+ - id: tool-wait-subagent
178
+ name: '@menghuan1918/dsh-apollo/presets/eng/plugins/wait-subagent/index.js'
179
+
180
+ - id: eng-exit-guard
181
+ name: '@menghuan1918/dsh-apollo/presets/eng/plugins/exit-guard/index.js'
182
+
183
+ - id: eng-mode-instructions
184
+ name: '@menghuan1918/dsh-apollo/presets/eng/plugins/mode-instructions/index.js'
185
+ config:
186
+ ptc: true
@@ -46,10 +46,9 @@
46
46
  # ── identity ────────────────────────────────────────────────────────────────
47
47
 
48
48
  # The preset's own persona, shadowing the deployment default for this agent.
49
- # One row on purpose: the rich engineering rules live in the user-global
50
- # instructions (~/.dsh/AGENTS.md) and the preset's `eng:mode-instructions`
51
- # section, not in the persona. `eng:mode-instructions` owns the delegation
52
- # policy; the tiers stay global because they track local route config.
49
+ # One row on purpose: the engineering rules, delegation policy and model
50
+ # tiers live in the preset's `eng:mode-instructions` section, not in the
51
+ # persona; ~/.dsh/AGENTS.md only keeps machine-local conventions.
53
52
  # 0.2.1's upstream `standard` preset carries `prefix` only: the working-
54
53
  # directory `suffix` line it used to set is gone, and eng follows suit.
55
54
  - id: persona
@@ -116,9 +115,9 @@
116
115
  # idle owner and is restored ONLY by a user-authored message, so a long
117
116
  # unattended chain of background jobs parks after its third wake — from the
118
117
  # fourth completion on, the notice degrades to injection and waits for the
119
- # user's next input. Keep this value identical in the eng-noask patch (the
120
- # upstream-drift test compares same-id row configs); upstream `standard`
121
- # ships no such key, and the drift test whitelists exactly this delta.
118
+ # user's next input. Keep this value identical in the eng-ptc patch (the
119
+ # upstream-drift test compares both presets against upstream with the
120
+ # same whitelist); upstream ships no such key.
122
121
  - id: tool-jobs
123
122
  name: '@deepseek-ai/dsh-tool-jobs'
124
123
  config:
@@ -327,15 +326,13 @@
327
326
 
328
327
  # ── mode instructions ────────────────────────────────────────────────────────
329
328
 
330
- # Preset-local prompt section carrying the two eng-only rules: the exit guard
331
- # contract and the delegation/orchestration policy (the latter moved out of the
332
- # user-global ~/.dsh/AGENTS.md on 2026-09-11 — the model tiers stay there
333
- # because they mirror this host's `subagent-model-selection` route list).
334
- # Registered as a system-prompt section (order 1, right after the persona slot)
335
- # so it is scoped to sessions mounted on this preset and nothing else; injected
336
- # from the first request alongside the other sections.
337
- # This plugins block (presets/eng.patch.yml) is the single source of truth;
338
- # the 0.2.1 bundle-patch mechanism loads it straight from this file, with no
339
- # boot-time copy in between.
329
+ # Preset-local prompt section carrying the engineering discipline (moved out
330
+ # of the user-global ~/.dsh/AGENTS.md), the delegation policy, the model
331
+ # tiers rendered from Apollo settings (`tiers.*`), and the exit guard
332
+ # contract when that switch is on. Registered as a system-prompt section
333
+ # (order 1, right after the persona slot) so it is scoped to sessions
334
+ # mounted on this preset; its text is re-rendered per request from the live
335
+ # Apollo config. `ptc: true` (set by eng-ptc) adds the rule for fanning
336
+ # out subagents inside one run_code program.
340
337
  - id: eng-mode-instructions
341
338
  name: '@menghuan1918/dsh-apollo/presets/eng/plugins/mode-instructions/index.js'
@@ -1,90 +1,90 @@
1
1
  ---
2
2
  name: brainstorming
3
- description: "把大型需求设计为多个协同 Spec。仅当用户显式调用 /brainstorming,或要求把大型任务拆分为可执行 Spec 时使用。"
3
+ description: "Design large requirements as multiple cooperating Specs. Use only when the user explicitly invokes /brainstorming, or asks to split a large task into executable Specs."
4
4
  ---
5
5
 
6
- # 大型任务头脑风暴
6
+ # Brainstorming Large Tasks
7
7
 
8
- 把大型需求整理为一个获批的主 Spec 和至少两个可执行子 Spec。保持 KISS:只沿真实的职责、依赖或验证边界拆分。
8
+ Turn a large requirement into one approved master Spec and at least two executable sub-Specs. Stay KISS: split only along real responsibility, dependency, or verification boundaries.
9
9
 
10
- **终态是交接给 `/exec`。** 不得实现功能、创建 worktree 或调用开发技能。用户批准书面 Spec 后停止。
10
+ **The end state is a handoff to `/exec`.** Do not implement features, create worktrees, or invoke development skills. Stop once the user approves the written Specs.
11
11
 
12
- ## 流程
12
+ ## Process
13
13
 
14
- 1. **探索项目上下文** — 检查文件、文档和当前项目状态。事实自己查,不问用户。
15
- 2. **逐一提问** — 每条消息只问一个决策问题,系统遍历设计树,每个问题以推荐答案开头。区分事实(自行查明)与决策(用户定夺)。详见下文提问规则。
16
- 3. **给出 2-3 个方案** — 含权衡和推荐,以推荐方案开头。
17
- 4. **分段展示设计** — 按复杂度决定每段长度,每段取得用户确认。需拆分时展示拆分方案(主 Spec + 子 Spec、依赖顺序、共享契约、集成验收)。
18
- 5. **写入全部 Spec** — 写盘后自审(占位符、矛盾、歧义、过度细节),内联修复。详见下文自审。
19
- 6. **派 spec-reviewer 审查** — 按 [`spec-document-reviewer-prompt.md`](spec-document-reviewer-prompt.md) 派一个全新只读 `subagent`(质量档 = 本会话最强模型)审查主 Spec 与全部子 Spec;修复阻塞项,必要时复派。
20
- 7. **请用户审阅** — 按反馈修改直至批准。
21
- 8. **交接给 `/exec`** — 告知用户用主 Spec 路径调用 `/exec`。
14
+ 1. **Explore project context** — inspect files, docs, and current project state. Look up facts yourself; do not ask the user.
15
+ 2. **Ask one question at a time** — one decision question per message, walking the design tree systematically, each question led by a recommended answer. Separate facts (look up yourself) from decisions (the user's call). See the question rules below.
16
+ 3. **Offer 2-3 options** — with tradeoffs and a recommendation, leading with the recommended option.
17
+ 4. **Present the design in sections** — scale each section's length to its complexity, and get the user's confirmation on each. When a split is needed, present it (master Spec + sub-Specs, dependency order, shared contracts, integration acceptance).
18
+ 5. **Write all Specs** — self-review after writing (placeholders, contradictions, ambiguity, over-detail) and fix inline. See self-review below.
19
+ 6. **Dispatch a spec-reviewer** — per [`spec-document-reviewer-prompt.md`](spec-document-reviewer-prompt.md), dispatch a fresh read-only `subagent` (quality tier) to review the master Spec and all sub-Specs; fix blockers and re-dispatch if needed.
20
+ 7. **Ask the user to review** — revise per feedback until approved.
21
+ 8. **Hand off to `/exec`** — tell the user to invoke `/exec` with the master Spec path.
22
22
 
23
- 完成标准:主 Spec + 全部子 Spec 已写入磁盘,用户已批准,已给出 `/exec` 调用方式。
23
+ Done when: the master Spec and all sub-Specs are on disk, the user has approved them, and the `/exec` invocation has been given.
24
24
 
25
- ## 提问规则
25
+ ## Question rules
26
26
 
27
- - **每条消息只问一个问题。** 等用户反馈再继续。一次问多个会导致混乱。
28
- - **给出推荐答案。** 附推理,用户可接受、拒绝或修改。
29
- - **事实 vs 决策。** 事实查代码库或文档获得,不问用户;决策展示给用户等待回答。
30
- - **优先多选题**,开放式问题也可以。
31
- - **聚焦理解:** 目标、约束、成功标准、架构、错误处理、测试。
27
+ - **One question per message.** Wait for the answer before continuing. Asking several at once causes confusion.
28
+ - **Lead with a recommended answer.** Include the reasoning; the user can accept, reject, or amend it.
29
+ - **Facts vs decisions.** Get facts from the codebase or docs; never ask the user. Present decisions to the user and wait for an answer.
30
+ - **Prefer multiple choice**, though open-ended questions are fine too.
31
+ - **Focus on understanding:** goals, constraints, success criteria, architecture, error handling, testing.
32
32
 
33
- 共识达成前不写 Spec。后续答案改变前提时,回头修正既有决定。
33
+ Do not write Specs before consensus. When a later answer changes a premise, go back and fix earlier decisions.
34
34
 
35
- ## 设计粒度
35
+ ## Design granularity
36
36
 
37
- 子 Spec 定义**做什么和为什么**,以及独立实现和验证所需的边界。不是实现食谱。(主 Spec 不在此列——它只是目标 + 索引,见拆分准则。)
37
+ A sub-Spec defines **what and why**, plus the boundaries needed to implement and verify it independently. It is not an implementation recipe. (The master Spec is exempt — it is just goal + index; see the split guidance.)
38
38
 
39
- - 包含目标、范围、关键决策、组件职责、交互、外部可观察行为、错误语义、验收标准、测试范围。
40
- - 把局部编码选择留给实现。不含代码、伪代码、私有类型设计、逐文件修改清单、分步指令。
41
- - 精确的公共契约(API 路由、共享 schema、配置键)仅在兼容性或迁移依赖时写入。
39
+ - Include goals, scope, key decisions, component responsibilities, interactions, externally observable behavior, error semantics, acceptance criteria, and test scope.
40
+ - Leave local coding choices to implementation. No code, pseudocode, private type design, per-file change lists, or step-by-step instructions.
41
+ - Write exact public contracts (API routes, shared schemas, config keys) only when compatibility or migration depends on them.
42
42
 
43
- ## 拆分准则
43
+ ## Split guidance
44
44
 
45
- 主 Spec 只承载总目标 + 索引(见下文多 Spec 结构),不承载任何具体执行内容。**鼓励多写子 Spec**——任务有几个独立单元就拆几个,下限两个,但更细的拆分只要每个子 Spec 仍能独立实现、独立验证就值得。每个子 Spec 必须能独立实现、独立测试,适合独立的 Spec → 实现周期。
45
+ The master Spec carries only the overall goal + index (see Multi-Spec structure below), never any concrete execution content. **Lean toward more sub-Specs** — split as many as the task has independent units, with two as the floor; finer splits are worth it as long as each sub-Spec can still be implemented and verified independently. Every sub-Spec must be independently implementable and testable, suited to its own Spec → implementation cycle.
46
46
 
47
- **拆分有价值时:** 任务确实复杂,有多个独立子系统或可并行轨道;每个子 Spec 接口清晰;拆分提升清晰度而非仅为并行。
47
+ **Splitting pays off when:** the task is genuinely complex, with multiple independent subsystems or parallel tracks; each sub-Spec has a clear interface; and the split improves clarity rather than just enabling parallelism.
48
48
 
49
- **过度拆分信号:** 子 Spec 间循环依赖;无法独立验证;共享契约多处不一致;拆出无独立职责的子 Spec。
49
+ **Signals of over-splitting:** circular dependencies between sub-Specs; nothing can be verified independently; shared contracts diverge in several places; sub-Specs carved out with no independent responsibility.
50
50
 
51
- 质量优先于并行——为清晰而拆分,不仅为了并行执行。
51
+ Quality over parallelism — split for clarity, not just for parallel execution.
52
52
 
53
- ## 多 Spec 结构
53
+ ## Multi-Spec structure
54
54
 
55
- ### 主 Spec
55
+ ### Master Spec
56
56
 
57
- **只做总目标 + 索引,不承载执行。** 内容限于:总目标、范围与非目标、子 Spec 索引(每个子 Spec 一行:职责 + 路径)、依赖 DAG 与并行分组、整体验收的指向。关键决策、共享契约、组件职责、交互、错误语义等具体内容一律下沉到子 Spec;主 Spec 只指明每个契约由哪个子 Spec 定义/拥有。不得在主 Spec 里实现任何东西。
57
+ **Only the overall goal + index, no execution content.** Confined to: overall goal, scope and non-goals, sub-Spec index (one line per sub-Spec: responsibility + path), dependency DAG and parallel groups, and a pointer to overall acceptance. Push all concrete content — key decisions, shared contracts, component responsibilities, interactions, error semantics — down to the sub-Specs; the master Spec only names which sub-Spec defines/owns each contract. Never implement anything in the master Spec.
58
58
 
59
- ### 子 Spec
59
+ ### Sub-Spec
60
60
 
61
- 独立实现、审查、测试和提交所需:边界明确的目标、范围内/外行为、依赖、输入输出和共享契约、错误语义、验收标准、聚焦验证范围、指向主 Spec 的链接。不复制主 Spec,只带入执行所需契约。
61
+ What independent implementation, review, testing, and commit need: a boundary-clear goal, in-scope/out-of-scope behavior, dependencies, inputs/outputs and shared contracts, error semantics, acceptance criteria, a focused verification scope, and a link back to the master Spec. Do not copy the master Spec; carry over only the contracts execution needs.
62
62
 
63
- ## 文件布局
63
+ ## File layout
64
64
 
65
- 落盘位置按工作区实际情况择一,不要两处都写:
65
+ Pick one landing location based on the actual workspace; do not write to both:
66
66
 
67
67
  ```text
68
- <工作区>/.workspace-docs/specs/MM-DD-<主题>-主设计/ # 工作区有 .workspace-docs/ 时用它
69
- <目标仓库>/docs/specs/MM-DD-<主题>-主设计/ # 否则用目标仓库自己的 specs 目录
70
- ├── MM-DD-<主题>-主设计.md
71
- ├── MM-DD-<主题>-<子任务A>-设计.md
72
- └── MM-DD-<主题>-<子任务B>-设计.md
68
+ <workspace>/.workspace-docs/specs/MM-DD-<topic>-master-design/ # when the workspace has .workspace-docs/
69
+ <target-repo>/docs/specs/MM-DD-<topic>-master-design/ # otherwise the target repo's own specs directory
70
+ ├── MM-DD-<topic>-master-design.md
71
+ ├── MM-DD-<topic>-<subtask-A>-design.md
72
+ └── MM-DD-<topic>-<subtask-B>-design.md
73
73
  ```
74
74
 
75
- - 主 Spec 与子 Spec 双向链接。
76
- - 目录内已有其它 Spec 时,沿用其文件名与头格式,不引入第二套约定。
77
- - 写入 `.workspace-docs/` 时每篇带 OKF 头部(`type: Design Spec`、`title`、`description`、`tags`、`status`、`repos`);提交推送遵循该仓库自己的 `AGENTS.md`。目标仓库无此约定时用仓库现有文档格式,不新造 OKF。
75
+ - Link master Spec and sub-Specs to each other in both directions.
76
+ - When the directory already holds other Specs, follow their file naming and header format; do not introduce a second convention.
77
+ - When writing under `.workspace-docs/`, give every file an OKF header (`type: Design Spec`, `title`, `description`, `tags`, `status`, `repos`); committing and pushing follow that repo's own `AGENTS.md`. Where the target repo has no such convention, use its existing doc format and do not invent OKF.
78
78
 
79
- ## 自审
79
+ ## Self-review
80
80
 
81
- 写入后用新鲜眼光检查:占位符(`TODO`/`TBD`)、内部一致性、范围聚焦、歧义、过度细节。内联修复全部问题。这是自己先过一遍;随后派 spec-reviewer 子代理做独立审查(流程第 6 步)。
81
+ After writing, check with fresh eyes: placeholders (`TODO`/`TBD`), internal consistency, scope focus, ambiguity, over-detail. Fix everything inline. This is your own first pass; a spec-reviewer subagent then does the independent review (process step 6).
82
82
 
83
- ## 可视化辅助
83
+ ## Visual aids
84
84
 
85
- 当展示优于讲述(mockup、布局、架构图、方案对比)时,写一个自包含 HTML 到系统临时目录(`$TMPDIR`,未设置时 `/tmp`),文件名 `brainstorm-<主题>-<序号>.html`:
85
+ When showing beats telling (mockups, layouts, architecture diagrams, option comparisons), write a self-contained HTML file to the system temp directory (`$TMPDIR`, or `/tmp` when unset), named `brainstorm-<topic>-<n>.html`:
86
86
 
87
- - 用 write 工具写完整文档:内联 CSS、无外部依赖、无脚本、无服务;每页 2-4 个选项或变体。
88
- - 文件名不复用;迭代就写新文件(`-2`、`-3`)。
89
- - 告知用户文件路径(DSH 界面可直接打开预览),并用一两句话概括页面内容;用户看后回到对话作答,不采集点击。
90
- - 每个问题独立判断是否需要可视化;概念性选择(A/B/C 方案、取舍清单)留在对话里。
87
+ - Write the complete document with the write tool: inline CSS, no external dependencies, no scripts, no server; 2-4 options or variants per page.
88
+ - Never reuse a file name; for iterations write a new file (`-2`, `-3`).
89
+ - Tell the user the file path (the DSH UI can open it for preview directly) and summarize the page in one or two sentences; the user looks, then answers back in the conversation — clicks are not collected.
90
+ - Decide per question whether a visual helps; keep conceptual choices (A/B/C options, tradeoff lists) in the conversation.