@quill507/dsh-orchestrator-preset 0.1.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.
- package/.gitattributes +20 -0
- package/.gitignore +140 -0
- package/LICENSE +21 -0
- package/README.md +533 -0
- package/README.zh.md +222 -0
- package/THIRD_PARTY_NOTICES.md +67 -0
- package/cordis.patch.yml +399 -0
- package/extensions/dsh/aegis-prefix.js +197 -0
- package/extensions/dsh/index.js +41 -0
- package/install.sh +193 -0
- package/lane-composition.mjs +288 -0
- package/package.json +69 -0
- package/personas/analyst.md +74 -0
- package/personas/archivist.md +75 -0
- package/personas/auditor.md +79 -0
- package/personas/forge.md +101 -0
- package/personas/orchestrator.md +176 -0
- package/personas/planner.md +114 -0
- package/personas/reader.md +56 -0
- package/personas/scout.md +60 -0
- package/personas/seer.md +69 -0
- package/personas/wright.md +58 -0
- package/plan-aware-persona.mjs +102 -0
- package/routing-sections.mjs +120 -0
- package/skills/orch-delegation-brief/SKILL.md +55 -0
- package/skills/orch-discussion-protocol/SKILL.md +61 -0
- package/skills/orch-evidence-protocol/SKILL.md +88 -0
- package/skills/orch-real-path-testing/SKILL.md +66 -0
- package/tools/audit-personas.mjs +215 -0
- package/tools/gen-cordis-patch.mjs +424 -0
- package/tools/preset-declaration.mjs +468 -0
- package/tools/verify-install.sh +643 -0
package/cordis.patch.yml
ADDED
|
@@ -0,0 +1,399 @@
|
|
|
1
|
+
# Generated by tools/gen-cordis-patch.mjs — DO NOT EDIT BY HAND.
|
|
2
|
+
# Source of truth: tools/preset-declaration.mjs
|
|
3
|
+
# Regenerate: node tools/gen-cordis-patch.mjs
|
|
4
|
+
# Shell source: kind=dump-config fallback=yes bash=false @258 pwsh=true @262 normalized-digest=9d6e78b51fc4 (absolute path and raw md5 intentionally omitted; digest is path-normalized)
|
|
5
|
+
#
|
|
6
|
+
# This file's `plugins[]` rows are declared in full because DSH agent presets
|
|
7
|
+
# have no inheritance or composition mechanism (see DESIGN.md §2.1).
|
|
8
|
+
# Rows marked [official] below are configuration derived from DeepSeek Harness
|
|
9
|
+
# (MIT License, Copyright (c) 2026 DeepSeek); see LICENSE for the attribution.
|
|
10
|
+
- insert:
|
|
11
|
+
- id: preset-dsh-orchestrator-preset
|
|
12
|
+
name: '@deepseek-ai/dsh-agent-preset'
|
|
13
|
+
config:
|
|
14
|
+
id: 'dsh-orchestrator-preset'
|
|
15
|
+
name: 'DSH Orchestrator Preset'
|
|
16
|
+
description: |-
|
|
17
|
+
A thin orchestration preset: aegis method pack for methodology, self-authored lane boundaries for delegation. Declares its full plugins[] because DSH presets have no inheritance.
|
|
18
|
+
plugins:
|
|
19
|
+
- id: persona
|
|
20
|
+
name: '@quill507/dsh-orchestrator-preset/plan-aware-persona.mjs'
|
|
21
|
+
config:
|
|
22
|
+
suffix: 'Your working directory is {{cwd}}.'
|
|
23
|
+
- id: routing-sections
|
|
24
|
+
name: '@quill507/dsh-orchestrator-preset/routing-sections.mjs'
|
|
25
|
+
- id: lane-composition
|
|
26
|
+
name: '@quill507/dsh-orchestrator-preset/lane-composition.mjs'
|
|
27
|
+
- id: agent-instructions
|
|
28
|
+
name: '@deepseek-ai/dsh-agent-instructions'
|
|
29
|
+
config:
|
|
30
|
+
maxBytes: 65536
|
|
31
|
+
- id: tool-bash
|
|
32
|
+
name: '@deepseek-ai/dsh-tool-bash'
|
|
33
|
+
disabled: !!js process.platform === 'win32'
|
|
34
|
+
- id: tool-pwsh
|
|
35
|
+
name: '@deepseek-ai/dsh-tool-pwsh'
|
|
36
|
+
disabled: !!js process.platform !== 'win32'
|
|
37
|
+
- id: tool-fs
|
|
38
|
+
name: '@deepseek-ai/dsh-tool-fs'
|
|
39
|
+
- id: tool-fs-search
|
|
40
|
+
name: '@deepseek-ai/dsh-tool-fs-search'
|
|
41
|
+
config:
|
|
42
|
+
sampleOverCapGlobResults: false
|
|
43
|
+
- id: tool-jobs
|
|
44
|
+
name: '@deepseek-ai/dsh-tool-jobs'
|
|
45
|
+
- id: skill-filesystem
|
|
46
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
47
|
+
- id: tool-skill
|
|
48
|
+
name: '@deepseek-ai/dsh-tool-skill'
|
|
49
|
+
- id: tool-ask-user
|
|
50
|
+
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
51
|
+
- id: tool-todo
|
|
52
|
+
name: '@deepseek-ai/dsh-tool-todo'
|
|
53
|
+
config:
|
|
54
|
+
allowParallelInProgress: true
|
|
55
|
+
- id: tool-web
|
|
56
|
+
name: '@deepseek-ai/dsh-tool-web'
|
|
57
|
+
config:
|
|
58
|
+
fetch: true
|
|
59
|
+
searchTimeoutMs: 60000
|
|
60
|
+
- id: planning
|
|
61
|
+
name: cordis:group
|
|
62
|
+
group: true
|
|
63
|
+
isolate:
|
|
64
|
+
planMode: true
|
|
65
|
+
config:
|
|
66
|
+
- id: plan-mode
|
|
67
|
+
name: '@deepseek-ai/dsh-plan-mode'
|
|
68
|
+
config:
|
|
69
|
+
section: |
|
|
70
|
+
You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user 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.
|
|
71
|
+
|
|
72
|
+
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.
|
|
73
|
+
|
|
74
|
+
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.
|
|
75
|
+
|
|
76
|
+
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.
|
|
77
|
+
|
|
78
|
+
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.
|
|
79
|
+
|
|
80
|
+
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.
|
|
81
|
+
- id: compaction
|
|
82
|
+
name: cordis:group
|
|
83
|
+
group: true
|
|
84
|
+
isolate:
|
|
85
|
+
compaction: true
|
|
86
|
+
toolResultPruner: true
|
|
87
|
+
config:
|
|
88
|
+
- id: compaction-basic
|
|
89
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
90
|
+
- id: command-compact
|
|
91
|
+
name: '@deepseek-ai/dsh-command-compact'
|
|
92
|
+
- id: tool-result-pruner
|
|
93
|
+
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
|
94
|
+
config:
|
|
95
|
+
thresholdChars: 8192
|
|
96
|
+
headChars: 4096
|
|
97
|
+
tailChars: 1024
|
|
98
|
+
- id: delegation
|
|
99
|
+
name: cordis:group
|
|
100
|
+
group: true
|
|
101
|
+
config:
|
|
102
|
+
- id: tool-subagent-control
|
|
103
|
+
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
104
|
+
- id: tool-subagent-list-agents
|
|
105
|
+
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
106
|
+
- id: tool-subagent-fork
|
|
107
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
108
|
+
config:
|
|
109
|
+
provider: fork
|
|
110
|
+
toolName: subagent_fork
|
|
111
|
+
backgroundMode: continuable
|
|
112
|
+
- id: tool-subagent-scout
|
|
113
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
114
|
+
config:
|
|
115
|
+
provider: spawn
|
|
116
|
+
toolName: subagent_scout
|
|
117
|
+
backgroundMode: continuable
|
|
118
|
+
maxDepth: 1
|
|
119
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/scout.md'), 'utf8')
|
|
120
|
+
toolFilter:
|
|
121
|
+
deny:
|
|
122
|
+
- write
|
|
123
|
+
- edit
|
|
124
|
+
- todo_write
|
|
125
|
+
- ask_user_question
|
|
126
|
+
- exit_plan_mode
|
|
127
|
+
- send_message
|
|
128
|
+
- interrupt_agent
|
|
129
|
+
- list_agents
|
|
130
|
+
- subagent_children
|
|
131
|
+
- subagent_send
|
|
132
|
+
- subagent_interrupt
|
|
133
|
+
- subagent_fork
|
|
134
|
+
- subagent_scout
|
|
135
|
+
- subagent_archivist
|
|
136
|
+
- subagent_seer
|
|
137
|
+
- subagent_reader
|
|
138
|
+
- subagent_analyst
|
|
139
|
+
- subagent_auditor
|
|
140
|
+
- subagent_wright
|
|
141
|
+
- subagent_forge
|
|
142
|
+
- subagent_planner
|
|
143
|
+
- mcp_playwright
|
|
144
|
+
- mcp_jlceda
|
|
145
|
+
- mcp_cloudflare-browser
|
|
146
|
+
- mcp_desktop-touch
|
|
147
|
+
- id: tool-subagent-archivist
|
|
148
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
149
|
+
config:
|
|
150
|
+
provider: spawn
|
|
151
|
+
toolName: subagent_archivist
|
|
152
|
+
backgroundMode: continuable
|
|
153
|
+
maxDepth: 1
|
|
154
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/archivist.md'), 'utf8')
|
|
155
|
+
toolFilter:
|
|
156
|
+
deny:
|
|
157
|
+
- write
|
|
158
|
+
- edit
|
|
159
|
+
- todo_write
|
|
160
|
+
- ask_user_question
|
|
161
|
+
- exit_plan_mode
|
|
162
|
+
- send_message
|
|
163
|
+
- interrupt_agent
|
|
164
|
+
- list_agents
|
|
165
|
+
- subagent_children
|
|
166
|
+
- subagent_send
|
|
167
|
+
- subagent_interrupt
|
|
168
|
+
- subagent_fork
|
|
169
|
+
- subagent_scout
|
|
170
|
+
- subagent_archivist
|
|
171
|
+
- subagent_seer
|
|
172
|
+
- subagent_reader
|
|
173
|
+
- subagent_analyst
|
|
174
|
+
- subagent_auditor
|
|
175
|
+
- subagent_wright
|
|
176
|
+
- subagent_forge
|
|
177
|
+
- subagent_planner
|
|
178
|
+
- mcp_playwright
|
|
179
|
+
- mcp_jlceda
|
|
180
|
+
- mcp_cloudflare-browser
|
|
181
|
+
- mcp_desktop-touch
|
|
182
|
+
- id: tool-subagent-seer
|
|
183
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
184
|
+
config:
|
|
185
|
+
provider: spawn
|
|
186
|
+
toolName: subagent_seer
|
|
187
|
+
backgroundMode: continuable
|
|
188
|
+
maxDepth: 1
|
|
189
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/seer.md'), 'utf8')
|
|
190
|
+
toolFilter:
|
|
191
|
+
deny:
|
|
192
|
+
- write
|
|
193
|
+
- edit
|
|
194
|
+
- todo_write
|
|
195
|
+
- ask_user_question
|
|
196
|
+
- exit_plan_mode
|
|
197
|
+
- send_message
|
|
198
|
+
- interrupt_agent
|
|
199
|
+
- list_agents
|
|
200
|
+
- subagent_children
|
|
201
|
+
- subagent_send
|
|
202
|
+
- subagent_interrupt
|
|
203
|
+
- subagent_fork
|
|
204
|
+
- subagent_scout
|
|
205
|
+
- subagent_archivist
|
|
206
|
+
- subagent_seer
|
|
207
|
+
- subagent_reader
|
|
208
|
+
- subagent_analyst
|
|
209
|
+
- subagent_auditor
|
|
210
|
+
- subagent_wright
|
|
211
|
+
- subagent_forge
|
|
212
|
+
- subagent_planner
|
|
213
|
+
- mcp_playwright
|
|
214
|
+
- mcp_jlceda
|
|
215
|
+
- mcp_cloudflare-browser
|
|
216
|
+
- mcp_desktop-touch
|
|
217
|
+
- id: tool-subagent-reader
|
|
218
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
219
|
+
config:
|
|
220
|
+
provider: spawn
|
|
221
|
+
toolName: subagent_reader
|
|
222
|
+
backgroundMode: continuable
|
|
223
|
+
maxDepth: 1
|
|
224
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/reader.md'), 'utf8')
|
|
225
|
+
toolFilter:
|
|
226
|
+
allow:
|
|
227
|
+
- read
|
|
228
|
+
- read_image
|
|
229
|
+
- id: tool-subagent-analyst
|
|
230
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
231
|
+
config:
|
|
232
|
+
provider: spawn
|
|
233
|
+
toolName: subagent_analyst
|
|
234
|
+
backgroundMode: continuable
|
|
235
|
+
maxDepth: 1
|
|
236
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/analyst.md'), 'utf8')
|
|
237
|
+
toolFilter:
|
|
238
|
+
deny:
|
|
239
|
+
- write
|
|
240
|
+
- edit
|
|
241
|
+
- todo_write
|
|
242
|
+
- ask_user_question
|
|
243
|
+
- exit_plan_mode
|
|
244
|
+
- send_message
|
|
245
|
+
- interrupt_agent
|
|
246
|
+
- list_agents
|
|
247
|
+
- subagent_children
|
|
248
|
+
- subagent_send
|
|
249
|
+
- subagent_interrupt
|
|
250
|
+
- subagent_fork
|
|
251
|
+
- subagent_scout
|
|
252
|
+
- subagent_archivist
|
|
253
|
+
- subagent_seer
|
|
254
|
+
- subagent_reader
|
|
255
|
+
- subagent_analyst
|
|
256
|
+
- subagent_auditor
|
|
257
|
+
- subagent_wright
|
|
258
|
+
- subagent_forge
|
|
259
|
+
- subagent_planner
|
|
260
|
+
- mcp_playwright
|
|
261
|
+
- mcp_jlceda
|
|
262
|
+
- mcp_cloudflare-browser
|
|
263
|
+
- mcp_desktop-touch
|
|
264
|
+
- id: tool-subagent-auditor
|
|
265
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
266
|
+
config:
|
|
267
|
+
provider: spawn
|
|
268
|
+
toolName: subagent_auditor
|
|
269
|
+
backgroundMode: continuable
|
|
270
|
+
maxDepth: 1
|
|
271
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/auditor.md'), 'utf8')
|
|
272
|
+
toolFilter:
|
|
273
|
+
deny:
|
|
274
|
+
- write
|
|
275
|
+
- edit
|
|
276
|
+
- todo_write
|
|
277
|
+
- ask_user_question
|
|
278
|
+
- exit_plan_mode
|
|
279
|
+
- send_message
|
|
280
|
+
- interrupt_agent
|
|
281
|
+
- list_agents
|
|
282
|
+
- subagent_children
|
|
283
|
+
- subagent_send
|
|
284
|
+
- subagent_interrupt
|
|
285
|
+
- subagent_fork
|
|
286
|
+
- subagent_scout
|
|
287
|
+
- subagent_archivist
|
|
288
|
+
- subagent_seer
|
|
289
|
+
- subagent_reader
|
|
290
|
+
- subagent_analyst
|
|
291
|
+
- subagent_auditor
|
|
292
|
+
- subagent_wright
|
|
293
|
+
- subagent_forge
|
|
294
|
+
- subagent_planner
|
|
295
|
+
- mcp_playwright
|
|
296
|
+
- mcp_jlceda
|
|
297
|
+
- mcp_cloudflare-browser
|
|
298
|
+
- mcp_desktop-touch
|
|
299
|
+
- id: tool-subagent-wright
|
|
300
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
301
|
+
config:
|
|
302
|
+
provider: spawn
|
|
303
|
+
toolName: subagent_wright
|
|
304
|
+
backgroundMode: continuable
|
|
305
|
+
maxDepth: 1
|
|
306
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/wright.md'), 'utf8')
|
|
307
|
+
toolFilter:
|
|
308
|
+
deny:
|
|
309
|
+
- ask_user_question
|
|
310
|
+
- exit_plan_mode
|
|
311
|
+
- send_message
|
|
312
|
+
- interrupt_agent
|
|
313
|
+
- list_agents
|
|
314
|
+
- subagent_children
|
|
315
|
+
- subagent_send
|
|
316
|
+
- subagent_interrupt
|
|
317
|
+
- subagent_fork
|
|
318
|
+
- subagent_scout
|
|
319
|
+
- subagent_archivist
|
|
320
|
+
- subagent_seer
|
|
321
|
+
- subagent_reader
|
|
322
|
+
- subagent_analyst
|
|
323
|
+
- subagent_auditor
|
|
324
|
+
- subagent_wright
|
|
325
|
+
- subagent_forge
|
|
326
|
+
- subagent_planner
|
|
327
|
+
- mcp_playwright
|
|
328
|
+
- mcp_jlceda
|
|
329
|
+
- mcp_cloudflare-browser
|
|
330
|
+
- mcp_desktop-touch
|
|
331
|
+
- id: tool-subagent-forge
|
|
332
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
333
|
+
config:
|
|
334
|
+
provider: spawn
|
|
335
|
+
toolName: subagent_forge
|
|
336
|
+
backgroundMode: continuable
|
|
337
|
+
maxDepth: 1
|
|
338
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/forge.md'), 'utf8')
|
|
339
|
+
toolFilter:
|
|
340
|
+
deny:
|
|
341
|
+
- ask_user_question
|
|
342
|
+
- exit_plan_mode
|
|
343
|
+
- interrupt_agent
|
|
344
|
+
- subagent_children
|
|
345
|
+
- subagent_send
|
|
346
|
+
- subagent_interrupt
|
|
347
|
+
- subagent_fork
|
|
348
|
+
- subagent_analyst
|
|
349
|
+
- subagent_auditor
|
|
350
|
+
- subagent_reader
|
|
351
|
+
- subagent_wright
|
|
352
|
+
- subagent_forge
|
|
353
|
+
- subagent_planner
|
|
354
|
+
- mcp_playwright
|
|
355
|
+
- mcp_jlceda
|
|
356
|
+
- mcp_cloudflare-browser
|
|
357
|
+
- mcp_desktop-touch
|
|
358
|
+
- id: tool-subagent-planner
|
|
359
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
360
|
+
config:
|
|
361
|
+
provider: spawn
|
|
362
|
+
toolName: subagent_planner
|
|
363
|
+
backgroundMode: continuable
|
|
364
|
+
maxDepth: 1
|
|
365
|
+
persona: !!js process.getBuiltinModule('node:fs').readFileSync(process.getBuiltinModule('node:module').createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/planner.md'), 'utf8')
|
|
366
|
+
toolFilter:
|
|
367
|
+
deny:
|
|
368
|
+
- write
|
|
369
|
+
- edit
|
|
370
|
+
- todo_write
|
|
371
|
+
- ask_user_question
|
|
372
|
+
- exit_plan_mode
|
|
373
|
+
- send_message
|
|
374
|
+
- interrupt_agent
|
|
375
|
+
- list_agents
|
|
376
|
+
- subagent_children
|
|
377
|
+
- subagent_send
|
|
378
|
+
- subagent_interrupt
|
|
379
|
+
- subagent_fork
|
|
380
|
+
- subagent_scout
|
|
381
|
+
- subagent_archivist
|
|
382
|
+
- subagent_seer
|
|
383
|
+
- subagent_reader
|
|
384
|
+
- subagent_analyst
|
|
385
|
+
- subagent_auditor
|
|
386
|
+
- subagent_wright
|
|
387
|
+
- subagent_forge
|
|
388
|
+
- subagent_planner
|
|
389
|
+
- mcp_playwright
|
|
390
|
+
- mcp_jlceda
|
|
391
|
+
- mcp_cloudflare-browser
|
|
392
|
+
- mcp_desktop-touch
|
|
393
|
+
- id: orch-method-pack
|
|
394
|
+
name: '@quill507/dsh-orchestrator-preset/extensions/dsh/index.js'
|
|
395
|
+
- id: orch-aegis-prefix
|
|
396
|
+
name: '@quill507/dsh-orchestrator-preset/extensions/dsh/aegis-prefix.js'
|
|
397
|
+
config:
|
|
398
|
+
prefixAegisSkills: true
|
|
399
|
+
describeAegisSkillsInZh: false
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Namespaces the aegis methodology pack's skills with an `aegis-` prefix, and
|
|
3
|
+
* optionally localises their descriptions.
|
|
4
|
+
*
|
|
5
|
+
* WHY THE PREFIX LIVES HERE
|
|
6
|
+
* The preset's resident routing table names twenty-one skills by their prefixed
|
|
7
|
+
* name, while the upstream pack registers them bare — it is host-agnostic and has
|
|
8
|
+
* no reason to know this preset exists. Nothing bridged that, so every aegis row
|
|
9
|
+
* in the routing table pointed at a name resolving to nothing, and the failure was
|
|
10
|
+
* silent: a routing entry that matches no skill simply never fires.
|
|
11
|
+
*
|
|
12
|
+
* WHY THE DESCRIPTION SWAP IS A SECOND, OFF-BY-DEFAULT FLAG
|
|
13
|
+
* Translating the catalogue is a reader preference, not a routing requirement, and
|
|
14
|
+
* forcing it on everyone who installs this preset would be wrong. It is OFF by
|
|
15
|
+
* default and turned on per deployment, in a layer the reader owns.
|
|
16
|
+
*
|
|
17
|
+
* WHY BOTH LIVE IN ONE PLUGIN
|
|
18
|
+
* They were briefly two plugins: this bridge for the prefix, a separate local one
|
|
19
|
+
* for descriptions. That produced a race — this bridge copies a description while
|
|
20
|
+
* registering, so whichever plugin ran first decided whether Chinese or English
|
|
21
|
+
* got copied, and the observed result was neither: twenty-one routing targets
|
|
22
|
+
* resolved, but only four descriptions were localised. Two plugins mutating the
|
|
23
|
+
* same registrations need a load-order contract to be correct, and such a contract
|
|
24
|
+
* is only correct until somebody reorders the bundle array. Doing both in one pass
|
|
25
|
+
* at registration removes the question instead of answering it.
|
|
26
|
+
*
|
|
27
|
+
* `skills/change` is still observed rather than reading the catalogue once, so a
|
|
28
|
+
* pack that registers late still gets namespaced.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import z from '@deepseek-ai/schemastery'
|
|
32
|
+
|
|
33
|
+
const AEGIS_PROVIDER = 'aegis-method-pack'
|
|
34
|
+
const PREFIX = 'aegis-'
|
|
35
|
+
|
|
36
|
+
/** Cordis plugin name. */
|
|
37
|
+
export const name = 'orch-aegis-prefix'
|
|
38
|
+
|
|
39
|
+
/** Only the skill registry: this plugin registers names, it serves none.
|
|
40
|
+
* No `settings` injection, because there is no settings surface to serve — the
|
|
41
|
+
* switches are set in a patch layer. See the note above `Config`. */
|
|
42
|
+
export const inject = ['skills']
|
|
43
|
+
|
|
44
|
+
/** Behaviour defaults, shared by the schema below and by the read in `apply`.
|
|
45
|
+
* Declared once so the schema's default and the code's default cannot drift. */
|
|
46
|
+
const DEFAULTS = Object.freeze({
|
|
47
|
+
prefixAegisSkills: true,
|
|
48
|
+
describeAegisSkillsInZh: false,
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* The two switches. **Not rendered as a settings card — see below.**
|
|
53
|
+
*
|
|
54
|
+
* Set them in a patch layer: the home layer `$DSH_HOME/cordis.patch.yml` applies
|
|
55
|
+
* after this bundle's, so a row there wins. Restate both keys, because a patch
|
|
56
|
+
* replaces a row's config rather than deep-merging it.
|
|
57
|
+
*
|
|
58
|
+
* WHY THERE IS NO UI, measured rather than assumed
|
|
59
|
+
* The host does build forms from plugin schemas — `dsh-settings.describe()` reads
|
|
60
|
+
* `entry.fiber.runtime.Config` and runs its own `volatileForm()` over it — but it
|
|
61
|
+
* only considers entries returned by `dsh-config-editor.entries()`, which filters
|
|
62
|
+
* to rows whose `parent.tree.ctx.fiber.entry?.id === "include"`. A row inserted by
|
|
63
|
+
* a bundle patch is not one of those, so nothing here appears in the settings UI.
|
|
64
|
+
*
|
|
65
|
+
* The one third-party plugin on this host that *does* have a settings card
|
|
66
|
+
* (`@quill507/dsh-auto-approval-llm`) does not use that path either: it ships a
|
|
67
|
+
* browser client plugin and its own GET route, and its source says outright that
|
|
68
|
+
* the route exists as the degradation source "for a card that has no host form
|
|
69
|
+
* (entry not ACTIVE)".
|
|
70
|
+
*
|
|
71
|
+
* So reaching the UI means writing a client plugin, which is a separate project
|
|
72
|
+
* rather than a field on this schema. The schema is kept anyway: it is the correct
|
|
73
|
+
* declaration, it carries the two defaults, and it is exactly what such a client
|
|
74
|
+
* would bind to. Two earlier attempts at the auto-form failed for reasons recorded
|
|
75
|
+
* above — a `zod` Config is invisible to `volatileForm`, and adding schemastery plus
|
|
76
|
+
* `.volatile()` satisfies that function while leaving the `include` filter unmet.
|
|
77
|
+
*/
|
|
78
|
+
export const Config = z.object({
|
|
79
|
+
prefixAegisSkills: z.boolean().default(DEFAULTS.prefixAegisSkills).volatile(),
|
|
80
|
+
describeAegisSkillsInZh: z.boolean().default(DEFAULTS.describeAegisSkillsInZh).volatile(),
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* English original -> compressed Chinese. The English string is the match key,
|
|
85
|
+
* taken verbatim from each SKILL.md, so an upstream rewrite falls through to
|
|
86
|
+
* English rather than mismatching into something garbled. `tools/verify-install.sh`
|
|
87
|
+
* checks every key against the installed pack, so a stale table announces itself.
|
|
88
|
+
*/
|
|
89
|
+
const ZH_DESCRIPTIONS = [
|
|
90
|
+
['Use when touching retiring old logic, collapsing duplicate owners, removing fallbacks, or schema/persistence/source-of-truth boundaries; identify opportunities automatically; destructive execution requires explicit confirmation.', '退役旧逻辑/合并重复owner/移除回退/动数据源边界时用;自动识别机会,破坏性执行需确认。'],
|
|
91
|
+
['Use when defining ambiguous or high-complexity new features, product behavior, UI/component design, architecture choices, contract changes, or when grilling/pressure-testing a plan or design. Routine small requests stay on the fast path.', '模糊/高复杂度新功能、UI/组件、架构选择、合同变更,或盘问/压力测试方案时用;常规小请求走快路径。'],
|
|
92
|
+
['Use when the user asks for caveman mode, fewer tokens, brief responses, compressed communication, or otherwise explicitly requests a much shorter answer.', '用户要求 caveman 模式/少 token/简短回答/压缩沟通时用。'],
|
|
93
|
+
['Use when facing 2+ independent tasks without a written plan, with no conflicting shared mutable state or sequential dependencies, where parallel delegation beats inline cost; otherwise inline. Planned tasks use subagent-driven-development.', '2+ 独立无依赖任务、无书面计划、无冲突共享可变状态/顺序依赖、并行派发优于内联时用;有计划的任务用 subagent-driven-development。'],
|
|
94
|
+
['Use when the user asks to establish shared project language, or project work exposes a conflicting, renamed, or deprecated domain term that needs active semantic modeling. Routine small tasks stay on the fast path.', '建立共享项目语言,或领域术语冲突/重命名/过时需要语义建模时用;常规小任务走快路径。'],
|
|
95
|
+
['Use when executing a written implementation plan across sessions or with review checkpoints. Small or single-slice plans stay inline. For same-session independent tasks, use subagent-driven-development instead.', '跨会话或带审查检查点执行书面实现计划时用;小/单切片计划内联;同会话独立任务用 subagent-driven-development。'],
|
|
96
|
+
['Use when verified work needs integration or cleanup of an existing task-created branch/worktree, or the user explicitly requests merge, PR, or branch lifecycle handling.', '已验证工作需集成/清理任务创建的分支/worktree,或用户明确要求 merge/PR/分支生命周期处理时用。'],
|
|
97
|
+
["Use when asked for first-principles or Occam's-razor review, or when high-risk decisions involve competing constraints, fallback growth, duplicate owners, or architecture direction risk. Ordinary bug fixes stay on the fast path.", '被要求第一性原理/Occam 剃刀审查,或高风险决策(竞争约束/回退增长/重复owner/架构方向风险)时用;普通 bug 修复走快路径。'],
|
|
98
|
+
['Use when the user explicitly sets an Aegis goal with /aegis-goal, Aegis goal:, or asks to define goal, success evidence, stop condition, or task boundaries before work.', '用户用 /aegis-goal、Aegis goal:,或要求定义目标、成功证据、停止条件、任务边界时用。'],
|
|
99
|
+
['Use when a task is multi-step, may span context resets or sessions, uses subagents, or risks losing state before completion.', '任务多步骤、跨上下文重置/会话、用子代理、或有完成前丢失状态风险时用。'],
|
|
100
|
+
['Use when receiving code review feedback before implementing suggestions, especially when feedback is unclear, risky, disputed, or technically questionable.', '收到代码评审反馈、实施建议前用,尤其反馈不清晰、有风险、有争议或技术上可疑时。'],
|
|
101
|
+
['Use when the user asks to create, write, update, amend, supersede, or evaluate an ADR, architecture decision record, durable architecture decision, decision log, or baseline sync after architecture-changing work.', '用户要求创建/编写/更新/修订/废止/评估 ADR、架构决策记录、持久化架构决策、决策日志或基线同步时用。'],
|
|
102
|
+
['Use when requesting independent code review, after implementation slices, before merging high-risk work, or when verification exposes evidence, baseline, architecture, compatibility, or retirement uncertainty.', '请求独立代码评审:实现切片后、合并高风险工作前、或验证暴露证据/基线/架构/兼容性/退役不确定性时用。'],
|
|
103
|
+
['Use when executing a written implementation plan with independent tasks in the current session where delegation beats inline coordination cost; otherwise inline. Ad-hoc 2+ tasks without a plan use dispatching-parallel-agents.', '执行书面实现计划、当前会话独立任务委托优于内联时用;临时 2+ 无计划任务用 dispatching-parallel-agents。'],
|
|
104
|
+
['Use when encountering a bug, test failure, or unexpected behavior, before proposing fixes', '遇到 bug、测试失败或意外行为、提出修复前用。'],
|
|
105
|
+
['Use when the user explicitly requests strict or test-first TDD, or when the current conversation already contains an explicit `TDD Route: strict` decision from another Aegis workflow.', '用户显式要求严格/测试优先 TDD,或会话已有 TDD Route: strict 决策时用。'],
|
|
106
|
+
['Use when the user says `aegis:update`, asks to update or upgrade an installed Aegis method-pack, wants the latest Aegis version, or asks whether Aegis is current on this host.', '用户说 aegis:update、要求更新/升级已装方法包、要最新版本或询问是否最新时用。'],
|
|
107
|
+
['Use when starting a turn or checking Aegis skill routing.', '回合开始或检查 Aegis 技能路由时用。'],
|
|
108
|
+
['Use when a coding task needs a concurrent checkout, unrelated dirty state blocks safe branch switching, or the user or repository explicitly requires a worktree.', '编码任务需并发 checkout、无关脏状态阻止安全切分支、或用户/仓库明确要求 worktree 时用。'],
|
|
109
|
+
['Use when about to claim work is complete, fixed, passing, verified, release-ready, or ready to commit, merge, publish, or hand off.', '声称完成/修复/通过/可发布,或准备提交/合并/发布/移交时用。'],
|
|
110
|
+
['Use when you have an approved spec or written requirements for a multi-step task that needs a durable plan document before touching code. Small, single-owner, or fast-path tasks do not need this skill.', '有已批准规格/书面需求的多步骤任务、动代码前需持久计划文档时用;小/单owner/快路径任务不需要。'],
|
|
111
|
+
['Use when creating new skills, editing existing skills, or verifying skills work before deployment', '创建新技能、编辑现有技能、或部署前验证技能可用时用。'],
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
const ZH_BY_EN = new Map(ZH_DESCRIPTIONS)
|
|
115
|
+
|
|
116
|
+
export function apply(ctx, rawConfig) {
|
|
117
|
+
// Read the two switches off the raw patch value, applying DEFAULTS for whatever
|
|
118
|
+
// the row does not set. Schemastery schemas are not zod's: there is no `.parse`
|
|
119
|
+
// here, and calling the schema does not fill defaults either — so the defaults
|
|
120
|
+
// have to come from the shared constant, which is also what the card shows.
|
|
121
|
+
const raw = rawConfig !== null && typeof rawConfig === 'object' ? rawConfig : {}
|
|
122
|
+
const pick = (key) => (typeof raw[key] === 'boolean' ? raw[key] : DEFAULTS[key])
|
|
123
|
+
const wantPrefix = pick('prefixAegisSkills')
|
|
124
|
+
const wantZh = pick('describeAegisSkillsInZh')
|
|
125
|
+
|
|
126
|
+
if (!wantPrefix) {
|
|
127
|
+
ctx.logger.info("[orch-aegis-prefix] prefix disabled by config; the preset's routing table will not resolve")
|
|
128
|
+
return
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const skills = ctx.skills
|
|
132
|
+
const done = new Set()
|
|
133
|
+
const disposers = []
|
|
134
|
+
let syncing = false
|
|
135
|
+
|
|
136
|
+
async function sync() {
|
|
137
|
+
if (syncing) return
|
|
138
|
+
syncing = true
|
|
139
|
+
try {
|
|
140
|
+
const summaries = await skills.list()
|
|
141
|
+
const targets = summaries.filter((s) => s.provider === AEGIS_PROVIDER && !done.has(s.name))
|
|
142
|
+
for (const summary of targets) {
|
|
143
|
+
const skill = await skills.get(summary.name)
|
|
144
|
+
if (!skill) continue
|
|
145
|
+
const bare = skill.name
|
|
146
|
+
const prefixed = bare.startsWith(PREFIX) ? bare : PREFIX + bare
|
|
147
|
+
// The swap happens HERE, in the same pass as the rename, so no window
|
|
148
|
+
// exists in which another plugin could copy the un-swapped text.
|
|
149
|
+
const description = wantZh
|
|
150
|
+
? (ZH_BY_EN.get(skill.description ?? '') ?? skill.description)
|
|
151
|
+
: skill.description
|
|
152
|
+
disposers.push(
|
|
153
|
+
skills.register({
|
|
154
|
+
name: prefixed,
|
|
155
|
+
...(description !== undefined ? { description } : {}),
|
|
156
|
+
...(skill.whenToUse !== undefined ? { whenToUse: skill.whenToUse } : {}),
|
|
157
|
+
invocation: skill.invocation ?? { modelInvocable: true, userInvocable: true },
|
|
158
|
+
source: 'orch-aegis-prefix',
|
|
159
|
+
content: skill.content,
|
|
160
|
+
...(skill.resourceBase !== undefined ? { resourceBase: skill.resourceBase } : {}),
|
|
161
|
+
...(skill.path !== undefined ? { path: skill.path } : {}),
|
|
162
|
+
...(skill.metadata !== undefined ? { metadata: skill.metadata } : {}),
|
|
163
|
+
}),
|
|
164
|
+
)
|
|
165
|
+
if (prefixed !== bare) {
|
|
166
|
+
// Tombstone the bare name. Runtime beats bundled on collision, so this
|
|
167
|
+
// wins over the provider's entry and the old spelling stops being
|
|
168
|
+
// loadable — one skill, one name, no way to reach it by the other.
|
|
169
|
+
disposers.push(
|
|
170
|
+
skills.register({
|
|
171
|
+
name: bare,
|
|
172
|
+
description: `Renamed to ${prefixed}; load that name instead.`,
|
|
173
|
+
invocation: { modelInvocable: false, userInvocable: false },
|
|
174
|
+
source: 'orch-aegis-prefix',
|
|
175
|
+
content: `This skill was renamed to ${prefixed}.`,
|
|
176
|
+
}),
|
|
177
|
+
)
|
|
178
|
+
}
|
|
179
|
+
done.add(summary.name)
|
|
180
|
+
ctx.logger.info(`[orch-aegis-prefix] "${bare}" -> "${prefixed}"${wantZh ? ' (zh)' : ''}`)
|
|
181
|
+
}
|
|
182
|
+
} catch (error) {
|
|
183
|
+
ctx.logger.warn(`[orch-aegis-prefix] sync failed: ${String(error)}`)
|
|
184
|
+
} finally {
|
|
185
|
+
syncing = false
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
ctx.logger.info(`[orch-aegis-prefix] applied; zh=${wantZh}, ${ZH_DESCRIPTIONS.length} mappings available`)
|
|
190
|
+
void sync()
|
|
191
|
+
ctx.on('skills/change', () => {
|
|
192
|
+
void sync()
|
|
193
|
+
})
|
|
194
|
+
ctx.effect(() => () => {
|
|
195
|
+
for (const dispose of disposers) dispose()
|
|
196
|
+
})
|
|
197
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin DeepSeek Harness bundle adapter for the orchestrator preset's own skills.
|
|
3
|
+
*
|
|
4
|
+
* Deliberately aegis-shaped and nothing more:
|
|
5
|
+
* - the host-owned filesystem provider stays the discovery implementation; this
|
|
6
|
+
* adapter only points one isolated provider at this package's own skills/ tree;
|
|
7
|
+
* - no skill bodies are copied at load time and the native skill tool is untouched;
|
|
8
|
+
* - no agent or agentTeams injection, so `inject` is just ["skills"].
|
|
9
|
+
*
|
|
10
|
+
* The `orch-` prefix is NOT applied here. It lives in each SKILL.md's frontmatter
|
|
11
|
+
* `name:`, which is where the filesystem provider reads the skill name from, so a
|
|
12
|
+
* resync from source can never bake a second naming decision into the tree.
|
|
13
|
+
*
|
|
14
|
+
* `includeDefaultRoots: false` is what keeps this isolated: the user's global
|
|
15
|
+
* skills directory is somebody else's environment and is not this package's
|
|
16
|
+
* business.
|
|
17
|
+
*
|
|
18
|
+
* Entry specifier: the bundle patch mounts this file as
|
|
19
|
+
* @quill507/dsh-orchestrator-preset/extensions/dsh/index.js
|
|
20
|
+
* The full scoped form is required. A bare or short form resolves to a directory
|
|
21
|
+
* that does not exist and the bundle fails to load with MODULE_NOT_FOUND, which
|
|
22
|
+
* is silent from the user's side — measured on this host, see the note in
|
|
23
|
+
* tools/verify-install.sh and hw-skills' own cordis.patch.yml.
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
import { fileURLToPath } from "node:url";
|
|
27
|
+
import { apply as applyFilesystemProvider } from "@deepseek-ai/dsh-skill-filesystem";
|
|
28
|
+
|
|
29
|
+
const skillsRoot = fileURLToPath(new URL("../../skills/", import.meta.url));
|
|
30
|
+
|
|
31
|
+
export const name = "orch-method-pack";
|
|
32
|
+
export const inject = ["skills"];
|
|
33
|
+
|
|
34
|
+
export function apply(ctx) {
|
|
35
|
+
applyFilesystemProvider(ctx, {
|
|
36
|
+
providerName: "orch-method-pack",
|
|
37
|
+
includeDefaultRoots: false,
|
|
38
|
+
bundledSkillDir: skillsRoot,
|
|
39
|
+
watch: false,
|
|
40
|
+
});
|
|
41
|
+
}
|