geneseed 2.1.0 → 3.0.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 (187) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/DESIGN.md +112 -61
  3. package/QUICKSTART.md +1 -1
  4. package/README.md +24 -14
  5. package/SETUP.md +83 -17
  6. package/SHIPPED.md +5 -4
  7. package/adapters/bob/README.md +3 -3
  8. package/adapters/claude-code/README.md +6 -4
  9. package/adapters/claude-code/skills/geneseed/SKILL.md +10 -6
  10. package/adapters/copilot/README.md +5 -4
  11. package/adapters/opencode/GLOBAL-HARNESS-SPEC.md +11 -6
  12. package/adapters/opencode/HOW-OPENCODE-LOADS.md +1 -1
  13. package/adapters/opencode/README.md +15 -9
  14. package/adapters/opencode/agents/orchestrator.md +1 -1
  15. package/adapters/opencode/plugins/geneseed-context.js +7 -7
  16. package/adapters/opencode/plugins/geneseed-guard.js +6 -6
  17. package/adapters/opencode/workflows/dispatch.js +1 -1
  18. package/bin/geneseed.mjs +72 -6
  19. package/docs/extending.md +164 -55
  20. package/docs/limits.md +4 -4
  21. package/docs/token-footprint.md +15 -4
  22. package/docs/web/authoring.md +1 -1
  23. package/docs/web/claude-hooks.md +2 -2
  24. package/docs/web/collaboration.md +3 -3
  25. package/docs/web/first-session.md +2 -2
  26. package/docs/web/footprint.md +14 -7
  27. package/docs/web/foreman-mode.md +2 -2
  28. package/docs/web/harnesses.md +5 -3
  29. package/docs/web/install-quick.md +1 -1
  30. package/docs/web/model.md +3 -3
  31. package/docs/web/plugin-context.md +2 -2
  32. package/docs/web/plugin-guard.md +3 -3
  33. package/docs/web/plugin-ponytail.md +1 -1
  34. package/docs/web/rules.md +23 -3
  35. package/docs/web/setup-choices.md +20 -7
  36. package/docs/web/themes-author.md +13 -1
  37. package/docs/web-ui.md +36 -12
  38. package/harness.config.json +1 -1
  39. package/js/catalog.mjs +29 -4
  40. package/js/checkout.mjs +24 -1
  41. package/js/cli-table.json +8 -6
  42. package/js/diff.mjs +8 -3
  43. package/js/doctor.mjs +307 -4
  44. package/js/emit.mjs +48 -11
  45. package/js/generate.mjs +39 -5
  46. package/js/hooks.mjs +8 -7
  47. package/js/installs.mjs +101 -4
  48. package/js/inventory.mjs +150 -21
  49. package/js/migrate.mjs +10 -4
  50. package/js/render.mjs +110 -7
  51. package/js/settings.mjs +218 -27
  52. package/js/setup.mjs +95 -5
  53. package/js/status.mjs +45 -4
  54. package/js/tui.mjs +44 -1
  55. package/js/uninstall.mjs +25 -6
  56. package/js/web/actions.mjs +56 -5
  57. package/js/web/api.mjs +95 -16
  58. package/js/web/docs.mjs +33 -5
  59. package/js/web/jobs.mjs +12 -3
  60. package/js/web/server.mjs +6 -0
  61. package/package.json +1 -1
  62. package/src/AGENT.md.tmpl +75 -65
  63. package/src/agents/_template.md +4 -4
  64. package/src/agents/advocate.md +4 -4
  65. package/src/agents/architect.md +2 -2
  66. package/src/agents/developer.md +5 -5
  67. package/src/agents/docs.md +2 -2
  68. package/src/agents/empiricist.md +3 -3
  69. package/src/agents/explorer.md +3 -3
  70. package/src/agents/framer.md +3 -3
  71. package/src/agents/historian.md +3 -3
  72. package/src/agents/operator.md +3 -3
  73. package/src/agents/pragmatist.md +3 -3
  74. package/src/agents/reviewer.md +2 -2
  75. package/src/agents/security.md +2 -2
  76. package/src/agents/skeptic.md +4 -4
  77. package/src/agents/steward.md +3 -3
  78. package/src/agents/tester.md +2 -2
  79. package/src/agents/user-advocate.md +3 -3
  80. package/src/agents/visionary.md +3 -3
  81. package/src/doctrines/README.md +41 -0
  82. package/src/doctrines/craft.md +51 -0
  83. package/src/doctrines/ops.md +61 -0
  84. package/src/doctrines/process.md +87 -0
  85. package/src/doctrines/rigor.md +52 -0
  86. package/src/laws/universal.md +17 -336
  87. package/src/memory/README.md +2 -2
  88. package/src/modes/README.md +2 -2
  89. package/src/modes/foreman.md +1 -1
  90. package/src/notebook/README.md +2 -2
  91. package/src/ontology/universal.md +89 -0
  92. package/src/postures/README.md +3 -3
  93. package/src/postures/artisan.md +3 -3
  94. package/src/postures/assistant.md +1 -1
  95. package/src/postures/expert.md +1 -1
  96. package/src/postures/mentor.md +1 -1
  97. package/src/postures/peer.md +2 -2
  98. package/src/skills/_template.md +2 -2
  99. package/src/skills/brainstorm.md +2 -2
  100. package/src/skills/clarify.md +2 -2
  101. package/src/skills/codebase-design.md +1 -1
  102. package/src/skills/commit.md +5 -5
  103. package/src/skills/council.md +4 -4
  104. package/src/skills/crash-course.md +1 -1
  105. package/src/skills/daydream/SKILL.md +1 -1
  106. package/src/skills/debug.md +2 -2
  107. package/src/skills/decode.md +1 -1
  108. package/src/skills/develop.md +6 -6
  109. package/src/skills/document-project.md +4 -4
  110. package/src/skills/domain-modeling.md +1 -1
  111. package/src/skills/drill.md +1 -1
  112. package/src/skills/feynman.md +1 -1
  113. package/src/skills/forge-mcp.md +3 -3
  114. package/src/skills/fresh-eyes.md +4 -4
  115. package/src/skills/frontend-design.md +1 -1
  116. package/src/skills/gap-detector.md +1 -1
  117. package/src/skills/geneseed-code-review.md +1 -1
  118. package/src/skills/geneseed.md +4 -4
  119. package/src/skills/git-archaeology.md +1 -1
  120. package/src/skills/git-rescue.md +3 -3
  121. package/src/skills/handoff.md +4 -4
  122. package/src/skills/herdr.md +1 -1
  123. package/src/skills/ingest.md +3 -3
  124. package/src/skills/learning-path.md +1 -1
  125. package/src/skills/migrate.md +5 -5
  126. package/src/skills/opencode-theme.md +1 -1
  127. package/src/skills/parallel-agents.md +2 -2
  128. package/src/skills/pipeline.md +2 -2
  129. package/src/skills/plan.md +2 -2
  130. package/src/skills/ponytail.md +1 -1
  131. package/src/skills/profile.md +1 -1
  132. package/src/skills/prose.md +2 -2
  133. package/src/skills/prototype.md +2 -2
  134. package/src/skills/refactor.md +2 -2
  135. package/src/skills/release.md +4 -4
  136. package/src/skills/repo-map.md +5 -5
  137. package/src/skills/research.md +6 -6
  138. package/src/skills/review-response.md +3 -3
  139. package/src/skills/roast-me.md +1 -1
  140. package/src/skills/rule.md +5 -5
  141. package/src/skills/ship.md +3 -3
  142. package/src/skills/tdd.md +2 -2
  143. package/src/skills/tickets.md +1 -1
  144. package/src/skills/wayfinder.md +1 -1
  145. package/src/skills/wiki.md +4 -4
  146. package/src/skills/workflow.md +2 -2
  147. package/themes/README.md +17 -7
  148. package/themes/_TEMPLATE.json +37 -36
  149. package/themes/biker.json +37 -36
  150. package/themes/commentator.json +37 -36
  151. package/themes/cyberpunk.json +37 -36
  152. package/themes/gamer.json +37 -36
  153. package/themes/imperial.json +37 -36
  154. package/themes/joker.json +37 -36
  155. package/themes/marvin.json +37 -36
  156. package/themes/mean.json +37 -36
  157. package/themes/military.json +37 -36
  158. package/themes/neutral.json +37 -36
  159. package/themes/pirate.json +37 -36
  160. package/themes/sports.json +37 -36
  161. package/themes/verstappen.json +37 -36
  162. package/themes/wizard.json +37 -36
  163. package/web/dist/assets/{About-BYXlmbyo.js → About-C0Mk0igT.js} +1 -1
  164. package/web/dist/assets/{Activity-us5MPf4u.js → Activity-C4aJJVXz.js} +1 -1
  165. package/web/dist/assets/{ActivityDetail-CiaQXUk2.js → ActivityDetail-DaQ85za0.js} +1 -1
  166. package/web/dist/assets/{Diff-Bh0qbZ2s.js → Diff-B3tlO2Yj.js} +1 -1
  167. package/web/dist/assets/{Doctor-BIlQME45.js → Doctor-BNC-5Dmo.js} +1 -1
  168. package/web/dist/assets/{Graph-4dYD1dPG.js → Graph-us0T6ZcV.js} +1 -1
  169. package/web/dist/assets/{Harnesses-PzYZ3LOC.js → Harnesses-DAMgyfM_.js} +1 -1
  170. package/web/dist/assets/Laws-rOxegJ75.js +1 -0
  171. package/web/dist/assets/{Library-CjMbksJW.js → Library-KmwrHA1J.js} +1 -1
  172. package/web/dist/assets/{Markdown-Bk81c3aZ.js → Markdown-0eQOVGSF.js} +1 -1
  173. package/web/dist/assets/{Profile-Curui_-j.js → Profile-ZU7WV6Xl.js} +1 -1
  174. package/web/dist/assets/{Rules-Bm283wdv.js → Rules-CtDoPhhf.js} +1 -1
  175. package/web/dist/assets/{Skills-gruqYuhl.js → Skills-BhoOxdkD.js} +1 -1
  176. package/web/dist/assets/{StatusBadge-EiM_FPqv.js → StatusBadge-CGvYVCwa.js} +1 -1
  177. package/web/dist/assets/{Themes-DU99j4Hr.js → Themes-Dr7OOkD7.js} +1 -1
  178. package/web/dist/assets/{activity-0rvQ6Vra.js → activity-B8aq3qtl.js} +1 -1
  179. package/web/dist/assets/index-2wqPDxuN.css +1 -0
  180. package/web/dist/assets/{index-0b2hobOo.js → index-AhMzkdbI.js} +1 -1
  181. package/web/dist/assets/index-CRftEtBX.js +12 -0
  182. package/web/dist/assets/{index-IiGFmCW_.js → index-D0lPN_qW.js} +1 -1
  183. package/web/dist/index.html +2 -2
  184. package/web/src/pages/Laws.jsx +282 -91
  185. package/web/dist/assets/Laws-DtZweXal.js +0 -1
  186. package/web/dist/assets/index-D5VY3TY_.js +0 -12
  187. package/web/dist/assets/index-DUCsDv7z.css +0 -1
