geneseed 3.11.0 → 3.13.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 (265) hide show
  1. package/CHANGELOG.md +160 -0
  2. package/README.md +5 -5
  3. package/SHIPPED.md +2 -2
  4. package/adapters/bob/README.md +1 -1
  5. package/adapters/claude-code/README.md +1 -1
  6. package/adapters/openclaude/README.md +1 -1
  7. package/adapters/opencode/README.md +3 -3
  8. package/adapters/opencode/plugins/geneseed-guard.js +157 -2
  9. package/bin/geneseed-cli.mjs +4 -0
  10. package/docs/README.md +41 -22
  11. package/docs/concepts/agents.md +3 -1
  12. package/docs/concepts/collaboration.md +3 -1
  13. package/docs/concepts/exclusions.md +4 -2
  14. package/docs/concepts/footprint.md +3 -1
  15. package/docs/concepts/foreman-mode.md +4 -2
  16. package/docs/concepts/hook-gates.md +61 -0
  17. package/docs/concepts/hooks.md +8 -56
  18. package/docs/concepts/host-matrix.md +38 -0
  19. package/docs/concepts/hosts.md +6 -32
  20. package/docs/concepts/loop-branch.md +66 -0
  21. package/docs/concepts/loop-bricks.md +48 -0
  22. package/docs/concepts/loop-contracts.md +33 -0
  23. package/docs/concepts/loop-gates.md +30 -0
  24. package/docs/concepts/loop-notes.md +43 -0
  25. package/docs/concepts/loop-risk.md +36 -0
  26. package/docs/concepts/loop-templates.md +50 -0
  27. package/docs/concepts/loops.md +73 -0
  28. package/docs/concepts/lsp.md +2 -0
  29. package/docs/concepts/memory.md +3 -1
  30. package/docs/concepts/notebook.md +3 -1
  31. package/docs/concepts/rules.md +4 -2
  32. package/docs/concepts/skills.md +3 -1
  33. package/docs/concepts/themes.md +3 -1
  34. package/docs/extending.md +28 -8
  35. package/docs/guides/autostart.md +3 -1
  36. package/docs/guides/choose-your-setup.md +5 -66
  37. package/docs/guides/headless.md +5 -3
  38. package/docs/guides/install-agent-md.md +37 -0
  39. package/docs/guides/install-bob.md +20 -0
  40. package/docs/guides/install-claude-code.md +22 -0
  41. package/docs/guides/install-clone.md +34 -0
  42. package/docs/guides/install-openclaude.md +25 -0
  43. package/docs/guides/install-opencode.md +35 -0
  44. package/docs/guides/install-scripted.md +21 -0
  45. package/docs/guides/install.md +9 -118
  46. package/docs/guides/loop-finish.md +54 -0
  47. package/docs/guides/loop-running.md +66 -0
  48. package/docs/guides/loop-which-template.md +35 -0
  49. package/docs/guides/mcp-filesystem.md +41 -0
  50. package/docs/guides/mcp-gitlab.md +66 -0
  51. package/docs/guides/mcp-markitdown.md +36 -0
  52. package/docs/guides/mcp.md +8 -137
  53. package/docs/guides/migrate.md +3 -1
  54. package/docs/guides/project-context.md +4 -2
  55. package/docs/guides/read-non-markdown.md +17 -0
  56. package/docs/guides/run-a-loop.md +64 -0
  57. package/docs/guides/run-anywhere.md +2 -0
  58. package/docs/guides/setup-doctrines.md +55 -0
  59. package/docs/guides/setup-footprint.md +48 -0
  60. package/docs/guides/uninstall.md +3 -1
  61. package/docs/guides/upgrade.md +3 -1
  62. package/docs/guides/verify.md +3 -1
  63. package/docs/guides/wiki.md +3 -1
  64. package/docs/guides/worktree.md +3 -1
  65. package/docs/reference/about.md +3 -1
  66. package/docs/reference/cli.md +2 -0
  67. package/docs/reference/env-context.md +40 -0
  68. package/docs/reference/environment.md +10 -59
  69. package/docs/reference/glossary.md +7 -1
  70. package/docs/reference/loop-actions.md +20 -0
  71. package/docs/reference/opencode-plugins.md +14 -116
  72. package/docs/reference/plugin-activity.md +20 -0
  73. package/docs/reference/plugin-context.md +27 -0
  74. package/docs/reference/plugin-guard.md +27 -0
  75. package/docs/reference/plugin-learn.md +27 -0
  76. package/docs/reference/plugin-notify.md +20 -0
  77. package/docs/reference/plugin-ponytail.md +19 -0
  78. package/docs/reference/plugin-workflow.md +25 -0
  79. package/docs/reference/troubleshoot-doctor.md +50 -0
  80. package/docs/reference/troubleshoot-hooks.md +99 -0
  81. package/docs/reference/troubleshoot-install.md +108 -0
  82. package/docs/reference/troubleshoot-tools.md +56 -0
  83. package/docs/reference/troubleshoot-update.md +23 -0
  84. package/docs/reference/troubleshoot-web.md +66 -0
  85. package/docs/reference/troubleshooting.md +13 -337
  86. package/docs/understand/a-day.md +3 -1
  87. package/docs/understand/enforced-vs-asked.md +3 -1
  88. package/docs/understand/harness.md +2 -0
  89. package/docs/understand/machine-bob.md +17 -0
  90. package/docs/understand/machine-claude.md +35 -0
  91. package/docs/understand/machine-opencode.md +36 -0
  92. package/docs/understand/on-your-machine.md +12 -55
  93. package/docs/understand/take-it-out.md +13 -0
  94. package/docs/web-ui.md +36 -5
  95. package/harness.config.json +1 -1
  96. package/js/README.md +32 -2
  97. package/js/build/driver.mjs +14 -8
  98. package/js/build/generate.mjs +10 -6
  99. package/js/build/render.mjs +5 -0
  100. package/js/build/source.mjs +5 -1
  101. package/js/cli-table.json +261 -0
  102. package/js/hosts/gitref.mjs +99 -0
  103. package/js/hosts/hooks.mjs +88 -1
  104. package/js/hosts/installs.mjs +21 -0
  105. package/js/hosts/mcp.mjs +1 -1
  106. package/js/hosts/native.mjs +43 -5
  107. package/js/inspect/checks-authoring.mjs +10 -0
  108. package/js/inspect/checks-build.mjs +28 -0
  109. package/js/inspect/diff.mjs +3 -0
  110. package/js/inspect/doctor.mjs +2 -1
  111. package/js/inspect/inventory.mjs +1 -0
  112. package/js/inspect/status.mjs +1 -1
  113. package/js/loop/catalog.mjs +127 -0
  114. package/js/loop/cli.mjs +173 -0
  115. package/js/loop/graph.mjs +163 -0
  116. package/js/loop/registry.mjs +196 -0
  117. package/js/loop/score.mjs +182 -0
  118. package/js/loop/state.mjs +436 -0
  119. package/js/maintain/migrate.mjs +4 -2
  120. package/js/maintain/setup.mjs +1 -1
  121. package/js/web/actions.mjs +34 -3
  122. package/js/web/api.mjs +51 -2
  123. package/js/web/daemon.mjs +43 -5
  124. package/js/web/docs.mjs +64 -12
  125. package/js/web/handler.mjs +1 -0
  126. package/js/web/jobs.mjs +3 -1
  127. package/js/web/routes.mjs +5 -1
  128. package/js/web/server.mjs +5 -3
  129. package/package.json +1 -1
  130. package/registry.json +14 -0
  131. package/src/AGENT.md.tmpl +2 -0
  132. package/src/agents/explorer.md +2 -2
  133. package/src/agents/researcher.md +3 -3
  134. package/src/bricks/README.md +34 -0
  135. package/src/bricks/_template.md +32 -0
  136. package/src/bricks/adr-challenge.md +20 -0
  137. package/src/bricks/adr-draft.md +15 -0
  138. package/src/bricks/apply.md +17 -0
  139. package/src/bricks/baseline-green.md +17 -0
  140. package/src/bricks/bruno-test.md +16 -0
  141. package/src/bricks/characterize.md +17 -0
  142. package/src/bricks/ci-fix.md +18 -0
  143. package/src/bricks/ci-triage.md +20 -0
  144. package/src/bricks/compat-check.md +16 -0
  145. package/src/bricks/deps-audit.md +14 -0
  146. package/src/bricks/docs-update.md +15 -0
  147. package/src/bricks/done-check.md +16 -0
  148. package/src/bricks/fitness-define.md +22 -0
  149. package/src/bricks/flake-check.md +17 -0
  150. package/src/bricks/flake-repro.md +18 -0
  151. package/src/bricks/identify.md +23 -0
  152. package/src/bricks/lint.md +14 -0
  153. package/src/bricks/migration-plan.md +21 -0
  154. package/src/bricks/mutation-check.md +18 -0
  155. package/src/bricks/plan.md +17 -0
  156. package/src/bricks/red-test.md +16 -0
  157. package/src/bricks/reproduce.md +16 -0
  158. package/src/bricks/review.md +19 -0
  159. package/src/bricks/security-scan.md +17 -0
  160. package/src/bricks/spec.md +18 -0
  161. package/src/bricks/test.md +14 -0
  162. package/src/bricks/upgrade-scout.md +16 -0
  163. package/src/doctrines/process.md +11 -8
  164. package/src/loops/api-endpoint.json +31 -0
  165. package/src/loops/architecture-decision.json +22 -0
  166. package/src/loops/bugfix.json +23 -0
  167. package/src/loops/ci-repair.json +19 -0
  168. package/src/loops/deps-upgrade.json +29 -0
  169. package/src/loops/enforce-architecture-rule.json +28 -0
  170. package/src/loops/feature.json +24 -0
  171. package/src/loops/fix-flaky-tests.json +30 -0
  172. package/src/loops/legacy-refactor.json +26 -0
  173. package/src/loops/legacy-tests.json +29 -0
  174. package/src/loops/refactor.json +24 -0
  175. package/src/loops/remove-dead-code.json +30 -0
  176. package/src/loops/spec-first-feature.json +29 -0
  177. package/src/loops/tdd.json +25 -0
  178. package/src/loops/update-contract.json +33 -0
  179. package/src/skills/brick-forge.md +48 -0
  180. package/src/skills/bruno-collection-generator.md +3 -3
  181. package/src/skills/bruno-test-writer.md +3 -3
  182. package/src/skills/ci-fix.md +3 -3
  183. package/src/skills/consolidate-memory.md +4 -4
  184. package/src/skills/council.md +1 -1
  185. package/src/skills/fresh-eyes.md +1 -1
  186. package/src/skills/geneseed.md +1 -1
  187. package/src/skills/git-archaeology.md +1 -1
  188. package/src/skills/git-rescue.md +4 -3
  189. package/src/skills/handoff.md +1 -1
  190. package/src/skills/herdr.md +1 -1
  191. package/src/skills/learn-mode.md +2 -2
  192. package/src/skills/loop.md +111 -0
  193. package/src/skills/opencode-theme.md +3 -3
  194. package/src/skills/ponytail.md +1 -1
  195. package/src/skills/profile.md +3 -4
  196. package/src/skills/prose.md +2 -3
  197. package/src/skills/quiz.md +1 -1
  198. package/src/skills/react-view-transitions/SKILL.md +1 -1
  199. package/src/skills/react-view-transitions/VENDOR.md +8 -3
  200. package/src/skills/research.md +3 -3
  201. package/src/skills/review-response.md +2 -2
  202. package/src/skills/rule.md +3 -3
  203. package/src/skills/security-audit.md +4 -4
  204. package/src/skills/teach.md +1 -1
  205. package/src/skills/wiki.md +3 -3
  206. package/src/skills/workflow.md +4 -4
  207. package/src/skills/worktree.md +2 -2
  208. package/themes/_TEMPLATE.json +2 -0
  209. package/themes/biker.json +2 -0
  210. package/themes/commentator.json +2 -0
  211. package/themes/cyberpunk.json +2 -0
  212. package/themes/gamer.json +2 -0
  213. package/themes/imperial.json +2 -0
  214. package/themes/joker.json +2 -0
  215. package/themes/marvin.json +2 -0
  216. package/themes/mean.json +2 -0
  217. package/themes/military.json +2 -0
  218. package/themes/neutral.json +2 -0
  219. package/themes/pirate.json +2 -0
  220. package/themes/sports.json +2 -0
  221. package/themes/verstappen.json +2 -0
  222. package/themes/wizard.json +2 -0
  223. package/web/dist/assets/Activity-Ca2Aruu7.js +1 -0
  224. package/web/dist/assets/ActivityDetail-Bo7v4Z_r.js +1 -0
  225. package/web/dist/assets/Dashboard-BuMq46aT.js +2 -0
  226. package/web/dist/assets/Docs-BzccCllG.js +5 -0
  227. package/web/dist/assets/FilterInput-CBcJBQPI.js +1 -0
  228. package/web/dist/assets/GreenhouseView-BCIKcnGG.js +2 -0
  229. package/web/dist/assets/Installs-DMFJvq7s.js +2 -0
  230. package/web/dist/assets/JournalView-o1rmd1_1.js +1 -0
  231. package/web/dist/assets/Laws-BANxq_I_.js +3 -0
  232. package/web/dist/assets/Library-DW4x0fbh.js +1 -0
  233. package/web/dist/assets/Loops-DEBibbBP.js +2 -0
  234. package/web/dist/assets/{Markdown-qjM2_ofS.js → Markdown-CdTX0kLe.js} +14 -14
  235. package/web/dist/assets/OperatorHudView-CLD0fYaA.js +2 -0
  236. package/web/dist/assets/Personal-6uMJvyBG.js +1 -0
  237. package/web/dist/assets/Tabs-BubnyZhF.js +1 -0
  238. package/web/dist/assets/activity-CObqyxkL.js +1 -0
  239. package/web/dist/assets/{api-Dc8f3ca-.js → api-D_ixdyEY.js} +1 -1
  240. package/web/dist/assets/drawable-C_x5xncq.js +1 -0
  241. package/web/dist/assets/index-CMPgezFm.js +2 -0
  242. package/web/dist/assets/index-DMsT4Aa6.css +1 -0
  243. package/web/dist/assets/{react-B9Z_tXRV.js → react-Bbzhmq4v.js} +1 -1
  244. package/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
  245. package/web/dist/assets/sections-Dg23Hel5.js +1 -0
  246. package/web/dist/assets/usePoll-BOqeunzF.js +1 -0
  247. package/web/dist/index.html +6 -5
  248. package/web/dist/assets/Activity-C52LEb-2.js +0 -1
  249. package/web/dist/assets/ActivityDetail-CjNLRvXg.js +0 -1
  250. package/web/dist/assets/Dashboard-B6_sSCHi.js +0 -2
  251. package/web/dist/assets/Docs-Dj7BmCSA.js +0 -5
  252. package/web/dist/assets/FilterInput-CVyqmYWM.js +0 -1
  253. package/web/dist/assets/GreenhouseView-BALwjQsA.js +0 -2
  254. package/web/dist/assets/Installs-BbffDQm3.js +0 -2
  255. package/web/dist/assets/JournalView-JpAQ8Hqe.js +0 -1
  256. package/web/dist/assets/Laws-DK7eCWSm.js +0 -3
  257. package/web/dist/assets/Library-CoamHelE.js +0 -1
  258. package/web/dist/assets/OperatorHudView-DVx1HlBx.js +0 -2
  259. package/web/dist/assets/Personal-eaXb1zcj.js +0 -1
  260. package/web/dist/assets/Tabs-BmGtt8E2.js +0 -1
  261. package/web/dist/assets/drawable-Du_PZrQj.js +0 -1
  262. package/web/dist/assets/index-Bz_KMRDH.css +0 -1
  263. package/web/dist/assets/index-CNFH7o55.js +0 -2
  264. package/web/dist/assets/sections-GalMS0Zv.js +0 -1
  265. package/web/dist/assets/usePoll-O0sJEw1Y.js +0 -1
