geneseed 3.8.0 → 3.10.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.
Files changed (229) hide show
  1. package/CHANGELOG.md +71 -1
  2. package/DESIGN.md +13 -10
  3. package/QUICKSTART.md +1 -1
  4. package/README.md +31 -32
  5. package/SETUP.md +7 -42
  6. package/SHIPPED.md +4 -4
  7. package/adapters/bob/README.md +17 -1
  8. package/adapters/openclaude/README.md +1 -1
  9. package/adapters/opencode/GLOBAL-HARNESS-SPEC.md +1 -1
  10. package/adapters/opencode/README.md +3 -3
  11. package/adapters/opencode/plugins/geneseed-context.js +78 -8
  12. package/adapters/opencode/plugins/geneseed-guard.js +9 -9
  13. package/adapters/opencode/plugins/geneseed-workflow.js +1 -1
  14. package/adapters/opencode/workflows/_runtime.js +2 -2
  15. package/adapters/opencode/workflows/dispatch.js +1 -1
  16. package/bin/geneseed-hook.mjs +1 -1
  17. package/docs/candidate-hosts.md +12 -5
  18. package/docs/extending.md +72 -40
  19. package/docs/token-footprint.md +26 -21
  20. package/docs/web/claude-hooks.md +1 -1
  21. package/docs/web/collaboration.md +1 -1
  22. package/docs/web/exclusions.md +0 -1
  23. package/docs/web/footprint.md +1 -1
  24. package/docs/web/harnesses.md +14 -14
  25. package/docs/web/install-quick.md +1 -1
  26. package/docs/web/plugin-guard.md +2 -2
  27. package/docs/web/rules.md +1 -1
  28. package/docs/web/themes-author.md +2 -2
  29. package/docs/web-ui.md +2 -2
  30. package/harness.config.json +1 -1
  31. package/js/README.md +8 -7
  32. package/js/build/driver.mjs +26 -95
  33. package/js/build/emit-claude.mjs +76 -81
  34. package/js/build/generate.mjs +0 -1
  35. package/js/build/render.mjs +10 -3
  36. package/js/build/source.mjs +105 -1
  37. package/js/build/stubs.mjs +25 -4
  38. package/js/cli-table.json +8 -8
  39. package/js/hosts/hooks.mjs +91 -59
  40. package/js/hosts/hosts.mjs +5 -21
  41. package/js/hosts/installs.mjs +4 -6
  42. package/js/hosts/mcp.mjs +3 -13
  43. package/js/hosts/native.mjs +28 -51
  44. package/js/hosts/opencode.mjs +1 -1
  45. package/js/hosts/settings.mjs +4 -78
  46. package/js/inspect/checks-authoring.mjs +153 -117
  47. package/js/inspect/checks-repo.mjs +45 -1
  48. package/js/inspect/diff.mjs +11 -3
  49. package/js/inspect/doctor.mjs +3 -3
  50. package/js/inspect/excludes.mjs +0 -4
  51. package/js/inspect/inventory.mjs +1 -2
  52. package/js/inspect/status.mjs +4 -4
  53. package/js/maintain/migrate.mjs +5 -5
  54. package/js/maintain/setup.mjs +3 -5
  55. package/js/maintain/uninstall.mjs +8 -42
  56. package/js/ui/tui.mjs +1 -1
  57. package/js/web/actions.mjs +4 -5
  58. package/js/web/api.mjs +10 -5
  59. package/package.json +1 -2
  60. package/registry.json +7 -0
  61. package/src/AGENT.md.tmpl +86 -65
  62. package/src/agents/_template.md +3 -3
  63. package/src/agents/advocate.md +3 -3
  64. package/src/agents/architect.md +3 -3
  65. package/src/agents/developer.md +4 -4
  66. package/src/agents/docs.md +3 -3
  67. package/src/agents/empiricist.md +4 -4
  68. package/src/agents/explorer.md +4 -4
  69. package/src/agents/framer.md +3 -3
  70. package/src/agents/historian.md +3 -3
  71. package/src/agents/operator.md +3 -3
  72. package/src/agents/pragmatist.md +3 -3
  73. package/src/agents/researcher.md +7 -7
  74. package/src/agents/reviewer.md +3 -3
  75. package/src/agents/security.md +3 -3
  76. package/src/agents/skeptic.md +3 -3
  77. package/src/agents/steward.md +3 -3
  78. package/src/agents/tester.md +3 -3
  79. package/src/agents/user-advocate.md +3 -3
  80. package/src/agents/visionary.md +3 -3
  81. package/src/doctrines/README.md +4 -3
  82. package/src/doctrines/comms.md +4 -4
  83. package/src/doctrines/craft.md +20 -20
  84. package/src/doctrines/ops.md +19 -19
  85. package/src/doctrines/process.md +20 -20
  86. package/src/doctrines/rigor.md +22 -22
  87. package/src/laws/universal.md +26 -44
  88. package/src/memory/README.md +3 -3
  89. package/src/modes/foreman.md +1 -1
  90. package/src/notebook/README.md +1 -1
  91. package/src/ontology/universal.md +8 -10
  92. package/src/postures/artisan.md +2 -2
  93. package/src/skills/_self-improvement.md +4 -4
  94. package/src/skills/_template.md +1 -1
  95. package/src/skills/brainstorm.md +3 -3
  96. package/src/skills/bruno-collection-generator.md +6 -6
  97. package/src/skills/bruno-test-writer.md +5 -5
  98. package/src/skills/ci-fix.md +4 -4
  99. package/src/skills/commit.md +11 -10
  100. package/src/skills/consolidate-memory.md +4 -4
  101. package/src/skills/council.md +2 -2
  102. package/src/skills/daydream/SKILL.md +10 -3
  103. package/src/skills/daydream/VENDOR.md +10 -2
  104. package/src/skills/daydream/instructions.md +2 -2
  105. package/src/skills/debug.md +4 -4
  106. package/src/skills/deps-audit.md +3 -3
  107. package/src/skills/develop.md +7 -7
  108. package/src/skills/document-project.md +6 -6
  109. package/src/skills/explain-changes/SKILL.md +69 -0
  110. package/src/skills/explain-changes/VENDOR.md +20 -0
  111. package/src/skills/explain-changes/scripts/render_changes.mjs +558 -0
  112. package/src/skills/forge-mcp.md +4 -4
  113. package/src/skills/fresh-eyes.md +4 -4
  114. package/src/skills/frontend-design.md +1 -1
  115. package/src/skills/geneseed.md +4 -4
  116. package/src/skills/git-archaeology.md +5 -5
  117. package/src/skills/git-rescue.md +7 -7
  118. package/src/skills/handoff.md +3 -3
  119. package/src/skills/ingest.md +5 -5
  120. package/src/skills/migrate.md +8 -8
  121. package/src/skills/parallel-agents.md +2 -2
  122. package/src/skills/pipeline.md +2 -2
  123. package/src/skills/plan.md +3 -3
  124. package/src/skills/ponytail.md +2 -2
  125. package/src/skills/profile.md +2 -2
  126. package/src/skills/prose.md +1 -1
  127. package/src/skills/prototype.md +1 -1
  128. package/src/skills/react-view-transitions/SKILL.md +1 -1
  129. package/src/skills/react-view-transitions/VENDOR.md +7 -2
  130. package/src/skills/refactor.md +3 -3
  131. package/src/skills/release.md +5 -5
  132. package/src/skills/repo-map.md +4 -4
  133. package/src/skills/research.md +9 -9
  134. package/src/skills/review-response.md +4 -4
  135. package/src/skills/rule.md +3 -3
  136. package/src/skills/security-audit.md +5 -5
  137. package/src/skills/ship.md +5 -5
  138. package/src/skills/skill-forge.md +4 -4
  139. package/src/skills/token-report/SKILL.md +2 -3
  140. package/src/skills/token-report/VENDOR.md +2 -3
  141. package/src/skills/token-report/scripts/token_report.mjs +7 -121
  142. package/src/skills/wiki.md +5 -5
  143. package/src/skills/workflow.md +3 -4
  144. package/src/skills/worktree.md +4 -4
  145. package/themes/_TEMPLATE.json +37 -39
  146. package/themes/biker.json +37 -39
  147. package/themes/commentator.json +37 -39
  148. package/themes/cyberpunk.json +37 -39
  149. package/themes/gamer.json +37 -39
  150. package/themes/imperial.json +37 -39
  151. package/themes/joker.json +37 -39
  152. package/themes/marvin.json +37 -39
  153. package/themes/mean.json +37 -39
  154. package/themes/military.json +37 -39
  155. package/themes/neutral.json +37 -39
  156. package/themes/pirate.json +37 -39
  157. package/themes/sports.json +37 -39
  158. package/themes/verstappen.json +37 -39
  159. package/themes/wizard.json +37 -39
  160. package/web/dist/assets/Activity-BjVp522q.js +1 -0
  161. package/web/dist/assets/ActivityDetail-8ep1bspW.js +1 -0
  162. package/web/dist/assets/Dashboard-OkC_PCH6.js +2 -0
  163. package/web/dist/assets/{Docs-DrJNDPwI.js → Docs-CKPWz00o.js} +2 -2
  164. package/web/dist/assets/FilterInput-CVyqmYWM.js +1 -0
  165. package/web/dist/assets/GreenhouseView-D0cbCJ5m.js +2 -0
  166. package/web/dist/assets/Installs-BtGGdoTt.js +2 -0
  167. package/web/dist/assets/JournalView-Ckl4dmzR.js +1 -0
  168. package/web/dist/assets/Laws-CLpdRRk8.js +3 -0
  169. package/web/dist/assets/Library-wPPuKQrI.js +1 -0
  170. package/web/dist/assets/{Markdown-BQAvN8xx.js → Markdown-CkFyfgNf.js} +14 -14
  171. package/web/dist/assets/OperatorHudView-CiAkAkQL.js +2 -0
  172. package/web/dist/assets/Personal-D8CnDo9v.js +1 -0
  173. package/web/dist/assets/Tabs-B4HNrrCs.js +1 -0
  174. package/web/dist/assets/drawable-BiwaOo6x.js +1 -0
  175. package/web/dist/assets/geist-mono-latin-400-normal-DTRLJnHl.woff2 +0 -0
  176. package/web/dist/assets/geist-mono-latin-500-normal-YINYabwD.woff2 +0 -0
  177. package/web/dist/assets/index-C1yil5j1.js +2 -0
  178. package/web/dist/assets/index-CDPDk2vj.css +1 -0
  179. package/web/dist/assets/{react-DbkvxWG5.js → react-B9Z_tXRV.js} +1 -1
  180. package/web/dist/assets/sections-GalMS0Zv.js +1 -0
  181. package/web/dist/assets/usePoll-O0sJEw1Y.js +1 -0
  182. package/web/dist/index.html +4 -4
  183. package/web/src/pages/Laws.jsx +616 -361
  184. package/adapters/copilot/README.md +0 -105
  185. package/web/dist/assets/Activity-CH-7cPIM.js +0 -1
  186. package/web/dist/assets/ActivityDetail-DZvz0xS5.js +0 -1
  187. package/web/dist/assets/CatalogRow-DftXpZHY.js +0 -1
  188. package/web/dist/assets/Diff-DvwdG0L9.js +0 -2
  189. package/web/dist/assets/Doctor-OTmwmYZg.js +0 -1
  190. package/web/dist/assets/FilterInput-BakJLvaV.js +0 -1
  191. package/web/dist/assets/GreenhouseView-XxrAdriX.js +0 -2
  192. package/web/dist/assets/Harness-C_LYNk5c.js +0 -1
  193. package/web/dist/assets/JournalView-BcuyeEaR.js +0 -1
  194. package/web/dist/assets/Laws-CWHrTKY4.js +0 -3
  195. package/web/dist/assets/Library-CA9IHghn.js +0 -1
  196. package/web/dist/assets/OperatorHudView-BMRY1Tt4.js +0 -2
  197. package/web/dist/assets/Profile-wceET1JY.js +0 -1
  198. package/web/dist/assets/Rules-BEXvY4Tx.js +0 -1
  199. package/web/dist/assets/Settings-DS2zF0Ez.js +0 -1
  200. package/web/dist/assets/Skills-DahlOJuI.js +0 -1
  201. package/web/dist/assets/StatusBadge-Cg6j-NJL.js +0 -1
  202. package/web/dist/assets/activity-iWaWVtsR.js +0 -1
  203. package/web/dist/assets/audiowide-latin-400-normal-6GFCX7ni.woff2 +0 -0
  204. package/web/dist/assets/drawable-BTHjTzF7.js +0 -1
  205. package/web/dist/assets/geist-mono-latin-400-normal-DKaoCDn5.woff2 +0 -0
  206. package/web/dist/assets/geist-mono-latin-500-normal-C3sF8Y1B.woff2 +0 -0
  207. package/web/dist/assets/geist-mono-latin-600-normal-BHzjB6_C.woff2 +0 -0
  208. package/web/dist/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
  209. package/web/dist/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
  210. package/web/dist/assets/ibm-plex-mono-latin-600-normal-BgSNZQsw.woff2 +0 -0
  211. package/web/dist/assets/ibm-plex-serif-latin-400-normal-BIGslYFI.woff2 +0 -0
  212. package/web/dist/assets/ibm-plex-serif-latin-500-normal-REKAfBVG.woff2 +0 -0
  213. package/web/dist/assets/ibm-plex-serif-latin-600-normal-DAxitmSu.woff2 +0 -0
  214. package/web/dist/assets/index-AN5Emnrg.js +0 -2
  215. package/web/dist/assets/index-Ruh93A3A.css +0 -1
  216. package/web/dist/assets/inter-latin-400-normal-C38fXH4l.woff2 +0 -0
  217. package/web/dist/assets/inter-latin-500-normal-Cerq10X2.woff2 +0 -0
  218. package/web/dist/assets/inter-latin-600-normal-LgqL8muc.woff2 +0 -0
  219. package/web/dist/assets/inter-latin-700-normal-Yt3aPRUw.woff2 +0 -0
  220. package/web/dist/assets/lawCats-Btjp3Hk_.js +0 -1
  221. package/web/dist/assets/oswald-latin-400-normal-BAFo8sP8.woff2 +0 -0
  222. package/web/dist/assets/oswald-latin-500-normal-B-eyT0Dw.woff2 +0 -0
  223. package/web/dist/assets/oswald-latin-600-normal-plFmSr5g.woff2 +0 -0
  224. package/web/dist/assets/oswald-latin-700-normal-vy6hmKSr.woff2 +0 -0
  225. package/web/dist/assets/poppins-latin-400-normal-cpxAROuN.woff2 +0 -0
  226. package/web/dist/assets/poppins-latin-500-normal-C8OXljZJ.woff2 +0 -0
  227. package/web/dist/assets/poppins-latin-600-normal-zEkxB9Mr.woff2 +0 -0
  228. package/web/dist/assets/poppins-latin-700-normal-Qrb0O0WB.woff2 +0 -0
  229. package/web/dist/assets/rolldown-runtime-CbXtAM7H.js +0 -1
