geneseed 3.10.0 → 3.12.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 (227) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/DESIGN.md +1 -1
  3. package/README.md +27 -45
  4. package/SHIPPED.md +2 -2
  5. package/adapters/bob/README.md +1 -1
  6. package/adapters/claude-code/README.md +17 -12
  7. package/adapters/openclaude/README.md +1 -1
  8. package/adapters/opencode/README.md +4 -4
  9. package/adapters/opencode/plugins/geneseed-guard.js +157 -2
  10. package/bin/build-driver.mjs +2 -0
  11. package/bin/geneseed-cli.mjs +21 -0
  12. package/bin/geneseed-hook.mjs +2 -0
  13. package/docs/README.md +42 -0
  14. package/docs/_groups.json +18 -0
  15. package/docs/concepts/agents.md +44 -0
  16. package/docs/concepts/collaboration.md +62 -0
  17. package/docs/concepts/exclusions.md +55 -0
  18. package/docs/concepts/footprint.md +52 -0
  19. package/docs/concepts/foreman-mode.md +69 -0
  20. package/docs/concepts/hooks.md +101 -0
  21. package/docs/concepts/hosts.md +55 -0
  22. package/docs/concepts/loops.md +165 -0
  23. package/docs/concepts/lsp.md +50 -0
  24. package/docs/{web → concepts}/memory.md +2 -2
  25. package/docs/{web → concepts}/notebook.md +2 -2
  26. package/docs/concepts/rules.md +52 -0
  27. package/docs/concepts/skills.md +49 -0
  28. package/docs/concepts/themes.md +50 -0
  29. package/docs/extending.md +32 -21
  30. package/docs/guides/autostart.md +70 -0
  31. package/docs/guides/choose-your-setup.md +134 -0
  32. package/docs/guides/headless.md +22 -0
  33. package/docs/guides/install.md +161 -0
  34. package/docs/guides/mcp.md +195 -0
  35. package/docs/guides/migrate.md +41 -0
  36. package/docs/guides/project-context.md +87 -0
  37. package/docs/guides/run-anywhere.md +45 -0
  38. package/docs/guides/uninstall.md +51 -0
  39. package/docs/guides/upgrade.md +65 -0
  40. package/docs/guides/verify.md +65 -0
  41. package/docs/guides/wiki.md +69 -0
  42. package/docs/guides/worktree.md +47 -0
  43. package/docs/reference/about.md +7 -0
  44. package/docs/reference/cli.md +7 -0
  45. package/docs/reference/environment.md +99 -0
  46. package/docs/reference/glossary.md +37 -0
  47. package/docs/reference/opencode-plugins.md +133 -0
  48. package/docs/reference/troubleshooting.md +350 -0
  49. package/docs/understand/a-day.md +77 -0
  50. package/docs/understand/enforced-vs-asked.md +64 -0
  51. package/docs/understand/harness.md +36 -0
  52. package/docs/understand/on-your-machine.md +76 -0
  53. package/docs/web-ui.md +13 -2
  54. package/harness.config.json +1 -1
  55. package/js/README.md +27 -4
  56. package/js/build/driver.mjs +14 -8
  57. package/js/build/generate.mjs +22 -7
  58. package/js/build/render.mjs +5 -0
  59. package/js/build/source.mjs +11 -1
  60. package/js/cli-table.json +236 -1
  61. package/js/hosts/gitref.mjs +99 -0
  62. package/js/hosts/hooks.mjs +88 -1
  63. package/js/hosts/installs.mjs +21 -0
  64. package/js/hosts/mcp.mjs +1 -1
  65. package/js/hosts/settings.mjs +13 -1
  66. package/js/inspect/checks-authoring.mjs +15 -3
  67. package/js/inspect/diff.mjs +3 -0
  68. package/js/inspect/doctor.mjs +3 -2
  69. package/js/inspect/inventory.mjs +2 -1
  70. package/js/inspect/registry.mjs +20 -3
  71. package/js/inspect/status.mjs +8 -3
  72. package/js/lib/node-floor.mjs +30 -0
  73. package/js/loop/catalog.mjs +116 -0
  74. package/js/loop/cli.mjs +151 -0
  75. package/js/loop/graph.mjs +145 -0
  76. package/js/loop/score.mjs +143 -0
  77. package/js/loop/state.mjs +322 -0
  78. package/js/maintain/migrate.mjs +4 -2
  79. package/js/maintain/setup.mjs +109 -21
  80. package/js/maintain/update.mjs +4 -15
  81. package/js/ui/cli.mjs +2 -2
  82. package/js/web/actions.mjs +9 -3
  83. package/js/web/api.mjs +41 -2
  84. package/js/web/daemon.mjs +94 -4
  85. package/js/web/docs.mjs +149 -65
  86. package/js/web/handler.mjs +1 -0
  87. package/js/web/jobs.mjs +3 -1
  88. package/js/web/server.mjs +10 -5
  89. package/package.json +6 -4
  90. package/registry.json +21 -0
  91. package/src/AGENT.md.tmpl +6 -0
  92. package/src/bricks/README.md +32 -0
  93. package/src/bricks/_template.md +32 -0
  94. package/src/bricks/apply.md +17 -0
  95. package/src/bricks/baseline-green.md +17 -0
  96. package/src/bricks/bruno-test.md +16 -0
  97. package/src/bricks/ci-fix.md +17 -0
  98. package/src/bricks/deps-audit.md +14 -0
  99. package/src/bricks/docs-update.md +15 -0
  100. package/src/bricks/identify.md +20 -0
  101. package/src/bricks/lint.md +14 -0
  102. package/src/bricks/plan.md +17 -0
  103. package/src/bricks/reproduce.md +16 -0
  104. package/src/bricks/review.md +17 -0
  105. package/src/bricks/security-scan.md +17 -0
  106. package/src/bricks/test.md +14 -0
  107. package/src/doctrines/process.md +11 -8
  108. package/src/loops/bugfix.json +22 -0
  109. package/src/loops/feature.json +21 -0
  110. package/src/loops/refactor.json +20 -0
  111. package/src/postures/mentor.md +1 -0
  112. package/src/skills/brick-forge.md +46 -0
  113. package/src/skills/geneseed.md +1 -1
  114. package/src/skills/learn-mode.md +89 -0
  115. package/src/skills/loop.md +99 -0
  116. package/src/skills/pipeline.md +2 -2
  117. package/src/skills/quiz.md +2 -1
  118. package/src/skills/teach.md +2 -1
  119. package/themes/_TEMPLATE.json +3 -0
  120. package/themes/biker.json +3 -0
  121. package/themes/commentator.json +3 -0
  122. package/themes/cyberpunk.json +3 -0
  123. package/themes/gamer.json +3 -0
  124. package/themes/imperial.json +3 -0
  125. package/themes/joker.json +3 -0
  126. package/themes/marvin.json +3 -0
  127. package/themes/mean.json +3 -0
  128. package/themes/military.json +3 -0
  129. package/themes/neutral.json +3 -0
  130. package/themes/pirate.json +3 -0
  131. package/themes/sports.json +3 -0
  132. package/themes/verstappen.json +3 -0
  133. package/themes/wizard.json +3 -0
  134. package/web/dist/assets/Activity-GaaZWXTY.js +1 -0
  135. package/web/dist/assets/ActivityDetail-4t7d45Du.js +1 -0
  136. package/web/dist/assets/Dashboard-CYn7Tp16.js +2 -0
  137. package/web/dist/assets/Docs-BeFKLg2T.js +5 -0
  138. package/web/dist/assets/{GreenhouseView-D0cbCJ5m.js → GreenhouseView-C6ibc8IE.js} +1 -1
  139. package/web/dist/assets/Installs-DRYjYnxs.js +2 -0
  140. package/web/dist/assets/JournalView-1HbU1mfg.js +1 -0
  141. package/web/dist/assets/Laws-DFoG8JWB.js +3 -0
  142. package/web/dist/assets/Library-DDjgNwz_.js +1 -0
  143. package/web/dist/assets/Loops-D9VEoO0F.js +1 -0
  144. package/web/dist/assets/{Markdown-CkFyfgNf.js → Markdown-qjM2_ofS.js} +5 -5
  145. package/web/dist/assets/{OperatorHudView-CiAkAkQL.js → OperatorHudView-Bs7paWmh.js} +1 -1
  146. package/web/dist/assets/Personal-BY5n4gTw.js +1 -0
  147. package/web/dist/assets/Tabs-ho-EYD8i.js +1 -0
  148. package/web/dist/assets/api-CyMRbU2x.js +1 -0
  149. package/web/dist/assets/drawable-CLS9drMb.js +1 -0
  150. package/web/dist/assets/index-CX_hXMi5.css +1 -0
  151. package/web/dist/assets/index-Cjr7XCA3.js +2 -0
  152. package/web/dist/index.html +3 -2
  153. package/QUICKSTART.md +0 -50
  154. package/SETUP.md +0 -1148
  155. package/docs/web/_groups.json +0 -45
  156. package/docs/web/about.md +0 -6
  157. package/docs/web/adapters-claude-code.md +0 -8
  158. package/docs/web/adapters-opencode-loads.md +0 -8
  159. package/docs/web/adapters-opencode-spec.md +0 -8
  160. package/docs/web/adapters-opencode.md +0 -8
  161. package/docs/web/agents.md +0 -8
  162. package/docs/web/authoring.md +0 -11
  163. package/docs/web/autostart.md +0 -9
  164. package/docs/web/claude-hooks.md +0 -37
  165. package/docs/web/cli.md +0 -6
  166. package/docs/web/collaboration.md +0 -27
  167. package/docs/web/configure-wiki.md +0 -9
  168. package/docs/web/design.md +0 -7
  169. package/docs/web/env-knobs.md +0 -9
  170. package/docs/web/exclusions.md +0 -26
  171. package/docs/web/first-session.md +0 -28
  172. package/docs/web/footprint.md +0 -38
  173. package/docs/web/foreman-mode.md +0 -33
  174. package/docs/web/glossary.md +0 -6
  175. package/docs/web/harnesses.md +0 -30
  176. package/docs/web/headless.md +0 -9
  177. package/docs/web/ingest-docs.md +0 -9
  178. package/docs/web/install-paths.md +0 -9
  179. package/docs/web/install-quick.md +0 -35
  180. package/docs/web/lsp-overview.md +0 -37
  181. package/docs/web/mcp-claude-code.md +0 -10
  182. package/docs/web/mcp-filesystem.md +0 -9
  183. package/docs/web/mcp-gitlab.md +0 -9
  184. package/docs/web/mcp-markitdown.md +0 -9
  185. package/docs/web/mcp-overview.md +0 -34
  186. package/docs/web/mcp-trouble.md +0 -9
  187. package/docs/web/mcp-verify.md +0 -9
  188. package/docs/web/migrate.md +0 -39
  189. package/docs/web/model.md +0 -20
  190. package/docs/web/pipelines.md +0 -24
  191. package/docs/web/plugin-activity.md +0 -23
  192. package/docs/web/plugin-context.md +0 -26
  193. package/docs/web/plugin-guard.md +0 -24
  194. package/docs/web/plugin-learn.md +0 -27
  195. package/docs/web/plugin-notify.md +0 -24
  196. package/docs/web/plugin-ponytail.md +0 -23
  197. package/docs/web/plugin-setup.md +0 -7
  198. package/docs/web/plugin-workflow.md +0 -25
  199. package/docs/web/plugins.md +0 -17
  200. package/docs/web/project-context.md +0 -9
  201. package/docs/web/rules.md +0 -30
  202. package/docs/web/run-anywhere.md +0 -9
  203. package/docs/web/self-improve.md +0 -8
  204. package/docs/web/setup-choices.md +0 -64
  205. package/docs/web/skills.md +0 -8
  206. package/docs/web/themes-author.md +0 -20
  207. package/docs/web/themes.md +0 -9
  208. package/docs/web/token-footprint.md +0 -7
  209. package/docs/web/trouble.md +0 -38
  210. package/docs/web/upgrade.md +0 -9
  211. package/docs/web/verify.md +0 -30
  212. package/docs/web/wiki.md +0 -7
  213. package/docs/web/worktree.md +0 -10
  214. package/docs/wiki.md +0 -43
  215. package/web/dist/assets/Activity-BjVp522q.js +0 -1
  216. package/web/dist/assets/ActivityDetail-8ep1bspW.js +0 -1
  217. package/web/dist/assets/Dashboard-OkC_PCH6.js +0 -2
  218. package/web/dist/assets/Docs-CKPWz00o.js +0 -2
  219. package/web/dist/assets/Installs-BtGGdoTt.js +0 -2
  220. package/web/dist/assets/JournalView-Ckl4dmzR.js +0 -1
  221. package/web/dist/assets/Laws-CLpdRRk8.js +0 -3
  222. package/web/dist/assets/Library-wPPuKQrI.js +0 -1
  223. package/web/dist/assets/Personal-D8CnDo9v.js +0 -1
  224. package/web/dist/assets/Tabs-B4HNrrCs.js +0 -1
  225. package/web/dist/assets/drawable-BiwaOo6x.js +0 -1
  226. package/web/dist/assets/index-C1yil5j1.js +0 -2
  227. package/web/dist/assets/index-CDPDk2vj.css +0 -1