@@ -1,8 +1,10 @@
1
1
  ---
2
2
  group: concepts
3
- order: 8
3
+ order: 10
4
4
  title: "Footprint (lean vs full)"
5
5
  kind: "concept"
6
+ section: "Configuration"
7
+ description: "Lean or full: how much of the constitution rides inline every turn."
6
8
  link: {"hash": "#/settings", "label": "Toggle it in Settings →"}
7
9
  ---
8
10
  **Footprint** decides how much of the [constitution](rules.md) the agent carries *inline* in its instructions file on every turn. It has two settings, **lean** (the default) and **full**, chosen per install. It is a token-cost dial, not a rules dial: every rule the install adopted is in force at either setting.
@@ -1,15 +1,17 @@
1
1
  ---
2
2
  group: concepts
3
- order: 10
3
+ order: 15
4
4
  title: "Foreman mode"
5
5
  kind: "concept"
6
+ section: "Working together"
7
+ description: "Direct or foreman: whether the session does the work or hands it to a crew."
6
8
  link: {"hash": "#/harness", "label": "Set the mode in Harness →"}
7
9
  ---
8
10
  **Mode** decides how work gets executed in a session. Two modes ship: **direct**, the default, where the agent does every task itself, and **foreman**, where the session hands substantial tasks to a crew of [agents](agents.md) and keeps talking to you while they work.
