@codedology/code-forge 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +136 -438
  3. package/docs/README.md +1 -1
  4. package/docs/reference/blocks.json +420 -1
  5. package/docs/reference/config.md +7 -0
  6. package/package.json +1 -1
  7. package/schema/code-forge.schema.json +22 -0
  8. package/scripts/first-use.mjs +11 -5
  9. package/skill/SKILL.md +2 -0
  10. package/skill/references/autopilot.md +2 -0
  11. package/skill/references/code.md +25 -1
  12. package/skill/references/review.md +10 -2
  13. package/skill/scripts/forge +1 -1
  14. package/src/autopilot/scopes.mjs +2 -1
  15. package/src/cli/block.mjs +235 -44
  16. package/src/cli/gates.mjs +36 -6
  17. package/src/cli/ledger.mjs +21 -2
  18. package/src/cli/report.mjs +14 -0
  19. package/src/cli/review-file.mjs +56 -16
  20. package/src/cli/run.mjs +44 -7
  21. package/src/cli/status.mjs +7 -3
  22. package/src/cli/upgrade.mjs +95 -15
  23. package/src/config/validate.mjs +13 -1
  24. package/src/gates/acceptance.mjs +7 -3
  25. package/src/gates/expand.mjs +25 -2
  26. package/src/gates/run.mjs +38 -8
  27. package/src/install/link.mjs +12 -6
  28. package/src/ledger/report.mjs +29 -7
  29. package/src/review/accept-hit.mjs +22 -4
  30. package/src/review/engine.mjs +30 -10
  31. package/src/review/finding.schema.json +2 -1
  32. package/src/review/fixloop.mjs +79 -14
  33. package/src/review/gate-check.mjs +22 -3
  34. package/src/review/lenses/recheck.md +3 -0
  35. package/src/review/packet.mjs +26 -0
  36. package/src/state/block.mjs +162 -20
  37. package/src/state/run.mjs +35 -8
  38. package/src/util/forbidden.mjs +14 -0
  39. package/src/util/reaper.mjs +3 -3
  40. package/src/worker/engine.mjs +60 -4
  41. package/src/worker/loop.mjs +19 -10
  42. package/src/worker/queue.mjs +5 -2
package/README.md CHANGED
@@ -1,472 +1,170 @@
1
1
  # @codedology/code-forge
2
2
 