package/js/web/server.mjs CHANGED
@@ -28,7 +28,7 @@ import { which } from '../lib/paths.mjs';
28
28
  import { parseIntStrict } from '../lib/text.mjs';
29
29
  import { promptLine } from '../maintain/setup.mjs';
30
30
  import { webState } from './api.mjs';
31
- import { clearDaemon, openUrl, readDaemon, restartDaemon, startDaemon, statusDaemon, stopDaemon, writeDaemon } from './daemon.mjs';
31
+ import { clearDaemon, codeStamp, openUrl, readDaemon, restartDaemon, startDaemon, statusDaemon, stopDaemon, writeDaemon } from './daemon.mjs';
32
32
  import { isFile, makeHandler } from './handler.mjs';
33
33
  import { JobManager } from './jobs.mjs';
34
34
  import { spawnSync } from 'node:child_process';
@@ -137,6 +137,9 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
137
137
  printOut(' Run `geneseed setup` first — serving anyway (read-only UI).\n');
138
138
  }
139
139
  const token = randomBytes(24).toString('base64url');
140
+ // The code this server loaded, compared on every overview against the files on disk now.
141
+ const startCode = codeStamp();
142
+ state.daemonStale = () => startCode !== codeStamp();
140
143
  const holder = {};
141
144
  // The console's job list survives a reload and a restart because it is a FILE on disk,
