Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"keywords": ["config", "cross-tool", "agents-md", "ai-coding", "claude-code", "cognitive-substrate"],
"skills": "./global/tools",
"agents": [
"./global/crew/doc-sync.md",
"./global/crew/frontend-verifier.md",
"./global/crew/independent-reviewer.md",
"./global/crew/scout.md",
Expand Down
56 changes: 56 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,62 @@ compression ladder, and reports the *computed missing set* — the inputs it cou
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`.

## 5. The end-to-end reliability layer

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`,
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:
`completion-gate.sh` runs synchronously (the lesson-mining `cortex.sh stop` stays
detached and can never block). The changed set is **session-scoped**: files from commits
whose committer time is ≥ session start, plus working-tree changes minus the dirt
snapshotted at SessionStart — so pre-existing edits, branch switches, and `git pull`s
are never pinned on the agent (adversarial review demonstrated all three false-block
classes). Paths are classified by ONE total function derived from the atlas registries
(`CODE_EXTS`/`DOC_EXTS`/config rules) plus the shared test-file predicate, parsed from
`-z` NUL-separated git output (C-quoted unicode paths classify correctly). Code moved
with no doc/state artifact → block once with the repair checklist as the reason; every
other row allows, every internal error allows (fail-open), the once-per-session marker
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).

**Session anchoring (SessionStart, `src/session.js`).** Records `HEAD` once per session
(`.forge/sessions/<sid>.base`; resume keeps it), prunes week-old session artifacts, and
injects: learned lessons, the anchored goal, the handoff snapshot, recent commits, and
uncommitted changes — a fresh session orients on evidence, not priors.

**The state/decision stores (`src/handoff.js`, `src/decide.js`).** `state.md` is a
bounded REWRITE (snapshot semantics — loader cost stays O(bound) forever);
`decisions.md` is append-only ADR-lite with a machine-readable `decision` ledger twin
(log semantics — supersede, never edit). Both refuse secrets at write.

**The diff-driven docs sweep (`src/docs_sync.js`).** `docs check` reconciles registries;
`docs sync` answers the diff-shaped question: changed identifiers (paths + definitions +
called symbols, from added AND removed lines, via the same `RULES` grammars the atlas
parses) swept against every doc artifact → UPDATED / STALE (file:line hits) /
VERIFIED-UNAFFECTED with the reason recorded. Pure reporter; the gate provides the teeth.

**Intent cards (`src/intent.js`).** Prompt → intent by the same exemplar k-NN math as
model routing — a labeled bank (English + Hinglish rows) under overlap similarity with a
confidence gate, NOT a keyword DFA. Note `intentGrams` ≠ `contentGrams`: route.js stops
generic task verbs (`fix`/`add`/`build`) as complexity noise, but they are exactly the
intent signal — same math, different stop-set data.

**The evidence trail (preflight).** Once a goal is anchored, every prompt appends its
graded `driftScore` to the session log; `cusum` (until now test-only math) accumulates
the series and a sustained alarm rides the gate's block reason. Proceeding under
assumptions appends a record the advisory names and the next handoff surfaces — a guess
can never silently become a fact.

**Deliberately not wired:** `checkpointCadence` (optimal-stopping check spacing) still
has no runtime step-loop to consume it — wiring it would mean inventing one. It stays
library math with tests until a real consumer exists.

## Component map — the reuse ledger (30 components)

**Reuse (rename + swap brand token, logic unchanged):**
Expand Down
56 changes: 56 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,62 @@ to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### 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`,
`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 switch `FORGE_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-readable `decision` ledger twin; bare `forge decide`
lists 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, `--strict` for 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 (`.github` is now walked),
manifests, and Dockerfiles become `config:` nodes with `references` edges to the code
paths they name, so `forge impact` lists the configs a change can break (lockfiles
excluded as generated churn).
- **End-to-end skills + agent** — `handoff`, `sync-docs`, and `catchup` skills, a
`doc-sync` crew agent that repairs stale docs in its own context, and an
`end-to-end` rules section (Definition of Done, no silent assumptions, decision log)
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`.
- **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); `-z` NUL parsing keeps unicode/space/arrow paths
correctly classified; an unwritable block-once marker stands down instead of blocking
every turn; a missing `session_id` disables gating instead of sharing `default` state;
a >7-day resume re-anchors instead of losing its baseline to the prune; `readState` no
longer truncates snapshots whose rows contain `<!--`; `forge decide` takes 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 `--base` instead of mislabeling the report.

## [0.9.0] - 2026-07-10

### Added
Expand Down
4 changes: 3 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
@AGENTS.md

# forgekit — contributor instructions

## Stack
Expand All @@ -7,7 +9,7 @@

## Commands
- Install: `npm ci`
- Test: `npm test` (node:test, 471+ tests)
- Test: `npm test` (node:test, 600+ tests)
- Lint + format: `npx biome check` (or `npm run check`)
- Typecheck: `npm run typecheck`
- Build pages: `npm run pages:build`
Expand Down
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,11 @@ The day-to-day value first — the substrate gives a frozen model what it can't
- **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
the way `CLAUDE.md` prose does not.
- **Work that finishes end to end.** A completion gate blocks "done" once per session when
code moved but no doc or state artifact followed — with the repair checklist as the answer
(`forge docs sync` sweeps the diff for stale prose, `forge handoff` writes the bounded
session snapshot the next session resumes from, `forge decide` records choices so no
session re-decides them).
- **One config for 9 tools.** Author your rules once; Forge emits each tool's native config,
plus MCP for Roo and VS Code. Zero runtime dependencies — one Node CLI, plain files in git,
no server.
Expand Down Expand Up @@ -156,7 +161,7 @@ default 25-file threshold).
| **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 commands, env vars, MCP tools, CHANGELOG vs reality |
| | `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 |
Expand All @@ -167,6 +172,8 @@ default 25-file threshold).
| | `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) |
Expand Down
Loading
Loading