Skip to content

feat: end-to-end alignment — docs↔code drift gating, math over keyword heuristics, persistent memory#46

Merged
CodeWithJuber merged 9 commits into
masterfrom
claude/forge-work-system-setup-p26ka5
Jul 10, 2026
Merged

feat: end-to-end alignment — docs↔code drift gating, math over keyword heuristics, persistent memory#46
CodeWithJuber merged 9 commits into
masterfrom
claude/forge-work-system-setup-p26ka5

Conversation

@CodeWithJuber

Copy link
Copy Markdown
Owner

What & why

Three systemic problems, fixed at the root and gated so they can't recur:

1. Docs and code were misaligned, and nothing noticed. A full audit found 56 real drift issues: the entire forge config command family undocumented, 18 env vars read but documented nowhere, a phantom env var in ROADMAP (LITELLM_GATEWAY_URL — never existed in code), MCP tool counts disagreeing across four docs (5 vs 15 vs 3 vs actual 19), and two completely empty CHANGELOG release sections. This PR fixes all of them and adds forge docs check (new CI job + doctor check): commands, env vars, MCP tool names/counts, and CHANGELOG are now machine-reconciled against the code — the sources of truth are the commands.js table, actual process.env reads (src + shell guards), and the mcp_tools.js registry. bump.mjs now refuses to rotate an empty [Unreleased].

2. Hardcoded regex made semantic decisions. Every keyword-list decision is replaced with math (data tables like exemplars stay data):

  • Routing: similarity-weighted k-NN over a labeled exemplar bank (overlap coefficient on stopword-filtered, plural-folded unigram+bigram sets, credibility-shrunk toward a prior) replaces the four topic keyword regexes and their additive magic weights. Unseen phrasings route by resemblance; every score returns its neighbors. Tune by adding labeled rows, not weights.
  • Secret detection: src/secrets.js is the single source of truth — format grammars + a Shannon-entropy gate (new src/math.js) for unknown-vendor tokens. The secret-redact guard imports the same module, ending the JS/shell regex divergence.
  • Lessons: graded token-overlap keyword matching (same-module partial credit) instead of all-or-nothing string equality.
  • Goal drift: goalDrift returns a graded driftScore — the magnitude the existing CUSUM detector was designed to accumulate but never received.
  • Substrate minimality warnings derive from computed preflight/route signals instead of a second keyword copy; skillgate gains an entropy detector for obfuscated base64 payloads; provider status probes /health for behavioral gateway evidence.

3. Changes didn't propagate end-to-end, and sessions forgot.

  • The atlas now parses markdown into doc nodes with references edges — forge impact src/foo.js lists the docs that go stale, and the pre-edit hook says so before the edit.
  • forge anchor set/show/clear persists the active goal in .forge/goal.md; SessionStart re-injects it every session.
  • The Stop hook auto-repairs a drifted managed AGENTS.md (FORGE_AUTOSYNC=0 to disable) — drift used to be detected by doctor and repaired by nobody.

Adversarial review before push: an 8-angle review (line-by-line, removed-behavior, cross-file, reuse/simplification/efficiency, altitude, conventions) surfaced 10 verified defects in the new code — most critically, entropy false positives on file paths/camelCase identifiers that would have corrupted tool output, and a lost routing floor on short concurrency phrasings. All fixed with regression tests in the final commit.

Checklist

  • npm test passes (Node 18/20/22) — 543 tests (was 500), 0 failures
  • npm run check passes (Biome lint + format)
  • New public functions have a test
  • Conventional commit message (feat:/fix:/docs: …)
  • CHANGELOG.md updated under ## [Unreleased] (and the empty 0.8.0/0.8.1 sections backfilled)
  • No new runtime dependency (dev deps ok)
  • Substrate/docs updated if this changes forge substrate, forge impact, router/gate, or MCP substrate tools — GUIDE routing/config/anchor/MCP/env sections rewritten; forge docs check passes clean on this tree (dogfooded)

Risk & rollback

  • Risk level: medium — routing scores and secret detection change behavior; both are advisory-by-default layers, all existing behavior contracts are pinned by tests, and the LLM band rails/floors are re-verified against review counterexamples.
  • Rollback plan: revert the branch commits; each wave is an independent commit (math → secrets → routing → wiring → docs machinery → memory → docs → hardening) so a single subsystem can be reverted alone.

Extra checks (tick if applicable)

  • npm run typecheck passes
  • Input validated at boundaries; errors handled (no swallowing — fail-safe paths log under FORGE_DEBUG=1)
  • Logs contain no secrets/PII (secret detection itself is under test both directions)
  • If AI-assisted: I understand it, verified the package APIs, and it has tests

Generated by Claude Code