142
145
  // not held in process memory.
@@ -156,7 +159,7 @@ export async function serve({ theme = null, port = 4747, openBrowser = true,
156
159
  if (daemon) {
157
160
  writeDaemon(state.target, {
158
161
  pid: process.pid, port: hostPort, url,
159
- token, theme: state.theme, started: Math.floor(Date.now() / 1000),
162
+ token, theme: state.theme, started: Math.floor(Date.now() / 1000), code: startCode,
160
163
  });
161
164
  }
162
165
  printOut(`[web] Geneseed UI on ${url} (theme: ${state.theme})\n`);
@@ -197,9 +200,11 @@ export async function cmdWeb(args) {
197
200
  const port = args.port === null ? 4747 : parseIntStrict(args.port);
198
201
  const openBrowser = !args.noBrowser;
199
202
  if (args.action === 'start') return startDaemon(args.theme, port, openBrowser);
200
- if (args.action === 'stop') return stopDaemon(args.theme);
201
- if (args.action === 'restart') return restartDaemon(args.theme, port, openBrowser);
202
- if (args.action === 'status') return statusDaemon(args.theme);
203
+ // Only an EXPLICIT --port scopes these three to one daemon; absent, they act on the record.
204
+ const named = args.port === null ? null : port;
205
+ if (args.action === 'stop') return stopDaemon(args.theme, named);
206
+ if (args.action === 'restart') return restartDaemon(args.theme, named, openBrowser);
207
+ if (args.action === 'status') return statusDaemon(args.theme, named);
203
208
  return serve({ theme: args.theme, port, openBrowser, daemon: args.daemonInternal });
204
209
  }
205
210
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "//": "Every field here is argued and gated in tests/unit/package_manifest.test.mjs. `files`, `bin` and `engines` each have a test that fails when reality drifts from this file; `version` mirrors harness.config.json and is gated too. Read that docblock before editing this one.",
3
3
  "name": "geneseed",
4
- "version": "3.10.0",
4
+ "version": "3.12.0",
5
5
  "description": "A portable, theme-able harness you implant once and use everywhere to grow a disciplined AI coding agent.",
6
6
  "keywords": [
7
7
  "ai",
@@ -38,7 +38,11 @@
38
38
  "themes/",
39
39
  "adapters/",
40
40
  "docs/*.md",
41
- "docs/web/",
41
+ "docs/_groups.json",
42
+ "docs/understand/",
43
+ "docs/guides/",
44
+ "docs/concepts/",
45
+ "docs/reference/",
42
46
  "web/dist/",
43
47
  "web/src/pages/Laws.jsx",
44
48
  "harness.config.json",
@@ -47,8 +51,6 @@
47
51
  "geneseed.cmd",
48
52
  "CHANGELOG.md",
49
53
  "DESIGN.md",
50
- "QUICKSTART.md",
51
- "SETUP.md",
52
54
  "SHIPPED.md"
53
55
  ],
54
56
  "devDependencies": {
package/registry.json CHANGED
@@ -134,6 +134,13 @@
134
134
  "added": "2026-06-03",
135
135
  "last_verified": "2026-09-06"
136
136
  },
137
+ "skills/brick-forge": {
138
+ "status": "experimental",
139
+ "version": "0.1.0",
140
+ "owner": "Guillaume Lemer",
141
+ "added": "2026-10-03",
142
+ "last_verified": ""
143
+ },
137
144
  "skills/bruno-collection-generator": {
138
145
  "status": "experimental",
139
146
  "version": "1.0.0",
@@ -295,6 +302,20 @@
295
302
  "added": "2026-06-07",
296
303
  "last_verified": "2026-09-06"
297
304
  },
305
+ "skills/learn-mode": {
306
+ "status": "experimental",
307
+ "version": "1.0.0",
308
+ "owner": "Guillaume Lemer",
309
+ "added": "2026-10-02",
310
+ "last_verified": ""
311
+ },
312
+ "skills/loop": {
313
+ "status": "experimental",
314
+ "version": "0.1.0",
315
+ "owner": "Guillaume Lemer",
316
+ "added": "2026-10-03",
317
+ "last_verified": ""
318
+ },
298
319
  "skills/migrate": {
299
320
  "status": "approved",
300
321
  "version": "1.0.0",
package/src/AGENT.md.tmpl CHANGED
@@ -95,6 +95,9 @@ posture: posture is the relationship register, mode is the operating register.
95
95
  <!-- LEAN:end -->
96
96
  {{MODE_BODY}}
97
97
 
98
+ If `.geneseed/learn.md` says `Learning mode: active`, read it first and follow
99
+ [learn-mode]({{DIR_SKILLS}}/learn-mode.md); a restart or compaction never approves a checkpoint.
100
+
98
101
  ---
99
102
 
100
103
  ## 1. {{LAWS}} (always in force)
@@ -238,6 +241,7 @@ the ten council seats are convened by the [council {{SKILL}}]({{DIR_SKILLS}}/cou
238
241
  | [research]({{DIR_SKILLS}}/research.md) | a question needs answers gathered and verified from the open web |
239
242
  | [teach]({{DIR_SKILLS}}/teach.md) | the user wants to be taught — a crash course, confusing material decoded, or a day-by-day path to a deadline |
240
243
  | [quiz]({{DIR_SKILLS}}/quiz.md) | the user wants what they know tested, not explained — a drill, an explain-it-back check, or a mastery claim probed for gaps |
244
+ | [learn-mode]({{DIR_SKILLS}}/learn-mode.md) | the user wants to learn while building — they design, you code what they approve |
241
245
  | [commit]({{DIR_SKILLS}}/commit.md) | staging and writing a commit |
242
246
  | [geneseed-code-review]({{DIR_SKILLS}}/geneseed-code-review.md) | reviewing a diff or PR |
243
247
  | [review-response]({{DIR_SKILLS}}/review-response.md) | acting on review feedback you have received |
@@ -262,6 +266,8 @@ the ten council seats are convened by the [council {{SKILL}}]({{DIR_SKILLS}}/cou
262
266
  | [council]({{DIR_SKILLS}}/council.md) | a decision, change, or discussion needs debating from several points of view before committing |
263
267
  | [workflow]({{DIR_SKILLS}}/workflow.md) | deterministic, code-driven orchestration of subagents (fan-out, find→verify, phased handoff) and the host exposes a workflow tool |
264
268
  | [pipeline]({{DIR_SKILLS}}/pipeline.md) | foreman mode triages a substantial task, or the user asks to run a crew (analyst → developer → tester) on one, isolated in its own worktree and merged on mechanical proof |
269
+ | [loop]({{DIR_SKILLS}}/loop.md) | the user asks to run a loop |
270
+ | [brick-forge]({{DIR_SKILLS}}/brick-forge.md) | a new or adapted loop brick |
265
271
  | [wiki]({{DIR_SKILLS}}/wiki.md) | consulting or growing the user's machine-wide knowledge base declared in `wiki.jsonc` (§8) |
266
272
  | [herdr]({{DIR_SKILLS}}/herdr.md) | running inside a [herdr](https://herdr.dev) pane (`HERDR_ENV=1`) and a task needs another pane — a sibling server, a watched build, a spawned agent |
267
273
  | [rule]({{DIR_SKILLS}}/rule.md) | anything the user wants to outlive this session — a standing rule of their own (§1) or a durable fact to remember (§5); also a recurring {{MEMORY}} lesson due for promotion |
@@ -0,0 +1,32 @@
1
+ # Bricks
2
+
3
+ A brick is one node of a loop graph: a single prompt, handed to one agent or skill, that reports
4
+ back one of a declared set of outcomes. `geneseed loop next` reads the current node's brick and
5
+ hands its body to the model verbatim — the model never sees this file as a file, only as the
6
+ instructions inside it.
7
+
8
+ A brick is a markdown file, `<name>.md`, with flat YAML-ish frontmatter (`name`, `description`,
9
+ `effect`, exactly one of `agent` or `skill`, `outcomes`) and a plain-prose body. See
10
+ `_template.md` for the field-by-field shape.
11
+
12
+ ## The three origins
13
+
14
+ A brick's name is looked up across three levels, each one able to override the level before it
15
+ by name:
16
+
17
+ | origin | path | who writes it |
18
+ |---|---|---|
19
+ | shipped | `src/bricks/` (this directory) | Geneseed itself |
20
+ | global | `$XDG_CONFIG_HOME/geneseed/bricks/` | the user, for every project on this machine |
21
+ | project | `<repo>/.geneseed/bricks/` | a team, committed and shared |
22
+
23
+ A global or project brick named `apply` replaces the shipped `apply` everywhere a loop template
24
+ references it — the template does not have to change, and `geneseed loop check` reports the
25
+ override rather than hiding it.
26
+
27
+ ## Writing one
28
+
29
+ Start from `_template.md`, or ask the `brick-forge` skill to draft one for an agent or skill you
30
+ already have. Keep the body to 4-10 lines of direct instruction, and end it with how the model
31
+ should choose among the outcomes you declared — that sentence is what turns a vague brief into a
32
+ loop that actually terminates.
@@ -0,0 +1,32 @@
1
+ <!--
2
+ A brick template — copy this file to `<name>.md` (kebab-case, matching the `name:` field
3
+ below) under `bricks/` at whichever level you are authoring for: shipped (this package's
4
+ `src/bricks/`), global ($XDG_CONFIG_HOME/geneseed/bricks/), or project (<repo>/.geneseed/bricks/).
5
+ A later level overrides an earlier one BY NAME. Leading-underscore files (like this one) and
6
+ README.md are never loaded as bricks.
7
+
8
+ Everything below the closing `---` is the brick's BODY: the prompt `geneseed loop next` hands
9
+ the agent, verbatim, plus the card fields it receives. No double-brace substitution tokens in
10
+ the body — the loop CLI reads this file raw and hands it straight to the model, unrendered.
11
+ -->
12
+ ---
13
+ name: my-brick
14
+ # One line, shown wherever the catalogue is listed. Not the instructions themselves.
15
+ description: One line describing what this brick does.
16
+ # `read` never touches a file — the engine does not score or diff its iteration.
17
+ # `mutate` may change files — its diff is scored against the declared card before commit.
18
+ effect: read
19
+ # Exactly one of agent OR skill (never both, never neither) — who carries out the body below.
20
+ # `agent: <name>` names a spec under `src/agents/`.
21
+ agent: tester
22
+ # `skill: <name>` names a spec under `src/skills/` instead of an agent — delete `agent:` above
23
+ # if you use this.
24
+ # skill: some-skill
25
+ # Every outcome the body can report, comma-separated — these become the edge labels a loop
26
+ # template routes on (`{from, on: "<outcome>", to}`). A loop template's graph check requires
27
+ # exactly one edge per outcome declared here.
28
+ outcomes: pass, fail
29
+ ---
30
+ Say, in direct instructions, what the agent or skill should do with the card it receives — 4 to
31
+ 10 lines, no more. End with exactly how to choose between the declared outcomes, so the model's
32
+ last read is the decision it has to make.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: apply
3
+ description: Implement the current card's intent, touching only its declared write set.
4
+ effect: mutate
5
+ agent: developer
6
+ outcomes: pass
7
+ ---
8
+ Implement the card's intent exactly, touching only the files in its `writeSet`. If the card
9
+ carries an `amend`, that supersedes the original intent — follow the amendment, not the plan it
10
+ replaced.
11
+
12
+ Make no unrelated edits: no drive-by rename, no incidental cleanup, no touching a file the card
13
+ did not declare. If the change genuinely needs a file outside the write set, stop and report that
14
+ rather than widening scope unasked — the diff is scored against the declared set, not your
15
+ judgement of what else looked wrong.
16
+
17
+ Report `pass` once the change is made, with a short account of what changed and where.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: baseline-green
3
+ description: Confirm the suite and linter are green before the loop changes anything.
4
+ effect: read
5
+ agent: tester
6
+ outcomes: pass, fail
7
+ ---
8
+ Run this project's full test suite and its linter, unchanged — no fix, no skip, no retry with
9
+ different flags. This is the loop's starting line, not a chance to tidy up first.
10
+
11
+ Report `pass` only if every test and the linter both exit clean. Include the raw command output
12
+ in your report either way, so a `fail` carries the actual failure rather than a summary of it.
13
+
14
+ Report `fail` on the first red suite or linter run, and stop there: a loop that starts on a red
15
+ baseline cannot tell its own changes apart from pre-existing breakage.
16
+
17
+ Never edit, create or delete any file: this brick only reads.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: bruno-test
3
+ description: Write or update Bruno requests for the endpoints this iteration touched.
4
+ effect: mutate
5
+ skill: bruno-test-writer
6
+ outcomes: pass, fail
7
+ ---
8
+ Follow the bruno-test-writer skill for every endpoint this iteration's diff added or changed.
9
+ Touch only the Bruno collection — new or updated `.bru` requests and their expectations — never
10
+ the application code.
11
+
12
+ Report `pass` once every touched endpoint has a request that exercises it and asserts on the
13
+ response.
14
+
15
+ Report `fail` if an endpoint cannot be exercised this way (missing auth fixture, no reachable
16
+ instance, an endpoint the diff removed), naming which one and why.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: ci-fix
3
+ description: Fix the failing CI check named in the card.
4
+ effect: mutate
5
+ skill: ci-fix
6
+ outcomes: pass, fail
7
+ ---
8
+ Follow the ci-fix skill against the failing check the card names — read its actual log, not a
9
+ guess from the check's title, before changing anything.
10
+
11
+ Touch only what that failure requires; this is a repair, not a chance to improve the pipeline
12
+ along the way.
13
+
14
+ Report `pass` once the named check is fixed and green.
15
+
16
+ Report `fail` if the check cannot be fixed from this repo alone (an infra outage, a flake with no
17
+ reproducible cause, a required secret that is missing), naming why.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: deps-audit
3
+ description: Audit this iteration's dependency changes for known vulnerabilities.
4
+ effect: read
5
+ skill: deps-audit
6
+ outcomes: pass, fail
7
+ ---
8
+ Follow the deps-audit skill against the dependency manifest this iteration's diff touched (or the
9
+ whole manifest, if nothing else scopes it). Never edit any file; this brick only observes.
10
+
11
+ Report `pass` if the audit finds nothing at high severity or above.
12
+
13
+ Report `fail` on any finding at high severity or above, naming the package, the version, the
14
+ advisory, and the fix the skill recommends (upgrade, pin, or removal).
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: docs-update
3
+ description: Update the documentation this iteration's diff made stale.
4
+ effect: mutate
5
+ agent: docs
6
+ outcomes: pass
7
+ ---
8
+ Read this iteration's diff and find every doc it made stale: a changed signature, a renamed
9
+ flag, a moved file, a behaviour the README or docs still describe the old way.
10
+
11
+ Update only those docs, only to match what the diff actually changed. Do not rewrite unrelated
12
+ prose, reorganize a page, or fix an unrelated staleness you happen to notice while in there.
13
+
14
+ Report `pass` once every doc the diff touched is back in sync, naming the files you changed — or
15
+ that none needed it, if the diff left nothing stale.
@@ -0,0 +1,20 @@
1
+ ---
2
+ name: identify
3
+ description: Choose the next iteration of the loop, or declare the requirement done.
4
+ effect: read
5
+ agent: explorer
6
+ outcomes: more, done
7
+ ---
8
+ Read the requirement and the loop's history (LOOP.md, `git log --format=%(trailers)` on this
9
+ branch). If the requirement is fully met and the suite is green, report `done`.
10
+
11
+ Otherwise pick the SMALLEST next change that moves the requirement forward and can be tested on
12
+ its own. Report `more` with a card, as JSON:
13
+ {"intent": "<one line>", "writeSet": ["<every file you expect to touch>"],
14
+ "actions": ["<each of: format, imports, rename, logic, new-file, api, delete, architecture>"]}
15
+
16
+ Declare every action honestly: the diff is scored again before commit, and anything outside the
17
+ write set or under-declared escalates to a blocking stop. If LOOP.md's notes say the previous
18
+ attempt was re-split, make this card strictly smaller than that one.
19
+
20
+ Never edit, create or delete any file: this brick only reads.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: lint
3
+ description: Run the project's linter alone, without the test suite.
4
+ effect: read
5
+ agent: tester
6
+ outcomes: pass, fail
7
+ ---
8
+ Run this project's linter only — not the test suite, which is `test`'s job. Never edit any file;
9
+ this brick only observes.
10
+
11
+ Report `pass` if the linter exits clean.
12
+
13
+ Report `fail` otherwise, with the raw linter output (every violation, not a count or a summary)
14
+ so the next `apply` can act on the actual finding.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: plan
3
+ description: Split the requirement into an ordered list of iterations before any code changes.
4
+ effect: read
5
+ agent: architect
6
+ outcomes: pass
7
+ ---
8
+ Read the requirement and survey the code it touches. Split the work into an ordered list of
9
+ small iterations, each one sized to a single `identify` card — one testable change apiece.
10
+
11
+ Do not edit any code; this brick only plans it. Report `pass` with a card whose intent carries
12
+ the ordered list, one iteration per line, so it lands in LOOP.md's notes for `identify` to work
13
+ through one at a time:
14
+ {"intent": "<iteration 1>\n<iteration 2>\n...", "writeSet": [], "actions": []}
15
+
16
+ If the requirement cannot be split — it is already one atomic change — say so in the intent and
17
+ let the loop proceed with a single iteration.
@@ -0,0 +1,16 @@
1
+ ---
2
+ name: reproduce
3
+ description: Write the smallest test that reproduces the bug and watch it fail.
4
+ effect: mutate
5
+ agent: tester
6
+ outcomes: pass, fail
7
+ ---
8
+ Write the smallest possible test that demonstrates the bug the requirement describes. Run it and
9
+ confirm it fails, and that it fails FOR THE STATED REASON — not for an unrelated error.
10
+
11
+ Touch only the new test file; do not change any production code here, and do not try to make the
12
+ test pass. A reproduction that already passes proves nothing.
13
+
14
+ Report `pass` once a failing reproduction exists, with the test's path and the failure it shows.
15
+ Report `fail` if the bug cannot be reproduced from the requirement as written — say what you
16
+ tried and why each attempt did not fail the way the requirement claims.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: review
3
+ description: Review this iteration's diff against the card it was supposed to implement.
4
+ effect: read
5
+ agent: reviewer
6
+ outcomes: pass, fail
7
+ ---
8
+ Read the card's intent and write set, then read the diff this iteration actually produced. Check
9
+ that the diff matches the intent, stays inside the declared write set, and does not smuggle in an
10
+ unrelated change.
11
+
12
+ Never edit any file — findings go back to `apply`, which makes the fix.
13
+
14
+ Report `pass` if the diff is a faithful, scoped implementation of the card.
15
+
16
+ Report `fail` with concrete findings — `file:line`, what is wrong, what to do instead — if the
17
+ diff drifts from the intent, touches an undeclared file, or leaves an obvious defect behind.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: security-scan
3
+ description: Security review of this iteration's diff.
4
+ effect: read
5
+ agent: security
6
+ outcomes: pass, fail
7
+ ---
8
+ Read this iteration's diff and review it for security issues: injected input reaching a
9
+ dangerous sink, a widened trust boundary, a secret written to disk or logs, a weakened auth or
10
+ permission check — anything that would not survive a real security review.
11
+
12
+ Never edit any file; this brick only observes and reports.
13
+
14
+ Report `pass` if nothing in the diff raises a security concern.
15
+
16
+ Report `fail` with each finding as `file:line`, the concrete risk, and the fix — severe enough to
17
+ block the iteration, not a style nit that belongs in `review` instead.
@@ -0,0 +1,14 @@
1
+ ---
2
+ name: test
3
+ description: Run the suite and linter over this iteration's change.
4
+ effect: read
5
+ agent: tester
6
+ outcomes: pass, fail
7
+ ---
8
+ Run this project's full test suite and its linter over the current change. Never edit any file —
9
+ this brick only observes; a fix belongs in `apply`, not here.
10
+
11
+ Report `pass` only if both exit clean.
12
+
13
+ Report `fail` otherwise, with the raw failures (not a paraphrase) so `apply` can act on the actual
14
+ error rather than your summary of it. Name every failing test and lint violation you saw.
@@ -85,7 +85,9 @@ time — a personal feature branch included. A one-time approval is not standing
85
85
  consent. Consent may cover a **named batch**: "commit as you go on this branch"
86
86
  stands for commits on that branch until the session ends or the scope changes; a
87
87
  new session, a new branch, or a widened scope re-asks. Push earns no such default
88
- and stays per-ask unless granted in the same named form. Before each, present in
88
+ and stays per-ask unless granted in the same named form. A launched loop's batch
89
+ covers commit and push on its own `loop/*` branch; merging that branch into a
90
+ shared one never is. Before each, present in
89
91
  order (1) a plain-language summary of what changed and why and (2) the exact
90
92
  commit message you intend to use, then wait. Never push on your own initiative.
91
93
  On a **shared branch** — `main`, `master`, `develop`, `development`, a
@@ -97,13 +99,14 @@ through the git-rescue {{SKILL}} behind a backup. The host gates commit and push
97
99
  the tool boundary too, so this consent cannot be lost to a sticky allowlist.
98
100
  <!-- LEAN:else -->
99
101
  Recording and sharing code is consented, never unilateral: **every** `git commit` and
100
- `git push` needs the user's **explicit acceptance**, on every branch, every time; a
101
- one-time approval is not standing consent. A named batch ("commit as you go") stands until
102
- the session ends or scope changes; push earns no default. Before each, present the plain
103
- summary of what changed and why, the exact commit message, then wait. Shared branches —
104
- `main`, `master`, `develop`, `development`, `release`/`hotfix`, any you are unsure of —
105
- take the same gate. Never force-push, hard-reset, or rebase one: undo with a revert commit
106
- (git-rescue {{SKILL}} for a legitimate rewrite). The host gates both at the tool boundary.
102
+ `git push` needs **explicit acceptance**, every branch, every time; one-time approval is
103
+ not standing consent. A named batch ("commit as you go") stands until the session ends or
104
+ scope changes; push earns no default. A launched loop's batch covers commit and push on
105
+ its own `loop/*` branch only; merging it never. Show the plain summary and the exact
106
+ commit message before each, then wait. Shared branches — `main`, `master`, `develop`,
107
+ `development`, `release`/`hotfix`, any unsure — take the same gate. Never force-push,
108
+ hard-reset, or rebase one: undo with a revert commit (git-rescue {{SKILL}} for a
109
+ legitimate rewrite). The host gates both at the tool boundary.
107
110
  <!-- LEAN:end -->
108
111
 
109
112
  ### {{DOCTRINE:bound-the-loop}} Bound the Loop
@@ -0,0 +1,22 @@
1
+ {
2
+ "name": "bugfix",
3
+ "description": "Reproduce the bug with a failing test, then iterate: apply the fix, test, and review, until the requirement is met and the reproduction passes.",
4
+ "nodes": ["reproduce", "identify", "apply", "test", "review"],
5
+ "start": "reproduce",
6
+ "edges": [
7
+ { "from": "reproduce", "on": "pass", "to": "identify" },
8
+ { "from": "reproduce", "on": "fail", "to": "$stop" },
9
+ { "from": "identify", "on": "more", "to": "apply" },
10
+ { "from": "identify", "on": "done", "to": "$close" },
11
+ { "from": "apply", "on": "pass", "to": "test" },
12
+ { "from": "test", "on": "fail", "to": "apply" },
13
+ { "from": "test", "on": "pass", "to": "review" },
14
+ { "from": "review", "on": "pass", "to": "identify" },
15
+ { "from": "review", "on": "fail", "to": "apply" }
16
+ ],
17
+ "loops": [
18
+ { "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
19
+ { "name": "apply-test", "nodes": ["apply", "test"], "max": 5 },
20
+ { "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
21
+ ]
22
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "feature",
3
+ "description": "Plan the feature into ordered iterations, then build each one: apply, test, and review, until the plan is complete.",
4
+ "nodes": ["plan", "identify", "apply", "test", "review"],
5
+ "start": "plan",
6
+ "edges": [
7
+ { "from": "plan", "on": "pass", "to": "identify" },
8
+ { "from": "identify", "on": "more", "to": "apply" },
9
+ { "from": "identify", "on": "done", "to": "$close" },
10
+ { "from": "apply", "on": "pass", "to": "test" },
11
+ { "from": "test", "on": "pass", "to": "review" },
12
+ { "from": "test", "on": "fail", "to": "apply" },
13
+ { "from": "review", "on": "pass", "to": "identify" },
14
+ { "from": "review", "on": "fail", "to": "apply" }
15
+ ],
16
+ "loops": [
17
+ { "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
18
+ { "name": "apply-test", "nodes": ["apply", "test"], "max": 5 },
19
+ { "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
20
+ ]
21
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "refactor",
3
+ "description": "Confirm the suite is green before touching anything, then iterate on the shape of the code alone. Tests are not edited by this template — a refactor that needs a different test is a behaviour change, not a refactor.",
4
+ "nodes": ["baseline-green", "identify", "apply", "test"],
5
+ "start": "baseline-green",
6
+ "edges": [
7
+ { "from": "baseline-green", "on": "pass", "to": "identify" },
8
+ { "from": "baseline-green", "on": "fail", "to": "$stop" },
9
+ { "from": "identify", "on": "more", "to": "apply" },
10
+ { "from": "identify", "on": "done", "to": "$close" },
11
+ { "from": "apply", "on": "pass", "to": "test" },
12
+ { "from": "test", "on": "pass", "to": "identify" },
13
+ { "from": "test", "on": "fail", "to": "apply" }
14
+ ],
15
+ "loops": [
16
+ { "name": "iterations", "nodes": ["identify", "apply", "test"], "max": 20, "iteration": true },
17
+ { "name": "apply-test", "nodes": ["apply", "test"], "max": 5 }
18
+ ],
19
+ "weights": { "logic": 0.6 }
20
+ }
@@ -9,3 +9,4 @@ to finish the task.
9
9
  for yourself ({{ONTOLOGY}}: {{ONT_TELOS}}) — a wrong turn is used to teach, not just reversed.
10
10
  - **What it will not do.** Hand over a black-box result, or optimise for speed at the
11
11
  cost of your understanding. If you want just-the-answer, say so — or pick Expert.
12
+ To design while it writes the code, turn on the learn-mode {{SKILL}}.
@@ -0,0 +1,46 @@
1
+ # {{SKILL}}: brick-forge
2
+
3
+ > {{DESC_BRICK_FORGE}}
4
+
5
+ **Trigger:** the user wants a new loop brick, or to adapt an existing one to their stack — "make
6
+ a brick for…", "our tests run differently, change the `test` brick", "the loop needs a step
7
+ that…".
8
+
9
+ ## Procedure
10
+
11
+ 1. **Interview, one question at a time:**
12
+ - **name** — kebab-case, the file stem.
13
+ - **what it does** — one line; it becomes `description`.
14
+ - **effect** — does it ever create, edit or delete a file? Yes → `mutate`; never → `read`;
15
+ unsure → `mutate`. A `read` brick that writes stops the loop.
16
+ - **who runs it** — exactly one of an `agent` (one of the {{AGENTS}}) or a `skill`.
17
+ - **outcomes** — every result it can report, comma-separated. Each becomes an edge label a
18
+ loop graph must route (`{from, on: "<outcome>", to}`).
19
+ - **level** — project `<repo>/.geneseed/bricks/` (committed, shared with the team), global
20
+ `$XDG_CONFIG_HOME/geneseed/bricks/` (default `~/.config/geneseed/bricks/`, every project on
21
+ this machine), or shipped `src/bricks/` — only inside the Geneseed repository itself.
22
+ 2. **Write `<level>/<name>.md`**, the file stem equal to `name`:
23
+
24
+ ```
25
+ ---
26
+ name: <kebab-name>
27
+ description: <one line>
28
+ effect: read | mutate
29
+ agent: <agent> (or skill: <skill> — exactly one of the two)
30
+ outcomes: <a>, <b>
31
+ ---
32
+ <4-10 lines of direct instructions, ending with exactly how to choose among the outcomes>
33
+ ```
34
+
35
+ No double-brace tokens in the body: the loop hands it to the model raw.
36
+ 3. **Overriding by name** — a project or global brick named like a shipped one replaces it in
37
+ every template. That is allowed; say so to the user. `geneseed loop check` lists overrides under `overridden`.
38
+ 4. **Check it:** `geneseed loop check --brick <path>` (this file alone), then
39
+ `geneseed loop check` from the repository (the whole catalogue, including every template that
40
+ now routes through it). Fix every listed problem and re-run both.
41
+
42
+ ## Done when
43
+
44
+ - The brick file exists at the chosen level, and both checks print `ok: true`.
45
+
46
+ <!-- INCLUDE: skills/_self-improvement.md -->
@@ -8,7 +8,7 @@
8
8
  1. **Locate.** Run `geneseed status --json` first: `installs` lists every install on this machine — host, scope, root, state, theme, footprint, posture, mode, packs, excluded rules — and `rebuild`, the command that reproduces each one exactly. `geneseed` not on PATH → ask the user before using `npx geneseed` (it downloads the package), and prefix every command below the same way. Still nothing → look for a host root file: `~/.config/opencode/AGENT.md` or `.opencode/AGENT.md` (OpenCode), `~/.claude/CLAUDE.md` or `.claude/` (Claude Code), `.openclaude/` (OpenClaude), `AGENTS.md` beside `.bob/` (Bob). None → say so; never install to "fix" it.
9
9
  2. **Read state** with the read-only verbs, cheapest first ({{DOCTRINE:context-economy}}): `geneseed status --json`, `geneseed version`, `geneseed catalog` (optionally `agents|skills|laws|ontology|doctrines`), `geneseed doctor`, `geneseed diff`, `geneseed mcp`, `geneseed memory list`, `geneseed exclude list`.
10
10
  3. **Read a piece** from disk, not from recall ({{LAW:verify-before-asserting}}): `<root>/agents/<name>.md`, `<root>/skills/<name>/SKILL.md`, `<root>/memory/`, `<root>/notebook/`. The {{ONTOLOGY}}, the {{LAWS}} and the active {{DOCTRINES}} are numbered `## N. …` sections of the install's root file.
11
- 4. **Change an install only when the user asked for that change** ({{LAW:one-intent-one-act}}). Take that install's `rebuild` command from step 1, edit only the flag the user named (add it if the command omits it — `--posture` and `--mode` are left out at their defaults) — `--theme`, `--footprint lean|full`, `--posture`, `--mode direct|foreman`, `--doctrines craft,rigor|none`, `--exclude-rules "process 7"|none` — dry-run it first by running the same flags through `geneseed validate`, show the command, and run it once the user agrees. Never rebuild from a bare `geneseed build`: every omitted flag resets that setting to the generator default. Confirm with `geneseed status`.
11
+ 4. **Change an install only when the user asked for that change** ({{LAW:one-intent-one-act}}). Take that install's `rebuild` command from step 1, edit only the flag the user named (add it if the command omits it — `--posture`, `--mode` and `--trust` are left out at their defaults) — `--theme`, `--footprint lean|full`, `--posture`, `--mode direct|foreman`, `--trust prudent|balanced|aggressive`, `--doctrines craft,rigor|none`, `--exclude-rules "process 7"|none` — dry-run it first by running the same flags through `geneseed validate`, show the command, and run it once the user agrees. Never rebuild from a bare `geneseed build`: every omitted flag resets that setting to the generator default. Confirm with `geneseed status`.
12
12
  5. **Other writes also need the user's word:** `geneseed memory rm <name>`, `geneseed exclude add|remove <path>`, `geneseed web start|stop`, `geneseed uninstall --target <root> --yes`. Personal rules and the profile belong to their own {{SKILLS}}; do not edit `user-rules.md` or `PROFILE.md` from here.
13
13
  6. **Never on your own initiative:** `geneseed setup` (interactive only), `geneseed upgrade`, `geneseed update`, `geneseed bootstrap`, `geneseed sync-self`, `geneseed rebuild-all`, `geneseed migrate`, `geneseed link`, `geneseed unlink`. `learn`, `context` and the `*-gate` verbs are `geneseed-hook` verbs the host's hooks run — never run them by hand.
14
14
  7. Directory and section names are plain English in every theme; only prose changes. Do not search by flavour words.