Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 8 additions & 54 deletions contracts/release-ready-v1.yaml

Large diffs are not rendered by default.

18 changes: 18 additions & 0 deletions docs/roadmaps/entries/PMAT-5174.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
- id: PMAT-5174
github_issue: 5174
item_type: task
title: 'Release: decide where the R5 dogfood receipt belongs on the publish path'
status: planned
priority: high
assigned_to: null
created: 2026-10-12T02:43:24Z
updated: 2026-10-12T02:43:24Z
spec: null
acceptance_criteria: []
phases: []
subtasks: []
estimated_effort: null
labels:
- kind:code
notes: null
epic: 3998
18 changes: 18 additions & 0 deletions docs/roadmaps/roadmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24753,3 +24753,21 @@ Not done, pending the ruling: moving the 31 fixture files to an obviously synthe
- kind:code
notes: null
epic: 3998
- id: PMAT-5174
github_issue: 5174
item_type: task
title: 'Release: decide where the R5 dogfood receipt belongs on the publish path'
status: planned
priority: high
assigned_to: null
created: 2026-10-12T02:43:24Z
updated: 2026-10-12T02:43:24Z
spec: null
acceptance_criteria: []
phases: []
subtasks: []
estimated_effort: null
labels:
- kind:code
notes: null
epic: 3998
28 changes: 25 additions & 3 deletions scripts/check_publish_preflight.sh
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
# R5 the newest dogfood receipt (`.dogfood/receipt-*.json`, written by
# scripts/dogfood.sh) says `verdict: GO` for THIS commit and THIS
# version. A stale receipt, a NO-GO, or no receipt at all refuses.
# Under the STANDING RELEASE POLICY (as R8 below) R5 is not run (#5174): the pre-publish
# dogfood never went green on a release and takes ~55 min, so it is not a release gate; it is
# a nightly lane, ticketed on red. `--receipt-only` still judges every receipt it is given.
# R7 the model matrix (#3717, #3712): the per-host receipts COMMITTED in this tree for this
# version (evidence/dogfood/models/<version>/, put there by the bump, #3708) are judged by
# scripts/check_model_ladder.sh -- the same judge autopilot's T-1 `models` step runs on its
Expand Down Expand Up @@ -135,6 +138,13 @@ newest_receipt() { # dir -> path of the newest receipt-*.json, or nothing
# rule_r5 root head version -> prints its row; 0 accepted, 1 refused
rule_r5() {
local root="$1" head="$2" version="$3" rdir receipt verdict rcommit rversion rphase rdeferred ropen bad_defer g
# The STANDING RELEASE POLICY covers this version: R5 is not run at all and no receipt is read (#5174).
# The pre-publish dogfood is a nightly lane; it returns here only as a GATE the operator rules in.
if [ "${POL_APPLIES:-0}" = 1 ]; then
echo "ok R5 STANDING RELEASE POLICY covers $version: the pre-publish dogfood was not run and no receipt was read; CRUX smoke (R7) is the release gate"
R5_SCOPED=1
return 0
fi
rdir="${PUBLISH_PREFLIGHT_RECEIPT_DIR:-$root/.dogfood}"
receipt="$(newest_receipt "$rdir")"
if [ -z "$receipt" ]; then
Expand Down Expand Up @@ -447,6 +457,7 @@ gate() {
local root="${PUBLISH_PREFLIGHT_ROOT:-}" release_ref r4_ref r4_on
local fails=0 status version tags head
R8_SCOPED=""
R5_SCOPED=""
for t in git cargo python3; do
command -v "$t" >/dev/null 2>&1 || die_env "$t is not on PATH"
done
Expand Down Expand Up @@ -482,7 +493,7 @@ gate() {
local prc=0
policy_ladder "$root" "$version" || prc=$?
case "$prc" in
0) [ "$POL_APPLIES" != 1 ] || echo "POLICY: crux-smoke -- the standing release policy in contracts/model-capability-ladder-v1.yaml covers $version: CRUX smoke under R7 is the release gate, R8 is not run, the larger ladder rows are nightly" ;;
0) [ "$POL_APPLIES" != 1 ] || echo "POLICY: crux-smoke -- the standing release policy in contracts/model-capability-ladder-v1.yaml covers $version: CRUX smoke under R7 is the release gate, R5 and R8 are not run, the larger ladder rows are nightly" ;;
*) echo "FAIL R7/R8 the standing release policy cannot be applied to $version, so neither the scope nor the full gate can be chosen: $POL_WHY"
fails=1; pol_bad=1 ;;
esac
Expand Down Expand Up @@ -565,9 +576,9 @@ gate() {
return 1
fi
if [ -n "${SCOPE:-}" ]; then
echo "PASS $PROG: clean, versioned, tagged, on $release_ref, dogfood GO, OPERATOR EMERGENCY SCOPE $SCOPE satisfied (the model matrix was NOT the gate${R8_SCOPED:+; release-readiness was NOT the gate})"
echo "PASS $PROG: clean, versioned, tagged, on $release_ref, $([ -n "${R5_SCOPED:-}" ] && echo "the dogfood was NOT the gate" || echo "dogfood GO"), OPERATOR EMERGENCY SCOPE $SCOPE satisfied (the model matrix was NOT the gate${R8_SCOPED:+; release-readiness was NOT the gate})"
else
echo "PASS $PROG: clean, versioned, tagged, on $release_ref, dogfood GO, model matrix green"
echo "PASS $PROG: clean, versioned, tagged, on $release_ref, $([ -n "${R5_SCOPED:-}" ] && echo "the dogfood was NOT the gate" || echo "dogfood GO"), model matrix green"
fi
return 0
}
Expand Down Expand Up @@ -618,6 +629,9 @@ receipt_gate() {
return 1
fi
echo "ok R2 version $version (cargo metadata, root manifest)"
# No policy is read here: --receipt-only judges the receipt it is given, whatever the release (the
# nightly negative control asks it to refuse a nightly receipt).
POL_APPLIES=0
if ! rule_r5 "$root" "$head" "$version"; then
echo "REFUSE $PROG --receipt-only: the T-4 publish gate would refuse this receipt (R5)."
return 1
Expand Down Expand Up @@ -1021,11 +1035,19 @@ FXREADY
FX_SCOPE_RC=1 row policy_scope_red_refuses 1 "FAIL R7 OPERATOR EMERGENCY SCOPE crux-smoke NOT satisfied" "$d"
FX_READINESS_RC=1 row policy_r8_is_not_the_gate 0 "release-readiness was NOT the gate" "$d"
FX_READINESS_RC=1 row policy_r8_is_not_run 0 "ok R8 STANDING RELEASE POLICY covers 1.2.3: release-readiness was not run" "$d"
# #5174: under the policy R5 reads no receipt -- a NO-GO one, or none at all, does not refuse --
# and --receipt-only still refuses the same NO-GO receipt.
write_receipt "$d" NO-GO "$(git -C "$d" rev-parse HEAD)" 1.2.3
row policy_r5_is_not_run 0 "ok R5 STANDING RELEASE POLICY covers 1.2.3: the pre-publish dogfood was not run" "$d"
row policy_pass_names_dogfood_not_gate 0 "the dogfood was NOT the gate" "$d"
POL_APPLIES=1 row policy_receipt_only_still_judges 1 "FAIL R5 dogfood receipt" "$d" receipt_gate
d="$tmp/pol-rc"; build_repo "$d"; record_policy "$d" 1.2.3
row policy_since_equal_covers 0 "POLICY: crux-smoke" "$d"
d="$tmp/pol-later"; build_repo "$d"; record_policy "$d" 1.2.4
FX_READINESS_RC=1 row policy_later_r8_enforced 1 "FAIL R8 the release-readiness wrapper exited 1" "$d"
FX_LADDER_RC=1 row policy_later_r7_is_matrix 1 "FAIL R7 model matrix NOT green" "$d"
write_receipt "$d" NO-GO "$(git -C "$d" rev-parse HEAD)" 1.2.3
row policy_later_r5_enforced 1 "FAIL R5 dogfood receipt" "$d"
d="$tmp/pol-dup"; build_repo "$d"; record_policy "$d" 1.2.0 1.2.3
row policy_and_record_refuse 1 "one release takes one ruling" "$d"
FX_READINESS_RC=1 row policy_and_record_no_scope 1 "FAIL R8 the release-readiness wrapper exited 1" "$d"
Expand Down
65 changes: 33 additions & 32 deletions scripts/check_release_t1_lanes_joined.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@
# overlap two 3 s lanes -> rc 0 in under 5 s (in series they need 6)
# interrupt TERM to the run -> rc 1 within seconds, nothing after the join, dogfood's child gone
# self-red models red; dogfood, signalled, exits 1 by itself -> dogfood RED (not STOPPED), both named
# and under the standing release policy (D2, #4930), where dogfood's ladder gate reads models' receipts:
# policy-order both green -> dogfood starts no earlier than models ends
# policy-models-red models red -> rc 1, dogfood NOT-RUN and never started
# policy-solo dogfood alone -> not held, rc 0
# and, on the autopilot text itself, that t1_dogfood exports MODEL_LADDER_CRUX_DIR and CRUX_CERT under
# the policy (the pair the T-4 preflight reads), that dogfood builds into its own target dir under
# and under the standing release policy, where the pre-publish dogfood is not run (#5174):
# policy-both both selected -> rc 0, models alone runs (one GO row), dogfood never started,
# one NOT-RUN line
# policy-models-red models red -> rc 1, dogfood never started
# policy-solo dogfood alone -> rc 0, no lane started, the NOT-RUN line
# and, on the autopilot text itself, that dogfood builds into its own target dir under
# $REPO_ROOT/target while models keeps CARGO_TARGET_DIR (readiness reads the apr models built), and
# that scripts/check_model_parity.sh runs every apr parity under the ladder's GPU lock (dogfood's C14
# parity and the ladder now share the GPU).
Expand Down Expand Up @@ -84,6 +84,7 @@ case_run() {
verdict() { awk -F'\t' -v s="$2" '$1==s {print $5}' "$TMP/$1/t1-steps.tsv" 2>/dev/null; }
col() { awk -F'\t' -v s="$2" -v c="$3" '$1==s {print $c}' "$TMP/$1/t1-steps.tsv" 2>/dev/null; }
ran() { [ -f "$TMP/$1/dogfood-ran" ]; }
notrun() { [ "$(grep -c 'STEP dogfood NOT-RUN: the standing release policy' "$TMP/$1/STATUS" 2>/dev/null)" = 1 ]; }
rows() { tail -n +2 "$TMP/$1/t1-steps.tsv" 2>/dev/null | wc -l; }
after() { grep -q 'AFTER-JOIN' "$TMP/$1/STATUS" 2>/dev/null; }
child_gone() { local c; c=$(cat "$TMP/$1/dogfood-child" 2>/dev/null); [ -n "$c" ] && ! kill -0 "$c" 2>/dev/null; }
Expand Down Expand Up @@ -122,20 +123,17 @@ table() {
DT=1 case_run "$j" "$t-self" "dogfood models" 0 0 1 1
[ "$C_RC" = 1 ] && [ "$(verdict "$t-self" dogfood)" = RED ] && grep -q 'STOP .*models dogfood RED' "$TMP/$t-self/STATUS" \
|| { echo "self-red: rc=$C_RC dogfood=$(verdict "$t-self" dogfood) (want dogfood RED: it exited 1 by itself, not by the signal)"; return 1; }
# D2 (P7 WIRE): under the standing release policy the dogfood's ladder gate reads the CRUX receipts
# the models lane writes, so dogfood starts only once models is GO.
AP_POLICY=1 case_run "$j" "$t-p-order" "dogfood models" 1 0 2 0
[ "$C_RC" = 0 ] && after "$t-p-order" \
&& [ "$(verdict "$t-p-order" dogfood)$(verdict "$t-p-order" models)" = GOGO ] \
&& [ "$(col "$t-p-order" dogfood 2)" -ge "$(col "$t-p-order" models 3)" ] \
|| { echo "policy-order: rc=$C_RC dogfood start=$(col "$t-p-order" dogfood 2) models end=$(col "$t-p-order" models 3) (want rc 0, 2 GO, dogfood started after models ended)"; return 1; }
# #5174: under the standing release policy the pre-publish dogfood is not run -- models runs alone.
AP_POLICY=1 case_run "$j" "$t-p-both" "dogfood models" 1 0 1 0
[ "$C_RC" = 0 ] && after "$t-p-both" && ! ran "$t-p-both" && [ "$(rows "$t-p-both")" = 1 ] \
&& [ "$(verdict "$t-p-both" models)" = GO ] && notrun "$t-p-both" \
|| { echo "policy-both: rc=$C_RC rows=$(rows "$t-p-both") models=$(verdict "$t-p-both" models) (want rc 0, models GO alone, dogfood never started, one NOT-RUN line)"; return 1; }
AP_POLICY=1 case_run "$j" "$t-p-mred" "dogfood models" 1 0 1 1
[ "$C_RC" = 1 ] && ! after "$t-p-mred" && ! ran "$t-p-mred" && [ "$(verdict "$t-p-mred" dogfood)" = NOT-RUN ] \
&& [ "$(verdict "$t-p-mred" models)" = RED ] \
|| { echo "policy-models-red: rc=$C_RC dogfood=$(verdict "$t-p-mred" dogfood) (want rc 1, models RED, dogfood NOT-RUN and never started)"; return 1; }
[ "$C_RC" = 1 ] && ! after "$t-p-mred" && ! ran "$t-p-mred" && [ "$(verdict "$t-p-mred" models)" = RED ] \
|| { echo "policy-models-red: rc=$C_RC models=$(verdict "$t-p-mred" models) (want rc 1, models RED, dogfood never started)"; return 1; }
AP_POLICY=1 case_run "$j" "$t-p-solo" "dogfood" 1 0 0 0
[ "$C_RC" = 0 ] && ran "$t-p-solo" && [ "$(rows "$t-p-solo")" = 1 ] \
|| { echo "policy-solo: rc=$C_RC rows=$(rows "$t-p-solo") (want rc 0: dogfood alone is not held)"; return 1; }
[ "$C_RC" = 0 ] && after "$t-p-solo" && ! ran "$t-p-solo" && [ "$(rows "$t-p-solo")" = 0 ] && notrun "$t-p-solo" \
|| { echo "policy-solo: rc=$C_RC rows=$(rows "$t-p-solo") (want rc 0, no lane started, the NOT-RUN line)"; return 1; }
return 0
}

Expand All @@ -156,25 +154,25 @@ dirs() {
[ -z "$m" ] || { echo "models moved off CARGO_TARGET_DIR, which readiness reads: $m"; return 1; }
}

# crux AUTOPILOT -> 0 when t1_dogfood points the ladder gate at models' receipts under the policy
crux() {
local e
e=$(awk '/^t1_dogfood\(\) \{/{p=1} p&&/MODEL_LADDER_CRUX_DIR=/{print; exit} p&&/^\}/{exit}' "$1")
case "$e" in
*'[ "$AP_POLICY" != 1 ] || export MODEL_LADDER_CRUX_DIR="$AP/models-t1" CRUX_CERT="$WT/evidence/crux/$V/prompt-certification.json"'*) ;;
*) echo "t1_dogfood does not export the models lane's CRUX receipts under the policy: '$e'"; return 1 ;;
esac
# nogo AUTOPILOT -> 0 when every line that can print "dogfood GO" swaps it out under the policy (#5174):
# the dogfood is not run then, so a receipt that names a dogfood GO would be a green nothing measured.
# The post-publish dogfood still runs after the publish, so its GO is struck out before the match.
nogo() {
local bad
bad=$(sed 's/post-publish dogfood GO//g' "$1" | grep -n 'dogfood GO' | grep -v '^[0-9]*:[[:space:]]*#' \
| grep -vF '[ "$AP_POLICY" != 1 ] || { AP_DF_RECEIPT="dogfood not run (policy)"; AP_DF_CLOSE="pre-publish dogfood not run' || true)
[ -z "$bad" ] || { echo "a line prints dogfood GO with no policy swap: $(printf '%s\n' "$bad" | head -n 1 | cut -c1-100)"; return 1; }
}

# check AUTOPILOT TAG -> 0 when the join and the dirs hold
check() {
awk '/^# The join\./{p=1} p{print} p&&/^fi$/{exit}' "$1" > "$TMP/$2.join"
grep -q 'wait -n' "$TMP/$2.join" || { echo "no join block (\"# The join.\" .. fi with wait -n)"; return 1; }
dirs "$1" && crux "$1" && locked "${3:-$PARITY}" && table "$TMP/$2.join" "$2"
dirs "$1" && nogo "$1" && locked "${3:-$PARITY}" && table "$TMP/$2.join" "$2"
}

bad=0
if why=$(check "$AUTOPILOT" real); then echo "ok the join holds (12 cases), dogfood reads models' CRUX receipts under the policy, dogfood's target dir is its own, parity takes the GPU lock"
if why=$(check "$AUTOPILOT" real); then echo "ok the join holds (12 cases), the dogfood lane is not started under the policy and no line claims a dogfood GO then, dogfood's target dir is its own, parity takes the GPU lock"
else echo "FAIL the autopilot's T-1 lanes: $why"; bad=1; fi

# The mutants run whatever the real tree did, so report mode prints every line before its verdict.
Expand All @@ -195,15 +193,18 @@ mutant first-red 's/t1_red="\${t1_red:+\$t1_red }\$s"/t1_red=${t1_red:-$s}/'
mutant no-trap "/^ trap 'for p in/d"
mutant shared-dogfood '/^ export CARGO_TARGET_DIR="\$REPO_ROOT\/target\/t1-dogfood"$/d'
mutant stopped-any-rc 's/ \&\& \[ "\$rc" -eq "\$t1_term_rc" \]; then v=STOPPED/; then v=STOPPED/'
mutant no-hold 's/ || t1_held=dogfood ;; esac$/ || : ;; esac/'
mutant held-after-red 's/^ if \[ "\$v" = GO \] && \[ -z "\$t1_red" \]; then$/ if :; then/'
mutant no-crux-env '/export MODEL_LADDER_CRUX_DIR="\$AP\/models-t1"/d'
mutant policy-runs-dogfood 's/ \&\& \[ "\$s:\$AP_POLICY" != dogfood:1 \]//'
mutant policy-drops-every-lane 's/\[ "\$s:\$AP_POLICY" != dogfood:1 \]/[ "$AP_POLICY" != 1 ]/'
mutant no-not-run-line '/^\[ "\$AP_POLICY" != 1 \] || ! run_step dogfood || say /d'
mutant dryrun-claims-go 's/receipts: \$AP_DF_RECEIPT, tag/receipts: dogfood GO, tag/'
mutant close-claims-go 's/Receipts: \$AP_DF_CLOSE, all/Receipts: pre-publish dogfood GO, all/'
mutant no-policy-swap 's/; \[ "\$AP_POLICY" != 1 \] || { AP_DF_RECEIPT="dogfood not run (policy)".*$//'
nm=$((nm + 1))
sed -e 's/flock -E 75 -w "\${MODEL_LADDER_LOCK_WAIT:-1800}" "\${MODEL_LADDER_GPU_LOCK:-\/tmp\/apr-gpu.lock}"/env/' "$PARITY" > "$TMP/m-parity.sh"
if cmp -s "$PARITY" "$TMP/m-parity.sh"; then echo "FAIL mutant parity-unlocked did not apply (anchor moved)"; fails=$((fails + 1))
elif why=$(check "$AUTOPILOT" m-parity "$TMP/m-parity.sh"); then echo "FAIL mutant parity-unlocked survived"; fails=$((fails + 1))
else echo "ok mutant parity-unlocked killed ($why)"; fi
[ "$fails" -eq 0 ] || { echo "FAIL $fails of $nm mutant(s)"; finish 1; }
[ "$bad" = 0 ] || finish 1
echo "PASS 12 case(s) + CRUX env + target dirs + parity lock, $nm mutant(s) killed: dogfood and models start together (dogfood held for models under the policy), join before readiness, and a red in either stops the pass"
echo "PASS 12 case(s) + target dirs + no dogfood GO under the policy + parity lock, $nm mutant(s) killed: dogfood and models start together (under the policy models runs alone, #5174), join before readiness, and a red in either stops the pass"
finish 0
Loading
Loading