@@ -4,26 +4,26 @@ order: 4
4
4
  title: "Supported harnesses"
5
5
  kind: "concept"
6
6
  ---
7
- One source, **six emit targets** — each with a per-repo and a global (`-global`) variant, plus a portable `files` bundle any `AGENT.md`-aware tool can read. **OpenCode** runs its own engine (JS plugins, colour themes, LSP); **Claude Code**, **Bob**, **Copilot**, and **OpenClaude** share one Claude-shaped engine that diverges only by host dialect.
7
+ One source, **five emit targets** — each with a per-repo and a global (`-global`) variant, plus a portable `files` bundle any `AGENT.md`-aware tool can read. **OpenCode** runs its own engine (JS plugins, colour themes, LSP); **Claude Code**, **Bob**, and **OpenClaude** share one Claude-shaped engine that diverges only by host dialect.
8
8
 
9
- The harness *content* — the constitution (Ethos, Rules, Doctrines), Agents, Skills, Memory, and the preamble voice — is **identical on every host**: one build renders the same text for all six targets. What differs is how much of it the host can *automate* (via plugins or hooks) versus carry as preamble discipline.
9
+ The harness *content* — the constitution (Ethos, Rules, Doctrines), Agents, Skills, Memory, and the preamble voice — is **identical on every host**: one build renders the same text for all five targets. What differs is how much of it the host can *automate* (via plugins or hooks) versus carry as preamble discipline.
10
10
 
