feat: per-prompt metacoder overlay + deps pinning#1
Merged
Conversation
Per-prompt metacoder that runs synchronously on UserPromptSubmit before the coding agent's first tool call. Emits a session-scoped overlay of guard rules (action: "block" only, tighten-only against the floor) plus an optional system_prompt_addendum. Same-tier model as the coding agent: Opus 4.7 max for Claude, GPT-5.5 xhigh for Codex. Both transports use the user's CLI subscription via `claude -p` / `codex exec` — no API keys required. The doc captures the locked-in decisions (model tier, hard-block enforcement, replace semantics across multi-prompt sessions), the floor/overlay invariant (action constraint + regex validation + ReDoS guards + append-after ordering), recursion-guard mechanics, hook timeout coordination, and the per-runner rollout contract. Six rounds of external review folded in at §reviewer-P1..P5 markers. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
On every UserPromptSubmit, an LLM peer of the coding agent (Opus 4.7 xhigh for Claude sessions, GPT-5.5 xhigh for Codex sessions) generates a session-scoped guard-rule overlay that the harness merges on top of floor rules for the lifetime of the prompt. Replaces the conceptual "user authors hooks" model with "hooks are compiled output per prompt." Both transports use the user's CLI subscription (`claude -p` / `codex exec`) — no ANTHROPIC_API_KEY or OPENAI_API_KEY required. Verified live: the Codex transport completes its argv handshake against the subscription endpoint, and the Claude transport returned a valid schema-correct emission with ANTHROPIC_API_KEY explicitly unset. Floor / overlay tighten-only invariant (overlay-loader.ts): - overlay rule ids must use the literal overlay_prefix from input - action must be "block" (ask/warn/soft_block/rewrite rejected) - floor-id collisions, disabled_rules, extra_exceptions all rejected - regex validated for ReDoS shapes, length, flag whitelist, syntax - after_command.pattern + active_when.file_scope also validated - raw input count capped before validation (prevents runaway emit) - overlay rules appended AFTER floor in merged set (floor wins) Per-session cache (server.ts): - sessionRules Map keyed by session_id, populated synchronously inside UserPromptSubmit so the first PreToolUse sees the overlay - on cache miss: hydrate from disk (survives daemon restart mid-session) - watchRulesFiles AND SIGHUP both clear the cache so floor reloads land - SessionEnd/Stop evicts both the cache entry and the on-disk overlay - non-ok metacoder outcomes (skipped/failed) also evict (replace semantics: prompt B's failure must not let prompt A's rules persist) - short-circuit when metacoder is disabled, with explicit eviction Recursion guard (plan §2.5): - metacoder spawns claude/codex subprocesses with INTERLINKED_METACODER_SUBPROCESS=1 in env - hook script (both adapter and legacy .mjs) forwards onto event - toLegacyHarnessEvent explicitly copies the field through - harness short-circuits UserPromptSubmit when set - generated .mjs also exits silently in subprocess mode so the metacoder's own internal prompts don't get written to activity.jsonl or POSTed to realtime sync Hook timeout coordination (plan §2.4): - adapter path: 35s for user-prompt phase, exceeds METACODER_TIMEOUT - legacy .mjs: HARNESS_USER_PROMPT_TIMEOUT_MS=35000 mirrors that - merge.ts clamps user-configured timeout_ms to <= 33000 so the hook always has buffer to return a clean timeout-allow decision Codex adapter encodeCodexAllow now emits hookSpecificOutput.additional Context on stdout for UserPromptSubmit (was stderr) so the metacoder's system_prompt_addendum reaches the agent's model context. Privacy: prompt scanner findings are redacted before the metacoder sees them. Raw PII never leaves the harness. 203 focused tests pass; six rounds of external review folded in. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
tsgo refuses to load `tsconfig.json` when a file path is on the command
line (`error TS5112`), so the harness's single-file PostToolUse check
was effectively running with default `compilerOptions` — no `types:
["node"]`, no `moduleResolution: "bundler"`. Every `import { ... } from
"node:fs"` then produced a spurious `TS2591: Cannot find name 'node:fs'`
in any file that uses node-protocol imports.
The new runTsgo materializes a per-call tmp `tsconfig.json` that
extends the project's real config and `include`s only the target file,
then invokes `tsgo -p <tmpTsconfig>`. tsgo now loads the full
`compilerOptions` while still checking exactly one file. The tmp
tsconfig is cleaned up after the call.
For `simulateEdit`'s tmp file path (which lives in `/tmp` and has no
sibling tsconfig), `runTsgo` accepts an explicit `projectRootHint` so
we walk up from the ORIGINAL file's directory to find the real
project's `tsconfig.json` instead of giving up at the tmp dir.
Also swaps the cache-key hash from SHA-1 → SHA-256 to satisfy the
harness's own `ubs_weak_hash` linter rule — non-security cache, perf
cost is in microseconds at this scale.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User-facing surface for the per-prompt overlay generator that landed in 31a14fe. Previously, the only way to enable/disable was to hand-edit `.interlinked/guard-rules.local.json` with knowledge of the JSON path — not discoverable. New `interlinked metacoder` subcommand mirroring the `interlinked scanner` pattern: `status`, `enable`, `disable`. Each toggle records an audit entry at `.interlinked/metacoder.audit.jsonl` (timestamp, actor, optional `--reason`) so "when was it off, and why?" is answerable. Reads/writes the same `metacoder.enabled` JSON path the rules-loader honors, so hot-reload picks up the change on the next watcher tick (~2 s) — no harness restart. README gets a "Metacoder (per-prompt overlay)" section with the subscription-auth promise, latency/cost trade-off, CLI cheat sheet, and links to the design memo + autogen config reference. `scripts/generate-docs.ts` is updated so the docs autogen path (`npm run docs`) now folds the metacoder into `configuration.md` (one table per field with defaults pulled directly from `DEFAULT_METACODER_CONFIG` — single source of truth) and the `cli-reference.md` picks up the new subcommands via the commander `--help` introspection it already does for every other command group. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The project's `software-version-fixtures-policy.test.ts` bans hardcoded fast-moving model aliases (gpt-5.5, claude-opus-4-7, gemini-N, etc.) in test files because they encode stale product knowledge. The escape hatch is the `REAL_WORLD_VERSION_FIXTURE_OK` marker on the same line or the line directly above, paired with a comment explaining why the real name is the test contract. The metacoder tests intentionally pin the exact model id — silent drift to a different model would be a behavioral regression we want to catch. Rephrased the describe/it block titles to drop the literal where it wasn't load-bearing, and added marker comments above the two assertions where the exact id IS the contract. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
-.Validation
npm run typechecknpm run typecheck:stablenpm run docs:checkCI=1 npm testnpm run buildnpx publintnpx --package=@arethetypeswrong/cli attw --pack . --profile esm-onlynpm pack --dry-runINTERLINKED_REPO_URL=/Users/quentincody/interlinked-cli INTERLINKED_REPO_REF=HEAD bash scripts/smoke-onboarding.sh