@codedology/code-forge 0.11.0 → 0.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 +80 -0
- package/README.md +30 -2
- package/docs/reference/blocks.json +359 -1
- package/docs/reference/config.md +7 -5
- package/package.json +2 -2
- package/schema/code-forge.schema.json +4 -2
- package/skill/SKILL.md +2 -0
- package/skill/references/code.md +19 -5
- package/skill/references/proof.md +8 -2
- package/skill/references/review.md +16 -7
- package/skill/references/rules-core.md +1 -1
- package/skill/scripts/forge +1 -1
- package/skill/templates/coder-brief.md +15 -3
- package/src/autopilot/actions.mjs +4 -5
- package/src/cli/block.mjs +41 -0
- package/src/cli/context.mjs +3 -2
- package/src/cli/gates.mjs +15 -6
- package/src/cli/review-file.mjs +114 -3
- package/src/cli/review.mjs +2 -2
- package/src/config/validate.mjs +12 -5
- package/src/context/pack.mjs +20 -13
- package/src/doctor/index.mjs +2 -1
- package/src/doctor/local.mjs +19 -0
- package/src/doctor/worker-probe.mjs +15 -2
- package/src/gates/expand.mjs +102 -9
- package/src/gates/run.mjs +6 -4
- package/src/install/wizard/flags.mjs +1 -1
- package/src/ledger/spend.mjs +3 -3
- package/src/proof/lock.mjs +27 -10
- package/src/proof/rule.mjs +9 -0
- package/src/proof/tiers.mjs +2 -14
- package/src/review/fixloop.mjs +11 -6
- package/src/review/gate-check.mjs +34 -9
- package/src/review/lenses/A.md +4 -0
- package/src/review/lenses/B.md +4 -0
- package/src/review/lenses/full.md +4 -0
- package/src/review/lenses/judge.md +4 -0
- package/src/review/lenses/quick.md +4 -0
- package/src/review/lenses/recheck.md +4 -0
- package/src/review/paired.mjs +1 -0
- package/src/review/reopen.mjs +18 -6
- package/src/review/schema-fallback.mjs +3 -3
- package/src/util/exec.mjs +2 -1
- package/src/util/file-locks.mjs +118 -0
- package/src/util/forbidden.mjs +29 -2
- package/src/util/gate-token.mjs +3 -0
- package/src/worker/engine.mjs +2 -2
- package/src/worker/loop.mjs +98 -33
- package/src/worker/queue.mjs +183 -33
- package/src/worker/watch.mjs +115 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,86 @@ waits on a second real consumer (plan §10.4, Q17).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.13.0] — 2026-10-14
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- The leak test in `test/worker/orphan.test.mjs` takes the current contents of the repo's `.code-forge` folder as its baseline, so `npm test` passes when that folder already holds files (B126).
|
|
14
|
+
- Close check: a `review.cap` row is superseded by a later verified human `review.reopened` row followed by a signed
|
|
15
|
+
`review.round` of the file's current content; a superseded cap row adds no ids, so old stop findings need no
|
|
16
|
+
waiver after a reopen (B123)
|
|
17
|
+
- `review-file --wait-block`: a file whose newest review left open findings and whose content changed after it is not
|
|
18
|
+
re-queued; the join answers `status: findings` with that ticket and writes one delivered marker; the next join
|
|
19
|
+
queues the latest content once, so a commit made blind to the findings never counts as a stall round (B122)
|
|
20
|
+
- Worker registry: each worker writes `<repo>/.code-forge/workers/<pid>-<start_time>.json` next to `queue/worker.json`
|
|
21
|
+
and beats both; boot counts live entries and writes its entry under one cross-process lock (limit 1); boot
|
|
22
|
+
removes dead entries (a known start-time mismatch is dead); an unreadable entry blocks the boot and `doctor`
|
|
23
|
+
lists it; `liveWorker` keeps the B30 fresh-heartbeat rule (B106)
|
|
24
|
+
- Watch mode holds rechecks: a commit of a file that already has a ticket gets no ticket, only a `watch.held`
|
|
25
|
+
row; `review-file --wait-block` queues one ticket for the latest content; older pending tickets are still
|
|
26
|
+
superseded (B121)
|
|
27
|
+
- Locks now hold across processes (`src/util/file-locks.mjs`, `~/.code-forge/locks`): ticket claims, the per-file and
|
|
28
|
+
block locks, the budget row, schema fallback and autopilot actions; a dead owner's lock (pid + start time) is broken
|
|
29
|
+
under a per-key break mutex; `doctor` lists bad locks and crashed break mutexes (B105)
|
|
30
|
+
- New opt-in key `review.fair_share` (boolean, default `false`): the worker pool gives each free slot to the
|
|
31
|
+
pending ticket whose block has the fewest running tickets; ties stay oldest first (B101)
|
|
32
|
+
- `context pack` with no `context` key writes a pack with the block header and the built-in proof rule (300-line cap)
|
|
33
|
+
instead of refusing; a bad `context` value still refuses (B118)
|
|
34
|
+
- `block close` prints `WARN block <id>: no green gates run for this block; …` when `gates.test` is set and the block's
|
|
35
|
+
last gate row is not a green `gate.done`; it still closes (B118)
|
|
36
|
+
- `block close --transcript` reads a Codex JSON log (`codex exec --json`) by its commands and file writes only;
|
|
37
|
+
agent messages, reasoning, command output and non-item events are skipped; other logs are scanned as before (B119)
|
|
38
|
+
|
|
39
|
+
### Fixed
|
|
40
|
+
|
|
41
|
+
- `block open` refuses an `--owned` or `--tests` entry that contains whitespace and names no existing file or directory
|
|
42
|
+
(a shell quoting slip), naming the entry; nothing is written (B118)
|
|
43
|
+
- `npm test -- --test-name-pattern=<p>` exits 0: six test files no longer call `rm(undefined)` in cleanup when
|
|
44
|
+
their setup was skipped by the pattern (B116, built with `code-forge run` itself)
|
|
45
|
+
- The close reason names each transcript rule break once (`rule_break transcript line <n>: <id>`, at most 5,
|
|
46
|
+
then `+<k> more rule_break`) instead of repeating a bare `rule_break` (B119)
|
|
47
|
+
- `gates run --run <r> --block <id>` with plain gates (no `{test_files}`, no `--changed`) writes its `gate.done` and
|
|
48
|
+
`gate.red` rows to the run's project ledger; before, it wrote none, so the B118 close warning fired after a green run (B120)
|
|
49
|
+
|
|
50
|
+
## [0.12.0] — 2026-10-14
|
|
51
|
+
|
|
52
|
+
### Added
|
|
53
|
+
|
|
54
|
+
- `gates run --changed` (with `--run` and `--block`) narrows `{test_files}` to changed tests and stem-paired tests of
|
|
55
|
+
changed sources, and a new `{changed_files}` gate token passes the changed paths; it falls back with `reason`
|
|
56
|
+
`no_baseline`, `unpaired`, `threshold` or `no_changes`; a green `gate.done` records the owned file hashes as the next
|
|
57
|
+
baseline (B99, #16)
|
|
58
|
+
- `review.file_loop: overlap` and `review-file --wait-block <id> --run <r> [--max]`: one wait for all owned changed
|
|
59
|
+
files of a block, one JSON line `{block, files: [{file, ticket, status}], done}`; a file changed after its ticket gets
|
|
60
|
+
its current content enqueued; timeout exits 0 with `reason: wait_timeout`, `not_queued` files give `reason:
|
|
61
|
+
not_queued`, no live worker exits 3 with `worker_down` (B100)
|
|
62
|
+
- `review.file_loop: watch`: the worker watches the block's HEAD and queues owned files from new commits, with the same
|
|
63
|
+
ticket ids as `review-file`; an older pending ticket of the same file is marked `superseded`; problems write one
|
|
64
|
+
`watch.skipped` row per reason (B104)
|
|
65
|
+
- every `code-forge context pack` carries a built-in `## proof rule (code-forge)` section that `context.max_lines` never
|
|
66
|
+
cuts: the red→green definition, no hand mutations, one exact test per clause, proof scales with risk, no extras the
|
|
67
|
+
acceptance does not ask for (B117)
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
|
|
71
|
+
- `block close` reports `coder report FAILED: TESTS line malformed: <line>` for a `TESTS ` line that does not end in
|
|
72
|
+
`exit=<n>`; no line at all still gives `no TESTS line` (B114)
|
|
73
|
+
- every review lens tells the reviewer not to ask for hand mutations or tests beyond the acceptance; a weak assertion is
|
|
74
|
+
fixed by a stronger assertion; over-engineering is at most a `nit` (B117)
|
|
75
|
+
|
|
76
|
+
### Removed
|
|
77
|
+
|
|
78
|
+
- the unused `proofRequirements` export in src/proof/tiers.mjs (B117)
|
|
79
|
+
|
|
80
|
+
### Fixed
|
|
81
|
+
|
|
82
|
+
- every fix-loop stop (stall, cap, split, stop-at, L3 exhaustion) records `stop_content_hash`, so `block reopen` works
|
|
83
|
+
after it; a stop with unknown content reopens when no verified `review.round` names the current hash (`from_hash:
|
|
84
|
+
null`), and the refusal no longer points to `block waive` (B114, #17)
|
|
85
|
+
- paired tests: a Python `<stem>_test.py` file pairs with `<stem>.py`, like `test_<stem>.py` (B115)
|
|
86
|
+
- `npm test -- <args>` passes the extra args to the main test phase again; the snapshot and final no-leak steps still
|
|
87
|
+
run (B115)
|
|
88
|
+
|
|
9
89
|
## [0.11.0] — 2026-10-13
|
|
10
90
|
|
|
11
91
|
### Added
|
package/README.md
CHANGED
|
@@ -8,10 +8,37 @@ for cross-model, parallel, evidence-gated feature delivery — on Claude Code, C
|
|
|
8
8
|
> `examples/` have all landed (`docs/reference/blocks.json` lists every build block). What changed
|
|
9
9
|
> in each version is in [CHANGELOG.md](CHANGELOG.md).
|
|
10
10
|
|
|
11
|
-
## What's new in 0.
|
|
11
|
+
## What's new in 0.13
|
|
12
12
|
|
|
13
13
|
In the next release:
|
|
14
14
|
|
|
15
|
+
In 0.13.0:
|
|
16
|
+
|
|
17
|
+
- **Every block gets the proof rule, with or without a `context` key (B118).** `code-forge context pack` no longer refuses a config with no `context` key. The pack then holds the block header and the proof rule.
|
|
18
|
+
- **Safer block open and close (B118).** `block open` refuses an owned or test path that has spaces and names no file, a common shell quoting slip. `block close` warns when the block has no green gates run.
|
|
19
|
+
- **Clean rule checks on Codex logs (B119).** Run `codex exec --json` and pass the log to `block close --transcript`. code-forge then checks only the commands Codex ran and the files it wrote. Agent messages, reasoning and command output no longer give false rule breaks. The close reason names each rule break once.
|
|
20
|
+
- **Gate results are recorded again (B120).** `gates run --run <r> --block <id>` now writes its `gate.done` row also when no gate uses `{test_files}`. Before, the row was missing, so `block close` warned after a green run and `status` showed no gate result.
|
|
21
|
+
- **Fair share between blocks (B101).** Set `review.fair_share: true` and each free review slot goes to the block with the fewest running reviews. A block with many queued files no longer makes another block wait. Without the key, the order stays oldest first.
|
|
22
|
+
- **Locks hold across processes (B105).** Ticket claims and the locks for files, blocks and the budget row now work across worker processes. Lock files live in `~/.code-forge/locks`. A lock of a dead process is taken over safely. A bad lock, or a break lock left by a crashed process, blocks its key until you remove it, and `code-forge doctor` names it.
|
|
23
|
+
- **Watch waits for the whole fix (B121).** In watch mode, a file's first commit is reviewed at once. A later commit of a file that already has a review is held, and a `watch.held` row records it. `review-file --wait-block` then queues one review for the file's latest content. A half-done fix commit no longer uses up the file's review rounds.
|
|
24
|
+
- **One registry file per worker (B106).** Each worker writes its own file in `.code-forge/workers/` and keeps it fresh with its heartbeat. A new worker starts only when the live count is under the limit, which is 1 for now. The count and the new file are written under one lock, so two workers that start at the same time cannot both run. A file of a dead worker is removed at the next start. A file that cannot be read blocks the start, and `code-forge doctor` names it.
|
|
25
|
+
- **The join shows findings before it rechecks (B122).** Sometimes the coder commits again before reading the last review. At `review-file --wait-block`, such a file is not reviewed again yet. The join answers `findings` with the old ticket, so the coder reads and fixes them first. The next join rechecks the latest content once. A blind commit no longer counts as a stall round.
|
|
26
|
+
- **A reopen clears old stop findings (B123).** After `block reopen` and a fresh review of the new content, the close no longer asks you to waive the findings of the old stop. Only the fresh review's findings count.
|
|
27
|
+
- **The test suite passes on machines that use code-forge on itself (B126).** A leak test no longer counts files that were already in the repo's `.code-forge` folder.
|
|
28
|
+
|
|
29
|
+
## What's new in 0.12
|
|
30
|
+
|
|
31
|
+
In 0.12.0:
|
|
32
|
+
|
|
33
|
+
- **Faster fix rounds (B99).** `code-forge gates run --run <r> --block <id> --changed` runs only the tests of files changed since the last green gate run, and `{changed_files}` passes only the changed files to lint or format gates. It falls back to the normal scope when it cannot be sure.
|
|
34
|
+
- **Write while reviews run (B100).** With `review.file_loop: overlap`, the coder enqueues each green file and keeps working. Before it ends, `forge review-file --wait-block <id> --run <r>` waits once for every file of the block.
|
|
35
|
+
- **Reopen after any stop (B114, #17).** Every review stop now records the content it reviewed. An older stop with unknown content can be reopened when the current content was never reviewed. A malformed `TESTS` line now gets its own clear error.
|
|
36
|
+
- **Python `*_test.py` tests pair with their source (B115).** Fix rounds and review packets now find `widget_test.py` for `widget.py`, as they already found `test_widget.py`.
|
|
37
|
+
- **Commit watch (B104).** Set `review.file_loop: watch` and the coder just commits each green file. The worker sees the new commits, queues each owned file for review and drops older pending reviews of the same file. `review-file --wait-block` waits for them all.
|
|
38
|
+
- **The proof rule travels with every block (B117).** Every context pack and every reviewer now carry one rule. Red→green: each new or changed test must fail on the old code first, then pass on the new code. No hand mutations. Proof scales with risk, and nothing is added that the task did not ask for.
|
|
39
|
+
|
|
40
|
+
## What's new in 0.11
|
|
41
|
+
|
|
15
42
|
In 0.11.0:
|
|
16
43
|
|
|
17
44
|
- **The release moves the README What's new list (B108).** `npm run release` now moves the "In the next release:" bullets under "In X.Y.Z:". A minor or major release starts a new "What's new in X.Y" heading. The empty anchor stays for the next block. The release refuses an empty CHANGELOG [Unreleased] or a missing anchor before it changes anything, and a failed check puts the README back with the other files. The checks now include `gen-config-doc --check`. `docs/releasing.md` has a releasing checklist.
|
|
@@ -381,7 +408,8 @@ CLI verbs like any other and every one of them is exercised by this package's ow
|
|
|
381
408
|
you the full issue and sends nothing without your yes. `CODE_FORGE_NO_ERROR_LOG=1` turns the log,
|
|
382
409
|
the warnings and the command list off. Every field is listed in [docs/privacy.md](docs/privacy.md).
|
|
383
410
|
- **No mutation testing.** Neither this package's own tests nor the product it ships run mutation
|
|
384
|
-
testing (
|
|
411
|
+
testing (the owner's ruling R14/Q16, 2026-09-25). Coders do not make hand mutations either: each new
|
|
412
|
+
or changed test is proven red→green, and a weak assertion is fixed by a stronger assertion. Proof is plain unit and feature tests with exact
|
|
385
413
|
assertions, plus a red→green runner that proves a new test fails before the fix and passes after (`node:test`
|
|
386
414
|
built in; any other runner through a `proof.runners` entry that writes a JUnit report).
|
|
387
415
|
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"plans/code-forge-plan-v1.3.md §10.4",
|
|
5
5
|
"plans/NIGHT-LOG.md"
|
|
6
6
|
],
|
|
7
|
-
"block_count":
|
|
7
|
+
"block_count": 128,
|
|
8
8
|
"baseline_ids": ["B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8"],
|
|
9
9
|
"baseline_note": "Wave 0-1 blocks, landed before v1.3; depends_on may name them, but they have no entry under blocks.",
|
|
10
10
|
"blocks": {
|
|
@@ -1825,6 +1825,364 @@
|
|
|
1825
1825
|
"B112"
|
|
1826
1826
|
],
|
|
1827
1827
|
"note": "root-added 2026-10-13; bug; 226 orphan test workers drove load to 350-450 and broke the release test step"
|
|
1828
|
+
},
|
|
1829
|
+
"B99": {
|
|
1830
|
+
"title": "Fix rounds check less: gates run --changed, {changed_files}",
|
|
1831
|
+
"wave": 14,
|
|
1832
|
+
"level": "L2",
|
|
1833
|
+
"status": "landed",
|
|
1834
|
+
"owned": [
|
|
1835
|
+
"docs/how-it-works.md",
|
|
1836
|
+
"docs/reference/config.md",
|
|
1837
|
+
"schema/code-forge.schema.json",
|
|
1838
|
+
"skill/references/code.md",
|
|
1839
|
+
"skill/references/proof.md",
|
|
1840
|
+
"skill/templates/coder-brief.md",
|
|
1841
|
+
"src/cli/gates.mjs",
|
|
1842
|
+
"src/config/validate.mjs",
|
|
1843
|
+
"src/gates/expand.mjs",
|
|
1844
|
+
"src/gates/run.mjs",
|
|
1845
|
+
"src/proof/lock.mjs",
|
|
1846
|
+
"src/util/gate-token.mjs",
|
|
1847
|
+
"test/gates/changed.test.mjs",
|
|
1848
|
+
"test/gates/placeholders.test.mjs"
|
|
1849
|
+
],
|
|
1850
|
+
"depends_on": [
|
|
1851
|
+
"B113"
|
|
1852
|
+
],
|
|
1853
|
+
"note": "root-added 2026-10-13; #16; owner D2=a: fix-round TESTS may use --changed, orchestrator runs full gates before close"
|
|
1854
|
+
},
|
|
1855
|
+
"B100": {
|
|
1856
|
+
"title": "Overlap loop: review-file --wait-block, review.file_loop overlap",
|
|
1857
|
+
"wave": 14,
|
|
1858
|
+
"level": "L2",
|
|
1859
|
+
"status": "landed",
|
|
1860
|
+
"owned": [
|
|
1861
|
+
"docs/how-it-works.md",
|
|
1862
|
+
"docs/reference/config.md",
|
|
1863
|
+
"schema/code-forge.schema.json",
|
|
1864
|
+
"skill/references/code.md",
|
|
1865
|
+
"skill/templates/coder-brief.md",
|
|
1866
|
+
"src/cli/review-file.mjs",
|
|
1867
|
+
"src/config/validate.mjs",
|
|
1868
|
+
"src/worker/queue.mjs",
|
|
1869
|
+
"test/config/schema-coverage.test.mjs",
|
|
1870
|
+
"test/worker/wait-block.test.mjs"
|
|
1871
|
+
],
|
|
1872
|
+
"depends_on": [
|
|
1873
|
+
"B99"
|
|
1874
|
+
],
|
|
1875
|
+
"note": "run-speed E3a; round 1 approved, minors noted (wait-block test 2/4 assertions could be stricter)"
|
|
1876
|
+
},
|
|
1877
|
+
"B114": {
|
|
1878
|
+
"title": "Stop with unknown content is no dead end (#17); TESTS line malformed",
|
|
1879
|
+
"wave": 14,
|
|
1880
|
+
"level": "L2",
|
|
1881
|
+
"status": "landed",
|
|
1882
|
+
"owned": [
|
|
1883
|
+
"docs/how-it-works.md",
|
|
1884
|
+
"skill/references/code.md",
|
|
1885
|
+
"skill/references/review.md",
|
|
1886
|
+
"src/cli/block.mjs",
|
|
1887
|
+
"src/review/fixloop.mjs",
|
|
1888
|
+
"src/review/reopen.mjs",
|
|
1889
|
+
"test/cli/block-tests-line.test.mjs",
|
|
1890
|
+
"test/review/reopen-unknown.test.mjs",
|
|
1891
|
+
"test/review/reopen.test.mjs"
|
|
1892
|
+
],
|
|
1893
|
+
"depends_on": [
|
|
1894
|
+
"B100"
|
|
1895
|
+
],
|
|
1896
|
+
"note": "#17; round 1 approved; built in parallel with B115; minor noted: reopen row lost if worker crashes between round save and state save"
|
|
1897
|
+
},
|
|
1898
|
+
"B115": {
|
|
1899
|
+
"title": "Small follow-ups: Python *_test.py pairing, npm test -- <args>, test cleanup errors",
|
|
1900
|
+
"wave": 14,
|
|
1901
|
+
"level": "L1",
|
|
1902
|
+
"status": "landed",
|
|
1903
|
+
"owned": [
|
|
1904
|
+
"docs/how-it-works.md",
|
|
1905
|
+
"package.json",
|
|
1906
|
+
"test/helpers/run-suite.sh",
|
|
1907
|
+
"skill/references/review.md",
|
|
1908
|
+
"src/review/paired.mjs",
|
|
1909
|
+
"test/no-leak.test.mjs",
|
|
1910
|
+
"test/no-leak-final.test.mjs",
|
|
1911
|
+
"test/review/paired.test.mjs",
|
|
1912
|
+
"test/router.test.mjs",
|
|
1913
|
+
"test/worker/helper-cleanup.test.mjs",
|
|
1914
|
+
"test/worker/helpers.mjs"
|
|
1915
|
+
],
|
|
1916
|
+
"depends_on": [
|
|
1917
|
+
"B114"
|
|
1918
|
+
],
|
|
1919
|
+
"note": "owner 2026-10-13; 2 rounds; noted: 6 old test files call rm(undefined) in cleanup under --test-name-pattern (follow-up); no-leak-final pins report order only at beforeExit"
|
|
1920
|
+
},
|
|
1921
|
+
"B104": {
|
|
1922
|
+
"title": "Commit watch: review.file_loop watch queues owned files from new commits",
|
|
1923
|
+
"wave": 14,
|
|
1924
|
+
"level": "L2",
|
|
1925
|
+
"status": "landed",
|
|
1926
|
+
"owned": [
|
|
1927
|
+
"docs/how-it-works.md",
|
|
1928
|
+
"docs/reference/config.md",
|
|
1929
|
+
"schema/code-forge.schema.json",
|
|
1930
|
+
"skill/references/code.md",
|
|
1931
|
+
"skill/references/review.md",
|
|
1932
|
+
"skill/templates/coder-brief.md",
|
|
1933
|
+
"src/config/validate.mjs",
|
|
1934
|
+
"src/util/exec.mjs",
|
|
1935
|
+
"src/worker/loop.mjs",
|
|
1936
|
+
"src/worker/queue.mjs",
|
|
1937
|
+
"src/worker/watch.mjs",
|
|
1938
|
+
"test/skill/structure.test.mjs",
|
|
1939
|
+
"test/worker/wait-block.test.mjs",
|
|
1940
|
+
"test/worker/watch.test.mjs"
|
|
1941
|
+
],
|
|
1942
|
+
"depends_on": [
|
|
1943
|
+
"B115"
|
|
1944
|
+
],
|
|
1945
|
+
"note": "3 rounds (r2 major fixed by the orchestrator with red→green); noted: activeTickets only from the scheduler pass; stop() during a watch tick still dispatches that pass; watch state reset after realpath; a file replaced by a directory stalls the watch after one skip row; enqueue passes the raw file to enqueueHash"
|
|
1946
|
+
},
|
|
1947
|
+
"B117": {
|
|
1948
|
+
"title": "Proof rule in every context pack, review lens, skill and doc; red→green defined",
|
|
1949
|
+
"wave": 14,
|
|
1950
|
+
"level": "L1",
|
|
1951
|
+
"status": "landed",
|
|
1952
|
+
"owned": [
|
|
1953
|
+
"docs/concepts.md",
|
|
1954
|
+
"docs/how-it-works.md",
|
|
1955
|
+
"docs/overview.md",
|
|
1956
|
+
"docs/tutorial-first-test.md",
|
|
1957
|
+
"skill/SKILL.md",
|
|
1958
|
+
"skill/references/code.md",
|
|
1959
|
+
"skill/references/proof.md",
|
|
1960
|
+
"skill/references/rules-core.md",
|
|
1961
|
+
"skill/templates/coder-brief.md",
|
|
1962
|
+
"src/context/pack.mjs",
|
|
1963
|
+
"src/install/wizard/flags.mjs",
|
|
1964
|
+
"src/proof/rule.mjs",
|
|
1965
|
+
"src/proof/tiers.mjs",
|
|
1966
|
+
"src/review/gate-check.mjs",
|
|
1967
|
+
"src/review/lenses/A.md",
|
|
1968
|
+
"src/review/lenses/B.md",
|
|
1969
|
+
"src/review/lenses/full.md",
|
|
1970
|
+
"src/review/lenses/judge.md",
|
|
1971
|
+
"src/review/lenses/quick.md",
|
|
1972
|
+
"src/review/lenses/recheck.md",
|
|
1973
|
+
"test/context/pack.test.mjs",
|
|
1974
|
+
"test/proof/tiers.test.mjs",
|
|
1975
|
+
"test/review/fixloop.test.mjs",
|
|
1976
|
+
"test/review/packet.test.mjs",
|
|
1977
|
+
"test/review/route.test.mjs",
|
|
1978
|
+
"test/review/test-quality.test.mjs",
|
|
1979
|
+
"test/skill/structure.test.mjs"
|
|
1980
|
+
],
|
|
1981
|
+
"depends_on": [
|
|
1982
|
+
"B104"
|
|
1983
|
+
],
|
|
1984
|
+
"note": "owner 2026-10-13: pass the proof rule to every project built with code-forge; 1 round, 3 minors not-bug; removed dead proofRequirements (mutants: held)"
|
|
1985
|
+
},
|
|
1986
|
+
"B116": {
|
|
1987
|
+
"title": "Test cleanup skips unset paths under --test-name-pattern (built with code-forge run)",
|
|
1988
|
+
"wave": 14,
|
|
1989
|
+
"level": "L1",
|
|
1990
|
+
"status": "landed",
|
|
1991
|
+
"owned": [
|
|
1992
|
+
"test/config/cli-models.test.mjs",
|
|
1993
|
+
"test/config/load.test.mjs",
|
|
1994
|
+
"test/config/refresh.test.mjs",
|
|
1995
|
+
"test/engines/isolation.test.mjs",
|
|
1996
|
+
"test/ledger/outcome.test.mjs",
|
|
1997
|
+
"test/skill/shim.test.mjs"
|
|
1998
|
+
],
|
|
1999
|
+
"depends_on": [
|
|
2000
|
+
"B117"
|
|
2001
|
+
],
|
|
2002
|
+
"note": "dogfood: brief run, review.file_loop watch, worktree isolation; ~8 min wall; 0 findings"
|
|
2003
|
+
},
|
|
2004
|
+
"B118": {
|
|
2005
|
+
"title": "Context pack without a context key; block open refuses whitespace paths that name no file; close warns without green gates",
|
|
2006
|
+
"wave": 14,
|
|
2007
|
+
"level": "L1",
|
|
2008
|
+
"status": "landed",
|
|
2009
|
+
"owned": [
|
|
2010
|
+
"docs/brief-mode.md",
|
|
2011
|
+
"skill/references/code.md",
|
|
2012
|
+
"src/cli/block.mjs",
|
|
2013
|
+
"src/cli/context.mjs",
|
|
2014
|
+
"src/context/pack.mjs",
|
|
2015
|
+
"test/cli/block-close-gates.test.mjs",
|
|
2016
|
+
"test/cli/block-open-owned.test.mjs",
|
|
2017
|
+
"test/context/pack.test.mjs",
|
|
2018
|
+
"test/proof/worktree-flow.test.mjs"
|
|
2019
|
+
],
|
|
2020
|
+
"depends_on": [
|
|
2021
|
+
"B116"
|
|
2022
|
+
],
|
|
2023
|
+
"note": "dogfood findings from B116, built with code-forge run; 0 review findings; the orchestrator updated the B62b malformed-record test for the new close warning"
|
|
2024
|
+
},
|
|
2025
|
+
"B119": {
|
|
2026
|
+
"title": "Transcript grep reads Codex JSON logs by commands only; close names each rule break once",
|
|
2027
|
+
"wave": 14,
|
|
2028
|
+
"level": "L2",
|
|
2029
|
+
"status": "landed",
|
|
2030
|
+
"owned": [
|
|
2031
|
+
"docs/brief-mode.md",
|
|
2032
|
+
"skill/references/code.md",
|
|
2033
|
+
"src/review/gate-check.mjs",
|
|
2034
|
+
"src/util/forbidden.mjs",
|
|
2035
|
+
"test/cli/block-close-rule-break.test.mjs",
|
|
2036
|
+
"test/review/external.test.mjs",
|
|
2037
|
+
"test/util/transcript-codex.test.mjs"
|
|
2038
|
+
],
|
|
2039
|
+
"depends_on": [
|
|
2040
|
+
"B118"
|
|
2041
|
+
],
|
|
2042
|
+
"note": "dogfood finding from B118, built with code-forge run; 1 review warning answered; named mutation (unknown item types fail closed) caught"
|
|
2043
|
+
},
|
|
2044
|
+
"B120": {
|
|
2045
|
+
"title": "Plain gates runs with --run --block write their gate rows",
|
|
2046
|
+
"wave": 14,
|
|
2047
|
+
"level": "L1",
|
|
2048
|
+
"status": "landed",
|
|
2049
|
+
"owned": [
|
|
2050
|
+
"src/proof/lock.mjs",
|
|
2051
|
+
"test/cli/block-close-gates.test.mjs"
|
|
2052
|
+
],
|
|
2053
|
+
"depends_on": [
|
|
2054
|
+
"B119"
|
|
2055
|
+
],
|
|
2056
|
+
"note": "dogfood finding from B119, built with code-forge run; 0 review findings; first dogfood close with no warning"
|
|
2057
|
+
},
|
|
2058
|
+
"B101": {
|
|
2059
|
+
"title": "Opt-in fair share across blocks in the worker pool (review.fair_share)",
|
|
2060
|
+
"wave": 14,
|
|
2061
|
+
"level": "L1",
|
|
2062
|
+
"status": "landed",
|
|
2063
|
+
"owned": [
|
|
2064
|
+
"docs/how-it-works.md",
|
|
2065
|
+
"docs/reference/config.md",
|
|
2066
|
+
"schema/code-forge.schema.json",
|
|
2067
|
+
"skill/references/review.md",
|
|
2068
|
+
"src/worker/loop.mjs",
|
|
2069
|
+
"test/config/schema-coverage.test.mjs",
|
|
2070
|
+
"test/worker/fair-share.test.mjs"
|
|
2071
|
+
],
|
|
2072
|
+
"depends_on": [
|
|
2073
|
+
"B120"
|
|
2074
|
+
],
|
|
2075
|
+
"note": "E4a; built with code-forge run; 0 review findings; the orchestrator re-pinned the schema path count (212 -> 213)"
|
|
2076
|
+
},
|
|
2077
|
+
"B105": {
|
|
2078
|
+
"title": "Cross-process locks for ticket claims, files, blocks and the budget row (E4b part 1)",
|
|
2079
|
+
"wave": 14,
|
|
2080
|
+
"level": "L2",
|
|
2081
|
+
"status": "landed",
|
|
2082
|
+
"owned": [
|
|
2083
|
+
"docs/how-it-works.md",
|
|
2084
|
+
"skill/references/review.md",
|
|
2085
|
+
"src/autopilot/actions.mjs",
|
|
2086
|
+
"src/doctor/index.mjs",
|
|
2087
|
+
"src/doctor/local.mjs",
|
|
2088
|
+
"src/ledger/spend.mjs",
|
|
2089
|
+
"src/review/schema-fallback.mjs",
|
|
2090
|
+
"src/util/file-locks.mjs",
|
|
2091
|
+
"src/worker/engine.mjs",
|
|
2092
|
+
"src/worker/loop.mjs",
|
|
2093
|
+
"test/util/file-locks.test.mjs",
|
|
2094
|
+
"test/worker/claim.test.mjs"
|
|
2095
|
+
],
|
|
2096
|
+
"depends_on": [
|
|
2097
|
+
"B101"
|
|
2098
|
+
],
|
|
2099
|
+
"note": "attempt 1 refused at close (coder transcript read ~/.code-forge/runs); re-run clean; two stopped reviews reopened by the owner and approved"
|
|
2100
|
+
},
|
|
2101
|
+
"B121": {
|
|
2102
|
+
"title": "Watch holds rechecks until the block join",
|
|
2103
|
+
"wave": 14,
|
|
2104
|
+
"level": "L2",
|
|
2105
|
+
"status": "landed",
|
|
2106
|
+
"owned": [
|
|
2107
|
+
"docs/how-it-works.md",
|
|
2108
|
+
"docs/reference/config.md",
|
|
2109
|
+
"schema/code-forge.schema.json",
|
|
2110
|
+
"skill/references/code.md",
|
|
2111
|
+
"skill/references/review.md",
|
|
2112
|
+
"src/worker/watch.mjs",
|
|
2113
|
+
"test/worker/watch.test.mjs"
|
|
2114
|
+
],
|
|
2115
|
+
"depends_on": [
|
|
2116
|
+
"B105"
|
|
2117
|
+
],
|
|
2118
|
+
"note": "Watch mode queues a file's first commit at once; later commits of a file that already has a ticket are held (watch.held row) until review-file --wait-block queues one ticket for the latest content. Stops a half-done fix commit from using the file's review rounds."
|
|
2119
|
+
},
|
|
2120
|
+
"B106": {
|
|
2121
|
+
"title": "Worker registry: one announcement per worker",
|
|
2122
|
+
"wave": 14,
|
|
2123
|
+
"level": "L2",
|
|
2124
|
+
"status": "landed",
|
|
2125
|
+
"owned": [
|
|
2126
|
+
"docs/how-it-works.md",
|
|
2127
|
+
"skill/references/code.md",
|
|
2128
|
+
"src/cli/review.mjs",
|
|
2129
|
+
"src/doctor/local.mjs",
|
|
2130
|
+
"src/doctor/worker-probe.mjs",
|
|
2131
|
+
"src/worker/loop.mjs",
|
|
2132
|
+
"src/worker/queue.mjs",
|
|
2133
|
+
"test/worker/registry.test.mjs"
|
|
2134
|
+
],
|
|
2135
|
+
"depends_on": [
|
|
2136
|
+
"B105"
|
|
2137
|
+
],
|
|
2138
|
+
"note": "Each worker writes <repo>/.code-forge/workers/<pid>-<start_time>.json next to worker.json and beats both; boot counts live entries and announces under one cross-process lock (limit 1); boot prunes dead entries (known start-time mismatch = dead); an unreadable entry blocks boot and doctor lists it; liveWorker keeps the B30 fresh-heartbeat rule."
|
|
2139
|
+
},
|
|
2140
|
+
"B122": {
|
|
2141
|
+
"title": "Join delivers unseen findings before a recheck",
|
|
2142
|
+
"wave": 14,
|
|
2143
|
+
"level": "L2",
|
|
2144
|
+
"status": "landed",
|
|
2145
|
+
"owned": [
|
|
2146
|
+
"docs/how-it-works.md",
|
|
2147
|
+
"skill/references/code.md",
|
|
2148
|
+
"skill/references/review.md",
|
|
2149
|
+
"src/cli/review-file.mjs",
|
|
2150
|
+
"src/worker/queue.mjs",
|
|
2151
|
+
"test/worker/wait-block.test.mjs"
|
|
2152
|
+
],
|
|
2153
|
+
"depends_on": [
|
|
2154
|
+
"B121"
|
|
2155
|
+
],
|
|
2156
|
+
"note": "At review-file --wait-block, a file whose newest review found problems and that changed after it (a commit made blind to the findings) is not rechecked: the join answers status findings with that ticket and writes one delivered marker. The next join rechecks the latest content once. Stops a blind commit from counting as a stall round."
|
|
2157
|
+
},
|
|
2158
|
+
"B123": {
|
|
2159
|
+
"title": "Reopen clears old cap ids after a fresh review",
|
|
2160
|
+
"wave": 14,
|
|
2161
|
+
"level": "L2",
|
|
2162
|
+
"status": "landed",
|
|
2163
|
+
"owned": [
|
|
2164
|
+
"docs/how-it-works.md",
|
|
2165
|
+
"skill/references/review.md",
|
|
2166
|
+
"src/review/gate-check.mjs",
|
|
2167
|
+
"test/review/gate-check-reopen-cap.test.mjs"
|
|
2168
|
+
],
|
|
2169
|
+
"depends_on": [
|
|
2170
|
+
"B122"
|
|
2171
|
+
],
|
|
2172
|
+
"note": "A review.cap row is superseded when a verified human review.reopened row comes after it and then a signed review.round of the file's current content. A superseded cap row adds no ids to the close check, so after a reopen only the fresh review's own findings need a fix, waiver or answer."
|
|
2173
|
+
},
|
|
2174
|
+
"B126": {
|
|
2175
|
+
"title": "Leak test ignores files already in the repo's .code-forge",
|
|
2176
|
+
"wave": 14,
|
|
2177
|
+
"level": "L1",
|
|
2178
|
+
"status": "landed",
|
|
2179
|
+
"owned": [
|
|
2180
|
+
"test/worker/orphan.test.mjs"
|
|
2181
|
+
],
|
|
2182
|
+
"depends_on": [
|
|
2183
|
+
"B113"
|
|
2184
|
+
],
|
|
2185
|
+
"note": "The final-check test in orphan.test.mjs forged an empty baseline, so files already in the repo's .code-forge folder (normal when code-forge builds itself) showed up as leaks and failed npm test. The test now records the folder's current contents as the baseline and still checks the exact planted leak list."
|
|
1828
2186
|
}
|
|
1829
2187
|
}
|
|
1830
2188
|
}
|
package/docs/reference/config.md
CHANGED
|
@@ -136,6 +136,8 @@ Every other key defaults as shown, or is entirely absent from a minimal file. `a
|
|
|
136
136
|
| `review.provider_concurrency.openai` | integer | | `2` | min 1 |
|
|
137
137
|
| `review.provider_concurrency.xai` | integer | | `2` | min 1 |
|
|
138
138
|
| `review.parallel_tickets` | integer | | `3` | min 1; max 16; B42: how many review tickets the worker runs at once (oldest first); 1 = one at a time. Tickets for the same file never overlap. |
|
|
139
|
+
| `review.fair_share` | boolean | | `false` | Give each free ticket slot to the block with the fewest running tickets; ties stay oldest first. |
|
|
140
|
+
| `review.file_loop` | enum: `wait`, `overlap`, `watch` | | `"wait"` | After each green file, enqueue its review. wait (default): wait for its ticket before the next file. overlap: continue coding, then run review-file --wait-block <id> --run <run> before the completion sentinel; inspect findings with --wait <ticket>. watch: commit each green file instead of running review-file. A file's first commit is queued at once. Later commits of a file that already has a ticket of this block are held (a watch.held row) until --wait-block, which queues the latest content once before the sentinel. Older pending tickets are still superseded. |
|
|
139
141
|
| `review.external` | object | | — | |
|
|
140
142
|
| `review.external.required` | boolean | | `false` | B58: true ⇒ block close skips the local per-file review checks (and the --report ticket check), with no terminal and under autopilot, and writes a signed gate.reviews_waived {by: config} row. Unowned changes, proof, no_changes and the transcript grep still refuse. No block may own .code-forge.yml. |
|
|
141
143
|
| `review.external.name` | string | | — | minLength 1; B58: the outside reviewer, written in the review.external and gate.reviews_waived rows. Required when required is true: run start refuses a missing or blank name. |
|
|
@@ -149,15 +151,15 @@ Every other key defaults as shown, or is entirely absent from a minimal file. `a
|
|
|
149
151
|
| `caps` | object | | — | |
|
|
150
152
|
| `caps.coders` | integer | | `2` | min 1 |
|
|
151
153
|
| `gates` | object | | — | |
|
|
152
|
-
| `gates.test` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. |
|
|
153
|
-
| `gates.lint` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. |
|
|
154
|
-
| `gates.types` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. |
|
|
155
|
-
| `gates.format` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. |
|
|
154
|
+
| `gates.test` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. With gates run --run --block --changed, {test_files} expands to changed tests plus stem-paired tests of changed sources, and {changed_files} expands to changed paths for lint or format. Both tokens must be whole argv items and cannot be the command or the only item. Config validation refuses a gate whose command or only item is {changed_files}. Deleted files count for pairing and the threshold, but both tokens receive only files that exist now. Without --changed, {changed_files} is dropped. Changed rows carry scope changed; narrowed rows have no reason. Only fallback rows carry a reason: no_baseline uses today's scope, unpaired uses today's test scope, threshold runs the full suite above the changed-file threshold, and no_changes uses today's scope when nothing is left to run. Gates without either token run unchanged. Any green gates run --run --block records owned file hashes on gate.done, including runs without --changed. When --slug is omitted, these rows go to the run's project ledger. More than 200 owned files means no record, so the next --changed falls back with no_baseline; unreadable inputs also leave no record. A fix-round TESTS line may use --changed; the orchestrator runs full gates before block close. |
|
|
155
|
+
| `gates.lint` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. With gates run --run --block --changed, {test_files} expands to changed tests plus stem-paired tests of changed sources, and {changed_files} expands to changed paths for lint or format. Both tokens must be whole argv items and cannot be the command or the only item. Config validation refuses a gate whose command or only item is {changed_files}. Deleted files count for pairing and the threshold, but both tokens receive only files that exist now. Without --changed, {changed_files} is dropped. Changed rows carry scope changed; narrowed rows have no reason. Only fallback rows carry a reason: no_baseline uses today's scope, unpaired uses today's test scope, threshold runs the full suite above the changed-file threshold, and no_changes uses today's scope when nothing is left to run. Gates without either token run unchanged. Any green gates run --run --block records owned file hashes on gate.done, including runs without --changed. When --slug is omitted, these rows go to the run's project ledger. More than 200 owned files means no record, so the next --changed falls back with no_baseline; unreadable inputs also leave no record. A fix-round TESTS line may use --changed; the orchestrator runs full gates before block close. |
|
|
156
|
+
| `gates.types` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. With gates run --run --block --changed, {test_files} expands to changed tests plus stem-paired tests of changed sources, and {changed_files} expands to changed paths for lint or format. Both tokens must be whole argv items and cannot be the command or the only item. Config validation refuses a gate whose command or only item is {changed_files}. Deleted files count for pairing and the threshold, but both tokens receive only files that exist now. Without --changed, {changed_files} is dropped. Changed rows carry scope changed; narrowed rows have no reason. Only fallback rows carry a reason: no_baseline uses today's scope, unpaired uses today's test scope, threshold runs the full suite above the changed-file threshold, and no_changes uses today's scope when nothing is left to run. Gates without either token run unchanged. Any green gates run --run --block records owned file hashes on gate.done, including runs without --changed. When --slug is omitted, these rows go to the run's project ledger. More than 200 owned files means no record, so the next --changed falls back with no_baseline; unreadable inputs also leave no record. A fix-round TESTS line may use --changed; the orchestrator runs full gates before block close. |
|
|
157
|
+
| `gates.format` | array<string> \| object \| null | | — | An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. With gates run --run --block --changed, {test_files} expands to changed tests plus stem-paired tests of changed sources, and {changed_files} expands to changed paths for lint or format. Both tokens must be whole argv items and cannot be the command or the only item. Config validation refuses a gate whose command or only item is {changed_files}. Deleted files count for pairing and the threshold, but both tokens receive only files that exist now. Without --changed, {changed_files} is dropped. Changed rows carry scope changed; narrowed rows have no reason. Only fallback rows carry a reason: no_baseline uses today's scope, unpaired uses today's test scope, threshold runs the full suite above the changed-file threshold, and no_changes uses today's scope when nothing is left to run. Gates without either token run unchanged. Any green gates run --run --block records owned file hashes on gate.done, including runs without --changed. When --slug is omitted, these rows go to the run's project ledger. More than 200 owned files means no record, so the next --changed falls back with no_baseline; unreadable inputs also leave no record. A fix-round TESTS line may use --changed; the orchestrator runs full gates before block close. |
|
|
156
158
|
| `gates.extra` | object | | — | |
|
|
157
159
|
| `gates.extra.secret_scan` | boolean | | `true` | |
|
|
158
160
|
| `gates.extra.safe_edit` | boolean | | `true` | |
|
|
159
161
|
| `gates.extra.invariants` | string | | — | |
|
|
160
|
-
| `gates.full_suite_threshold_files` | integer | | `10` | min 1; A block that owns more files than this runs the full suite for a {test_files} gate (reason threshold), not its related tests. Owned files are counted this way. A glob or a directory counts the tracked and new (not ignored) files it covers. A path not created yet counts as 1. Outside git each entry counts 1. A git failure runs the full suite. block open --tests names the test files precisely. |
|
|
162
|
+
| `gates.full_suite_threshold_files` | integer | | `10` | min 1; A block that owns more files than this runs the full suite for a {test_files} gate (reason threshold), not its related tests. Owned files are counted this way. A glob or a directory counts the tracked and new (not ignored) files it covers. A path not created yet counts as 1. Outside git each entry counts 1. A git failure runs the full suite. block open --tests names the test files precisely. With gates run --changed, the threshold counts changed files since the last green gates run --run --block instead. |
|
|
161
163
|
| `proof` | object | | — | |
|
|
162
164
|
| `proof.tiers` | object | | — | |
|
|
163
165
|
| `proof.tiers.high` | object | | — | |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codedology/code-forge",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Plan/harden/code/review orchestration CLI and Agent Skill for cross-model, parallel, evidence-gated feature delivery.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"scripts": {
|
|
41
|
-
"test": "
|
|
41
|
+
"test": "sh test/helpers/run-suite.sh",
|
|
42
42
|
"typecheck": "tsc --checkJs --noEmit",
|
|
43
43
|
"release": "node scripts/release.mjs",
|
|
44
44
|
"changelog": "node scripts/changelog.mjs",
|
|
@@ -185,6 +185,8 @@
|
|
|
185
185
|
}
|
|
186
186
|
},
|
|
187
187
|
"parallel_tickets": { "type": "integer", "minimum": 1, "maximum": 16, "default": 3, "description": "B42: how many review tickets the worker runs at once (oldest first); 1 = one at a time. Tickets for the same file never overlap." },
|
|
188
|
+
"fair_share": { "type": "boolean", "default": false, "description": "Give each free ticket slot to the block with the fewest running tickets; ties stay oldest first." },
|
|
189
|
+
"file_loop": { "type": "string", "enum": ["wait", "overlap", "watch"], "default": "wait", "description": "After each green file, enqueue its review. wait (default): wait for its ticket before the next file. overlap: continue coding, then run review-file --wait-block <id> --run <run> before the completion sentinel; inspect findings with --wait <ticket>. watch: commit each green file instead of running review-file. A file's first commit is queued at once. Later commits of a file that already has a ticket of this block are held (a watch.held row) until --wait-block, which queues the latest content once before the sentinel. Older pending tickets are still superseded." },
|
|
188
190
|
"external": {
|
|
189
191
|
"type": "object",
|
|
190
192
|
"additionalProperties": false,
|
|
@@ -240,7 +242,7 @@
|
|
|
240
242
|
"type": "integer",
|
|
241
243
|
"minimum": 1,
|
|
242
244
|
"default": 10,
|
|
243
|
-
"description": "A block that owns more files than this runs the full suite for a {test_files} gate (reason threshold), not its related tests. Owned files are counted this way. A glob or a directory counts the tracked and new (not ignored) files it covers. A path not created yet counts as 1. Outside git each entry counts 1. A git failure runs the full suite. block open --tests names the test files precisely."
|
|
245
|
+
"description": "A block that owns more files than this runs the full suite for a {test_files} gate (reason threshold), not its related tests. Owned files are counted this way. A glob or a directory counts the tracked and new (not ignored) files it covers. A path not created yet counts as 1. Outside git each entry counts 1. A git failure runs the full suite. block open --tests names the test files precisely. With gates run --changed, the threshold counts changed files since the last green gates run --run --block instead."
|
|
244
246
|
}
|
|
245
247
|
}
|
|
246
248
|
},
|
|
@@ -511,7 +513,7 @@
|
|
|
511
513
|
}
|
|
512
514
|
},
|
|
513
515
|
"argvOrNull": {
|
|
514
|
-
"description": "An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason.",
|
|
516
|
+
"description": "An argv array (never a shell string), an {argv, env} object, or null. An argv item that is exactly {test_files} is replaced by the block's test files. It must be a whole item. It cannot be the command or the only item. The test files are the block open --tests paths, else the owned entries that are concrete test files. The item is dropped, and the full suite runs, in two cases. The block owns more files than full_suite_threshold_files (reason threshold). Or no test file is known, or the gate runs without --run/--block (reason no_tests). The gate.red and gate.done rows then carry scope related with test_count, or scope full with reason. With gates run --run --block --changed, {test_files} expands to changed tests plus stem-paired tests of changed sources, and {changed_files} expands to changed paths for lint or format. Both tokens must be whole argv items and cannot be the command or the only item. Config validation refuses a gate whose command or only item is {changed_files}. Deleted files count for pairing and the threshold, but both tokens receive only files that exist now. Without --changed, {changed_files} is dropped. Changed rows carry scope changed; narrowed rows have no reason. Only fallback rows carry a reason: no_baseline uses today's scope, unpaired uses today's test scope, threshold runs the full suite above the changed-file threshold, and no_changes uses today's scope when nothing is left to run. Gates without either token run unchanged. Any green gates run --run --block records owned file hashes on gate.done, including runs without --changed. When --slug is omitted, these rows go to the run's project ledger. More than 200 owned files means no record, so the next --changed falls back with no_baseline; unreadable inputs also leave no record. A fix-round TESTS line may use --changed; the orchestrator runs full gates before block close.",
|
|
515
517
|
"anyOf": [
|
|
516
518
|
{ "type": "array", "minItems": 1, "items": { "type": "string", "minLength": 1 } },
|
|
517
519
|
{
|
package/skill/SKILL.md
CHANGED
|
@@ -64,6 +64,8 @@ State lives in the plan file's header — `facts → planned → hardened → co
|
|
|
64
64
|
- **R16** Proof is exact assertions on the main behaviour
|
|
65
65
|
- **R17** Never relax a rule alone
|
|
66
66
|
|
|
67
|
+
Red→green means an assertion failure on old code, then a pass on new code; no hand mutations; proof scales with risk; no extras beyond acceptance (R16).
|
|
68
|
+
|
|
67
69
|
## §5 Where to read more
|
|
68
70
|
|
|
69
71
|
| when | read |
|