From 80798953cb259f77c4ca581624245351f7160028 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 18:02:47 +0000 Subject: [PATCH 1/2] feat(usability): dynamic stack + more languages, self-update, quiet CLI, self-dogfood MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four owner-requested improvements, plus a ReDoS fix found in review. Tech (dynamic + broader): - src/stack.js + `forge stack`: detect the repo's REAL stack by reading its manifests (package.json/pyproject/go.mod/Cargo.toml/Gemfile/composer.json/ pom.xml·gradle/*.csproj) → languages, frameworks, package managers, and the actual test commands, which now feed substrate's verification checklist. Data-driven (add a row, not code), fail-safe on every manifest. - atlas RULES gains Ruby, C#, PHP, Kotlin, Swift, C/C++ (and Java method defs). One registry; the walk, completion gate, and docs sweep pick each up via CODE_EXTS. The shared Java/C# method grammar is line-anchored and {0,6}-bounded after review caught polynomial backtracking (5.2s → 26ms on a pathological file); a ReDoS regression test pins it. Auto-update: - src/update.js + `forge update` (`--check` reports commits-behind-upstream from a cached hourly fetch; bare applies via ff-only pull, or hands back `npm i -g`). doctor surfaces a non-nagging notice (FORGE_NO_UPDATE_CHECK=1 silences). Fail-open on offline / non-git / detached HEAD. Quiet CLI: - The `Forge —` title line is now behind `--verbose`/FORGE_VERBOSE; commands emit their result first. The --help/--version banner is unchanged. Self-dogfood: - .claude/settings.json wires forgekit's own guards via ${CLAUDE_PROJECT_DIR}, so the repo runs its own completion gate / cortex / guards in local dev. Docs (README/GUIDE/ARCHITECTURE) + CHANGELOG updated; `forge docs check` green. 620 tests → 632 (12 new), biome + typecheck clean. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2 --- .claude/settings.json | 64 +++++++++ ARCHITECTURE.md | 83 +++++++---- CHANGELOG.md | 81 +++++++---- README.md | 138 +++++++++--------- docs/GUIDE.md | 303 +++++++++++++++++++++++----------------- src/atlas.js | 240 ++++++++++++++++++++++++++----- src/cli.js | 119 ++++++++++++---- src/commands.js | 6 +- src/doctor.js | 16 +++ src/stack.js | 276 ++++++++++++++++++++++++++++++++++++ src/substrate.js | 9 +- src/update.js | 125 +++++++++++++++++ test/atlas.test.js | 51 +++++++ test/cli_cortex.test.js | 4 +- test/diagnose.test.js | 98 ++++++++++--- test/dogfood.test.js | 32 +++++ test/quiet.test.js | 33 +++++ test/stack.test.js | 84 +++++++++++ test/uivisual.test.js | 39 ++++-- test/update.test.js | 67 +++++++++ 20 files changed, 1527 insertions(+), 341 deletions(-) create mode 100644 .claude/settings.json create mode 100644 src/stack.js create mode 100644 src/update.js create mode 100644 test/dogfood.test.js create mode 100644 test/quiet.test.js create mode 100644 test/stack.test.js create mode 100644 test/update.test.js diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..d3f476c --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,64 @@ +{ + "//": "forgekit dogfoods its own plugin during local dev. These hooks mirror hooks/hooks.json but resolve through ${CLAUDE_PROJECT_DIR} (this repo) instead of ${CLAUDE_PLUGIN_ROOT}, so the guards run without a marketplace install. Every guard is advisory/fail-open; the completion gate honors FORGE_STOPGATE=0.", + "statusLine": { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/statusline.sh" }, + "hooks": { + "SessionStart": [ + { + "matcher": "startup|resume|clear", + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/recall-load.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh session-start" } + ] + } + ], + "UserPromptSubmit": [ + { + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh prompt" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh preflight" } + ] + } + ], + "PreToolUse": [ + { + "matcher": "Edit|Write|MultiEdit|Bash", + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/protect-paths.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cost-budget.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/doom-loop.sh" } + ] + }, + { + "matcher": "Edit|Write|MultiEdit", + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh pre-edit" } + ] + } + ], + "PostToolUse": [ + { + "matcher": "Edit|Write|MultiEdit", + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/format-on-edit.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh capture" } + ] + }, + { + "matcher": "Bash|Read|Grep", + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/secret-redact.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh capture" } + ] + } + ], + "Stop": [ + { + "hooks": [ + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/completion-gate.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/lean-guard.sh" }, + { "type": "command", "command": "bash \"${CLAUDE_PROJECT_DIR}\"/global/guards/cortex.sh stop" } + ] + } + ] + } +} diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 466f1f5..23bd176 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -3,7 +3,7 @@ > **One brain for every AI coding agent.** A large language model is stateless: one > context window, wiped every call. It has no memory of what your team learned, no > foresight about what an edit will break, and no enforced guardrails. forgekit is the -> **cognitive substrate** — the layer that runs *before* the model edits code, supplying +> **cognitive substrate** — the layer that runs _before_ the model edits code, supplying > proof-carrying memory, impact foresight, and enforced guardrails — and a **cross-tool > config compiler** that delivers that brain as native config into every tool at once. @@ -23,6 +23,7 @@ Every command referenced below is real and wired in `src/cli.js`. Run `forge --h for the full list. ## Locked decisions + - **Brand = `Forge`** — CLI `forge`; layer names: skills→**tools**, agents→**crew**, hooks→**guards**, code-graph→**atlas**, minimalism→**lean**, memory→**recall**. Brand stored as **one token** (the `brand` key in `brand.json`); rebrand = 1 edit. @@ -30,8 +31,8 @@ for the full list. the brand token changes, so a rename never breaks install. - **Scope = full multi-tool day 1** — nine tools plus MCP, from one canonical source. - **Install = all three channels** (plugin + hardened installer + npm CLI), all - three pointing at the *same* tree ("one tree, three front doors"). -- **Own `lean` + `atlas`** — as *thin layers over proven primitives*, not + three pointing at the _same_ tree ("one tree, three front doors"). +- **Own `lean` + `atlas`** — as _thin layers over proven primitives_, not from-scratch reimplementations (reuse-first). ## 1. A four-layer config compiler with ONE source @@ -65,7 +66,7 @@ The four layers, brand-named and emitted cross-tool: - **crew** (`~/.forge/crew/` → `~/.claude/agents/`) — isolated sub-agents (scout / verifier / frontend-verifier). - **guards** (`~/.forge/guards/` → `settings.json` hooks) — **the only layer that - *enforces* rather than suggests.** A guard is a deterministic hook the model cannot + _enforces_ rather than suggests.** A guard is a deterministic hook the model cannot drift from. Prose rules in CLAUDE.md get acknowledged and then forgotten after compaction; a guard does not. Every enforceable invariant belongs here. - **mcp** — the protocol layer. Forge ships one stdio server (`src/cortex_mcp.js`) @@ -74,12 +75,12 @@ The four layers, brand-named and emitted cross-tool: ratify/retract), and ops/health — the full table is in docs/GUIDE.md. Cross-cutting concerns thread through all four: **atlas** (the code graph), **lean** -(minimalism — shipped as *both* a tool and a Stop-guard, so it applies whether or not +(minimalism — shipped as _both_ a tool and a Stop-guard, so it applies whether or not the model invokes it), and **recall** (memory). ## 2. The pre-action gate — `forge substrate` -**cognitive substrate** — the layer that runs *before* the model edits code. `forge +**cognitive substrate** — the layer that runs _before_ the model edits code. `forge substrate ""` (and the MCP tool `substrate_check`) runs one ordered pass of checks and returns a single verdict. It composes the individually-callable stages (`preflight`, `route`, `atlas`, `impact`, `reuse`, `context`, `scope`, `lean`, @@ -120,7 +121,7 @@ Everything else stays a warning the human can override. ## 3. Proof-carrying memory — the ledger + team merge **proof-carrying memory (PCM)** — every stored fact, lesson, or reuse artifact is a -*claim* that carries its own evidence. It is trusted only once independent oracles +_claim_ that carries its own evidence. It is trusted only once independent oracles (tests, CI, a human accept/revert) raise its confidence above a floor. A wrong lesson decays out instead of ossifying. @@ -161,7 +162,7 @@ Decision recorded in ## 4. The reuse / context loop `forge reuse` is a proof-carrying code cache. A generated artifact is only served again -when its evidence still holds — the confidence is above the floor *and* its atlas +when its evidence still holds — the confidence is above the floor _and_ its atlas dependencies still resolve. Otherwise it falls through to generation and mints a fresh claim on the way back. @@ -181,7 +182,7 @@ flowchart LR The completeness gate on the retrieval side is `forge context ""`: it assembles a budgeted context via set-cover over the predicted edit set (`R(edit)`), applies a -compression ladder, and reports the *computed missing set* — the inputs it could not +compression ladder, and reports the _computed missing set_ — the inputs it could not assemble. That missing set is exactly what the substrate pipeline's context stage reads to decide whether an edit is safe to start. Surface: `forge reuse query | mint | stats`. @@ -189,8 +190,8 @@ to decide whether an edit is safe to start. Surface: `forge reuse query | mint | Two failure modes this layer exists to kill: **partial work** (code changes without the artifacts that depend on it) and **session amnesia** (the next session re-assumes what -this one knew). Instructions raise the *probability* of correct behavior; deterministic -hooks guarantee a *floor* — with per-task miss rate `1−p` and gate catch rate `c`, +this one knew). Instructions raise the _probability_ of correct behavior; deterministic +hooks guarantee a _floor_ — with per-task miss rate `1−p` and gate catch rate `c`, silent misses fall to `(1−p)(1−c)`, and every layer here is one more `c`. **The completion gate (Stop, `src/gate.js`).** The only Stop-path guard that may answer: @@ -207,7 +208,7 @@ other row allows, every internal error allows (fail-open), the once-per-session is written BEFORE the block (unwritable marker → stand down rather than nag every turn), a missing `session_id` disables gating (no shared-state leaks between sessions), and `FORGE_STOPGATE=0` kills it. `.forge/state.md` is gitignored, so its signal is -mtime-vs-baseline (the baseline file's mtime *is* session start). +mtime-vs-baseline (the baseline file's mtime _is_ session start). **Session anchoring (SessionStart, `src/session.js`).** Records `HEAD` once per session (`.forge/sessions/.base`; resume keeps it), prunes week-old session artifacts, and @@ -251,6 +252,7 @@ session-learner` (guards) · `statusline` · `tech-currency · stack-notes · self-correction` (rules) · project-layer template. **Own-branded replacements (thin layer over proven primitive):** + - **`lean`** — a model-invoked **tool** (YAGNI ladder, reuse-before-build, shortest-diff) **+** a deterministic **`lean-guard`** Stop-hook that nudges on oversized diffs. No plugin, no engine. @@ -258,6 +260,7 @@ self-correction` (rules) · project-layer template. graph engine, no language server, no database. **Net-new (justified by a pain):** + - **`forge sync`** (the cross-tool emitter) · **`forge doctor`** (health check) · **`forge init`** (one-command bootstrap) · **`cost-budget` guard** · **Start-Here catalog** · **`recall`** unified memory subsystem. @@ -278,26 +281,53 @@ self-correction` (rules) · project-layer template. `atlas.json` is the single source the impact, reuse-revalidation, and hallucination-flag stages all read. There is no SQLite database and no `.forge/atlas.db`. +The `RULES` table (`src/atlas.js`) is the ONE language registry — JS/TS, Python, Go, +Rust, Java, Ruby, C#, PHP, Kotlin, Swift, C/C++ as regex grammars (zero-dep; a real +parser would need tree-sitter, which the no-runtime-deps rule forbids). `CODE_EXTS = +new Set(Object.keys(RULES))` means adding a language auto-extends the walk, the +completion gate's code-class, and the docs sweep — no other file changes. + +**`forge stack` (`src/stack.js`)** answers the complementary question the parser can't: +_what is this repo actually built with?_ It reads the dependency manifests +(package.json, pyproject.toml, go.mod, Cargo.toml, Gemfile, composer.json, pom.xml/ +build.gradle, *.csproj) and reports languages + frameworks + package managers + real +test commands. Detection is data (`SIGNATURES`-style tables), every reader is fail-safe, +and the detected test commands feed `substrate`'s verification checklist — so "run the +tests" means the repo's *actual\* runner, not an assumed `npm test`. + +**`forge update` (`src/update.js`)** is the self-update path across all three install +modes. It detects a git checkout vs an npm/copy install, does a cached (hourly) best- +effort `git fetch`, and reports commits-behind-upstream; `doctor` surfaces that as a +non-nagging notice (`FORGE_NO_UPDATE_CHECK=1` to silence). Every path is fail-open — +offline, no upstream, or detached HEAD returns "unknown", never an error. + +CLI output is **quiet by default**: the per-command `Forge — …` title is branding +chrome behind `--verbose`/`FORGE_VERBOSE`, so a command emits its result first. The repo +also dogfoods its own plugin via a committed `.claude/settings.json` that wires the +guards through `${CLAUDE_PROJECT_DIR}`. + ## Verified cross-tool emit matrix -*(All rows confirmed against vendor docs.)* Forge emits config for **nine tools**, plus + +_(All rows confirmed against vendor docs.)_ Forge emits config for **nine tools**, plus an **MCP server** for Roo Code and VS Code. -| Tool | Native target | How Forge emits | -|------|---------------|-----------------| -| **Claude Code** | `CLAUDE.md` (+ `.claude/rules/*.md`, `settings.json`); **no** AGENTS.md | Thin `CLAUDE.md` whose first line is `@AGENTS.md`; guards+permissions → `settings.json` | -| **Codex** | `AGENTS.md` native (32 KiB cap) | Canonical `AGENTS.md` at root **is** the source; keep < 32 KiB or it silently truncates | -| **Cursor** | `AGENTS.md` + `.cursor/rules/*.mdc` (`.cursorrules` deprecated) | `AGENTS.md` for flat rules; `.mdc` when scoping/precedence needed; never leave a legacy `.cursorrules` | -| **Gemini** | `GEMINI.md` by default; **AGENTS.md only via `context.fileName` opt-in** | Write `.gemini/settings.json` `context.fileName:["AGENTS.md",…]` (avoids a 2nd copy) | -| **Aider** | `CONVENTIONS.md` via `read:` in `.aider.conf.yml` | Emit `.aider.conf.yml` with `read: AGENTS.md` | -| **Copilot** | root `AGENTS.md` + `.github/copilot-instructions.md` | Rely on root `AGENTS.md`; optional generated `.github` pointer | -| **Windsurf/Devin** | `AGENTS.md` auto-discovered; caps 6k/12k chars | Root `AGENTS.md` under caps; detect `.windsurf` vs `.devin` at init | -| **Zed** | first match of a precedence list incl. `AGENTS.md` | Emit `AGENTS.md` + doctor flags any earlier-precedence legacy file shadowing it | -| **Continue** | `.continue/rules/*.md` + `.continue/mcpServers/*.yaml` | Emit a rules file plus the Forge MCP server config | +| Tool | Native target | How Forge emits | +| ------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------ | +| **Claude Code** | `CLAUDE.md` (+ `.claude/rules/*.md`, `settings.json`); **no** AGENTS.md | Thin `CLAUDE.md` whose first line is `@AGENTS.md`; guards+permissions → `settings.json` | +| **Codex** | `AGENTS.md` native (32 KiB cap) | Canonical `AGENTS.md` at root **is** the source; keep < 32 KiB or it silently truncates | +| **Cursor** | `AGENTS.md` + `.cursor/rules/*.mdc` (`.cursorrules` deprecated) | `AGENTS.md` for flat rules; `.mdc` when scoping/precedence needed; never leave a legacy `.cursorrules` | +| **Gemini** | `GEMINI.md` by default; **AGENTS.md only via `context.fileName` opt-in** | Write `.gemini/settings.json` `context.fileName:["AGENTS.md",…]` (avoids a 2nd copy) | +| **Aider** | `CONVENTIONS.md` via `read:` in `.aider.conf.yml` | Emit `.aider.conf.yml` with `read: AGENTS.md` | +| **Copilot** | root `AGENTS.md` + `.github/copilot-instructions.md` | Rely on root `AGENTS.md`; optional generated `.github` pointer | +| **Windsurf/Devin** | `AGENTS.md` auto-discovered; caps 6k/12k chars | Root `AGENTS.md` under caps; detect `.windsurf` vs `.devin` at init | +| **Zed** | first match of a precedence list incl. `AGENTS.md` | Emit `AGENTS.md` + doctor flags any earlier-precedence legacy file shadowing it | +| **Continue** | `.continue/rules/*.md` + `.continue/mcpServers/*.yaml` | Emit a rules file plus the Forge MCP server config | Roo Code and VS Code receive the Forge MCP server via `forge init` (`.roo/mcp.json`, `.vscode/mcp.json`) rather than a rules file. ## Repo layout — one tree, three front doors + ``` forgekit/ package.json # npm CLI: bin `forge` → src/cli.js @@ -336,6 +366,7 @@ forgekit/ scripts/ build-pages.mjs # generates public/index.html, the live status page, from real repo data ``` + Public site deploy (two independent Pages targets, both built from `landing/` + `scripts/build-pages.mjs`): `.github/workflows/static.yml` (GitHub Pages — assembles landing + status page into one `_site/`) · `.gitlab-ci.yml` (GitLab Pages — status @@ -346,9 +377,10 @@ The plugin manifest, `install.sh`, and the npm bin **all reference `global/` + asserts all three resolve to `global/`. ## Risks & honest boundaries + - **Enforcement ceiling** — guards enforce only what is expressible as a hook (paths, format, diff-size, budget). Semantic rules ("prefer functional") stay prose and - *will* sometimes be ignored. Forge **reduces, does not eliminate** rule drift. Say so. + _will_ sometimes be ignored. Forge **reduces, does not eliminate** rule drift. Say so. - **Verification reduces, does not certify** — `crew` verifiers and the `atlas has` hallucination flag cut review burden; they do not prove the code correct. - **No weight-level learning** — `recall` / `self-improve` are file-and-prompt memory @@ -368,5 +400,6 @@ asserts all three resolve to `global/`. `FORGE_EMBED` is the only embeddings path, and it is opt-in. --- + See [ROADMAP.md](ROADMAP.md) for direction and [`docs/adr/`](docs/adr/) for the recorded architecture decisions (zero runtime deps, the SKILL.md standard, guard-over-prose). diff --git a/CHANGELOG.md b/CHANGELOG.md index a5709fa..fa80487 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,36 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### Added + +- **`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 a `SIGNATURES` + row), 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 `RULES` table; + the walk, completion gate, and docs sweep pick each up automatically. +- **`forge update`** — self-update: `--check` reports whether a newer version is + available (commits behind upstream, from a cached hourly fetch), bare applies it + (`git pull --ff-only` for a checkout, or the `npm i -g` command otherwise). `forge +doctor` surfaces a non-nagging "update available" notice; `FORGE_NO_UPDATE_CHECK=1` + silences it. Fail-open: offline / non-git / detached-HEAD never error. +- **Self-dogfood** — a committed `.claude/settings.json` wires 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. + +### Changed + +- **CLI output is quiet by default** — the `Forge — …` title line no longer + prints on every command; results come first. `--verbose` or `FORGE_VERBOSE=1` restores + it. The `--help` / `--version` banner is unchanged. + ## [0.10.0] - 2026-07-10 ### Added + - **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`, @@ -48,6 +75,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). compiled into every tool by `forge sync`. ### Fixed + - **`cortex.sh` hook entry resolution in symlink installs** — `~/.forge/src/…` pointed at the nonexistent `global/src/`, silently no-opping every cortex hook outside plugin mode; the shim now resolves through the symlink (`pwd -P`), same as `secret-redact.sh`. @@ -67,6 +95,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.9.0] - 2026-07-10 ### Added + - **Gateway environments work end to end** — `ANTHROPIC_AUTH_TOKEN` is recognized everywhere `ANTHROPIC_API_KEY` is; `ANTHROPIC_MODEL` / `FORGE_MODEL` pin one model (bypassing tier routing); a gateway-looking `ANTHROPIC_BASE_URL` auto-classifies as @@ -92,6 +121,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **`src/math.js`** — Shannon entropy, charset classes, exact set Jaccard/overlap. ### Changed + - **Routing scores by exemplar similarity, not keyword lists** — the text rubric is similarity-weighted k-NN over a labeled `EXEMPLARS` bank (overlap-coefficient on stopword-filtered unigram+bigram sets, credibility-shrunk); the four topic keyword @@ -109,18 +139,22 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [0.8.1] - 2026-07-08 ### Added + - **MCP write tools** — `forge_remember`, `forge_ledger_ratify`, `forge_ledger_retract` join the read tools (19 tools total). ### Changed + - Simplified CLI surface and improved dashboard UX empty states. ### Fixed + - Stale documentation across command references. ## [0.8.0] - 2026-07-08 ### Added + - **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 @@ -130,9 +164,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). `litellm.config.yaml` exposing complexity tiers as model aliases. ### Fixed -- TypeScript errors and Biome 2.5.2 lint warnings across source and tests. - +- TypeScript errors and Biome 2.5.2 lint warnings across source and tests. ## [0.7.0] - 2026-07-08 @@ -260,8 +293,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). [1, 50] — every input measured or priced, no magic constants. - **Context assembly + completeness gate (P4 of the substrate-v2 plan).** `forge context - ""` makes what goes into the window a budgeted optimization and makes - *sufficiency* a computed set. The required-knowledge set `R(edit)` — the target's +""` makes what goes into the window a budgeted optimization and makes + _sufficiency_ a computed set. The required-knowledge set `R(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 @@ -353,7 +386,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 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, and `forge recall - consolidate` reconciles deletions into tombstones. `putClaim` repairs corrupt/truncated +consolidate` reconciles deletions into tombstones. `putClaim` repairs corrupt/truncated claim files instead of trusting `existsSync`. `forge ledger --personal` reaches the personal ledger (previously write-only); `forge ledger show` resolves by shard instead of scanning; `forge init` emits the union-merge `.gitattributes` rule into consumer @@ -362,16 +395,16 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Documentation - **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.md` now 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. `ROADMAP.md` now carries the P1–P8 + phase plan. Docs only — no runtime behavior changes. - **Visual flow diagrams in the entry-point docs.** A "one source → every tool + pre-action gate" mermaid in `README.md` and a "your day with Forge" loop in `ONBOARDING.md` (alongside the propose→verify diagram in the substrate README) — making the model easier to grasp at a glance, @@ -382,7 +415,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - **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-posterior `val` that decays toward *uncertainty* (never + confidence, a time-decayed Beta-posterior `val` that 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). @@ -415,7 +448,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 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 + _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** @@ -425,13 +458,13 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 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 into `forge substrate` (a `minimality.footprint` field) and available standalone as `forge lean ""`. -- **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_hook` now captures a normalized signature of failing +- **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_hook` now captures a normalized signature of failing test output; `detectDoomLoop` fires 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 substrate` now predicts the - tests likely to break *before* an edit (`impact.predictedTests`): the impacted files that are + 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. @@ -457,7 +490,7 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). `secret`/`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* + 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`/`readEpisodes` and `cortex_hook.readSession` now skip a corrupt lesson file / JSONL line instead of throwing @@ -478,8 +511,8 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Added -- **Opt-in LLM adjudication for the substrate (`FORGE_LLM=1`)** — one shared, fail-safe `claude -p` proposer (`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 unless `FORGE_LLM_AMBIENT=1`. `forge substrate --json` carries an `llm.provenance` map per faculty for auditability. -- **Bidirectional verified reconcile (default on when `FORGE_LLM=1`; `llm.bidirectional` in `source/substrate.json` to 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 within `band` and 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. Set `llm.bidirectional: false` for the conservative tighten-/raise-only mode. Impact edges stay graph-+-grep-verified; goal-drift stays off→on with a goal-referencing reason. +- **Opt-in LLM adjudication for the substrate (`FORGE_LLM=1`)** — one shared, fail-safe `claude -p` proposer (`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 unless `FORGE_LLM_AMBIENT=1`. `forge substrate --json` carries an `llm.provenance` map per faculty for auditability. +- **Bidirectional verified reconcile (default on when `FORGE_LLM=1`; `llm.bidirectional` in `source/substrate.json` to 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 within `band` and 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. Set `llm.bidirectional: false` for the conservative tighten-/raise-only mode. Impact edges stay graph-+-grep-verified; goal-drift stays off→on with a goal-referencing reason. - **Explicit memory `val` term** — lesson retrieval now decomposes into the white paper's `relevance × freshness × validity × scope`, with `validity()` (a ground-truth Beta posterior over confirmed vs. contradicted outcomes) exported and ranked so outcome-confirmed lessons outrank merely-recent ones. ### Changed diff --git a/README.md b/README.md index e6eaf5f..66cf325 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ A large language model is stateless — one context window, wiped every call. - It has **no enforced guardrails** — prose rules get forgotten after a compaction. And every tool wants its own config file (`CLAUDE.md`, `AGENTS.md`, `.cursor/rules`, -`GEMINI.md`, MCP…). Forge is the **cognitive substrate** — the layer that runs *before* +`GEMINI.md`, MCP…). Forge is the **cognitive substrate** — the layer that runs _before_ the model edits code, supplying memory, foresight, and guardrails — and the compiler that delivers it into every tool from one source. @@ -81,11 +81,11 @@ so a wrong lesson decays out instead of ossifying. Full design: The day-to-day value first — the substrate gives a frozen model what it can't hold itself: - **Memory that persists across sessions and teammates.** Every lesson, fact, and verified - reuse is *proof-carrying memory (PCM)* — a claim that carries its own evidence and is only + reuse is _proof-carrying memory (PCM)_ — a claim that carries its own evidence and is only trusted once independent oracles raise its confidence above a floor. Wrong lessons decay out instead of ossifying. - **Foresight before you break things.** Ask "what does changing `verifyToken` break?" and - get the *blast radius* — the set of files an edit is predicted to impact, read from the + get the _blast radius_ — the set of files an edit is predicted to impact, read from the code graph, including coupled files you never named. - **Guardrails that can't be forgotten.** Deterministic hooks enforce the rules a model must never break (protected paths, cost budget, doom loops) — they survive a context compaction @@ -102,8 +102,8 @@ The day-to-day value first — the substrate gives a frozen model what it can't ### The measured evidence Every number is a median from `npm run bench` on this repo, recorded with its environment -block in [`reports/benchmarks.md`](reports/benchmarks.md) — the project rule is *a number is -an assumption until measured*. +block in [`reports/benchmarks.md`](reports/benchmarks.md) — the project rule is _a number is +an assumption until measured_. - **Blast radius in 0.43 ms** (warm code-graph). On 6 hand-labeled cases from this repo's real import graph: recall **0.97** vs **0.33** for looking at the edited file alone. @@ -112,7 +112,7 @@ an assumption until measured*. Claude Code it runs on **every prompt, automatically**. - **62.1% cost saved vs always-premium** — from the white paper's live routing prototype on real models (paper §9; that's the paper's measurement, not this repo's — `forge cost - --stages` reports only *your* measured stages). +--stages` reports only _your_ measured stages). - **Conflict-free team memory** — merging two 500-claim ledger replicas takes **158 ms**; the merge is a property-tested join-semilattice, so teammate ledgers converge in any order over plain git. @@ -121,12 +121,12 @@ an assumption until measured*. Install — pick one row (the recommended paths need no token and no clone): -| You use… | Run this | -| --- | --- | -| **Claude Code / Codex** *(recommended — full plugin, ambient guards)* | `/plugin marketplace add CodeWithJuber/forgekit` then `/plugin install forgekit` | -| **Any tool, from the CLI** | `npm install -g @codewithjuber/forgekit` | -| **No registry** | `npm install -g github:CodeWithJuber/forgekit` | -| **Contributors / local dev** | `git clone https://github.com/CodeWithJuber/forgekit.git && cd forgekit && npm link` — or `bash install.sh` for the symlink setup | +| You use… | Run this | +| --------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | +| **Claude Code / Codex** _(recommended — full plugin, ambient guards)_ | `/plugin marketplace add CodeWithJuber/forgekit` then `/plugin install forgekit` | +| **Any tool, from the CLI** | `npm install -g @codewithjuber/forgekit` | +| **No registry** | `npm install -g github:CodeWithJuber/forgekit` | +| **Contributors / local dev** | `git clone https://github.com/CodeWithJuber/forgekit.git && cd forgekit && npm link` — or `bash install.sh` for the symlink setup | Then, in your project: @@ -156,42 +156,44 @@ Advisory by default. Set `FORGE_ENFORCE=1` to turn the substrate into a hard blo strongest signals (vacuous prompt, un-assemblable required context, blast radius over the default 25-file threshold). -| Group | Command | Does | -| --- | --- | --- | -| **Config layer** | `forge init` | emit every tool's native config from one source | -| | `forge sync` | recompile canonical source → each tool's native files (idempotent) | -| | `forge doctor` | pass/fail health check: tools, guards, MCP, drift | -| | `forge docs` | docs↔code drift — `check` reconciles commands/env/MCP/CHANGELOG; `sync` sweeps the diff for stale doc mentions | -| | `forge config` | provider setup — show / switch / add providers, set the default model | -| | `forge harden` | wire gitleaks pre-commit + sandbox settings | -| | `forge catalog` | Start-Here index of every tool / crew / guard | -| | `forge brand` | print the brand token map | -| **Memory & team** | `forge ledger` | proof-carrying memory — stats / verify / show / blame / query / ratify / retract / merge / import | -| | `forge recall` | cross-session personal memory — list / add / consolidate | -| | `forge remember` | durable, repo-committable fact | -| | `forge brain` | portable project-memory index | -| | `forge cortex` | self-correcting lessons — `status` / `why` | -| | `forge reuse` | proof-carrying code cache — query / mint / stats | -| | `forge handoff` | bounded session snapshot (`.forge/state.md`) — rewritten each handoff, re-injected every session start | -| | `forge decide` | append-only decision log (`.forge/decisions.md`, D-#### ADR-lite) — future sessions read it instead of re-deciding | -| **Substrate (pre-action)** | `forge substrate` | the full pre-action gate in one pass | -| | `forge preflight` | assumption / info-gap check | -| | `forge route` | cheapest capable model tier (`route gateway` emits LiteLLM config) | -| | `forge impact` | predict blast radius for a symbol or file | -| | `forge scope` | cluster + surface coupled files | -| | `forge imagine` | consequence sim + minimal dry-run suite (`--run` executes it sandboxed) | -| | `forge context` | budgeted context assembly + completeness gate | -| | `forge atlas` | build / query / has (hallucinated-symbol check) the code graph | -| | `forge anchor` | goal-drift check (advisory) — `set`/`show`/`clear` persists the goal across sessions | -| | `forge diagnose` | doom-loop: same failure 3× → diagnosis + escalation | -| | `forge lean` | scope-minimality footprint (advisory) | -| | `forge cost` | real per-day spend · measured stage factors (`--stages`) | -| **Verification & safety** | `forge verify` | independent gate — tests + hallucinated-symbol flag + provenance | -| | `forge scan` | skill-gate: vet a SKILL.md / .mcp.json for injection / RCE / exfil | -| | `forge spec` | spec-as-contract drift — init / lock / check | -| **UI / design** | `forge taste` | pick one visual direction → DESIGN.md | -| | `forge uicheck` | contrast · fingerprint · design · visual (WCAG · slop+conformance · Playwright) | -| **Observability** | `forge dash` | localhost-only read-only dashboard over ledger, metrics, blast radius (default port 4242) | +| Group | Command | Does | +| -------------------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------ | +| **Config layer** | `forge init` | emit every tool's native config from one source | +| | `forge sync` | recompile canonical source → each tool's native files (idempotent) | +| | `forge doctor` | pass/fail health check: tools, guards, MCP, drift, update | +| | `forge update` | self-update — `--check` reports if a newer version exists, bare applies it | +| | `forge docs` | docs↔code drift — `check` reconciles commands/env/MCP/CHANGELOG; `sync` sweeps the diff for stale doc mentions | +| | `forge config` | provider setup — show / switch / add providers, set the default model | +| | `forge harden` | wire gitleaks pre-commit + sandbox settings | +| | `forge catalog` | Start-Here index of every tool / crew / guard | +| | `forge brand` | print the brand token map | +| **Memory & team** | `forge ledger` | proof-carrying memory — stats / verify / show / blame / query / ratify / retract / merge / import | +| | `forge recall` | cross-session personal memory — list / add / consolidate | +| | `forge remember` | durable, repo-committable fact | +| | `forge brain` | portable project-memory index | +| | `forge cortex` | self-correcting lessons — `status` / `why` | +| | `forge reuse` | proof-carrying code cache — query / mint / stats | +| | `forge handoff` | bounded session snapshot (`.forge/state.md`) — rewritten each handoff, re-injected every session start | +| | `forge decide` | append-only decision log (`.forge/decisions.md`, D-#### ADR-lite) — future sessions read it instead of re-deciding | +| **Substrate (pre-action)** | `forge substrate` | the full pre-action gate in one pass | +| | `forge preflight` | assumption / info-gap check | +| | `forge route` | cheapest capable model tier (`route gateway` emits LiteLLM config) | +| | `forge impact` | predict blast radius for a symbol or file | +| | `forge scope` | cluster + surface coupled files | +| | `forge imagine` | consequence sim + minimal dry-run suite (`--run` executes it sandboxed) | +| | `forge context` | budgeted context assembly + completeness gate | +| | `forge atlas` | build / query / has (hallucinated-symbol check) the code graph | +| | `forge stack` | detect this repo's real stack (languages, frameworks, test commands) from its manifests | +| | `forge anchor` | goal-drift check (advisory) — `set`/`show`/`clear` persists the goal across sessions | +| | `forge diagnose` | doom-loop: same failure 3× → diagnosis + escalation | +| | `forge lean` | scope-minimality footprint (advisory) | +| | `forge cost` | real per-day spend · measured stage factors (`--stages`) | +| **Verification & safety** | `forge verify` | independent gate — tests + hallucinated-symbol flag + provenance | +| | `forge scan` | skill-gate: vet a SKILL.md / .mcp.json for injection / RCE / exfil | +| | `forge spec` | spec-as-contract drift — init / lock / check | +| **UI / design** | `forge taste` | pick one visual direction → DESIGN.md | +| | `forge uicheck` | contrast · fingerprint · design · visual (WCAG · slop+conformance · Playwright) | +| **Observability** | `forge dash` | localhost-only read-only dashboard over ledger, metrics, blast radius (default port 4242) | **→ Every command with a worked example and real output: [`docs/GUIDE.md`](docs/GUIDE.md).** @@ -215,17 +217,17 @@ outcome, and per-author trust. No server, no sync service — it's just files in ## How it compares Structural differences only — each row is checkable against the named source, and the full -tables (including what each adjacent tool does *better*) are in +tables (including what each adjacent tool does _better_) are in [`reports/benchmarks.md` → Uniqueness](reports/benchmarks.md#uniqueness--structural-contrasts-with-adjacent-tools): -| Property | Forge | Note stores / gateways / RAG | -| --- | --- | --- | -| Memory confidence moved **only by independent oracles** (tests, CI, human) | yes — closed `ORACLES` table; unverifiable evidence rejected (`src/ledger.js`) | note stores keep notes as written | -| Unreviewed knowledge decays toward *uncertainty*, not deletion | yes — time-decayed Beta posterior; dormant claims kept for audit | notes persist unchanged until deleted | -| Conflict-free team merge over plain git | yes — join-semilattice, property-tested | per-machine SQLite or a hosted store | -| Routing decision visible and diffable **before** dispatch | yes — deterministic rubric over `src/model_tiers.json` | gateways decide inside the proxy at request time | -| Cached code served **only with verification evidence**, revalidated against the current code graph | yes — `SERVE_FLOOR`, `revalidate()` in `src/reuse.js` | plain RAG serves on similarity alone | -| **What they do better** | — | hosted sync, web UIs, embedding search that catches paraphrase; gateways actually *move traffic* (failover, quotas). Forge is a transparency layer, not a replacement | +| Property | Forge | Note stores / gateways / RAG | +| -------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Memory confidence moved **only by independent oracles** (tests, CI, human) | yes — closed `ORACLES` table; unverifiable evidence rejected (`src/ledger.js`) | note stores keep notes as written | +| Unreviewed knowledge decays toward _uncertainty_, not deletion | yes — time-decayed Beta posterior; dormant claims kept for audit | notes persist unchanged until deleted | +| Conflict-free team merge over plain git | yes — join-semilattice, property-tested | per-machine SQLite or a hosted store | +| Routing decision visible and diffable **before** dispatch | yes — deterministic rubric over `src/model_tiers.json` | gateways decide inside the proxy at request time | +| Cached code served **only with verification evidence**, revalidated against the current code graph | yes — `SERVE_FLOOR`, `revalidate()` in `src/reuse.js` | plain RAG serves on similarity alone | +| **What they do better** | — | hosted sync, web UIs, embedding search that catches paraphrase; gateways actually _move traffic_ (failover, quotas). Forge is a transparency layer, not a replacement | ## Honest limits @@ -236,9 +238,9 @@ graph — the impact numbers above are n = 6 hand-labeled cases on one JavaScrip substrate's rubrics are heuristic; the MinHash near-match is weak on very short specs (an optional embeddings backend — `FORGE_EMBED` — lifts this; MinHash stays the zero-dependency default); and `forge cost --stages` reports **measured stages only** — a stage with no -events says "no data", never a default. What's *asserted* is safe to gate on (repo +events says "no data", never a default. What's _asserted_ is safe to gate on (repo grounding, graph traversal, routing arithmetic, test commands); everything else is -*advisory*. **Tests and human corrections always win.** Full list: +_advisory_. **Tests and human corrections always win.** Full list: [docs/GUIDE.md → Honest limits](docs/GUIDE.md#honest-limits). ## Why a cognitive substrate? The white paper @@ -275,15 +277,15 @@ its root — it does not get the landing page. ## Documentation -| Doc | What's in it | -| --- | --- | -| [`ONBOARDING.md`](ONBOARDING.md) | Five minutes to productive + the design principles. | -| [`docs/GUIDE.md`](docs/GUIDE.md) | Every command, worked examples, all cases, how to extend. | -| [`reports/benchmarks.md`](reports/benchmarks.md) | Every measured number, methodology, and `npm run bench` to reproduce. | -| [`docs/cognitive-substrate/`](docs/cognitive-substrate/) | The white paper, evidence map, ecosystem map, and prototype sources. | -| [`ARCHITECTURE.md`](ARCHITECTURE.md) | The four-layer compiler and the cross-tool emit matrix. | -| [`docs/RELEASING.md`](docs/RELEASING.md) | How releases are cut (tag → npm + GitHub Release). | -| [`CHANGELOG.md`](CHANGELOG.md) | What changed, per release. | +| Doc | What's in it | +| -------------------------------------------------------- | --------------------------------------------------------------------- | +| [`ONBOARDING.md`](ONBOARDING.md) | Five minutes to productive + the design principles. | +| [`docs/GUIDE.md`](docs/GUIDE.md) | Every command, worked examples, all cases, how to extend. | +| [`reports/benchmarks.md`](reports/benchmarks.md) | Every measured number, methodology, and `npm run bench` to reproduce. | +| [`docs/cognitive-substrate/`](docs/cognitive-substrate/) | The white paper, evidence map, ecosystem map, and prototype sources. | +| [`ARCHITECTURE.md`](ARCHITECTURE.md) | The four-layer compiler and the cross-tool emit matrix. | +| [`docs/RELEASING.md`](docs/RELEASING.md) | How releases are cut (tag → npm + GitHub Release). | +| [`CHANGELOG.md`](CHANGELOG.md) | What changed, per release. | ## Community & support diff --git a/docs/GUIDE.md b/docs/GUIDE.md index 544d7f6..66f5517 100644 --- a/docs/GUIDE.md +++ b/docs/GUIDE.md @@ -1,9 +1,9 @@ # Forge — the complete guide -**One brain for every AI coding agent.** A language model is *stateless* — one context +**One brain for every AI coding agent.** A language model is _stateless_ — one context window, wiped every call. It can't remember what your team learned, can't foresee what an edit breaks, and has no enforced guardrails. Forge is the **cognitive substrate** — -the layer that runs *before* the model edits code — that supplies exactly those three +the layer that runs _before_ the model edits code — that supplies exactly those three things, and it ships them as native config to nine AI coding tools at once. The brain is the point; one config for every tool is how the brain gets delivered. @@ -25,15 +25,15 @@ recipes, and how to extend each piece. If you just want to get going, the Every command is real and wired. Grouped by what it does: -| Group | Commands | -| --- | --- | -| **Config / cross-tool sync** | `forge init` · `forge sync` · `forge doctor` · `forge docs` · `forge config` · `forge harden` · `forge catalog` · `forge brand` | -| **Memory & ledger (PCM)** | `forge ledger` · `forge recall` · `forge remember` · `forge brain` · `forge cortex` · `forge reuse` · `forge handoff` · `forge decide` | -| **Code graph & retrieval** | `forge atlas` · `forge context` | -| **Substrate / pre-action** | `forge substrate` · `forge preflight` · `forge route` · `forge impact` · `forge scope` · `forge imagine` · `forge anchor` · `forge diagnose` · `forge lean` · `forge cost` | -| **Verification & safety** | `forge verify` · `forge scan` · `forge spec` | -| **UI / design** | `forge taste` · `forge uicheck` | -| **Dashboard** | `forge dash` | +| Group | Commands | +| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Config / cross-tool sync** | `forge init` · `forge sync` · `forge doctor` · `forge update` · `forge docs` · `forge config` · `forge harden` · `forge catalog` · `forge brand` | +| **Memory & ledger (PCM)** | `forge ledger` · `forge recall` · `forge remember` · `forge brain` · `forge cortex` · `forge reuse` · `forge handoff` · `forge decide` | +| **Code graph & retrieval** | `forge atlas` · `forge stack` · `forge context` | +| **Substrate / pre-action** | `forge substrate` · `forge preflight` · `forge route` · `forge impact` · `forge scope` · `forge imagine` · `forge anchor` · `forge diagnose` · `forge lean` · `forge cost` | +| **Verification & safety** | `forge verify` · `forge scan` · `forge spec` | +| **UI / design** | `forge taste` · `forge uicheck` | +| **Dashboard** | `forge dash` | Storage in one line: the code graph is `.forge/atlas.json` (plain JSON, not SQLite); the ledger is content-addressed claims under `.forge/ledger/` (git-committable, union-merge). @@ -50,11 +50,11 @@ prompt can fix: it can't **remember** across sessions, can't **learn** from outc can't **imagine** what an edit breaks, can't reliably **check itself**, and can't see **what already exists** beyond its window. -Forge supplies those faculties from the *outside*, in three layers: +Forge supplies those faculties from the _outside_, in three layers: - **tools** — know-how the model loads on demand (`lean`, `atlas`, `recall`…). - **crew** — isolated sub-agents for focused work (`scout`, `verifier`…). -- **guards** — deterministic shell hooks that *enforce* what prose can't (the only +- **guards** — deterministic shell hooks that _enforce_ what prose can't (the only layer the model can't drift from). Two subsystems sit on top: **Cortex** (self-correcting memory) and the **cognitive @@ -132,7 +132,7 @@ Forge substrate — pre-action check ``` It found `login.js` and `session.js` — the two files that import `verifyToken` but you -never named. That's the "forgot the coupled file" bug, caught *before* the edit. +never named. That's the "forgot the coupled file" bug, caught _before_ the edit. **A vague task — it tells you to ask first:** @@ -242,7 +242,7 @@ Forge impact — blast radius ### `forge scope ` — can this be split into sessions? Groups the files you name into independent clusters and surfaces coupled files you -*didn't* name — so you split cleanly instead of overloading one session. +_didn't_ name — so you split cleanly instead of overloading one session. ```console $ forge scope src/auth.js src/report.js @@ -258,7 +258,7 @@ Forge scope — task decomposition ### `forge anchor ""` — are your changes still on the stated goal? Goal-anchoring (the paper's M4): it re-reads your original objective against the files -you've *actually* changed (`git diff HEAD` + untracked, minus forge's own generated +you've _actually_ changed (`git diff HEAD` + untracked, minus forge's own generated config), and flags work that wandered off-goal. Quiet on a clean tree — it only speaks once there's a diff to compare, so it's a mid-session "am I still on track?" check. @@ -276,7 +276,7 @@ Forge anchor — goal-drift check doesn't — so it's surfaced as drift to confirm or undo. Coarse and advisory by design (path/keyword match, not semantic). `forge substrate` folds this in automatically. The result also carries `driftScore` (the off-goal fraction per checkpoint) — the graded -signal the `cusum` change-point detector accumulates to catch *sustained* small drift. +signal the `cusum` change-point detector accumulates to catch _sustained_ small drift. **The goal persists.** `forge anchor set ""` stores it in `.forge/goal.md`; every new session re-injects it at SessionStart, a bare `forge anchor` checks against it, and @@ -297,7 +297,7 @@ forge handoff "built the export endpoint" \ ``` Every new session re-injects the snapshot at SessionStart, so the next session — any -machine, any day — *resumes* instead of re-assuming. Refuses secrets, like every forge +machine, any day — _resumes_ instead of re-assuming. Refuses secrets, like every forge store. Updating it also satisfies the completion gate (below): the weakest way to stop cleanly is to tell the future what happened. @@ -307,14 +307,14 @@ Sessions re-decide (or silently contradict) what a past session already settled, nothing durable recorded the choice. `forge decide` appends one ADR-lite line to `.forge/decisions.md` (`- **D-0007** (2026-07-10): …`) and mints a machine-readable `decision` claim in the ledger. Bare `forge decide` lists the last ten. Append-only by -design: a decision that stops being true gets a *new* entry, never an edit — the log is +design: a decision that stops being true gets a _new_ entry, never an edit — the log is history, and `forge docs sync` exempts it for exactly that reason. ### `forge docs sync` — which prose did this diff make stale? `forge docs check` reconciles the registries; `docs sync` answers the diff-shaped question. It extracts the changed identifiers (paths, definitions, called symbols — -from added *and removed* lines, so deletions count), scans every doc artifact (atlas doc +from added _and removed_ lines, so deletions count), scans every doc artifact (atlas doc nodes + README/GUIDE/ARCHITECTURE), and gives each one a verdict: ```console @@ -373,6 +373,41 @@ $ forge atlas has doesNotExistSymbol `query` costs a few hundred tokens instead of reading five files; `has` is a cheap "is this symbol real?" check before an agent calls it. +The atlas parses **JS/TS, Python, Go, Rust, Java, Ruby, C#, PHP, Kotlin, Swift, and +C/C++** — adding a language is a regex grammar in `src/atlas.js RULES`, and everything +downstream (the walk, the completion gate's code-class, the docs sweep) picks it up from +that one table. + +### `forge stack` — what is THIS repo actually built with? + +The atlas lists the languages forge can _parse_; `forge stack` answers the other +question — the repo's _real_ stack — by reading its dependency manifests (not a hardcoded +menu). It reports languages, frameworks, package managers, and the actual test +command(s), which also feed the substrate's verification checklist: + +```console +$ forge stack + languages: JavaScript/TypeScript, TypeScript + frameworks: Next.js, React + pkg mgrs: pnpm + test: npx vitest + evidence: package.json +``` + +Detection reads `package.json` (deps → frameworks, lockfile → package manager), +`pyproject.toml`/`requirements.txt`, `go.mod`, `Cargo.toml`, `Gemfile`, `composer.json`, +`pom.xml`/`build.gradle`, and `*.csproj`. Widening it is adding a data row, not code. +`--json` for tooling. Nothing detected → an honest "no known stack". + +### `forge update` — self-update + +No more manual "am I on the latest?". `forge update --check` reports whether a newer +version is available (git checkout: commits behind upstream, from a cached hourly fetch); +bare `forge update` applies it (`git pull --ff-only` for a checkout — symlink/npm-link +installs go live immediately; npm-global installs get the `npm i -g` command). `forge +doctor` also surfaces a one-line notice when behind (cached, never nags; silence it with +`FORGE_NO_UPDATE_CHECK=1`). Fail-open: offline or a non-git install never errors. + ### `forge recall add | list | consolidate` — cross-session memory Durable facts, one per file, injected at the start of the next session by the @@ -387,7 +422,7 @@ $ forge recall list ### `forge cortex [status | why ]` — self-correcting memory -Status of the lessons Cortex has learned from *this repo's* correction history. +Status of the lessons Cortex has learned from _this repo's_ correction history. ```console $ forge cortex @@ -505,7 +540,7 @@ crash, timeout, garbage output — silently degrades to the MinHash path Derives the required-knowledge set for an edit (the target's definitions, hop-1 dependents, sibling tests, trusted lessons), covers it under a token budget with a -compression ladder (full → head → pointer), and computes what's *missing* as a set +compression ladder (full → head → pointer), and computes what's _missing_ as a set difference — not a feeling. ```console @@ -614,7 +649,7 @@ visual loop: renders the page headless at two viewports (1280×800, 390×844), fingerprints the **computed** styles of every visible element — what the cascade, `var()` resolution, and runtime theming actually produced — and runs the exact same design gate as `design` (exit 1 on fail). Screenshots land in `.forge/ui/` for human -review. Playwright is an *optional tier* (ADR-0005): `package.json` stays +review. Playwright is an _optional tier_ (ADR-0005): `package.json` stays dependency-free; without a browser runtime the command prints a "skipped (no browser runtime)" note and exits 0 — enable it with `npm i -D playwright-core` or point `FORGE_PLAYWRIGHT` at an existing install (e.g. @@ -676,22 +711,22 @@ Plain `forge cost` remains the per-day spend view via `ccusage`. ### The rest -| Command | Answers | -| --- | --- | -| `forge init` | Emit every tool's native config from one source. | -| `forge sync` | Recompile `source/` → each tool's files (idempotent). | -| `forge doctor` | Health check: layers, install, drift, cortex. | -| `forge docs check` | Docs↔code drift: commands, env vars, MCP tools, CHANGELOG reconciled against the code (CI-gated on the forge repo itself). | -| `forge docs sync` | Diff-driven stale-docs sweep: UPDATED / STALE (file:line hits) / VERIFIED-UNAFFECTED per artifact (see the full section above). | -| `forge catalog` | Start-Here index of every tool / crew / guard. | -| `forge brain` / `forge remember` | Portable project memory inlined into `AGENTS.md`. | -| `forge cost` | Real per-day spend (via `ccusage`) + the cost ceiling; `--stages` for the measured report. | -| `forge scan ` | Vet a skill/MCP (SKILL.md/.mcp.json) for injection/RCE/exfil before install. | -| `forge harden` | Wire gitleaks pre-commit + sandbox settings. | -| `forge spec [init\|lock\|check]` | Spec-as-contract drift check. | -| `forge brand` | Print the active brand token map. | -| `forge lean ""` | Scope-minimality footprint for a task — advisory (the Lean Path as a command). | -| `forge taste [