All notable changes to this project are documented here. The format is based on Keep a Changelog and this project adheres to Semantic Versioning.
0.25.0 - 2026-07-20
- Landing + status pages: token-driven fluid type scale and spacing scale.
src/brand.jsnow computes a fluidclamp()type scale (--fs-n2…--fs-7) and a 4px-base spacing scale (--sp-1…--sp-24) from a formula, the same way it already derived the color palette frombrand.json.landing/index.htmland the generated status page (scripts/build-pages.mjs) now consume these tokens for every font-size/margin/padding/gap instead of hand-picked pixel values;test/pages.test.jsenforces that both surfaces stay in lockstep with the formula.forge uicheck designnow reports the landing page's spacing values 100% on-grid (previously 96% on an inconsistent 2px base).
0.24.0 - 2026-07-20
forge docs impact— a reusable documentation-impact graph. Wheredocs checkreconciles a fixed list of registries anddocs syncscans a diff for raw identifiers,docs impactanswers the general question the project kept forgetting: "I changed X — which documented surfaces mention X and are now potentially stale?" It works in three data-driven stages: (1) a pluggable extractor registry derives the typed entities the project documents (command names, CLI flags,FORGE_*env vars, MCP tool names, exported symbols, brand tokens, the version,package.jsonfields) from their canonical sources — reusingdocs_check'senvVarsRead/srcFilesand theCOMMANDS/TOOLSregistries; (2) a word-boundary- and code-fence-aware scan of every doc surface (all tracked*.md,CITATION.cff, the plugin manifests, the landing page,package.json) builds an inverted index entity →file:line; (3) an impact query maps the entities a git diff changed to every doc location that references them, ranked by confidence. Advisory by default (--strictexits non-zero for CI);--since <ref>,--staged,--min-confidence <n>, and--jsonflags;docs checkprints a one-line advisory pointing here when the working tree touched a documented entity. Newsrc/docs_impact.js.
0.23.2 - 2026-07-20
- Windows path portability (Git Bash CI). Several subsystems compared or emitted paths
with the OS-native separator or as raw filesystem paths, which broke on Windows where
path.relative/joinyield\and drive letters look like URL schemes:atlasandscopenow normalize every repo-relative path to POSIX (/) before using it as a graph node id, cache key, or comparison target, so impact/decompose/graph results match on Windows (a no-op on Linux/macOS). A sharedtoPosixhelper lives insrc/util.js.uicheckvisual target resolution no longer mistakes a Windows drive-letter path (C:\…) for an unsupported URL scheme, so local files render and the playwright-absent path still degrades to a clean skip.initwrites hook/statusline commands intosettings.jsonin POSIX form.bash(Git Bash) treats\as an escape, so a native Windows path would corrupt the command; ownership/dedup matching normalizes separators too, keeping merges idempotent.- The
secret-redactguard importssrc/secrets.jsvia afile://URL instead of a raw path, so the Node redactor no longer degrades to a silent no-op on Windows. imagine's sandboxed dry-run attributes per-file pass/fail by comparing paths in POSIX form, andbuild-pagestolerates CRLF when parsing the changelog for the status page.
0.23.1 - 2026-07-19
forge imagine --dry-runper-file attribution on macOS.dryRun()matched node--test's realpath'dlocation:diagnostics against a rawmkdtempworktree path; on platforms wheretmpdir()is itself a symlink (macOS:/var→/private/var,/tmp→/private/tmp) the two never matched, so the pass/fail-per-file breakdown was silently dropped. The worktree root is now canonicalized withrealpathSyncbefore comparison (a no-op on Linux). The CI smoke matrix now runs the full unit suite onmacos-latest, which surfaced this.
0.23.0 - 2026-07-19
- PostToolUse redaction now honors the structured-output contract (CR-01). Built-in
tools (Bash, Read, Grep, …) return structured objects, and Claude Code ignores an
updatedToolOutputwhose shape doesn't match the original — the previous redactor stringified objects, so its replacement was silently discarded and the unredacted output stayed visible. Redaction is now recursive and type-preserving: strings are redacted in place, arrays/objects keep their exact keys and structure, non-string leaves pass through untouched, and an unchanged response emits no rewrite. Tests now cover Bash-shaped, Grep-shaped, and nested structured responses. - Strict mode is honest and actually propagates (CR-02). The shell wrapper no longer
swallows the redactor's exit status with an unconditional
exit 0— a strict-mode (FORGE_GUARD_STRICT=1) degradation now reaches Claude as exit 2. Documentation and comments no longer claim strict mode "blocks": PostToolUse fires after the tool ran, so exit 2 is surfaced stderr feedback, not enforcement — blocking belongs to the PreToolUse guard. A wrapper-level regression test drives the realsecret-redact.sh. - Guard blocks shell writes to protected paths (HI-06). The PreToolUse guard now blocks
writes/mutations to protected paths (
.env, keys,secrets/,.ssh/) via redirections and truncations (> .env,: > .env),tee,sed -i,cp/mv/install, anddd of=, not just reads. Interpreter-driven writes (python -c,node -e) remain out of scope and are documented as such — this is defence in depth, not a sandbox. - Hardened git secret-reader detection (HI-07). Reader detection now sees through wrappers
and global options (
env/command/VAR=valprefixes,/usr/bin/git,-C/--no-pager/-c/--git-dir/--work-tree) and coversgit blame/show-index/bundle. - Broader hook tool coverage (HI-08). The protect-paths PreToolUse matcher now includes
NotebookEdit, and the secret-redact PostToolUse matcher includesWebFetch,NotebookEdit, and MCP tools (mcp__.*); the settings template and plugin manifest stay in sync.
forge verifyruns every detected suite (HI-01). A polyglot repo where a passing Node suite hid a failing or unexecuted pytest suite no longer reports PASS — every detected executable suite runs, and a non-executable or missing one makes the overall result INCOMPLETE. Per-suiteexecuted/notExecuteddetail is recorded.- Verification is bound to the final code state (HI-02). Provenance records a
codeStatefingerprint (git HEAD + a hash of working/staged/untracked changes); the completion gate only counts aforge verifyPASS as evidence when that fingerprint still matches at Stop, so code edited after verification no longer passes on a stale stamp. - Completion gate detects edits to pre-dirty files (HI-03). The session baseline stores a content fingerprint per already-dirty file, so further edits to it during the session are seen instead of hidden by its start-of-session dirty state.
- A changed test file is no longer proof (HI-04). A deleted or empty test file no longer satisfies the code-change evidence requirement; the test leg needs a substantive (existing, non-empty) test file or a code-state-bound verify PASS.
- Honest spawn and metrics classification (ME-01, ME-02). Spawn failures (missing binary,
permission/exec-format errors, signal kills, timeout) are reported INCOMPLETE rather than a
false test FAIL — only a real non-zero exit counts as FAIL; deep-verify metrics no longer
count NOT_CONFIGURED/INCOMPLETE runs as a pass. Provenance records
gitAvailableso a failure to detect changed files is never reported as a clean tree (ME-04). - Ownership-safe settings uninstall (HI-05). The settings merge records an
_forgeOwnedmanifest of exactly what it added (permissions genuinely absent before, hook guard-identities, statusLine,$schema);forge init --remove-settingsreverses only those, never a user-owned entry that predates Forge. Ownership is path-aware, so a user's custom hook that merely shares a basename with a Forge hook is never claimed or removed; a legacy scan seeds the manifest for pre-manifest installs. - Init aborts on profile-persistence failure (HI-09). When
forge init --profilecan't persist because.forge/forge.config.jsonis corrupt, init now aborts before sync,.gitattributes, and the settings merge — zero side effects — instead of continuing and reporting the error afterward. - Safer installer transactions (HI-10).
install.shbacks up a user-owned symlink at a destination instead of silently replacing it, and stops (Uninstall INCOMPLETE, non-zero) rather than removing assets that settings hooks still reference when settings cleanup fails. - Verification surfaces monorepo suites (ME-03).
detectStack()now reportsworkspaces(declared workspace globs) andpackageRoots(nested package roots found via a bounded, capped scan), so a root test command can no longer silently claim to cover a whole npm/pnpm/Turborepo/Maven/Gradle/Python monorepo. - Evidence resolution strength gates confidence (ME-05).
ci:/human:/file:refs are format- and existence-checked, and unresolved pointers liketest:<id>or a non-existentfile:path can no longer lift a claim's confidence into the trusted/serving band; a resolvable git-ref confirmation still counts exactly as before. - Secret-bearing ledger metadata is refused (ME-06). Secret-shaped evidence refs, authors, tombstone reasons, and provenance metadata are refused before they can be written to the ledger — the same detector already applied to claim content — and quarantined records are stored redacted.
- Trusted quarantine identity (ME-07). Quarantine keys rejected records by a trusted content hash instead of the record's own (attacker-controllable) hash, so distinct forgeries sharing a fake hash are both retained and malformed lines with no hash are captured instead of dropped.
- Per-target MCP ownership and atomic add/remove (ME-08, ME-10). Adoption is tracked per
{server, target}, so adopting a same-name server for one tool never authorizes overwriting another tool's entry (legacyadopted: [name]still honored and migrated);integrations addrecords nothing on a partial emit andremovekeeps the entry (reporting an incomplete transaction) if any target cleanup fails, so config and disk never drift silently. - Divergent registry-name MCP entries preserved (ME-09). A user's own MCP server sharing a
built-in name (e.g.
forge-cortex) is no longer overwritten without explicit--adopt. - Validated MCP names and safe serialization (ME-11). Managed server names must match
^[a-z0-9][a-z0-9_-]{0,63}$,foo/forge-fooContinue-file collisions are rejected before any write, and command strings are quoted safely into YAML and TOML. - Non-object JSON is treated as corrupt (ME-12). Repo config and global settings now reject
valid-but-non-object JSON (
null,[],"x",42) as corrupt instead of silently overwriting it, preserving the original bytes. - Crash-safe config writes (ME-13).
forge.config.jsonwrites take a timestamped backup and go through a temp file + atomic rename. - Complete tool list (ME-14).
roois now a selectable primary tool, and aider/continue/windsurf/roo are auto-detected from their on-disk markers, reconcilingforge toolswith the MCP emit targets. - Functional doctor health probes (ME-15, ME-16, ME-17, ME-18).
forge doctorvalidates the actual Forge hook wiring against the template (not just the_forgemarker), verifies~/.forgeis a symlink/dir whose required guard assets resolve (catching plain-file shadows and dangling links), runs a real redactor self-test instead of trusting Node's presence, and records a partial--fixsync (nestedaction:"error"rows) as a failed repair. - Explicit PARTIAL sync status (ME-19).
forge syncreturns and reports an aggregate status; if any target fails mid-run the result isPARTIALandsync/initsay so and exit non-zero instead of implying every tool is configured. - Fail-safe legacy rules (ME-20). A corrupt legacy
.forge/rules.jsonno longer abortsforge sync— it warns once, falls back to default rules, and leaves the file's bytes intact. - Exact gitattributes rule detection (ME-21). The ledger union-merge rule is detected by its
exact active line, so a comment mentioning
.forge/ledger/no longer suppresses the real rule.
-
Disclose the global settings merge before it happens (ME-22).
forge initnow prints the global~/.claude/settings.jsonmerge disclosure before the merge mutates the file, not after. -
Hooks install in exec form (ME-23). Hooks and the statusline now use Claude Code's exec form (
"command": "bash", "args": [...]) instead of a shell string, so a guard path containing spaces works with no quoting — removing the shell-quoting hazard the earlier RA-12 fix worked around. Upgrades are seamless: an existing install written in the old shell-string form (or the${CLAUDE_PLUGIN_ROOT}plugin spelling) is deduped by guard identity and healed in place to exec form on the next merge, and ownership tracking / uninstall are form-agnostic — so a re-install never duplicates a hook and uninstall still reverses exactly Forge's own additions. -
Honest positioning (ME-24). README no longer claims "one brain for every AI coding agent", "enforced guardrails", or that every task passes a deterministic gate: automatic hooks are Claude Code-specific (advisory by default, enforcement opt-in via
FORGE_ENFORCE=1), other tools receive shared instructions and MCP tools, and guardrails are described as defence in depth, not a security sandbox.
0.22.1 - 2026-07-18
- Only real profiles (RA-14).
forge init --profilenow acceptsminimalandstandardonly — the formerweb-app/backend-service/library/regulatednames were always aliases of the full pack (sync only ever branched onminimal) and are now deprecated aliases ofstandard: accepted with a deprecation warning, stored asstandard, and a legacy name already stored in an existing config still syncs as standard (with a one-time warning). New exportedvalidateProfile()maps legacy names before any side effect. - Honest wording (RA-22, RA-23, RA-24). package.json's description now says what
ships — shared memory, impact analysis, and guardrail hooks emitted as native config —
instead of "the cognitive substrate every frozen model is missing". README's loop intro
now states that the automatic pre-action check is Claude Code hooks (advisory by
default, enforcement opt-in via
FORGE_ENFORCE=1) while other tools receive instructions and MCP tools to invoke; the comparison table now claims what the ledger does today — evidence must name a known oracle and a typed, format-checked reference at append time — rather than implying stored evidence is re-verified on load.
- Git read-command bypasses closed (RA-05). The
protect-pathsguard now classifiesgit diff,git stash,git cat-file,git archive, andgit grepas content readers, closing the secret-file read path via git plumbing (git diff -- .env,git cat-file -p HEAD:.env,git archive HEAD .env). The settings template movesBash(git stash:*)from allow to ask:git stash show -pcan dump stashed secret content with no path token for the guard to match, so the permission prompt is the only defense there. - Secret redactor no longer fails silently (RA-06). Any redaction failure prints a
visible
secret redaction DEGRADEDwarning to stderr, and newFORGE_GUARD_STRICT=1escalates degraded redaction to a blocking exit instead of passing unredacted output through.
forge verify --deepcan no longer pass when nothing ran (RA-01). Deepoknow requires the core tests status to be PASS in addition to the lens consensus; the result, provenance, and metrics carry an additive four-statestatus(PASS/FAIL/INCOMPLETE/NOT_CONFIGURED), and a repo with no configured verifier exits 1 withNOT VERIFIEDinstead of printing PASS.forge verifyexecutes the detected runner (RA-08). pnpm/yarn/bun repos spawn their own package manager instead of a hardcodednpm test; pytest runs directly; non-executable detections (go/cargo/mvn/gradle/dotnet/rspec/phpunit) or a missing binary report an honest INCOMPLETE naming the real command.detectStack()gains a structuredtestRunnersfield ({bin, args, label}) alongside the unchangedtestCommandsstrings; npx-based runners are report-only and never executed.- CLI verify output distinguishes all four states (RA-09).
BLOCKEDis reserved for a runner that actually failed; anything that never completed printsNOT VERIFIED(still exit 1) instead of the misleading "tests failing". - Ledger log lines are hash-verified at read time (RA-02).
readLog()recomputes every record's content hash and drops forged/corrupt lines (evidence lines must also be valid outcomes), so a hand-edited log line can no longer moveval(). Imports and merges no longer bypass validation: imported evidence goes through the full append gate (oracle/ref checks includinggit:resolution against the destination repo), and rejected records are quarantined as sealed audit lines underquarantine/<claimId>.logwith aquarantinedcount surfaced byforge ledger merge.validOutcome()rejects typed-but-empty refs (e.g.git:), matching append-time validation. - Stale ambient atlas is no longer authoritative (RA-07). When the atlas is stale and
a hook can't rebuild it, impact, impacted files, and predicted tests are dropped rather
than silently computed from stale data; renderers say "impact unavailable" without a
contradicting test list, and
FORGE_ENFORCE=1never hard-blocks on a stale blast radius. - Completion gate enforces real obligations (RA-10). Code changes now owe test
evidence — a test file moved with the change or a fresh passing
forge verifyrun — in addition to docs/state; a handoff alone no longer satisfies the gate for code (config-only changes keep the lighter docs-or-handoff bar). Kill switch, block-once, and fail-open behavior are unchanged. - Doctor honesty (RA-19, RA-20). A missing atlas reports subsystem health
UNAVAILABLE(new neutralnastatus) instead ofACTIVE, anddoctor --fixrecords a repair that returns an error object (e.g.mergeSettingsrefusing a corrupt file) as failed with the reason instead of successful. - Settings failures propagate (RA-04).
forge initfails (exit 1, stderr) when the settings merge is refused or errors, andinstall.shreportsInstall INCOMPLETEand exits 1 instead of printingDone.when hooks weren't wired. - Hook paths are shell-quoted (RA-12). Hook and statusline commands merged into
~/.claude/settings.jsonsingle-quote the package path, so installs under a path containing spaces work; old unquoted entries dedupe against and are upgraded to the quoted form on re-merge. - Invalid profile aborts before side effects (RA-13). An invalid
forge init --profilevalue no longer leaves a partial repo scaffold,.forge/write, or settings merge behind. - Reversible settings uninstall (RA-11, RA-17, RA-18). New
forge init --remove-settings(also run byinstall.sh --uninstall) reverses the settings merge — template-shaped hooks/permissions/statusline and the_forgemarker are removed with a backup, user entries untouched. The installer header now tells the truth about the global, reversible merge, announces it before merging, and gains--no-settingsto skip it. - MCP emitters are no longer destructive (RA-03). Installed integrations are recorded
in
.forge/forge.config.json(mcp.integrations), andforge syncandforge integrations addboth emit the same full managed set — the sync/add/sync oscillation that deleted each other's servers is gone. - MCP configs respect ownership (RA-21). Continue gets one forge-marked YAML per
managed server (the legacy combined file is migrated away only when provably forge's),
Codex servers live in
# forge:managed:<name>blocks refreshed by byte-compare, and a same-name JSON entry the user configured is never overwritten — it is reported with an--adopthint instead. Newforge integrations remove <name>reverses an add, deleting only forge-owned entries, blocks, and files; running it twice is a no-op. - Stop-hook auto-sync detects body drift (RA-16). Auto-sync now byte-compares
AGENTS.mdagainst the exact content sync would write instead of trusting the embedded marker hash, so a hand-edited body with an intact marker is repaired. - Repo config consolidated; malformed JSON fails loudly (RA-15).
src/repo_config.jsis now the single per-repo config module:readForgeConfig/writeForgeConfigoperate on the unified.forge/forge.config.json(unknown keys round-trip through writes), migration-read the legacy.forge/config.json(primaryTool/tools; the unified file wins on key conflicts, the legacy file is left in place), and never silently discard corrupt JSON — reads warn once per process on stderr and report the corrupt path, and writers (forge init --profile,forge tools <name>) refuse to overwrite an unparseable config instead of replacing it with defaults.forge syncstill fail-opens to default rules on a corrupt config but surfaces a warning in its report.
0.22.0 - 2026-07-17
- Onboarding & state safety.
forge initno longer silently replaces a present-but-unparseable~/.claude/settings.json(it refuses and preserves the original), backs the file up before changing it, and writes atomically (temp + rename). Hook/statusline commands now resolve to the installed package (~/.forge/…→<pkg>/global/…) so npm-global installs don't reference an unmaterialized~/.forge. Personal recall moved to the XDG state dir instead of the source tree;install.shseparates read-only assets from mutable state, migrates anyglobal/recall/facts, and no longer routes path ops througheval. - Security defaults. Removed broad default Bash read allows
(
cat/head/tail/rg/git show/git log) so secret-file reads prompt instead of auto-approving, and moved dependency installs (npm ci/npm install/…) toask.protect-pathsnow blocks reading a protected path via Bash (e.g.cat .env,git show HEAD:.env). Secret redaction is reimplemented in Node (secret-redact.mjs) with nojqdependency and prints a visible DEGRADED warning rather than silently no-op'ing;forge doctortreats missingnodeas a failure. - Managed-file integrity.
writeIfChangedandforge doctornow compare the full file body against the canonical source instead of trusting the embeddedforge:syncmarker, so a hand-edited managed file (AGENTS.md, etc.) with an intact marker is detected and restored onforge sync(P0-08). - Third-party MCP is opt-in.
context7is no longer installed by default;forge initwires only forge's own server. Newforge integrationscommand adds an optional server (e.g.context7) after showing its package, network behaviour, and the files it touches, writing only with--yes(P0-06). MCP emitters now refresh a drifted forge-owned entry instead of leaving a stale one (user servers untouched). - Core correctness. Atlas staleness is inventory-aware (a new/removed file now
invalidates the graph), and
forge impact/substratereport "impact unavailable" on a stale/missing atlas instead of presenting 0 impacted files as trustworthy (P0-07).forge verifyreturnsPASS | FAIL | INCOMPLETE | NOT_CONFIGURED(never "pass" when no verifier ran), drives real test commands off the stack detector, and includes untracked files in provenance (P0-09). Ledger evidence refs are validated — a typedgit:<sha>ref must resolve before it can affect confidence (P0-10). - Effective-date pricing. Model prices support scheduled
{effectiveFrom, effectiveUntil}windows resolved bypriceOf(model, date); Sonnet 5 now carries its $2/$10 introductory rate (through 2026-08-31) and the $3/$15 successor, andforge routeshows the current effective price (P0-12). - Release integrity. A reusable
quality-gateworkflow (tests, Biome, typecheck, ShellCheck, zero-dep assertion, version-drift, docs check,npm pack) is now required by CI, the version bump, and the release — a tag/publish can no longer proceed onnpm testalone while other gates fail (P0-11). - Honest claims & wording. Dropped scanner "ok to install" certification language
(S-01); renamed
P(defect)→defectRiskScoreandresidual→remainingUncheckedWeightin output; reframed the preflight score as a heuristic; qualified "proof-carrying memory" as evidence-referenced and "zero-config" as guided/low-configuration across the docs; added a beta status block and per-benchmark sample sizes.
- Policy profiles & repo config.
forge init --profile minimal|standard|web-app| backend-service|library|regulatedwrites.forge/forge.config.json; theminimalprofile emits only the five core-safety rules instead of the full engineering pack (P1-02).forge.config.jsongives explicit override semantics —profile,disableSections(drop by id/title), andrules(append) with deterministic order (P1-03). - Change-obligation guidance. The completion gate now spells out change-type obligations (code → docs + a test, config → config docs; test-only owes nothing) so it points at the right artifact instead of accepting any doc/state touch as done (P1-05).
- Subsystem health.
forge doctorreports each key subsystem (secret-redaction, guards, atlas, managed-config, pricing) in a standardACTIVE|DEGRADED|UNAVAILABLE| FAILEDvocabulary so a degraded control stays visible (P1-06). - Help grouping. Experimental commands are grouped under "Labs (experimental)" in
forge --help, separating the core reliability loop from experiments (P1-01). - UI rule. Replaced the "make chain-of-thought visible" AI-UX rule with safe-rationale guidance (assumptions, tool actions, sources, verification evidence — no hidden reasoning traces) (P1-04).
0.21.1 - 2026-07-17
forge dejacould never fire.DEJA_FLOORwas 0.55, above the ~0.42 ceilingretrieve()can produce for a repo-scopedsummaryclaim (the σ term is < 0.73 and the 0.6 repo scope-weight caps it), so the anti-repetition advisory was a permanent silent no-op. Recalibrated to 0.39 — inside the real band (unrelated ≈0.34, identical ≈0.42) — with an end-to-end test that drivesrecordSessionSummary→dejaAdvisoryso the floor can't drift out of range again.forge hardencrashed in a linked worktree/submodule..gitis a file there, not a directory, somkdirSync('.git/hooks')threwENOTDIRand aborted the whole command. The hooks dir is now resolved viagit rev-parse --git-path hooks.forge ledger synccould silently skip a push to a new/pruned remote. The idempotence check compared against a stale localrefs/<cli>/ledgerleft from a prior remote; a remote lacking the ref was reportedupToDatewithout ever receiving the ledger. It now only trusts the short-circuit when the fetch actually found the ref on this remote.forge verify --deepevidence base could diverge.addedfell back to--cachedbutchangedFilesdid not, so the structural lenses (impact/docsdrift) went silent on a base whose worktree matches HEAD while the index differs.changedFilesnow mirrors the same fallback.- Cortex halt metrics were always "pass". The preflight hook read
result.gate?.halted, a fieldsubstrateCheck()never returns, so the cost dashboard's halt-rate was permanently zero. It now reads the real signal (assumption.shouldAsk). forge radarusage misattribution. A dep whose name is aname.-prefix of another (lodashvslodash.debounce) could steal the other's import count via a first-match break in alphabetical order; names are now matched most-specific-first.forge precommitdiff-header parse. An added content line beginning with++rendered as+++and was misread as a file header (dropping that line, mis-attributing the rest); the parser now tracks hunk state so headers are only matched before the@@.
0.21.0 - 2026-07-17
- Per-command help + word forms.
forge <command> --help/-hnow works for every command (intercepted centrally in the dispatcher, no longer silently dropped), alongside the word formsforge help [command]andforge version. Help renders from the sameCOMMANDStable the docs check reconciles: entries may now be a plain summary string OR a rich{summary, usage, flags, examples, env}object (both coexist; the high-traffic commands are migrated), read through newcommandSummary/commandHelphelpers. An unknown command now suggests the nearest match ("did you mean …?") via a character-bigramsuggest()over the existingsetOverlapsimilarity. forge doctor --fix— one-command auto-repair. Each safely fixable finding now carries a repair that reuses an existing idempotent function: missing hooks/permissions in~/.claude/settings.json→mergeSettings, a missing ledger union-merge rule →ensureLedgerGitattributes, a missing/staleAGENTS.md→sync, and non-executable guards →chmod +x.forge doctor --fixruns the repairs, prints arepairs:block, then re-checks; a second run is a clean no-op. Unsafe findings (provider keys, MCP count, pricing, gateway) stay report-only. Thenodecheck is now reconciled withpackage.jsonengines (>=20): fail below 18, warn on 18–19, ok on 20+.- Zero-config settings wiring + first-run hint.
forge init --settings-onlyruns only the idempotent,_forge-marker-guarded settings merge (hooks + permissions into~/.claude/settings.json) with no repo emit, andinstall.shnow calls it instead of printing a block to paste by hand (honoring--dry-run). When a real command runs before settings are forge-managed, one tip line to stderr points atforge init/forge doctor --fix; it is stateless, self-silences once init runs, andFORGE_NO_HINT=1mutes it. forge tools— primary-tool config + auto-gitignore for secondary-tool artifacts. A repo that only uses one agent no longer has to track every other tool's emitted files.forge tools <name>records the primary tool in.forge/config.jsonand writes a marked, reversible block into.gitignore(# forge:gitignore:begin … :end, managed bysrc/gitignore.js) that ignores exactly the NON-primary emit targets — computed fromsync()'s own report rows, so the block always matches what Forge emits. User lines, the sharedAGENTS.md, and the primary tool's own files are never touched.forge toolsshows the detected/primary tool (auto-detected from which agent folder exists, mirroring provider detection) and what's gitignored;forge tools --resetclears the config and strips only the block. Opt-in — plainforge syncnever writes.gitignore.forge dashfirst-run clarity.dashDatanow reports ameta.empty/meta.forgeDirsignal (true when.forge/holds no ledger claims and no metrics events), and the dashboard shows a plain-language empty-state banner ("No data in .forge/ yet — runforge sync, then work a session") plus a?legend that explains what every panel means in one sentence. Display-only — the append-only ratify/retract writes are unchanged.- Web session-start install hook.
.claude/hooks/session-start.sh(wired into the repo'sSessionStarthooks alongside the existing recall/cortex context hooks) makes Claude Code on the web ready to lint and test: synchronous, idempotent, gated onCLAUDE_CODE_REMOTE=true(a no-op locally), and it skips the install entirely when the dev toolchain is already resolvable.
0.20.0 - 2026-07-17
forge know— the A7 knowledge-router. Total routing (formal-synthesis Theorem T6) of any fact to its storage home: exemplar k-NN over a labeled bank (src/knowledge_router.js) picks among claude-md / rule / skill / state / decision / ledger-fact / recall; below-confidence facts fall back to the ledger (provenancefallback) instead of being dropped. Append-only homes are written directly (decide log, repo-ledger fact claim, personal recall store), curated files get advice naming the right command, secrets are refused before dispatch, and--dry-run/--jsonroute without writing. Distilled Cortex lessons that read like decisions or durable facts auto-route to those homes (fail-open).- Commit-level gate rung (
forge precommit). The gate lattice's middle rung (turn ⊂ commit ⊂ PR):src/commit_gate.jsclassifies staged files with the same registry-derived classifier as the Stop gate (code staged with no doc/state artifact → finding) and runs the built-in secret detector over staged added lines as a gitleaks fallback.FORGE_COMMIT_GATEsets the mode (warndefault ·block·0kill switch); a detected secret blocks in every mode.forge hardennow installs a pre-commit hook that runs gitleaks when present, then the commit gate — and never clobbers a user-authored hook (writespre-commit.forgebeside it instead). - Pin/downgrade via
update --to <version>. NewapplyUpdateToinsrc/update.js: for a git checkout it fetches tags, verifies the release tag exists (unknown version → honest miss, never a throw), and detached-checkouts the tag with a note on how to return to latest; npm-global installs get the exactnpm i -g <pkg>@<version>instruction instead. - Multi-lens verification consensus.
forge verify --deep(newsrc/consensus.js) runs a LENSES table over the diff — tests, unknown symbols, unreviewed impact radius, docs drift, secrets in added lines, spec-lock drift, plus an optional--llmmajority-of-3 reviewer panel — and aggregates noisy-ORP(defect)=1−∏(1−wᵢsᵢ)with the same cross-family gate as the lesson miner: a lone structural signal (or the model reviewer alone) never blocks; a failing test suite or a leaked secret blocks solo. Findings extend.forge/provenance.jsonwith per-lens evidence and the Theorem-D residual∏(1−cⱼ)over the lenses that ran, and each run appends onestage:"verify"metrics record. forge radar— dependency-currency rings (I4 verified currency). New zero-depsrc/radar.jsreads this repo's Node manifests, probes the registry (injectablefetchImpl; metadata + bulk advisories; 4s timeout) and classifies every dependency into an adopt/trial/assess/hold ring from evidence — staleness (540-day half-life), major-version lag, severity-weighted advisories, deprecation; atlas usage is stakes, not risk. Deprecated or a critical advisory →hold; fewer than two verified evidence kinds →assess(never adopt on absence). Cached at.forge/radar.json(FORGE_RADAR_TTL_H, default 24h);--offlineserves the stale cache or fails honestly;--refreshre-probes;--jsonfor tooling. A network scan records I4 evidence into the ledger (currency:<dep>facts, supersede semantics) plus a metrics line, and the pre-edit hook surfaces a cache-only advisory when a file imports aholddependency (kill switchFORGE_RADAR=0).- Cross-machine memory sync.
forge ledger syncpush-pulls the PCM ledger through a git ref (refs/forge/ledgerviahash-object/mktree/commit-treeplumbing; non-fast-forward races re-merge and retry ≤3 — monotone by the CRDT join, so nothing is lost) or a shared directory (bidirectional union-merge;FORGE_SYNC_DIRis the default dir target). Target precedence:--dir>--remote/--ref> the repo's git remote >FORGE_SYNC_DIR> an honest "no target".--personalsyncs the per-user ledger beside the recall store, making recall facts portable across machines. Fails open (offline, missing remote, or corrupt remote blob → an honest reason, never a throw); the git runner is injectable so tests drive it with local bare remotes and never touch the network. - Anti-repetition memory (
forge deja). A first-try success mints no Cortex lesson, so its trace used to be discarded when the session ended — the root of cross-session repetition. Now every session Stop mints onesummaryclaim (an existing ledger kind) with a secret-redacted gist of the task and the files touched, attaching atest.runconfirm outcome when the session's own tests passed (so verified work outranks a mere attempt). Newsrc/deja.jsdejaLookupranks prior summaries/lessons/diagnoses via the same Eq. 3 retrieval asledger query;forge deja "<task>"surfaces them, and the pre-action substrate shows a one-line "déjà vu" advisory when a prompt matches prior solved work. Kill switchFORGE_DEJA=0. Because summaries are ordinary ledger claims,forge ledger mergecarries them between machines. - Dashboard v2 (
forge dash). The localhost lens gains four panels over the durable.forge/stores plus live refresh: Radar (dependency-currency rings read from the.forge/radar.jsoncache — never fetches), Trends (per-stagemetrics.jsonlhistory bucketed by day as inline-SVG sparklines, 90-day window), Memory browser (ranked recall search over the ledger viaretrieve, with confidence and freshness bars), and Session timeline (durable mint/tombstone events across sessions). New read-only endpointsGET /api/history,/api/claims?q=&kind=,/api/radar, and/api/timeline; the page polls every 5s, paused while the tab is hidden. The append-only write discipline (onlyPOST /api/ratifyand/api/retract) is unchanged, and corrupt or missing stores degrade to empty sections. - Static HTML report (
forge report). New zero-depsrc/report.jsemits a self-contained.forge/report.html— the offline twin offorge dash(no server, no fetch, no CDN, no JS to read it).renderReportis pure and reusesdashData, bucketsmetrics.jsonlinto a 90-day activity sparkline (server-side inline SVG), reads the.forge/radar.jsoncache directly and defensively (absent → the radar section is omitted), and draws its palette fromrootTokensCss()so it matches the dashboard.--out <path>overrides the default location.
0.19.0 - 2026-07-17
- Color-aware CLI output. New zero-dep
src/fmt.js:supportsColorhonoring theFORCE_COLOR>NO_COLOR>TERM=dumb> TTY precedence, brand-token painting (24-bit frombrand.jsonwhenCOLORTERMdeclares truecolor, portable 16-color fallback otherwise), visible-width-alignedtable, andbarconfidence meters — adopted acrossledger(stats/blame/query),cortex,route,doctor, andcostoutput plus the--verbosetitle line. Piped output stays escape-free.
- Research crosswalk reconciled with the code. The formal-synthesis paper's
crosswalk (rows 5/6/12/14 and the README §11 binding paragraph) cited hooks that
no longer exist (
docs-guard.sh,session-context.sh,intent-router.sh); the bindings now name the real system (cortex.sh→src/gate.jsstopGate,src/session.jsrehydrationBlock,src/intent.jsexemplar k-NN), with kit-only names marked by akit:prefix. A newcrosswalkdocs-check reconciler fails CI when any non-kit:.js/.shbinding incrosswalk.jsonnames a file that does not exist insrc/,global/guards/, orhooks/.
0.18.0 - 2026-07-16
- Single design-token source.
brand.jsongained acolorsblock (full dark + light palettes) as the one source of the visual palette, plusfontsandsite.src/brand.jsexposes it viacssVars(scheme)+rootTokensCss()pure helpers; the generated status page (scripts/build-pages.mjs) now injects tokens from that one source (and gains light mode), andtest/pages.test.jsenforces full-palette parity — every dark and light hex inbrand.jsonmust appear on both public pages, so the landing page and status page can no longer fork into two palettes claiming to be one. - Landing page redesign. Rebuilt
landing/index.htmlon a Stat-Led structure: the real shipped hero diagram is now embedded (inlined so it resolves in local preview and at the deployed site root), the fake terminal chrome, placeholder digit/glyph icons, and faux-live pulse dot are gone, capabilities use real inline SVG icons in a hairline-divided layout instead of a uniform card grid, and the sticky-nav blur is compositor-light. Light-mode accents are darkened to meet AA contrast on the light paper. - Accessibility + design-system hygiene. All accent/supplementary-text pairs on
both themes are now verified ≥4.5:1 (bumped
--faintin dark + light, and light--brand/--ok, at the single brand.json source). Border-radii are collapsed onto a deliberate 3-level scale (--radius-sm/--radius/ pill), soforge uicheck designpasses spacing-scale, radius-levels, and shadow-levels with a healthy slop-distance. Focus rings appear instantly (no animated outline), motion is transform/opacity-only underprefers-reduced-motion.
- Social + icon metadata on both public pages. The landing and generated status
pages now ship
og:image/twitter:image(a 1200×630 brand card,docs/assets/og.png, rasterized once via Chromium — an author artifact, not a runtime dep), a favicon + apple-touch-icon (docs/assets/favicon.svg/apple-touch-icon.png), and consistentcanonical==og:url. The status page gained a full Open Graph / Twitter /SoftwareApplicationJSON-LD head; the deploy workflow copies the brand assets to the Pages root so the absolute URLs resolve. - Brand-aligned status line.
global/statusline.shnow renders the exact brand tokens (ember#f26430, warm-taupe greys) in 24-bit truecolor from a named palette block, with a 256-color fallback when the terminal can't do truecolor. Newtest/statusline.test.jssmoke-tests the segments, the exact truecolor hexes, the fallback, and graceful degradation on minimal input. - Mermaid theme-value guard.
forge docs check'scheckDiagramsnow verifies each%%{initblock carries the brand's actual color values (ember + warm-black frombrand.json), not just that a theme directive is present — a diagram can no longer declare a theme and still render off-brand. README leads with aStart in 60 secondsblock, andARCHITECTURE.mddocumentsbrand.jsonas the single color source.
- Status-page metrics were silently stale. The
impactandsavedregexes inscripts/build-pages.mjsno longer matched the current README, so those "repo-sourced" numbers were really hardcoded fallbacks. Regexes fixed to parse the README, and a non-match is now a hard build error (mustMatch) instead of a silent fallback; the deadclaimfield is removed. - Generated status page no longer ships stale/leaky.
public/index.htmlis a build artifact (regenerated at deploy), so it is now gitignored and dropped from the npmfileslist — a stale committed copy (old version + a dev-branch name leaked into a visible chip) can no longer be published in the tarball. - Landing → status link now points at the absolute Pages URL, so it resolves in
local file preview instead of 404-ing on
./status/.
0.17.0 - 2026-07-15
- OpenAI + Gemini provider detection —
autoDetectProvider()now recognizesOPENAI_API_KEYandGEMINI_API_KEY(orGOOGLE_API_KEY) as zero-config fallbacks after Anthropic, exposingopenaiandgeminias built-in providers with tier→model maps. Both are reached over their OpenAI-compatible chat/completions surface:src/llm.jsgained an OpenAI-compatible wire format (resolveHttpProvider()now returns aformatfield) alongside the Anthropic Messages path, so a native key from either vendor works with no manual config. Anthropic credentials still win when present.forge configstatus andlistDetectedProviders()surface the new keys.
0.16.0 - 2026-07-15
- Playwright interaction loop —
forge uicheck interact <file-or-url>drives the page headless underprefers-reduced-motionand checks what it does (console-clean, keyboard-reachable, focus-visible, reduced-motion), whereuicheck visualonly fingerprints what it paints. The verdict is recorded through the ledger's cross-family-gatedbehavioraloracle (advisory by default;--recordappends it as evidence on the projectfingerprintclaim,--enforcegates). Reuses the visual gate's Playwright resolver + loopback-only target guard; Playwright stays an optional tier (ADR-0005) with a graceful skip. Newsrc/uiinteract.js(runInteractions,summarizeVerdict,verdictOutcome,recordInteraction) with a browser-free test suite.
0.15.0 - 2026-07-15
- measured-promotion gate + outcome-calibrated routing
0.14.0 - 2026-07-15
- Measured-promotion gate + outcome-calibrated routing (
forge route calibrate) — a reusablesrc/promote.jsgeneralizes the risk predictor's kill-criteria: an advisory signal (a calibrated weight, later a consolidation cluster or hazard estimate) may become active only if it beats the current baseline on held-out data under a metric+margin — the honesty register (overview §4), never an assertion. First application:forge route calibratefits an affine correction of the routing rubric toward a held-out labeled fixture and promotes it only if it lowers held-out MAE. Advisory by default — routing keeps the rubric until a promotion is adopted (calibratedComplexitymirrorspredictor.riskFor). Zero deps, fully unit-tested. - Legacy-store retirement (
FORGE_LEDGER_ONLY) — the PCM ledger can now be the only store. Since P1 it has been the convergent write store (dual-write) with a merged read (ledger_read); withFORGE_LEDGER_ONLY=1the legacy files (.forge/lessons/*.md, recall/brain fact files) stop being written and every read materializes from the ledger — cortex confirm/create/distill dedup againstledgerLessons,mergedLessonsreturns the ledger view, andrecall.readFactfalls back to the ledger (also fixing merged teammate facts that had no local file). Runforge ledger importfirst to backfill. Default off keeps the legacy files canonical.
0.13.0 - 2026-07-15
- Custom-gateway model remap (
src/gateway_model_map.js). The tier table pins public Anthropic IDs that a self-hosted LiteLLM/proxy gateway may not serve; when a non-default gateway base URL is set, Forge fetchesGET /v1/modelsonce per process and scores each advertised model against every tier's family (family-word gate +setOverlapname-token score, deterministic tie-break) to remaphaiku/sonnet/opus/fableonto the gateway's real IDs.forge doctorsurfaces the resolvedtier→modelmapping under a gateway models row. Zero breaking change — theMODELSexport shape is unchanged, it fails safe to the stock ID on no gateway / unreachable/v1/models/ no family match, and an explicit.forge/providers.jsonalias orANTHROPIC_MODELoverride always wins. Directapi.anthropic.comsessions never probe and are byte-identical.
0.12.4 - 2026-07-11
- security: drop two inert
curl-pipe deny rules from the settings template. Claude Code only honors:*as a trailing wildcard, so the trailing pipe made the colon a literal and the rules matched nothing. Real pipe-to-shell enforcement already lives inprotect-paths.sh, now tightened to also catch a no-space pipe and azshtarget. Adds a regression test for template rule shape.
0.12.3 - 2026-07-11
- bump.mjs keeps ROADMAP's "Now" marker in sync
0.12.2 - 2026-07-11
- allowlist bibliography citation-key false positives in gitleaks
- don't let an empty Unreleased section blank the status page changelog
0.12.1 - 2026-07-11
- don't let an empty Unreleased section blank the status page changelog
0.12.0 - 2026-07-11
- Goal-drift classification is graded and identifier-aware (
src/anchor.js). A changed file's on-goal/off-goal call is now a noisy-OR (1 − (1 − p)^hits) over how many distinct goal concepts it exhibits in its path and the identifiers it defines (via the atlas), thresholded at the single-hit floor — replacing the binary path-substring match, so a file that implements the goal but never names it in its path is caught deterministically, not just by the opt-in LLM pass.driftScorestays the off-goal fraction, so the CUSUM detector's operating point is unchanged (an on-goal checkpoint scores 0 and drains the chart); the sharper classification is what improves the signal. - Specification completeness is a logistic estimator (
src/preflight.js). The M2 assumption gate'ss(x)completeness score is now a logistic over its features (concreteness, named specifics, vagueness, a smoothtanhlength term) — replacing the additive scorer's magic coefficients and discontinuous word-count steps. Thesigmoidbounds it to (0,1) with no clamp, each feature's pull stays attributable, and a labeled bank could refine the weights viapredictor.js'strainLogistic. Calibrated to keep the documented examples (a bare "make the auth better" ≈ 0.23 → ask; a concrete verifyToken edit ≈ 0.63 → proceed).
forge docs checknow guards intra-repo links and roadmap freshness — two more reconcilers close recurring "docs rot" classes:checkLinksresolves every Markdown anchor (#xandpath.md#x) against the target file's real headings using GitHub-exact slugs (an em-dash yields--, never collapsed), catching dead anchors like a renamed#install;checkRoadmapfails when ROADMAP's "Now" marker trails the shippedpackage.jsonversion.
- Dead and fabricated docs — a fabricated
forge routeexample indocs/GUIDE.md(an impossibleFable 5 / Opus/ "premium tier" output) now shows the real routed verdict; broken#installanchors inONBOARDING.mdand the substrate README now point to#60-second-quickstart; a dead#use-it-in-a-scriptself-link resolves; and ROADMAP's "Now" marker is current (v0.11.0). All now enforced by the new docs-check guards.
0.11.0 - 2026-07-11
forge stack— dynamic stack detection: reads the repo's dependency manifests (package.json,pyproject.toml,go.mod,Cargo.toml,Gemfile,composer.json,pom.xml/build.gradle,*.csproj) and reports its real languages, frameworks, package managers, and test commands — data-driven (extend by adding aSIGNATURESrow), not a hardcoded menu. The detected test commands now drive the substrate's verification checklist instead of assuming npm.- Six more atlas languages — Ruby, C#, PHP, Kotlin, Swift, and C/C++ join JS/TS,
Python, Go, Rust, and Java (whose method defs are now indexed too). One
RULEStable; the walk, completion gate, and docs sweep pick each up automatically. forge update— self-update:--checkreports whether a newer version is available (commits behind upstream, from a cached hourly fetch), bare applies it (git pull --ff-onlyfor a checkout, or thenpm i -gcommand otherwise).forge doctorsurfaces a non-nagging "update available" notice;FORGE_NO_UPDATE_CHECK=1silences it. Fail-open: offline / non-git / detached-HEAD never error.- Self-dogfood — a committed
.claude/settings.jsonwires forgekit's own guards via${CLAUDE_PROJECT_DIR}, so the repo runs its own completion gate, cortex, and guards during local dev without a marketplace install. - Auto-release on merge — pushing a
feat/fix/perf/breaking change tomasternow cuts the release automatically (bump → tag → npm publish → GitHub Release); a chore/docs-only merge skips cleanly (bump.mjs autoexits3). When[Unreleased]is empty,bump.mjssynthesizes the changelog body from commit subjects so every release still describes itself. Manual Actions → Bump version dispatch stays available. forge docs checknow guards diagrams, model prices, and benchmark numbers — three new reconcilers close the blind spots behind recurring complaints: everymermaidblock across all Markdown must carry the branded theme and use<br/>(not a literal\n); model prices in the docs must matchsrc/model_tiers.json; and every boldedN msclaim in the README must be a valuereports/benchmarks.mdactually measured.
- CLI output is quiet by default — the
Forge <command> — …title line no longer prints on every command; results come first.--verboseorFORGE_VERBOSE=1restores it. The--help/--versionbanner is unchanged. - Unified public design system — the landing page and the generated status page now
share one warm ember/near-black palette and a system font stack (the landing page no
longer declares the Inter webfont it never loaded).
test/pages.test.jsenforces token parity, a non-empty changes list, and no phantom webfont. - Restyled the terminal statusline — a restrained palette (muted structure, one ember
accent, green/red reserved for the diff) with consistent
·separators and a subtle context-limit marker instead of an alarming red block. - Plain-language docs pass — the README and GUIDE openings lead with what forgekit is
and does; the deep math (
y = f(x), join-semilattice, Beta posteriors) moved into parentheticals or the white paper, and comparison-table cells no longer cite code identifiers as if they were user features.
- Broken diagrams — two
mermaiddiagrams rendered in Mermaid's off-brand default theme, one with literal\nnode breaks GitHub showed as garbage; both fixed, and the over-wide 13-node pre-action pipeline was regrouped so it reads at GitHub width. - Status page "Latest changes" list — wrapped CHANGELOG bullets were truncated mid-sentence (and could render empty); the parser now joins lazy/indented continuation lines into the full item.
0.10.0 - 2026-07-10
- The completion gate — a synchronous Stop hook (
global/guards/completion-gate.sh→src/gate.js) that blocks a session ONCE when code changed but no doc or state artifact moved with it, answering with the repair checklist (forge docs sync,forge handoff,forge decide, plus a CUSUM goal-drift alarm when the session's recorded drift sustained). Loop-safe (stop_hook_active+ once-per-session marker), fail-open on every error path, kill switchFORGE_STOPGATE=0. Classification derives from the atlas registries + the shared test-file predicate — no parallel regex lists. forge handoff— the bounded session snapshot: rewrites.forge/state.md(≤150 lines; goal/phase, acceptance criteria, done, next, gotchas, recorded assumptions, in-progress git files) and SessionStart re-injects it, so the next session resumes instead of re-assuming. Refuses secrets like every forge store.forge decide— append-only ADR-lite decision log (.forge/decisions.md,D-####numbering) + a machine-readabledecisionledger twin; bareforge decidelists the last ten. Supersede with a new entry, never an edit.forge docs sync— the diff-driven half of docs↔code alignment: changed identifiers (paths, definitions, called symbols — from added AND removed lines) swept against every doc artifact → UPDATED / STALE (file:line hits) / VERIFIED-UNAFFECTED (reason recorded). Advisory by default,--strictfor CI,--base <ref>to widen; CHANGELOG and the decision log are exempt (append-only history).- Session baseline + rehydration — SessionStart records the session's git anchor
(
.forge/sessions/<sid>.base; a resume never moves it), prunes week-old session artifacts, and injects the handoff snapshot + last 10 commits + uncommitted changes. - Intent protocol cards — UserPromptSubmit classifies the prompt with the same
exemplar k-NN math as routing (labeled bank incl. Hinglish rows, overlap similarity,
confidence gate) and injects a bugfix/feature/refactor/release protocol card once per
run of that intent; questions get no ceremony. Kill switch
FORGE_INTENT=0. - Recorded assumptions — when preflight proceeds without asking, the assumption is appended to the session log, named in the advisory, and surfaces in the next handoff; the per-prompt goal-drift score is recorded the same way and feeds the gate's CUSUM.
- Config artifacts in the atlas — CI workflows (
.githubis now walked), manifests, and Dockerfiles becomeconfig:nodes withreferencesedges to the code paths they name, soforge impactlists the configs a change can break (lockfiles excluded as generated churn). - End-to-end skills + agent —
handoff,sync-docs, andcatchupskills, adoc-synccrew agent that repairs stale docs in its own context, and anend-to-endrules section (Definition of Done, no silent assumptions, decision log) compiled into every tool byforge sync.
cortex.shhook entry resolution in symlink installs —~/.forge/src/…pointed at the nonexistentglobal/src/, silently no-opping every cortex hook outside plugin mode; the shim now resolves through the symlink (pwd -P), same assecret-redact.sh.- Twelve defects found by a two-angle adversarial review of the new layer, all with
regression tests — the gate no longer attributes pre-session dirt, branch-switch/pull
commits, or vendor trees to the session (session-scoped changed set: committer-time
window + SessionStart dirty snapshot);
-zNUL parsing keeps unicode/space/arrow paths correctly classified; an unwritable block-once marker stands down instead of blocking every turn; a missingsession_iddisables gating instead of sharingdefaultstate; a >7-day resume re-anchors instead of losing its baseline to the prune;readStateno longer truncates snapshots whose rows contain<!--;forge decidetakes a lock so concurrent appends can't mint duplicate D-#### ids; the docs sweep stopped scanning its own bookkeeping (.forge/state.md), scans touched docs for REMOVED symbols (the rename case), counts lowercase symbols only inside backticks, dedupes recorded assumptions, and errors on an unknown--baseinstead of mislabeling the report.
0.9.0 - 2026-07-10
- Gateway environments work end to end —
ANTHROPIC_AUTH_TOKENis recognized everywhereANTHROPIC_API_KEYis;ANTHROPIC_MODEL/FORGE_MODELpin one model (bypassing tier routing); a gateway-lookingANTHROPIC_BASE_URLauto-classifies as LiteLLM; and the LLM proposer falls back to direct HTTP (src/llm.js, Anthropic Messages API) when theclaudeCLI is absent — or onFORGE_LLM_HTTP=1. forge docs check(+ CI job + doctor check) — reconciles README/GUIDE/ ARCHITECTURE/ROADMAP against the code: every CLI command documented, every env var read is documented and every documented var is real, MCP tool counts/names match the registry, CHANGELOG sections non-empty. First run found 56 real drift issues, including a phantom env var.scripts/bump.mjsnow refuses to rotate an empty[Unreleased].- Docs are in the impact graph — the atlas parses markdown into doc nodes with
referencesedges to the code they name, soforge impact src/foo.jslists the docs that go stale, and the pre-edit hook says so before the edit. - Persistent goal —
forge anchor set/show/clearstores the active goal in.forge/goal.md; SessionStart re-injects it and a bareforge anchorchecks against it.goalDriftalso returns a gradeddriftScorefor the CUSUM detector. - AGENTS.md auto-repair — the Stop hook re-runs sync when the managed AGENTS.md
drifts from its canonical inputs (disable:
FORGE_AUTOSYNC=0). - Entropy secret detection —
src/secrets.jsis the single source of truth (format grammars + Shannon-entropy gate for unknown-vendor tokens); thesecret-redactguard now imports it, ending the JS/shell regex divergence. src/math.js— Shannon entropy, charset classes, exact set Jaccard/overlap.
- Routing scores by exemplar similarity, not keyword lists — the text rubric is
similarity-weighted k-NN over a labeled
EXEMPLARSbank (overlap-coefficient on stopword-filtered unigram+bigram sets, credibility-shrunk); the four topic keyword regexes and their additive magic weights are gone. Tune routing by adding labeled rows, not by editing weights. - Lesson matching is graded — the keyword tier of
matchScorescores by token overlap (same-module partial credit) instead of all-or-nothing string equality. - Substrate minimality warnings derive from computed signals (preflight missing dimensions + route score) instead of a second keyword copy.
forge scandetects obfuscated payloads — long high-entropy base64 blobs flag as findings alongside the signature rules.providerStatusprobes/healthon any custom base URL and reports behavioral gateway evidence (a proxy that answers /health is a gateway, whatever its hostname).
0.8.1 - 2026-07-08
- MCP write tools —
forge_remember,forge_ledger_ratify,forge_ledger_retractjoin the read tools (19 tools total).
- Simplified CLI surface and improved dashboard UX empty states.
- Stale documentation across command references.
0.8.0 - 2026-07-08
- Forge work system — auto-install flow, multi-provider routing, the cost
dashboard (
forge dash), and the cortex MCP server's read-path tools. - Zero-config provider auto-detection —
autoDetectProvider()resolves the provider from the environment (LiteLLM local/hosted, OpenRouter, Anthropic);forge initreports what it found. - Hosted LiteLLM gateway support —
emitGatewayConfig()writes alitellm.config.yamlexposing complexity tiers as model aliases.
- TypeScript errors and Biome 2.5.2 lint warnings across source and tests.
0.7.0 - 2026-07-08
- Optional embeddings tier (
src/embed.js, ADR-0005; ROADMAP "Next"): setFORGE_EMBED=cmd:<command>(stdin/stdout JSON protocol — any local model or script) orFORGE_EMBED=http:<url>(OpenAI-compatible,$FORGE_EMBED_MODEL/$FORGE_EMBED_KEY, key never logged) andforge reuse query+forge ledger queryreplace the MinHashrelterm with embedding cosine (near/adapt ≥ 0.85/0.7 — a higher bar than Jaccard's 0.8/0.6 to match dense cosine's noise floor), fixing the documented weak spot on very short specs. Vectors are disk-cached (.forge/embed-cache.jsonl, content-hash keyed, corrupt-tolerant, truncate-oldest); both commands print the backend that served (sim: minhash/sim: embed(cmd)); any provider failure degrades silently to MinHash.dependenciesstays empty — the tier is configuration, not a package; the pure ledger core never imports it. forge uicheck visual <file-or-url>— the Playwright visual loop (07-ui-quality-gate §5): renders the page headless at two viewports, fingerprints the computed styles of every visible element (what the cascade and runtime theming actually painted, with usedauto-margins and never-painted UA noise filtered out), and runs the identicaldesigngate over that rendered vector — screenshots land in.forge/ui/. Playwright stays an optional tier (ADR-0005):package.jsongains no dependency, absence degrades to a "skipped (no browser runtime)" note with exit 0 (npm i -D playwright-coreorFORGE_PLAYWRIGHT=…to enable), and non-loopback http(s) targets are refused by default (--remoteto override) — a gate that fetches arbitrary URLs is an exfiltration hazard.
- Ledger read-path flip (P2). Reads are now a merged view (legacy ∪ ledger) via the
new
src/ledger_read.js, so teammate knowledge that arrives withforge ledger mergeactually reaches injection and retrieval: cortex lesson surfaces (lessonsForContext,startupBlock,summary, the substrate advisory and routing past-mistake density) map ledgerlessonclaims onto the legacy lesson shape with an evidence-derived status (tombstoned → retired, val ≥ 0.6 → active, val < 0.45 with a contradiction → quarantined, else candidate), and fact surfaces (recall list/MEMORY.md, brain'sAGENTS.mdindex) include live ledgerfactclaims — always deduped by legacy id/slug with the local file winning, and best-effort (a missing or corrupt ledger degrades to legacy-only). Write paths (recordMistake's confirm-vs-create lookup,recordContradiction,applyDistillation) deliberately keep reading the legacy store they edit; convergence comes from content-addressed claim ids.reconcileFactsnow only tombstones locally-authored claims, so a merged teammate fact survivesforge recall consolidate. Legacy formats are still written — full retirement is the next step. - Professional redesign of the public site, gated by forge's own UI system. The
landing page (
landing/index.html) and the generated status page (scripts/build-pages.mjs→public/index.html) are rebuilt on one design system — theforge dasheight-color warm-ink/ember palette, a strict 4px spacing base, three radius levels, one shadow — and both now passforge uicheck designand the renderedforge uicheck visualgate (the old pages failed with 15–19 accumulated colors and 5–9 radius levels; a project fingerprint claim is minted so conformance is checked too). Scroll-reveal is JS-gated progressive enhancement (no-JS UAs, crawlers, and reduced-motion users see the full page), and the Pages workflow (static.yml) now builds and deploys an assembled_site/— landing at the site root, status page at/status/— instead of uploading the entire repository as the artifact.
0.6.0 - 2026-07-07
- Docs consolidation pass: deduplicated cross-doc prose into single canonical homes
(the substrate README now points at the GUIDE's command reference, output table, and
honest-limits list instead of repeating them), added orientation diagrams
(ARCHITECTURE four-layer compiler + ledger, substrate-v2 phase graph with all phases
marked shipped, the GUIDE daily loop), brought the ROADMAP current, and refreshed the
model-facing skills/crew guidance for the v0.5.0 surface (
forge context,forge imagine --run,forge diagnose,forge ledger blame,forge cost --stages,forge uicheck design --taste) without growing the skills' context payload.
0.5.0 - 2026-07-07
-
Security & OSS hardening: CodeQL, gitleaks secret-scan (blocking; verified clean on the full history), and OSSF Scorecard workflows; refreshed repo topics; SECURITY.md now states the supported line (0.5.x) and documents the ledger's forgery-resistance properties (content-hash verification; oracle weights never trusted from records).
-
UI fingerprints resolve CSS
var()indirection, so design systems declared as custom properties fingerprint fully (the dashboard now reads as a 6-value 4px scale with two radius levels instead of one lonely spacing value), and the five taste profiles gain machine-readable constraint JSONs (global/taste/<name>.json) wired intoforge uicheck design --taste <name>— with auto-pickup from aforge taste-managed DESIGN.md. Prose steers generation; the JSON is what the gate checks. -
One-click release automation.
scripts/bump.mjs(node stdlib only, unit-tested) bumps every version field in one shot —package.json,package-lock.json, both plugin manifests,CITATION.cff, the landing page — rotates the CHANGELOG[Unreleased]section under a dated heading, and prints the new version;npm run bump -- <patch|minor|major|auto>(auto = conventional commits since the last tag: BREAKING → major, feat → minor, else patch). The newbump.ymlworkflow makes a release one click from the Actions tab (commit + tag + dispatch ofrelease.yml);release.ymlnow soft-skips npm publish whenNPM_TOKENis missing instead of failing, and CI gained a version-drift guard (node scripts/bump.mjs check). -
Benchmark harness (
npm run bench) + measured results doc.bench/bench.mjs(node stdlib only) measures the substrate primitives as medians of N runs after warmup — atlas build/incremental/impact latency on this repo, ledger mint+put/loadClaims/mergeDirs/val() on seeded synthetic fixtures, reuse fingerprint + exact/near-LSH lookup at 100 and 1000 artifacts,assemble()and fullsubstrateCheckwall time — and writes the tables plus an environment block intoreports/benchmarks.md. The same run scoresimpact()precision/recall/F1 against a committed, hand-labeled case set from this repo's real import graph (bench/impact_cases.mjs, every reference cited; one known-miss alias case kept in on purpose), reported next to — never blended with — the paper prototype's mutation-derived numbers, plus a structural-only contrast with adjacent tools (note stores, LLM gateways, plain RAG), every row checkable from the named source. -
Loop closure (P5 of the substrate-v2 plan): doom-loop diagnosis, imagination, CUSUM drift, checkpoint cadence.
forge diagnose "<error>"hashes each failure into a signature (line numbers, addresses, timestamps, and absolute paths normalized out) and counts recurrences in a 50-entry ring; the 3rd identical hit is thrash — it mints a content-addresseddiagnosisclaim into the team ledger and tells the agent to STOP retrying and escalate ONE model tier with the diagnosis as the prompt's head (the same loop becomes a one-per-team event, not one-per-session).forge imagine "<task>"is the static half of the consequence simulator (paper Eq. 4): entities → blast radius → predicted breaks with confidence, plus the minimal dry-run test suite via weighted greedy set cover (weight = file size as a duration proxy; classic ln-n approximation) andriskScore = Σ confidence.forge imagine --runexecutes that minimal suite in a sandboxed ephemeral git worktree (HEAD-only — refused on a dirty tree unless--allow-dirty), parses the TAP summary into per-file verdicts, always removes the worktree (verified in a finally), and meters the run (stage: "imagine"); on this repo the 8-test selected suite measured 1.3 s where the full suite takes ~60 s.anchor.cusum()adds the M4 one-sided CUSUM control chart (k = 0.35, h = 1.0): sustained small drift alarms, a single exploratory spike drains back to zero.verify.checkpointCadence()prices M6's "when to check?" as the optimal-stopping threshold rulen* = ⌈checkCost / (pErr·tokensPerStep·costPerToken)⌉, clamped to [1, 50] — every input measured or priced, no magic constants. -
Context assembly + completeness gate (P4 of the substrate-v2 plan).
forge context "<task>"makes what goes into the window a budgeted optimization and makes sufficiency a computed set. The required-knowledge setR(edit)— the target's definitions, its hop-1 dependents from the atlas, sibling tests, and team lessons trusted past val ≥ 0.8 — is derived, then covered by pinned items with a compression ladder (full → head → pointer): a tight budget downgrades granularity instead of silently dropping coverage. Optional items (trusted facts) fill remaining budget greedily with per-source diminishing returns.missing = R \ coveredbecomes derived clarifying questions ("the task namesXbut the repo doesn't define it — which file implements it?"), shown inforge substrateand — underFORGE_ENFORCE=1— blocking: acting on missing context is acting on a guess. Incomplete context stops being a feeling and starts being a set difference. -
Generated-UI quality gate (P6 of the substrate-v2 plan). Taste becomes measurable:
src/uifingerprint.jsextracts a deterministic design fingerprint from CSS/JSX/Tailwind classes — pure static parsing, no LLM, no screenshots — covering palette (HSL + 12-bin hue histogram), spacing (base unit by residual-minimization approximate GCD, on-scale fraction), font families, radius and shadow levels. Two distances gate generated UI:slopDistanceto a shipped, rationale-documented generic-template signature set (default-Tailwind blue/indigo, stock Bootstrap, the AI-landing gradient) must stay HIGH, andconformanceto the project's own fingerprint — stored as a sharedfingerprintledger claim viamintProjectFingerprint— must stay LOW;uiGatefailures are actionable per-feature edits, never a bare score. Scale-conformance checks (spacing-on-base, radius/shadow level caps, palette bound) joinASSERTABLE_CHECKS.forge uicheckgainsfingerprint <file...> [--mint]anddesign <file...>(exit 1 on fail) alongside the unchanged contrast math. -
Local dashboard (P7 of the substrate-v2 plan).
forge dash [--port N]serves a read-only lens on the substrate's state: anode:httpstdlib server (localhost-only, zero runtime deps) with ONE self-contained HTML page — inline CSS/JS, no CDN, no framework, no build step. Panels: Ledger (claims with val bars, kind filter, contested claims — val ∈ [0.4, 0.6] with ≥1 contradiction — and per-author trust), Cost/Cache (stage counters + measured saved-token estimates from.forge/metrics.jsonl), and Impact (atlas blast-radius explorer via/api/impact?target=X). Every claim row shows itsforge ledger blame <id>command — no unexplained scores anywhere in the UI. Data is separated from serving (dashData()vsserve()insrc/dash.js) so the payload is tested without sockets, and corrupt/missing stores degrade to empty sections instead of taking down the lens. The ratify/retract POSTs are a follow-up; this phase never writes. -
Measured cost report (P8 of the substrate-v2 plan).
forge cost --stages [--json]computes per-stage cost factors as pure arithmetic over.forge/metrics.jsonl(src/cost_report.js): gate halt rate, tier-weighted cache hit rate (exact 1.0 / near 0.85 / adapt 0.5), route saving priced against the always-premium baseline, and context assembly — then composesC = C₀ · Π(1 − fᵢ)over ONLY the measured stages. A stage with no events reports "no data", never a default; the composed figure is a lower bound whose caveats name every unmeasured stage; the paper's 62 % routing figure is cited as context, and ~90 % appears only as a labeled target.substrateChecknow meters the assumption gate on the explicit path (onegatehalt/pass line per decision; ambient hooks stay write-free),recordGate/recordRoutegive future stage wiring one obvious call each, andreports/cost-eval.mdscaffolds the paired-run harness report with a truthful empty state. -
Proof-carrying reuse cache (P3 of the substrate-v2 plan).
forge reuseturns "reuse already-generated code" from prose into a deterministic system: verified code becomes anartifactclaim keyed by a normalized task fingerprint (volatile literals → typed placeholders; MinHash sketch + 16×8 LSH banding for near-match), looked up through the exact → near → adapt → miss ladder. An artifact serves ONLY while its proof holds — confidence above the 0.6 floor (an unverified mint sits at the 0.5 prior and does not serve) and every declared dependency still resolving in the atlas; a failed revalidation appends agraph.revalcontradiction, so stale code demotes itself for the whole team.forge reuse query|mint|stats, a reuse stage inforge substrate(read-only on the ambient hook path), andsrc/metrics.js— the stage-tagged.forge/metrics.jsonlthe cost model's measured savings are computed from. Thereuse-firstskill now calls the cache before advising a repo search. -
Team memory (P2 of the substrate-v2 plan). The PCM ledger becomes shared:
forge ledger merge <path>performs the conflict-free semilattice merge of any other ledger tree (a teammate's checkout, a worktree, a backup) — identical knowledge minted independently converges to one claim with every author preserved in its provenance log.forge ledger blame <id>is the accountability view (every mint, every oracle outcome, every retraction, per-author trust).forge ledger query "<text>"ranks live claims by the paper's Eq. 3. Every claim, evidence record, and tombstone now carries the git identity (FORGE_AUTHORoverride; cached; best-effort). Per-author trustu(author) ∈ [0.5, 1]is computed from the oracle track record of the claims an author minted — smoothed to 1.0 for new teammates, floored at 0.5, self-confirmation excluded — and optionally weightsval().forge doctornow checks the union-merge driver is present (a populated ledger without it WILL conflict) and the ledger's normal form.
- PCM ledger hardened after an 8-angle adversarial review of the P1 merge. The
conflict-free-merge guarantee is now structural: claim file bytes are a pure function of
(kind, body, scope) — byte-identical on every replica — while provenance and tombstones
move into per-claim append-only logs (hash-deduped, union-merged like evidence), so
concurrent mints and concurrent retractions can never produce a git conflict or a
merge-order-dependent state. Forged evidence is now powerless AND detectable:
val()takes oracle weights from the ORACLES table (never the stored record) and skips unknown oracles, whileforge ledger verifyrecomputes every record's content hash and flags mismatches, ghost oracles, and inflated weights.forge ledger importis truly idempotent (claims already tracked live are never re-synthesized — no double counting). Cortex shadow-writes: distillation now supersedes (evidence carried over, template claim tombstoned); evidence refs carry the confirmation counter so same-day sessions with colliding episode ids stay distinct; regex-detected reverts contradict at the conservative bridge weight instead of the full-weight human oracle. Fact claims: one CRLF-tolerant parser (recall.readFact), trimmed bodies (shadow path and import path mint one id), same-name updates supersede the stale claim, andforge recall consolidatereconciles deletions into tombstones.putClaimrepairs corrupt/truncated claim files instead of trustingexistsSync.forge ledger --personalreaches the personal ledger (previously write-only);forge ledger showresolves by shard instead of scanning;forge initemits the union-merge.gitattributesrule into consumer repos.SCOPE_WEIGHThas one home (ledger core; lessons re-exports).
- Substrate v2 plan: the whitepaper, completed (
docs/plans/substrate-v2/). Nine specs- two ADRs mapping every remaining paper faculty/mechanism to a concrete algorithm, unified
by the Proof-Carrying Memory (PCM) protocol: every stored unit (lesson, fact, cached
artifact, graph edge, design fingerprint, diagnosis) becomes a content-addressed claim whose
confidence is a decayed Beta posterior over independent-oracle outcomes — retrieval implements
the paper's Eq. 3, team memory is a conflict-free CRDT ledger merged over git, code reuse is a
proof-carrying artifact cache, context assembly is a token-budget knapsack with a set-cover
completeness gate, and generated-UI quality is a measurable slop-distance/conformance gate.
ADR-0005 relaxes the zero-dependency rule to selective optional deps with stdlib fallbacks;
ADR-0006 converges all persistence on the PCM ledger.
ROADMAP.mdnow carries the P1–P8 phase plan. Docs only — no runtime behavior changes.
- two ADRs mapping every remaining paper faculty/mechanism to a concrete algorithm, unified
by the Proof-Carrying Memory (PCM) protocol: every stored unit (lesson, fact, cached
artifact, graph edge, design fingerprint, diagnosis) becomes a content-addressed claim whose
confidence is a decayed Beta posterior over independent-oracle outcomes — retrieval implements
the paper's Eq. 3, team memory is a conflict-free CRDT ledger merged over git, code reuse is a
proof-carrying artifact cache, context assembly is a token-budget knapsack with a set-cover
completeness gate, and generated-UI quality is a measurable slop-distance/conformance gate.
ADR-0005 relaxes the zero-dependency rule to selective optional deps with stdlib fallbacks;
ADR-0006 converges all persistence on the PCM ledger.
- Visual flow diagrams in the entry-point docs. A "one source → every tool + pre-action gate"
mermaid in
README.mdand a "your day with Forge" loop inONBOARDING.md(alongside the propose→verify diagram in the substrate README) — making the model easier to grasp at a glance, while preserving the docs' existing dry-precise voice.
- Proof-Carrying Memory ledger (P1 of the substrate-v2 plan).
src/ledger.js— the pure PCM core (ADR-0006): content-addressed claims over canonical JSON, an oracle taxonomy in which only independent signals (tests, CI, human accept/revert) may move confidence, a time-decayed Beta-posteriorvalthat decays toward uncertainty (never toward false), the paper's Eq. 3 retrieval score, dependency-free MinHash similarity + union-find consolidation clustering, and a join-semilattice merge (property-tested: commutative, associative, idempotent — teammate ledgers converge in any order).src/ledger_store.js— the git-native on-disk ledger (.forge/ledger/): one immutable file per claim sharded by id, append-only hash-deduped evidence logs (union-merge safe, see.gitattributes), tombstones, attic,LEDGER.mdindex, and a CI-friendly normal-formverify.forge ledger stats|verify|show|importCLI. The legacy stores stay the read path in P1: cortex shadow-writes every lesson event (create/confirm/ human-revert contradiction) into the ledger,forge remember/forge recall addshadow facts, andforge ledger importback-fills history idempotently (src/ledger_bridge.js). Secret-refusal now lives in the ledger core so no claim kind can store a credential (re-exported fromrecall.jsfor compatibility). - Uniform
--json.doctor,route,preflight,verify, andscopenow accept--json(previously onlyimpact/substrate/anchordid) — so CI and scripts can gate on the health check, the routed tier, the assumption gap, and the verification result. forge doctorsees more silent misconfiguration. New checks: guard scripts present and executable,jq/gitavailability (several guards degrade withoutjq), atlas presence + freshness (a stale graph misleads impact/verify), and model-pricing staleness (warns when the verified date is >90 days old).- Evaluation harness (
src/eval.js). The deterministic core of the prototype's mutation-testing idea: score the impact oracle's precision/recall/F1 over labeled cases and against the edited-file-only baseline the paper measured against — so the graph-quality claim is checkable in CI.
-
Model tiers carry a currency + a verified date.
model_tiers.jsexportsPRICING_CURRENCY("USD") andPRICING_VERIFIED, whichforge doctoruses for the staleness warning. -
One shared call-site extractor (
src/extract.js).atlas.jsandverify.jseach kept their own copy of the call regex + builtins ignore-list; they now share one module so the two can't drift apart. -
Opt-in enforcing gate (
FORGE_ENFORCE=1). The substrate's assumption gate can now be a real halt (the paper's Eq 5 / M2 "block on insufficient input"), not just advice. On the Claude Code ambient path it blocks a prompt with no concrete anchor at all ("fix it", "make it better") — or an action into a very large predicted blast radius — and returns the clarifying questions. Deliberately low-false-positive: a specified task is never blocked, and it's off by default (enforceDecision()insrc/substrate.js). -
M5 anti-over-engineering is now measured, not guessed (
forge lean). The paper'sφ(y) − φ*(x)check replaces the old three-keyword stub:src/lean.jsreads the working diff and flags the footprint beyond what the task asked for — new abstractions the task never named, a large diff for a short ask, files touched beyond the stated scope. Folded intoforge substrate(aminimality.footprintfield) and available standalone asforge lean "<task>". -
Doom-loop breaker (self-correction). Complements the shell guard (which catches the same action repeated) by catching the subtler loop the paper names — different edits that keep producing the same test failure.
cortex_hooknow captures a normalized signature of failing test output;detectDoomLoopfires when one signature recurs past a threshold, and the pre-edit hook surfaces a "stop and find the root cause" advisory with the diagnosis. -
Consequence simulation — failing-tests class (Eq 4).
forge substratenow predicts the tests likely to break before an edit (impact.predictedTests): the impacted files that are tests, plus each impacted source file's sibling test — surfaced so you run the narrowest affected tests first, not after the fact.
forge syncnow adopts an existing projectCLAUDE.mdinstead of skipping it. Previously a repo with its ownCLAUDE.mdwas left untouched — which meant Forge's shared rules never reached Claude Code there. Sync now prepends the one-line@AGENTS.mdimport (idempotent, every original line preserved) and reportsadopted.AGENTS.mdkeeps its back-up-then-write behaviour; your skills and other tool files are untouched.
- The Cortex capture/learn loop now works in the dotfile install too.
global/settings.template.jsonwired onlycortex.sh preflight(1 of 6 modes), so dotfile users got the substrate advisory but never captured events or distilled lessons — the learning loop was dead for them while plugin users had it. The template now wires all six modes (session-start,prompt,preflight,pre-edit,capture,stop), matchinghooks/hooks.json. forge verifycan't hang.runTestsnow bounds the test run with a timeout (FORGE_VERIFY_TIMEOUT_MS, default 10 min); a timeout is reported honestly as "did not complete", never as a pass.- Secret-refusal no longer guts auth-related work.
SECRET_REmatched the bare wordssecret/password/api key, so any task or lesson merely mentioning them was silently refused — disabling the LLM proposer (adjudicate) and blocking memory persistence (recall/lessons) for exactly the high-risk code you most want help on. The word arm now requires a value-shaped assignment (password = "…",SECRET_KEY: …); credential formats (sk-…,ghp_…, JWTs, …) are still refused. - One malformed file no longer takes down memory.
lessons_store.load/readEpisodesandcortex_hook.readSessionnow skip a corrupt lesson file / JSONL line instead of throwing (which previously broke retrieval, routing, and the pre-edit advisory everywhereloadis used). recordMistakereportsrefused(notcreated) when a save is rejected, so the Stop hook never tries to distill a phantom lesson;applyDistillation/recordContradictionsurface the real write result too.- Atlas emits
inheritsedges (class X extends Y; Pythonclass X(Base)) — the weight was defined but never produced, so base-class changes were invisible to blast-radius. - Atlas is incremental + staleness-aware.
build()reuses per-file extraction by content hash (a sidecar cache) instead of re-parsing the whole repo;isStale()letsverifyrebuild when the cached graph is out of date (post-edit hallucination detection was running on a stale atlas). A capped graph now degrades to "uncertain" rather than raising false "unknown symbol". - Performance:
resolveEdgesis O(E) (was O(E·N) — a full node scan per edge);impact()reuses one memoized reverse-adjacency map across the up-to-8 calls persubstraterun. substrateno longer recomputes preflight twice (or fires a redundant assumption model call): the gap is computed once and threaded into routing.
- Opt-in LLM adjudication for the substrate (
FORGE_LLM=1) — one shared, fail-safeclaude -pproposer (src/adjudicate.js) wired thinly into the assumption gate (M2), model routing (M1), impact/blast-radius, and goal-drift (M4). The model only proposes; every proposal is verified against the deterministic rubric, the code graph, or a grep before it can move a verdict. Off by default — behaviour is unchanged unless enabled — never blocks, and the ambient Claude Code hook stays deterministic unlessFORGE_LLM_AMBIENT=1.forge substrate --jsoncarries anllm.provenancemap per faculty for auditability. - Bidirectional verified reconcile (default on when
FORGE_LLM=1;llm.bidirectionalinsource/substrate.jsonto disable). A verified reading may now reduce caution as well as add it — clear a false "ASK FIRST" (llm-cleared) and route a task down a tier (llm-lowered) — but only withinbandand never past the hard floors: the gate can't clear a task with no concrete anchor or one naming symbols/files the repo lacks, and routing can't drop below a strong-signal (algorithmic/architectural) floor. Setllm.bidirectional: falsefor the conservative tighten-/raise-only mode. Impact edges stay graph-+-grep-verified; goal-drift stays off→on with a goal-referencing reason. - Explicit memory
valterm — lesson retrieval now decomposes into the white paper'srelevance × freshness × validity × scope, withvalidity()(a ground-truth Beta posterior over confirmed vs. contradicted outcomes) exported and ranked so outcome-confirmed lessons outrank merely-recent ones.
- Unified the model-call path — the Cortex distiller now shares the
adjudicaterunner instead of its ownclaudeshell-out.
0.4.0 - 2026-07-06
- Forge Cognitive Substrate — one pre-action command (
forge substrate) plus an MCP surface (substrate_check,predict_impact,assumption_gate,route_task,scope_files): assumption gate, transparent model routing, impact/blast-radius, scope decomposition, Cortex lessons, minimality, and a verification checklist. - M4 goal-anchoring (
forge anchor) — a deterministic goal-drift check that flags changed files off the stated goal. All 11 white-paper capabilities now ship a real mechanism. - Atlas v2 graph — dependency nodes/edges + reverse-dependency impact traversal (the symbol-query API is preserved).
docs/GUIDE.md(the complete command guide) anddocs/RELEASING.md(release runbook).- Repo automation —
repo-settings.yml(About/topics/Discussions as code) andlabels.yml(label sync) workflows; a Codex plugin manifest andcognitive-substrateskill; the paper bundle underdocs/cognitive-substrate/.
- Publish to public npm.
@codewithjuber/forgekitnow publishes to npmjs with provenance, sonpm install -g @codewithjuber/forgekitneeds no token (replacing the GitHub Packages route, which required auth even for public installs). The release workflow was fixed to trigger on a tag, publish, and cut a GitHub Release with generated notes. - Substrate auto-runs in Claude Code via a
UserPromptSubmithook — it surfaces only when something needs attention and never blocks — andforge initemits a "run substrate before risky work" rule into every other tool's config. - Docs overhaul — README rewritten (problem → solution → how, npm-first, SEO-friendly); the install, honest-limits, frozen-model, and substrate blocks are single-sourced instead of copied across files; the supported-tool list is reconciled everywhere.
- Security (research prototype): removed the pickle-based cache in
impact_oracle/world_model.py— an insecure-deserialization (RCE) vector on a caller-suppliedcache_dir. Now JSON node-link only, withcache_dircontained insideroot. - Smaller npm package — stopped publishing the ~2 MB paper bundle and the redundant
*_src.zip(source lives unzipped underresearch/). - Perf —
substrateCheckno longer recomputes the assumption assessment.
0.3.1 - 2026-07-05
- Publish to GitHub Packages instead of npmjs. Package renamed to the scoped
@codewithjuber/forgekit;publishConfig.registry→https://npm.pkg.github.com. The release workflow now authenticates with the built-inGITHUB_TOKEN(packages: write) — no externalNPM_TOKENsecret. A committed.npmrcmaps the scope to the registry and setsmin-release-age=7(supply-chain cooldown). Note: GitHub Packages requires consumers to authenticate even for public installs, so thebash install.shclone path stays the friction-free primary channel.
0.3.0 - 2026-07-05
- Forge Preflight — a deterministic, math-first layer that runs BEFORE tokens are spent,
on the premise that an LLM is a fixed-capacity stochastic predictor: size the task to the
model, fill the context, detect assumptions. All advisory, never blocks.
- Assumption detector (
forge preflight, UserPromptSubmit hook): scans a task for code identifiers/files the repo doesn't define — what the model would otherwise ASSUME — and surfaces the known-unknowns so it asks instead of confabulating. The research whitespace. - Complexity routing (
forge route): recommends the cheapest CAPABLE model (Haiku → Sonnet → Opus → Fable) from code-task signals (files, fan-out, churn, past-mistake density, ambiguity).forge route gatewayemits a LiteLLM config for real auto-routing. - Decomposition (
forge scope): a zero-dep import graph → connected components → independent clusters (run as separate sessions) + the coupled files you didn't name. - Design-quality: emitted AI-UX rules (anti-slop, WCAG, functional empty states, specific
errors, confidence/transparency, pattern selection) +
forge uicheck(exact WCAG contrast math) + a calibrated frontend-verifier that ASSERTS only the deterministic and keeps hierarchy/taste ADVISORY (the fix for hallucinated UI audits). - Cross-tool via
preflight_check/route_task/scope_filesMCP tools.
- Assumption detector (
0.2.0 - 2026-07-05
- Forge Cortex — self-correcting project memory. Detects a genuine recurring mistake
on this repo (test-fail→fix, revert, symbol thrash, explicit human undo), distills a
structured lesson, and re-confirms it against independent outcomes — with an
anti-self-reinforcement lifecycle (
Betaconfidence + decay; injection never confirms; a green build always wins) so a wrong lesson decays out instead of ossifying.forge cortex,forge cortex why <symbol>. - Ambient hooks (fail-safe, never block): capture signals during a session, distill at
Stop, inject learned lessons atSessionStart, and aPreToolUseadvisory before a risky edit. - Local error predictor (heuristic + a tiny logistic model) gated by an AUC-PR kill-switch — it only ships if it measurably beats the heuristic; otherwise it falls back or disables.
- Cross-tool: lessons inlined into
AGENTS.md+ a zero-dependency MCP server (forge cortex-mcp, registered insource/mcp.json). - Optional LLM lesson distiller (
ENABLE_CORTEX_DISTILL=1) — replaces the deterministic template with a real distilled lesson viaclaude -p. forge doctorreports Cortex lesson state;forge cataloglists Cortex.
0.1.0 - 2026-07-05
- Cross-tool config emitter (
forge sync) — one source → each tool's native format; three install channels (Claude plugin + marketplace, installer, npm);forge doctor; code-graph (atlas);leandiscipline; guard/skill/crew layers. - Verification layer:
forge verify(tests + hallucinated-symbol catch + provenance), doom-loop breaker guard, bias-safeindependent-revieweragent. - Security gate:
forge scan(skill-gate),secret-redactguard, structuredpermissionDecisioninprotect-paths,forge harden(gitleaks + sandbox). - Cross-tool MCP emit; portable memory (
forge brain/forge remember); design-taste menu (forge taste);forge specspec-lock + OpenSpec wiring; MCP ~6-server hygiene check; coverage + type-checking (tsc --checkJs); 2026 production-standard rules; OWASP-LLM / NIST SSDF / SLSA control mapping.