Skip to content

feat: formal-synthesis paper features (v2) — know, precommit, verify --deep, radar, ledger sync, deja, dash v2, report + Mintlify docs#68

Merged
CodeWithJuber merged 12 commits into
masterfrom
claude/research-paper-implementation-va5g2u
Jul 17, 2026
Merged

feat: formal-synthesis paper features (v2) — know, precommit, verify --deep, radar, ledger sync, deja, dash v2, report + Mintlify docs#68
CodeWithJuber merged 12 commits into
masterfrom
claude/research-paper-implementation-va5g2u

Conversation

@CodeWithJuber

Copy link
Copy Markdown
Owner

What & why

The first two research-paper commits (crosswalk fix + fmt.js) landed in #67 and released as v0.19.0. This PR delivers the remaining 9 features that close the verified gaps between research/formal-synthesis/ ("A Formal Theory of the Cognitive Substrate for Coding Agents") and src/, plus the two priority tracks (UI/UX and cross-session memory), plus a user-facing Mintlify docs site.

Features (one conventional commit each):

  • feat(know)A7 knowledge-router: total route(fact) → storage home (paper Theorem T6), exemplar k-NN, ledger-fact fallback so it is total by construction. forge know "<fact>".
  • feat(precommit)commit-level gate rung (the paper's missing middle of turn ⊂ commit ⊂ PR): staged F1 classifier + secret scan, wired via harden. FORGE_COMMIT_GATE=warn|block|0.
  • feat(update)--to <version> pin/downgrade (git tag checkout or npm instruction).
  • feat(verify)multi-lens consensus (verify --deep): noisy-OR + cross-family gate (the scoreMistake shape), Theorem-D residual reporting, optional N-sample LLM reviewer (never solo).
  • feat(radar)dependency-currency rings (paper invariant I4): adopt/trial/assess/hold computed from registry evidence (staleness half-life, major-lag, advisories, deprecation), never hardcoded lists; missing evidence never upgrades a dep; recorded as I4 ledger claims; cache-only pre-edit advisory. FORGE_RADAR=0, FORGE_RADAR_TTL_H.
  • feat(ledger)sync: CRDT push/pull over a git ref or shared dir, --personal recall portability. FORGE_SYNC_DIR.
  • feat(deja)anti-repetition: session-summary claims at Stop + similar-task lookup, so first-try successes leave durable, cross-machine memory. forge deja "<task>", FORGE_DEJA=0.
  • feat(dash)dash v2: live refresh, history trends, radar/memory/gate/timeline panels (append-only write discipline preserved).
  • feat(report) — self-contained HTML report emit.
  • docs(mintlify) — user-facing docs site (mintlify/docs.json + 18 MDX pages: intro, quickstart, installation, 6 concepts, CLI reference, 3 guides) + advisory broken-link CI. Deploys via the Mintlify GitHub App (connect the repo once in the dashboard).

A final fix(review) commit resolves 3 correctness findings from an integrated-branch code review: verify --deep's secret lens now uses redaction-grade precision (no false-block on x = process.env.KEY), the dash radar panel reads radar's real installed/reasons fields, and radar records deprecated=unknown rather than asserting false on unverified metadata.

Checklist

  • npm test passes — 851 pass / 0 fail / 2 pre-existing skips
  • npm run check passes (Biome — 6 pre-existing warnings unchanged, 0 errors)
  • New public functions have a test (one *.test.js per new module)
  • Conventional commit message (feat:/fix:/docs: …)
  • CHANGELOG.md updated under ## [Unreleased]
  • No new runtime dependency (zero-dep rule intact; Mintlify is a docs platform, not a dep)
  • Substrate/docs updated — new commands in commands.js + README + docs/GUIDE.md; docs check green (incl. the crosswalk reconciler)

Risk & rollback

  • Risk level: medium — new commands + hook advisories are additive and all fail-open (exit 0); network features (radar) are cache-first with offline degradation and injectable fetch; ledger sync is monotone by CRDT semilattice.
  • Rollback plan: revert the merge; every feature has a kill switch (FORGE_COMMIT_GATE=0, FORGE_RADAR=0, FORGE_DEJA=0); no ledger schema change (no new ORACLES/KINDS rows) so cross-version merges stay clean.

Extra checks (tick if applicable)

  • npm run typecheck passes (JSDoc/tsc)
  • Input validated at boundaries; errors handled — fail-open by design, injectable runners for all network/LLM I/O
  • Authorization/ownership checked (n/a — local dev tooling, dash binds 127.0.0.1 only)
  • Logs contain no secrets/PII — summaries/claims secret-redacted; secret-shaped values refused at store
  • If AI-assisted: understood, package APIs verified, tests included

🤖 Generated with Claude Code

https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU


Generated by Claude Code

claude added 12 commits July 17, 2026 11:02
…omes

Implements the formal-synthesis paper's A7 step as code (Theorem T6
totality): src/knowledge_router.js routes any fact to one of seven
storage homes (claude-md / rule / skill / state / decision /
ledger-fact / recall) with the same exemplar k-NN math as intent.js
(labeled HOME_EXEMPLARS bank + setOverlap + confidence gate, reusing
intentGrams). Below the gate the fact falls back to `ledger-fact` with
provenance:"fallback" — never "none": the ledger's decay-toward-unsure
semantics make an unsure placement safe.