11
- | Capability | OpenCode | Claude | Bob | Copilot | OpenClaude |
12
- | --- | :---: | :---: | :---: | :---: | :---: |
13
- | Agents · Skills · Memory | ✅ | ✅ | ✅ | ✅ | ✅ |
14
- | Context injection | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble | 🪝 hook² |
15
- | Memory write-back (learn) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble | 🪝 hook² |
16
- | Git-gate consent (Doctrine process 5) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble | 🪝 hook² |
17
- | Sovereign-repo excludes | ⚙️ plugin | ✅ | ✅ | ➖ | ✅ |
18
- | MCP server wiring | ✅ | ✅ | ✅ | ✅ | ✅ |
19
- | Colour themes | ✅ | ➖ | ➖ | ➖ | ➖ |
20
- | LSP · workflows · primary-agent · `/`-commands | ✅ | ➖ | ➖ | ➖ | ➖ |
11
+ | Capability | OpenCode | Claude | Bob | OpenClaude |
12
+ | --- | :---: | :---: | :---: | :---: |
13
+ | Agents · Skills · Memory | ✅ | ✅ | ✅ | ✅ |
14
+ | Context injection | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
15
+ | Memory write-back (learn) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
16
+ | Git-gate consent (Consent Before Push) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
17
+ | Sovereign-repo excludes | ⚙️ plugin | ✅ | ✅ | ✅ |
18
+ | MCP server wiring | ✅ | ✅ | ✅ | ✅ |
19
+ | Colour themes | ✅ | ➖ | ➖ | ➖ |
20
+ | LSP · workflows · primary-agent · `/`-commands | ✅ | ➖ | ➖ | ➖ |
21
21
 
22
22
  ✅ native · ⚙️ OpenCode plugin · 🪝 `settings.json` hook · 📄 preamble prose only · ➖ no host mechanism (harness discipline still applies). ¹ Bob honours Claude-dialect hooks best-effort — inert if unsupported, harness still holds via the preamble. ² OpenClaude is a Claude Code fork: Claude's hooks verbatim, under `~/.openclaude` or a repo's `.openclaude/`.
23
23
 