3
- A CLI (`code-forge`) plus one Agent Skill that runs the **plan → harden → code → review** pipeline
4
- for cross-model, parallel, evidence-gated feature delivery — on Claude Code, Codex, Grok, and Solo.
5
-
6
- > **Status:** published on npm. The CLI, the decision layer, the review engine, the worker, the
7
- > proof policy, the installer, the Agent Skill under `skill/` and the example repo under
8
- > `examples/` have all landed (`docs/reference/blocks.json` lists every build block). What changed
9
- > in each version is in [CHANGELOG.md](CHANGELOG.md).
10
-
11
- ## What's new in 0.14
12
-
13
- In the next release:
14
-
15
- In 0.14.0:
16
-
17
- - **A stale review no longer counts as done (B125).** When a file changed during its review and came back to the same content, `review-file --wait-block` now reviews it once more by itself. No `--fresh` by hand.
18
- - **Agent waivers with proof (B124a).** `block waive --yes` now works for a warning or nit finding. The reason must name evidence: a `path:line`, a test file, or an acceptance clause. A fresh judge must agree. The row is marked `by: agent`, and `block close` lists it. A critical finding and `block reopen` stay human-only.
19
- - **Accept a false rule hit (B127).** `block accept-hit <id> --run <r> --rule <rule-id> --line <n> --transcript <path> --reason <text>` lets a human accept one false transcript hit, after a yes in their own terminal. The close then skips that hit only when the rule and the exact line text match. The close lists each accepted hit, and `--json` adds `accepted_hits`. A coder can never run this verb.
20
- - **Undo and check agent waivers (B124b).** `block unwaive <id> <finding> --run <r> --file <path> --reason <text>` lets a human undo one agent waiver. The finding is then open again. `code-forge report` has a new `agent_waivers` section. Set `review.agent_waivers.require_ack: true`, and `block close` waits until a human runs `block ack-waivers <id> --run <r>` and says yes to the list. Both verbs are human-only.
21
- - **Agent reopen with evidence (B124c).** `block reopen <id> --file <path> --reason <text> --yes` lets the orchestrator reopen a stopped file without you. The reason must cite evidence, a fresh judge must agree, and only one agent reopen per block and file is allowed in a run. The row says `by: agent`. `block close --json` lists them in `agent_reopens`. Without `--yes`, a human still confirms.
22
-
23
- ## What's new in 0.13
24
-
25
- In 0.13.0:
26
-
27
- - **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.
28
- - **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.
29
- - **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.
30
- - **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.
31
- - **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.
32
- - **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.
33
- - **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.
34
- - **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.
35
- - **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.
36
- - **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.
37
- - **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.
38
-
39
- ## What's new in 0.12
40
-
41
- In 0.12.0:
42
-
43
- - **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.
44
- - **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.
45
- - **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.
46
- - **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`.
47
- - **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.
48
- - **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.
49
-
50
- ## What's new in 0.11
51
-
52
- In 0.11.0:
53
-
54
- - **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.
55
- - **The close writes the ticket lines (B96).** The coder's final report no longer needs a `reviewed <path> ticket <id>` line per file. `block close` prints one for every file the review gate accepts (approved, waived or answered), with the queue's ticket. `--json` and the block's done file carry them as `reviewed: [{file, ticket, via}]`. With `--report`, a hand line that names another ticket prints `WARN report ticket mismatch <path>` on stderr, and the close goes on.
56
- - **A big-diff file steps up to a full review (B109).** A low-risk file whose diff is too big for the quick review budget used to stop with `split_required`, and splitting it only made the diff bigger. Now the review plans again as one full L2 session. If the diff fits the full budget, the file is reviewed. The `review.plan` row records the step as `step_up`.
57
- - **A file that was too big can be reviewed again (B110).** A first-round `split_required` result ran no review. After you raise the budget and run `run reload`, `review-file` (or `review-file --fresh`) tries again with the same ticket. A recheck stop still needs `block reopen` or `block waive`.
58
- - **A recheck that did not really review never stalls (B111).** A recheck on unchanged content runs no session and counts no round; it returns `reason: 'no-fix-hunks'`. A recheck answer that skips an open finding is a broken answer, not a "still open". So the stall rule sees only real rechecks. The recheck summary now shows each session's status and tokens.
59
- - **Paired files for the reviewer, part 1 (B97).** code-forge can now find a changed file's test file (or a test's source file) by name, and list its test names or exported symbols in a small `## paired` packet section. The section is dropped first when the packet is too big. A reviewer can also ask for a new, untracked test file when the block owns and changed it. B98 sends these to the reviewers.
60
- - **Reviewers see the paired test file (B98).** When a block changes `src/a.mjs` and `test/a.test.mjs`, the reviewer of `src/a.mjs` now gets the test names in a `## paired` section, in the first review and in rechecks. Tests named with `block open --tests` count too. The reviewer is told those tests exist, so it no longer reports them as missing. It can still ask for a test file's body, even a new untracked one the block owns.
61
- - **Faster reviews (B112).** A review ticket reads the diffs of the block's other changed files only when the review asks for them, and only once.
62
- - **No leftover workers (B113).** A worker stops by itself when its run record or its HOME is removed. `npm test` now fails when a test leaves a worker running.
63
-
64
- ## What's new in 0.10
65
-
66
- In 0.10.0:
67
-
68
- - **Choose how long a 1Password key stays cached (B84).** Set `keys.cache_hours` (1 to 24, default 8) in `.code-forge.yml`, or `keys set <name> --op <ref> --cache-hours <n>` for one key. A lower value shortens keys that are already cached at the next read.
69
- - **Warnings before a cached key runs out (B85).** `keys list` and `doctor` warn when a 1Password key has less than 1 hour left. When the cached key expired and 1Password does not answer, `jev ask` prints the exact command to re-link it: `code-forge keys set jev --op <ref>`.
70
- - **A test report reader for red-green proof (B86).** code-forge can now read a JUnit XML test report (XCTest, Swift Testing, PHPUnit, Pest, pytest). A missing, broken or empty report, or an error that is not a failed assertion, never counts as red. B87 connects it to `proof red-green`.
71
- - **Red-green proof for any test runner (B87).** A new `proof.runners` list in `.code-forge.yml` names a runner per test-file glob: an adapter (`junit` or `swift`), an argv with `{test_file}`, `{test_id}`, `{test_filter}` and `{report}`, optional `env` and `timeout_s`. `proof red-green` runs that argv and reads its JUnit report, so PHPUnit, Pest, XCTest or pytest tests can be proven. The list is fixed at `run start`; a bad entry refuses the proof and never falls back to `node:test`.
72
- - **Red-green proof for Swift (B88).** A `proof.runners` entry with `adapter: swift` runs `swift test --parallel --filter {test_filter} --xunit-output {report}` and reads both the XCTest and the Swift Testing reports. The test filter is anchored, so a similar suite or test name is never picked up. A test that does not compile at base is `RED_INVALID compile` (a test of a new API needs the human waiver). Checked live with Swift 6.3.3 and Xcode 26.6.
73
- - **Red-green proof for PHP (B89).** A `proof.runners` entry with `adapter: junit` and `[php, artisan, test, "{test_file}", --filter, "{test_filter}", --log-junit, "{report}"]` proves PHPUnit and Pest tests in a Laravel app. A test of a class the block added is `RED_INVALID import`, also when Laravel prints its AI-agent JSON summary. Checked live with PHP 8.4, Laravel 13, PHPUnit 12 and Pest 4.
74
- - **Red-green proof for Xcode projects (B102).** A `proof.runners` entry with `adapter: xcodebuild` and an `xcode` object (`scheme`, `destination`, `test_target`) proves XCTest and Swift Testing tests through `xcodebuild test` on a simulator or on macOS. code-forge checks first that full Xcode and the simulator are there, runs only the named suite with `-only-testing`, and reads the result bundle. A build failure is `RED_INVALID compile`. code-forge never boots, creates or deletes a simulator.
75
- - **Xcode red-green checked live (B103).** An opt-in live check (`CODE_FORGE_LIVE_XCODE=1`) proves XCTest and Swift Testing tests red→green through `xcodebuild test` on an iPhone simulator. It skips with a reason when full Xcode or a simulator is missing. Verified with Xcode 26.6.
76
- - **Big files go to a big-context reviewer (B90).** Set `review.routes` once, for example `{min_lines: 400, model: <id>, session_timeout_s: 900}`. Files with that many lines get that model and timeout. No more editing `.code-forge.yml` per file. Each routed file gets a signed `review.route` row.
77
- - **Timeouts reach the second level (B91).** A timeout now counts as a broken result, like an answer that fails the schema. At the second broken result on one file, the second-level model is tried at once, in the same ticket. You no longer wait for a second ticket.
78
- - **Test-quality hint (B92).** A test that reads a source file and checks its text is a weak test. The review packet now lists those lines for the reviewer. The reviewer decides if it is a problem. The list is a hint, not a finding.
79
- - **More room for the Codex coder (B93).** New setting `coder.sandbox`. With `profile: toolchain`, the Codex coder may also write to the folders you list in `add_dirs`, such as a build cache. With `profile: full`, the Codex sandbox is off and `doctor` warns you. Secret folders like `~/.ssh` are always refused. The setting is fixed for the whole run.
80
- - **One fix round per block (B94).** The skill now waits for every review and test of a block. Then it sends the coder ONE fix message with every failing test and every open finding. It never sends findings one at a time.
81
- - **Waive and reopen ask you at a terminal (B80).** `block waive` and `block reopen` now ask the human for a yes in their own terminal. There is no `--yes`. With no terminal they record nothing. The prompt is a speed bump, not proof of a human: a pseudo-terminal passes it.
82
-
83
- ## What's new in 0.9
84
-
85
- In 0.9.0:
86
-
87
- - **A lost review state is rebuilt, not reset.** When the review state file of a file is gone (for example, macOS cleaned its temp folder), the worker rebuilds it from the signed ledger and writes a `review.state_restored` row. Rounds, open findings and stops stay as they were. If the ledger cannot rebuild it, the ticket is refused as `review-state-lost`, not `tampered` (#15).
88
- - **Review state no longer lives in the temp folder.** It is saved under `~/.code-forge/runs/<run>/review-state/`, so a temp cleanup or a worker restart does not touch it. A state file from an older run is moved there once, after a check against its signed anchor. `code-forge doctor` warns when a state file of an active run is missing and says whether the ledger can rebuild it (#15).
89
- - **Waiving every finding is a real way out.** A file whose signed review on its current content left findings, all cleared by accepted waivers, now counts as reviewed (`reviewed_by_waiver`, never approved). `block close` writes one signed `gate.review_waived_all` row for it. A critical still needs a human waiver, and a finding with an unknown severity does too (#9).
90
- - **Tests no longer fail because of your own live run.** The test guard used to fail when a code-forge run you had open wrote its lock file during `npm test`. Now new files of a run that existed before the tests are not counted as leaks. A new run or any other new file still fails the tests.
91
- - **A restore brings back the exact reviewed text.** The reviewed text is now also kept as a git object, and the signed ledger points to it. After a lost state file is rebuilt, the next round reviews only what changed since the last review, even when the file changed. If git has removed the object, the round reviews the full file, as before (#15).
92
- - **A fix in another file can answer a finding.** `review-file <file> --block <id> --answers <ids> --of <source>` asks a fresh reviewer whether a change in another owned file of the block fixes findings of the source file. Each finding it judges `resolved` gets a signed `review.answered` row, and the source file can then close as `reviewed_by_waiver` with an `answered` list. If either file changes later, the answer no longer counts. The answering file still needs its own approval (#9).
93
- - **`block reopen` restarts a stopped file.** After you change a file whose review stopped, `code-forge block reopen <id> --run <r> --file <path> --reason <text>` starts a fresh round 1 for it. A file whose review state is lost can be reopened on its current content. Only a human may run it: a coder's command line is blocked, like `block waive`. The block's one L3 step stays used. The same content is refused, so you cannot simply roll again (#12, #15).
94
- - **Safer answers packets and clearer reopen errors (B79).** An id named only by a `review.cap` row with no recorded severity is refused before any reviewer session. The answers packet checks the source file for secrets, stays inside the packet budget and refuses `packet-too-large` instead of going over it. `block reopen` refuses a bad `tmp.root` and names the cause of a failed write.
95
- - **A last-chance patch that fixes something is progress (B73).** When the L3 patch closes at least one old finding and the file is under the round cap, the fix loop goes on at L2 instead of stopping `l3_patch_exhausted`. A stopped answer from `review-file` and the gate's `review_cap` detail now list the exits: `block reopen`, `block waive`, `review-file --answers`, re-decompose.
96
- - **A steadier test suite (B81).** The ledger rotation race test forces the race order through a test hook, so it no longer fails at random under load.
97
- - **Deleted files get a useful review (B74).** When a block deletes an owned file, the review packet says the file is deleted and lists up to 20 files that still name it, so the reviewer can look for dangling references. A deletion still needs an approval.
98
- - **`review-file --fresh` (B75).** Runs a file's review again only when the cached result never counted (`stale`, `unavailable`, or a non-verdict refusal such as `other-run`). A counted result is refused `fresh-needs-reopen` and names `block reopen` and `block waive`; a tampered one is refused `fresh-tampered`. A coder may use it.
99
- - **Another steadier test (B82).** The worker restart test waits for killed sessions to exit instead of checking once, so it no longer fails at random under load.
100
- - **The review exits, in one place (B76).** `skill/references/review.md` §5, `code.md` and `docs/how-it-works.md` name the ways out of a stopped file in order: fix and the human's `block reopen`, `review-file --answers`, `block waive`, re-decompose. They also say `block attempt` never resets review state and that a lost state file is rebuilt from the ledger.
101
- - **`review-file --fresh` fails closed (B83).** When a cached result cannot be put back, the ticket gets a refused `fresh-restore-failed` marker (or keeps its claim), so the worker does not run it by itself. `block reopen` clears it. Messages name the error code only.
102
-
103
- ## What's new in 0.8
104
-
105
- In 0.8.0:
106
-
107
- - **Run only the tests a block touches.** `block open --tests <paths>` names the block's test
108
- files. A gate argv item exactly `{test_files}` becomes those files. When the block owns more
109
- files than `gates.full_suite_threshold_files`, or no test file is known, the full suite runs.
110
- The ledger row says which one ran. A gate can also be `{argv, env}`. Env values are never
111
- printed. Gate env is not a secret store.
112
- - **Laravel works under export, checked live.** A Laravel app on PHPUnit (no Pest) is now
113
- detected. Export copies the Composer `vendor` folder instead of linking it, so the tests load
114
- the block's code, not the main tree's. A live check (`CODE_FORGE_LIVE_PHP=1`) runs a Laravel
115
- app on PHPUnit and on Pest through the export.
116
- - **One git worktree per block.** With `proof.isolation: worktree`, `block open` gives each block
117
- its own git worktree and branch (`proof.worktree.dir`, `branch`, `base`). Blocks in different
118
- trees may own the same files. Nothing is pushed. `block close --remove-worktree` removes the
119
- tree and keeps the branch. Gates, reviews, the close check and the mutation proof of that
120
- block all run on the block's tree, never on the main checkout.
121
- - **A context pack for coders.** Set `context: {rules, lessons, commands, max_lines}`.
122
- `code-forge context pack --run <r> --block <id>` writes one file with the block's header,
123
- the build and test commands, the project rules and the lessons, cut to `max_lines`. It prints
124
- the path and a token estimate, and writes a signed `context.pack` row. Review packets now
125
- carry the same rules and lessons. With no `context` key, nothing changes.
126
- - **Coders prove a green test run.** A coder prints `TESTS <command> exit=<n>` just before its
127
- COMPLETE sentinel. With `context.require_coder_tests: true` (fixed at `run start`),
128
- `block close --report` refuses a report with no such line or a non-zero exit, even when
129
- reviews are waived, and writes a signed `coder.tests` row when it passes.
130
- - **Short status.** `code-forge status [--run <id>] [--json]` prints at most 10 lines per run:
131
- state, mode, spend, and one line per open block with its level, model, last gate and open
132
- findings. It is read-only. Every `block` verb takes `--json` and prints one JSON line, so an
133
- orchestrator never has to read logs or poll transcripts.
134
- - **A signal when a block ends.** Every block end writes `~/.code-forge/runs/<run>/blocks/<id>.done.json`
135
- (status, commit, spend, open findings). With `hooks.on_block_end` (fixed at `run start`),
136
- code-forge also runs your command once per block end, with the block id, status and file path
137
- in its env, under a timeout, and writes a signed `hook.ran` row. A failing hook only warns.
138
- - **Breaking: coders no longer push or open draft PRs by default.** `autonomy.coder_may_push` and
139
- `autonomy.coder_may_open_draft_pr` now default to `false`. `init` asks both (default no) and
140
- writes your answers. To keep the old behaviour, set both to `true` in `.code-forge.yml`.
141
- - **Outside review rounds next to code-forge cost.** `code-forge ledger outside-review --run <r>
142
- --pr <n> --rounds <n> --findings <n> [--link <url>] [--block <id>]…` records how many rounds an
143
- outside reviewer needed on a PR (a later call for the same PR replaces it). `report` gets a
144
- 14th section, `outside_review`: per PR, the rounds and findings next to the code-forge cost
145
- of its blocks.
146
- - **A walk-through for brief-only runs.** [docs/brief-mode.md](docs/brief-mode.md) walks one task
147
- from a brief to a closed block with an outside reviewer: related tests, a worktree, the context
148
- pack, the done file and hook, `status`, and the outside review rounds in `report`. A test runs
149
- the page's own config and steps, so the page and the CLI stay the same.
150
-
151
- ## What's new in 0.7
152
-
153
- In 0.7.7:
154
-
155
- - **Work from a brief, with no plan.** `run start --mode brief` marks the run as brief-only.
156
- Then `block open` without `--level` picks the lane from the rules: the owned files,
157
- `--lines` and `proof.tiers.high.paths`. A signed `decision` row records it with
158
- `source: rules`. `--level` still wins, and `report` shows the mode of each run.
159
-
160
- In 0.7.6:
161
-
162
- - **An outside reviewer can replace the local review.** Set `review.external: {required: true,
163
- name: <reviewer>}` in `.code-forge.yml`. `block close` then skips the per-file review check
164
- and writes a signed `gate.reviews_waived` row with `by: config`. It needs no TTY and works
165
- under autopilot. All other close checks still run. The key is fixed at `run start`, and a
166
- coder can never own `.code-forge.yml`.
167
-
168
- In 0.7.5:
169
-
170
- - **An owned directory owns the files inside it, everywhere.** A block that owns `src/feature`
171
- now owns `src/feature/a.swift` for `block open`, `block claim`, `block rebase`, the scope gate,
172
- proof and the review worker, not only for `block close`. `block open` refuses a second block
173
- that owns a file or folder inside it (or a folder around it), so two coders can no longer edit
174
- the same files at once. A path that is already a file when the block opens owns only itself.
175
-
176
- In 0.7.4:
177
-
178
- - **Code moved between files is no longer read as deleted.** When a block moves code from one
179
- file to another, each file's review packet now says where the lines went (or came from), so the
180
- reviewer of the old file stops reporting the removal as a lost feature, also on rechecks. Every
181
- hunk is still reviewed.
182
-
183
- In 0.7.3:
184
-
185
- - **A model that keeps failing the answer format gets a stand-in.** When a reviewer's answer
186
- fails the schema twice on the same packet and you set `review.second_levels` for that level, the
187
- worker retries that packet once with the second model, and the ledger records it. Each failed
188
- answer's shape (its keys, types and schema errors, never its text) is logged, so you can see
189
- what went wrong.
190
-
191
- In 0.7.2:
192
-
193
- - **Long documents get reviewed.** The packet budget (`review.budgets.full_in`) is now 32,000
194
- tokens, and a Markdown file still too large is reviewed section by section instead of refused;
195
- a `split_required` result now says its size and the budget.
196
-
197
- In 0.7.1:
198
-
199
- - **Short clean reviews count.** A clean pass (no findings, every hunk acknowledged, a summary)
200
- needs only 40 output tokens on any diff size, so a correct short "no defect" review is no
201
- longer refused as `too_short`.
202
-
203
- In 0.7.0:
204
-
205
- - **The close gate now checks every file.** `block close` could close a block with critical
206
- findings still open: files inside an owned folder were skipped, and so was work committed
207
- before `block open` or done in another worktree. Now every reviewed file is checked, a newer
208
- failed review beats an older approval, a critical needs your waiver, a change outside the
209
- block's files is refused, and `--no-require-reviews` asks you at a terminal.
210
-
211
- ## What's new in 0.6
212
-
213
- In 0.6.1:
214
-
215
- - **Never relax a rule alone.** A new skill rule (R17): the orchestrator and the delegate never
216
- change, relax or remove a limit, threshold, budget, gate or review requirement. When a limit
217
- blocks work they stop, show the data, propose options and wait for you.
218
- - **Fixes from using code-forge on itself.** A verb run from a subfolder now uses the project's
219
- ledger and config. `plan check` reads the list form the template shows. `facts` checks a flag
220
- with `grep -rn -- <flag> <source folder>` instead of `--help`, so the check runs in the
221
- delegate's sandbox.
222
-
223
- In 0.6.0:
224
-
225
- - **Autopilot.** Step away for up to 24 hours. `code-forge autopilot start` grants a delegate (a
226
- fresh closed-book L2 or L3 session, never Codex) a few of your decisions: waive a warning or a
227
- nit, one extra fix round past the review cap, the coder level. The orchestrator asks the
228
- delegate first (`autopilot ask`) and acts only on an answer it acted on. A fixed deny list in
229
- the code keeps the rest yours: critical and proof waivers, skipping reviews, plan and design
230
- approval, any limit or rule change, budget raises, merges, destructive actions. Every answer is
231
- a signed ledger row; each waiver opens a GitHub issue. See [docs/autopilot.md](docs/autopilot.md).
232
- - **Budget per category.** `--budget review=<usd>,coding=<usd>` pauses a category at `--stop-at`
233
- (default 0.9) of its cap until you return. `autopilot approve` (only you, at a terminal) changes
234
- one setting until a time and puts it back by itself. While a grant is active, `run reload`
235
- refuses any limit key.
236
- - **A live log for your return.** In Claude Code the orchestrator keeps one Claude Docs page per
237
- run with two tabs: Binnacle (status at a glance, decisions, blocks, open questions, actions only
238
- you can take, incidents, timeline) and Full log (every event, newest first). `autopilot status`
239
- and `autopilot stop` print its link; without the connector they print two Markdown files in the
240
- run dir (`autopilot binnacle`, `autopilot log`).
241
- - **From 0.5.x, not listed before:** two files of one block can no longer both take the block's one
242
- L3 patch rung (0.5.0), and a maintainer can install a tagged release before it is on npm
243
- ([getting-started](docs/getting-started.md#keeping-it-up-to-date), 0.5.1).
244
-
245
- ## What's new in 0.5
246
-
247
- - **Parallel review.** The worker reviews `review.parallel_tickets` files at once (default 3), with
248
- a session limit per provider (`review.provider_concurrency`), backoff on rate limits, and
249
- `budget.usd` still holding. `code-forge review` now waits on all files under one `--max`
250
- deadline and prints each result as it finishes. `code-forge doctor` shows the numbers;
251
- `npm run bench:review` measured 6 reviews in 12 s at 1 and 4 s at 3.
252
- - **`code-forge facts` verifies again.** It dropped every answer in 0.4.0; now answers match, and a check
253
- that breaks the read-only rules marks only its own claim as not counted, with the reason.
254
- - **Clearer budget refusals.** A session refused because other running sessions hold the budget says
255
- how much they hold and what this session would cost.
256
- - **Plan approval in plan mode.** The skill shows a checked plan to you in the harness's plan mode
257
- (Claude Code: EnterPlanMode → ExitPlanMode) before any block starts.
258
-
259
- ## What's new in 0.4
260
-
261
- - **Cost control.** Set `budget.usd` per run: one warning at 80%, no new session at 100%. Every
262
- session row carries an estimated `usd`; `report` and `run status` show the spend, and
263
- `ledger add coder --usd` records spend code-forge did not see.
264
- - **Cheaper, faster fixes.** One review round that leaves 2 or more warnings climbs the coder one
265
- level (`escalation.*`). Docs and contract blocks code at L1 or higher and skip multimodel review;
266
- a file with risk 0–1 gets one reviewer (`review.single_reviewer_max_risk`).
267
- - **Change the config mid-run.** `code-forge run reload --run <id>` re-reads `.code-forge.yml`
268
- without stopping open blocks.
269
- - **Stricter plans.** `plan check` refuses a block whose level is not the lane recorded with
270
- `jev ask lane --block <id>` (or `--rules` without Jev), and prints the lane of every block.
271
- `block close --report <file>` fails a coder report that does not name a review ticket per file.
272
- - **Codex is refused for closed-book roles** (reviewer, judge, System 2, plan author): it always
273
- has a shell. See [Security model](#security-model).
274
- - **Steadier reviews.** A timed-out review session is retried once; `review.session_timeout_s`
275
- defaults to 300; a live worker with a fresh heartbeat is never reported down.
276
- - **Better error reports.** `logs report --with-doctor` adds a cleaned setup check; errors list the
277
- last 5 command names; recovered problems are logged as warnings; an error that a newer version
278
- fixes tells you to upgrade instead of filing it.
279
- - **Earlier checks.** `validate` refuses an effort the level's provider cannot take (for example
280
- `xhigh` on an openai level), so nothing fails when the session starts.
281
-
282
- Fixed in 0.3.1 and 0.3.2: Claude reviewer sessions no longer fail at once on the `--json-schema`
283
- flag; Grok answers are read from Grok's own answer envelope; Jev `score` questions (such as `risk`)
284
- no longer fall back to rules; and a clean review of a tiny diff (20 added lines or fewer) needs only
285
- 40 output tokens, so it is no longer refused as `too_short`.
286
-
287
- ## What ships
288
-
289
- - A CLI (`code-forge`), installed globally with `npm install -g @codedology/code-forge`; `code-forge
290
- init` then links the skill into every detected harness (Claude Code, Codex, Grok, …).
291
- - One Agent Skill (`skill/SKILL.md` + `references/`) that is prose only — every fact (model ids,
292
- efforts, commands, thresholds, paths) lives in config or in the CLI, never in the skill text.
293
- - A JSON Schema for `.code-forge.yml` (`schema/code-forge.schema.json`), documented in
294
- `docs/reference/config.md` (generated — see below).
295
-
296
- See the skill's `skill/references/` for the full architecture, decision layer, review engine, proof
297
- policy and security model; `docs/reference/blocks.json` lists the build blocks.
3
+ A CLI and Agent Skill for cross-model, parallel, evidence-gated feature delivery.
4
+
5
+ Latest: 0.15.0 - see [CHANGELOG.md](CHANGELOG.md)
6
+
7
+ ## The problem
8
+
9
+ An agent can write code quickly, but you still have to decide what to build and how to check it.
10
+ Long tasks lose context, parallel edits collide, and a green test can miss the intended behavior.
11
+ code-forge splits work into owned blocks, gives each change a fresh review, and records proof.
12
+ You approve the plan and keep control of budgets, permissions, and landing the result.
298
13
 
299
14
  ## Install
300
15
 
16
+ Requires Node.js >= 22 and git. Install the CLI with `npm install -g @codedology/code-forge`.
17
+ The scoped npm name is only for installation; the command is `code-forge`.
18
+ The unscoped npm package `code-forge` is an unrelated tool.
19
+
20
+ Inside your repository, run the setup wizard:
21
+
301
22
  ```bash
302
- npm install -g @codedology/code-forge
303
23
  code-forge init
304
24
  ```
305
25
 
306
- The scoped name is used only to install; the command is `code-forge`. The unscoped npm package
307
- `code-forge` is a different, unrelated tool.
308
-
309
- The wizard asks a few short questions (tools, harnesses, provider matrix, multimodel, keys,
310
- engine), every one with a default on Enter. Gates and proof settings come from the project:
311
- `init` prints what it found, marks what it left blank, and lets you use, customize or leave them
312
- for later. Non-interactively:
26
+ Press Enter for defaults for tools, harnesses, providers, multimodel review, keys, and engine.
27
+ The wizard detects gates and proof settings, marks blanks, and lets you use, customize, or defer
28
+ them. It writes `.code-forge.yml` and links the skill into detected harnesses. Re-running it
29
+ keeps what it already wrote. For a first try without a System-1 (Jev) key:
313
30
 
314
31
  ```bash
315
32
  code-forge init --no-interaction --no-jev
316
33
  ```
317
34
 
318
- `--no-jev` skips the System-1 key for a first try; drop it and pass `--jev-ref <1Password item ID>`
319
- (or the item link, or `op://vault/item/field`; code-forge finds the vault and the key field) or
320
- `--jev-env MY_JEV_KEY` once you have one. A second run of `init` changes nothing it already wrote.
35
+ When ready, use `--jev-ref <1Password item ID|link|op://vault/item/field>` or
36
+ `--jev-env MY_JEV_KEY` instead of `--no-jev`. See [setup details](docs/getting-started.md).
321
37
 
322
- To upgrade: `npm install -g @codedology/code-forge@latest`, then `code-forge upgrade` (re-copies
323
- skill installs made with `--copy`). See [docs/getting-started.md](docs/getting-started.md#keeping-it-up-to-date).
38
+ ### What ships
324
39
 
325
- ## Quickstart
40
+ - The `code-forge` CLI and one prose-only [Agent Skill](skill/SKILL.md), with supporting
41
+ [references](skill/references/). Model IDs, efforts, commands, thresholds, and paths come from
42
+ config or the CLI.
43
+ - A JSON Schema for `.code-forge.yml` and its generated [configuration reference](docs/reference/config.md).
44
+ - An [example repository](examples/) and a [build-block map](docs/reference/blocks.json).
326
45
 
327
- Once `init` has written `.code-forge.yml`, these all run for real:
46
+ ## 5-minute quickstart
47
+
48
+ After setup, check the configuration, selected model, and installed links:
328
49
 
329
50
  ```bash
330
- code-forge validate # loads and validates .code-forge.yml
331
- code-forge resolve L1 # {provider, model, effort, fallback, cli} for a level
332
- code-forge doctor --quick # config + links + key resolution only
333
- code-forge list # what is installed where, and whether it still resolves
334
- code-forge keys list # NAME / SOURCE / BACKEND / EXPIRES — never a value; WARN under 1 h left
335
- code-forge models # the model catalog per provider
336
- code-forge --help # every verb, one per line
51
+ code-forge validate
52
+ code-forge resolve L1
53
+ code-forge doctor --quick
54
+ code-forge list
55
+ code-forge keys list
56
+ code-forge models
57
+ code-forge --help
337
58
  code-forge version
338
59
  ```
339
60
 
340
- ## Review only
341
-
342
- To review code you already wrote — no plan, no coder, no proof — run this in the repository:
343
-
344
- ```bash
345
- code-forge review # verdict + fix list per changed file; exit 0 only if all approved
346
- ```
61
+ `resolve` prints the provider, model, effort, fallback, and CLI for a level. `doctor --quick`
62
+ checks config, links, and key resolution; `keys list` prints sources and expiry, never values,
63
+ and warns with less than one hour left.
347
64
 
348
- It reviews your branch against the merge base with the default branch (on the default branch: your
349
- uncommitted work), with the same fresh, closed-book reviewer sessions a block gets. Narrow it with
350
- `--files <path…>`, state the change with `--intent "<text>"`, pick the base with `--base <ref>`, or
351
- get one JSON document with `--json`. Exit codes: `0` all approved or nothing to review, `1` any
352
- finding, stop or unavailable review, `2` usage. See [docs/review-only.md](docs/review-only.md).
65
+ Write a brief describing the change and how you will know it works. In your agent, invoke
66
+ `/code-forge full path/to/brief.md`: it plans, hardens, asks you to approve the plan, then codes.
67
+ Use `/code-forge plan|harden|code <file>` for one phase at a time.
68
+ Set a per-run `budget.usd` before starting paid sessions: one warning at 80%, no new session at 100%.
69
+ The [first-test tutorial](docs/tutorial-first-test.md) walks through a complete delivery;
70
+ [brief mode](docs/brief-mode.md) covers one small task without a plan.
353
71
 
354
- ## The verbs
72
+ ### Review only
355
73
 
356
- Verbs are discovered from `src/cli/*.mjs` — adding one never touches the router
357
- (`bin/code-forge.mjs`), so this list is exactly `code-forge --help`'s output plus each verb's own
358
- usage line.
74
+ For code you already wrote, run this in the repository:
359
75
 
360
- | Verb | Usage |
361
- |---|---|
362
- | `init` | `code-forge init [--no-interaction] [--tools recommended\|current] [--yes-tool <tool>]… [--harness a,b] [-g\|-p] [--copy] [--provider P] [--level Ln=model[:effort][@provider]]… [--refresh-models] [--multimodel on\|off] [--second-provider P] [--jev-ref <item-id\|link\|op://…> \| --jev-env NAME \| --no-jev] [--engine auto\|solo\|harness] [--solo-project N] [--gate name=cmd]… [--proof isolation=export\|lock \| high=a,b \| link_dirs=a,b \| copy_untracked=a,b]… [--coder-may-push yes\|no] [--coder-may-open-draft-pr yes\|no] [--skip-doctor]` |
363
- | `doctor` | `code-forge doctor [--quick] [--json] [--cwd <dir>]` |
364
- | `tools` | `code-forge tools [--json]` · `code-forge tools install [<id>…] [--yes] [--dry-run]` — see and install the recommended tools (claude, codex, gemini, grok, op, solo) |
365
- | `validate` | `code-forge validate [--file <path>]` |
366
- | `resolve` | `code-forge resolve <L0\|L1\|L2\|L3>` |
367
- | `run` | `code-forge run start [--cwd <dir>] [--run <id>] [--engine <e>] [--worker-pid <pid>]` · `run start --reattach --run <id> [--worker-pid <pid>]` · `run status --run <id>` (with spent and budget USD) · `run reload --run <id>` (re-read `.code-forge.yml` mid-run) · `run end --run <id>` |
368
- | `block` | `code-forge block open <id> --run <r> [--level L<n>] --owned <paths…> --acceptance <file> [--brief <file>] [--attempt <n>] [--base <sha>] [--lines <n>] [--kind code\|docs\|contract]` · `block attempt\|rebase <id> --run <r>` · `block close <id> --run <r> [--transcript <file>] [--report <file>] [--no-require-reviews]` · `block claim <id> <path> --run <r>` · `block stop <id> --run <r> --reason <text>` · `block waive <id> <finding-id> --run <r> --file <path> --reason <text> [--yes]` · `block reopen <id> --run <r> --file <path> --reason <text> [--yes]` (without `--yes` you run them in your own terminal and they ask for a yes; with `--yes` the reason must cite evidence, a fresh judge must agree, and the row is `by: agent`) · `block accept-hit <id> --run <r> --rule <rule-id> --line <n> --transcript <path> --reason <text>` · `block unwaive <id> <finding-id> --run <r> --file <path> --reason <text>` · `block ack-waivers <id> --run <r>` (these three are human-only) |
369
- | `worker` | `code-forge worker --run <id> [--cwd <dir>] [--poll-ms <n>] [--once]` — started detached by `run start`, never by a coder |
370
- | `review` | `code-forge review [--base <ref>] [--files <path…>] [--acceptance <file> \| --intent "<text>"] [--run <id>] [--max <seconds>] [--json] [--keep-run]` — review only: no coder, no proof, never closes a block |
371
- | `review-file` | `code-forge review-file <path> --block <id> [--run <id>]` (enqueue) · `review-file --wait <ticket> [--max <seconds>s]` (poll, default 90s; still running at `--max` prints `status: pending, reason: wait_timeout`) |
372
- | `spawn` | `code-forge spawn --level L0\|L1\|L2\|L3 --role <role> --brief <file> [--schema <file>] [--cwd <dir>] [--run <id>] [--block <id>] [--timeout <seconds>] [--background]` |
373
- | `s2` | `code-forge s2 --packet <file.json> [--run <id>] [--block <id>] [--timeout <seconds>]` |
374
- | `author` | `code-forge author --job plan\|harden --brief <file> [--facts <file>] [--draft <file>] [--answers <file>] [--out <file>] [--run <id>] [--timeout <seconds>]` |
375
- | `facts` | `code-forge facts --brief <file> [--sources <path>…] [--out <file>] [--run <id>] [--timeout <seconds>]` |
376
- | `plan` | `code-forge plan check <plan-file> [--facts <sheet>] [--slug <slug>]` — every block's level must be the lane recorded by `jev ask lane --block <id>`; prints `lanes: B1 L1 (rules) · …` |
377
- | `proof` | `code-forge proof tier --file <path> --risk <0-3> [--security] [--cwd <dir>]` · `proof export <block> --run <r> [--remove]` · `proof lock\|unlock\|restore <block> --run <r>` · `proof red-green <block> --run <r> --test <file[::case]> [--mechanism revert\|assertion-deletion]` (a non-`node:test` file runs through its `proof.runners` entry) |
378
- | `gates` | `code-forge gates detect\|run\|secret-scan\|safe-edit\|scope\|acceptance\|transcript-grep --cwd <dir> …` |
379
- | `jev` | `code-forge jev ask <question-id> --state <file> [--cwd <dir>] [--slug <slug>] [--key-ref <ref>] [--block <id>] [--plan <file>] [--rules]` — `--rules` answers `lane`, `risk` or `security_sensitive` without Jev; writes to the project's ledger slug |
380
- | `keys` | `code-forge keys list \| set <name> [--op <item-id\|link\|op://ref> [--cache-hours <1-24>]] \| test <name> [--ref <ref>] \| remove <name>` |
381
- | `ledger` | `code-forge ledger tail --slug <slug> [--n\|-n <count>]` · `ledger calibration --slug <slug> [--question <id>]` · `ledger outcome --slug <slug> --pr <n> --ci red\|green\|reverted` · `ledger outcome --slug <slug> --scan-git [--cwd <dir>] [--days <n>]` · `ledger add coder --run <r> --block <b> --usd <n> [--note "..."]` |
382
- | `report` | `code-forge report --slug <slug> [--json] [--export <dir>]` — 13 sections, then the spend per run (open blocks included) and the total |
383
- | `models` | `code-forge models [--refresh --from-cli-caches]` |
384
- | `list` | `code-forge list` |
385
- | `remove` | `code-forge remove [<harness>] [--scope project\|global]` |
386
- | `upgrade` | `code-forge upgrade [--source <path>]` |
387
- | `logs` | `code-forge logs [--last N] [--json]` · `logs summary [--days N] [--json]` · `logs clear [--yes]` · `logs path` — the local error log (`~/.code-forge/logs/errors.jsonl`): errors, warnings, and `[fixed in X.Y.Z]` marks |
388
- | `logs report` | `code-forge logs report [--last N] [--kind K] [--verb V] [--note "text"] [--include-warnings] [--with-doctor] [--no-ai] [--allow-old] [--force] [--dry-run] [--yes]` — share selected errors as a public GitHub issue; you see the full text first and say yes once. An error a newer version fixes is not filed unless `--force` |
389
- | `autopilot` | `code-forge autopilot start --run <id> --until <ISO-8601 with offset> --delegate <L2\|L3> --allow <scope,…> [--deny <scope,…>] [--budget <category>=<usd>,…] [--stop-at <0..1>] [--yes]` · `autopilot status --run <id> [--json]` · `autopilot stop --run <id>` (both print the live log's link, or the two Markdown files) · `autopilot ask --run <id> --scope <scope> --question <text> [--options a,b,…] [--context-file <path>] [--block <id>] [--file <path>] [--finding <id>] [--json]` · `autopilot waive\|round\|level … --decision <id>` · `autopilot approve --run <id> --key <dot.path> --value <json> --until <time>` (owner only, at a terminal) · `autopilot binnacle --run <id> [--json\|--markdown] [--link <https url>]` · `autopilot log --run <id> [--json\|--markdown]` — the owner's time-boxed grant to a delegate; see [docs/autopilot.md](docs/autopilot.md) |
390
- | `help` / `version` | `code-forge --help` (or no verb) · `code-forge --version` |
391
-
392
- `run`, `block`, `worker`, `spawn`, `s2`, `author`, `facts` and `review-file` are what the Agent
393
- Skill's loop calls during a real block; you will not usually type them by hand, but they are plain
394
- CLI verbs like any other and every one of them is exercised by this package's own test suite.
76
+ ```bash
77
+ code-forge review
78
+ ```
395
79
 
396
- ## Security model
80
+ It reviews the branch against the merge base with the default branch, or uncommitted work on
81
+ the default branch, using fresh closed-book sessions. It runs no planner, coder, or proof.
82
+ Narrow with `--files <paths…>`, choose `--base <ref>`, explain with `--intent "<text>"`, or use
83
+ `--json`. Exit 0 means all approved or nothing to review; 1 means a finding, stop, or unavailable
84
+ review; 2 means usage. See [review-only details](docs/review-only.md).
397
85
 
398
- - **`signer: same-user boundary only`.** Every review/gate-relevant ledger row is HMAC-signed with
399
- a per-project key, so tampering by a different user or a rewritten history is detectable.
400
- `doctor` always prints this line — the signature is not a defense against an attacker who
401
- already runs code as you, and no part of code-forge claims otherwise.
402
- - **Keys never reach a coder process.** Provider and Jev keys resolve only inside the worker or the
403
- orchestrator's own CLI calls (`env:<NAME>` → OS keychain → 1Password, cached for
404
- `keys.cache_hours`: default 8 h, at most 24 h → ask at setup only). `keys list`/`keys test` never print a value; every stdout/stderr path is redacted.
405
- - **A forbidden-command list** stops a coder from starting its own worker, waiving a review, or
406
- running other orchestrator-only actions — rendered into each provider's own deny-list mechanism
407
- (`--disallowedTools` for Claude, an execpolicy rules file plus prose for Codex).
408
- - **Closed-book reviews.** Reviewers, judges, System 2 and the plan author see the packet and
409
- nothing else: Claude runs them with no tools, Grok with every tool denied. Codex (provider
410
- `openai`) has no mode without a shell, so code-forge refuses it for those roles: `validate`
411
- warns, `resolve` marks the level `closed_book: "refused"`, `doctor` fails its isolation row, and
412
- the session is never started. Codex coders are unchanged. `review.allow_open_book_codex: true`
413
- accepts the risk and keeps Codex in those roles, with a warning on every surface.
414
- - **The error log stays on your machine.** A failed verb is logged to
415
- `~/.code-forge/logs/errors.jsonl` with flag names but never flag values, and with home folder,
416
- project, emails, `op://` references and 1Password item IDs replaced. `logs report` cleans the
417
- text twice (built-in rules, then an AI check), stops on anything that looks like a key, shows
418
- you the full issue and sends nothing without your yes. `CODE_FORGE_NO_ERROR_LOG=1` turns the log,
419
- the warnings and the command list off. Every field is listed in [docs/privacy.md](docs/privacy.md).
420
- - **No mutation testing.** Neither this package's own tests nor the product it ships run mutation
421
- testing (the owner's ruling R14/Q16, 2026-09-25). Coders do not make hand mutations either: each new
422
- 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
423
- assertions, plus a red→green runner that proves a new test fails before the fix and passes after (`node:test`
424
- built in; any other runner through a `proof.runners` entry that writes a JUnit report).
425
-
426
- ## Configuration reference
427
-
428
- `schema/code-forge.schema.json` is the source of truth for `.code-forge.yml`.
429
- [docs/reference/config.md](docs/reference/config.md) lists every key with its type and default.
430
- Keys added in 0.4, 0.5 and 0.6 (`review.parallel_tickets` and `review.provider_concurrency` are
431
- new in 0.5, `autopilot.min_confidence` in 0.6):
432
-
433
- | Key | Default | What it does |
434
- |---|---|---|
435
- | `budget.usd` | none | per-run spend stop in USD: one warning at 80%, no new session at 100% |
436
- | `escalation.after_rounds_with_warnings` | `1` | rounds with many warnings at one level before the coder climbs (`0` turns it off) |
437
- | `escalation.warning_threshold` | `2` | how many open warnings make a round "heavy" (any critical counts too) |
438
- | `levels.coder_floor_docs` | `L1` | the lowest level that codes a docs or contract block |
439
- | `review.single_reviewer_max_risk` | `1` | at or below this risk a file gets one reviewer and no judge |
440
- | `review.multimodel_for_docs` | `false` | let docs and contract blocks use multimodel review too |
441
- | `review.allow_open_book_codex` | `false` | let Codex run reviewer, judge, System 2 and plan author anyway |
442
- | `review.session_timeout_s` | `300` | a review session that runs longer is killed and retried once |
443
- | `review.routes` | none | big files go to another model: a file with at least `min_lines` lines is reviewed by the rule's `model`, with its own `session_timeout_s` and `second` level |
444
- | `review.parallel_tickets` | `3` | review tickets the worker runs at once (1 to 16); `1` reviews one file at a time |
445
- | `review.provider_concurrency` | anthropic `4`, openai `2`, xai `2` | review sessions at once per provider |
446
- | `autopilot.min_confidence` | `0.7` | the lowest delegate confidence that is acted on; below it the question goes to you |
447
-
448
- `code-forge block open … --kind code|docs|contract` sets a block's kind when its file endings do
449
- not say it. The reference page is generated:
86
+ ## How it works
450
87
 
451
- ```bash
452
- node scripts/gen-config-doc.mjs # regenerate docs/reference/config.md
453
- node scripts/gen-config-doc.mjs --check # exit 0 if it's already up to date, 1 otherwise
88
+ ```text
89
+ plan -> code -> review -> proof -> land
90
+ ^ | |
91
+ | +<--fix-+
92
+ +-- human approval after hardening
454
93
  ```
455
94
 
456
- ## Development
95
+ The skill checks and hardens the plan before your approval. Coders work in blocks with explicit
96
+ owned files and acceptance clauses; independent blocks can run in parallel. A worker runs fresh
97
+ reviewer sessions outside the coder's sandbox. Fix rounds are bounded; unresolved work stops.
98
+ Tests and red→green proof establish that a change meets its acceptance clauses before closing.
99
+ You control the final merge and publish permissions; coders cannot push or open draft PRs by
100
+ default. See [the workflow](docs/how-it-works.md) and [concepts](docs/concepts.md).
457
101
 
458
- ```bash
459
- npm install
460
- npm test # node --import ./test/helpers/isolate.mjs --test 'test/**/*.test.mjs'
461
- npm run typecheck # tsc --checkJs --noEmit
462
- ```
102
+ ## Key commands
463
103
 
464
- Node >= 22 required (ruling R7). No build step — the package ships plain ESM `.mjs`, run directly
465
- by Node. `docs/reference/blocks.json` maps each build block to the files it owns and what it
466
- depends on, kept in sync with the maintainer's design plan.
104
+ | Command | Use it to |
105
+ |---|---|
106
+ | `code-forge init` | Configure the project and install the skill |
107
+ | `code-forge doctor --quick` | Check config, links, and keys |
108
+ | `code-forge review` | Review existing changes without a coding run |
109
+ | `code-forge run start\|status\|reload\|end` | Manage a run and inspect its spend |
110
+ | `code-forge block open\|close\|stop` | Track owned work and enforce its acceptance gates |
111
+ | `code-forge review-file` | Enqueue a file review or wait for its ticket |
112
+ | `code-forge proof tier\|red-green` | Choose proof strength and prove a test fails before the fix |
113
+ | `code-forge gates detect\|run` | Discover and run project checks |
114
+ | `code-forge keys list\|set\|test\|remove` | Manage key references without printing secrets |
115
+ | `code-forge report` | Inspect recorded outcomes and costs |
116
+ | `code-forge logs` | Inspect local errors; `logs report` previews a public issue |
117
+ | `code-forge upgrade` | Refresh installed skill copies after upgrading the package |
118
+ | `code-forge --help` | List every verb; each verb prints its own usage on bad arguments |
119
+
120
+ The skill normally calls `run`, `block`, `worker`, `spawn`, `s2`, `author`, `facts`, and
121
+ `review-file` for you. See the [workflow](docs/how-it-works.md) for these lower-level operations.
122
+ To upgrade, run `npm install -g @codedology/code-forge@latest`, then `code-forge upgrade` for a version summary and release notes; add `--plain` for just the install lines.
123
+
124
+ ### Configuration reference
125
+
126
+ [schema/code-forge.schema.json](schema/code-forge.schema.json) is the source of truth.
127
+ The reference lists every key, type, and default, including budget, escalation, coder floors,
128
+ review risk, multimodel, concurrency, and timeout settings.
129
+ `review.routes` sends big files to another model with its own timeout and second level.
130
+ `block open --kind code|docs|contract` overrides the kind inferred from filenames.
131
+ Regenerate the reference with `node scripts/gen-config-doc.mjs`; add `--check` to check it.
132
+
133
+ ## Supported agents
134
+
135
+ Use Claude Code, Codex, or Grok as agent harnesses, or Solo as the execution engine.
136
+ Gemini, Cursor, and Copilot have detection and skill linking only.
137
+ See [agent support and limits](docs/overview.md) for adapters and degraded modes.
138
+ Closed-book role restrictions are described below.
139
+
140
+ ## Security model
467
141
 
468
- Releasing: record changes with `npm run changelog -- <type> "<text>"` and fixed error reports with
469
- `npm run known-fix -- add <fp> <version> "<summary>"`, then `npm run release -- <patch|minor|major|x.y.z> [--dry-run]`
470
- bumps, moves the README's "In the next release:" bullets under the new version, checks the config
471
- doc, commits and tags (it never pushes or publishes). Publish with `npm publish` from your
472
- machine, then push the tag: CI only creates the GitHub release. See [docs/releasing.md](docs/releasing.md).
142
+ Review and gate rows are HMAC-signed: `signer: same-user boundary only`. A process running as
143
+ you can read the signing key; this does not defend against that process. `doctor` states the limit.
144
+ Provider and Jev keys resolve only in the worker or orchestrator: environment → OS keychain →
145
+ 1Password (cached for 8 hours by default, at most 24) → setup prompt. Keys never reach coders;
146
+ key commands print no values and output is redacted. Provider deny lists restrict coder actions.
147
+
148
+ Reviewers, judges, System 2, and the plan author see only their packet: Claude has no tools and
149
+ Grok has every tool denied. Codex always has a shell, so those roles are refused by default;
150
+ `review.allow_open_book_codex: true` opts into the risk with warnings.
151
+ Errors stay in a local, cleaned log. `logs report` cleans twice, checks for keys, previews the
152
+ issue, and sends only with your yes; `CODE_FORGE_NO_ERROR_LOG=1` disables logging.
153
+ Proof uses unit/feature tests and red→green, with no mutation testing or hand mutations.
154
+ See [security details](skill/references/security.md) and [privacy](docs/privacy.md).
155
+
156
+ ## Links
157
+
158
+ - [Documentation](docs/): setup, concepts, tutorials, and reference pages.
159
+ - [CHANGELOG.md](CHANGELOG.md): all per-version release history.
160
+ - Roadmap: [public feature ideas](https://claude.ai/artifact/BmeWyqRxZYsWr7eH5vBtdF)
161
+
162
+ ### Development
163
+
164
+ The package ships plain ESM `.mjs` files with no build step. In a checkout, run `npm install`,
165
+ `npm test`, and `npm run typecheck`. Check the generated config reference before releasing.
166
+ Record changes with `npm run changelog -- <type> "<text>"`; record fixed error reports with
167
+ `npm run known-fix -- add <fp> <version> "<summary>"`. `npm run release -- <bump> [--dry-run]`
168
+ bumps versions, releases the CHANGELOG, updates the optional Latest line, checks, commits, and
169
+ tags. Publish with `npm publish`, then push the tag; CI creates the GitHub release.
170
+ See [releasing](docs/releasing.md).