package/docs/extending.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # Extending — what it costs to change this tool
2
2
 
3
3
  `docs/limits.md` is the standing answer to *"what does this tool not prove about itself?"*.
4
- This file is its companion: **"what does it cost to add one thing?"** — one law, one skill, one
5
- plugin, one hook verb, one doc page, one theme, one screen.
4
+ This file is its companion: **"what does it cost to add one thing?"** — one invariant, one
5
+ doctrine rule, one skill, one plugin, one hook verb, one doc page, one theme, one screen.
6
6
 
7
7
  It exists because the answer is never one file. Every user-visible noun in Geneseed has
8
8
  *satellites* — a themed title in fourteen voices, a class in a hand-written map, a count in a
@@ -10,6 +10,11 @@ badge, a row in a ledger, a page in the console — and the gates that keep them
10
10
  across `doctor`, the Node suite and four CI jobs. A contributor who knows the satellites ships in
11
11
  one pass; one who does not discovers them one red gate at a time.
12
12
 
13
+ The governance surface is three tiers and they cost very different amounts. **Adding a doctrine
14
+ rule is the cheap, common case** (§2a); **amending an invariant** is next (§2b); **adding an
15
+ invariant** is the most expensive single edit in the repo after the CLI surface (§2c); **adding a
16
+ whole pack** is rare and mechanical (§2d).
17
+
13
18
  Written after the Python migration completed (2026-08-18), against `main`. Verified: every
14
19
  file:line below was opened, and the commands were run.
15
20
 
@@ -35,11 +40,22 @@ Two rules follow from the table and they cause most of the surprises:
35
40
 
36
41
  ### Counts are computed — never type one
37
42
 
