geneseed 3.12.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.
- package/CHANGELOG.md +121 -0
- package/README.md +2 -2
- package/SHIPPED.md +1 -1
- package/adapters/bob/README.md +1 -1
- package/adapters/claude-code/README.md +1 -1
- package/adapters/openclaude/README.md +1 -1
- package/adapters/opencode/README.md +3 -3
- package/docs/README.md +41 -22
- package/docs/concepts/agents.md +3 -1
- package/docs/concepts/collaboration.md +3 -1
- package/docs/concepts/exclusions.md +4 -2
- package/docs/concepts/footprint.md +3 -1
- package/docs/concepts/foreman-mode.md +3 -1
- package/docs/concepts/hook-gates.md +61 -0
- package/docs/concepts/hooks.md +8 -56
- package/docs/concepts/host-matrix.md +38 -0
- package/docs/concepts/hosts.md +6 -32
- package/docs/concepts/loop-branch.md +66 -0
- package/docs/concepts/loop-bricks.md +48 -0
- package/docs/concepts/loop-contracts.md +33 -0
- package/docs/concepts/loop-gates.md +30 -0
- package/docs/concepts/loop-notes.md +43 -0
- package/docs/concepts/loop-risk.md +36 -0
- package/docs/concepts/loop-templates.md +50 -0
- package/docs/concepts/loops.md +24 -116
- package/docs/concepts/lsp.md +2 -0
- package/docs/concepts/memory.md +3 -1
- package/docs/concepts/notebook.md +3 -1
- package/docs/concepts/rules.md +4 -2
- package/docs/concepts/skills.md +3 -1
- package/docs/concepts/themes.md +3 -1
- package/docs/extending.md +23 -8
- package/docs/guides/autostart.md +3 -1
- package/docs/guides/choose-your-setup.md +5 -80
- package/docs/guides/headless.md +5 -3
- package/docs/guides/install-agent-md.md +37 -0
- package/docs/guides/install-bob.md +20 -0
- package/docs/guides/install-claude-code.md +22 -0
- package/docs/guides/install-clone.md +34 -0
- package/docs/guides/install-openclaude.md +25 -0
- package/docs/guides/install-opencode.md +35 -0
- package/docs/guides/install-scripted.md +21 -0
- package/docs/guides/install.md +9 -118
- package/docs/guides/loop-finish.md +54 -0
- package/docs/guides/loop-running.md +66 -0
- package/docs/guides/loop-which-template.md +35 -0
- package/docs/guides/mcp-filesystem.md +41 -0
- package/docs/guides/mcp-gitlab.md +66 -0
- package/docs/guides/mcp-markitdown.md +36 -0
- package/docs/guides/mcp.md +8 -137
- package/docs/guides/migrate.md +3 -1
- package/docs/guides/project-context.md +4 -2
- package/docs/guides/read-non-markdown.md +17 -0
- package/docs/guides/run-a-loop.md +64 -0
- package/docs/guides/run-anywhere.md +2 -0
- package/docs/guides/setup-doctrines.md +55 -0
- package/docs/guides/setup-footprint.md +48 -0
- package/docs/guides/uninstall.md +3 -1
- package/docs/guides/upgrade.md +3 -1
- package/docs/guides/verify.md +3 -1
- package/docs/guides/wiki.md +3 -1
- package/docs/guides/worktree.md +3 -1
- package/docs/reference/about.md +3 -1
- package/docs/reference/cli.md +2 -0
- package/docs/reference/env-context.md +40 -0
- package/docs/reference/environment.md +10 -59
- package/docs/reference/glossary.md +3 -1
- package/docs/reference/loop-actions.md +20 -0
- package/docs/reference/opencode-plugins.md +14 -118
- package/docs/reference/plugin-activity.md +20 -0
- package/docs/reference/plugin-context.md +27 -0
- package/docs/reference/plugin-guard.md +27 -0
- package/docs/reference/plugin-learn.md +27 -0
- package/docs/reference/plugin-notify.md +20 -0
- package/docs/reference/plugin-ponytail.md +19 -0
- package/docs/reference/plugin-workflow.md +25 -0
- package/docs/reference/troubleshoot-doctor.md +50 -0
- package/docs/reference/troubleshoot-hooks.md +99 -0
- package/docs/reference/troubleshoot-install.md +108 -0
- package/docs/reference/troubleshoot-tools.md +56 -0
- package/docs/reference/troubleshoot-update.md +23 -0
- package/docs/reference/troubleshoot-web.md +66 -0
- package/docs/reference/troubleshooting.md +13 -337
- package/docs/understand/a-day.md +3 -1
- package/docs/understand/enforced-vs-asked.md +3 -1
- package/docs/understand/harness.md +2 -0
- package/docs/understand/machine-bob.md +17 -0
- package/docs/understand/machine-claude.md +35 -0
- package/docs/understand/machine-opencode.md +36 -0
- package/docs/understand/on-your-machine.md +12 -55
- package/docs/understand/take-it-out.md +13 -0
- package/docs/web-ui.md +35 -15
- package/harness.config.json +1 -1
- package/js/README.md +11 -3
- package/js/cli-table.json +27 -1
- package/js/hosts/mcp.mjs +1 -1
- package/js/hosts/native.mjs +43 -5
- package/js/inspect/checks-build.mjs +28 -0
- package/js/loop/catalog.mjs +12 -1
- package/js/loop/cli.mjs +28 -6
- package/js/loop/graph.mjs +18 -0
- package/js/loop/registry.mjs +196 -0
- package/js/loop/score.mjs +45 -6
- package/js/loop/state.mjs +125 -11
- package/js/maintain/setup.mjs +1 -1
- package/js/web/actions.mjs +25 -0
- package/js/web/api.mjs +13 -0
- package/js/web/docs.mjs +64 -12
- package/js/web/routes.mjs +5 -1
- package/package.json +1 -1
- package/src/agents/explorer.md +2 -2
- package/src/agents/researcher.md +3 -3
- package/src/bricks/README.md +3 -1
- package/src/bricks/adr-challenge.md +20 -0
- package/src/bricks/adr-draft.md +15 -0
- package/src/bricks/characterize.md +17 -0
- package/src/bricks/ci-fix.md +2 -1
- package/src/bricks/ci-triage.md +20 -0
- package/src/bricks/compat-check.md +16 -0
- package/src/bricks/done-check.md +16 -0
- package/src/bricks/fitness-define.md +22 -0
- package/src/bricks/flake-check.md +17 -0
- package/src/bricks/flake-repro.md +18 -0
- package/src/bricks/identify.md +6 -3
- package/src/bricks/migration-plan.md +21 -0
- package/src/bricks/mutation-check.md +18 -0
- package/src/bricks/plan.md +6 -6
- package/src/bricks/red-test.md +16 -0
- package/src/bricks/review.md +5 -3
- package/src/bricks/spec.md +18 -0
- package/src/bricks/upgrade-scout.md +16 -0
- package/src/loops/api-endpoint.json +31 -0
- package/src/loops/architecture-decision.json +22 -0
- package/src/loops/bugfix.json +1 -0
- package/src/loops/ci-repair.json +19 -0
- package/src/loops/deps-upgrade.json +29 -0
- package/src/loops/enforce-architecture-rule.json +28 -0
- package/src/loops/feature.json +8 -5
- package/src/loops/fix-flaky-tests.json +30 -0
- package/src/loops/legacy-refactor.json +26 -0
- package/src/loops/legacy-tests.json +29 -0
- package/src/loops/refactor.json +5 -1
- package/src/loops/remove-dead-code.json +30 -0
- package/src/loops/spec-first-feature.json +29 -0
- package/src/loops/tdd.json +25 -0
- package/src/loops/update-contract.json +33 -0
- package/src/skills/brick-forge.md +3 -1
- package/src/skills/bruno-collection-generator.md +3 -3
- package/src/skills/bruno-test-writer.md +3 -3
- package/src/skills/ci-fix.md +3 -3
- package/src/skills/consolidate-memory.md +4 -4
- package/src/skills/council.md +1 -1
- package/src/skills/fresh-eyes.md +1 -1
- package/src/skills/git-archaeology.md +1 -1
- package/src/skills/git-rescue.md +4 -3
- package/src/skills/handoff.md +1 -1
- package/src/skills/herdr.md +1 -1
- package/src/skills/learn-mode.md +2 -2
- package/src/skills/loop.md +22 -10
- package/src/skills/opencode-theme.md +3 -3
- package/src/skills/ponytail.md +1 -1
- package/src/skills/profile.md +3 -4
- package/src/skills/prose.md +2 -3
- package/src/skills/quiz.md +1 -1
- package/src/skills/react-view-transitions/SKILL.md +1 -1
- package/src/skills/react-view-transitions/VENDOR.md +8 -3
- package/src/skills/research.md +3 -3
- package/src/skills/review-response.md +2 -2
- package/src/skills/rule.md +3 -3
- package/src/skills/security-audit.md +4 -4
- package/src/skills/teach.md +1 -1
- package/src/skills/wiki.md +3 -3
- package/src/skills/workflow.md +4 -4
- package/src/skills/worktree.md +2 -2
- package/web/dist/assets/Activity-Ca2Aruu7.js +1 -0
- package/web/dist/assets/ActivityDetail-Bo7v4Z_r.js +1 -0
- package/web/dist/assets/Dashboard-BuMq46aT.js +2 -0
- package/web/dist/assets/Docs-BzccCllG.js +5 -0
- package/web/dist/assets/FilterInput-CBcJBQPI.js +1 -0
- package/web/dist/assets/GreenhouseView-BCIKcnGG.js +2 -0
- package/web/dist/assets/Installs-DMFJvq7s.js +2 -0
- package/web/dist/assets/JournalView-o1rmd1_1.js +1 -0
- package/web/dist/assets/Laws-BANxq_I_.js +3 -0
- package/web/dist/assets/Library-DW4x0fbh.js +1 -0
- package/web/dist/assets/Loops-DEBibbBP.js +2 -0
- package/web/dist/assets/{Markdown-qjM2_ofS.js → Markdown-CdTX0kLe.js} +14 -14
- package/web/dist/assets/OperatorHudView-CLD0fYaA.js +2 -0
- package/web/dist/assets/Personal-6uMJvyBG.js +1 -0
- package/web/dist/assets/Tabs-BubnyZhF.js +1 -0
- package/web/dist/assets/activity-CObqyxkL.js +1 -0
- package/web/dist/assets/{api-CyMRbU2x.js → api-D_ixdyEY.js} +1 -1
- package/web/dist/assets/drawable-C_x5xncq.js +1 -0
- package/web/dist/assets/index-CMPgezFm.js +2 -0
- package/web/dist/assets/index-DMsT4Aa6.css +1 -0
- package/web/dist/assets/{react-B9Z_tXRV.js → react-Bbzhmq4v.js} +1 -1
- package/web/dist/assets/rolldown-runtime-hePW80VL.js +1 -0
- package/web/dist/assets/sections-Dg23Hel5.js +1 -0
- package/web/dist/assets/usePoll-BOqeunzF.js +1 -0
- package/web/dist/index.html +6 -5
- package/web/dist/assets/Activity-GaaZWXTY.js +0 -1
- package/web/dist/assets/ActivityDetail-4t7d45Du.js +0 -1
- package/web/dist/assets/Dashboard-CYn7Tp16.js +0 -2
- package/web/dist/assets/Docs-BeFKLg2T.js +0 -5
- package/web/dist/assets/FilterInput-CVyqmYWM.js +0 -1
- package/web/dist/assets/GreenhouseView-C6ibc8IE.js +0 -2
- package/web/dist/assets/Installs-DRYjYnxs.js +0 -2
- package/web/dist/assets/JournalView-1HbU1mfg.js +0 -1
- package/web/dist/assets/Laws-DFoG8JWB.js +0 -3
- package/web/dist/assets/Library-DDjgNwz_.js +0 -1
- package/web/dist/assets/Loops-D9VEoO0F.js +0 -1
- package/web/dist/assets/OperatorHudView-Bs7paWmh.js +0 -2
- package/web/dist/assets/Personal-BY5n4gTw.js +0 -1
- package/web/dist/assets/Tabs-ho-EYD8i.js +0 -1
- package/web/dist/assets/drawable-CLS9drMb.js +0 -1
- package/web/dist/assets/index-CX_hXMi5.css +0 -1
- package/web/dist/assets/index-Cjr7XCA3.js +0 -2
- package/web/dist/assets/sections-GalMS0Zv.js +0 -1
- package/web/dist/assets/usePoll-O0sJEw1Y.js +0 -1
package/docs/concepts/hosts.md
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
package/docs/concepts/loops.md
CHANGED
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
group: concepts
|
|
3
|
-
order: 11
|
|
4
|
-
title: "Loops"
|
|
5
3
|
kind: "concept"
|
|
6
|
-
|
|
4
|
+
section: "Loops"
|
|
5
|
+
order: 16
|
|
6
|
+
title: "Loops"
|
|
7
|
+
link: {"hash":"#/docs/loop-actions","label":"The geneseed loop actions →"}
|
|
8
|
+
description: "What a loop is, the ring of bricks it runs, and how it differs from foreman mode."
|
|
7
9
|
---
|
|
10
|
+
To run one, see [Run a loop](../guides/run-a-loop.md).
|
|
11
|
+
|
|
8
12
|
A **loop** is a requirement worked as small, validated, committed iterations instead of one long
|
|
9
13
|
turn. `geneseed loop` is the state machine: it decides every transition, ceiling, score and stop,
|
|
10
14
|
and hands the agent one node at a time to run. The `loop` [skill](skills.md) is the only thing
|
|
@@ -22,10 +26,11 @@ report. One cycle through the graph back to its head is an **iteration**; the gr
|
|
|
22
26
|
array names every cycle that is allowed to exist, each with a `max` number of times a node inside
|
|
23
27
|
it may be re-entered. Picture it as rings: the outer ring is the iteration itself (plan, apply,
|
|
24
28
|
test, review, back to plan), and inner rings sit inside it for retries (apply failed its test, try
|
|
25
|
-
`apply` again without going all the way back around). The
|
|
26
|
-
`bugfix`, `feature`, `refactor` — all nest a
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
`apply` again without going all the way back around). The shipped templates that center on
|
|
30
|
+
`apply` — `bugfix`, `feature`, `refactor`, `tdd`, `legacy-refactor`, `deps-upgrade` — all nest a
|
|
31
|
+
short `apply`↔`test` retry ring inside the iteration ring, and most nest a second, wider
|
|
32
|
+
`review-fix` ring around that. `legacy-tests` and `ci-repair` have no `apply` at all: the first
|
|
33
|
+
only ever writes tests, the second repairs CI directly through `ci-fix`.
|
|
29
34
|
|
|
30
35
|
Work closes into a commit whenever the graph re-enters the iteration loop's head — so any setup
|
|
31
36
|
work before the loop starts (reproducing a bug, say) is its own unit, numbered iteration 0, kept
|
|
@@ -42,120 +47,23 @@ all gets exactly 1 — no re-entry — which is also why **every cycle inside an
|
|
|
42
47
|
named inner loop** in the graph JSON: `geneseed loop check` (and `loop init`, which runs the same
|
|
43
48
|
check) refuses a graph with an undeclared cycle inside an iteration, before a single node runs.
|
|
44
49
|
|
|
45
|
-
## Bricks, templates, and the three origins
|
|
46
|
-
|
|
47
|
-
A **brick** is a markdown file: YAML-ish frontmatter (`name`, `description`, `effect` — `read` or
|
|
48
|
-
`mutate` — exactly one of `agent` or `skill`, and `outcomes`) plus a 4-10 line prose body. The
|
|
49
|
-
model never sees the file; `geneseed loop next` hands it the body as the prompt. A **loop
|
|
50
|
-
template** (`bugfix`, `feature`, `refactor`, or one composed by hand) is the graph JSON that wires
|
|
51
|
-
bricks together.
|
|
52
|
-
|
|
53
|
-
Both are looked up across three origins, each able to override the one before it **by name**:
|
|
54
|
-
|
|
55
|
-
| origin | path | who writes it |
|
|
56
|
-
|---|---|---|
|
|
57
|
-
| shipped | `src/bricks/`, `src/loops/` | Geneseed itself — read by the CLI from its own source, never emitted into an install |
|
|
58
|
-
| global | `$XDG_CONFIG_HOME/geneseed/{bricks,loops}` (default `~/.config/geneseed/…`) | the user, for every project on this machine |
|
|
59
|
-
| project | `<repo>/.geneseed/{bricks,loops}` | a team, committed and shared |
|
|
60
|
-
|
|
61
|
-
Precedence is project > global > shipped. A project or global brick named `apply` replaces the
|
|
62
|
-
shipped `apply` everywhere a template references it, without the template changing.
|
|
63
|
-
`geneseed loop check` lists every override it finds, never silently.
|
|
64
|
-
|
|
65
|
-
A per-install skill exclusion is invisible to the CLI — it has no way to know which skills your
|
|
66
|
-
install carries. The `loop` skill covers the gap itself: when composing a graph it skips a brick
|
|
67
|
-
whose `skill` it doesn't have.
|
|
68
|
-
|
|
69
|
-
To add or adapt a brick, use the `brick-forge` skill — ask it, or see
|
|
70
|
-
[the bricks README](https://github.com/geneseed-dev/geneseed/blob/main/src/bricks/README.md) in
|
|
71
|
-
the repository.
|
|
72
|
-
|
|
73
|
-
## Risk, trust, and the three validation levels
|
|
74
|
-
|
|
75
|
-
Before a `mutate` brick runs, the loop scores the card the brick's setup declared: one risk weight
|
|
76
|
-
per action kind it named, and the score is the **max**, not a sum — one contract change outweighs
|
|
77
|
-
ten trivial renames, and ten trivial renames never add up to one. After the brick runs, the loop
|
|
78
|
-
re-scores against the real diff, and the diff can only raise the score, never lower it:
|
|
79
|
-
|
|
80
|
-
- a file touched outside the declared write set raises the score to at least **api** (`0.8`);
|
|
81
|
-
- more than 20 deleted lines raises it to at least the **delete** weight;
|
|
82
|
-
- touching a file listed in the loop's `contracts` raises it to at least the **api** weight.
|
|
83
|
-
|
|
84
|
-
`LOOP.md` itself is excluded from every score and every diff check — it's the engine's own
|
|
85
|
-
bookkeeping, rewritten on every action, never part of the work being judged.
|
|
86
|
-
|
|
87
|
-
The score is checked against a **trust preset** — `--preset` on `geneseed loop init`, editable
|
|
88
|
-
afterward in `LOOP.md`'s `preset` field, applying from the next score on:
|
|
89
|
-
|
|
90
|
-
| preset | silent ≤ | soft ≤ | above soft |
|
|
91
|
-
|---|---|---|---|
|
|
92
|
-
| prudent | 0.1 | 0.3 | blocking |
|
|
93
|
-
| balanced (default) | 0.2 | 0.6 | blocking |
|
|
94
|
-
| aggressive | 0.4 | 0.8 | blocking |
|
|
95
|
-
|
|
96
|
-
Three levels follow from where the score lands:
|
|
97
|
-
|
|
98
|
-
- **silent** — nothing more than the commit trailers below.
|
|
99
|
-
- **soft** — listed under "to review" in the run's final summary; no notification during the run.
|
|
100
|
-
- **blocking** — the run ends. `LOOP.md` is written with `status: awaiting`, and a person has to
|
|
101
|
-
answer with `geneseed loop decide --verdict ok|no|amend`. Amending a verdict marks the decision
|
|
102
|
-
`blocking (amended)` in the trailers rather than silently rewriting it to something else.
|
|
103
|
-
|
|
104
|
-
## `LOOP.md` and its trailers
|
|
105
|
-
|
|
106
|
-
`LOOP.md`, at the worktree root, is both the human-readable record (title, requirement, and the
|
|
107
|
-
rule that you may edit `preset` or `contracts` there) and the engine's own JSON state block. Every
|
|
108
|
-
closing commit carries seven trailers, read straight off that state:
|
|
109
|
-
|
|
110
|
-
```
|
|
111
|
-
Loop-Iteration: <n>
|
|
112
|
-
Loop-Bricks: <every brick name visited this unit, deduplicated>
|
|
113
|
-
Loop-Risk-Declared: <score>
|
|
114
|
-
Loop-Risk-Actual: <score>
|
|
115
|
-
Loop-Threshold: <preset> <silent>/<soft>
|
|
116
|
-
Loop-Decision: silent | soft | blocking[ (amended)]
|
|
117
|
-
Loop-Tests: <what the loop was told about test state>
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
## The `loop/*` branch, and why merge always asks
|
|
121
|
-
|
|
122
|
-
A loop runs in its own worktree, on a branch named `loop/<slug>` — the `loop` skill creates both
|
|
123
|
-
with `git worktree add -b loop/<slug>` before `geneseed loop init` writes `LOOP.md` there.
|
|
124
|
-
While that branch is checked out and `LOOP.md` carries the engine's state marker, the git gate lets
|
|
125
|
-
exactly one commit/push form through without asking:
|
|
126
|
-
|
|
127
|
-
```
|
|
128
|
-
git add -A && git commit -F <message_file> && git push [-u] <remote> HEAD:<loop branch>
|
|
129
|
-
```
|
|
130
|
-
|
|
131
|
-
Nothing else is exempt — not `git commit -m`, not a quoted refspec, not a plain `git push` with no
|
|
132
|
-
explicit `HEAD:<ref>` — any other shape still asks. The exemption only ever covers a `loop/*`
|
|
133
|
-
branch, and never a shared one (`main`, `master`, `develop`, `development`, `release/*`,
|
|
134
|
-
`hotfix/*`). The **final** commit of a run — the one that removes `LOOP.md` on `$close` — is
|
|
135
|
-
outside the exemption too, because the loop is no longer running when it lands; that ask is your
|
|
136
|
-
consent to close it. **Merging a loop branch into anything else always asks, with no exception.**
|
|
137
|
-
The loop reports the branch to merge and the iterations that landed in "to review" — it never
|
|
138
|
-
merges for you.
|
|
139
|
-
|
|
140
|
-
## `geneseed loop` actions
|
|
141
|
-
|
|
142
|
-
| action | what it does |
|
|
143
|
-
|---|---|
|
|
144
|
-
| `check` | lists templates and every brick (available, unavailable, overridden); validates one graph file (`--graph`) or one brick file (`--brick`) |
|
|
145
|
-
| `init` | writes a fresh `LOOP.md` from a template or graph file, under a title, requirement and trust preset |
|
|
146
|
-
| `next` | the only driver of the cycle — returns the next thing to do: run a node, score a card, answer an `awaiting`, or a terminal |
|
|
147
|
-
| `score` | scores a declared card (`--declared`) before a mutate node runs, or the real diff (`--diff`, numstat piped on stdin) before a commit |
|
|
148
|
-
| `record` | records a brick's reported outcome and advances the graph |
|
|
149
|
-
| `decide` | answers an `awaiting` validation with a verdict and a note |
|
|
150
|
-
|
|
151
|
-
Run `geneseed loop --help` for the full flag list.
|
|
152
|
-
|
|
153
50
|
## Limits
|
|
154
51
|
|
|
155
52
|
- **No parallel nodes.** The graph runs one node at a time; there is no fan-out.
|
|
156
|
-
- **A per-install skill exclusion is invisible to the CLI** (see
|
|
53
|
+
- **A per-install skill exclusion is invisible to the CLI** (see [Bricks and their origins](loop-bricks.md)) — the `loop` skill is
|
|
157
54
|
responsible for skipping bricks it can't run, not the engine.
|
|
158
55
|
|
|
56
|
+
## Read on
|
|
57
|
+
|
|
58
|
+
- [Loop templates](loop-templates.md): the shipped graphs, and when to use each.
|
|
59
|
+
- [Bricks and their origins](loop-bricks.md): what a brick is, and where your own override the shipped ones.
|
|
60
|
+
- [Notes and rules](loop-notes.md): what survives an iteration, and what every brick must follow.
|
|
61
|
+
- [Risk, trust and validation levels](loop-risk.md): how a change is scored, and when it stops for you.
|
|
62
|
+
- [Human gates](loop-gates.md): the bricks that always wait for a person.
|
|
63
|
+
- [Contracts and ignored deletions](loop-contracts.md): the globs that raise or ignore risk.
|
|
64
|
+
- [LOOP.md, trailers and the loop branch](loop-branch.md): the state file, the commit trailers, and why merging always asks.
|
|
65
|
+
- [Loop actions](../reference/loop-actions.md): the `geneseed loop` commands.
|
|
66
|
+
|
|
159
67
|
## Not foreman mode
|
|
160
68
|
|
|
161
69
|
A loop and a [foreman-mode](foreman-mode.md) pipeline are both "hand work off and keep going," but
|
package/docs/concepts/lsp.md
CHANGED
|
@@ -3,6 +3,8 @@ group: concepts
|
|
|
3
3
|
order: 13
|
|
4
4
|
title: "Code intelligence (LSP, OpenCode)"
|
|
5
5
|
kind: "concept"
|
|
6
|
+
section: "Configuration"
|
|
7
|
+
description: "Language servers on OpenCode, so the agent sees real diagnostics."
|
|
6
8
|
---
|
|
7
9
|
OpenCode can run **language servers** — the same Language Server Protocol servers your editor uses — so the agent sees real diagnostics, type errors and definitions, not just text. Geneseed turns this on for every language OpenCode ships a server for.
|
|
8
10
|
|
package/docs/concepts/memory.md
CHANGED
package/docs/concepts/rules.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
group: concepts
|
|
3
|
-
order:
|
|
3
|
+
order: 3
|
|
4
4
|
title: "Rules (the constitution)"
|
|
5
5
|
kind: "concept"
|
|
6
|
+
section: "Harness"
|
|
7
|
+
description: "The constitution: the standing rules every session carries, in laws and doctrine packs."
|
|
6
8
|
link: {"hash": "#/laws", "label": "Browse the constitution →"}
|
|
7
9
|
---
|
|
8
10
|
The **constitution** is the set of standing rules the agent carries into every session. It is authored in `src/`, rendered into the instructions file your host reads (`AGENT.md`, `CLAUDE.md` or `AGENTS.md`), and comes in layers that differ in one thing: whether you can turn them off.
|
|
@@ -37,7 +39,7 @@ When two instructions disagree, the higher one wins.
|
|
|
37
39
|
| **process** | how a session runs — planning, context economy, docs first, bounded loops, consent before every commit and push |
|
|
38
40
|
| **comms** | how answers are presented — stable reference codes on tracked items, a diagram or table only where it earns its place |
|
|
39
41
|
|
|
40
|
-
All of them are on by default. This install built in {N_PACKS_ACTIVE}, carrying {N_DOCTRINE_RULES} rules between them. You choose packs at build time with `--doctrines`, or drop single rules with `--exclude-rules`; the how-to is in [
|
|
42
|
+
All of them are on by default. This install built in {N_PACKS_ACTIVE}, carrying {N_DOCTRINE_RULES} rules between them. You choose packs at build time with `--doctrines`, or drop single rules with `--exclude-rules`; the how-to is in [Doctrine packs and single rules](../guides/setup-doctrines.md).
|
|
41
43
|
|
|
42
44
|
A pack you leave out **still ships**: every pack file lands under `doctrines/` beside the instructions file whether or not it was built in. A rule that cites an inactive pack still resolves on disk, and you can read the alternatives before turning one on. An inactive pack loses its binding force, not its availability.
|
|
43
45
|
|
package/docs/concepts/skills.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
group: concepts
|
|
3
|
-
order:
|
|
3
|
+
order: 5
|
|
4
4
|
title: "Skills"
|
|
5
5
|
kind: "concept"
|
|
6
|
+
section: "Harness"
|
|
7
|
+
description: "Written playbooks the agent follows for a repeatable task."
|
|
6
8
|
link: {"hash": "#/section/skills", "label": "Browse the catalog →"}
|
|
7
9
|
---
|
|
8
10
|
A **skill** is a repeatable workflow written as a markdown playbook: when it applies, the steps, and what "done" looks like. The agent reads the playbook before acting, so a task it has a skill for is done the same careful way every time instead of improvised.
|
package/docs/concepts/themes.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
group: concepts
|
|
3
|
-
order:
|
|
3
|
+
order: 11
|
|
4
4
|
title: "Themes"
|
|
5
5
|
kind: "concept"
|
|
6
|
+
section: "Configuration"
|
|
7
|
+
description: "The agent's voice and the words the harness uses, never its structure."
|
|
6
8
|
---
|
|
7
9
|
A **theme** changes the agent's *voice* and the words the harness uses for its own parts. It never changes structure: the same rules, in the same order, with the same files, folders and links, whatever theme you pick.
|
|
8
10
|
|