geneseed 3.19.0 → 3.20.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 +6 -0
- package/SHIPPED.md +1 -1
- package/docs/concepts/loops.md +4 -3
- package/harness.config.json +1 -1
- package/js/build/stubs.mjs +2 -1
- package/js/hosts/hooks-context.mjs +2 -1
- package/js/loop/state.mjs +2 -2
- package/js/web/catalog.mjs +1 -1
- package/package.json +1 -1
- package/src/bricks/apply.md +1 -1
- package/src/bricks/test.md +1 -1
- package/src/doctrines/process.md +3 -3
- package/src/loops/api-endpoint.json +1 -1
- package/src/loops/bugfix.json +1 -1
- package/src/loops/ci-repair.json +1 -1
- package/src/loops/deps-upgrade.json +1 -1
- package/src/loops/enforce-architecture-rule.json +1 -1
- package/src/loops/feature.json +1 -1
- package/src/loops/fix-flaky-tests.json +1 -1
- package/src/loops/legacy-refactor.json +1 -1
- package/src/loops/legacy-tests.json +1 -1
- package/src/loops/refactor.json +1 -1
- package/src/loops/remove-dead-code.json +1 -1
- package/src/loops/spec-first-feature.json +1 -1
- package/src/loops/tdd.json +1 -1
- package/src/loops/update-contract.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,12 @@ label. For the capability ↔ spec map, see [SHIPPED.md](SHIPPED.md).
|
|
|
8
8
|
|
|
9
9
|
## [Unreleased]
|
|
10
10
|
|
|
11
|
+
## [3.20.0] — 2026-10-09
|
|
12
|
+
|
|
13
|
+
### Changed
|
|
14
|
+
- Loops repair twice before giving up: the test repair rings (`apply-test`, `fix-test`, `write-run`, `stabilise`) now allow two repairs instead of one, then the attempt is discarded for one fresh try, then the loop stops for you. The first revision carries most of the gain, but a second still lands fixes the first missed. Bound the Loop, the `apply` and `test` bricks and the loops concept page say two. Review rings are unchanged.
|
|
15
|
+
- The fallback to the old wiki manifest name (`wiki.jsonc`) stays for now, against the 3.18.0 note that it would go in the next release: nothing yet reports an install that missed the rename, so removing it could drop a wiki in silence.
|
|
16
|
+
|
|
11
17
|
## [3.19.0] — 2026-10-09
|
|
12
18
|
|
|
13
19
|
### Added
|
package/SHIPPED.md
CHANGED
|
@@ -20,7 +20,7 @@ historical references, not files distributed with the repo.
|
|
|
20
20
|
> **On version numbers.** [`harness.config.json`](harness.config.json)'s `version` is a
|
|
21
21
|
> human-readable label only. The canonical identity of an installed harness is the
|
|
22
22
|
> **source fingerprint** stamped in `.geneseed-version` (see `geneseed version`), not the
|
|
23
|
-
> string. Current label: **3.
|
|
23
|
+
> string. Current label: **3.20.0**.
|
|
24
24
|
|
|
25
25
|
## Capabilities
|
|
26
26
|
|
package/docs/concepts/loops.md
CHANGED
|
@@ -50,9 +50,10 @@ check) refuses a graph with an undeclared cycle inside an iteration, before a si
|
|
|
50
50
|
**A ring's `max` is also its own repair budget.** The edge that returns to a ring's first node
|
|
51
51
|
from inside it — `test` → `apply` — is charged to the smallest ring holding both ends, and that
|
|
52
52
|
ring stops at its `max` even when a wider ring raises the node's shared budget. The shipped test
|
|
53
|
-
rings (`apply-test`, `fix-test`, `write-run`, `stabilise`) are `max:
|
|
54
|
-
attempt is discarded for one fresh try, then the loop stops for you.
|
|
55
|
-
|
|
53
|
+
rings (`apply-test`, `fix-test`, `write-run`, `stabilise`) are `max: 2`: two repairs, then the
|
|
54
|
+
attempt is discarded for one fresh try, then the loop stops for you. Most of the gain is in the
|
|
55
|
+
first revision — 0.82 correct after one, 0.673 after two (arXiv 2607.24604) — but a second still
|
|
56
|
+
lands fixes the first missed, so it is kept as the last chance, and nothing past it.
|
|
56
57
|
|
|
57
58
|
**`error` always stops.** A brick may declare the outcome `error` without an edge for it; the
|
|
58
59
|
engine sends it to `$stop`. The shipped `test` brick reports it when a check crashed or its
|
package/harness.config.json
CHANGED
|
@@ -2,5 +2,5 @@
|
|
|
2
2
|
"_comment": "version is a human-readable release label only; the canonical identity of an installed harness is the source fingerprint stamped in .geneseed-version (see `harness version`), not this string.",
|
|
3
3
|
"theme": "neutral",
|
|
4
4
|
"product": "Geneseed",
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.20.0"
|
|
6
6
|
}
|
package/js/build/stubs.mjs
CHANGED
|
@@ -223,7 +223,8 @@ export function ensureContextStub(out) {
|
|
|
223
223
|
|
|
224
224
|
/** The wiki manifest's name. `geneseed-` says who owns it in a shared `.claude/`/`.opencode/`. */
|
|
225
225
|
export const WIKI_FILE = 'geneseed-wiki.jsonc';
|
|
226
|
-
/** Its earlier names, newest first. Readers still fall back to them
|
|
226
|
+
/** Its earlier names, newest first. Readers still fall back to them, with no end date:
|
|
227
|
+
* nothing yet tells a user an install missed the rename, so dropping the fallback would lose a wiki in silence. */
|
|
227
228
|
const LEGACY_WIKI_FILES = ['wiki.jsonc', 'wiki.json'];
|
|
228
229
|
|
|
229
230
|
/**
|
|
@@ -128,7 +128,8 @@ const cost = (s) => s.length + (s.match(/\n/g) || []).length + 2;
|
|
|
128
128
|
const SESSION_FILES = ['user-rules.md', 'PROFILE.md', 'memory/MEMORY.md', 'anamnesis/MEMORY.md',
|
|
129
129
|
'notebook/NOTEBOOK.md', 'geneseed-wiki.jsonc'];
|
|
130
130
|
// The wiki manifest's earlier name, read when the new one is absent (an install not yet re-emitted,
|
|
131
|
-
// or a rename that failed).
|
|
131
|
+
// or a rename that failed). Kept until a missed rename is reported somewhere (status), since
|
|
132
|
+
// without it such an install loses its wiki in silence; `wiki.json`, older still, is the build's to rename.
|
|
132
133
|
const LEGACY_WIKI = 'wiki.jsonc';
|
|
133
134
|
// SHA-256 of each seed body in `js/build/stubs.mjs` (`SESSION_SEEDS`), CRLF folded. A file still
|
|
134
135
|
// byte-identical to its seed says nothing, so it is skipped rather than injected as noise.
|
package/js/loop/state.mjs
CHANGED
|
@@ -291,8 +291,8 @@ function allowedEntries(graph, v) {
|
|
|
291
291
|
// The repair ring an edge closes: the smallest non-iteration loop whose FIRST node is the edge's
|
|
292
292
|
// target and which also holds its source (test -> apply is apply-test's repair, review -> apply
|
|
293
293
|
// review-fix's). Its own counter makes `max` the number of repairs that ring may spend, even when
|
|
294
|
-
// a wider ring sharing the node raises the node budget above it — `max:
|
|
295
|
-
// `exhaust`'s fresh attempt, then a stop (arXiv 2607.24604:
|
|
294
|
+
// a wider ring sharing the node raises the node budget above it — `max: 2` is two repairs, then
|
|
295
|
+
// `exhaust`'s fresh attempt, then a stop (arXiv 2607.24604: revisions past the first lower accuracy).
|
|
296
296
|
// Its key lives in `counters`, so every reset of a unit resets it too.
|
|
297
297
|
function repairRing(graph, from, to) {
|
|
298
298
|
const iteration = iterationLoop(graph);
|
package/js/web/catalog.mjs
CHANGED
|
@@ -185,7 +185,7 @@ export function notebookItems(state) {
|
|
|
185
185
|
|
|
186
186
|
/**
|
|
187
187
|
* The wiki manifest's names, current first. `wiki.jsonc` is the name before the `geneseed-`
|
|
188
|
-
* prefix: the build renames it on the next emit, and until then it is still read
|
|
188
|
+
* prefix: the build renames it on the next emit, and until then it is still read (no end date; see `LEGACY_WIKI_FILES`).
|
|
189
189
|
*/
|
|
190
190
|
const WIKI_NAMES = ['geneseed-wiki.jsonc', 'wiki.jsonc'];
|
|
191
191
|
const WIKI_META = ['Wiki manifest', 'your machine-wide knowledge base(s)'];
|
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.
|
|
4
|
+
"version": "3.20.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",
|
package/src/bricks/apply.md
CHANGED
|
@@ -10,7 +10,7 @@ carries an `amend`, that supersedes the original intent — follow the amendment
|
|
|
10
10
|
replaced.
|
|
11
11
|
|
|
12
12
|
When this is a repair after `test`, act on the latest `test` note only — it is the verdict on
|
|
13
|
-
the code as it stands. Fix every finding it lists in this one pass:
|
|
13
|
+
the code as it stands. Fix every finding it lists in this one pass: repairs are capped at two.
|
|
14
14
|
|
|
15
15
|
Make no unrelated edits: no drive-by rename, no incidental cleanup, no touching a file the card
|
|
16
16
|
did not declare. If the change genuinely needs a file outside the write set, stop and report that
|
package/src/bricks/test.md
CHANGED
|
@@ -11,7 +11,7 @@ brick only observes; a fix belongs in `apply`, not here.
|
|
|
11
11
|
1. **Gate** — the build or compile step. If it fails, mark every check below `SKIPPED (gate
|
|
12
12
|
failed)` and report.
|
|
13
13
|
2. **Focused checks** — the linter and the tests the change can reach. Run every one even after a
|
|
14
|
-
failure: they check independent properties, and
|
|
14
|
+
failure: they check independent properties, and each repair must see every finding at once.
|
|
15
15
|
3. **Full suite** — only when everything above passed; otherwise `SKIPPED (an earlier check failed)`.
|
|
16
16
|
|
|
17
17
|
List every check with `PASS`, `FAIL`, `ERROR` or `SKIPPED (reason)` — one that did not run is
|
package/src/doctrines/process.md
CHANGED
|
@@ -114,8 +114,8 @@ legitimate rewrite). The host gates both at the tool boundary.
|
|
|
114
114
|
Every autonomous loop needs an exit you set before you enter it. Before iterating —
|
|
115
115
|
retrying, searching, generating-and-checking — fix the bounds: a cap on attempts, a
|
|
116
116
|
budget of time or tokens, and an explicit definition of success *and* of failure.
|
|
117
|
-
A check-and-repair loop gets
|
|
118
|
-
|
|
117
|
+
A check-and-repair loop gets two repairs, then a fresh attempt or a hand-back — more
|
|
118
|
+
revisions cost accuracy. Only a verdict on the final artifact counts: a pass from before
|
|
119
119
|
an edit is void, and old check output is never fed back. Then watch for the loop that has stopped progressing:
|
|
120
120
|
if you are issuing the same call, hitting the same error, or trying variations of one
|
|
121
121
|
approach with no new information, that is not persistence, it is thrashing — break out, change strategy,
|
|
@@ -127,7 +127,7 @@ stop itself is a cost without a limit.
|
|
|
127
127
|
<!-- LEAN:else -->
|
|
128
128
|
Fix an autonomous loop's bounds before you enter it: an attempt cap, a time or token
|
|
129
129
|
budget, an explicit definition of success *and* failure. A check-and-repair loop spends
|
|
130
|
-
|
|
130
|
+
two repairs at most, then a fresh attempt or a hand-back; accept only a verdict on the final
|
|
131
131
|
artifact — a pass from before an edit is void, old check output is never fed back.
|
|
132
132
|
Watch for the loop that has stopped progressing: the same call, the same error, variations with no new information are
|
|
133
133
|
thrashing; break out, change strategy, or stop. When a bound is reached or progress
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"loops": [
|
|
26
26
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "bruno-test", "security-scan", "review"], "max": 20, "iteration": true },
|
|
27
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
27
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
28
28
|
{ "name": "review-fix", "nodes": ["apply", "test", "bruno-test", "security-scan", "review"], "max": 3 }
|
|
29
29
|
],
|
|
30
30
|
"contracts": ["**/openapi*.yaml", "**/openapi*.yml", "**/openapi*.json", "**/swagger*.yaml", "**/swagger*.yml", "**/swagger*.json"]
|
package/src/loops/bugfix.json
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
],
|
|
18
18
|
"loops": [
|
|
19
19
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
|
|
20
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
20
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
21
21
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
22
22
|
]
|
|
23
23
|
}
|
package/src/loops/ci-repair.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"loops": [
|
|
24
24
|
{ "name": "iterations", "nodes": ["upgrade-scout", "apply", "test", "deps-audit", "review"], "max": 20, "iteration": true },
|
|
25
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
25
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
26
26
|
{ "name": "review-fix", "nodes": ["apply", "test", "deps-audit", "review"], "max": 3 }
|
|
27
27
|
],
|
|
28
28
|
"ignoreDeletions": ["**/package-lock.json", "**/yarn.lock", "**/pnpm-lock.yaml", "**/*.lock", "**/gradle.lockfile"]
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"loops": [
|
|
24
24
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
|
|
25
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
25
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
26
26
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
27
27
|
]
|
|
28
28
|
}
|
package/src/loops/feature.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"loops": [
|
|
20
20
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review", "done-check"], "max": 20, "iteration": true },
|
|
21
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
21
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
22
22
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
23
23
|
]
|
|
24
24
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
],
|
|
25
25
|
"loops": [
|
|
26
26
|
{ "name": "iterations", "nodes": ["identify", "apply", "flake-check", "test", "review"], "max": 10, "iteration": true },
|
|
27
|
-
{ "name": "stabilise", "nodes": ["apply", "flake-check"], "max":
|
|
27
|
+
{ "name": "stabilise", "nodes": ["apply", "flake-check"], "max": 2 },
|
|
28
28
|
{ "name": "review-fix", "nodes": ["apply", "flake-check", "test", "review"], "max": 3 }
|
|
29
29
|
]
|
|
30
30
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"loops": [
|
|
21
21
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
|
|
22
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
22
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
23
23
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
24
24
|
],
|
|
25
25
|
"weights": { "logic": 0.6 }
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"loops": [
|
|
24
24
|
{ "name": "iterations", "nodes": ["identify", "characterize", "test", "mutation-check"], "max": 20, "iteration": true },
|
|
25
|
-
{ "name": "write-run", "nodes": ["characterize", "test"], "max":
|
|
25
|
+
{ "name": "write-run", "nodes": ["characterize", "test"], "max": 2 },
|
|
26
26
|
{ "name": "kill-mutants", "nodes": ["characterize", "test", "mutation-check"], "max": 3 }
|
|
27
27
|
],
|
|
28
28
|
"weights": { "new-file": 0.2 }
|
package/src/loops/refactor.json
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"loops": [
|
|
20
20
|
{ "name": "iterations", "nodes": ["identify", "apply", "test"], "max": 20, "iteration": true },
|
|
21
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
21
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 }
|
|
22
22
|
],
|
|
23
23
|
"weights": { "logic": 0.6 }
|
|
24
24
|
}
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
],
|
|
23
23
|
"loops": [
|
|
24
24
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review"], "max": 20, "iteration": true },
|
|
25
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
25
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
26
26
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
27
27
|
],
|
|
28
28
|
"weights": { "delete": 0.5 },
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"loops": [
|
|
25
25
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "review", "done-check"], "max": 20, "iteration": true },
|
|
26
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
26
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
27
27
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
28
28
|
]
|
|
29
29
|
}
|
package/src/loops/tdd.json
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
],
|
|
20
20
|
"loops": [
|
|
21
21
|
{ "name": "iterations", "nodes": ["identify", "red-test", "apply", "test", "review"], "max": 20, "iteration": true },
|
|
22
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
22
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
23
23
|
{ "name": "review-fix", "nodes": ["apply", "test", "review"], "max": 3 }
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
],
|
|
24
24
|
"loops": [
|
|
25
25
|
{ "name": "iterations", "nodes": ["identify", "apply", "test", "compat-check", "review"], "max": 20, "iteration": true },
|
|
26
|
-
{ "name": "apply-test", "nodes": ["apply", "test"], "max":
|
|
26
|
+
{ "name": "apply-test", "nodes": ["apply", "test"], "max": 2 },
|
|
27
27
|
{ "name": "review-fix", "nodes": ["apply", "test", "compat-check", "review"], "max": 3 }
|
|
28
28
|
],
|
|
29
29
|
"contracts": [
|