Skip to content

fix(registry-gate): digest a candidate with its own engine defaults - #2589

Merged
modelmirror merged 1 commit into
stagingfrom
claude/project-thread-7xm4kn
Oct 20, 2026
Merged

modelmirror merged 1 commit into
stagingfrom
claude/project-thread-7xm4kn

Conversation

@modelmirror-agent

Copy link
Copy Markdown
Contributor

Requested by ModelMirror · project thread

What & why

The promotion train (promotion-prep) runs main's code and calls promotion-gate.sh registry <candidate>. registry_gate.live_actors_at copied only the candidate's config/predictors.yaml, config/evaluators.yaml and prompts into a scratch root. The two code-side digest inputs came from the running package: pricing.DEFAULT_MODELS and process_version.ENGINE_RETRIEVAL. A batch that bumps an engine default was therefore digested with the old model and refused.

That is why the train refused #2588 (proc-v10, codex → gpt-6.1-sol, gemini → gemini-4-argon) and never dispatched the integration gate suite. The CI promotion-gate check runs the head's own code, so its registry stage passed. It went red only on freshness.

The fix parses both literals from the candidate's source with ast and literal_eval, so it never imports the candidate. It threads them through digest_for_actor as an optional CodeInputs, and every other caller keeps the running package's values. It fails closed: the gate refuses a source it cannot read as exactly one literal dict. That covers a missing file, a syntax error, a non-literal value, zero or two assignments, a later mutation (subscript assign, |=, .update()), or a wrong shape.

Artifact served: the promotion train's registry verdict, and so whether it dispatches the gate suite and merges a candidate unattended.

Evidence (fedcourts registry-gate --main-ref origin/main):

code --at result
main's (unfixed) 58c6d0a43 (#2588 head) refuses codex/gemini baseline + judge digests (as the train did)
this branch 58c6d0a43 registry: 13 pending, step 0 clean
unfixed (head's) origin/main tree refuses the four proc-v10 digests (the mirror case)
this branch origin/main tree registry: 0 pending, step 0 clean

Limits.

  • The train runs main's code, so this takes effect only after it reaches main. Main's current gate will still refuse promote: staging → main (2026-10-20) — 58c6d0a43 #2588, or any candidate that carries proc-v10, whether or not it also carries this fix. That batch needs a maintainer dispatch of gh workflow run integration-test.yml --ref promote/<date> -f scenario=gate, then a hand merge.
  • Other parts of the digest's shape still come from the running code: the canonical key set and the config pydantic models. A batch that changes them is still digested by the base's shape until it lands. The module docstring now says so.

Effect check (handover note): after the promotion that carries this lands, uv run fedcourts registry-gate --at origin/main --main-ref origin/main prints step 0 clean. On the next candidate that moves an engine default, the train's body shows registry: ok and it dispatches the gate suite itself.

Merge: this touches src/fedcourtsai/registry_gate.py and its tests, which are maintainer-owned (the process registry the gate's Step 0 reads), so I'm leaving it for your review and merge.

Review: I ran code-reviewer. It found three blockers (format, an E501/SIM102, and mypy on non-exported names in the test), all fixed. I also took its recommendations: refuse mutations after the assignment, wrap SyntaxError/TypeError as gate refusals, and update the stale docs in docs/cli.md and the CLI docstring.

Checklist

  • Branched off staging and targets staging; this PR is focused on one thing.
  • Ran the relevant parts of the local gate. scripts/gate.sh lint types is clean. test gives 9158 passed and 2 failed. Both failures are environment-only: test_client redirect hits the session proxy, and test_collect's unreadable-file case can't be unreadable when running as root. Both are untouched by this diff.
  • Regenerated schemas/ if a pydantic model changed: no model changed.
  • Updated any docs the change makes stale (docs/cli.md, the registry-gate docstring, the module docstring).
  • No secrets, tokens, or credentials in code, data, or logs.

Generated by Claude Code

The promotion train runs the base's code, and the registry gate copied
only the candidate's config and prompts, taking pricing.DEFAULT_MODELS
and ENGINE_RETRIEVAL from the running package. A batch that bumps an
engine default was therefore digested with the old model and refused.
Parse both literals from the candidate's source (never importing it) and
thread them through digest_for_actor; refuse a source the gate cannot
read as exactly one literal.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GCZXYYDuAk85KKTdV8eMBA
@modelmirror-agent modelmirror-agent self-assigned this Oct 20, 2026
@modelmirror-agent
modelmirror-agent marked this pull request as ready for review October 20, 2026 14:00
@modelmirror
modelmirror merged commit 9bb5265 into staging Oct 20, 2026
7 checks passed
@modelmirror
modelmirror deleted the claude/project-thread-7xm4kn branch October 20, 2026 14:10
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