Repository navigation
Releases
forge 0.14.3
A patch release: the Codex monitor's per-task timer no longer restarts after a halt. This page covers what changed since 0.14.2 (PR #152).
Task timers survive a resume
Each time a halted task was resumed, the runner reset its start time, so the monitor's timer went back to 0:00. A task worked for 40 minutes across a few halts could show 5.
- Active time carries over. The timer column shows the time the task has actually been running, summed across invocations. A halt still stops it; a resume continues from where it stopped.
- Wall-clock alongside. Once a task has been resumed, the time since its first start appears in parentheses:
7:00 (60:00)is 7 minutes of work over an hour that included waiting on halts. - run.json: each task gains
first_started_atandactive_secs. Older run files without them display as before. A segment that ended without a recorded end time (the process died mid-task) adds nothing.
Codex
No hooks/hooks.json change since 0.14.2, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.14.3, then codex plugin add forge@forge.
forge 0.14.2
A patch release: on Claude Code, the orchestrator now tells you what's going on during a run, and stalled agents get noticed. This page covers what changed since 0.14.1 (PR #151).
A status line every 10 minutes (Claude)
Between agent notifications the Claude orchestrator was silent, so a long-running worker and a stuck one looked the same, and finding out meant asking.
- When execution starts, the orchestrator arms a 10-minute heartbeat. Each tick prints one line, for example:
⏱ 14:20 · Task 3/8 · worker (forge-standard) · running 14m · 12:41 "running touched tests" (2m ago) · tasks 1–2 passed - Workers and reviewers append one line per step to a progress file, which is where the "what is it doing" part comes from.
- The heartbeat stops when the run passes, halts or reaches close-out.
Stalled agents get noticed (#146)
A worker that started its suite in the background and ended its turn could sit idle indefinitely. One did for about 24 minutes on a recent run, and nobody noticed until the user asked.
- Prevention: agents never end a turn while a command they started is still running. A command longer than the 10-minute foreground limit runs in the background and writes an exit marker, and the agent waits for that marker within its own turn.
- Detection: if a tick finds an agent that has gone idle without reporting, the status line names it and the orchestrator nudges it once. Nothing is counted across ticks.
Codex is unaffected: codex exec has no background mode, and forge-monitor.py already shows progress there.
Codex
No hooks/hooks.json change since 0.14.1, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.14.2, then codex plugin add forge@forge.
forge 0.14.1
A patch release: three fixes from a 0.13.14 Codex run that took about 11½ hours for four tasks. This page covers what changed since 0.14.0 (PR #150).
Reused finding ids no longer halt as regressions (#144)
Reviewers write their own finding ids (f1, f2, …), and they are never shown the findings an earlier review resolved. A new finding that happened to reuse a resolved id halted the run as regression. Every halt re-invokes the run with a cold reviewer, which numbers from f1 again, so the halts fed each other: nine in a row, about two hours.
regressionnow halts only when acceptance goes from green to red, or when a widening that was already resolved is rejected again. Widening ids are built by the runner, so a match there really is the same file.- A reviewer finding whose id matches a resolved one is an ordinary fix finding and goes to rework. A defect that genuinely comes back is raised again and reworked, and
stuckand the backstop still bound a loop that can't fix it. - Inline runs are unchanged: there the same agent raises and remembers its own findings.
Reviewers no longer have to prove the repository unchanged (#149)
The reviewer contract said the repository "must be byte-for-byte as you found it". Reviewers inventoried every file, saw the runner's own gitignored .forge/ logs change during the review, and reported preservation as unverifiable. That caused three unverified halts.
Reviewers now never write in the repository and leave that check to the orchestrator's fingerprint (working tree, index, HEAD, branch). Gitignored paths are out of scope.
Workers no longer run acceptance (#147)
Standard and complex workers ran the task's acceptance commands, and then the orchestrator ran them again. With a full suite in acceptance, that cost about an hour on a recent eight-task run. Workers now run the test files their change touches, and the orchestrator alone runs acceptance; a failure comes back as a rework lap. Trivial-tier (forge-light) workers still run acceptance, because their batch has no review.
Codex
No hooks/hooks.json change since 0.14.0, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.14.1, then codex plugin add forge@forge.
forge 0.14.0
A minor release, because execution behavior changes. This page covers what changed since 0.13.14 (PR #148).
Scope widening replaces the repair-out-of-scope halt
A plan can't name every file a task will need. When a repair touched a file outside the task's diff, forge used to halt repair-out-of-scope for a human, and nearly every one of those halts was approved anyway. In one recent session, all five were approved, and four were on files the plan had declared or the run had already written.
- Workers may widen, with a reason. After every worker turn (first attempt and every rework lap), forge lists each existing file the worker modified outside its task's
**Files:**. The worker records why in a widening record: the reason, plus the finding or requirement it serves. - The reviewer arbitrates. Each widened path gets a ruling,
acceptedorrejected. A rejection becomes a fix finding: the worker reverts it or argues back. If it's rejected a second time, the run haltsstuckand the human decides. - Close-out lists them. Accepted widenings show up beside the staged deferrals, for information only. Widenings from trivial-tier tasks and inline runs, which have no reviewer, are marked "not reviewed".
- Only two things still halt: deleting an existing file outside scope (
scope-delete), and a worker commit (worker-committed).
A worker can't widen its own scope
- Detection diffs from a checkpoint, the
HEADand branch recorded before a stage's first worker dispatch and held across rework laps, never fromHEADread afterwards. - Scope, the exempt spec files and the citable refs are all read from the plan as committed at that checkpoint. Editing the plan's working copy changes nothing.
- After every worker turn,
HEADmust equal the checkpoint on the same branch. An added commit, reset, amend, branch switch or detached HEAD haltsworker-committedand names the commits. The freeze moves no ref; you decide on resume whether they stay.
**Files:** is machine-read
- Bulleted
Create:/Modify:/Test:entries of backticked repo-relative paths, with an optional trailing note. - Prose entries ("every portal
.tsxthe guard flags"), globs, and the single-line form are lint errors naming the task and line. - Completed plans aren't migrated. Resuming an older plan whose
**Files:**lines are prose needs those lines rewritten first.
CLI changes (forge_dispose.py)
- New subcommand:
widened. - Decision CLI:
--planand--checkpointare now required, and--wideningsis new. - Removed:
--repair-snapshot. It's now a usage error. - decision.json: gains a
wideningsblock.
Halt records from before this release that name repair-out-of-scope still resume.
Codex
No hooks/hooks.json change since 0.13.14, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.14.0, then codex plugin add forge@forge.
forge 0.13.14
A stable patch release. This page covers what changed since 0.13.13 (PRs #141 and #143). Both changes came from a repo where one feature routinely amends three specs at once: a semantic layer, its API routes and its UI.
One plan per change, not per spec
The planning skill said "one plan per subsystem." Agents took each per-system spec as a subsystem and wrote one plan per spec, so a feature crossing three specs became three plans built one layer at a time, even though the work goes back and forth between them.
- Planning: one plan per shippable change. Declare every touched spec in
**Spec files:**, and a task may name sections from several specs ([api] Routes, [ui] Dashboard). Split plans only when a piece works and ships on its own. - Brainstorming: the scope check decomposes only into pieces that ship on their own. Touching several specs is not decomposition.
The tooling has supported multi-spec plans since 0.13.4; only the skill text lagged behind.
Spec review checks the spec under review (#142)
Spec lint ran only on specs a plan declared. A spec whose system id didn't match its filename passed spec review and every single-spec plan, then failed mid-plan the first time a multi-spec plan declared it.
forge_docreview.py --specnow runs the living-spec lint rules on the reviewed spec before building the packet or validating a verdict. Any defect stops the run and lists every problem.- Only that spec is checked. Old drift elsewhere in
docs/forge/specs/doesn't block unrelated reviews. - To find existing drift in a repo, run
forge_lint.py --specsonce from its root.
Codex
No hooks/hooks.json change since 0.13.13, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.14, then codex plugin add forge@forge.
forge 0.13.13
A stable patch release. This page covers what changed since 0.13.12 (PR #140). It cuts down rejected spec- and plan-review verdicts, which were costing a reviewer retry each.
Review packets list the exact names to copy
Across the audited sessions, 45 of 256 document-review verdicts were rejected and retried. About three quarters of the defects were the reviewer naming something not quite as given: a section with a sub-location or two headings joined in it, a reference list with entries missing or added, a file path with a line number.
- Spec review: the packet now lists every heading under Section names, each as an exact JSON string. A finding's
sectionis one of those, copied verbatim; a finer location goes inevidence, and a finding about two sections is two findings. - References: the packet says to write exactly one entry for each listed unresolved reference, and none for any other.
- Plan review: section-table headings are printed as JSON strings, and a new Spec headings list gives
contradictionandspec-defectfindings exact names to cite.
Line numbers allowed in dependencies_read
dependencies_read[].file now accepts path, path:N or path:N-M. Reviewers kept adding line numbers even though the packet forbade it. Any other form still has to be a tracked path as written, so a malformed suffix is still rejected.
Codex
No hooks/hooks.json change since 0.13.12, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.13, then codex plugin add forge@forge.
forge 0.13.12
A stable patch release. This page covers what changed since 0.13.11 (PR #139). It changes which review findings forge fixes on its own, and adds a guard so those fixes stay inside the task.
Findings in new code are always fixed
Before, a finding was fixed in-loop only when the reviewer labeled it contract-breaking and cited a named acceptance criterion. Everything else, including real bugs in code the task had just written, was deferred. An audit of 13 runs found 37 of 43 real new-code defects labeled improvement, and they were only fixed because a human insisted at close-out.
- Every verifiable in-diff finding is now fixed in the task's rework loop, whatever its impact label. Whether a finding counts as a defect or polish is the reviewer's judgment. Whether it's in this task's diff is a fact the runner checks.
- Off the diff, nothing changes. A cited contract-breaking finding in code an earlier task wrote still goes to the final review, and one in pre-existing code still halts for you. Everything else still defers.
unverifiablefindings still go to the final review.
A repair that leaves the task's files halts
After every rework lap, on task and final reviews, forge compares the repair with what the task had already changed. If the repair modified or deleted a file the task hadn't touched, the run halts with the new reason repair-out-of-scope and names the files.
- A file the repair creates is allowed, since it changes no existing code.
- The check works at file level, so an edit inside a file the task already touched passes.
- Codex: the runner does the check itself. Claude: the orchestrator passes the pre-repair tree as
forge_dispose.py --repair-snapshot <tree>(fromforge_fingerprint.py snapshot), anddecision.jsongainsrepair_out_of_scope.
Codex
No hooks/hooks.json change since 0.13.11, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.12, then codex plugin add forge@forge.
forge 0.13.11
A stable patch release. This page covers what changed since 0.13.10 (PR #138). It fixes two spec-review packet bugs that showed up in a brownfield repo with many tracked images.
Spec review no longer crashes on a binary match
Reference resolution parsed the first git grep line as path:line:text. When the first match was a binary file, git printed Binary file <path> matches instead, and packet build crashed with a ValueError. A short backticked ref like rpm can match by chance inside a PNG.
- Symbols resolve against text files only (
git grep -I): a spec never refers to bytes inside a binary file. - Any other unexpected grep output raises an error naming the line, instead of failing on a bare unpack.
- The structural
dependencies_readcheck shares the resolver, so a symbol claimed to live in a binary file now reads as not found.
Spec reviewers can open the hunting list
The packet named skills/brainstorming/design-anti-patterns.md relative to the plugin root. The reviewer runs in the repo under review, where that path doesn't exist, so reviewers skipped the hunting list without saying so. The packet now names it by absolute path under the plugin root.
Codex
No hooks/hooks.json change since 0.13.10, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.11, then codex plugin add forge@forge.
forge 0.13.9
A stable patch release. This page covers what changed since 0.13.8 (PR #135). It fixes approvals leaking between reviews that reuse the same finding id.
Finding identity is scoped to its review
Reviewers number findings from f1 in every review, and approvals were keyed on that bare id. Approving task 2's f1 also exempted task 5's f1. Issue #128.
- Finding identity is runner-owned and review-scoped:
t<N>:<id>orfinal:<id>, stamped once and read everywhere. Approvals, seeds, unverified entries, halt-record findings, receipts and--statuskey on it. - A scoped
carried_fromis kept only when it names a prior finding the review's packet carried. Anything else is a validation defect on the retry path, which closes an identity-borrowing hole. - Every prior finding in a packet is presented under its identity as
id, so a seed-carried finding keeps its approval across verification laps. - Malformed verdict ids and
carried_fromvalues are validation defects, not rawTypeErrors. The final-review loop filters approved identities from its halted list, as the task loop does.
Command changes
forge_dispose.pyrequires--scopeand takes--prior-identities.--resolvetakes an identity or an unambiguous bare id; an ambiguous bare id raises and lists the candidates.- A halt record without identities raises on resume.
Codex
No hooks/hooks.json change since 0.13.8, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.9, then codex plugin add forge@forge.
forge 0.13.8
A stable patch release. This page covers what changed since 0.13.7 (PR #133). Reviewers now verify by running code in a scratch copy, and the runner proves they left your repository alone.
Reviewers execute, and the runner checks they didn't write
Reviewers used to run under a read-only sandbox, which stopped them from executing anything to confirm a finding. The sandbox is gone on both harnesses; in its place the runner fingerprints the repository around every review. Issue #127.
- Reviewer dispatches run without the read-only sandbox and verify by executing in a scratch copy. The agent contracts carry the scratch-copy, no-stash and break-the-code rules, with evidence required.
- The runner fingerprints the repository before every reviewer dispatch and on every exit: working tree, index, HEAD and branch. A change is a
reviewer-wrotehalt that freezes the pre-review capture, restores refs, and cannot be recovered within the run.scripts/forge_fingerprint.py(snapshot,verify,freeze) gives the Claude loop the same guarantee. - Task discovery packets carry the acceptance command results with a do-not-re-run assertion, so a reviewer doesn't repeat them.
- The pre-repair snapshot captures untracked files, so repair deltas compare tree against tree.
Final review can halt as unverified
- Seed findings and unverifiable coverage entries accumulate as a terminal
unverifiedset. A final-review pass with an open entry halts before doc-sync. Answer it with--resolve <id>=accept:<evidence>|defer|repair. - Run-level approved ids outlive the halt record and reach final-review convergence.
repair_taskis required on a runner-derived pre-existing contract-breaking finding, on both harnesses.
Known limits
On the Claude path the fingerprint file is reviewer-writable, and .git/hooks and .git/config are outside the fingerprint (#131).
Codex
No hooks/hooks.json change since 0.13.7, so Codex doesn't ask you to re-trust forge's hooks.
Install
claude plugin marketplace update forge
claude plugin update forge@forge # or: claude plugin install forge@forgeRestart the session to apply. On Codex: codex plugin marketplace add forcetrainer/forge --ref forge--v0.13.8, then codex plugin add forge@forge.