24
- **The git-gate row is the one capability that is not always present**, on any host. It implements **Doctrine process 5**, so it is wired only on an install that built the **process** [doctrine pack](#/docs/setup-choices) in — drop that pack and the boundary drops with it, because a gate that keeps asking for a rule the install never adopted is a gate arguing with its own harness. One asymmetry: on OpenCode that holds for a *fresh* install, but a pack-off rebuild of an install whose `opencode.json` already carries a `git commit*` entry leaves it in place and reports it — Geneseed cannot tell its own entry from one you typed, so it removes neither ([doctrine packs](#/docs/setup-choices)). The invariant-territory refusals in the same neighbourhood (`rm -rf`, a force-push) are the Rules' territory, not the pack's, and stay in every build.
24
+ **The git-gate row is the one capability that is not always present**, on any host. It implements **Consent Before Push** (`process 5`), so it is wired only on an install that built the **process** [doctrine pack](#/docs/setup-choices) in — drop that pack and the boundary drops with it, because a gate that keeps asking for a rule the install never adopted is a gate arguing with its own harness. One asymmetry: on OpenCode that holds for a *fresh* install, but a pack-off rebuild of an install whose `opencode.json` already carries a `git commit*` entry leaves it in place and reports it — Geneseed cannot tell its own entry from one you typed, so it removes neither ([doctrine packs](#/docs/setup-choices)). The invariant-territory refusals in the same neighbourhood (`rm -rf`, a force-push) are the Rules' territory, not the pack's, and stay in every build.
25
25
 
26
- **No host drops an Agent, Skill, or the memory convention.** The asymmetry is otherwise entirely in *automation mechanism*: OpenCode's plugins and Claude/Bob/OpenClaude's hooks enforce a few of these rules for you at the tool boundary, where **Copilot** (no hook mechanism) enforces them through preamble discipline. The OpenCode-only extras (themes, LSP, workflow runner, primary-agent) have no analogue on a Claude-shaped host.
26
+ **No host drops an Agent, Skill, or the memory convention.** The asymmetry is otherwise entirely in *automation mechanism*: OpenCode's plugins and Claude/Bob/OpenClaude's hooks enforce a few of these rules for you at the tool boundary; what no host can automate rides the preamble. The OpenCode-only extras (themes, LSP, workflow runner, primary-agent) have no analogue on a Claude-shaped host.
27
27
 
28
28
  ---
29
29
 
@@ -18,7 +18,7 @@ To keep the command around: `npm install -g geneseed`, then plain `geneseed …`
18
18
 
19
19
  ### 2. Open your agent
20
20
 
21
- Open OpenCode (or Claude Code, Bob, Copilot, OpenClaude, or any `AGENT.md`-aware tool) in any repo. The first reply opens with the readiness sigil (`✅` neutral / `🧬` imperial / your theme's equivalent) and your project's docs are already in context.
21
+ Open OpenCode (or Claude Code, Bob, OpenClaude, or any `AGENT.md`-aware tool) in any repo. The first reply opens with the readiness sigil (`✅` neutral / `🧬` imperial / your theme's equivalent) and your project's docs are already in context.
22
22
 
23
23
  ### Prefer a clone?
24
24
 
@@ -6,9 +6,9 @@ kind: "concept"
6
6
  ---
7
7
  Enforces the safety Laws at the tool boundary (`tool.execute.before`) — the same *enforce by injection, don't just instruct* stance as the context plugin. The guard ships whole on every install, whatever [doctrine packs](#/docs/setup-choices) it built in — its blocking arms are **invariant** territory, and the speed-bump below is about which store a note belongs in, which is your call either way. The one boundary that does follow a pack is the commit/push consent gate, and that lives in the permission block rather than here. High-confidence patterns only, so legitimate work is never caught:
8
8
 
9
- - **Blocks** — writes to private-key / credential files (**Law I**), catastrophic shell like `rm -rf /` (**Law IV**), and any mutation under a declared wiki's `protected` folders (AGENT.md §8, from `wiki.jsonc`).
9
+ - **Blocks** — writes to private-key / credential files (**Sealed Secrets**), catastrophic shell like `rm -rf /` (**Deletion Is Deliberate**), and any mutation under a declared wiki's `protected` folders (AGENT.md §8, from `wiki.jsonc`).
10
10
  - **Warns** (logged, allowed) — `.env` writes and force-push.
11
- - **Speed-bumps** — the *first* write to `user-rules.md` or a memory file is refused, naming **Doctrine process 1**: a standing rule or a durable fact is the user's call, settled through the rule skill. A re-issued write goes through, so a legitimate write is never trapped. (On Claude Code and Bob the same guard is a `geneseed-hook rule-gate` hook, which can *ask* the user instead of refusing — OpenCode's `tool.execute.before` has no ask tier.)
11
+ - **Speed-bumps** — the *first* write to `user-rules.md` or a memory file is refused, naming **Persist Insight**: a standing rule or a durable fact is the user's call, settled through the rule skill. A re-issued write goes through, so a legitimate write is never trapped. (On Claude Code and Bob the same guard is a `geneseed-hook rule-gate` hook, which can *ask* the user instead of refusing — OpenCode's `tool.execute.before` has no ask tier.)
12
12
 
13
13
  ### Install
14
14
 
package/docs/web/rules.md CHANGED
@@ -13,7 +13,7 @@ The agent's standing rules come in **three tiers**, and the tier decides how a r
13
13
 
14
14
  ### Invariants — always on
15
15
 
16
- {N_LAWS} rules in `src/laws/universal.md`, numbered in Roman from `I`: sealed secrets, one intent per act, verify before asserting, deliberate deletion, surface failures, data not orders, least privilege, cure the cause, and the external gate. They hold in every task and every repository, they are never traded away, and no install can switch one off. Cited by numeral — `Rule IV`.
16
+ {N_LAWS} rules in `src/laws/universal.md`, numbered in Roman from `I`: sealed secrets, one intent per act, verify before asserting, deliberate deletion, surface failures, data not orders, least privilege, cure the cause, and echo the intent. They hold in every task and every repository, they are never traded away, and no install can switch one off. Cited by name — *Deletion Is Deliberate* — never by numeral: the numeral is only the rule's position, and it moves when a rule before it is removed.
17
17
 
18
18
  ### Doctrines — chosen at build time
19
19
 
@@ -11,8 +11,8 @@ A theme is one JSON file under `themes/` declaring voice tokens only: `BANNER`,
11
11
 
12
12
  Every rule in the constitution gets its title from a theme key, and a theme that omits one ships a rule with a blank heading:
13
13
 
14
- - `LEX_I`…`LEX_IX` — one title per invariant. `doctor` holds this to an **equality**, not mere presence: a `LEX_*` outside `I`–`IX` is a title for a rule that does not exist and fails the check too.
15
- - `DOC_*` — one title per doctrine rule, named after its address (`DOC_CRAFT_1`, `DOC_PROCESS_5`, …). `doctor` reads the pack files under `src/doctrines/` and requires exactly the set they name — a missing one is a blank heading, an extra one is a dead key.
14
+ - `LEX_<ID>` — one title per invariant, keyed by the law's permanent id (`LEX_VERIFY_BEFORE_ASSERTING`), never by its number. `doctor` holds this to an **equality**, not mere presence: a `LEX_*` no law declares is a title for a rule that does not exist and fails the check too.
15
+ - `DOC_<ID>` — one title per doctrine rule, keyed by its id (`DOC_AUTOMATE_REPETITION`, `DOC_CONSENT_BEFORE_PUSH`, …). `doctor` reads the pack files under `src/doctrines/` and requires exactly the set they declare — a missing one is a blank heading, an extra one is a dead key. A title is the rule's heading only: a citation of the rule renders as its English principle name in every voice.
16
16
  - `PACK_*` — one name per pack (`PACK_CRAFT`, `PACK_RIGOR`, `PACK_OPS`, `PACK_PROCESS`, `PACK_COMMS`), used for the pack's own sub-heading.
17
17
 
18
18
  The Ethos section names are **not** theme keys: a citation reads `({{ONTOLOGY}}: {{ONT_TELOS}})`, token on both sides, so heading and reference always move together. They live in the build's fixed structure table and you neither declare nor rename them.
package/docs/web-ui.md CHANGED
@@ -120,7 +120,7 @@ streams the output of background jobs and keeps their history across reloads.
120
120
  - **Docs** (`#/docs`) — rendered documentation: markdown pages, concept pages, a CLI
121
121
  reference (generated from the harness argument parser), and a glossary, grouped into
122
122
  Get started / Core concepts / How-to / MCP servers / Plugins / Reference / Deeper. Filtered
123
- for one host family (OpenCode, or Claude Code — which Bob, Copilot and OpenClaude share); with no
123
+ for one host family (OpenCode, or Claude Code — which Bob and OpenClaude share); with no
124
124
  choice stored it follows the deployed install.
125
125
 
126
126
  ### 🩺 Care
@@ -160,7 +160,7 @@ streams the output of background jobs and keeps their history across reloads.
160
160
  global harness goes dormant (hooks stay silent, the global preamble never loads);
161
161
  add or remove one here, the web mirror of `harness exclude add|remove|list`.
162
162
  - **Settings** (`#/settings`) — a **Console direction** picker (the visual flavour of the
163
- console) with a **Dashboard layout** control (Auto follows each theme's designed Status
163
+ console: Cultivar, Operator, Matrix or Atlas) with a **Dashboard layout** control (Auto follows each theme's designed Status
164
164
  lens; Cultivar / Greenhouse / Operator / Journal force one regardless of skin), the
165
165
  install snapshot (deployed/target/theme/version/memory store), a Maintenance card (PATH
166
166
  link/unlink, uninstall), an offline package download, server controls (Stop), and the
@@ -2,5 +2,5 @@
2
2
  "_comment": "version is a human-readable release label only; the canonical identity of an installed harness is the source fingerprint stamped in .geneseed-version (see `harness version`), not this string.",
3
3
  "theme": "neutral",
4
4
  "product": "Geneseed",
5
- "version": "3.8.0"
5
+ "version": "3.10.0"
6
6
  }
package/js/README.md CHANGED
@@ -37,15 +37,15 @@ as a per-host install at project or global scope.
37
37
 
38
38
  | module | owns |
39
39
  |---|---|
40
- | `source.mjs` | Where the SOURCE is: `ROOT`/`SRC`/`THEMES`/`CONFIG`, `PACK_ORDER`, rule ids, the cfg object |
40
+ | `source.mjs` | Where the SOURCE is: `ROOT`/`SRC`/`THEMES`/`CONFIG`, `PACK_ORDER`, the rule canon (stable ids → positional numbers, citations → names), the cfg object |
41
41
  | `render.mjs` | The pure text pipeline: theme load, `INCLUDE` inlining, CATALOG blocks, `{{TOKENS}}`, dest paths |
42
42
  | `bundle.mjs` | `build` — render a theme into a bundle dir, plus the source-completeness refusal. Sits UNDER both emits |
43
- | `emit-claude.mjs` | The Claude/Bob/Copilot/OpenClaude emit — the render half plus the settings + CLAUDE.md managed-block wire |
43
+ | `emit-claude.mjs` | The Claude/Bob/OpenClaude emit — the render half plus the settings + CLAUDE.md managed-block wire |
44
44
  | `emit-opencode.mjs` | The OpenCode emits — a project's `.opencode/` and the global config dir. Deliberate twin of the above |
45
45
  | `emit-common.mjs` | Constants, tree walkers, and the three writers BOTH global emits share. Decides no host |
46
46
  | `stubs.mjs` | Write-once seed files: context, wiki, rules, excludes, profile, `.gitignore`, memory/notebook indexes |
47
47
  | `version.mjs` | The release marker: fingerprint the sources, read/compare/write an install's version, warn on downgrade |
48
- | `driver.mjs` | The generator driver: `--emit`/`--theme`/`--footprint` flag parsing, the eleven emit targets, per-host emit orchestration, the prune and the manifest. `bin/build-driver.mjs` is only its entry |
48
+ | `driver.mjs` | The generator driver: `--emit`/`--theme`/`--footprint` flag parsing, the nine emit targets, per-host emit orchestration, the prune and the manifest. `bin/build-driver.mjs` is only its entry |
49
49
  | `generate.mjs` | CLI verbs `build`, `prompt`, `theme`, `rebuild-all` — the thin face over `driver.mjs` |
50
50
  | `catalog.mjs` | `geneseed catalog` — prints the shipped roster. Classifies nothing itself |
51
51
  | `themes.mjs` | Maintainer-only `--sync-themes`: inserts `_TEMPLATE.json`'s missing keys into the committed themes |
@@ -66,8 +66,8 @@ user co-owns, and the hook verbs those emitted configs then run.
66
66
 
67
67
  | module | owns |
68
68
  |---|---|
69
- | `hosts.mjs` | The five host config dirs (opencode/claude/bob/copilot/openclaude), plus `resolvePath`/`expanduser` |
70
- | `hooks.mjs` | The verbs the emitted hooks run every session: `context`, `git-gate`, `rule-gate`, `tool-gate` (the two gates fused, for Copilot), `learn`. `--host` picks the verdict dialect |
69
+ | `hosts.mjs` | The four host config dirs (opencode/claude/bob/openclaude), plus `resolvePath`/`expanduser` |
70
+ | `hooks.mjs` | The verbs the emitted hooks run every session: `context`, `git-gate`, `rule-gate`, `tool-gate` (the two gates fused, for Bob), `learn`. `--host` picks the verdict dialect |
71
71
  | `settings.mjs` | Merges into user-owned `settings.json`/`opencode.json`; owns the hook shim and the managed blocks |
72
72
  | `native.mjs` | Capability specs → host-native subagents and skills. The impure half of the emit |
73
73
  | `opencode.mjs` | OpenCode-only extras: colour themes, primary agent, `/commands`, plugins, overrides stub |
@@ -182,8 +182,9 @@ and inline lists are held against a surface list written out in
182
182
 
183
183
  | I want to | open first | then |
184
184
  |---|---|---|
185
- | a doctrine rule | `src/doctrines/<pack>.md` — APPEND, ids run contiguously | `docs/extending.md` §2a — five files, `--sync-themes`, restyle 14 voices by hand. Author BOTH LEAN halves |
186
- | a law (invariant) | `src/laws/universal.md` — **APPEND, never insert** | `docs/extending.md` §2c. Author both LEAN halves: the lean footprint ships nothing else |
185
+ | a doctrine rule | `src/doctrines/<pack>.md` — `### {{DOCTRINE:<id>}} <Principle>`; the number is its position | `docs/extending.md` §2a — five files, `--sync-themes`, restyle 14 voices by hand. Author BOTH LEAN halves |
186
+ | a law (invariant) | `src/laws/universal.md` — `### {{LAW:<id>}} <Principle>`; cite by id, never by number | `docs/extending.md` §2c. Author both LEAN halves: the lean footprint ships nothing else |
187
+ | to remove or retire a rule | `docs/extending.md` §2e | `RETIRED_RULE_IDS` in `js/build/source.mjs` — a retired id is never reused |
187
188
  | a skill or an agent | `src/skills/<name>.md` or `src/agents/<name>.md` | `docs/extending.md` §3 — eight steps. Write the FILE before the table row or the build aborts |
188
189
  | a doctor check | `js/inspect/checks-{build,repo,authoring}.mjs` | register with `ran(...)` in `doctor.mjs`, then a PLANTED FAULT in `tests/unit/harness.test.mjs` |
189
190
  | a web endpoint | GET → `js/web/api.mjs`; POST → `js/web/actions.mjs` | declare it in `js/web/routes.mjs`; the partition test probes the real handler |
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The generator driver — flag parsing, the eleven emit targets, and the per-host emit orchestration.
2
+ * The generator driver — flag parsing, the nine emit targets, and the per-host emit orchestration.
3
3
  * `bin/build-driver.mjs` (`geneseed-build`) is only its entry; this module is what the CLI verbs
4
4
  * (`build`, `setup`, `migrate`, `doctor`, `diff`, `validate`, the web console) import. It lived in
5
5
  * `bin/` until 2026-09, which made nine `js/` modules import upward from a binary.
@@ -51,7 +51,7 @@ import { parseJson, jsonDumpsIndent } from '../lib/json.mjs';
51
51
  // that should exist twice. golden.py's 259 cells are what made the move safe to attempt.
52
52
  import {
53
53
  GLOBAL_MANIFEST, resolvePath, opencodeConfigDir, claudeConfigDir, bobConfigDir,
54
- copilotConfigDir, openclaudeConfigDir, hostCatalogsNatively,
54
+ openclaudeConfigDir, hostCatalogsNatively,
55
55
  } from '../hosts/hosts.mjs';
56
56
 
57
57
  // P5d moved these out of this file for the reason P5c moved the host resolvers: `harness
@@ -71,9 +71,9 @@ import { registryRecord, registryRoots } from '../inspect/registry.mjs';
71
71
  // maintainer pair that needs nothing this driver is banned from having.
72
72
  import { syncThemes } from './themes.mjs';
73
73
 
74
- /** The eleven `--emit` choices: build.py:337-338's nine, then OpenClaude's pair. */
74
+ /** The nine `--emit` choices: a plain bundle, then a project and a global emit per host. */
75
75
  const EMITS = ['files', 'opencode', 'opencode-global', 'claude', 'claude-global',
76
- 'bob', 'bob-global', 'copilot', 'copilot-global', 'openclaude', 'openclaude-global'];
76
+ 'bob', 'bob-global', 'openclaude', 'openclaude-global'];
77
77
 