9
11
 
10
12
  > **You already know this:** a tech lead with a team. Quick questions get answered on the spot; a real feature becomes a ticket that someone builds on a branch, and the lead reviews the result before it is merged.
11
13
 
12
- Mode is chosen at build time, so it does not drift mid-session, and kept across every rebuild and re-theme. It is separate from [posture](collaboration.md) (the relationship register), the doctrine packs ([Rules](rules.md)) and [footprint](footprint.md).
14
+ Mode is chosen at build time, so it does not drift mid-session, and kept across every rebuild and re-theme. It is separate from [posture](collaboration.md) (the relationship register), the doctrine packs ([Rules](rules.md)) and [footprint](footprint.md). It is also separate from a [loop](loops.md) — a pipeline is a one-shot, uncommitted crew for a single task; a loop is a long-running state machine that commits each validated iteration on its own branch.
13
15
 
14
16
  ### direct — the default
15
17
 
@@ -0,0 +1,61 @@
1
+ ---
2
+ group: concepts
3
+ order: 7
4
+ title: "Hook gates, settings and the shim"
5
+ kind: "concept"
6
+ section: "Harness"
7
+ description: "Gates fail closed, the settings files hooks are written to, Bob and OpenClaude, and the hook shim."
8
+ ---
9
+ How Geneseed's [hooks](hooks.md) behave when something goes wrong, where they are written on each host, and the one file they all run through.
10
+
11
+ ## Gates fail closed, and leave a trace
12
+
13
+ If a gate cannot evaluate a call — an unreadable payload, a bug — it asks, with the error as its reason, rather than silently letting the call through. Every prompt a gate raises adds one line to `notebook/gates.jsonl` in the install: the rule and the time, never the command or content. `geneseed status` counts them by rule.
14
+
15
+ ```bash
16
+ geneseed status
17
+ ```
18
+
19
+ In an [excluded folder](exclusions.md), every hook of a global install exits silently. And a global install's `context` hook stands down when the repo has its own per-repo install of the same host, so nothing is injected twice.
20
+
21
+ ## Where they are written
22
+
23
+ | Host | Global | Per repo |
24
+ | --- | --- | --- |
25
+ | Claude Code | `~/.claude/settings.json` | `.claude/settings.local.json` |
26
+ | OpenClaude | `~/.openclaude/settings.json` | `.openclaude/settings.local.json` |
27
+ | Bob | `~/.bob/settings/settings.json` | `.bob/settings.json` |
28
+
29
+ Per repo, Claude Code and OpenClaude hooks go into the **local**, untracked settings file: the hook commands contain paths on your machine, and the team-shared `settings.json` would hand every teammate broken hooks.
30
+
31
+ The merge is surgical. Every other key and every hook of your own survive, and the install manifest records exactly which hook groups are Geneseed's, so an upgrade replaces and an uninstall removes only those.
32
+
33
+ ## Bob and OpenClaude
34
+
35
+ **OpenClaude** is a Claude Code fork: it gets the same hooks and the same prompts, unchanged.
36
+
37
+ **Bob** has its own contract. It uses Claude's event names but ignores a hook's output before a tool call — the only way to refuse is exit code 2 — and it has no tool matcher, `SubagentStop` or `PreCompact`. So Bob gets three hooks:
38
+
39
+ - `SessionStart` → `geneseed-hook context`.
40
+ - `PreToolUse` → `geneseed-hook tool-gate`, the git gate and the rule gate fused into one command that decides from the shape of the call. It **blocks** (exit 2) only for the two Rules, secrets and destructive git. The commit/push and rule-or-memory checks become a warning line, because a hard block would leave Bob unable to commit at all.
41
+ - `Stop` → `geneseed-hook learn`.
42
+
43
+ Neither host has been verified live on the authoring machine. If a hook does not fire, the same rules still reach the agent through the instructions file.
44
+
45
+ ## The hook shim
46
+
47
+ Hooks run with your project as the working directory, so each command needs an absolute path. Rather than write the Node path and the Geneseed checkout path into every settings file, every hook points at one stable file, the **hook shim**: `~/.geneseed/bin/geneseed-hook` (`geneseed-hook.cmd` on Windows). The shim holds those two paths; your settings hold none. Set `GENESEED_HOME` to keep it somewhere other than `~/.geneseed`.
48
+
49
+ Every build rewrites the shim, so moving the checkout and running one build repairs every install at once.
50
+
51
+ **A stale shim fails silently.** Hooks report through their output and exit 0 on every path — that is what keeps a broken hook from breaking your tool calls. The flip side: if the shim points at a checkout that no longer exists, every hook on the machine stops working and nothing tells you. The agent simply stops getting project context and the gates stop asking. `geneseed doctor` checks the shim; a build repairs it.
52
+
53
+ ```bash
54
+ geneseed doctor
55
+ ```
56
+
57
+ See [Hook, context and memory problems](../reference/troubleshoot-hooks.md).
58
+
59
+ ## Cost
60
+
61
+ The hook program is small on purpose: it adds about 14 ms to each tool call.
@@ -1,8 +1,10 @@
1
1
  ---
2
2
  group: concepts