storeFact dispatches to the EXISTING stores verbatim: appendDecision
(decide.js), shadowFact into the repo ledger (ledger_bridge.js), and
recall add + personal-ledger shadow (the exact `forge recall add` CLI
path). Curated-file homes (claude-md/rule/skill/state) are advise-only
— routing returns advice naming the right command instead of a blind
write. Secrets are refused before any dispatch (hasSecret), and
storeFact never throws.

Surfaces:
- CLI `forge know "<fact>" [--dry-run|--json]` (Memory group).
- Cortex hook: distilled lessons (ENABLE_CORTEX_DISTILL=1) that route
  to decision/ledger-fact at confidence >=0.5 also shadow there,
  try/catch fail-open inside enrichCreated.
- Docs: README + GUIDE command mentions, GUIDE worked section,
  CHANGELOG [Unreleased] bullet. No new env vars, no new deps, no new
  ledger KINDS.

Tests (test/knowledge_router.test.js, 12): totality fuzz (100
arbitrary strings all land in a real HOMES member), per-family routing
from unseen phrasings, dry-run never writes, advise-only homes never
write, secret refusal, decision/ledger/recall auto-writes verified
against their stores, CLI --dry-run --json smoke.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
… wired via harden

Adds the middle rung of the gate lattice (turn ⊂ commit ⊂ PR):

- src/commit_gate.js — stagedFiles (git diff --cached -z), classifyPath reuse
  from gate.js (code staged with no doc/state artifact → completeness finding),
  and secrets.js detection over staged ADDED lines only as the gitleaks
  fallback (confirmed at redaction-grade precision so ordinary code like
  `token = process.env.TOKEN` is never a false block).
- Modes via FORGE_COMMIT_GATE: warn (default, print + allow), block (refuse),
  0/off (kill switch); a detected secret blocks in every mode (mizan — a
  credential in history is not repairable). Fail-open like stopGate.
- forge precommit CLI command (+ --json), registered in commands.js (Quality).
- harden.js: pre-commit hook is now gitleaks-if-present + `node <root>/src/cli.js
  precommit`, fail-open when node/package are missing, and no-clobber — a
  user-authored hook is kept and ours lands beside it as pre-commit.<cli>.
- Docs in the same change: README/GUIDE command rows, GUIDE env table row for
  FORGE_COMMIT_GATE, CHANGELOG [Unreleased] bullet.
- Tests: test/commit_gate.test.js (warn/pass/block/secret/removed-lines/kill-
  switch/fail-open/unicode -z/pure-table) + harden hook install/no-clobber.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