78
78
  /** `_build_emit.PRIMARY_AGENT_SRC`. */
79
79
  const PRIMARY_AGENT_SRC = path.join(ROOT, 'adapters', 'opencode', 'agents', 'orchestrator.md');
@@ -497,7 +497,7 @@ export function hookRunnerEntry() {
497
497
  * to suppress the GLOBAL preamble of the same host, or null for a host that gets none.
498
498
  *
499
499
  * `_PREAMBLE_CONFIG_DIR` has exactly one key, so only a `CLAUDE.md` carrier resolves to a
500
- * value: Bob's and Copilot's `AGENTS.md`, and Copilot's `copilot-instructions.md`, get null.
500
+ * value: Bob's `AGENTS.md` gets null.
501
501
  *
502
502
  * Computed HERE and not in the render child, and that is the inverted boundary rule doing
503
503
  * real work rather than being restated. P3b's note on the Python original: it resolves
@@ -519,10 +519,8 @@ function preambleExclude(claudeMd, host) {
519
519
  /**
520
520
  * `_build_global._warn_bob_global_over_project` — informational, never auto-removes.
521
521
  *
522
- * Same shape as `warnCopilotGlobalOverProject` and a DIFFERENT message, because the two
523
- * hosts differ in what they can promise: Copilot simply stacks both preambles, while Bob's
524
- * workspace rules may or may not shadow the global copy depending on precedence nothing can
525
- * verify at emit time — so this text hedges where Copilot's asserts.
522
+ * The text hedges on purpose: Bob's workspace rules may or may not shadow the global copy,
523
+ * depending on a precedence nothing can verify at emit time.
526
524
  */
527
525
  function warnBobGlobalOverProject() {
528
526
  const survivors = projectSurvivors('bob');
@@ -646,27 +644,6 @@ function projectSurvivors(emitName) {
646
644
  return out;
647
645
  }
648
646
 
649
- /**
650
- * `_build_global._warn_copilot_global_over_project` — purely informational.
651
- *
652
- * Copilot documents no exclude or shadow mechanism, so a global preamble and a project
653
- * one simply stack. UNREACHABLE from every golden cell: each emits into a fresh sandbox
654
- * whose registry is empty, so `projectSurvivors` is always `[]` and this never prints.
655
- * Reaching it needs a project emit registered BEFORE a global one in the same sandbox.
656
- */
657
- function warnCopilotGlobalOverProject() {
658
- const survivors = projectSurvivors('copilot');
659
- if (!survivors.length) return;
660
- process.stderr.write(
661
- `[geneseed] WARN: ${survivors.length} project Copilot install(s) already exist — `
662
- + 'emitting GLOBAL now means BOTH preambles load together in those repos '
663
- + '(doubled context): Copilot stacks ~/.copilot/copilot-instructions.md on top '
664
- + "of a repo's own AGENTS.md. Review and remove what you don't want:\n");
665
- for (const root of survivors) {
666
- process.stderr.write(` - ${root} -> geneseed uninstall --target "${root}"\n`);
667
- }
668
- }
669
-
670
647
  /**
671
648
  * `_build_emit.emit_opencode` — the driver body, which is what this phase actually ports.
672
649
  *
@@ -776,22 +753,14 @@ function emitOpencodeGlobal(cfg, args, out) {
776
753
  }
777
754
 
778
755
  /**
779
- * `_build_global._emit_claude_core` — the shared engine behind six emits.
780
- *
781
- * Only the two Copilot ones run through it so far, and that is a deliberate split rather
782
- * than an arbitrary stopping point: `js/build/emit-claude.mjs's wire` gates the entire settings/hook path
783
- * behind `if (!isCopilot)`, so a Copilot emit never reaches `hookPrefix` and therefore never
784
- * needs `hookOpts` — the pair of machine-absolute values (`sys.executable` and the harness
785
- * entry point) that a Node driver has no way to produce. Copilot crossing first isolates
786
- * this driver body from that question entirely.
756
+ * `_build_global._emit_claude_core` — the shared engine behind six emits (Claude, Bob and
757
+ * OpenClaude, each per-repo and global).
787
758
  *
788
- * `hookOpts` is OMITTED for a host that does not wire hooks, rather than passed as `{}` or
789
- * `null`. If a future change ever routed a Copilot emit into the hook path, `hookPrefix()`
790
- * would receive `undefined`, hit its own default and throw the error it was built to throw
791
- * — where `null` would raise an unrelated TypeError and `{}` would bake the literal string
792
- * `"undefined"` into the shim and silently kill every hook in the install. Fail loud, on
793
- * purpose. The four hook-writing hosts pass a real pair from `hookRunnerEntry()`, which
794
- * cannot fail to produce one — `process.execPath` is the node already running.
759
+ * Every caller passes a real `hookOpts` pair from `hookRunnerEntry()`, which cannot fail to
760
+ * produce one — `process.execPath` is the node already running. Were it ever omitted,
761
+ * `hookPrefix()` would receive `undefined`, hit its own default and throw the error it was
762
+ * built to throw — where `null` would raise an unrelated TypeError and `{}` would bake the
763
+ * literal string `"undefined"` into the shim and silently kill every hook in the install.
795
764
  */
796
765
  function emitClaudeCore(cfg, args, { cfgDir, claudeMd, scope, host, out, hookOpts }) {
797
766
  const manifestPath = path.join(cfgDir, GLOBAL_MANIFEST);
@@ -799,12 +768,10 @@ function emitClaudeCore(cfg, args, { cfgDir, claudeMd, scope, host, out, hookOpt
799
768
  const oldOwned = (doc && doc.owned) || [];
800
769
  const oldManaged = (doc && doc.managed && typeof doc.managed === 'object'
801
770
  && !Array.isArray(doc.managed)) ? doc.managed : {};
802
- const isCopilot = host === 'copilot';
803
771
 
804
- // RENDER + WIRE in one child's worth of work. `preambleExclude` is null for every host
805
- // but Claude — `_PREAMBLE_CONFIG_DIR` has exactly one key, `CLAUDE.md` — so neither
806
- // Copilot carrier filename (copilot-instructions.md, AGENTS.md) resolves to one, and
807
- // neither does Bob's. Spelling it as a call rather than a literal is what makes that a
772
+ // RENDER + WIRE in one child's worth of work. `preambleExclude` is null for every
773
+ // carrier but `CLAUDE.md` — `_PREAMBLE_CONFIG_DIR` has exactly one key — so Bob's
774
+ // `AGENTS.md` does not resolve to one. Spelling it as a call rather than a literal is what makes that a
808
775
  // measured `null` instead of an assumed one.
809
776
  const rendered = emitClaudeRender(cfg, {
810
777
  theme: args.theme, cfgDir, claudeMd, scope, host,
@@ -832,8 +799,7 @@ function emitClaudeCore(cfg, args, { cfgDir, claudeMd, scope, host, out, hookOpt
832
799
  // VERIFY — re-read the settings file just written and match it against the claims just
833
800
  // recorded, so a merge that silently did not stick (a commented file, a mid-flight
834
801
  // external edit, a bug in the merge) is loud now instead of surfacing as hooks that
835
- // quietly never fire. Copilot's settings have their own shape and their own check; a
836
- // Copilot PROJECT emit records no hooks and so checks nothing.
802
+ // quietly never fire.
837
803
  //
838
804
  // On the Python driver this stage runs in Python AFTER a Node child did the wiring, which
839
805
  // makes it a live cross-implementation check on every build. Here both halves are Node, so
@@ -845,10 +811,8 @@ function emitClaudeCore(cfg, args, { cfgDir, claudeMd, scope, host, out, hookOpt
845
811
  // deleting this call is byte-identical in all 259 cells. `test_verify_reports_an_orphaned
846
812
  // _geneseed_hook` plants the fault that makes it speak.
847
813
  phaseLog('VERIFY');
848
- if (!isCopilot || managed.settings_hooks) {
849
- settingsIntegrityCheck(
850
- path.join(cfgDir, managed.settings_file || 'settings.json'), managed, 'present');
851
- }
814
+ settingsIntegrityCheck(
815
+ path.join(cfgDir, managed.settings_file || 'settings.json'), managed, 'present');
852
816
  return {
853
817
  nAgents: stats.nAgents,
854
818
  nSkills: stats.nSkills,
@@ -858,38 +822,6 @@ function emitClaudeCore(cfg, args, { cfgDir, claudeMd, scope, host, out, hookOpt
858
822
  };
859
823
  }
860
824
 
861
- /** `_build_global.emit_copilot` — per-repo: AGENTS.md at the repo root + a `.github/` layer. */
862
- function emitCopilot(cfg, args, out) {
863
- const root = args.root ? resolveOut(args.root) : out;
864
- const cfgDir = path.join(root, '.github');
865
- const r = emitClaudeCore(cfg, args, {
866
- cfgDir, claudeMd: path.join(root, 'AGENTS.md'), scope: 'project', host: 'copilot', out,
867
- });
868
- process.stdout.write(`[geneseed] copilot (folder) -> ${root}: AGENTS.md + .github/ `
869
- + `(${r.nAgents} agents (.agent.md), ${r.nSkills} skills), ${r.memStatus}, `
870
- + `${r.nbStatus}. No hooks at project scope (Copilot reads hooks from `
871
- + '~/.copilot/settings.json only — the global emit wires them).\n');
872
- return cfgDir;
873
- }
874
-
875
- /** `_build_global.emit_copilot_global` — into Copilot's personal config dir (~/.copilot). */
876
- function emitCopilotGlobal(cfg, args, out) {
877
- const cfgDir = args.cfgDir ?? copilotConfigDir();
878
- warnCopilotGlobalOverProject();
879
- // The hook runner pair, as for Claude and Bob: the global emit is the one Copilot scope
880
- // that wires hooks (`~/.copilot/settings.json`), and the shim it bakes is machine-wide.
881
- const hookOpts = hookRunnerEntry();
882
- const r = emitClaudeCore(cfg, args, {
883
- cfgDir, claudeMd: path.join(cfgDir, 'copilot-instructions.md'),
884
- scope: 'global', host: 'copilot', out, hookOpts,
885
- });
886
- process.stdout.write(`[geneseed] copilot-global -> ${cfgDir}: ${r.nAgents} agents (.agent.md), `
887
- + `${r.nSkills} skills, copilot-instructions.md, ${r.memStatus}, ${r.nbStatus}, `
888
- + `${r.nHooks} hooks (settings.json: sessionStart context, preToolUse gate, agentStop + `
889
- + 'preCompact learn); MCP servers go in mcp-config.json.\n');
890
- return cfgDir;
891
- }
892
-
893
825
  /**
894
826
  * `_build_global.emit_claude_global` — into Claude Code's global config dir (~/.claude).
895
827
  *
@@ -1018,7 +950,7 @@ function writeMarkers(markerDir, emit, footprint) {
1018
950
  mkdirSync(markerDir, { recursive: true });
1019
951
  writeText(path.join(markerDir, '.geneseed-emit'), `${emit}\n`);
1020
952
  // Written for EVERY emit (build.py:443, unconditional), unlike the theme marker:
1021
- // the claude/bob/copilot PROJECT installs never call build(), so this is their only
953
+ // the claude/bob/openclaude PROJECT installs never call build(), so this is their only
1022
954
  // footprint record. Read by harness._footprint_of_dir, which defaults to 'full'.
1023
955
  writeText(path.join(markerDir, '.geneseed-footprint'), `${footprint}\n`);
1024
956
  } catch { /* best-effort, exactly as build.py:444-445 — a marker hiccup never fails a build */ }
@@ -1049,14 +981,13 @@ const GLOBAL_EMITS = {
1049
981
  opencode: emitOpencodeGlobal,
1050
982
  claude: emitClaudeGlobal,
1051
983
  bob: emitBobGlobal,
1052
- copilot: emitCopilotGlobal,
1053
984
  openclaude: emitOpenclaudeGlobal,
1054
985
  };
1055
986
 
1056
987
  /**
1057
988
  * The PER-REPO half of the same idea, and `doctor` is its only caller.
1058
989
  *
1059
- * `_claude_bob_emit_problems` renders `emit_claude`, `emit_bob` and `emit_copilot` into
990
+ * `_claude_bob_emit_problems` renders `emit_claude`, `emit_bob` and `emit_openclaude` into
1060
991
  * throwaway sandboxes and scans each — the three emits that write CLAUDE.md/AGENTS.md
1061
992
  * straight into a repo, and the ones outside doctor's sweep when the skill-table dead links
1062
993
  * shipped.
@@ -1072,7 +1003,7 @@ const GLOBAL_EMITS = {
1072
1003
  * three-positional call leaves in place, inherited here rather than re-decided.
1073
1004
  */
1074
1005
  const PROJECT_EMITS = {
1075
- claude: emitClaude, bob: emitBob, copilot: emitCopilot, openclaude: emitOpenclaude,
1006
+ claude: emitClaude, bob: emitBob, openclaude: emitOpenclaude,
1076
1007
  // P2. `opencode` joins the three for `cmdValidate`, which has to be able to render EVERY
1077
1008
  // `--emit` choice into its sandbox and not only the three doctor already scans. Its call
1078
1009
  // shape is `emitClaude`'s exactly — `(cfg, args, out)` — so the row is the whole change.
@@ -1210,7 +1141,7 @@ function run(argv) {
1210
1141
  markerDir = GLOBAL_EMITS[args.emit.slice(0, -'-global'.length)](cfg, args, out);
1211
1142
  } else if (args.emit !== 'files') {
1212
1143
  // The PROJECT emits keep their markers in `out`, not in the host config dir the emit
1213
- // wrote to (build.py:435-436) — `.github/` is the layer, `out` is the install.
1144
+ // wrote to (build.py:435-436) — `.claude/` is the layer, `out` is the install.
1214
1145
  PROJECT_EMITS[args.emit](cfg, args, out);
1215
1146
  } else {
1216
1147
  // The ninth choice, a plain bundle: `nativeCatalog: false` is build.py:421's
@@ -1223,7 +1154,7 @@ function run(argv) {
1223
1154
  writeMarkers(markerDir, args.emit, args.footprint);
1224
1155
  // build() drops a .geneseed-theme in `out` for the emits that call it; the global emits
1225
1156
  // render into the config dir WITHOUT calling build(), so the theme is recorded here.
1226
- // Deliberately not written for the claude/bob/copilot PROJECT emits — they carry none,
1157
+ // Deliberately not written for the claude/bob/openclaude PROJECT emits — they carry none,
1227
1158
  // and `_harness_setup._installed_defaults` detects those by an AGENT.md sigil scan
1228
1159
  // instead. Writing one for them would change the emitted tree.
1229
1160
  if (args.emit.endsWith('-global')) {
@@ -1234,7 +1165,7 @@ function run(argv) {
1234
1165
  // An ALLOW-LIST, not "everything that is not global": a plain `--emit files` dev build —
1235
1166
  // the default — must never pollute the registry, and only the four per-repo host emits
1236
1167
  // are ones `_EMIT_HOST_SCOPE` can map back to a row. Records `out`, where the marker is.
1237
- if (['opencode', 'claude', 'bob', 'copilot', 'openclaude'].includes(args.emit)) {
1168
+ if (['opencode', 'claude', 'bob', 'openclaude'].includes(args.emit)) {
1238
1169
  registryRecord(markerDir);
1239
1170
  }
1240
1171
  return 0;