3
- order: 5
3
+ order: 6
4
4
  title: "Hooks (Claude Code, Bob, OpenClaude)"
5
5
  kind: "concept"
6
+ section: "Harness"
7
+ description: "The commands Claude Code, Bob and OpenClaude run at fixed moments, and what each gate does."
6
8
  ---
7
9
  A **hook** is a command your host runs at a fixed moment — when a session starts, before a tool call, when the agent finishes. On Claude Code, Bob and OpenClaude, hooks are how Geneseed does anything *in code* rather than in prose: load your project's docs, stop a risky command for your confirmation, save what was learned.
8
10
 
@@ -10,7 +12,7 @@ A **hook** is a command your host runs at a fixed moment — when a session star
10
12
 
11
13
  Geneseed writes its hooks into the host's settings file. Every hook calls one program, `geneseed-hook`, with a verb — not the `geneseed` CLI you type yourself. The instructions file (`CLAUDE.md`) needs no hook: the host loads it by location.
12
14
 
13
- ### The hooks on Claude Code
15
+ ## The hooks on Claude Code
14
16
 
15
17
  | Event | When | Command | What it does | Conditional? |
16
18
  | --- | --- | --- | --- | --- |
@@ -22,7 +24,7 @@ Geneseed writes its hooks into the host's settings file. Every hook calls one pr
22
24
  | `SubagentStop` | a subagent finishes | `geneseed-hook learn` | records a lesson for that agent in `memory/agents/<name>.md` | needs `GENESEED_LLM` |
23
25
  | `PreCompact` | before auto-compaction | `geneseed-hook learn` | captures memory before the transcript is summarised | needs `GENESEED_LLM` |
24
26
 
25
- ### What each one does, and what you see
27
+ ## What each one does, and what you see
26
28
 
27
29
  **context.** Before your first message, the agent receives your own harness files — `user-rules.md`, `PROFILE.md`, the memory index, the notebook index, your wiki declaration — skipping any still untouched since install, then the repo's docs, discovered by convention or listed in a `context.json`. Each file is capped at 16 KB and the whole injection at 48 KB; what does not fit is listed for the agent to read on demand. You see nothing, except that the agent already knows your project. See [Project context](../guides/project-context.md).
28
30
 
@@ -44,58 +46,8 @@ export GENESEED_LLM="claude -p"
44
46
 
45
47
  Unset, `learn` does nothing useful — it prints the prompt it would have sent. Geneseed never stores or embeds an API key. See [Memory](memory.md).
46
48
 
47
- ### Gates fail closed, and leave a trace
48
-
49
- If a gate cannot evaluate a call — an unreadable payload, a bug — it asks, with the error as its reason, rather than silently letting the call through. Every prompt a gate raises adds one line to `notebook/gates.jsonl` in the install: the rule and the time, never the command or content. `geneseed status` counts them by rule.
50
-
51
- ```bash
52
- geneseed status
53
- ```
54
-
55
- In an [excluded folder](exclusions.md), every hook of a global install exits silently. And a global install's `context` hook stands down when the repo has its own per-repo install of the same host, so nothing is injected twice.
56
-
57
- ### Where they are written
58
-
59
- | Host | Global | Per repo |
60
- | --- | --- | --- |
61
- | Claude Code | `~/.claude/settings.json` | `.claude/settings.local.json` |
62
- | OpenClaude | `~/.openclaude/settings.json` | `.openclaude/settings.local.json` |
63
- | Bob | `~/.bob/settings/settings.json` | `.bob/settings.json` |
64
-
65
- Per repo, Claude Code and OpenClaude hooks go into the **local**, untracked settings file: the hook commands contain paths on your machine, and the team-shared `settings.json` would hand every teammate broken hooks.
66
-
67
- The merge is surgical. Every other key and every hook of your own survive, and the install manifest records exactly which hook groups are Geneseed's, so an upgrade replaces and an uninstall removes only those.
68
-
69
- ### Bob and OpenClaude
70
-
71
- **OpenClaude** is a Claude Code fork: it gets the same hooks and the same prompts, unchanged.
72
-
73
- **Bob** has its own contract. It uses Claude's event names but ignores a hook's output before a tool call — the only way to refuse is exit code 2 — and it has no tool matcher, `SubagentStop` or `PreCompact`. So Bob gets three hooks:
74
-
75
- - `SessionStart` → `geneseed-hook context`.
76
- - `PreToolUse` → `geneseed-hook tool-gate`, the git gate and the rule gate fused into one command that decides from the shape of the call. It **blocks** (exit 2) only for the two Rules, secrets and destructive git. The commit/push and rule-or-memory checks become a warning line, because a hard block would leave Bob unable to commit at all.
77
- - `Stop` → `geneseed-hook learn`.
78
-
79
- Neither host has been verified live on the authoring machine. If a hook does not fire, the same rules still reach the agent through the instructions file.
80
-
81
- ### The hook shim
82
-
83
- Hooks run with your project as the working directory, so each command needs an absolute path. Rather than write the Node path and the Geneseed checkout path into every settings file, every hook points at one stable file, the **hook shim**: `~/.geneseed/bin/geneseed-hook` (`geneseed-hook.cmd` on Windows). The shim holds those two paths; your settings hold none. Set `GENESEED_HOME` to keep it somewhere other than `~/.geneseed`.
84
-
85
- Every build rewrites the shim, so moving the checkout and running one build repairs every install at once.
86
-
87
- **A stale shim fails silently.** Hooks report through their output and exit 0 on every path — that is what keeps a broken hook from breaking your tool calls. The flip side: if the shim points at a checkout that no longer exists, every hook on the machine stops working and nothing tells you. The agent simply stops getting project context and the gates stop asking. `geneseed doctor` checks the shim; a build repairs it.
88
-
89
- ```bash
90
- geneseed doctor
91
- ```
92
-
93
- See [Troubleshooting](../reference/troubleshooting.md).
94
-
95
- ### Cost
96
-
97
- The hook program is small on purpose: it adds about 14 ms to each tool call.
98
-
99
- ### Verify
49
+ ## Verify
100
50
 
101
51
  Open a session in a repo and ask the agent what it knows about the project — it should answer from the repo's docs without reading them first. Ask it to commit something: you should get a prompt before the commit runs.