New applyUpdateTo in src/update.js: for a git checkout it fetches tags
(best-effort, offline-safe), verifies the release tag exists (accepts
0.17.0 or v0.17.0, and both v-prefixed and bare tag names), then does a
detached checkout at the tag with a note on how to return to latest.
npm/copy installs get the exact 'npm i -g <pkg>@<version>' instruction.
Never throws: missing version, unknown tag, and dirty-tree checkout
failures are honest {ok:false, reason} results.

CLI: 'update --to <version>' wired before --check/bare paths (--json
supported); commands.js row, README table row, GUIDE prose, and a
CHANGELOG [Unreleased] bullet updated in the same change. Eight new
tests in test/update.test.js cover pin/idempotence/bare-tag/miss/
non-git/dirty-tree/arg-validation plus a CLI --json path, all on tmp
git fixtures with no network.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…ional N-sample reviewer)

New src/consensus.js closes GAP 2 (self-consistency / majority-of-N review):
`forge verify --deep` runs a LENSES table of independent checks — tests
(solo-trusted outcome), unknown symbols, unreviewed impact radius (atlas
dependents not in the diff, the gate.js repairReason traversal), docs drift
(gate.js classifyPath F1 signal), secrets in added lines (solo-trusted),
spec-lock drift, and an opt-in reviewer panel — and aggregates them exactly
like lessons.js scoreMistake: noisy-OR P(defect)=1−∏(1−wᵢsᵢ) plus the
cross-family gate (≥2 evidence families or a solo lens), so correlated
structural signals stay advisory while a failing suite or leaked secret
blocks alone. Every run reports the Theorem-D residual ∏(1−cⱼ) over the
lenses that ran (mizan: a PASS states what it still can't see), extends
.forge/provenance.json with per-lens evidence, and appends one
stage:"verify" metrics record.

Reviewer lens: N=3 independent adjudicate() samples, strict-majority vote,
abstains below ⌈n/2⌉ usable replies; gated on llmEnabled (FORGE_LLM=1 or
`--llm`), injectable runner — tests never touch a model or the network.
verify() now also returns the added diff lines so the deep lenses read the
same bytes the base pass parsed. CLI renders the lens table with fmt.js;
README/GUIDE/CHANGELOG updated in the same change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…rding + pre-edit advisory

New zero-dep src/radar.js implements `forge radar` (paper crosswalk GAP 4 = I4
verified currency). It reads this repo's Node manifests, probes the registry via an
injectable fetch (metadata + bulk advisories, 4s timeout, never touches the network in
tests), and classifies each dependency into an adopt/trial/assess/hold ring from a
formula over evidence — staleness (540-day half-life), major-version lag, severity-
weighted advisories, deprecation; atlas import-sites are stakes, not risk. Mizan: every
ring ships the evidence that earned it, and missing evidence never upgrades a dep
(deprecated/critical → hold; <2 verified evidence kinds → assess).

Cached at .forge/radar.json (FORGE_RADAR_TTL_H, default 24h); --offline serves the stale
cache flagged with its age or fails honestly; --refresh re-probes; --json for tooling. A
network scan records I4 evidence into the ledger (one currency:<dep> fact per dependency,
shadowFact supersede semantics keep the latest verification live with history in
tombstones) plus a stage:radar metrics line. The cortex pre-edit hook surfaces a
cache-only advisory (hooks never fetch) when a file imports a hold dependency; kill
switch FORGE_RADAR=0.

Every-surface: commands.js row + Quality group; README + docs/GUIDE command mention;
FORGE_RADAR / FORGE_RADAR_TTL_H documented; CHANGELOG [Unreleased] bullet; one test file
(test/radar.test.js, network fully injected). Gates: node --test, biome, tsc, docs check
all green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…rtability

`forge ledger sync` moves the proof-carrying-memory ledger between machines
without a merge-path argument. The ledger is already a state-based CRDT
(content-addressed claims + hash-deduped append-only logs joined by the
`mergeStates` semilattice); sync is a transport that ships that state and
re-runs the join.

New module src/ledger_sync.js (zero deps, injectable git runner, fail-open):
- Target discovery (syncTarget): --dir > --remote/--ref > the repo's git remote
  > FORGE_SYNC_DIR > an honest "no target". Pure + injectable env/run.
- Dir mode (syncDir): bidirectional mergeDirs with a shared directory — both
  replicas converge to the union.
- Ref mode (syncRef): git plumbing over refs/<cli>/ledger — pull = fetch the ref,
  cat-file the state.json blob, importState; push = canonicalize → hash-object →
  mktree → commit-tree → update-ref → push, skipped when the remote tree already
  equals ours (byte-level idempotence). A non-fast-forward race re-fetches,
  re-imports (monotone), rebuilds on the new parent and retries ≤3 — nothing lost.
- --personal targets the per-user ledger the recall store shadows into, so recall
  facts become portable across machines.
- Offline, a missing remote, or a corrupt remote blob all degrade to an honest
  reason (never throws). Tests drive real git with local bare remotes — no network.

Every surface, one commit: commands.js ledger row (+ sync); cli.js `sync` branch
+ usage string; README + docs/GUIDE prose (incl. FORGE_SYNC_DIR env contract);
CHANGELOG [Unreleased]; test/ledger_sync.test.js (target discovery, dir/ref
convergence to byte-identical state, idempotence, race retry, honesty,
--personal portability). Gates green: node --test, biome, tsc, docs check.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…advisory

Anti-repetition memory closing W2d. The user's "why do I keep re-solving the
same task across sessions" root cause: Cortex only mints on CORRECTION episodes,
so a clean first-try success leaves no durable trace — clearSession discards it
and the next session starts blind.

- src/deja.js: recordSessionSummary mints ONE `summary` claim (existing ledger
  KIND — no protocol change) at session Stop, with a deterministic, secret-
  redacted gist (first prompt via redactSecrets) + files touched. A passing test
  run attaches one `test.run` confirm outcome, so `val` separates solved-and-
  verified from merely-attempted. dejaLookup ranks prior summary/lesson/diagnosis
  claims with the SAME Eq.3 retrieve() as `ledger query` (rel × rec × val).
- src/cortex_hook_main.js: stop mode mints the summary before clearSession
  (fail-safe, kill switch FORGE_DEJA=0); preflight mode emits a one-line
  "déjà vu" advisory when a prompt matches prior solved work (cache-only read).
- CLI `forge deja "<task>"` (+ --json) ranks prior sessions with fmt.js bars.
- commands.js row + GROUPS.Memory; README + docs/GUIDE mention `forge deja`;
  FORGE_DEJA documented; CHANGELOG [Unreleased] bullet; test/deja.test.js.

Because summaries are ordinary ledger claims, `forge ledger merge` (and a future
`forge ledger sync`) carry them between machines — anti-repetition across surfaces.
Zero new runtime deps; no new ORACLES/KINDS rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…line panels

Extend the localhost dashboard (src/dash.js + src/dash.html) into a v2 lens over
the durable .forge/ stores, keeping the dashData/serve split and append-only write
discipline (the only writes remain POST /api/ratify and /api/retract).

New read-only endpoints, each a pure section builder that never throws and degrades
to an empty payload on corrupt/missing stores:
- GET /api/history — metrics.jsonl bucketed by day×stage, 90-day window, per-stage
  daily series for sparklines (historyData).
- GET /api/claims?q=&kind= — memory browser ranked via ledger retrieve (Eq.3
  rel×rec×val) with confidence + freshness, budget 50 (claimsData).
- GET /api/radar — dependency-currency rings read from the .forge/radar.json cache
  only (never fetches); tolerant of shape drift, empty panel when absent (radarData).
- GET /api/timeline — durable mint/tombstone events from the ledger, newest first
  (timelineData) — not the ephemeral session logs.

dash.html gains four panels (Radar rings, Trends sparklines, Memory browser with
live debounced search + kind filter, Session timeline), a ~30-line inline-SVG
sparkline helper, and 5s live polling paused on document.hidden. Self-contained,
no CDN, brand tokens only.

Docs move in the same commit: commands.js summary, README + docs/GUIDE.md dash
descriptions, CHANGELOG [Unreleased]. New tests in test/dash.test.js cover each
lens payload-first plus the serve routes and corrupt-store degradation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
Add `forge report` — the offline twin of `forge dash`. New zero-dep
src/report.js emits ONE self-contained .forge/report.html (no server, no
fetch, no CDN, no JS to read it) that opens offline, mails, or attaches to a
PR.

- renderReport(root) is PURE: reuses dashData(root) (dash.js) for the ledger
  and metrics payload, buckets metrics.jsonl into a 90-day activity sparkline
  via a ~15-line server-side inline SVG helper (no xmlns → zero external
  refs), and reads the .forge/radar.json cache DIRECTLY and defensively —
  report.js never imports radar.js, so absent/corrupt cache simply omits the
  radar section.
- Palette comes from rootTokensCss() (brand.js), so the report's tokens are
  the brand's single source, never a forked copy. All dynamic strings escaped.
- writeReport(root) is the only side-effecting entry point; CLI `forge report`
  writes .forge/report.html (or `--out <path>`).

Every-surface: commands.js row + Config group placement, README + GUIDE
command docs, CHANGELOG [Unreleased] bullet, one test file
(test/report.test.js: self-containment, brand token block, escaping, radar
defensiveness, history bucketing, sparkline). No new env vars, zero new
runtime deps.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
Add a self-contained Mintlify documentation site under mintlify/, additive to
the existing docs/ Markdown (which remains the source of truth). Derived from
README.md, ARCHITECTURE.md, ONBOARDING.md, and src/commands.js.

Pages (18):
- Get started: introduction, quickstart, installation
- Core concepts: config compiler, proof-carrying memory, pre-action gate,
  cross-session memory, verification gates, model routing
- CLI reference: overview + one page per GROUP (core, memory, substrate,
  quality, config); documents all 37 commands plus v0.19+ additions
  (know, deja, precommit, radar, report, tools, verify --deep, update --to)
- Guides: zero-config onboarding, team memory, keeping deps current with radar

Also adds docs.json (Mintlify config: ember brand palette from brand.json,
tabs→groups→pages navigation), brand favicon + light/dark logo SVGs, a
mintlify/README.md (local preview + GitHub-App deploy notes), and an advisory,
non-blocking .github/workflows/docs-links.yml running `npx mintlify
broken-links` on PRs touching mintlify/. No deploy workflow (Mintlify deploys
via its GitHub App). Zero runtime/dev dependencies added.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
…ead, honest deprecated=unknown

Three correctness fixes from the integrated-branch code review:

- consensus.js secretsLens is a solo-trusted BLOCKING lens but used the broad
  hasSecret() detector; a diff line like `const k = process.env.API_KEY` would
  false-block `verify --deep`. Now uses the same redaction-grade check
  (hasSecret && redactSecrets !== text) commit_gate.js uses for its blocking path.
- dash.js radarData read d.version/d.evidence, but radar.js writes installed/reasons,
  so the dash radar panel showed empty versions. Now reads d.installed (+ reasons),
  tolerating the legacy shape; test covers radar's real cache shape.
- radar.js probeRegistry set deprecated=false when the latest version doc was
  missing; that asserts "not deprecated" on unverified evidence. Now null (unknown)
  so classifyDep never counts a spurious evidence kind (mizan).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
CI Biome check failed on 4 format errors introduced when the review fixes
were reflowed by a local editor hook into non-canonical form. Ran
`biome check --write` on the affected files (consensus.js, dash.js, radar.js,
test/dash.test.js). No behavior change; tests 851 pass, docs check green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017Ebv4QDTqzPzgApBW2KUsU
@CodeWithJuber
CodeWithJuber marked this pull request as ready for review July 17, 2026 13:06
@CodeWithJuber
CodeWithJuber merged commit 70519ba into master Jul 17, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants