Skip to content

promote: staging → main (2026-10-20-2) — 9bb5265ae - #2590

Merged
modelmirror merged 79 commits into
mainfrom
promote/2026-10-20-2
Oct 20, 2026
Merged

modelmirror merged 79 commits into
mainfrom
promote/2026-10-20-2

Conversation

@fedcourtsai-dev

@fedcourtsai-dev fedcourtsai-dev Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Drafted by the promotion train at 2026-10-20T14:35Z for promote/2026-10-20-2 at 9bb5265ae over main f9bdab01a. The branch was cut from staging and never moves, so the integration evidence and an approval of this head stay valid while staging carries on. The train regenerates the block between the markers while this PR is open; write anything else outside it.

Gate status (promote/2026-10-20-2 at 9bb5265ae):

  • freshness: not yet — freshness: no green 'ranged-reads' integration-test run at 9bb5265;freshness: no green 'corpus-service' integration-test run at 9bb5265;freshness: no green 'stub-cascade' integration-test run at 9bb5265
  • registry: not yet — registry: predictor codex-baseline computes sha256:70fee158526caa6870d43ace70c3781db39f644379c86c363538ebdefa57547c, which the registry does not register; run fedcourts register-process in the PR that moved it;registry: predictor gemini-baseline computes sha256:a9033e56819e775e561b802dec24bae437c17c751e5a7f5fa4b3eeb31383951f, which the registry does not register; run fedcourts register-process in the PR that moved it;registry: evaluator codex-judge computes sha256:18a76b9301aef6770b5c5f9965dd6fcabb2a929964a56be2151405ce878e0456, which the registry does not register; run fedcourts register-process in the PR that moved it
  • contexts (admin read, run by hand): due — the batch changes .github/workflows/ci.yml, .github/workflows/integration-test.yml, .github/workflows/promotion-prep.yml, .github/workflows/run-analytics.yml, .github/workflows/run-backtest.yml (+9 more).
    Run scripts/promotion-gate.sh contexts with an admin-read token before merging.
    It reads main's workflows, so for the workflow changes run scripts/promotion-gate.sh contexts again once this merges.