52
+
53
+ What happens when a gate cannot decide, where the hooks are written, and the one file they all run through: [Hook gates, settings and the shim](hook-gates.md).
@@ -0,0 +1,38 @@
1
+ ---
2
+ group: concepts
3
+ order: 2
4
+ title: "What each host automates"
5
+ kind: "concept"
6
+ section: "Harness"
7
+ description: "Row by row, which checks each host runs in code and which stay prose."
8
+ ---
9
+ Every [host](hosts.md) gets the same content. This table is what each one lets Geneseed **automate** (check in code before an action) rather than only **ask** of the model.
10
+
11
+ | Capability | OpenCode | Claude Code | Bob | OpenClaude |
12
+ | --- | :---: | :---: | :---: | :---: |
13
+ | Instructions file | `AGENT.md` via `opencode.json` | `CLAUDE.md` | `AGENTS.md` + `rules/geneseed.md` | `CLAUDE.md` (`.openclaude/` per repo) |
14
+ | Agents · Skills · Memory · Notebook | ✅ | ✅ | ✅ | ✅ |
15
+ | Project context loaded at session start | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
16
+ | Memory written back at session end (learn) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
17
+ | Destructive git (force-push, `reset --hard`…) | 🔒 permission ask | 🪝 ask | 🪝 block¹ | 🪝 ask² |
18
+ | Secrets kept out of files | ⚙️ block⁴ | 🪝 ask | 🪝 block¹ | 🪝 ask² |
19
+ | Consent before every commit and push | 🔒 permission ask | 🪝 ask | 🪝 warning¹ | 🪝 ask² |
20
+ | Rule-or-memory write needs your call | ⚙️ speed bump³ | 🪝 ask | 🪝 warning¹ | 🪝 ask² |
21
+ | Sovereign-repo exclusions | ⚙️ plugins stand down | ✅ `claudeMdExcludes` | ✅ rules shadow stub | ✅ `claudeMdExcludes` |
22
+ | MCP server wiring | ✅ `mcp` | ✅ `mcpServers` | ✅ `mcp.json` | ✅ `mcpServers` |
23
+ | Colour themes · LSP · workflow runner · primary agent · `/`-commands | ✅ | ➖ | ➖ | ➖ |
24
+
25
+ ✅ native · ⚙️ OpenCode plugin · 🔒 `permission.bash` entry in `opencode.json` · 🪝 `settings.json` hook · ➖ no host mechanism (the rule still applies as prose).
26
+
27
+ ¹ **Bob** has its own hook contract: Claude's event names, but it ignores a hook's output on `PreToolUse`, so the only way to refuse is exit code 2. Geneseed therefore blocks only the two always-on rules (secrets, destructive git) and turns the two consent checks into a logged warning. It has no `SubagentStop` or `PreCompact` event, so learn runs on `Stop` only. **Unverified live** — there is no Bob install on the authoring machine; the rules preamble still holds if a hook does not fire.
28
+ ² **OpenClaude** is a Claude Code fork and gets Claude's hooks and verdicts verbatim, in `~/.openclaude/settings.json` (global) or `.openclaude/settings.local.json` (per repo). **Unverified live** for the same reason.
29
+ ³ OpenCode's plugin hook can only allow or throw — there is no "ask the user" — so this check stops the first such write once rather than prompting.
30
+ ⁴ The checks differ in shape: OpenCode's guard plugin blocks writes *to* private-key and credential files by path; the Claude-shaped hook looks at the *content* being written for credential-shaped strings (cloud keys, tokens, private-key blocks) and asks. A `.env` file is exempt on the hook side — that is where a secret is allowed to live.
31
+
32
+ ## The one conditional row
33
+
34
+ The **consent before commit and push** row depends on a choice you make at build time. It enforces the rule *Consent Before Push*, which belongs to the **process** doctrine pack ([Rules](rules.md)). Build without that pack, or exclude that one rule, and the commit/push question goes away — but the gate itself stays: on Claude Code and OpenClaude the `git-gate` hook is still wired (with `--no-consent`), so destructive git is still caught. Everything else in the table is always on.
35
+
36
+ One OpenCode asymmetry: Geneseed shares `opencode.json` with you and cannot tell its own `git commit*` permission entry from one you typed, so a rebuild without the process pack leaves an existing entry in place and says so instead of deleting it.
37
+
38
+ In plain terms: [Enforced vs. asked](../understand/enforced-vs-asked.md).
@@ -3,53 +3,27 @@ group: concepts
3
3
  order: 1
4
4
  title: "Hosts"
5
5
  kind: "concept"
6
+ section: "Harness"
7
+ description: "The AI coding tools Geneseed installs into, and what each one can enforce."
6
8
  ---
7
9
  A **host** is the AI coding tool Geneseed installs into — OpenCode, Claude Code, Bob or OpenClaude. Geneseed does not run the model; the host does. Geneseed writes the files the host reads (the instructions file, agents, skills) and, where the host allows it, wires small programs that run around the agent's actions. The *content* is the same on every host. What differs is how much of it the host lets Geneseed **automate** — check in code before an action — rather than only **ask** of the model in prose.
8
10
 
9
11
  > **You already know this:** one codebase, several CI providers. The pipeline does the same job everywhere, but each provider exposes different hooks, so some checks run natively on one and are a manual step on another.
10
12
 
11
- ### What is the same everywhere
13
+ ## What is the same everywhere
12
14
 
13
15
  One build renders the same text for every host: the constitution ([rules](rules.md)), the {N_AGENTS} [agents](agents.md), the {N_SKILLS} [skills](skills.md), the [memory](memory.md) and [notebook](notebook.md) conventions, and the theme's voice. No host drops an agent, a skill or the memory convention.
14
16
 
15
17
  Each host has a **global** install (in its config directory, active in every repo) and a **per-repo** install (inside one project). There is also a portable `files` bundle — a plain `Harness/` folder with an `AGENT.md` that any tool reading an instructions file can use, with no automation at all.
16
18
 
17
- ### Two engines
19
+ ## Two engines
18
20
 
19
21
  - **OpenCode** runs its own engine: Geneseed installs JavaScript **plugins** that OpenCode loads, plus permission entries in `opencode.json`. It also gets OpenCode-only extras: colour themes, [language servers](lsp.md), a workflow runner, a primary agent and `/`-commands.
20
22
  - **Claude Code**, **Bob** and **OpenClaude** share one Claude-shaped engine: Geneseed wires **hooks** into the host's `settings.json`, each calling `geneseed-hook <verb>`. See [Hooks](hooks.md).
21
23
 
22
- ### What each host automates
23
-
24
- | Capability | OpenCode | Claude Code | Bob | OpenClaude |
25
- | --- | :---: | :---: | :---: | :---: |
26
- | Instructions file | `AGENT.md` via `opencode.json` | `CLAUDE.md` | `AGENTS.md` + `rules/geneseed.md` | `CLAUDE.md` (`.openclaude/` per repo) |
27
- | Agents · Skills · Memory · Notebook | ✅ | ✅ | ✅ | ✅ |
28
- | Project context loaded at session start | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
29
- | Memory written back at session end (learn) | ⚙️ plugin | 🪝 hook | 🪝 hook¹ | 🪝 hook² |
30
- | Destructive git (force-push, `reset --hard`…) | 🔒 permission ask | 🪝 ask | 🪝 block¹ | 🪝 ask² |
31
- | Secrets kept out of files | ⚙️ block⁴ | 🪝 ask | 🪝 block¹ | 🪝 ask² |
32
- | Consent before every commit and push | 🔒 permission ask | 🪝 ask | 🪝 warning¹ | 🪝 ask² |
33
- | Rule-or-memory write needs your call | ⚙️ speed bump³ | 🪝 ask | 🪝 warning¹ | 🪝 ask² |
34
- | Sovereign-repo exclusions | ⚙️ plugins stand down | ✅ `claudeMdExcludes` | ✅ rules shadow stub | ✅ `claudeMdExcludes` |
35
- | MCP server wiring | ✅ `mcp` | ✅ `mcpServers` | ✅ `mcp.json` | ✅ `mcpServers` |
36
- | Colour themes · LSP · workflow runner · primary agent · `/`-commands | ✅ | ➖ | ➖ | ➖ |
37
-
38
- ✅ native · ⚙️ OpenCode plugin · 🔒 `permission.bash` entry in `opencode.json` · 🪝 `settings.json` hook · ➖ no host mechanism (the rule still applies as prose).
39
-
40
- ¹ **Bob** has its own hook contract: Claude's event names, but it ignores a hook's output on `PreToolUse`, so the only way to refuse is exit code 2. Geneseed therefore blocks only the two always-on rules (secrets, destructive git) and turns the two consent checks into a logged warning. It has no `SubagentStop` or `PreCompact` event, so learn runs on `Stop` only. **Unverified live** — there is no Bob install on the authoring machine; the rules preamble still holds if a hook does not fire.
41
- ² **OpenClaude** is a Claude Code fork and gets Claude's hooks and verdicts verbatim, in `~/.openclaude/settings.json` (global) or `.openclaude/settings.local.json` (per repo). **Unverified live** for the same reason.
42
- ³ OpenCode's plugin hook can only allow or throw — there is no "ask the user" — so this check stops the first such write once rather than prompting.
43
- ⁴ The checks differ in shape: OpenCode's guard plugin blocks writes *to* private-key and credential files by path; the Claude-shaped hook looks at the *content* being written for credential-shaped strings (cloud keys, tokens, private-key blocks) and asks. A `.env` file is exempt on the hook side — that is where a secret is allowed to live.
44
-
45
- ### The one conditional row
46
-
47
- The **consent before commit and push** row depends on a choice you make at build time. It enforces the rule *Consent Before Push*, which belongs to the **process** doctrine pack ([Rules](rules.md)). Build without that pack, or exclude that one rule, and the commit/push question goes away — but the gate itself stays: on Claude Code and OpenClaude the `git-gate` hook is still wired (with `--no-consent`), so destructive git is still caught. Everything else in the table is always on.
48
-
49
- One OpenCode asymmetry: Geneseed shares `opencode.json` with you and cannot tell its own `git commit*` permission entry from one you typed, so a rebuild without the process pack leaves an existing entry in place and says so instead of deleting it.
50
-
51
- ### Where to go next
24
+ ## Where to go next
52
25
 
