@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/README.md ADDED
@@ -0,0 +1,533 @@
1
+ # dsh-orchestrator-preset
2
+
3
+ A thin-shell agent preset for [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness):
4
+ the **aegis methodology pack** (upstream, consumed at runtime, unmodified) plus a
5
+ **self-authored orchestration layer** — nine named lanes with mechanically declared tool
6
+ boundaries, resident routing sections, a plan-aware persona, and an evidence-based
7
+ completion gate.
8
+
9
+ The repository root **is** the bundle. There is no `bundle/` subdirectory: the files here
10
+ are exactly the files that get installed.
11
+
12
+ [English](README.md) · [中文](README.zh.md)
13
+
14
+ ---
15
+
16
+ ## Design
17
+
18
+ > **This section is the current and complete authority for what this preset is and how it
19
+ > works.** There is no separate design specification in this repository: the full design
20
+ > draft this grew out of — about 280K of design history, decision trail and rejected
21
+ > alternatives — is **not distributed here**. It is held back, and this section is the
22
+ > design description in its place. If you want the deeper reasoning, ask; it is not linked
23
+ > because a link to a file this repository does not contain would look authoritative and
24
+ > fail on click.
25
+
26
+ ### What it is
27
+
28
+ DSH has no notion of an agent that delegates. A preset declares a set of tools and a
29
+ persona; nothing in that vocabulary says "this work belongs to someone else". This preset
30
+ supplies that missing layer. The orchestrator does not write code, search a codebase, or
31
+ review its own output — it routes each piece to a lane that is *declared* to be allowed to
32
+ do it, and then judges the result against evidence on disk.
33
+
34
+ ### Lanes and their tool boundaries
35
+
36
+ Nine lanes are rows of the preset itself: `planner`, `scout`, `archivist`, `seer`,
37
+ `reader`, `analyst`, `auditor`, `wright`, `forge`. Each carries its own persona file and
38
+ its own `toolFilter`, so a lane's capability boundary is **declarative, not advisory** — a
39
+ read-only lane's `deny` list removes `write`, `edit`, `todo_write`, every other lane's
40
+ dispatch tool, and the lead-side child-addressing tools from its seat. The deny lists are
41
+ what keep a lane from re-entering the coordinator role.
42
+
43
+ `lane-composition.mjs` closes a gap the host leaves open. A Team assembly gives the lead
44
+ `send_message` / `list_agents` / `interrupt_agent`, which address teammates **by name** and
45
+ cannot reach a `subagent_*` child at all — so a lead delegating through `subagent_*` lanes
46
+ would have no way to list, continue, or interrupt them. This bundle registers exactly those
47
+ three actions under distinct names (`subagent_children`, `subagent_send`,
48
+ `subagent_interrupt`), addressed by **durable agent id**. Two id namespaces, never mixed.
49
+ The three names are registered *globally* on purpose: `tools.restrict()` resolves against
50
+ the global registry, so a scoped registration would make every lane's deny entry illegal and
51
+ take the whole lane family down.
52
+
53
+ ### Routing sections
54
+
55
+ `routing-sections.mjs` registers four **static** text sections that are reassembled every
56
+ turn by the host's `systemPrompt` registry: the domain-owner table, the trigger-arbitration
57
+ table, a short index of standing judgements, and the MCP discipline. They are static
58
+ constants on purpose — a dynamic system prefix invalidates the session cache wholesale.
59
+
60
+ The single-owner rule is the point. The MCP discipline lives in exactly one section, the
61
+ orchestrator persona carries one pointer to it, and a delegation brief may *reference* it
62
+ but must never restate it. The same discipline governs the orchestration layer's own
63
+ content: the orchestrator persona explicitly disclaims the lane roster and the MCP rules,
64
+ because a second copy is a second owner.
65
+
66
+ **The four `orch-*` skill names are load-bearing, and renaming one is a two-file edit.**
67
+ `routing-sections.mjs` and `personas/orchestrator.md` both name `orch-evidence-protocol` and
68
+ `orch-delegation-brief` explicitly, and the routing table's rows resolve by that exact
69
+ string. Rename a skill directory and its frontmatter but not those references, and the row
70
+ keeps pointing at a name nothing provides — which is a silent failure, because a routing
71
+ entry that matches no skill simply never fires. `node tools/gen-cordis-patch.mjs` and
72
+ `node tools/audit-personas.mjs` catch a half-finished rename; neither is run automatically,
73
+ so run one after touching a skill name.
74
+
75
+ The `orch-` prefix itself is not decoration: these skills land in a registry that also holds
76
+ whatever else a given machine has installed, so an unprefixed `evidence-protocol` would be a
77
+ name waiting to collide.
78
+
79
+ ### Evidence and state
80
+
81
+ Completion is a file, not a sentence. A task counts as done only when
82
+ `.dsh/evidence/<task-id>-<slug>.md` exists, is non-empty, and carries exactly one anchored
83
+ verdict line as its last line. Every path touched in a turn is classified at completion as
84
+ `in_scope`, `out_of_scope`, `undeclared` or `illegal`, and anything but `in_scope` blocks
85
+ the completion claim. State that must outlive a session — the lane ledger
86
+ (`.dsh/state/lanes.md`), direction-level ownership claims (`.dsh/state/claims.md`) and
87
+ goal frames (`.dsh/goals/<slug>.md`) — lives in files, so that a claim can be checked
88
+ against what other writers also see.
89
+
90
+ ### How this differs from the upstream aegis pack
91
+
92
+ aegis supplies **method**: how to write a plan, run strict TDD, debug systematically, run a
93
+ review, verify before claiming done. It is a library of skills, and it assumes a single
94
+ coordinator doing the work.
95
+
96
+ This preset supplies **topology**: who does what, under which tool restrictions, with which
97
+ evidence. The two are orthogonal and complementary — aegis skills are routed *to* lanes
98
+ rather than executed in place. What the preset adds that aegis structurally cannot is
99
+ everything that presupposes more than one agent: the lane ledger and its three states, the
100
+ direction-level atomic claim with a staleness criterion for cross-session ownership, and
101
+ the independent-review rule. Those are not extensions to aegis; they are a different axis,
102
+ and no aegis skill is modified to accommodate them.
103
+
104
+ ---
105
+
106
+ ## Sourcing: what is upstream, what was measured here
107
+
108
+ Being precise about this matters more than it usually does, because a preset is a pile of
109
+ claims about someone else's runtime.
110
+
111
+ | Claim | Status |
112
+ |---|---|
113
+ | A bundle declares a patch via the `dsh.bundle.patch` field in its `package.json`, e.g. `"patch": "./cordis.patch.yml"`. | **Upstream contract.** Verbatim in the published `@deepseek-ai/dsh-base` manifest, which also exports the patch as a subpath. |
114
+ | Later patch layers win, and a patch **replaces the whole row** rather than deep-merging it — so a row overriding `config` must restate every key it needs. | **Corroborated twice, independently.** |
115
+ | Exact layer order: bundle patches in `dsh.profile.bundles` order, then the profile's own `cordis.patch.yml`, then `$DSH_HOME/cordis.patch.yml`, then each `--patch` overlay. | **Verified on host version 0.2.0-rc.1.** Not confirmed against upstream documentation. |
116
+ | A profile lives at `~/.dsh/profiles/<name>/` containing `cordis.yml`, `cordis.patch.yml` and `package.json`. | **Verified on host version 0.2.0-rc.1.** Not confirmed against upstream documentation. |
117
+ | `config.selectedDefault` is in the preset schema and is the effective value; the schema also carries `config.default`, and `defaultId` resolves `selectedDefault ?? default`. | **Verified on host version 0.2.0-rc.1**, against `@deepseek-ai/dsh-agent-preset-registry`. |
118
+
119
+ DeepSeek Harness is MIT-licensed: [`github.com/deepseek-ai/deepseek-harness`](https://github.com/deepseek-ai/deepseek-harness).
120
+ Unrelated projects sharing a similar name are not a source for anything in this repository.
121
+
122
+ ---
123
+
124
+ ## Repository layout
125
+
126
+ | Path | What it is |
127
+ |---|---|
128
+ | `cordis.patch.yml` | **Generated.** The preset's rows. Do not edit by hand — see below. |
129
+ | `tools/preset-declaration.mjs` | **The single source of truth** for the preset's rows. |
130
+ | `tools/gen-cordis-patch.mjs` | Generates `cordis.patch.yml` from the declaration. |
131
+ | `tools/audit-personas.mjs` | Static audit of the persona files (originality thresholds against an excluded upstream corpus). |
132
+ | `plan-aware-persona.mjs` | Swaps the persona between Orchestrator and Planner per assembly. |
133
+ | `routing-sections.mjs` | The four resident routing sections. |
134
+ | `lane-composition.mjs` | The three durable-agent-id child-addressing tools. |
135
+ | `personas/` | Ten persona files: orchestrator, planner, and one per lane. |
136
+ | `skills/` | The four self-authored `orch-*` skills. This directory is the authoritative list of them. |
137
+ | `extensions/dsh/` | The bundle's two plugins: the skills provider, and the aegis prefix bridge. |
138
+ | `docs/` | **Not distributed.** The design history is held back; the Design section above is the specification. |
139
+ | `install.sh` | Installs everything below into a DSH home. |
140
+ | `tools/verify-install.sh` | Twenty read-only checks that the preset is installed and selected. |
141
+ | `README.zh.md` | The Chinese README. Same content, same obligations. |
142
+ | `LICENSE` | MIT, plus third-party attribution. |
143
+
144
+ **Editing the preset.** `cordis.patch.yml` carries a "DO NOT EDIT BY HAND" header and is
145
+ regenerated. Change `tools/preset-declaration.mjs` and run:
146
+
147
+ ```sh
148
+ node tools/gen-cordis-patch.mjs
149
+ ```
150
+
151
+ The generator needs a skeleton patch to merge against; it looks for `--skeleton <path>`,
152
+ then `$DSH_SKELETON`, then the host's own `standard.patch.yml`, and it refuses to invent one
153
+ if none is found. The `cordis.patch.yml` in this repository is byte-for-byte what that
154
+ command produces from the committed declaration.
155
+
156
+ ---
157
+
158
+ ## Installation
159
+
160
+ The install method is a **`link:`** dependency, not an npm publish. `package.json` carries
161
+ `"private": true` **precisely so the `@local/`-scoped name can never be published by
162
+ accident** — that guard is what makes the current name safe, and it is the flag to remove at
163
+ the moment of any real publication (see [Publishing to npm](#publishing-to-npm-future-work-not-yet-done)).
164
+ The package declares **no** `dependencies` — the host supplies everything at runtime. It does
165
+ declare `peerDependencies`, all four marked `optional`, so that what it was tested against is
166
+ written down without any install being able to fail over it:
167
+
168
+ | Package | Range | Why |
169
+ |---|---|---|
170
+ | `@deepseek-ai/dsh-skill-filesystem` | `>=0.2.0-rc.2 <2` | the provider this bundle mounts |
171
+ | `@deepseek-ai/dsh-tools` | `>=0.2.0-rc.2 <2` | `defineTool`, used by `lane-composition.mjs` |
172
+ | `@deepseek-ai/cordis` | `>=4.0.1 <5` | the plugin contract; a real major boundary |
173
+ | `@deepseek-ai/schemastery` | `>=3.18.0 <4` | the `Config` schema the settings card is built from |
174
+
175
+ The lower bounds name **the version this was actually run against**, not an earlier one the
176
+ design happened to reference. The upper bounds follow the convention the published
177
+ `@quill507/dsh-auto-approval-llm` uses on the same host packages. `optional: true` is what
178
+ keeps the declaration honest: the coupling here is deep — `ctx.skills.registerProvider` is a
179
+ host API — so a major change could break this silently, and saying so is worth more than
180
+ pretending the range is enforced. It is not.
181
+
182
+ ### 0. Host version gate
183
+
184
+ ```sh
185
+ dsh --version # install.sh refuses below 0.1.7-rc.1
186
+ ```
187
+
188
+ This is a hard check inside `install.sh`, and it is deliberately **looser** than the
189
+ `peerDependencies` above: 0.1.7-rc.1 is the version the design was written against, while
190
+ 0.2.0-rc.2 is the version it has been run on. Between those two the honest answer is
191
+ **untested**, and the two numbers are kept separate for that reason rather than quietly
192
+ merged into one. `install.sh --check` runs this gate and writes nothing.
193
+
194
+ ### 1–4. Install
195
+
196
+ ```sh
197
+ ./install.sh # into $DSH_HOME, or ~/.dsh
198
+ DSH_HOME=/some/other/home ./install.sh
199
+ ```
200
+
201
+ From a clone, that stages the bundle into `<DSH_HOME>/plugins/dsh-orchestrator-preset-bundle/`
202
+ and verifies the per-profile symlink. Nothing is copied into `~/.dsh/skills/`, and there is no
203
+ companion plugin: the four skills are served by the bundle's own provider, and the aegis prefix
204
+ bridge is mounted by a row the generator emits. Doing it by hand:
205
+
206
+ ```sh
207
+ # 1. copy the bundle
208
+ cp -r . ~/.dsh/plugins/dsh-orchestrator-preset-bundle/
209
+
210
+ # 2. link it into a profile (see step 5 for the package.json line that makes this work)
211
+ # and run `pnpm install` there — pnpm creates the symlink from the `link:` dependency.
212
+ # Verify with test -L, never test -e: Git Bash can silently degrade a link into a
213
+ # copy, and a copy passes test -e while freezing every later edit to the bundle.
214
+ test -L ~/.dsh/profiles/web/node_modules/@quill507/dsh-orchestrator-preset && echo "real symlink"
215
+
216
+ # 3. the four self-authored skills need NO install step — they ship inside the
217
+ # bundle and are served by extensions/dsh/index.js, a filesystem skill provider
218
+ # mounted by the generated patch with includeDefaultRoots:false. Nothing is
219
+ # written to ~/.dsh/skills/.
220
+
221
+ # 4. nothing to install. The aegis prefix bridge ships inside the bundle as
222
+ # extensions/dsh/aegis-prefix.js, mounted by a generated patch row with two
223
+ # settings: prefixAegisSkills (default on) and describeAegisSkillsInZh
224
+ # (default off, turned on in your own layer — see below).
225
+ ```
226
+
227
+ **Nothing is copied into `~/.dsh/skills/`.** The four `orch-*` skills travel with the bundle
228
+ and a provider scoped to it serves them, so installing this preset adds nothing to your
229
+ global skills directory and removing it takes nothing away. That directory is where other
230
+ people's tools live; a preset that scatters copies into it inherits the mess without the
231
+ context. What this bundle ships is exactly what is in `skills/`, and `.gitignore` admits
232
+ those four paths one by one — a fifth cannot be added without saying so.
233
+
234
+ `describeAegisSkillsInZh` defaults to off because translating a catalogue is a reader
235
+ preference rather than a routing requirement.
236
+
237
+ **Set it in a patch layer. There is no settings-page control for it yet.** The home layer
238
+ `$DSH_HOME/cordis.patch.yml` applies after this bundle's, so a row there wins:
239
+
240
+ ```yaml
241
+ - id: orch-aegis-prefix
242
+ config:
243
+ prefixAegisSkills: true
244
+ describeAegisSkillsInZh: true
245
+ ```
246
+
247
+ Restate **both** keys. A patch replaces a row's config rather than deep-merging it, so naming
248
+ only the one you are changing drops the other back to its default. A restart is needed either
249
+ way: the config is read when the plugin is applied.
250
+
251
+ ### Why there is no control yet, and what it would take
252
+
253
+ The host does build settings forms from plugin schemas, and this plugin's `Config` is written
254
+ the way that requires — `@deepseek-ai/schemastery` rather than `zod`, with both fields marked
255
+ `.volatile()`. That is not sufficient, which was measured rather than assumed:
256
+ `dsh-settings.describe()` only considers entries that `dsh-config-editor.entries()` returns,
257
+ and that filters to rows whose `parent.tree.ctx.fiber.entry?.id === "include"`. A row inserted
258
+ by a bundle patch is not one of those, so nothing here reaches the settings UI.
259
+
260
+ The one third-party plugin on the development machine that does have a settings card
261
+ (`@quill507/dsh-auto-approval-llm`) does not use that path either — it ships a browser client
262
+ plugin plus its own GET route, and its own source calls the route the degradation source "for a
263
+ card that has no host form (entry not ACTIVE)". So a control here means writing a client
264
+ plugin: a `dsh.client` declaration, a separate browser entry, a read route, and a form bound to
265
+ this entry's id. That is a small project, not a field on this schema, and it is **not done**.
266
+
267
+ **Client-page support is planned and tracked here as unfinished.** Until it lands the switches
268
+ are config-only, and this section is the place to look when wondering why.
269
+
270
+ ### 5. Wire it into a profile
271
+
272
+ In `~/.dsh/profiles/<profile>/package.json`, add the dependency and the same string to
273
+ `dsh.profile.bundles`, keeping its position:
274
+
275
+ ```json
276
+ "@quill507/dsh-orchestrator-preset": "link:<DSH_HOME>/plugins/dsh-orchestrator-preset-bundle"
277
+ ```
278
+
279
+ then run `pnpm install` in that profile directory. In
280
+ `~/.dsh/profiles/<profile>/cordis.patch.yml`, select the preset:
281
+
282
+ ```yaml
283
+ - id: preset-dsh-orchestrator-preset
284
+ name: '@deepseek-ai/dsh-agent-preset'
285
+ config:
286
+ selectedDefault: dsh-orchestrator-preset
287
+ ```
288
+
289
+ A patch replaces the whole row rather than deep-merging it, so that snippet is the whole
290
+ row, not an addition to a larger one. Both profiles must pin the **same released tag** of
291
+ aegis; desktop must not float.
292
+
293
+ `install.sh` deliberately stops before this step: those are the live installation's own
294
+ files, and `cordis.patch.yml` is watched by `dsh-hmr`, so writing it triggers an immediate
295
+ full re-assembly of the running host. The script prints the edits instead of making them.
296
+
297
+ ### 6. Install the aegis methodology pack
298
+
299
+ `aegis` is an upstream dependency, not something this repository ships. Install it through
300
+ the host, and pin the same released tag in both profiles.
301
+
302
+ ---
303
+
304
+ ## Troubleshooting
305
+
306
+ **A preset chosen in the GUI does not come back on its own.** The preset chooser persists
307
+ through the config editor, which rewrites the profile's own `cordis.patch.yml` in place. A
308
+ preset picked there overwrites `selectedDefault`, and nothing restores it. The bundle's own
309
+ patch is not touched — only the profile's. Re-apply the step 5 row to come back; there is
310
+ no state to reset.
311
+
312
+ **`cordis.yml` is empty, and that is correct.** The host defines the empty list as a literal
313
+ and rewrites it on every boot so that it stays empty; composed rows are written back into
314
+ it by the loader, which would otherwise duplicate every bundle insert on the next boot.
315
+ **Grepping `cordis.yml` can never tell you which preset is selected** — inspect
316
+ `cordis.patch.yml` instead.
317
+
318
+ **The bundle loads but its files are not found.** Check the symlink with `test -L`. A
319
+ directory that exists but is not a symlink is a copy, and a copy will not track later edits.
320
+
321
+ **A lane behaves as if it lost a shell tool.** The preset declares *both* shells —
322
+ `tool-bash` and `tool-pwsh` — each gated on `process.platform`, so on Windows the preset
323
+ asks for `pwsh` and off Windows for `bash`. A layer applied **after** the profile layer can
324
+ override that: the `~/.dsh/cordis.patch.yml` home layer is one such place, and a host set
325
+ up for bash-only on Windows will force `tool-bash: disabled: false` and
326
+ `tool-pwsh: disabled: true` there. That is a **deployment fact, not a defect** — the
327
+ preset does not require `pwsh`, and a disabled tool is still a known tool, so the lanes
328
+ dispatch and work normally on bash alone. If a lane looks like it has lost its shell,
329
+ check your own home or profile layer before suspecting the preset: the home layer wins,
330
+ and it wins silently. Note that the generator derives the shell name that goes into the
331
+ lanes' `toolFilter` deny lists from the *effective* values of both the host layer and the
332
+ preset's own rows, so changing that override means re-running
333
+ `node tools/gen-cordis-patch.mjs`. This preset changes no tool row, filter or persona to
334
+ accommodate any particular shell arrangement.
335
+
336
+ **The persona prefix is empty.** `plan-aware-persona` fails loud on a missing or empty
337
+ persona file rather than silently stripping the agent's identity. Read the error: it names
338
+ the file.
339
+
340
+ ---
341
+
342
+ ## Verifying the install
343
+
344
+ ```sh
345
+ ./tools/verify-install.sh # checks the "desktop" profile
346
+ ./tools/verify-install.sh web
347
+ ```
348
+
349
+ Is the preset really installed, and is it really the one selected? Twenty checks across
350
+ eight groups, plain `PASS`/`FAIL` lines and a summary, exit non-zero if anything fails. It
351
+ is **read-only**: it composes the profile tree in memory and never writes to a DSH home —
352
+ check 5 asserts that rather than assuming it.
353
+
354
+ | # | What it checks |
355
+ |---|---|
356
+ | 1 | the profile patch selects this preset, exactly once |
357
+ | 2 | the bundle link is a **real symlink** — `test -L`, never `test -e`, because a link silently degraded into a copy still passes `test -e` |
358
+ | 3 | the bundle is **resolvable by package name** through the link, i.e. present *and* usable |
359
+ | 4 | the patch generator is in sync, run with **`DSH_HOME` unset** |
360
+ | 5 | the **composed** tree really selects this preset, with no occurrence of the pre-rename name, and the preset row present |
361
+ | 6 | the four `orch-*` skills are installed, and the four retired unprefixed names are gone as directories |
362
+ | 7 | the two shell rows read as this host deliberately configured them |
363
+ | 8 | leak gate: no machine-local absolute path, no third-party skill name and no private-data token, in any **tracked** file |
364
+
365
+ **Check 4 runs with `DSH_HOME` unset on purpose.** The generator resolves its skeleton
366
+ from `$DSH_HOME` and falls back to `~/.dsh`, so a shell that happens to export the variable
367
+ resolves fine while a plain one did not — and that read as "the tool is broken". The tool
368
+ was since repaired to fall back, so this proves it rather than assuming it.
369
+
370
+ **Check 5 composes the tree instead of reading `cordis.yml`,** because `cordis.yml` cannot
371
+ answer the question: it is a four-line empty root the host rewrites on every launch, so it
372
+ structurally cannot contain those rows and anything dumped into it dies at the next boot.
373
+ `dsh --profile <name> --dump-config` is also unavailable — the launcher refuses it outright
374
+ for an Electron-managed profile such as `desktop`. So the script calls the host's own
375
+ read-only loader, skips the step that rewrites `cordis.yml`, and greps the composed output.
376
+
377
+ ---
378
+
379
+ ## Dependencies
380
+
381
+ This bundle has no runtime npm dependencies. It imports `@deepseek-ai/dsh-tools` (for
382
+ `defineTool`, in `lane-composition.mjs`) and nothing else from the npm ecosystem; that
383
+ package is provided by the **host**, which is why it is neither a `dependency` nor a
384
+ `peerDependency` here.
385
+
386
+ The persona files are resolved by deep path at runtime
387
+ (`createRequire(baseUrl).resolve('@quill507/dsh-orchestrator-preset/personas/scout.md')`).
388
+ `baseUrl` is injected by the host, so resolution is independent of where the bundle is
389
+ installed. One fragility worth naming: `package.json` has **no `exports` field**, so those
390
+ deep `.md` paths currently resolve through Node's legacy no-exports behaviour. An explicit
391
+ `exports` map would be more robust and is listed under the npm work below.
392
+
393
+ ---
394
+
395
+ ## Publishing to npm (future work, not yet done)
396
+
397
+ **None of this has been done, attempted or tested.** It is recorded so the path is not
398
+ rediscovered from scratch. The runtime specifier is still `@local/`, and that is a
399
+ deliberate deferral, not an oversight: renaming the runtime specifier means re-linking and
400
+ re-verifying a working desktop installation, which is not a cost worth paying for a
401
+ packaging change nobody has asked for yet.
402
+
403
+ If it is wanted later:
404
+
405
+ - **The package name** it would take is currently undecided; it must match the bundle
406
+ directory name's tail segment, and it must stop being `@local/`-scoped.
407
+ - **The one line that must change** is `tools/preset-declaration.mjs:45`,
408
+ `export const bundlePkg = '@quill507/dsh-orchestrator-preset'`. That single constant
409
+ owns all 12 specifier references in the generated `cordis.patch.yml`; the 12 resolve to 12
410
+ distinct files (3 `.mjs` and 9 persona `.md`). Change that one line, then run
411
+ `node tools/gen-cordis-patch.mjs` — no other edit is needed, and no persona file is
412
+ affected. (`personas/orchestrator.md` is inlined rather than file-resolved, so it is
413
+ correctly absent from that list.)
414
+ - **Two things beyond that are unsolved**: the four skills under `skills/` are plain Markdown
415
+ with no npm story and would need a postinstall step to copy them into a profile's skills
416
+ directory; and `package.json` carries `"private": true`, which npm refuses to publish.
417
+ The `exports` map and the second-package question are both settled — the map exists, and
418
+ the companion plugin was folded into `extensions/dsh/aegis-prefix.js` rather than shipped
419
+ as its own package.
420
+ - **`"private": true` must be removed** at the moment of publication. It is the guard that
421
+ currently makes the name safe to have.
422
+ - **The npm account does not exist yet** on the public registry, so publication is blocked
423
+ on account setup, not on the code.
424
+
425
+ ### The skill-provider architecture — adopted, deliberately not built
426
+
427
+ **This is not implemented and not tested.** It is recorded because the owner adopted it as
428
+ the approach for a *later* round, and because it changes two of the items above.
429
+
430
+ The approach: **mount a plugin that calls `apply()` from `@deepseek-ai/dsh-skill-filesystem`**,
431
+ configured with `includeDefaultRoots: false` and `bundledSkillDir` pointing at the package's
432
+ own `skills/` tree. It is the same roughly 12-line shape aegis uses for its own bundled
433
+ skills. The package is already resolvable from this bundle with **zero new dependencies**,
434
+ and it exports `apply`, `FileSystemSkillProvider` and `Config` — so the entry point is
435
+ already there; what is missing is the call site and the registration.
436
+
437
+ **What it would delete:**
438
+
439
+ - **Install step 3 disappears.** Copying the four skills into the global `~/.dsh/skills/`
440
+ is no longer needed, because the provider serves them from inside the package. That also
441
+ removes the "copy one directory at a time, never the whole tree" hazard for users.
442
+ - **npm todo item 5 disappears with it** — the postinstall skill-copying step is the very
443
+ thing this architecture exists to avoid, so that item should be struck from the list
444
+ above rather than solved.
445
+
446
+ **What it would cost, and why that is why it is deferred:**
447
+
448
+ - **It changes the generated `cordis.patch.yml`.** A new plugin row has to be declared, so
449
+ the patch is regenerated and its current verified md5 — `ba04ddbeb2eaa82bcb9f6d2df00fc219`
450
+ — stops being the expected value. Anything that pins that digest has to be updated with it.
451
+ - The regeneration has to be done for real and re-verified against a host, not reasoned
452
+ about: the same generator that reproduces today's patch byte-for-byte is the thing that
453
+ would produce the new one, and a skill-provider row that fails to mount would remove the
454
+ four skills at runtime rather than at install time.
455
+
456
+ Doing it now would mean shipping a change to the running installation's skill surface for a
457
+ benefit nobody has asked for yet. Deferring costs nothing but a stale `cordis.patch.yml`
458
+ digest.
459
+
460
+ ---
461
+
462
+ ## License
463
+
464
+ MIT — see [`LICENSE`](./LICENSE).
465
+
466
+ ## Acknowledgements
467
+
468
+ This preset is mostly other people's work arranged in a particular way, and it is worth
469
+ saying whose.
470
+
471
+ **[DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)** — the host this
472
+ runs inside, MIT-licensed. The configuration rows in `cordis.patch.yml` are derived from
473
+ it, the bundle/patch model this project is built on is its design, and its own first-party
474
+ bundles (`dsh-web-app`, `dsh-base`) are the reference implementations the architecture here
475
+ was read off. Several findings recorded in this README — that composing a profile rewrites
476
+ its `cordis.yml`, that a filesystem skill provider can be pointed at an arbitrary tree —
477
+ are the host's documented behaviour, measured rather than guessed.
478
+
479
+ **[aegis](https://github.com/GanyuanRan/Aegis)** — the methodology pack this preset routes
480
+ into, by Jesse Vincent and Ganyuan Ran. It owns the method: the routing discipline, the
481
+ skill-per-situation idea, the pressure-testing and verification habits. This project
482
+ supplies the orchestration layer around it and consumes aegis at runtime without vendoring
483
+ a line of its text. Its `extensions/dsh/index.js` was also the working reference for the
484
+ provider mounted here — twelve lines that made the skills-in-the-bundle design obviously
485
+ correct before it was tried.
486
+
487
+ **[itamzxm](https://github.com/itamzxm)** — author of **Auto-Pilot**, a set of seven skills
488
+ written to work across agent environments other than this one, rather than for any single
489
+ host. They are bare skill directories with no package manifest, which is why nothing here was
490
+ a candidate to install: Auto-Pilot was read as a source of mechanisms, not adopted as a
491
+ component. Six groups of its mechanisms are borrowed here by mechanism rather than by text —
492
+ its memory model, its convening gate and convergence states, its bare-run test and delegation
493
+ letter, its four scheduling rules, and its search and goal criteria. Auto-Pilot is not
494
+ published and carries no licence, and none of its text appears in this repository; where a
495
+ mechanism came from it, this repository's own design history names which one rather than
496
+ restating it.
497
+
498
+ **[Tacrine](https://github.com/Tacrine)** — who ported the oh-my-openagent agent set to
499
+ DeepSeek Harness and modified it, before this repository existed. The ten personas here
500
+ began as that port's output.
501
+
502
+ **oh-my-openagent** ([code-yeongyu/oh-my-openagent](https://github.com/code-yeongyu/oh-my-openagent))
503
+ — the upstream those personas ultimately descend from, and its author **code-yeongyu**. That
504
+ project is not open source, and no text from it is distributed here: every persona in this
505
+ repository has since been rewritten against an explicit threshold — under 2% n-gram overlap
506
+ with the upstream agent sources, and no run of six consecutive matching lines.
507
+ `tools/audit-personas.mjs` is that threshold, made runnable. Its term-probe half runs
508
+ anywhere; the overlap half needs the upstream corpus, which is deliberately not included, so
509
+ the rewrite is **partial evidence rather than a verified claim** — the tool reports it as
510
+ unverified, not as a pass, because those are different things.
511
+
512
+ **The authors of the packages this was tested against** — `@deepseek-ai/schemastery`, and the DSH packages that
513
+ supply `dsh-tools`, `dsh-skill-filesystem` and `dsh-home-paths`. Nothing here would load
514
+ without them, and none of them are dependencies of this package: the host supplies them at
515
+ runtime, which is precisely why this bundle declares no runtime dependencies of its own.
516
+
517
+ And a note on what is **not** acknowledged here: the tooling used to build this — a
518
+ language model working through a long session — is not a source of the design. The mistakes
519
+ in it are catalogued in this repository's own history rather than smoothed away, and the
520
+ distinction between what was measured and what was assumed is marked throughout.
521
+
522
+ ## Third-party attribution
523
+
524
+ The formal record — what is in this repository from somewhere else, and what is deliberately
525
+ not in it — is [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md). It is kept in its own
526
+ file rather than appended to `LICENSE`, because an appended block makes GitHub's licence
527
+ detector report "Other" for a file that is plainly MIT, and because a fact with two homes has
528
+ no home.
529
+
530
+ Two points from it are worth stating here, since they affect what you may do with this code:
531
+ the `aegis` pack is consumed at runtime and **not vendored**, and the third-party skills on
532
+ any given machine are **not redistributed** — some carry no licence at all, which makes
533
+ redistributing them a violation rather than an oversight.