Skip to content

T44 #4875: the pmat hunt runs one hop from the pick, after Coverage Nightly - #4881

Open
noahgift wants to merge 48 commits into
mainfrom
a7w/4875-hunt-chain
Open

noahgift wants to merge 48 commits into
mainfrom
a7w/4875-hunt-chain

Conversation

@noahgift

@noahgift noahgift commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Closes #4875. Stacked on #4872 (its head is this branch's base); merge #4872 first. Do not arm before then.

Why

Under the pick chain (#4872), qwen-story-daily and coverage-nightly start from the same pick. Coverage takes 60-70 min and the story job is capped at 30, so the story's pmat hunt finds no coverage file for its commit and its gaps read not_measured on most nights.

What

  • qwen-hunt-nightly.yml (new): chained from Coverage Nightly, one hop from the pick. Its C step reads the coverage run's created_at and conclusion, so a failed coverage run makes the hunt not_measured. It downloads that run's coverage-json artifact and judges on the coverage.sha it records, never on the run's head_sha. It runs scripts/story_pmat_hunt.sh, then extracts the manifest, computes growth, uploads artifacts, files a tracking issue (continue-on-error) and fails the job on any hunt failure.
  • lib_story_pmat.sh: STORY_HUNTS, one table of the eight beats' hunts. qwen-story.sh runs line N via story_hunt N; story_pmat_hunt.sh runs all eight.
  • qwen-story-daily.yml: PMAT_HUNT defaults to 0, so the story can no longer go red on a hunt. A dispatch can still turn the hunt on.
  • check_producers_chain.sh: HOPS="qwen-hunt-nightly=coverage-nightly" (gate change).
    • A hop must chain from its listed upstream's name: and passes the same P1/P3/P4 checks.
    • An unlisted workflow chained from a listed producer is P5 RED.
    • A hop counts as listed for P6.
    • Also RED: an upstream that is not a listed producer, a hop that is also a producer, and a missing hop.
  • nightly_train.sh: the qwen-hunt lane.
  • mutants-nightly.yml: the timeout comment now states the chained start window instead of "ends by 06:00Z".
  • Contracts: FALSIFY-QWEN-STORY-004 now reads story_hunt; the nightly-pick clock domain names the one-hop case.

Review findings at 31873fe, each with a must-RED row

  • A hop of a hop passed: the upstream list held only producer names. A hop's own name is now an upstream too (row p5_unlisted_hop_of_a_hop).
  • Block-style workflows: lists were not read. The guard reads flow lists, scalars and one - item per line, and drops trailing comments (rows p5_unlisted_block_upstream, p5_unlisted_block_pick, p5_unlisted_block_commented, hop_block_single_chained, p2_listed_block_two_entries).
  • Multi-entry lists naming the pick in any position passed. Every entry is now checked (rows p5_unlisted_pick_first, p5_unlisted_pick_second, p5_unlisted_pick_scalar).
  • A form the guard cannot read now fails P2 in any file: an alias, an empty list, an inline on: or workflow_run:, a list on the next line, a folded scalar, a nested list, a continued item (rows p2_unlisted_*). An unlisted workflow chaining from something else stays green (unlisted_other_chain_ok).
  • FALSIFY-QWEN-STORY-004 read file order. The contract and check_story_pmat_hunt.sh §10 now require each beatN_*() to end with story_hunt N, with no hunt anywhere else. Its mutants now kill 14/14, including a hunt moved into another beat, a re-indented extra hunt, a repeated hunt and a hunt outside any beat.
  • on: keys at indent 4 were not read, so a workflow_run there passed. Keys under on: at any indent other than 2 are now unreadable: a workflow_run there is P2 and a schedule there is P1 (rows p2_unlisted_on_indent4, p2_listed_on_indent4, p1_schedule_on_indent4).
  • A beat defined twice passed 004, though bash runs the last definition. 004 and §10 now fail on a second beatN_ definition in any form: the same name, another name, the function keyword, a space before (), an indented one-liner.
  • P7 night line: new rows for a commented-out line and for a call inside another line; mutant m76 drops -x from the calls check.

Red on the base

A fixture of the base tree plus an unlisted extra.yml chained from "Coverage Nightly":

  • base guard: PASS every nightly producer chains from "Nightly pick" (vacuous);
  • this guard: FAIL extra.yml: P5 chains from "Coverage Nightly", a listed producer or hop, but is not in HOPS, then RED.

Receipts (all run at ed69010, which merges #4872 at 07d5f6c)

  • Guard on the real tree: PASS.
  • Guard self-test: 97 rows. Mutants: 72/72 killed, 0 errors.
  • nightly_train.sh --self-test: 100/100, mutants 81/81. check_release_scripts_derive_identity.sh: PASS. nightly_pick.sh --self-test: 51/51.
  • check_story_pmat_hunt.sh: OK. Its own mutants killed 22/22.
  • check_no_pipe_into_grep_q: PASS at 60, the ceiling, which is unchanged.
  • bashrs gate: PASS, 520 files, 0 SEC/DET/IDEM errors. actionlint: the changed workflows are clean; the only notes are SC2016 infos in coverage-nightly.yml, which main has too. pv validate contracts/qwen-story-v1.yaml: valid.

Known limit (documented in the guard and the contract)

A pick rerun the next evening reruns coverage with a new created_at, so the hunt asks for the next night. The same-sha rule then reads that as not_measured, never as a wrong reading.

🤖 Generated with Claude Code

noahgift and others added 30 commits October 4, 2026 13:47
One job picks the night's candidate C (main's head at pick time) and
publishes it as refs/nightly/<night>, create-only and never forced.
Producers verify they measured C, the train and a release resolve C,
so a merge to main after the pick cannot change the night's line
(operator ask).

- scripts/lib/nightly_pick.sh: option-neutral lib (night, pick,
  resolve, verify); 0 ok, 1 RED, 2 NOT_MEASURED, 3 caller error.
- scripts/release/nightly_pick.sh: CLI, --self-test 25/25 (incl. the
  planted merge after the pick and its counter-row), --mutants 10/10.
- contracts/nightly-pick-v1.yaml: NP-INV-001..006, FALSIFY-NP-001/002.
- .github/workflows/nightly-pick.yml: report-only pick job; scheduled
  events fire hours late, so producers chain from the pick, not cron.

Nothing reads refs/nightly/* yet and nothing is blocking.

ont-delta: none — new pattern contract, no new ontology class or predicate
Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A plain push is not create-only outside refs/heads and refs/tags: it
fast-forwards an existing ref. main only moves forward, so a pick that
lost a race to an older commit moved the night's C (proved: with the
lease removed, the new race row goes RED).

- push carries --force-with-lease=refs/nightly/<night>: (expects the
  ref absent), so the first pick wins in every race.
- merge-base exit 1 is RED (not on main); any other failure is
  NOT_MEASURED, never RED.
- np_night fails by return 3 if date fails; lib header cites no ruling.
- case table 28/28: race won by an ancestor, the ref left at the
  winner, an unknown commit is not_measured. Mutants 12/12 (m11 plain
  push, m12 unknown commit as RED; m01 now drops the lease for -f).

ont-delta: none — contract text only, no new ontology class or predicate
Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
git matches an ls-remote pattern and a push destination by their
tail, so a branch named refs/heads/refs/nightly/<night> was read as
the night's C, and it swallowed the pick's push ("Everything
up-to-date", no ref created). Any other remote ref ending in
refs/nightly/<night> now makes the night ambiguous: NOT_MEASURED for
pick and resolve, never a C.

- np__read reads the exact ref name only and refuses an ambiguous one.
- the race loser's KEPT path returns 0 explicitly.
- workflow checks out full history so the on-main test is not shallow.
- case table 30/30 (decoy branch rows), mutants 13/13 (m13 the decoy
  read as C; m10 re-anchored after the explicit return).

ont-delta: none — contract text only, no new ontology class or predicate
Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Repository rulesets cover only branches and tags, so the night's ref moves
from refs/nightly/<night> to the branch refs/heads/nightly/<night>, where a
ruleset (update, deletion and non-fast-forward refused; creation allowed; no
bypass) can hold it immutable on the server. The pick still creates it once
with the expect-absent lease, pushed with the workflow's GITHUB_TOKEN, so no
workflow fires on the new branch.

Only that exact branch is C. New case rows: the rolling tag refs/tags/nightly
is never read as a pick, a pick beside it creates the branch, and a branch
named nightly (a directory/file clash) is not_measured. The ambiguity and
decoy rows are re-planted under the new namespace.

Receipts: --self-test 34/34 green; --mutants killed=13 total=13 errors=0;
pv validate valid; bashrs 0 errors on both scripts.

ont-delta: none — the contract's refs and invariant wording move to the branch namespace; no new term or relation
Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The rolling-tag rows held only as a regression guard: no mutant read the
tag. Mutant m14 widens the read so refs/tags/nightly is seen, and the case
table turns RED (17 rows). The workflow header no longer says "never
forced": the push is create-only because its lease expects the ref absent.

Receipts: --self-test 34/34 green; --mutants killed=14 total=14 errors=0;
pv validate valid; bashrs 0 errors.

ont-delta: none — one more mutant named in the falsifier's prediction; no new term or relation
Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
scripts/release/nightly_c_checkout.sh resolves the night from the
triggering pick's start time, fetches nightly/<night>, detaches onto C,
re-verifies HEAD against the ref, and exports NIGHTLY_C / NIGHTLY_NIGHT.
No pick is not_measured (2); a tree that cannot switch or a ref that
moved is RED (1). --self-test 22/22 rows, --mutants 9/9 killed.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each of the 15 producers loses its schedule and gains a workflow_run on
"Nightly pick" (completed, main). After every checkout of this repo, a
step runs scripts/release/nightly_c_checkout.sh --at <the pick run's
run_started_at>, so the producer measures the night's C pinned at
nightly/<night>, never main's head at whatever hour GitHub created a
scheduled run. A failed pick leaves no C, so the step exits 2
(not_measured) and the producer run is red.

Gates that read the trigger accept the chain:
- check_coverage_has_producers.sh R3: a producer may be scheduled OR
  chained (workflow_run, workflows: ["Nightly pick"], types: completed);
  6 new rows, including another workflow, two workflows, a requested
  type, and a commented-out chain, which stay RED.
- check_silicon_coverage.sh counts workflow_run runs next to schedule
  and workflow_dispatch; 3 new rows (chained, switch-over inside the
  lookback, real run chained) are RED on the old guard, green here.

Known limits: mutants-nightly's base is the last success's head_sha
(main at trigger), so the commits between C and that sha are skipped
once; cuda-nightly's yield marker uses the pick's head_sha, which equals
C unless the nightly ref already existed.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…sures C

scripts/release/check_producers_chain.sh reads the workflow text and is
RED when a listed producer still has a schedule (P1), lacks the
workflow_run on the name nightly-pick.yml declares, completed, main (P2),
checks this repo out without the C step next, after an optional
Preflight (P3; the C step's if must be exactly the workflow_run test, or
that test && (the checkout's own if)), names github.sha/GITHUB_SHA
without NIGHTLY_C or workflow_run.head_sha (P4), or when the list and
the chained set differ either way (P5).

Self-test 28 rows on fixtures copied from the real producers; mutants
16/16 killed, 0 errors. The real tree PASSes. Not wired into CI here:
a new gate is held for sign-off.

Limits: it reads the workflow, not the scripts a step calls; a declared
origin/main comparand (guards-nightly's SATD ceiling) is not judged.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hain

Rule 3 (a path-filtered workflow must re-check itself every night) is now
judged by scripts/lib/workflow_runs_nightly.awk, not by the SCHEDULE line of
workflow_path_filters.py. That line is still printed and nothing reads it. It
is deleted in a follow-up, because the pre-commit complexity gate rejects any
commit that touches the .py (cognitive 44 at base, 40 with the deletion, limit
25). A nightly trigger is a schedule with a non-empty cron, or a workflow_run
on "Nightly pick" with types naming completed. Without the second form, the
producers that chain from the pick would turn the check RED.

Evidence:
- scripts/tests/workflow_runs_nightly_test.sh: 22-row table PASS, mutants
  killed 9/9, errors 0.
- check_workflow_path_filters.sh self-test gains wf7 (chain, passes), wf8
  (chain from another workflow, fails) and wf9 (commented chain, fails).
- scripts/tests/workflow_path_filters_rule3_parity.sh runs the old rule 3
  (from --base) and the new one over the same fixtures plus every head and
  base workflow. The only allowed difference is old RED -> new green on the
  chained workflows.
- not_measured locally: both sides of the parity run and the check's
  self-test need python3 with yaml. They are CI-only and not wired into
  CI here.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_producers_chain.sh (rows 28 -> 37, mutants 16 -> 25, all killed):
- P3: the C step may carry only name, if, env NIGHTLY_PICK_AT and run. A
  continue-on-error, or an env line such as GIT_DIR, would swallow a failed
  switch to C and leave the job measuring main's head while green.
- P3: a quoted `uses: "actions/checkout@..."` counts as a checkout. A listed
  producer with zero checkouts of this repo is RED, and so is a job-level
  `uses:` (a reusable workflow whose checkout this file cannot see).
- P3: a checkout `if:` with `${{ }}` or a block scalar is RED, because the C
  step cannot copy it into `... && (<if>)` (`a && (${{ x }})` is always true).
- P4: github.workflow_sha and GITHUB_WORKFLOW_SHA are named too, and a
  NIGHTLY_C in a trailing comment no longer exempts the line.
- The repo-exempt row now also has a checkout of this repo (a producer with
  only an other-repo checkout is RED by the rule above).

workflow_runs_nightly.awk: a `- cron:` item at the key's own indent
(`  schedule:` then `  - cron: X`, valid YAML the old rule accepted) is a
cron, not a new key. 24 rows, mutants 10/10. The parity fixtures gain the
same shape.

workflow_path_filters_rule3_parity.sh: the default --base is 316dee2,
main before T44. Once T44 is on main, origin/main holds no old rule 3.

Mutation harnesses (this guard, nightly_c_checkout.sh, the awk test): a sed
that rejects the patch is now an ERROR. Before, it produced an empty script
whose RED rows counted as a kill. A broken patch injected into the awk test
reports ERROR.

Declined: requiring a checkout in every job of a producer. Jobs that only
post results do not touch the tree.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_producers_chain.sh (rows 37 -> 41, mutants 25 -> 29, all killed):
- A step list whose dash sits at the `steps:` indent (`steps:` then
  `- uses: ...` at the same column) is parsed as steps. Before, it flushed on
  the first item, and its checkout went unjudged.
- `repository:` exempts a checkout only when it names another repo literally.
  `${{ github.repository }}`, or this repo's name in any case, is a checkout of
  this repo and owes the C step.
- A step that uses a local action (`uses: ./...`) is RED in a listed
  producer, because a checkout inside it cannot be judged from this file.
- The stated limits now name a later run step that fetches main again (text
  only), and an `on:` that is not a block mapping at indent 2 (fails P2,
  closed).

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
check_producers_chain.sh (rows 41 -> 44, mutants 29 -> 32, all killed):
- `repository: paiml/aprender # this repo` no longer exempts a checkout of
  this repo, because a trailing comment is stripped before the comparison.
- P4 matches the SHA names case-insensitively and in index form:
  `github['sha']`, `GitHub.SHA`, `github_workflow_sha`.
- The stated limits name a flow-style step (`- {uses: ...}`), which is not
  read as a checkout.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Brings the branch onto main for its turn in the serial contract lane.

Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The serial contract lane's turn for this branch: one new contract file, so
the README CONTRACT_COUNT blocks go 1893 -> 1894, contracts/contracts.nt
gains the five nightly-pick-v1 triples, and pv-sat rewrites the witness
(census id-set hash and reasoner sha). Fixed points asserted:
pv extract contracts --check, readme_sync.sh --check, and pv lint gates
ont-consistency, refines and bindings, all 0.

Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the guard keeps LANES in step

After PR-A (#4731) the train's LANES table read every nightly producer by `^schedule$`. T44 removes those
crons: the 15 producers now start on the "Nightly pick" workflow_run. Left alone, every one of those lanes would read
not_measured for good. This lands atomically with the trigger change.

- nightly_train.sh: the 15 chained lanes read `^workflow_run$`; fleet-toolset (still on its own cron) stays
  `^schedule$`. Two rows: a chained lane is green on its workflow_run run and not_measured on a schedule run.
  Mutant m43 (any event counted). The header states the limit: a chained run is filed under main's head when the
  pick finished while its tree is the pick's commit; they differ only when a merge lands while the pick runs.
- check_producers_chain.sh P6: a listed producer whose lane is not exactly `^workflow_run$`, a lane reading
  workflow_run runs of an unlisted workflow, a missing train or no LANES table is RED. 6 rows, 5 mutants.
  The mutation harness now copies the train into its directory and first runs the unmutated copy there: without
  that, every row failed in the mutant dir and all 37 kills were vacuous.
- contracts/nightly-train-v1.yaml: description, FALSIFY-NT-001 and -002 predictions name the chain.

Receipts:
- bash scripts/release/nightly_train.sh --self-test: 59/59 rows
- bash scripts/release/nightly_train.sh --mutants: 43/43 killed
- bash scripts/release/check_producers_chain.sh: PASS on this tree
- bash scripts/release/check_producers_chain.sh --self-test: 50 rows; --mutants: 37/37 killed, errors 0
- pv validate contracts/nightly-train-v1.yaml: 0 errors, 0 warnings
- pv lint contracts --gate sigma: Pass, formal_prose 1463
- bashrs lint: 0 errors on both scripts; +1 / +7 warnings, all parser false positives inside awk text or fixture
  paths, of kinds the files already carry

ont-delta: none (prose fields of one contract; no shape or type change)

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A chained producer's run is filed under main's head at the time the pick
finished, but its tree is the night's pick. A pick dispatched again later
keeps the older C and still fires with the newer head, so the train could
credit main's head with evidence measured on an older commit.

nightly_train.sh (rows 59 -> 70, mutants 43 -> 54, all killed):
- The one GraphQL query also reads refs/heads/nightly/*. A chained lane
  counts a run only when the pick for the night that holds the run's
  creation time, [N 12:00Z, N+1 12:00Z), is C. An unread pick reads
  not_measured.
- A run created 12:00Z-17:59Z also needs the night before to be C, because
  the producer takes its night from the pick's start. The scheduled pick
  fires at 20:30Z. The header states the remaining limit.
- --from carries picks.tsv, and only dated ref names count as nights.

check_producers_chain.sh P6 (rows 50 -> 52, mutants 37 -> 39): a listed
producer with no lane is RED, and so is a second LANES assignment.

Refs #4749

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Refreshes the branch for its turn as contract-lane head.

Agent: aprender-a7f
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

# Conflicts:
#	contracts/witness/f4a1686f98d541afc73cc61d63d1a9726ef28aaee70bad35dff472cef083bf67.json
… grep -q under pipefail)

judge() tested each workflow's output with `printf '%s\n' "$out" | grep -q '^FAIL'`.
Under `set -o pipefail`, grep -q exits at the first match, the printf dies of SIGPIPE,
and the pipeline reports failure: a FAIL that was found reads as no FAIL, so the
guard can pass a broken producer. The self-test's own must-match check had the
mirror defect and went RED once in four runs on an unchanged tree.

- hasl TEXT ARGS: grep over a here-string, used by judge() and the row check.
- The must/mustnot checks in nightly_pick.sh and nightly_c_checkout.sh use a here-string too.
- Row sigpipe_fail_before_2mib: a FAIL line followed by 2 MiB must be seen.
- Mutant m40_hasl_piped puts the pipe back; the row goes RED on it (3/3 runs).

Agent: aprender-a7r
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… no longer dropped

Agent: aprender-a7r
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7r
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
np__args validated NIGHT and SHA with `printf '%s\n' "$1" | grep -qxE`,
and grep -x matches line by line: a value whose first line is well
formed ("2026-10-09<newline>x", a 40-hex sha followed by a second line)
passed the check and went on to git. The check now uses [[ =~ ]] with
^...$, which anchors the whole string.

Case table: two new rows, multiline_night_is_a_caller_error and
multiline_sha_is_a_caller_error, were RED before the fix (rc 2, want 3)
and are green after it (36/36). Mutants: m08/m09 now patch the new
check; m15/m16 put the per-line check back and are each killed by their
new row. --mutants: 16/16 killed, 0 errors.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ller error too

The per-line check also passed a value with only a trailing newline
("2026-10-09<newline>", a sha plus newline). Two rows cover it:
trailing_newline_night_is_a_caller_error and
trailing_newline_sha_is_a_caller_error. m15/m16, which restore the
per-line check, are now each killed by two rows. m15/m16 move after m14.

--self-test: 38/38 green. --mutants: 16/16 killed, 0 errors.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ck is not measured

The night table for the nightly producers: night = UTC date of (created_at - 12h) of the pick run.

- Every producer's C step now takes NIGHTLY_PICK_AT from github.event.workflow_run.created_at,
  not run_started_at. A rerun of either run keeps created_at, but run_started_at moves, so a pick
  rerun the next day used to name the next night.
- Every C step also passes NIGHTLY_PICK_CONCLUSION (github.event.workflow_run.conclusion) to
  nightly_c_checkout.sh --pick-conclusion. Anything but success is not_measured (exit 2): nothing
  is exported, the tree is left alone, and there is no fallback to main's head. A missing value
  is a caller error.
- nightly_c_checkout.sh case rows cover the boundaries: a pick created at 01:00Z, 23:30Z,
  11:58Z (producer starting after noon) and 11:59:59Z is night N; 12:00:00Z is N+1; failed and
  cancelled picks are not measured.
- New mutant m10: the conclusion is ignored.
- check_producers_chain.sh pins the new C-step text. New rows go RED when a producer reads
  run_started_at, drops or re-sources the conclusion env, or does not pass --pick-conclusion.
  New mutant m41: any conclusion source passes.

Receipts (bash only):
- nightly_c_checkout.sh --self-test 32/32, --mutants 10/10 killed
- check_producers_chain.sh on the tree PASS, --self-test 57/57, --mutants 41/41 killed

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 12:00:00Z row proved only that night N is not chosen. A row now plants
night N+1's own pick and asserts 12:00:00Z measures it (night and tree).

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…s ship together

The producers name the night from the pick run's created_at; the pick's own
whole-value check (c310) lands in the same change, so neither side ships alone.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, over c310's pick proof (#4798)

Authored fresh on a7w/4749-c310. J is the newest commit at most 6 behind the head
on which every verdict lane has a measured run; a plain run stands for its head_sha,
a chained run for the pick of its night only. A night with no pick ref falls to
c310's not_measured; a failed pick read is not_measured on every lane, no fallback.

Agent: aprender-w4798
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…iku, gpt-oss), paths scrubbed

Agent: aprender-w4798
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ned-run rules (#4798)

Agent: aprender-w4798
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
noahgift and others added 8 commits October 6, 2026 01:02
…runner can run it

build-darwin runs nightly_c_checkout.sh on the macOS runner, whose date is BSD.
`date -u -d` is GNU-only: there --at was "not a time" (rc 3) and the self-test
went 12/34, so build-darwin failed every chained night and publish-darwin was
skipped.

The lib now does the conversion itself (np_date, np_days, np_epoch:
days_from_civil and civil_from_days, round-tripped so a day the calendar
lacks is refused). nightly_c_checkout.sh and `nightly_pick.sh --at` both use
it. build-darwin runs both self-tests on the runner, on every event.

Measured on the macOS runner, with the runner's own PATH:
  before: nightly_pick 35/38, nightly_c_checkout 12/34 (rc 1)
  after:  nightly_pick 51/51, nightly_c_checkout 37/37 (rc 0)
Linux: mutants 22/22 and 10/10 killed. check_producers_chain PASS.
bashrs finding set unchanged or smaller.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The ARM64 CUDA job ran `ci_self_hosted_preflight.sh --cuda` between its checkout and
the C step. So it ran main's head's copy of the preflight, not C's, on the
night it was meant to judge C. check_producers_chain P3 allowed one
"Preflight…" step in that gap, and cuda-nightly was the only producer that
used it.

The preflight now comes right after the C step, and P3 has no gap: the C step
must be the very next step after the checkout. Row p3_preflight_between now
expects P3 to fail. Mutant m05 puts the old skip back, and that row kills it.

check_producers_chain: PASS on the tree, self-test 57 rows, mutants 41/41.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…closed

Three review findings on check_producers_chain and the pick:

C1 (false green). The pick took its night from the clock (`night`, no --at).
Producers take it from the pick run's created_at, which a rerun keeps. If
night N's pick was rerun after 12:00Z on N+1, it picked nightly/N+1 at main's
head, while every chained producer built N's pick. From 18:00Z on the train
credited that build to N+1's pick. The pick now reads its own run's
created_at (`gh api .../runs/$GITHUB_RUN_ID`, actions: read) and passes it as
--at, which takes the ISO form through the lib. New rule P7 checks that both
lines are live and exact and that no other night call exists. Five rows.
Mutants m44-m47. The old nightly-pick.yml goes RED on P7.

C2. An unreadable producer gave no FAIL line and PASS, because awk's exit
status was dropped. A non-zero judge_file exit is now a FAIL for that file.
Row p5_unreadable_producer, mutant m43.

C3. P1 missed a quoted or spaced `"schedule":` key, which GitHub runs. Two
rows, mutants m41 and m42.

check_producers_chain: PASS on the tree, self-test 65 rows, mutants 48/48.
bashrs finding set unchanged. pv validate nightly-pick-v1: 0 errors.
The aprender-contracts cargo tests were not run here (contract text only);
CI shows them.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-w4798
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…s its calls whole

nightly_train.sh: a producer chained from "Nightly pick" builds the pick of
the pick run's created_at, which a rerun keeps. The train filed the run
under the night of its own createdAt, so a pick rerun the next evening
built one pick and was judged green on another. Each chained run now
belongs to the night of the newest Nightly pick run created at or before
it. When an older pick run was updated after that one was created, the
run is not_measured, since that rerun may be what fired it. The query
reads the pick runs (createdAt, updatedAt). A missing pick workflow fails
the query, and a list that does not parse fails the pick read for every
lane.

check_producers_chain.sh P7: the live night calls went through a pipe
into grep -q. grep -q exits on the first match, the writer takes SIGPIPE,
and pipefail turned that into a pass, so a second live call ahead of
1.4 MB of exact ones passed. The calls are now read whole, then tested
with hasl.

contracts/nightly-train-v1.yaml: the next older run is taken for J, not C.
The description states the attribution by the pick run.

New rows: a rerun the next evening is credited to the old night (must be
RED); a rerun after the next pick is not_measured; a pick run not rerun
judges its own night; no pick run seen; a pick-run list kept or unread;
the query reads the pick runs or refuses without the workflow; a second
live call ahead of 1.4 MB. Mutant ids m41 are no longer duplicated.

  nightly_train --self-test 97/97, --mutants 75/75 killed
  check_producers_chain --self-test 66/66, --mutants 49/49 killed
  check_producers_chain on the tree: PASS
  pv validate contracts/nightly-train-v1.yaml: valid
  bashrs finding set unchanged or smaller on both scripts

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ll pick-run list must reach back 30 days

nightly_train.sh asked for `nightly: refs(...)` inside defaultBranchRef.
GitHub refuses that ("Field 'refs' doesn't exist on type 'Ref'"), so every
read failed and every lane printed not_measured. Fixture answers never saw
the nesting. The field now sits under repository. Run once against GitHub
with the real workflow list: no errors key, and nightly refs, history and
pick runs all came back. The old query, sent the same way, returned that
error. A new row measures the brace depth of each top-level field in the
query.

Pick-run window: the query read the 20 newest Nightly pick runs, and a
rerun of an older one was unseen, so its producers were credited to the
newest night (measured: green on A from B's builds). It now reads 100. A
chained run is not_measured when the list is full and its oldest run is
less than 30 days, GitHub's rerun limit, before the run.

The receipt states the chained rule as chainc, not nightc. The contract
description and the script header state the window rule.

New rows: a full list under 30 days is not_measured (must be RED); a full
list over 30 days judges; the query's field depths.

  nightly_train --self-test 100/100, --mutants 81/81 killed
  check_producers_chain on the tree: PASS
  pv validate contracts/nightly-train-v1.yaml: valid
  bashrs finding set unchanged or smaller

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ck chain

main changed the on: block of two producers after this branch was reviewed. A
planted quorum round decided how to take them (decoy caught by both lanes):

- mutants-nightly: the pick chain only. main's 03:00 cron is a schedule the
  producer guard forbids (P1). The pick's 20:30Z cron is dispatched 4-7h late,
  so the chained run starts near the quiet hours that cron aimed for.
- qwen-story-daily: the pick chain only. #4715's coverage fetch stays, but it
  looks the coverage run up by NIGHTLY_C: under the pick chain the triggering
  run is the pick, which has no coverage artifact. Coverage takes longer than
  this 30-min job, so the hunt reads not_measured on most nights until it gets
  its own job chained from Coverage Nightly. The checkout ref main added is
  dropped: the C step switches the tree to C.

Two guards were already red at the reviewed head, and this fixes both:
- guards-nightly maps NIGHTLY_C (written to GITHUB_ENV by the C step) into the
  two steps that read it, so check_workflow_env_defined.sh sees it defined.
- nightly_c_checkout.sh's fixtures use plain mktemp -d (still TMPDIR), which
  clears the bashrs gate's three SEC010 findings.

Refs #4749, #4798

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ightly

Under the pick chain the story and coverage start together; coverage takes
60-70 min and the story job 30, so the story's hunts read not_measured on
most nights. The hunt now runs in qwen-hunt-nightly, chained from Coverage
Nightly, on that run's own coverage-json artifact (matched on coverage.sha,
never head_sha). The story keeps its hunts behind PMAT_HUNT, default 0.

- lib_story_pmat.sh: STORY_HUNTS, one table of the eight beats' hunts;
  qwen-story.sh runs line N via story_hunt N, story_pmat_hunt.sh runs all.
- check_producers_chain.sh: HOPS. A hop chains from its listed upstream's
  name:, its C step reads the upstream run; an unlisted file chained from a
  listed producer is P5 RED (the old guard passed it vacuously); a hop
  counts as listed for P6. 8 rows, 9 mutants (74 rows, 58/58 killed).
- nightly_train.sh: the qwen-hunt lane.
- mutants-nightly.yml: the timeout comment states the chained window.
- contracts: FALSIFY-QWEN-STORY-004 reads story_hunt; the pick's clock
  domain names the one-hop case and its rerun limit.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 6, 2026

Copy link
Copy Markdown

§13.11 rung 1 — quorum shadow verdict

S13-SHADOW pr=4881 head=31873feb1f71060de6ca90aad50049a3db0def02 verdict=REFUSE class=Q1 arm_rc=1

Shadow mode: this records a verdict and merges nothing. A refusal
to arm is not a block (§13 adds zero rows to §7) — the pull request is
exactly as green as it was.

noahgift and others added 10 commits October 6, 2026 14:15
…th main

Two required guards were red on the PR's merge with main:

- check_no_pipe_into_grep_q.sh counted 63 sites against its ceiling of 60.
  All three new ones were mutant-table lines. nightly_pick.sh m15/m16 now
  feed grep a here-string; each still checks per line, so each still fails
  the self-test. check_producers_chain.sh m48 put back the piped grep -q on
  purpose. A here-string there is the same as hasl(), so the mutant could
  never be killed. It is dropped: in live code, the grep-q guard itself
  catches that piped form.
- bashrs DET002 at nightly_train.sh:131, `date -u -d "$n + 1 day"`. The
  next day is now pure arithmetic in next_day(), so date(1) is gone. It
  matched date(1) on every day from 1999-12-25 to 2101-03-05 (36960 days)
  and refuses the impossible dates date(1) refuses. A malformed name made
  date(1) answer with tomorrow: a clock read. next_day refuses it, and the
  caller's case pattern already filtered it out.

The ceiling stays at 60.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…hunts bound to their beat

The producers-chain guard now reads every entry of a workflow_run's
workflows: list, in flow, scalar or block form, and fails P2 on a form it
cannot read. An unlisted workflow chaining from the pick, a listed producer
or a hop, at any position in its list, fails P5. A hop's own name counts as
an upstream, so a hop of a hop is caught.

FALSIFY-QWEN-STORY-004 and check_story_pmat_hunt.sh now require each
beatN_*() to end with story_hunt N, with no hunt anywhere else.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Main's #4868 gave the models lane a producer (models-nightly.yml), so a
judged commit now needs a models run too. The moved-head fixture had none,
found no judged commit and fell back to the head, so its self-test row went
red on the merge. The fixture now carries a models run on the judged commit.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
derive_identity R3 refuses a numeric comparison against a literal of two
or more digits. next_day's month wrap now reads months=12, and the
self-test's dupx reads CHAINED=201. Self-test 100/100, mutants 81/81.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…atch

- check_producers_chain.sh reads on: keys only at indent 2. Keys at another
  indent are now unreadable: workflow_run there is P2, schedule there is P1.
  New rows: p2_unlisted_on_indent4, p2_listed_on_indent4,
  p1_schedule_on_indent4, p7_pick_night_commented, p7_pick_night_inside_line.
  New mutant m76 drops -x from the P7 calls check. 97 rows, 72/72 killed.
- check_story_pmat_hunt.sh and FALSIFY-QWEN-STORY-004 give 0 when a beatN_
  function is defined twice or in another form, because bash runs the last
  definition. Five fixture forms; mutants 22/22 killed.

Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent: aprender-a7w
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

T44: pmat hunt in its own job chained from Coverage Nightly, so it reads the night's coverage

1 participant