38
- `{N_LAWS}` `{N_AGENTS}` `{N_SKILLS}` `{N_PLUGINS}` are substituted at request time from the live
39
- inventory (`js/web/docs.mjs:169-172`). Typing a literal number into a `docs/web` page is caught by
40
- `proseMirrorProblems` (`js/doctor.mjs:715-737`). The README badges and prose, and the
41
- `N laws, N agents, N skills` line in `SHIPPED.md`, are the hand-written exceptions — and each has
42
- its own doctor arm (`js/doctor.mjs:676`, `:739`, `:822-829`).
43
+ Eight tokens are substituted at request time from the live inventory, by `docCounts` in
44
+ `js/web/docs.mjs`: `{N_LAWS}` `{N_AGENTS}` `{N_SKILLS}` `{N_PLUGINS}`, plus the four the
45
+ three-tier split added — `{N_ONTOLOGY}` (the ontology's sections), `{N_PACKS}` (packs that exist),
46
+ `{N_PACKS_ACTIVE}` (packs this install built in) and `{N_DOCTRINE_RULES}` (rules inside the active
47
+ packs). `{N_LAWS}` is the **invariant** count and nothing else; there is deliberately no token
48
+ meaning "the whole constitution", because `proseMirrorProblems` holds README and `SHIPPED.md`
49
+ prose to that same number and a token that quietly meant something wider would put the docs and
50
+ the gate at odds with no way to re-bless either.
51
+
52
+ ⚠ **Only a `kind: "concept"` page is substituted.** A `markdown`-kind page renders `{N_PACKS}`
53
+ literally, on the screen, as those nine characters.
54
+
55
+ Typing a literal number into a `docs/web` page is caught by `proseMirrorProblems`. The README
56
+ badges and prose, and the `N laws, N agents, N skills` line in `SHIPPED.md`, are the hand-written
57
+ exceptions — and each has its own arm in `js/doctor.mjs` (`countTableProblems` walks the five
58
+ badge keys `agents`/`skills`/`laws`/`themes`/`plugins`; `proseMirrorProblems` holds the prose).
43
59
 
44
60
  ---
45
61
 
@@ -128,18 +144,38 @@ Notes that matter:
128
144
 
129
145
  ---
130
146
 
131
- ## 2 — Adding a LAW
147
+ ## 2 — Changing the constitution
132
148
 
133
- Ten files, of which five are pure satellites. Ground truth: `git show --stat 1b53701` (law XXXVIII)
134
- touched 21 files, 14 of them themes.
149
+ Three tiers, four different costs. The addresses are `{{LAW}} <roman>` for an invariant and
150
+ `{{DOCTRINE}} <pack> <n>` for a doctrine rule; the ontology is cited by section name and adding a
151
+ section to it is not a checklist, it is a design change.
135
152
 
136
- 1. `src/laws/universal.md` — **append** `### {{LAW}} <roman> — {{LEX_<roman>}}` plus the body.
137
- Never insert: 397 `{{LAW}} <numeral>` cross-references live in `src/`, plus hardcoded citations
138
- in `js/hooks.mjs` and two OpenCode plugins, and **nothing resolves a cross-reference against the
139
- canon**. Renumbering silently rewires every one of them.
140
- 2. `themes/_TEMPLATE.json` — add `LEX_<roman>` in template order. **Nothing gates this file**
141
- (`themeFiles()` filters `_`-prefixed names, `js/installs.mjs:113`), so forgetting it is green
142
- today and starves the *next* law's sync.
153
+ To count the cross-references either tier already carries, from the repo root:
154
+
155
+ ```bash
156
+ grep -rhoE "\{\{LAW\}\} [IVXL]+" src/ | wc -l
157
+ grep -rhoE "\{\{DOCTRINE\}\} [a-z]+ [0-9]+" src/ | wc -l
158
+ ```
159
+
160
+ On this checkout that reports 153 and 209. Both numbers move on every wave of editing, which is
161
+ why the commands are here and the answers are not load-bearing.
162
+
163
+ ### 2a — Adding a DOCTRINE RULE (the common case)
164
+
165
+ Five files, none of them a count. This is the slot most new material belongs in, and it is cheap
166
+ on purpose so that the invariant slot stays scarce.
167
+
168
+ 1. `src/doctrines/<pack>.md` — **append** `### {{DOCTRINE}} <pack> <n> — {{DOC_<PACK>_<n>}}` plus
169
+ the body. Two gates in `constitutionProblems` (`js/doctor.mjs`) sit on this: the pack named in
170
+ the *heading* is what addresses the rule (not the filename, so a rule filed in the wrong file is
171
+ reported rather than silently renamed), and ids must run **contiguously from 1**, so appending
172
+ at the end is the only place `n` is free. Packs are numbered independently — nothing outside
173
+ this file renumbers.
174
+ 2. `themes/_TEMPLATE.json` — add `DOC_<PACK>_<n>`. ⚠ **This file *is* gated for this key family.**
175
+ `themeFiles()` filters `_`-prefixed names and theme parity never sees the template, but
176
+ `constitutionProblems` reads it alongside the fourteen voices for `DOC_*` and `LEX_*`
177
+ specifically — because it is what `--sync-themes` seeds the *next* voice from. Every other key
178
+ family in that file is still ungated.
143
179
  3. Seed the fourteen themes:
144
180
 
145
181
  ```bash
@@ -147,37 +183,110 @@ touched 21 files, 14 of them themes.
147
183
  ```
148
184
 
149
185
  ⚠ Four spellings of this command are in circulation and two of them fail — `doctor`'s own tip
150
- is one of the two. See §7.2 before you copy a command from anywhere else.
151
- 4. Restyle all fourteen by hand. `--sync-themes` writes the template's `<themed title for …>`
152
- placeholder and only *prints* `RESTYLE these`; a shipped placeholder passes every gate.
153
- 5. `js/inventory.mjs:40` — `LAW_CLASS`, one of the six in `LAW_CLASSES` (`:56`).
154
- 6. `web/src/pages/Laws.jsx:28` — `LAW_META`: same class, plus the one-line Principle. **This copy
155
- exists nowhere else**; a law absent here renders with a blank description. It is why that one
156
- React file ships alone out of `web/src` in `package.json` — `doctor` regex-parses its literal.
157
- 7. `README.md` — badge `badge/laws-N` and the `N universal laws` sentence.
158
- 8. `SHIPPED.md` — the `N laws, N agents, N skills` triple.
159
- 9. `tests/unit/harness.test.mjs:293` — the negative fixture hardcodes the *next* free numeral;
160
- bump it or it stops being a fixture and starts being a duplicate.
161
- 10. `CHANGELOG.md`, then rebuild and commit `web/dist` (step 6 touched `web/src`).
162
-
163
- **Amending** a law is steps 1, 10 and — if the principle moved — 6. Two extra cautions:
186
+ is one of the two. See §7.2 before you copy a command from anywhere else. Then restyle all
187
+ fourteen by hand: `--sync-themes` writes the template's placeholder and only *prints*
188
+ `RESTYLE these`; a shipped placeholder passes every gate.
189
+ 4. `web/src/pages/Laws.jsx` — a `DOCTRINE_META` row keyed `'<pack>.<n>'`. Its first field is the
190
+ **pack**, not one of `LAW_CLASSES`' six; `doctrineMetaProblems` requires an *equality* between
191
+ that field and the key's own pack, which catches the copy error a six-way vocabulary cannot — a
192
+ row pasted from the pack above it, keeping the wrong pack. Its second field is the one-line
193
+ Principle, and **that copy exists nowhere else**; a rule absent here renders with a blank
194
+ description.
195
+ 5. `CHANGELOG.md`, then rebuild and commit `web/dist` (step 4 touched `web/src`).
196
+
197
+ **What a doctrine rule does *not* cost**, and each of these is a deliberate asymmetry:
198
+
199
+ - **No class entry.** There is no `LAW_CLASS` analogue: a doctrine rule's class *is* its pack, and
200
+ there is no second taxonomy over it.
201
+ - **No count, anywhere.** No badge, no `SHIPPED.md` triple, no prose mirror. The console spends
202
+ `{N_PACKS}` / `{N_PACKS_ACTIVE}` / `{N_DOCTRINE_RULES}`, all computed at request time.
203
+ - **No test fixture to bump**, and no renumber risk.
204
+
205
+ ⚠ **Cite only downward.** An always-on tier may never reference a toggleable one:
206
+ `constitutionProblems` refuses a `{{DOCTRINE}}` token anywhere under `src/ontology/` or
207
+ `src/laws/`, because a `--doctrines craft` build would then ship an invariant pointing at text its
208
+ `AGENT.md` does not contain. Doctrine→doctrine citations are fine and stay — every pack file ships
209
+ on disk whether or not it was built in. If the build's own default is narrowed,
210
+ `constitutionProblems` emits a `[note]` naming every citation that points at a shelved pack; notes
211
+ are printed and **not** counted, because a narrowed build is a configuration its owner chose, not
212
+ a defect.
213
+
214
+ ### 2b — Amending an INVARIANT
215
+
216
+ Steps 1 and 9 of §2c, plus `LAW_META` if the Principle line moved. Two cautions:
164
217
 
165
218
  - `--footprint` defaults to **lean**, and lean keeps only the heading plus the first sentence
166
- (`js/render.mjs:167`). A clause added to the second paragraph is invisible in the default build.
167
- Amend the first sentence, or the amendment does not exist for most installs.
168
- - ⚠ **Law I is frozen.** `LEX_I` is one of seven theme keys recorded byte-for-byte in the
169
- primitives corpus (§5). Retitling Law I in any theme reddens a snapshot that cannot be re-blessed.
219
+ (`terseBlocks` in `js/render.mjs`). A clause added to the second paragraph is invisible in the
220
+ default build. Amend the first sentence, or the amendment does not exist for most installs. The
221
+ same is true of a doctrine rule; it is **not** true of the ontology, which ships whole at both
222
+ footprints.
223
+ - ⚠ **Rule I is frozen.** `LEX_I` is one of seven theme keys recorded byte-for-byte in the
224
+ primitives corpus (§5.2). Retitling Rule I in any theme reddens a snapshot that cannot be
225
+ re-blessed.
226
+
227
+ ### 2c — Adding an INVARIANT
228
+
229
+ Nine steps, and only the first is the rule itself. This is the expensive one, and it should be:
230
+ the bar is in `DESIGN.md` Decision 7, and most candidates belong in a doctrine pack instead.
170
231
 
171
- The carrier itself is gated: `tests/unit/emit_smoke.test.mjs:211-265` checks every law reaches
172
- every one of nine emit modes in order and themed, under both footprints, with a ceiling **and** a
173
- floor on the rendered size. Headroom measured today: ~2 100 chars full, ~1 200 lean — about three
174
- average laws at full footprint, which is the binding one.
232
+ 1. `src/laws/universal.md` — **append** `### {{LAW}} <roman> — {{LEX_<roman>}}` plus the body.
233
+ Never insert: the `{{LAW}}` cross-references counted above live all over `src/`, plus hardcoded
234
+ citations in `js/hooks.mjs` and two OpenCode plugins, and **nothing resolves a cross-reference
235
+ against the canon**. Renumbering silently rewires every one of them.
236
+ 2. `themes/_TEMPLATE.json` — add `LEX_<roman>` in template order. Gated, as in §2a step 2:
237
+ `constitutionProblems` holds `LEX_I..LEX_IX` as an **equality** across all fifteen files (the
238
+ fourteen voices and the template), so both a missing key *and* a leftover one are reported. That
239
+ arm exists because the renumber left `LEX_XXII`, `LEX_XXIII`, `LEX_XXIV` and `LEX_XXXVI` behind
240
+ in every file and parity was silent — they were absent from nowhere.
241
+ 3. `--sync-themes`, then restyle all fourteen by hand (§2a step 3).
242
+ 4. `LAW_CLASS` in `js/inventory.mjs` — one of the six in `LAW_CLASSES` beside it.
243
+ 5. `LAW_META` in `web/src/pages/Laws.jsx` — same class, plus the one-line Principle. Note the map
244
+ is keyed by **arabic** number where `universal.md` heads with a Roman numeral. **This copy
245
+ exists nowhere else**; a rule absent here renders with a blank description. It is why that one
246
+ React file ships alone out of `web/src` in `package.json` — `doctor` regex-parses its literal.
247
+ 6. `README.md` — badge `badge/laws-N` and the `N universal laws` sentence.
248
+ 7. `SHIPPED.md` — the `N laws, N agents, N skills` triple.
249
+ 8. `tests/unit/harness.test.mjs` — the negative fixture for the `LAW_CLASS` gate plants a rule at
250
+ the *first free numeral*, which is `X` now that the invariants are I..IX. Bump it, or it stops
251
+ being a fixture and starts being a duplicate.
252
+ 9. `CHANGELOG.md`, then rebuild and commit `web/dist` (step 5 touched `web/src`).
253
+
254
+ ⚠ While restyling, `{{LAW}}` must stay a **single word** in every theme (and so must
255
+ `{{DOCTRINE}}`). Both heading parsers match the tier noun with `\S+`, so a two-word value does not
256
+ error — the heading simply stops matching and the whole tier parses to nothing, in silence.
257
+ `constitutionProblems` refuses one, which is the only reason it is visible at all.
258
+
259
+ The carrier itself is gated: `tests/unit/emit_smoke.test.mjs` checks every rule reaches every one
260
+ of nine emit modes in order and themed, under both footprints, with a `CEILING` **and** a floor
261
+ (half the ceiling) on the rendered size. Its docblock carries the current measurement: headroom is
262
+ 1,522 characters (2.8%) at full and 1,794 (4.8%) at lean, against the largest carrier — the
263
+ host-agnostic `files` bundle. Read that docblock before adding text to any tier; it is
264
+ re-measured, never nudged, and the ceiling is measured **with all four packs active**, which is
265
+ the only configuration it can speak for.
266
+
267
+ ### 2d — Adding a whole PACK
268
+
269
+ Rare, and mechanical. On top of §2a for each rule the pack carries:
270
+
271
+ 1. `src/doctrines/<pack>.md`, opening with its lead line — `**{{PACK_<NAME>}}** — how … .` A pack
272
+ file `PACK_ORDER` names but cannot read, or one carrying no `### {{DOCTRINE}} <pack> <n>`
273
+ heading at all, is a refusal.
274
+ 2. `PACK_ORDER` in `js/checkout.mjs` — the registration, and the render order. It is **narrative,
275
+ not alphabetical** (craft → rigor → ops → process); discovery sorts alphabetically and the
276
+ renderer refuses a `.md` under `src/doctrines/` that `PACK_ORDER` does not name, rather than
277
+ skipping it.
278
+ 3. `PACK_<NAME>` in `themes/_TEMPLATE.json` and all fourteen voices. Unlike `DOC_*`, this family is
279
+ held only by `themeParityProblems` — presence, across the voices, template excluded.
280
+ 4. `DOCTRINE_BLURBS` in `js/setup.mjs` — the one-line description an installer sees in the wizard,
281
+ and the only place a pack is ever explained to them. Missing entries fall back to the bare name.
282
+ 5. `harness.config.json` if the pack should be on by default; `constitutionProblems` refuses a
283
+ `doctrines` array naming a pack this checkout does not ship.
175
284
 
176
285
  ---
177
286
 
178
287
  ## 3 — Adding a SKILL or an AGENT
179
288
 
180
- **Order matters at the first two steps.** `missingReferencedSpecs` (`js/emit.mjs:493`) *aborts the
289
+ **Order matters at the first two steps.** `missingReferencedSpecs` (in `js/emit.mjs`) *aborts the
181
290
  build* when `AGENT.md.tmpl` names a spec with no file — so the file comes before the table row, or
182
291
  nothing builds at all. The refusal is clean: `tests/unit/emit_gates.test.mjs:265` proves a refused
183
292
  emit leaves the prior install intact.
@@ -185,14 +294,14 @@ emit leaves the prior install intact.
185
294
  1. `src/skills/<name>.md` or `src/agents/<name>.md`. The shape is load-bearing: `# {{SKILL}}: <name>`,
186
295
  a blank line, then a `>` blockquote holding `{{DESC_<NAME>}}` — title, blockquote, nothing
187
296
  between. `doctor` checks both the presence of the purpose line and that the blockquote is the
188
- *first* block (`js/doctor.mjs:899-908`).
297
+ *first* block (`authoringProblems`, via `firstBlockquote` and `descBlockProblem`).
189
298
  2. One row in the hand-authored table in `src/AGENT.md.tmpl` (agents `125-141`, skills `183-229`).
190
299
  Gated both ways: a row with no file, and a file with no row.
191
300
  3. `DESC_<NAME>` in **all fourteen** themes. Theme parity catches a missing one; nothing catches
192
301
  an unstyled placeholder.
193
- 4. **Skills only** — `SKILL_CLASS` in `js/inventory.mjs:59`. Gated both ways
194
- (`js/doctor.mjs:785-791`), which matters because the runtime fallback is silent: an unclassified
195
- skill renders as `build` (`js/inventory.mjs:166`).
302
+ 4. **Skills only** — `SKILL_CLASS` in `js/inventory.mjs`. Gated both ways, inside
303
+ `countTableProblems`, which matters because the runtime fallback is silent: an unclassified
304
+ skill renders as `build`.
196
305
  5. `registry.json` — a row keyed `skills/<name>` or `agents/<name>` with `status` ∈
197
306
  {`experimental`, `approved`, `deprecated`}, a semver `version`, a non-blank `owner`, an ISO
198
307
  `added`, and `last_verified: ""`. **This is the most forgettable step**: four hand-typed fields,
@@ -231,7 +340,7 @@ The `geneseed-` prefix and the `.js` suffix are mechanically load-bearing: the b
231
340
 
232
341
  1. `adapters/opencode/plugins/geneseed-<name>.js` — ESM, zero dependencies. The factory-export
233
342
  convention is real (OpenCode requires it) but **ungated**; the only generic gate on plugin
234
- source is `node --check` (`js/doctor.mjs:924-941`).
343
+ source is `node --check` (the one spawn in `authoringProblems`).
235
344
  2. `docs/web/plugin-<name>.md` — `group: plugins`, `title: "geneseed-<name>"`, `kind: "concept"`.
236
345
  3. `docs/web/plugins.md` — a bullet. The count above it renders from `{N_PLUGINS}`.
237
346
  4. `docs/web/model.md` — a second `{N_PLUGINS}` sentence whose **enumeration of the capabilities
@@ -396,8 +505,9 @@ only, at best, on its presence.
396
505
 
397
506
  | What | Where | Gated on |
398
507
  |---|---|---|
508
+ | `§N` cross-references into `AGENT.md`'s anatomy | `src/skills/*`, `src/agents/*`, `adapters/**` | **range only.** `constitutionProblems` refuses a `§N` the template declares no section for — which catches a pointer past the end, the shape *removing* a section leaves. It cannot catch one that still resolves and now means something else, which is the shape *inserting* a section leaves, and is what actually happened when `## 2. Doctrines` pushed every later section down one. **Renumbering the anatomy means `grep -rn '§' src/ adapters/` and reading every hit.** Four satellites and a live OpenCode deny message shipped stale because the sweep stopped at `AGENT.md.tmpl` |
399
509
  | Per-law Principle lines | `web/src/pages/Laws.jsx` | presence and class only, never accuracy |
400
- | 560 themed law titles (40 × 14) | `themes/*.json` | key presence only — a shipped placeholder is green |
510
+ | 504 themed constitution titles (36 keys × 14 voices) — `LEX_I..LEX_IX` (9), `DOC_<PACK>_<n>` (23), `PACK_<NAME>` (4) | `themes/*.json` | key presence only — a shipped placeholder is green. `LEX_*` and `DOC_*` are held across the template too, and in both directions; `PACK_*` only across the voices |
401
511
  | The README keyword enumerations | `README.md`, `docs/web/rules.md` | nothing |
402
512
  | The plugin capability enumeration | `docs/web/model.md` | nothing (the number substitutes; the list does not) |
403
513
  | Section labels and page subtitles | `web/src/lib/sections.js`, `web/src/pages/Docs/index.jsx` | nothing |
@@ -540,20 +650,19 @@ to kill every pid on the port, then `geneseed web start`.
540
650
  Ordered by what unblocks the most work per unit of effort. Each is small; none is urgent enough to
541
651
  stop a change today, and all of them cost a contributor a wrong turn until they are done.
542
652
 
543
- 1. **Rewrite the authoring section of `DESIGN.md` (§7.1) and fix `doctor`'s tip (§7.2).** These are
544
- the two documents a contributor reads *first* when adding a law, and both name programs that no
545
- longer exist. Half an hour, and it removes the most likely first wrong turn.
546
- 2. **Extend the fenced-command gate to `DESIGN.md` and `docs/**/*.md` (§7.3).** One array literal.
547
- It would have caught item 1 the day it was written, and it keeps catching it.
548
- 3. **Decide the hook-verb question (§5.1) before it is asked under pressure.** Either mirror the
653
+ 1. **Extend the fenced-command gate to `DESIGN.md` and `docs/**/*.md` (§7.3).** One array literal.
654
+ Today it covers four documents, and both of the pointer-to-nothing defects §7 records — the
655
+ `DESIGN.md` authoring section and `doctor`'s theme-parity tip, since fixed — sat outside its
656
+ reach. It keeps catching them.
657
+ 2. **Decide the hook-verb question (§5.1) before it is asked under pressure.** Either mirror the
549
658
  CLI side's exemption list onto the hook half, or write down that the hook verb set is closed.
550
659
  Either answer is fine; discovering the question mid-feature is not.
551
- 4. **Write down the frozen-key list (§5.2) where a theme author will see it** — `themes/README.md`
660
+ 3. **Write down the frozen-key list (§5.2) where a theme author will see it** — `themes/README.md`
552
661
  is the natural home. Seven keys × fifteen files is a small enough surface to name explicitly,
553
662
  and today nothing warns you before the snapshot goes red.
554
- 5. **Gate `AGENT_LESSON_PROMPT` like its sibling (§7.7), and either gate or delete
663
+ 4. **Gate `AGENT_LESSON_PROMPT` like its sibling (§7.7), and either gate or delete
555
664
  `adapters/claude-code/settings.json` (§7.10).** Two silent failure modes, both cheap to close.
556
- 6. **Consider a `scripts` block in the root `package.json`.** There is currently no single command
665
+ 5. **Consider a `scripts` block in the root `package.json`.** There is currently no single command
557
666
  that runs what CI runs; every contributor reassembles the five by hand from this file. A
558
667
  `verify` script is three lines and makes §1 executable rather than descriptive.
559
668
 
package/docs/limits.md CHANGED
@@ -78,10 +78,10 @@ nothing else — **M1, M2, M3, M4 and M8** (`EMIT`, `EMIT_IMPERIAL`, `EMIT_CLAUD
78
78
  `CLI_CONTEXT`). All five are killed by `tests/unit/` alone, the control included, and each row now
79
79
  **declares** the unit file that kills it rather than a replay that can no longer run — M1 and M3
80
80
  `maintainer_tools`, M2 `node_driver`, M4 `hook_form`, M8 `hook_cli`. A gate a matrix names and
81
- cannot run guards nothing, and is worse than none, because it is trusted (law XXXVIII). For every
82
- defect the mutation matrix knows how to plant, the corpus was redundant. That is the whole
83
- argument, and it is the only one that licenses a deletion: a test goes because a living gate
84
- already proves the property, never because it is red.
81
+ cannot run guards nothing, and is worse than none, because it is trusted (Doctrine rigor 2,
82
+ Honest Tests). For every defect the mutation matrix knows how to plant, the corpus was
83
+ redundant. That is the whole argument, and it is the only one that licenses a deletion:
84
+ a test goes because a living gate already proves the property, never because it is red.
85
85
 
86
86
  **What was knowingly LOST: byte-level regression detection on emit, cli and web output.** Nothing
87
87
  now notices that a rendered bundle, a verb's stdout / stderr / exit code, or an HTTP response body
@@ -30,10 +30,21 @@ every host the same way instead of one silently falling behind.
30
30
 
31
31
  ## Where the tokens go
32
32
 
33
- - **The root file is ~76% of the bill**, and its Rules section alone is ~6.3k
34
- of the ~10.7k. The [footprint dial](#/docs/footprint) (`full` vs `lean`)
35
- exists precisely because this is the only lever that matters — trimming
36
- anything else is noise.
33
+ - **The root file is ~76% of the bill**, and the constitution inside it is the
34
+ bulk of that — no longer one section but three: the Ontology, the nine Rules,
35
+ and the doctrine packs this install built in. **Two** levers move it, not one.
36
+ The [footprint dial](#/docs/footprint) (`lean`, the default, keeps each Rule
37
+ and each doctrine rule as its heading plus first line, and ships the Ontology
38
+ *whole*; `full` inlines every rationale). And the
39
+ [doctrine packs](#/docs/setup-choices) — `geneseed-build --doctrines craft,rigor`
40
+ drops whole blocks of §2 at build time, which removes far more than the
41
+ footprint dial trims. Anything else is noise.
42
+
43
+ The three-tier split grew the root file: measured on `neutral`, `AGENT.md`
44
+ went from 31,457 bytes to 36,882 at `lean` (+17.2%) and 53,378 to 54,810 at
45
+ `full` (+2.7%). The lean growth is the larger one *by design* — the Ontology
46
+ is prose, and truncating four flowing sections to four orphan sentences would
47
+ have shipped a worldview nobody could read.
37
48
  - **Skill bodies (~53k) and agent bodies (~10k) are lazy** on every host —
38
49
  loaded only when invoked. A typical skill costs ≤3k per invocation; the
39
50
  heaviest (`react-view-transitions`, ~17.5k with its reference files) loads
@@ -4,7 +4,7 @@ order: 0
4
4
  title: "Edit the source"
5
5
  kind: "concept"
6
6
  ---
7
- Everything theme-independent lives under `src/` — laws, agents, skills, memory and notebook conventions, and the `AGENT.md.tmpl` entrypoint. Voice tokens live under `themes/` as one JSON file per theme. After editing, `geneseed build --emit opencode-global` (or `geneseed update`) re-renders the deployed bundle. The `doctor` action verifies the result: unresolved theme tokens, dead links, hermetic escapes, theme-key parity, and that the committed bundle matches a fresh render.
7
+ Everything theme-independent lives under `src/` — the constitution (`ontology/`, `laws/`, `doctrines/`), the `postures/` and `modes/` registers, agents, skills, memory and notebook conventions, and the `AGENT.md.tmpl` entrypoint. Voice tokens live under `themes/` as one JSON file per theme. After editing, `geneseed build --emit opencode-global` (or `geneseed update`) re-renders the deployed bundle. The `doctor` action verifies the result: unresolved theme tokens, dead links, hermetic escapes, theme-key parity, and that the committed bundle matches a fresh render.
8
8
 
9
9
  Each agent and skill also carries a lifecycle status — `experimental`, `approved` or `deprecated` — recorded in `registry.json` at the repo root alongside its version, owner and add-date. The file is maintainer-side: it is never rendered into a bundle, so a status costs no session context. Adding a spec means adding its row; `doctor` fails on a spec with no row and on a row with no spec, and the catalog badges anything that is not `approved`. The same pass refuses to let a credential ship, and holds every vendored skill folder to an immutable upstream commit rather than a moving branch.
10
10
 
@@ -9,8 +9,8 @@ Claude Code has no `instructions` array and no JS plugin dir — the harness rea
9
9
  ### The four hooks
10
10
 
11
11
  - **Context injection** — `SessionStart` (startup, clear, resume) runs `geneseed-hook context`: auto-discovers the repo's docs by convention and injects them before your first turn, plus your machine wiki. It honours the same `GENESEED_CONTEXT` manifest as the OpenCode context plugin.
12
- - **Git gate** — `PreToolUse` on Bash runs `geneseed-hook git-gate`: enforces the safety Laws at the tool boundary, before a shell command executes.
13
- - **Rule gate** — `PreToolUse` on the write tools runs `geneseed-hook rule-gate`: a write to `user-rules.md` or to a memory file asks first, because whether something you want kept is a standing rule or a durable fact is *your* call, settled through the [rule skill](#/docs/skills) (**Law VI**). Ordinary edits are untouched.
12
+ - **Git gate** — `PreToolUse` on Bash runs `geneseed-hook git-gate`: a `git commit` or `git push` anywhere in the command line — a compound one-liner and a `-C <path>` form included — asks first, at the tool boundary and before the shell runs it (**Doctrine process 5**). It is the one hook that rides a doctrine pack: an install built without **process** never gets this group, because a boundary that keeps asking for a rule the install did not adopt is a gate arguing with its own harness.
13
+ - **Rule gate** — `PreToolUse` on the write tools runs `geneseed-hook rule-gate`: a write to `user-rules.md` or to a memory file asks first, because whether something you want kept is a standing rule or a durable fact is *your* call, settled through the [rule skill](#/docs/skills) (**Doctrine process 1**). Ordinary edits are untouched.
14
14
  - **Learn** — `Stop` and `SubagentStop` run `geneseed-hook learn`: distils durable memories into the install's `memory/` store at session end; a subagent's stop routes to the per-agent lesson path (`memory/agents/<name>.md`).
15
15
 
16
16
  ### Where they live
@@ -4,7 +4,7 @@ order: 11
4
4
  title: "The collaboration layer"
5
5
  kind: "concept"
6
6
  ---
7
- Beyond the Laws, four mechanisms shape *how* the agent works with you — the register, the mutual contract, how memory binds, and who you are. All four are plain content in `AGENT.md` and its neighbours, so they ride to every host (OpenCode, Claude, Bob, Copilot) unchanged.
7
+ Beside the [constitution](#/docs/rules), a handful of mechanisms shape *how* the agent works with you — the two registers, the mutual contract, how memory binds, and who you are. All of them are plain content in `AGENT.md` and its neighbours, so they ride to every host (OpenCode, Claude, Bob, Copilot) unchanged.
8
8
 
9
9
  ### Postures — the register
10
10
 
@@ -16,7 +16,7 @@ A **mode** is the session's operating register — *how* work gets executed, as
16
16
 
17
17
  ### The Pact — a two-way contract
18
18
 
19
- Where the Laws bind the agent, the **Pact** binds the collaboration. It holds three co-equal protections (you, the truth, the agent) and — unusually — names what *you* owe back: don't punish candour that honours the pact, give context up front, decide when shown a fork. It is framing, not an enforced rule.
19
+ Where the Rules bind the agent, the **Pact** binds the collaboration — and it is not a layer beside them: it is stated inside the Ontology's **Telos**, the tier that is always in force, so it holds in every task and every repository. It carries three co-equal protections (you, the truth, the agent), never traded one for another, and — unusually — names what *you* owe back: don't punish candour that honours the pact, give context up front, decide when shown a fork. Your half is not enforceable against you; the agent's half is binding on it.
20
20
 
21
21
  ### Typed memory — binding force
22
22
 
@@ -24,4 +24,4 @@ A memory may carry an optional `force` — **constraint** (imposed, not the agen
24
24
 
25
25
  ### Your profile — identity
26
26
 
27
- `PROFILE.md`, seeded once beside `AGENT.md` and never overwritten, holds *who you are*: role, habits, register preferences. It is identity, not rules — it colours how the agent works but never binds (precedence is Laws, then `user-rules.md`, then the profile). Edit it here under the **Profile** tab, or in the file directly — or let the agent draft it: the [[profile]] skill interviews you (who you are, how you work, how you like answers pitched) and writes the file only with your consent, routing anything that is really a standing rule to `user-rules.md` instead.
27
+ `PROFILE.md`, seeded once beside `AGENT.md` and never overwritten, holds *who you are*: role, habits, register preferences. It is identity, not rules — it colours how the agent works but never binds (precedence is the Ontology and the Rules, then `user-rules.md`, then the active Doctrines, then the profile). Edit it here under the **Profile** tab, or in the file directly — or let the agent draft it: the [[profile]] skill interviews you (who you are, how you work, how you like answers pitched) and writes the file only with your consent, routing anything that is really a standing rule to `user-rules.md` instead.
@@ -8,7 +8,7 @@ Once installed, the agent doesn't change *how* you talk to your tool — it chan
8
8
 
9
9
  ### What loaded automatically
10
10
 
11
- - **`AGENT.md`** — {N_LAWS} universal Rules the agent obeys.
11
+ - **`AGENT.md`** — the [constitution](#/docs/rules): the Ontology's {N_ONTOLOGY} sections, {N_LAWS} always-on Rules, and the {N_DOCTRINE_RULES} doctrine rules from the packs this install built in.
12
12
  - **Your repo's docs** — `README.md`, `CONTRIBUTING.md`, anything under `docs/` the harness discovers.
13
13
  - **Your machine's wiki** (if you [set one up](#/docs/configure-wiki)) — eager entries and a lazy listing of the rest.
14
14
  - **The skill and agent catalogue** — invokable by name.
@@ -25,4 +25,4 @@ Skills are repeatable workflows; agents are capability specialists. You invoke t
25
25
 
26
26
  ---
27
27
 
28
- **Catalog:** [Skills](#/section/skills) · [Agents](#/section/agents) · [Rules](#/laws)
28
+ **Catalog:** [Skills](#/section/skills) · [Agents](#/section/agents) · [Constitution](#/laws)
@@ -5,17 +5,24 @@ title: "Footprint (lean vs full)"
5
5
  kind: "concept"
6
6
  link: {"hash": "#/settings", "label": "Toggle it in Settings →"}
7
7
  ---
8
- **Footprint** controls how much of the Rules your agent carries *inline* in `AGENT.md` every turn. Two states — **lean** (the default) and **full** — set per install. It's a token-cost dial, not a change to which Rules apply: every Rule is always in force, and across lean and full the emitted files are otherwise identical — same Agents, Skills, plugins, commands, Memory, and Notebook.
8
+ **Footprint** controls how much of the [constitution](#/docs/rules) your agent carries *inline* in `AGENT.md` every turn. Two states — **lean** (the default) and **full** — set per install. It's a token-cost dial, not a change to which rules apply: whatever this install adopted is in force at either setting, and across lean and full the emitted files are otherwise identical — same Agents, Skills, plugins, commands, Memory, and Notebook. (The dial that *does* change which rules apply is the [doctrine packs](#/docs/setup-choices), a separate choice.)
9
9
 
10
10
  ### The difference
11
11
 
12
- - **Full** — Section 1 of `AGENT.md` inlines every Rule's complete text *and* its reasoning. The agent sees the full law set, rationale included, on every single turn.
13
- - **Lean** — Section 1 carries each Rule as its **heading + the rule itself** (one line), followed by a pointer to the complete law file (`laws/universal.md`, shipped beside `AGENT.md`) — the agent reads the rationale on demand when a rule's application is unclear. Lean trims Section 1 by roughly 40%.
12
+ - **Full** — `AGENT.md` inlines the Ontology, every Rule and every rule of the **active** doctrine packs, complete text and reasoning included, on every single turn.
13
+ - **Lean** — each Rule and each doctrine rule is carried as its **heading + the rule itself** (one line), each tier closing with a pointer to its complete text shipped beside `AGENT.md` — the agent reads the reasoning on demand when a rule's application is unclear. The **Ontology ships whole even at lean**: it is flowing prose, not numbered blocks, and truncating it to first sentences would leave orphan fragments rather than a shorter argument.
14
+
15
+ ### What ships on disk either way
16
+
17
+ Neither setting hides text from the agent; they hide it from *every turn*.
18
+
19
+ - **Lean** writes `laws/`, `ontology/` and `doctrines/` in full text into the install, beside `AGENT.md`, because the inline copy has lost text the agent may still need.
20
+ - **Full** writes `doctrines/` for the mirror-image reason: full inlines only the packs this install built in, so the ones it left out have to be on disk for a citation into them to resolve, and for you to read before turning one on.
14
21
 
15
22
  ### Which to choose
16
23
 
17
- - Keep **full** if token cost is a non-issue, you want the rationale always present, or you run a smaller/cheaper model — with the *why* eagerly in context, a model applies a Rule's nuance more reliably. This is why full is the default.
18
- - Switch to **lean** to reclaim context and cost on long sessions, large repos, or cost-sensitive runs, trusting the agent to pull the full law when it needs the *why*. Lean is **safe**: the complete law text still ships, and the harness explicitly points the agent there before acting on secrets, deletion, git history, scope, or untrusted content. It's an optimization, not a rules cut.
24
+ - Keep **lean** — the default — on long sessions, large repos, or cost-sensitive runs, trusting the agent to pull the complete text when it needs the *why*. Lean is **safe**: that text still ships, and the harness explicitly points the agent there before acting on secrets, deletion, git history, scope, or untrusted content. It's an optimization, not a rules cut.
25
+ - Switch to **full** if token cost is a non-issue, you want the reasoning always present, or you run a smaller/cheaper model — with the *why* eagerly in context, a model applies a rule's nuance more reliably.
19
26
 
20
27
  ### How to set it
21
28
 
@@ -23,9 +30,9 @@ It's set-and-forget — stored in the `.geneseed-footprint` marker, preserved ac
23
30
 
24
31
  - **Settings** — the **Footprint** toggle flips the current install (full ⇄ lean) and rebuilds it in place.
25
32
  - **Harnesses tab** — a per-harness dropdown sets it for any one install independently, then **Apply**.
26
- - **Setup / re-theme wizard** — asks for footprint alongside voice and mode.
33
+ - **Setup / re-theme wizard** — asks for footprint alongside voice, posture, mode, and doctrine packs.
27
34
  - **CLI** — `geneseed-build --footprint lean` (with any `--emit`).
28
35
 
29
36
  ---
30
37
 
31
- **Related:** [Rules (Laws)](#/laws) · [Voice vs structure](#/docs/themes) · [Token footprint — the numbers](#/docs/token-footprint)
38
+ **Related:** [The constitution](#/docs/rules) · [Voice vs structure](#/docs/themes) · [Token footprint — the numbers](#/docs/token-footprint)
@@ -5,7 +5,7 @@ title: "Foreman mode"
5
5
  kind: "concept"
6
6
  link: {"hash": "#/harnesses", "label": "Set the mode in Harnesses →"}
7
7
  ---
8
- **Mode** is the session's *operating* register — how work gets executed — a separate dial from posture (the *relationship* register) and footprint (how much of the Rules loads inline). Two modes ship, set at build time so the choice holds steady instead of drifting mid-session, and preserved across every rebuild and re-theme.
8
+ **Mode** is the session's *operating* register — how work gets executed — one of four build-time dials, beside posture (the *relationship* register), [doctrine packs](#/docs/setup-choices) (which practice rules bind) and footprint (how much of the constitution loads inline). Two modes ship, set at build time so the choice holds steady instead of drifting mid-session, and preserved across every rebuild and re-theme.
9
9
 
10
10
  ### direct — the default
11
11
 
@@ -25,7 +25,7 @@ Because the crew runs apart from the conversation, the session stays responsive
25
25
  Set-and-forget, stored beside the install and preserved across rebuilds and re-themes:
26
26
 
27
27
  - **Harnesses tab** — the per-install **Mode** dropdown (beside Voice, Footprint, and Posture), then **Apply**.
28
- - **Setup / re-theme wizard** — asks for mode alongside voice, posture, and footprint.
28
+ - **Setup / re-theme wizard** — asks for mode alongside voice, posture, doctrine packs, and footprint.
29
29
  - **CLI** — `geneseed-build --mode foreman`; switch back with `--mode direct`.
30
30
 
31
31
  ---
@@ -6,14 +6,14 @@ kind: "concept"
6
6
  ---
7
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 **Copilot** share one Claude-shaped engine that diverges only by host dialect.
8
8
 
9
- The harness itself — Rules, Agents, Skills, Memory, and the preamble voice — is **identical on every host**. 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 (Ontology, 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
11
  | Capability | OpenCode | Claude | Bob | Copilot |
12
12
  | --- | :---: | :---: | :---: | :---: |
13
13
  | Agents · Skills · Memory | ✅ | ✅ | ✅ | ✅ |
14
14
  | Context injection | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble |
15
15
  | Memory write-back (learn) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble |
16
- | Git-gate consent (Rule XX) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble |
16
+ | Git-gate consent (Doctrine process 5) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 📄 preamble |
17
17
  | Sovereign-repo excludes | ⚙️ plugin | ✅ | ✅ | ➖ |
18
18
  | MCP server wiring | ✅ | ✅ | ✅ | ✅ |
19
19
  | Colour themes | ✅ | ➖ | ➖ | ➖ |
@@ -21,7 +21,9 @@ The harness itself — Rules, Agents, Skills, Memory, and the preamble voice —
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.
23
23
 
24
- **No host drops an Agent, Skill, or the memory convention.** The asymmetry is entirely in *automation mechanism*: OpenCode's plugins and Claude/Bob's hooks enforce a few Rules for you, 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.
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.
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'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.
25
27
 
26
28
  ---
27
29
 
@@ -32,4 +32,4 @@ A checkout needs **git** and the same **Node ≥ 22.3** as everything else — t
32
32
 
33
33
  ---
34
34
 
35
- **Next:** [Posture & footprint](#/docs/setup-choices) · [Verify it works](#/docs/verify) · [What you just installed](#/docs/model) · [Install by hand instead](#/docs/install-paths)
35
+ **Next:** [Posture, doctrines & footprint](#/docs/setup-choices) · [Verify it works](#/docs/verify) · [What you just installed](#/docs/model) · [Install by hand instead](#/docs/install-paths)
package/docs/web/model.md CHANGED
@@ -4,14 +4,14 @@ order: 0
4
4
  title: "The harness model"
5
5
  kind: "concept"
6
6
  ---
7
- Geneseed assembles five runtime pieces around a single `AGENT.md` entrypoint: **Rules** (the laws the agent obeys), **Agents** (capability specialists you delegate to), **Skills** (repeatable workflows the agent can invoke), **Memory** (one-fact-per-file durable knowledge), and a **Notebook** (the agent's own sovereign space).
7
+ Geneseed assembles its runtime pieces around a single `AGENT.md` entrypoint: an **Ontology** (how the agent thinks, decides and speaks — always on), **Rules** (the always-on invariants it never breaks), **Doctrines** (practice packs this repository chose at build time), **Agents** (capability specialists you delegate to), **Skills** (repeatable workflows the agent can invoke), **Memory** (one-fact-per-file durable knowledge), and a **Notebook** (the agent's own sovereign space). The first three are the [constitution](#/docs/rules), in that order of precedence — with your own `user-rules.md` sitting between the Rules and the Doctrines.
8
8
  <!--harness:opencode-->
9
9
  On OpenCode, {N_PLUGINS} **Plugins** bind the pieces to the host: context injection, learn-at-session-end, the safety guard, the saved workflow runner, end-of-run notifications, a live-activity feed for this console, and an opt-in minimal-code mode.
10
10
  <!--/harness-->
11
11
  <!--harness:claude-->
12
- On Claude Code, three settings.json **hooks** bind the pieces to the host — context injection, the git safety gate, and learn-at-session-end. See [How Geneseed binds to Claude Code](#/docs/claude-hooks).
12
+ On Claude Code, four settings.json **hooks** bind the pieces to the host — context injection, the git consent gate (wired only when the **process** doctrine pack is built in), the rule gate on writes to `user-rules.md` and memory, and learn-at-session-end. See [How Geneseed binds to Claude Code](#/docs/claude-hooks).
13
13
  <!--/harness-->
14
- The structure is theme-independent — a theme only changes the *voice* (banner, sigil, prose), never a folder or a link. A separate dial, the **[footprint](#/docs/footprint)**, sets how much of the Rules load inline each turn (full vs lean), the **[collaboration layer](#/docs/collaboration)** — posture, the Pact, typed memory, your profile — shapes how the agent works *with you*, and the **mode** dial ([direct vs foreman](#/docs/foreman-mode)) sets *how work gets executed* — one agent turn by turn, or a foreman triaging tasks into [pipelines](#/docs/pipelines).
14
+ The structure is theme-independent — a theme only changes the *voice* (banner, sigil, prose), never a folder or a link. Four dials are fixed at build time and preserved across every rebuild: **[posture](#/docs/collaboration)** (the relationship register), **mode** ([direct vs foreman](#/docs/foreman-mode) — one agent turn by turn, or a foreman triaging tasks into [pipelines](#/docs/pipelines)), **[doctrine packs](#/docs/setup-choices)** (which practice rules bind — the only dial that changes *which* rules apply), and **[footprint](#/docs/footprint)** (how much of the constitution loads inline each turn, full vs lean). Around them the **[collaboration layer](#/docs/collaboration)** — posture, the Pact, typed memory, your profile — shapes how the agent works *with you*.
15
15
 
16
16
  ### What this UI actually shows
17
17
 
@@ -4,7 +4,7 @@ order: 1
4
4
  title: "geneseed-context"
5
5
  kind: "concept"
6
6
  ---
7
- Enforces **Law XVIII** (*Load the Project Context*) by injection, not instruction: on `session.created` it auto-discovers the repo's docs by convention and injects the `eager` ones before your first turn, so the harness needs **zero per-repo files**.
7
+ Enforces the project-context load by injection, not instruction: on `session.created` it auto-discovers the repo's docs by convention and injects the `eager` ones before your first turn, so the harness needs **zero per-repo files**.
8
8
 
9
9
  - **Eager** (injected in full, budget-capped): root `AGENTS.md` / `AGENT.md` / `CLAUDE.md` / `.cursorrules`, `README.md`, `CONTRIBUTING.md`.
10
10
  - **Lazy** (path + first heading, read on demand): `docs/`, `doc/`, `architecture/`, `adr/`, monorepo `packages/*/README.md`, other root `*.md`. `node_modules`, `.git`, `dist`, `build` are never scanned.
@@ -19,7 +19,7 @@ Installs with the other plugins in one step — see [Plugin setup](#/docs/plugin
19
19
  - `GENESEED_CONTEXT` — path to an explicit `context.json` manifest (or drop `.harness/context.json` in the repo) to take control: same schema, plus glob `path`s, `load: exclude`, and `"extend": true` to layer on top of discovery.
20
20
  - `GENESEED_EAGER_FILE_KB` (default 16) / `GENESEED_EAGER_TOTAL_KB` (default 48) — budget caps; an oversized eager file is demoted to a lazy listing, never silently truncated.
21
21
  - `GENESEED_CONTEXT_VISIBLE=1` — force the visible `PROJECT CONTEXT` block instead of the invisible per-request transform.
22
- - `GENESEED_CONTEXT_INJECT=off` — disable injection entirely (falls back to the soft AGENT.md Law).
22
+ - `GENESEED_CONTEXT_INJECT=off` — disable injection entirely; the load falls back to prose the agent has to honour itself — AGENT.md's own **Context** section, and **Doctrine process 4** (read the project's documentation for a part of the system before changing it) where the process pack is built in.
23
23
 
24
24
  ### Verify
25
25
 
@@ -4,11 +4,11 @@ order: 3
4
4
  title: "geneseed-guard"
5
5
  kind: "concept"
6
6
  ---
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. High-confidence patterns only, so legitimate work is never caught:
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 §7, from `wiki.jsonc`).
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`).
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 **Law VI**: 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 **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.)
12
12
 
13
13
  ### Install
14
14