26
+ - Which checks each host runs in code, row by row: [What each host automates](host-matrix.md).
53
27
  - What exactly each host writes to disk: [What lands on your machine](../understand/on-your-machine.md).
54
28
  - Code-enforced versus asked-of-the-model, in plain terms: [Enforced vs. asked](../understand/enforced-vs-asked.md).
55
29
  - Per-host detail for maintainers: [OpenCode](../../adapters/opencode/README.md) · [Claude Code](../../adapters/claude-code/README.md) · [Bob](../../adapters/bob/README.md) · [OpenClaude](../../adapters/openclaude/README.md).
@@ -0,0 +1,66 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 23
6
+ title: "LOOP.md, trailers and the loop branch"
7
+ description: "The loop's state file, the trailers on every commit, the loop/* branch exemption, and the console's view."
8
+ ---
9
+ ## `LOOP.md` and its trailers
10
+
11
+ `LOOP.md`, at the worktree root, is both the human-readable record (title, requirement, and the
12
+ rule that you may edit `preset` or `contracts` there) and the engine's own JSON state block. Every
13
+ closing commit carries a fixed set of trailers, read straight off that state — `Loop-Gates` only
14
+ when the unit passed at least one human gate:
15
+
16
+ ```
17
+ Loop-Iteration: <n>
18
+ Loop-Bricks: <every brick name visited this unit, deduplicated>
19
+ Loop-Risk-Declared: <score>
20
+ Loop-Risk-Actual: <score>
21
+ Loop-Threshold: <preset> <silent>/<soft>
22
+ Loop-Decision: silent | soft | blocking[ (amended)]
23
+ Loop-Tests: <what the loop was told about test state>
24
+ Loop-Gates: <every node whose gate passed this unit, deduplicated>
25
+ ```
26
+
27
+ ## The `loop/*` branch, and why merge always asks
28
+
29
+ A loop runs in its own worktree, on a branch named `loop/<slug>` — the `loop` skill creates both
30
+ with `git worktree add -b loop/<slug>` before `geneseed loop init` writes `LOOP.md` there.
31
+ While that branch is checked out and `LOOP.md` carries the engine's state marker, the git gate lets
32
+ exactly one commit/push form through without asking:
33
+
34
+ ```
35
+ git add -A && git commit -F <message_file> && git push [-u] <remote> HEAD:<loop branch>
36
+ ```
37
+
38
+ Nothing else is exempt — not `git commit -m`, not a quoted refspec, not a plain `git push` with no
39
+ explicit `HEAD:<ref>` — any other shape still asks. The exemption only ever covers a `loop/*`
40
+ branch, and never a shared one (`main`, `master`, `develop`, `development`, `release/*`,
41
+ `hotfix/*`). The **final** commit of a run — the one that removes `LOOP.md` on `$close` — is
42
+ outside the exemption too, because the loop is no longer running when it lands; that ask is your
43
+ consent to close it. **Merging a loop branch into anything else always asks, with no exception.**
44
+ The loop reports the branch to merge and the iterations that landed in "to review" — it never
45
+ merges for you.
46
+
47
+ ## Watching a loop
48
+
49
+ Every `geneseed loop init` upserts an identity row — root, branch, title, started — into a
50
+ **loop registry** at `$XDG_CONFIG_HOME/geneseed/loops.json` (default `~/.config/geneseed/loops.json`).
51
+ `LOOP.md` stays the only source of loop *state*; the registry just lets the console find a loop
52
+ without scanning every worktree on the machine. Only loops launched by this version or later are
53
+ registered, so a loop started before the registry existed won't appear until re-initialised.
54
+
55
+ The console's **Loops › Active** tab (`GET /api/loops/active`, polled every few seconds) reads that
56
+ registry and shows one card per loop: branch, status (`running`, `awaiting`, `done`, `stopped`,
57
+ `finished`, or `unreadable` if `LOOP.md` fails to parse), `iteration N / max`, and its current
58
+ node. A loop `awaiting` a decision is highlighted with what it's waiting on — the launch, the
59
+ declared score, the actual score, or a human gate (with its node) — but **the answer is given in the agent's session**, with
60
+ `geneseed loop decide`, never from the page. A finished loop (`LOOP.md` removed) is kept, muted,
61
+ for 7 days after first being seen finished, then dropped. Selecting a card draws its ring with the
62
+ current node filled, with the iteration history (declared, actual, decision, tests) underneath.
63
+
64
+ Each live card also carries a **preset picker** (`POST /api/loops/preset`) that rewrites
65
+ `LOOP.md`'s `preset` field — the same edit you could make by hand — applying from the next score
66
+ on, not retroactively. It's the tab's only write; there is no relaunch button.
@@ -0,0 +1,48 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 18
6
+ title: "Bricks and their origins"
7
+ description: "What a brick is, how templates wire bricks, and how project and global bricks override shipped ones."
8
+ ---
9
+ A **brick** is a markdown file: YAML-ish frontmatter (`name`, `description`, `effect` — `read` or
10
+ `mutate` — exactly one of `agent` or `skill`, and `outcomes`) plus a 4-10 line prose body. The
11
+ model never sees the file; `geneseed loop next` hands it the body as the prompt. A **loop
12
+ template** — a shipped template (see [Loop templates](loop-templates.md)) or one composed by hand — is the graph JSON
13
+ that wires bricks together.
14
+
15
+ Both are looked up across three origins, each able to override the one before it **by name**:
16
+
17
+ | origin | path | who writes it |
18
+ |---|---|---|
19
+ | shipped | `src/bricks/`, `src/loops/` | Geneseed itself — read by the CLI from its own source, never emitted into an install |
20
+ | global | `$XDG_CONFIG_HOME/geneseed/{bricks,loops}` (default `~/.config/geneseed/…`) | the user, for every project on this machine |
21
+ | project | `<repo>/.geneseed/{bricks,loops}` | a team, committed and shared |
22
+
23
+ Precedence is project > global > shipped. A project or global brick named `apply` replaces the
24
+ shipped `apply` everywhere a template references it, without the template changing.
25
+ `geneseed loop check` lists every override it finds, never silently.
26
+
27
+ A per-install skill exclusion is invisible to the CLI — it has no way to know which skills your
28
+ install carries. The `loop` skill covers the gap itself: when composing a graph it skips a brick
29
+ whose `skill` it doesn't have.
30
+
31
+ To add or adapt a brick, use the `brick-forge` skill — ask it, or see
32
+ [the bricks README](../../src/bricks/README.md) in
33
+ the repository.
34
+
35
+ ## Java notes for the newer bricks
36
+
37
+ - **`mutation-check`** (`legacy-tests`) prefers PIT on a Maven build: `mvn test-compile
38
+ org.pitest:pitest-maven:mutationCoverage -DtargetClasses=<fq.Class*>
39
+ -DreportsDirectory=<OS temp dir> -DtimestampedReports=false`, and needs `pitest-junit5-plugin`
40
+ on the classpath under JUnit 5; on Gradle, the `info.solidsoft.pitest` plugin's `pitest` task.
41
+ With neither configured it reports `unavailable` rather than adding the plugin itself or a
42
+ silent `pass`.
43
+ - **`fitness-define`** (`enforce-architecture-rule`) reaches for ArchUnit first on Java — a
44
+ `FreezingArchRule`, whose violation store doubles as the allowlist of today's violations —
45
+ before dependency-cruiser, import-linter, eslint-plugin-boundaries or size-limit elsewhere.
46
+ - **`migration-plan`** (`update-contract`) treats Pact or Spring Cloud Contract, where the repo
47
+ already records consumer contracts, as the check `compat-check` runs against each step rather
48
+ than only the consumers' own test suites.
@@ -0,0 +1,33 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 22
6
+ title: "Contracts and ignored deletions"
7
+ description: "The contract globs that always raise risk, the deletions a template ignores, and the glob dialect."
8
+ ---
9
+ A template may declare `contracts`: globs for the interface or schema files whose *shape* a
10
+ change can break, not just the implementation behind it — `update-contract` and
11
+ `api-endpoint` ship defaults (OpenAPI/Swagger/AsyncAPI specs, `.proto`, `.avsc`, GraphQL schemas,
12
+ Flyway/Liquibase migrations). They're copied into `LOOP.md`'s own `contracts` at `loop init`;
13
+ `loop init --contracts <globs>` appends more, and the list is editable by hand in `LOOP.md`
14
+ afterward, applying from the next score on. Touching a file any of these globs match raises the
15
+ *actual* score to at least the **api** weight (0.8) regardless of the declared card — a contract
16
+ edit is never silent.
17
+
18
+ A template may also declare `ignoreDeletions`: globs excluded from the ">20 deleted lines"
19
+ escalation rule only. `deps-upgrade` lists lockfiles this way (`**/package-lock.json`,
20
+ `**/yarn.lock`, `**/pnpm-lock.yaml`, `**/*.lock`, `**/gradle.lockfile`) because a lockfile
21
+ regenerating under a bump deletes and re-adds hundreds of lines with no risk in them;
22
+ `remove-dead-code` ignores generated output (`**/generated/**`, `**/generated-sources/**`,
23
+ `**/target/**`, `**/build/generated/**`) for the same reason. A file matched by `ignoreDeletions`
24
+ is still subject to the write-set check — it must still be declared or match a write-set glob, it
25
+ just doesn't count toward the deletion total.
26
+
27
+ Both lists, and the write set, share one hand-rolled glob dialect (no dependency — this module
28
+ imports only node builtins): `*` and `?` stay inside one path segment, `**` crosses segments and
29
+ `**/` may match zero directories (so `**/yarn.lock` also covers the root one); there is no brace
30
+ expansion (`{a,b}`). A write-set entry is matched as a glob too, but only when it has at least one
31
+ literal (non-`*`/`?`) path segment — a wildcard-only entry like `**` or `**/*.java` would
32
+ otherwise declare the whole repo as writable, so it's left to match nothing instead and the
33
+ check fails closed.
@@ -0,0 +1,30 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 21
6
+ title: "Human gates"
7
+ description: "Bricks that hold for a person whatever the score, and how ok, no and amend answer them."
8
+ ---
9
+ A brick can hold for a person regardless of preset or score, independent of the [risk machinery](loop-risk.md): its frontmatter carries `gate: human`, optionally narrowed with `gateOn: <outcomes>` (no
10
+ `gateOn` holds on every outcome the brick can report). `adr-challenge` (holds on `pass` — a
11
+ drafted ADR that survived its skeptic), `fitness-define`, `migration-plan` and `spec` all gate
12
+ this way: the loop reports `{awaiting}` with `kind: "gate"` before the edge that outcome would
13
+ normally follow is taken at all — **the gate holds the whole transition**, so nothing is scored,
14
+ committed or counted against a ring budget while it waits.
15
+
16
+ `geneseed loop decide --verdict ok|no|amend` answers it:
17
+
18
+ - **`ok`** follows the edge the brick's reported outcome actually points to. On a brick gated on
19
+ more than one outcome, a held `fail` still routes through its own edge on `ok` — which is
20
+ usually `$stop` — so `ok` on a held failure stops the loop, it doesn't wave it through.
21
+ - **`no`** stops the loop at that node.
22
+ - **`amend`** re-runs the same brick with your note appended to `LOOP.md`'s notes, so the next
23
+ run of that brick sees it; the node's re-entry (ring) budget restarts, since the amendment
24
+ changes what the unit does. A node can be amended at most 3 times per iteration — the 4th
25
+ amend stops the loop instead: three rounds that didn't converge are a conversation, not a loop.
26
+
27
+ Every closing commit that passed a gate names it under `Loop-Gates` (see [LOOP.md, trailers and the loop branch](loop-branch.md)). The console's
28
+ **Active** tab shows a gated loop as `Awaiting gate at <node>`, the same way it shows a score
29
+ `awaiting`. A gate passed in a read-only setup unit leaves its approval as a note in `LOOP.md`,
30
+ not a trailer — that unit closes without a commit.
@@ -0,0 +1,43 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 19
6
+ title: "Notes and rules"
7
+ description: "What survives an iteration in LOOP.md's notes, and the rules a template hands every brick."
8
+ ---
9
+ Two ways words travel through a loop: the notes a brick leaves in `LOOP.md`, and the rules a template hands every brick.
10
+
11
+ ## Notes: what survives an iteration
12
+
13
+ A `read` brick can find something worth keeping — a plan, a review finding, a mutation gap, a
14
+ classified CI failure — that the next brick needs but the outcome string alone can't carry.
15
+ `geneseed loop record --note "<text>"` (or `--note-file <path>` for anything multi-line or that
16
+ mentions `git commit`/`push`, which a shell argument can't carry safely) appends it to `LOOP.md`'s
17
+ notes, so it survives into the next node and the next iteration instead of evaporating with the
18
+ brick's own context. The brick never records a note itself — a brick only ever reports its
19
+ outcome, plus the path to a file it wrote; the loop skill records it with `--note-file` on the
20
+ brick's behalf. This applies to `plan` and `review` as much as to the newer bricks: any `read`
21
+ brick whose finding the next brick needs writes it to a file in the OS temp directory and reports
22
+ that file's path with the outcome.
23
+
24
+ ## `description` and `rules`: what a template is for, and what every brick must do
25
+
26
+ A template's JSON carries two prose fields, and they are never confused:
27
+
28
+ - **`description`** — the catalogue blurb: what the template is for and when to pick it. The
29
+ `loop` skill and the console read it to choose a template; no brick ever receives it.
30
+ - **`rules`** — optional, a list of one-line instructions every brick of this loop must follow
31
+ (`["Each card's intent cites the proof it is unused: …", "Generated sources do not count as
32
+ unused."]`). `geneseed loop check` refuses anything but a list of non-empty strings.
33
+
34
+ `geneseed loop next` hands the template's `rules` to every node — not only the iteration head that
35
+ reads `LOOP.md` — so a template-wide proviso (cite your deletion proof, a flaky test is never fixed
36
+ with a retry, contract edits stop for a human by design) is visible to whichever brick runs,
37
+ including `review`, which checks the diff against it. A graph with no `rules`, or an empty list,
38
+ omits the field; there is no fallback to `description`.
39
+
40
+ A template may also carry a **`category`** — one of `architecture`, `tests`, `development`,
41
+ `refactoring`, `day-to-day` — the shelf the console's Loops page files it under, in that order.
42
+ It is optional (a template without one is listed under *Other*); `geneseed loop check` refuses
43
+ any other value.
@@ -0,0 +1,36 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 20
6
+ title: "Risk, trust and validation levels"
7
+ description: "How a loop scores a change, the trust presets, and the silent, soft and blocking levels."
8
+ ---
9
+ Before a `mutate` brick runs, the loop scores the card the brick's setup declared: one risk weight
10
+ per action kind it named, and the score is the **max**, not a sum — one contract change outweighs
11
+ ten trivial renames, and ten trivial renames never add up to one. After the brick runs, the loop
12
+ re-scores against the real diff, and the diff can only raise the score, never lower it:
13
+
14
+ - a file touched outside the declared write set raises the score to at least **api** (`0.8`);
15
+ - more than 20 deleted lines raises it to at least the **delete** weight;
16
+ - touching a file listed in the loop's `contracts` raises it to at least the **api** weight.
17
+
18
+ `LOOP.md` itself is excluded from every score and every diff check — it's the engine's own
19
+ bookkeeping, rewritten on every action, never part of the work being judged.
20
+
21
+ The score is checked against a **trust preset** — `--preset` on `geneseed loop init`, editable
22
+ afterward in `LOOP.md`'s `preset` field, applying from the next score on:
23
+
24
+ | preset | silent ≤ | soft ≤ | above soft |
25
+ |---|---|---|---|
26
+ | prudent | 0.1 | 0.3 | blocking |
27
+ | balanced (default) | 0.2 | 0.6 | blocking |
28
+ | aggressive | 0.4 | 0.8 | blocking |
29
+
30
+ Three levels follow from where the score lands:
31
+
32
+ - **silent** — nothing more than the commit trailers (see [LOOP.md, trailers and the loop branch](loop-branch.md)).
33
+ - **soft** — listed under "to review" in the run's final summary; no notification during the run.
34
+ - **blocking** — the run ends. `LOOP.md` is written with `status: awaiting`, and a person has to
35
+ answer with `geneseed loop decide --verdict ok|no|amend`. Amending a verdict marks the decision
36
+ `blocking (amended)` in the trailers rather than silently rewriting it to something else.
@@ -0,0 +1,50 @@
1
+ ---
2
+ group: concepts
3
+ kind: "concept"
4
+ section: "Loops"
5
+ order: 17
6
+ title: "Loop templates"
7
+ description: "Every shipped loop template, what it is for, and the notes that matter when you pick one."
8
+ ---
9
+ The loop templates Geneseed ships. Each is a graph of [bricks](loop-bricks.md) wired for one kind of work; [Run a loop](../guides/run-a-loop.md) picks one by what you want to do.
10
+
11
+ | template | purpose | when to use |
12
+ |---|---|---|
13
+ | `bugfix` | reproduce, fix, test, review a defect | a reported bug with a reproduction step |
14
+ | `feature` | plan, then build and review in small iterations | new behaviour with no existing test pinning it |
15
+ | `refactor` | restructure behind the existing tests, no behaviour change | the tests already cover the code you're moving |
16
+ | `tdd` | plan, then write each failing test before the code that passes it | you want the test written first, every iteration |
17
+ | `legacy-tests` | pin undocumented behaviour with characterization tests, mutation-checked, production code untouched | code with no tests and no spec, before anyone risks changing it |
18
+ | `legacy-refactor` | pin current behaviour once with characterization tests, then refactor behind that net | the refactor target has no tests yet but will get changed |
19
+ | `deps-upgrade` | upgrade one package or group per iteration: read breaking changes, bump, adapt, audit | a dependency bump that needs to land as reviewable steps, not one big diff |
20
+ | `ci-repair` | triage failing CI checks for the current commit and fix one code failure per iteration | a red CI run on a `loop/*` branch that needs to go green |
21
+ | `architecture-decision` | draft one ADR per decision the requirement names, challenged by a skeptic brick, reviewed by the user | a design choice worth recording before (or instead of) any code changes |
22
+ | `enforce-architecture-rule` | encode an architecture rule as a test with an allowlist of today's violations, then fix one violation per iteration | a rule the codebase should hold everywhere but doesn't yet |
23
+ | `update-contract` | change an interface with live consumers as expand, migrate one consumer per iteration, contract | an API, schema or event change that can't break existing callers in one step |
24
+ | `spec-first-feature` | write the feature's spec (EARS criteria, ordered tasks) for review, then build one task per iteration | a feature whose acceptance criteria are worth pinning down before any code |
25
+ | `api-endpoint` | plan, build, test, write a Bruno request and security-review one endpoint change per iteration | an HTTP API feature where each endpoint needs its own exercised request and a security pass |
26
+ | `remove-dead-code` | confirm the suite is green, then delete one coherent group of unused code per iteration, test, review | code a tool (knip, ts-prune, vulture, PMD…) and a reference search say is unused |
27
+ | `fix-flaky-tests` | confirm flakiness by repeated runs, then fix one test's root cause per iteration — never a retry or a sleep | a test that fails only sometimes, not every run |
28
+
29
+ `feature` and `spec-first-feature` both end with an independent `done-check`: before `$close`, it
30
+ maps every acceptance criterion to a passing test (or a stated manual check) and reports `fail`
31
+ with what's missing rather than trusting the iterations that already ran.
32
+
33
+ `legacy-tests` and `legacy-refactor` both open on `baseline-green` — the suite must already be
34
+ green before either template pins anything, and `baseline-green` reporting `fail` stops the loop
35
+ rather than characterizing a change no one can tell from existing breakage.
36
+
37
+ `mutation-check`, inside `legacy-tests`, needs a mutation tool on the stack (Stryker, PIT, mutmut,
38
+ cargo-mutants) to prove the new characterization tests actually bite. With none configured it
39
+ reports `unavailable` rather than a silent `pass` — and still writes a note saying what it checked,
40
+ so the gap is visible in `LOOP.md` rather than just absent from it.
41
+
42
+ `ci-repair` needs CI to actually run on `loop/*` branches; `ci-triage` keys off the HEAD commit's
43
+ checks (`gh run list --commit`), and with no run for that commit it reports `done` with a note
44
+ rather than treating a branch CI never touched as green.
45
+
46
+ `deps-upgrade` lists lockfiles under `ignoreDeletions` (`**/package-lock.json`, `**/yarn.lock`,
47
+ `**/pnpm-lock.yaml`, `**/*.lock`, `**/gradle.lockfile`): a lockfile regenerating under a bump deletes
48
+ and re-adds hundreds of lines with no risk in them, so those lines stay out of the deleted-lines
49
+ count. Everything else keeps the default `delete` weight, and a lockfile outside the iteration's
50
+ write set still escalates like any other file.