Skip to content

feat: per-prompt metacoder overlay + deps pinning#1

Merged
QuentinCody merged 6 commits into
mainfrom
codex/pin-dependencies
May 14, 2026
Merged

feat: per-prompt metacoder overlay + deps pinning#1
QuentinCody merged 6 commits into
mainfrom
codex/pin-dependencies

Conversation

@QuentinCody
Copy link
Copy Markdown
Owner

Summary

  • Pin direct dependency specs to the exact versions already resolved in the lockfile.
  • Give the slow verify suppression integration test enough time under CI load.
  • Fix secret-token regex boundaries for token alphabets that can validly end with -.

Validation

  • npm run typecheck
  • npm run typecheck:stable
  • npm run docs:check
  • CI=1 npm test
  • npm run build
  • npx publint
  • npx --package=@arethetypeswrong/cli attw --pack . --profile esm-only
  • npm pack --dry-run
  • tarball install smoke test
  • INTERLINKED_REPO_URL=/Users/quentincody/interlinked-cli INTERLINKED_REPO_REF=HEAD bash scripts/smoke-onboarding.sh

QuentinCody and others added 6 commits May 13, 2026 12:57
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>
@QuentinCody QuentinCody changed the title [codex] pin dependencies and stabilize CI feat: per-prompt metacoder overlay + deps pinning May 14, 2026
@QuentinCody QuentinCody marked this pull request as ready for review May 14, 2026 17:31
@QuentinCody QuentinCody merged commit be1e14e into main May 14, 2026
3 checks passed
@QuentinCody QuentinCody deleted the codex/pin-dependencies branch May 14, 2026 17:31
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.

1 participant