Skip to content

promote: staging → main (2026-10-20) — 58c6d0a43 - #2588

Closed
fedcourtsai-dev[bot] wants to merge 77 commits into
mainfrom
promote/2026-10-20
Closed

fedcourtsai-dev[bot] wants to merge 77 commits into
mainfrom
promote/2026-10-20

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-20T12:46Z for promote/2026-10-20 at 58c6d0a43 over main fa29d24a2. 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 at 58c6d0a43):

  • freshness: not yet — freshness: no green 'ranged-reads' integration-test run at 58c6d0a;freshness: no green 'corpus-service' integration-test run at 58c6d0a;freshness: no green 'stub-cascade' integration-test run at 58c6d0a
  • 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 process registry gate refuses this head, so the integration gate is not dispatched (see the run's annotations); fix it on staging and close this candidate

Next (maintainer): read the batch and approve this PR at 58c6d0a43. 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.

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 27 commits October 19, 2026 17:05
…, not the control

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

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
feat(corpus): a remote-writes switch only the corpus writer jobs set
…restore wrongly recorded exits

The cert disposition patterns read a partial Rule 46 dismissal and a
stay order's "should the petition be denied" clause as the petition's
exit, and missed "the petitions are GRANTED". A third
disposition-convergence arm, restored-grant, relabels a committed
denied/dismissed outcome whose recording sentence is now refused and
whose docket later grants. Registers the pending harness boundary
cert-exit-guard-and-plural-nouns with a dated freeze-record entry.

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

A dry run now holds the read-only role alone: no App token, no git identity,
no corpus-write lock, the remote-writes switch off. Its dedupe and scope
reconcile prerequisites apply to the runner's copy and stop before the push,
every pass authenticates git only on an apply, the OCR re-mint takes the
read-only role on a dry run, and the verdict publishes on an apply only.

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

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

The merits parser missed a judgment joined to the grant recital, a
ruling on a lower court's order or determination, a long subject-verb
gap, a Rule 46 decree inside a longer order, and read a consolidated
entry's first verb for every docket. A parsed judgment now clears
merits_terminated. Registers the pending harness boundary
merits-judgment-parser-summary-ruling-consolidated with a dated
freeze-record entry.

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

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DfjaLBEcsn9UBUSe33fpwE
State in the docs that a dry run narrows what the corpus job holds, not what
it can mint; refresh the stale lock, token and dispatch-form wording; and make
the push-guard test require the dry-run branch to exit before any push.

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

fix(judgment): read summary rulings, Rule 46 decrees and per-docket clauses
… the cert ones

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

fix(cert): refuse partial and conditional exits, read plural grants, restore wrongly recorded exits
ci(run-repair): give the corpus job's dry run the read-only role and no write credential
… outside its lane (#2575)

* feat(stamp): audit a predict cell's logged calls for reads and writes outside its lane

The stamp reads the cell's retrieval_log.json and appends one harness
warning per kind to its flags.json: a call naming the removed qp-topics
oracle, another cell's committed predictions/ or evaluations/ output, or a
write under data/ or a case record/ outside the cell's run directory. A path
named only to exclude it is no access. Capture now leads a file tool's
serialized params with its target path, so the path survives the slice cut.

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

* fix(cell-access): resolve review on the lane audit

Keep a revision's ^ out of the exclusion strip, count grep -v as a read as
the evaluate prompt does, spare a slice end only where capture cut it, read
a bare predictions directory from history, match the cell's own run by case
and event, normalise and unquote write targets, and bound the note however
its quoted paths escape. Leave capture's key order as it is: it sits on the
graders' reading path, so the audit documents the writes it cannot see.

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
Coverage is reported in the job summary and never gated on, and it costs
about a tenth of the test step on every PR push. A push to main still
measures and reports it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
ci: measure coverage on pushes to main only, not on every PR run
…cided

A new docs/document-provisioning.md walks a filing from selection to a
cell's record/documents/: each step's code and governing section, the kinds
a cell can be given, the settings that bound the set, what it does not
cover, and how coverage is measured.

The OCR sweep's plan-artifact carve-out was still "proposed" in
data-sources.md, security.md, pipeline.md and data-pipeline.md although the
sweep's run-seed jobs are on main, and its scanned-filing scrub residual
was still described as open after the residual detector landed. Both now
state the current design, including that a document the detector flags is
still staged to the cell.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TEb9wVQZk1u4uf8Stwn1kq
docs: map document provisioning; record the OCR sweep carve-out as decided
The cert resolver now records "probable jurisdiction noted" and "further
consideration of the question of jurisdiction postponed to the hearing of
the case on the merits" as granted, so a direct appeal's docket carries
its grant and latches the merits pair. A sentence naming a docket number
is skipped, so a combined order never grants on the wrong docket.

Registered as a pending harness boundary with a freeze-record entry. The
one-off refresh of the 44 affected dockets is held until summary
affirmance and want-of-question dismissals are read, so direct appeals
enter the pools on both sides at once.

Refs #2581

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

feat(cert): read probable jurisdiction noted as a direct-appeal grant
…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
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