Train: the integration gate is running (https://github.com/ModelMirrorAI/fedcourtsai/actions/runs/39440437340)

Next (maintainer): read the batch and approve this PR at 9bb5265ae. The train then merges it with a merge commit once the integration gate run, the required checks and the registry gate hold at this head and no predict/evaluate/back-test round is in flight. Merging it yourself instead is fine. To stop it, request changes or close it: a closed candidate is not re-cut at the same staging tip, and the next one is cut when the train is dispatched after staging moves.

The batch

Effect checks

#2546: fix(documents): bound the contact scrub's email shape; leave Ohio State Reports citations alone

uv run pytest tests/test_documents.py -k "ohio or linear_time or not_a_contact or mailing_address" is green, and uv run fedcourts process-digest --all prints the same label and six digests at the carrying merge as at its first parent.

#2547: fix(summaries): withhold staged documents the contact scrub left residuals on

On the next summarize run after promotion, the stage job's summary line reads stage check: … kept, … removed, M document(s) withheld. A case with residual-flagged documents shows ::warning::removed scotus/<docket>/<kind> from the staged records: document withheld: <n> contact residual(s). uv run pytest tests/test_summaries.py -k stage is green.

#2550: feat(process-version): proc-v10 — codex pair → gpt-6.1-sol, gemini pair → gemini-4-argon

After the carrying promotion, the next run-predict codex and gemini cells carry process_version.label: proc-v10 with digests 7ab92dd4… / bee46e92…. Their usage.json records "model": "gpt-6.1-sol" / "gemini-4-argon", with cost lines at the new rates.

To check:

  • git grep -l '"model": "gpt-6.1-sol"' origin/main -- data/cases | wc -l is greater than 0, and the same for gemini-4-argon.
  • Then re-run uv run fedcourts successor-disclosures --closed proc-v8 --successor proc-v10 for the dated follow-up entry.

#2557: docs(security): the production read-write role's trust names corpus-write alone

None at run time; this is documentation. The IAM change itself is checked by the next scheduled run-pull window succeeding under corpus-write.

#2587: ci: land data-run PRs as merge commits under their PR titles

After promotion, the first data-run PR merged by its job lands as a merge commit with the PR title as its subject:

git log origin/main --first-parent --merges --format='%s' -5

This should show predict: N prediction(s) (run …) (#N)-style subjects. It should not show Merge pull request #N from ModelMirrorAI/run/… for job-merged PRs.

No effect-check note found. Add one to the feature PR's description (the next refresh picks it up) or write it below the end marker, or say there why none applies:

After the merge

  1. Tag promotion/<YYYY-MM-DD> on the merge commit (-2 for a same-day second batch).
  2. Fill the freeze-record placeholders this batch owes:
    • <FILL: census evaluations digest=a8610eec,6a88d3dc>
    • <FILL: census predictions digest=7ab92dd4,bee46e92>
    • <FILL: merge sha>
    • <FILL: merged-at>
    • <FILL: promotion tag>
  3. Run the effect checks above and record what they printed.

Re-run promotion-gate: the integration gate suite went green at 9bb5265 in run 39440437340 (15:00Z), after the check last ran.


Generated by Claude Code

claude and others added 30 commits October 18, 2026 18:33
…se-variant guard

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019NtSiNeMSRGjEKSx7yTfdu
docs(security): record the case-sensitive ruleset patterns and the case-variant guard
…ts with the workflows

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019NtSiNeMSRGjEKSx7yTfdu
docs(security): align the token table, App grants and environment lists with the workflows
Under pipefail, `grep -q` exits on its first match without draining its
input, so the upstream writer can take SIGPIPE and the pipeline reads as
no-match. The 13 `env | grep -E '^AWS_' | grep -qvE ...` tripwires could
therefore pass on a leaked credential when the environment is large. They
now drain with `grep -vE ... > /dev/null`, which keeps the exit status. The
engine watchdog's piped `grep -Eq` takes a here-string instead, and a new
test refuses a piped quiet grep anywhere in the workflows, actions and
scripts.

spend.ceiling_usd goes from $4,000 to $3,000 (the derived $2,500 plus
$500 of headroom), with the comments in tracking.yaml, review-hold.yaml
and docs/pipeline.md brought in step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCyqNnoryARN5qnhghLJDd
…State Reports citations alone

The plain email pattern ran unbounded local-part and label runs, so a long
run of address characters with an @ and no domain behind it took quadratic
time (about 29 s at the 150,000-character document cap). Every run is now
bounded at the RFC limits and the domain at nine labels.

The street shape and the residual detector read '123 Ohio St. 3d 456' as an
address; a negative lookahead on the final name token leaves the reporter
citation (optional 2d/3d series and a 1-4 digit page) alone while an Ohio
Street address is still withheld.

Registers the scrub-ohio-reporter-citation harness boundary pending, with
its freeze-record entry.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
…duals on

summary-stage-check now removes, from a kept case, every staged document whose
manifest row carries a non-zero (or non-integer) contact_residuals count,
together with its manifest row, so a contact detail the scrub missed on a
filing's opening or closing does not reach the public one-day summary-stage
artifact. The rule keys on the residual count, not contact_scrubbed: false,
which every represented docket's documents also read.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
…s full effect

Review round: a series-less Ohio St. citation now needs a pin cite or a
parenthesis after its page, and a series one a page standing alone and not
followed by a capitalized word, so '350 Ohio St. 200', '350 Ohio St. 4B' and
'1200 W Ohio St. 3d Floor' stay withheld; the Law Journal spelling is read as
a citation. The freeze entry states the manifest flip, the past-bound email
strings, the counting windows, the evaluator side and the unsized exposure.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
… documents apart

Review round: a manifest row with no contact_residuals key is withheld (nothing
says it is clean); a manifest kind that is not a file stem removes the case
before anything is unlinked; the stage-check line counts withheld documents
apart from removed cases; case-summaries.md says the summary is written from
the rest of the record under the plan's digest.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
fix(ci): drain the credential tripwires' grep; spend ceiling to $3,000
…ir → gemini-4-argon

Moves the codex and gemini engine defaults, prices both models at their
published rates, registers proc-v10 pending (four digests move, the claude
pair carries forward), and adds its freeze-record entry. Tests that read the
committed registry now tolerate a pending label and date their fixtures off
the last counting instant.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XrszNR5q9CFWAXN6Ln6A8E
The repair-parity prerequisites test re-parsed run-repair.yml ~500 times;
the workflow is now parsed once per process and each pass's steps are
selected once. The every-command help render is one case per command, so
xdist spreads it. The ledger scan (validate data, ops-report) parses YAML
with libyaml's safe loader through serialize.load_yaml and replaces
Path.relative_to with the same lexical prefix test minus the parents walk.

Refs #2528


Claude-Session: https://claude.ai/code/session_01FP36E1sR8BzuBwdFwEmPsM

Co-authored-by: Claude <noreply@anthropic.com>
typer.testing.CliRunner.invoke converts the Typer app to its Click group on
every call, which for this CLI walks all 166 commands' signatures. The tree
depends only on the app's registrations, so conftest now routes the runner's
conversion through a per-app cache (tests/cli_build_cache.py), with tests
that the cache is installed, keyed per app, and on invoke's path.

Refs #2528

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FP36E1sR8BzuBwdFwEmPsM
Anchor the promotion-record fixtures to a fixed past instant so they pass
once the merge stamps the label, let the registry goldens through later
stamps without loosening known rows, narrow the pending-close relaxation,
and correct the freeze-record disclosures, the spend caveat and the budget
projection the reviewers flagged.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XrszNR5q9CFWAXN6Ln6A8E
test(ci): build the CLI's Click tree once per test process
chore: sync main into staging
The $2,000 budget sits under the trailing 30-day spend ($2,302 on
2026-10-19) while the long-conference campaign is still in the window, so
every predict, evaluate and summarize round waits on a human release. At
$2,500, $500 under the $3,000 spend ceiling, routine rounds release again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LCyqNnoryARN5qnhghLJDd
feat(process-version): proc-v10 — codex pair → gpt-6.1-sol, gemini pair → gemini-4-argon
config(review-hold): auto-release budget to $2,500
Resolve the freeze-record append conflict (the proc-v10 entry first, then
this entry) and restate the entry's digest line and counting windows
against the proc-v10 label now pending on staging.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
…rite alone

The maintainer removed environment:prod from the production read-write
corpus role's trust, so SECURITY.md and docs/security.md state the narrowed
trust as the current design rather than a pending IAM step; the provisioning
order stays as the rule for re-provisioning. The Claude GitHub App exchange
stays the stated accepted residual.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
Review round: security.md's staging comparison, its runbook step and its
role table, data-pipeline.md's credential-split note, and the comments in
run-predict, run-evaluate, run-pull and staging-corpus-refresh no longer
describe the read-write role's narrowing to corpus-write as a future step.
The re-provisioning order names the subject it keeps and what skipping its
last step leaves open.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
…ail-bound-ohio-cite

fix(documents): bound the contact scrub's email shape; leave Ohio State Reports citations alone
…op-residuals

fix(summaries): withhold staged documents the contact scrub left residuals on
…t-app-residual

docs(security): the production read-write role's trust names corpus-write alone
`gh pr merge --auto` ran seconds after `gh pr create`, while the PR's
required checks were queued but unreported; gh read the PR as mergeable,
called mergePullRequest instead of arming, and the ruleset refused. Arm
with enablePullRequestAutoMerge(MERGE), fall back to a direct merge,
retry for a few minutes until the checks register, and fail the run
when neither takes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfjaLBEcsn9UBUSe33fpwE
…PR body wording

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfjaLBEcsn9UBUSe33fpwE
…er's current petition

A summary filed under a docket id whose number the Clerk re-docketed
describes the earlier petition. summarize-plan now lists every committed
summary whose snapshot day precedes the newest record's DocketedDate as
withdrawn, compares the case against its newest summary left, and the
publish job deletes the withdrawn files on the reviewed refresh PR, the
jail admitting only those deletions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfjaLBEcsn9UBUSe33fpwE
Step 0 gains check 8: every label, blessing, window and boundary stamped on
main reaches the merge field for field and in main's order, the
merge-stamping declaration stays put, and evaluator blessing labels only grow
by a label new to main. The comparison is three-way against every merge base,
so a stamp not yet synced back passes. register-process's pending close and
blessing drop pass, and so does a revocation of a closed window dated at or
after the head.

The golden harness boundaries now pin the five rows stamped on 2026-10-16 and
2026-10-18.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
claude and others added 8 commits October 19, 2026 22:58
…pdates for the site

run-analytics gains a public-updates mode and a Monday 12:57 UTC cron that
adds each missing week's public-update render to metrics/updates/<week>.md
(fedcourts archive-public-updates) and lands it as an unattended PR on
metrics/public-updates, bounded by a new add-only path jail
(assert-update-paths) that the required paths check runs.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzhLezuGW2VqKEbvVCjtsx
Refuse an incomplete --through week, validate week numbers in the jail,
collapse caption whitespace, fence metrics/updates out of the back-test
replay, move the cron to 12:59, guard git add on an absent directory, and
bring the docs and isolation tests in step.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EzhLezuGW2VqKEbvVCjtsx
chore: sync main into staging
feat(public-update): a write-once weekly update history under metrics/updates for the site
The unattended data-run PRs to main (collect, the big-case board, the
update history) switch from squash to merge commits, so every merge on
both branches is a merge commit and main's rulesets can drop squash
once this is promoted. Each merge commit takes "<PR title> (#N)" as its
subject, on merge-when-green.sh's own merge and on the auto-merge arm,
so main's first-parent log reads one line per run and keeps the
auto-released mark the review hold counts its daily cap from, dated
when the PR lands.

Tests pin the counter against merge-commit history (merge commit and
ready commit both reachable, either alone in the window, the platform's
default subject), the merge subject and method, and the arm string.
The promotion-prep walk for the last promotion merge is sized for the
data merges it now passes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013fZbpKTGZGjiioGWJu3ZzR
ci: land data-run PRs as merge commits under their PR titles
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
modelmirror enabled auto-merge October 20, 2026 15:18
@modelmirror
modelmirror merged commit 7d4f2c6 into main Oct 20, 2026
34 of 36 checks passed
@modelmirror
modelmirror deleted the promote/2026-10-20-2 branch October 20, 2026 15:24
@github-actions

Copy link
Copy Markdown
Contributor

promotion-record — 7d4f2c6 (#2590): success

Run: https://github.com/ModelMirrorAI/fedcourtsai/actions/runs/39448152455

  • tag: promotion/2026-10-20, prereg/proc-v10
  • filled: 7 placeholder(s); stamped: 13 registration(s)
  • stale placeholders an earlier merge carried (not filled):
    • line 10886: refresh commit
    • line 10887: ot2026-cell pool
    • line 10888: ot2025-cell pool

This branch was successfully deployed

1 active deployment
staging — 9bb5265a Deployed Oct 20, 2026 by modelmirror via scenario (qp-topic, claude-code) #232
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