Comment thread src/goal.js Fixed
claude added 9 commits July 10, 2026 07:02
…et Jaccard

The one numeric family missing from forge's math inventory (cosine, MinHash,
Beta posteriors, CUSUM, logistic regression all exist). Entropy backs the
upcoming secret-detection upgrade; setJaccard backs exemplar similarity where
MinHash estimation is unnecessary.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
…for JS and shell

src/secrets.js now owns detection AND redaction: the historical format grammars
(unchanged semantics, SECRET_RE still exported) plus a Shannon-entropy gate that
catches unknown-vendor credentials the format list can never enumerate. Every
refusal site (ledger mint, recall/lesson persist, adjudicate both directions,
diagnose traces, ledger verify) now calls hasSecret().

global/guards/secret-redact.sh imports the same module via node instead of
keeping a narrower divergent sed regex — the shell guard and the JS refusal
sites can no longer disagree (sed remains only as a degraded fallback when the
source tree is unreachable). Parity pinned by tests.

Precision invariants preserved: bare English mentions ("implement password
hashing") still pass; hex digests/UUIDs/identifiers are exempt by construction.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
The text-complexity rubric is now similarity-weighted k-NN regression over a
labeled exemplar bank (50 example tasks with target complexities): overlap-
coefficient similarity on stopword-filtered, plural-folded unigram+bigram sets,
credibility-shrunk toward a prior, plus a bounded structural term (length,
code fences, constraint/step counts). Replaces the four hand-tuned ALGO/ARCH/
MODERATE/TRIVIAL keyword regexes and their additive magic weights.

Why: a keyword list needs the literal token — "two threads deadlock when the
queue is full" scored zero on the old rubric because neither "race condition"
nor "mutex" appears. k-NN scores it by resemblance to labeled neighbors, and
every score stays attributable (the neighbors are returned with the estimate).

The exemplar bank is data: add rows to improve coverage, no weights move.
strongSignal (the LLM lower-bound floor) now means "confidently matched a hard
exemplar" rather than "contains an algorithmic keyword". All existing routing
behavior contracts hold (same tier cutoffs, same band rails, same free-raise/
bounded-lower reconcile).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
- lessons.matchScore keyword tier is graded (0.3 × token-overlap coefficient):
  an exact keyword keeps its historical 0.3, a same-module partial match earns
  partial credit instead of the old all-or-nothing string equality.
- anchor.goalDrift returns driftScore in [0,1] (off-goal fraction per checkpoint),
  the graded magnitude cusum() was designed to accumulate but never received.
- substrate.minimalityWarnings no longer keeps its own keyword copies: warnings
  derive from the preflight DIMENSIONS rubric (missing target_scope/constraints)
  and the route score already computed in the same gate.
- skillgate gains an entropy-based obfuscation detector: a 200+ char base64-class
  blob at >=4.5 bits/char flags as a possible obfuscated payload — signatures
  catch known attack shapes, entropy catches the unknown one hiding as a blob.
- providers: isLikelyGateway documented as a prior; providerStatus now probes
  /health on any custom base URL and reports behavioral gateway evidence, so a
  proxy the URL vocabulary missed still gets classified by how it behaves.

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

New src/docs_check.js reconciles documentation CLAIMS against the sources of
truth that already exist in code, so a feature can no longer merge with its
docs silently missing:
- commands: README/GUIDE vs the commands.js table (extracted from cli.js so
  --help and the docs check render from the same data)
- env vars: prose docs vs actual process.env reads in src/*.js AND $VAR reads
  in shell guards; both directions (undocumented reads + phantom vars)
- MCP tools: doc counts and tool names vs the cortex_mcp TOOLS registry (now
  exported)
- CHANGELOG: latest header matches package.json, no empty release sections,
  [Unreleased] can't stay empty while src commits accumulate

Wired in three places: new `forge docs check` command (exit non-zero), a
doctor check that runs only inside the forge repo itself, and a docs-drift CI
job. scripts/bump.mjs now refuses to rotate an empty [Unreleased] — the exact
mechanism that produced two empty release sections.

Atlas now parses markdown: each doc becomes a graph node with references
edges to the code it names (backticked paths/symbols, link targets), so
`forge impact src/foo.js` lists the DOCS that go stale — the missing code→doc
half of end-to-end propagation. First run of the checker found 56 real drift
issues including a phantom env var (FORGE_BRAND) no audit had caught.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
Three fixes for cross-session amnesia and silent drift:

- src/goal.js + `forge anchor set/show/clear`: the active goal now persists in
  .forge/goal.md. SessionStart re-injects it, and a bare `forge anchor` checks
  drift against the stored goal — it used to live in one command's argv and
  vanish with the session, so every new session re-assumed the objective.
- sync.autoSyncIfDrifted(): the Stop hook now REPAIRS AGENTS.md drift instead
  of leaving it for doctor to report — lessons/facts learned in a session reach
  every AGENTS.md-reading tool immediately. Never adopts an unmanaged repo;
  kill switch FORGE_AUTOSYNC=0.
- pre-edit hook: when the cached atlas knows docs that reference the file being
  edited (the new doc-reference edges), it says so before the edit — code
  changes carry their documentation with them instead of leaving it behind.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
Fixes every drift issue the new reconciler found (56 on first run):

- README: forge config + forge docs rows in the Commands table; accurate
  19-MCP-tools claim with a link to the full list; anchor set/show/clear noted.
- GUIDE: new forge config section (auto-detection priority order, corporate
  gateway walkthrough); forge docs section; routing section rewritten for the
  exemplar k-NN rubric with honest sample output; persistent-goal docs; full
  19-tool MCP table; complete environment-variable reference covering every
  var the code actually reads (kept honest by forge docs check in CI).
- ARCHITECTURE: brand-token wording no longer reads as a phantom FORGE_BRAND
  env var; MCP layer described as the real 19-tool server.
- ROADMAP: phantom LITELLM_GATEWAY_URL replaced with the real mechanism
  (litellm.config.yaml + ANTHROPIC_BASE_URL); OpenAI/Gemini detection moved
  from Shipped to Next (it is not implemented); version header current.
- CHANGELOG: backfilled the empty [0.8.0] and [0.8.1] sections from git
  history and wrote [Unreleased] covering the gateway work and this change.
- CLAUDE.md: docs check added to the pre-commit gate; benchmarks wording
  updated for the exemplar rubric.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
An 8-angle review of the branch surfaced verified defects; all fixed with
regression tests:

Secret detection (the critical class — false positives corrupted tool output):
- TOKEN_RE no longer includes '/', so file paths split into segments instead of
  fusing into one high-entropy token (src/components/UserProfileCard2/index.js
  was detected as a secret and redacted to '[REDACTED].js').
- The entropy gate additionally requires >=3 scattered digit runs: long camelCase
  identifiers with a lone digit clear 3.9 bits/char (measured), random keys have
  scattered digits — the discriminator entropy alone could not provide.
- Redaction of assigned values is now narrower than detection: only quoted or
  opaque-token values mask, so reading 'const token = jwt.sign(payload, key)'
  is never mangled. Detection stays broad for store refusals.
- PEM masking is case-insensitive and tolerates truncated headers.
- The guard prefilters with grep before spawning node, and the node reader uses
  setEncoding('utf8') so multibyte chars split across chunks can't corrupt output.

Routing:
- strongConf 0.5 -> 0.35 plus short-phrasing exemplars (deadlock in a worker
  pool, race condition in a queue, back pressure, schema migration): the LLM
  lower-bound floor holds again on every review counterexample.
- Prose sequence markers ('and then', 'after that') count toward nSteps.
- Exemplar gram footprints precomputed at module load (hooks route per prompt).

Lessons: generic path tokens (src, js, index, ...) are excluded from keyword
matching — a lesson keyed to src/auth/login.js no longer matches every .js edit.

Preflight/substrate: dead regex alternatives fixed ('scal' never matched
'scalable'); authentication/payment/billing now imply the constraints dimension;
the minimality warning is worded to what the signal means; completeness guarded.

Structure: MCP tool registry moved to src/mcp_tools.js (pure data), breaking the
doctor -> docs_check -> cortex_mcp -> doctor import cycle; docs_check scans src/
recursively and follows BRAND.cli; generated/churning docs (AGENTS, CHANGELOG)
excluded from the atlas so auto-sync can't perpetually re-stale it; DOC_EXTS
replaces the empty-array sentinel; the pre-edit hook strips the root prefix only
at a path-separator boundary; new user-facing strings use brand tokens; dead
math exports removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
- test/math.test.js assembles its high-entropy fixture at runtime (the
  repo's _fixtures.js pattern) so no credential-shaped literal exists for
  gitleaks to flag — applied through the branch history, which stays clean
  end to end (the repo deliberately carries no scanner allowlist).
- goal.js getGoal slices at the first provenance comment instead of
  regex-stripping comment blocks (CodeQL js/incomplete-multi-character-
  sanitization: a replace can leave a partial '<!--' behind).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019PXuKmJp92Gdo2FudNjSx2
@CodeWithJuber CodeWithJuber force-pushed the claude/forge-work-system-setup-p26ka5 branch from 3acf75b to 1693318 Compare July 10, 2026 07:05
@CodeWithJuber CodeWithJuber marked this pull request as ready for review July 10, 2026 07:09
@CodeWithJuber CodeWithJuber merged commit d5439d5 into master Jul 10, 2026
11 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.

3 participants