--- ../v9-exercises/r10/staged-r10-queue-guard.sh 2026-09-12 16:05:43.046285800 -0700 +++ fp-driver-d2.sh 2026-09-12 19:36:20.983438300 -0700 @@ -1,230 +1,124 @@ #!/bin/bash # ============================================================================= -# FIELD DRIVER v5 r10 — subject 85f84d73. FOR SOURCE REVIEW ONLY. -# NOT RUN. NO BUILD GRANT. NO FIELD GRANT. NO ELEVATION GRANT. -# todlando 2026-09-12; r5 by hertz 2026-09-12. -# -# r6 = r5 (0891059048...) plus the repairs below. r5 is PRESERVED beside this file and -# is not edited. r6 CHANGES, on top of r5: -# A. THE ENFORCEMENT FACE STRING WAS STALE and could only ever count zero. The -# repaired arm prints 'ActiveStore enforcement codes are' (windows.rs:826); the -# classifier still grepped the pre-repair 'ActiveStore enforcement is'. MEASURED -# at the subject over crates/: 0 occurrences of the old string, 1 of the new, -# and 13 of the 14 face strings resolve nonzero -- so the single zero is real -# and not a dead predicate. A zero there did not merely lose a count: precedence -# fell through to unverified-generic, which asserted ABSENT-or-MISSPELLED -- the -# OPPOSITE of what an enforcement Err proves, on the very outcome the repair -# exists to produce, at exit 0. -# B. ENFORCEMENT_REPRESENTATION_FAULT (5 throw sites in the query script at this -# subject) was not counted at all. It is now its own count and its own face: -# the host could not TRANSPORT the codes, which is a different finding from the -# codes being WRONG, and neither is the pair being absent or misspelled. -# C. A WRAPPER NO LONGER ERASES ITS CAUSE. The after-write wrappers and the specific -# cause are computed separately and reported as wrapper/cause, so a transport -# fault inside an after-write wrapper stays distinguishable from a code refusal -# inside one. Every count is still reported, unchanged. -# D. LAN_FIREWALL_CLEAN IS BOUND TO ITS INVOCATION CONTEXT. The token has TWO print -# sites -- serveverb.rs:379 on the stop path and :530 inside -# reconcile_lan_firewall -- so a count alone cannot attribute it to either. -# E. The generic verdict no longer claims more than it proves. -# F. BUILD PROVENANCE (doyle, on todlando's finding). The pre-build executable hash -# and mtime are captured as EVIDENCE, the subject identity is re-read at the -# boundary either side of the producer, and S5 REJECTS the known pre-repair -# artifact by hash. Deliberately NOT encoded: any rule that identical bytes -# prove no build, or that changed bytes prove the intended source. Neither is -# true, and PE nondeterminism is not a correctness invariant. -# -# r5 CHANGES, against the accepted artifact-reuse revision d3891b09 (preserved): -# 1. SUBJECT moves from 53d625cd to 85f84d73 (blob c28874ef -> 848a23fe). W is -# unchanged: .worktrees/304-w2-repr is already detached at 85f84d73. -# 2. FRESH run and home paths -- SP moves to a new bundle root, so BIN, RUN_ROOT -# and H all move with it and no prior run's evidence or home is reachable. -# 3. S3 returns to --build-current; the --artifact reuse of a prebuilt executable -# is dropped. ONE release build, produced by the rollout verb itself. -# -# WHAT THE SUBJECT MOVE FALSIFIES, corrected below rather than carried forward: -# - The PRODUCT CONTRACT block was read at 53d625cd. Its bootstrap_firewall.rs -# anchors still hold at 85f84d73 (verified: mutation_permitted :19, the subject -# row's format string :104, outcome() :120). Its windows.rs anchors have MOVED -- -# see the note in that block. They are DOCUMENTATION: this driver matches on -# string literals, never on source line numbers. -# - d1_render.py's live exercise was against blob c28874ef, NOT 848a23fe. -# - The QUERY const is no longer byte-identical across the shas it named. -# Each is corrected at its own site. Exercise status at r6, stated exactly: -# - d1_render.py IS NOW EXERCISED against 848a23fe by a source-only render. -# - The revised CLASSIFIER is exercised by captured-output fixtures -- no host, no -# product invocation; see classifier-control.sh and its receipt beside this file. -# - Everything else remains UNEXERCISED: no cargo, no generated PowerShell, no host -# probe, no field run, no elevation. -# -# v4 was rejected on ten defects (doyle), on two MEASURED driver-control failures -# (hertz, stub arms), and on doyle's corrections to those findings. v5 is written -# against all of them. Where v4 stated something I had not read, v5 cites the file -# and line I read it in. -# -# WHAT CHANGED, and the defect each change answers: -# -# D1..D10 = doyle's ten. F1..F10 = hertz's source review. C = doyle's corrections. -# -# D1/F1/C THREE SEPARATE RESOURCE STATES, each marked BEFORE the dispatch that -# could create it, each persisted as a FILE so a SIGKILL still leaves the -# marker: pool_acquired, listener_may_exist, fw_mutation_may_have_occurred. -# Cleanup acts only on states this run actually marked. hertz MEASURED v4 -# dispatching two product commands and a pool-release after a capacity -# failure that created nothing; none of those can be reached here. -# Per C: mutation-may-have-occurred is marked BEFORE the elevated setup is -# requested, not after it succeeds — a REFUSED setup can leave rules behind. -# D1 The ORIGINAL failure is preserved: cleanup never overwrites the exit code -# or the first recorded failure, and cleanup's own failures go to their own -# file (cleanup-failures.txt) so they cannot be read as the finding. -# D2/C NO LINE CLAIMS ELEVATION. The driver ASSERTS it is unelevated (S0a) and -# refuses to continue if it is. Every elevated action is an explicit HANDOFF -# to liam: a request file with a nonce, then a receipt, and then the receipt -# is VERIFIED BY MY OWN CENSUS. A receipt is a claim; the census is evidence. -# D3 CI axis is spt-bs-core (the CODE repo), job-level, and its exit is GATED. -# `gh run list` REJECTS --json jobs, and `gh run view --json status` freezes, -# so the list carries status/conclusion and any non-terminal run is then read -# with `view --json jobs`. Refreshed after the build as well as before it. -# D4 Fail closed everywhere. Every producer's exit is read in a guarded branch. -# A git failure can no longer read as a clean tree: the exit is checked -# BEFORE the emptiness of its output is interpreted. -# D5/C The seed is bound to ITS OWN keygen invocation. Any inherited seed is -# explicitly discarded; exactly one public_hex and one seed_hex are parsed -# from that invocation; the seed is exported from what was parsed, so the -# signer's key IS the generated key by construction. The value is never -# echoed, never recorded, and lives only under a 0700 dir that cleanup reaps. -# D6 THREE-WAY provenance: the executable's measured sha256, the staged -# artifact's measured sha256, and the artifact_sha256 inside the SIGNED -# metadata must all be equal. -# D7 Every trial enforces its ARM's pair state before AND after, the expected -# PORT and BINDER (listener path == the built executable), a successful -# listener stop with the per-arm stop signature, and a VALID CPU capture. -# D8 THE VERDICT STRINGS ARE THE PRODUCT'S, READ AT THIS SHA. v4 matched -# LAN_FIREWALL_VERIFIED and "LAN admission verified"; NEITHER EXISTS in -# crates/. See the CONTRACT block below for what does. -# D9/F8 D1 runs on setup REJECTION too, BEFORE any teardown is requested, and a -# failed D1 can no longer finish at exit 0 calling the run complete. -# D10 A pre-existing evidence dir or isolated home is REJECTED, never truncated. -# F2/C Signals terminate normal execution and enter state-aware cleanup EXACTLY -# ONCE. No trial resumes after a signal. SIGKILL remains a residual and is -# named as one, with the state markers on disk as the recovery instruction. -# F3 The 5470 field comparison brackets the ELEVATED actions too, and a FINAL -# post-cleanup comparison runs. v4 bracketed only the low-risk population. -# F4/F5 The evidence dir is per-run and timestamped, so no assertion can be -# satisfied by a PRIOR run's row and no rerun destroys the record it should -# be compared against. Nothing is truncated. -# F6 diff is read as 0 same / 1 changed / >=2 INSTRUMENT FAILURE. An unreadable -# snapshot must not be announced as "5470 CHANGED". -# F7 The capacity floor is read immediately before EVERY producer, and the hard -# stop is evaluated, not just the admission floor. -# F9 refusal faces are COUNTED, ALL of them reported, and the verdict taken by a -# written-down precedence — not by whichever grep happens to run last. -# F10/C Instruments live in a separate dir from results, AND every instrument's -# sha256 is written into the evidence dir, because placement is not provenance. -# hertz Q3 Occurrences are counted with grep -o, not grep -c: two subject records on -# one line would count as one line and defeat the >1 guard. -# C [ -f ] on a file run_cmd already created cannot fail, and -s is NOT proof of -# execution. Launch/capture failures get their OWN status; an empty stderr is -# classified as a MISSING-ROW OUTCOME, which is a measurement, not an error. +# D2 DRIVER — #297 bounded out-of-band capture, run BY THE EXISTING FIELD DRIVER. +# hertz 2026-09-13. FOR SOURCE REVIEW. NOT RUN IN THE FIELD. +# NO BUILD GRANT. NO FIELD GRANT. NO ELEVATION GRANT. NO RESIDUAL-PID GRANT. +# +# PROVENANCE: this is the FROZEN r10 driver, staged-r10-queue-guard.sh, sha256 +# a78f4ba6ed5491ccb38d26f8a3fe4f1a7a9f23296d85a133511b1bf9396d1fbf (todlando; frozen by +# doyle Y2B7UUAS, R10-FROZEN.sha256 re-verified here), with the r10 WORKLOAD REMOVED and the +# #297 D2 capture points ADDED. The exact diff against that file is the deliverable beside +# this one. Every retained block is retained BYTE-FOR-BYTE, so the diff shows only what D2 +# changed. r10 is the base and not v9 (a9510e1e) deliberately: v9 predates the accepted +# binder-path, classifier, cleanup-exit and queue-guard repairs, and starting from it would +# have silently reintroduced four defects that were already paid for. +# +# WHY THIS FILE AND NOT A WRAPPER (doyle, 2026-09-13). I first built a separate wrapper that +# sequenced the capture points beside this driver, and exercised the wrapper until it went +# green. That was a parallel orchestrator standing next to machinery that already had +# handoff, state-marking and exactly-once cleanup — a weaker copy of a stricter check, which +# is worse than no copy because it arrives carrying evidence. The wrapper and its receipts +# are PRESERVED as superseded evidence (d2_wrapper.ps1, d2_wrapper_check.ps1, +# receipt-wrapper-check-wps51.txt); they are kept, not tended, and nothing here calls them. +# +# WHAT WAS REMOVED — the BUILD AND TIMING WORKLOAD, each named with its reason, because a +# silently dropped gate is a defect: +# - debug-keygen / debug-pin / debug-rollout --build-current / debug-mark-applied, the +# subject_boundary pair that bracketed the producer, and the THREE-WAY PROVENANCE check. +# D2 reuses the executable r10 already built and receipted; there is no new artifact to +# sign, stage or agree with. The executable is instead PINNED BY EXACT HASH (S1), and +# that hash is stated in the elevated request as well, because a clean source tree does +# not identify reused executable bytes. +# - pool-claim / pool-release. Nothing here runs cargo, so no build pool is claimed; +# claiming one would write a lane identity this run does not have. +# - capacity_gate. It exists ahead of PRODUCERS (F7). With no producer, a disk floor gates +# nothing. +# - cpubracket.ps1, trial(), both arms, expect_pair's a/b vocabulary, completion_verdict +# and populated_timing_report. There is no timed workload: the pair is created once, +# read three times, and torn down. Two of r10's three "what a green establishes" ceiling +# clauses went with them, because they were about trials and timings this run never +# takes. +# +# WHAT WAS KEPT, AND WHY IT IS NOT WORKLOAD: +# - THE STATUS-FILTERED CI AXIS and the ANCESTRY-AUTHENTICATED BOX CENSUS, at preflight and +# again immediately before the elevated leg. This box is shared with a self-hosted +# runner and a merge-push re-occupies it; admission to a shared host is not a property of +# the workload, and the readings are POINT-IN-TIME (R10-FROZEN says so). +# - the 5470 GUARD IN FULL. This run mutates the host firewall through a handoff, so +# preserving the production port is a safety property of the mutation. +# - the binder-path canonical comparison, the classifier face_report, the r8 cleanup-exit +# handler, exactly-once state-aware cleanup, signal handling and the handoff mechanics. +# +# WHAT WAS ADDED: +# t1 the ONLY elevated read the design has, RIDING THE seq-001 SETUP REQUEST. One nonce is +# one execution: an elevated read cannot be added after the leg returns without a +# second handoff and a second authorization. If it does not run, t1 is UNAVAILABLE — a +# LABELLED EVIDENCE GAP, never a licence to report the capture contract satisfied. +# t2 at the outcome of the setup, beside D1, BEFORE any teardown is requested — so the +# state at a refusal is captured while it still exists. +# t3 immediately before the teardown request is written, with the manifest hashed first. +# TWO BUDGETS, ENFORCED AND SEPARATE (plan §4): a 300 s EXPERIMENTAL budget and a 180 s +# CLEANUP REPORTING deadline. The experimental deadline ENDS ACTIVITY AND STARTS +# CLEANUP — it exits through the EXIT trap, which is the only way cleanup is ever +# entered, so a truncated run tears down exactly like a complete one. The reporting +# deadline expiring means THE REPORT IS DUE, never that the host is tidy: cleanup stays +# PENDING while a residual-identity authorization is outstanding. +# RESIDUAL IDENTITY reporting (plan §6): pid + creation time + executable path + command +# line, read fresh, with the enumeration's own positive control so a dead process +# table cannot read as a tidy host. This driver REPORTS AND STOPS. It kills nothing: +# the r10 pid authorization was pid-specific and is SPENT, and a fresh pid-naming +# authorization is a STOP, not a step. +# A RUN LEDGER carrying the four exits separately and the two verdicts. +# +# THE EXITS STAY SEPARATE, at every point (plan §5.0). The elevated setup's native exit and +# each capture's native exit are independent values in their own files. Neither is inferred +# from, overwritten by, or substituted for the other. d2_capture.ps1 exits only 0 (a document +# was written — a document full of DENIED states is still a capture), 2 (could not write) or +# 3 (arguments rejected). NO PROPERTY STATE IS EVER AN EXIT CODE, and this driver's own exit +# is likewise not a statement that the run was green: the verdicts live in the ledger. +# +# VALIDATION DECIDES WHETHER AN OBSERVATION WAS MADE, NEVER WHETHER ITS VALUE IS THE WANTED +# ONE (doyle, 2026-09-13). Legitimate null, empty-string, empty-array and ABSENT all pass. A +# DENIED or ERROR outcome is a QUERY FAILURE THAT WAS OBSERVED — counted, reported, and +# distinct from a MISSING REQUIRED OBSERVATION, which is the only thing that makes a document +# incomplete. Nothing here requires EnforcementStatus to be [1]; refusing [5, 20] would +# refuse the evidence this capture exists to collect. # # --------------------------------------------------------------------------- -# PRODUCT CONTRACT, read at 53d625cd. Nothing below is remembered or guessed. +# PRODUCT CONTRACT, read at 85f84d73 and unchanged here. Only the lines this driver still +# READS are kept; the build-chain lines went with the build chain. # -# ANCHOR NOTE (r5). The subject is now 85f84d73, and windows.rs changed between the -# two. The serveverb.rs, lanhost.rs and bootstrap_firewall.rs anchors below were -# re-checked at 85f84d73 and still hold. The windows.rs LINE NUMBERS DO NOT: the -# three legs are now verify :764, reconcile :835, cleanup :963 (was 676/801/889), -# decide() is :786 with pair_satisfied_by :797, source store :808 and enforcement -# :824 (was 713-756), and snapshot() is :748 (was 675-680). The ORDER and the -# reasoning below are unchanged -- only the line numbers moved, and they are cited -# for a reader, never parsed. The enforcement arm now compares NUMERIC CODES against -# ENFORCEMENT_CERTIFIED rather than a display spelling; that is the repair under test. -# -# serveverb.rs:180-187 Lan{bootstrap:false,stop:false} builds LanStatus. A timed -# call without --bootstrap QUERIES A STOPPED LISTENER (v3's -# withdrawn command). -# serveverb.rs:233-249 The LanUp arm prints LAN_BOOTSTRAP_UP, the sha256 anchors -# and LAN-EXPOSED, calls report_lan_admission, and RETURNS 0 -# UNCONDITIONALLY. report_lan_admission returns unit, and -# reconcile_lan_firewall's i32 is DISCARDED at :371 and :387. -# => `serve lan --bootstrap` EXITS 0 EVEN WHEN UNVERIFIED. -# So a zero exit is NECESSARY BUT NOT SUFFICIENT (doyle): a -# nonzero rc is a real control error (:170,:192,:198) and is -# never accepted, while a zero carries no admission -# information on its own and is checked alongside the verdict -# line and the pair census. -# serveverb.rs:297-302 print_lan_admission -> LAN_FIREWALL_RECONCILED (stdout). -# THE positive admission verdict. -# serveverb.rs:311 lan_firewall_warning -> LAN_FIREWALL_UNVERIFIED (stderr) -# serveverb.rs:318 lan_cleanup_warning -> LAN_FIREWALL_CLEANUP_UNVERIFIED -# serveverb.rs:331 LAN_FIREWALL_MUTATION_DISABLED — the opt-out refusing a -# mutation. Its PRESENCE in a trial proves verify() did not -# return Ok(true) (the Ok(true) arm returns at :357 before -# request_lan_firewall is reached). -# serveverb.rs:341/345 LAN_FIREWALL_REPAIR_REQUESTED / _ELEVATION_UNAVAILABLE. -# "Launching it is not proof of admission or cleanup" — the -# product says so itself; treated as neither. +# serveverb.rs:233-249 The LanUp arm returns 0 UNCONDITIONALLY, so a zero exit carries no +# admission information on its own, while a nonzero IS a real +# control error (:170,:192,:198) and is never accepted. +# serveverb.rs:297-302 print_lan_admission -> LAN_FIREWALL_RECONCILED (stdout). THE +# positive admission verdict. +# serveverb.rs:311/318 LAN_FIREWALL_UNVERIFIED / LAN_FIREWALL_CLEANUP_UNVERIFIED (stderr) +# serveverb.rs:331 LAN_FIREWALL_MUTATION_DISABLED — the opt-out refusing a mutation. # serveverb.rs:379 LAN_FIREWALL_CLEAN — is_clean() Ok(true) on a stop. -# lanhost.rs:81 LAN_BOOTSTRAP_ALREADY_UP. In a trial this means THE PREVIOUS -# STOP FAILED and the wall measures a different path => VOID. -# serveverb.rs:376-391 report_lan_cleanup: is_clean Ok(false), UNELEVATED, goes to -# request_lan_firewall, which the opt-out REFUSES — so THE -# PAIR IS RETAINED. That is what makes Arm B repeatable, and -# the retention is EVIDENCED by MUTATION_DISABLED + -# CLEANUP_UNVERIFIED together, then measured by census. -# bootstrap_firewall.rs:19-25 mutation_permitted errors when SPT_INSTALL_NO_FIREWALL -# is set. It gates ONLY request_lan_firewall (serveverb:330) -# and reconcile_lan_firewall (:486). verify() :29-37 is NOT -# gated, so the verify-query leg still runs: listener up, -# exactly one verify-query, no elevation, no reconcile. -# bootstrap_firewall.rs:99-109 THE SUBJECT ROW, on stderr: -# bootstrap-firewall leg= program=

wall_ms= outcome= -# The wall is measured INSIDE the process around the child, -# the same boundary the 3000 ms budget is enforced at -# (:136-188). NOT comparable with a Measure-Command wall. -# bootstrap_firewall.rs:120-126 outcome(): killed beats failed; killed and failed are -# DIFFERENT findings. -# windows.rs:676/801/889 The only three legs: verify-query, reconcile-write, cleanup. -# A trial must show exactly ONE verify-query and no others. -# windows.rs:713-756 decide() order: duplicate-name hygiene, THEN -# pair_satisfied_by (:723) -> Ok(false), THEN source store -# (:731), THEN LAN scope (:745), THEN enforcement (:749). -# BECAUSE pair_satisfied_by IS CHECKED FIRST, reaching the -# enforcement arm PROVES the pair matched. That is the -# representation-accepted discriminator, and the reason it is. -# windows.rs:817 mismatch_message is reachable ONLY from reconcile()'s -# post-write re-verification. An UNELEVATED trial with a -# mismatched pair gets decide() Ok(false), which :362 renders -# as the GENERIC "owned admission is absent or does not match -# the listener" — THE SAME STRING ARM A PRODUCES WITH NO PAIR. -# So ABSENT and MISSPELLED are indistinguishable at the trial's -# product surface, and THE CENSUS IS WHAT SUPPLIES THE ARM. -# This corrects my own registered outcome table. -# windows.rs:816 reconcile() re-verifies after writing, so -# LAN_FIREWALL_RECONCILED from the ELEVATED setup DOES imply -# verify() returned Ok(true) at that instant. -# windows.rs:675-680 / bootstrap_firewall.rs:136-188 -# snapshot() hands stdout straight to serde_json; run_bounded -# pipes with a 1 MiB cap and no tee. The product's -# failure-time matcher input is UNRECOVERABLE at this sha. -# D1 is out-of-band and bounds host spellings only. -# xtask/src/main.rs:2204-2218 debug-keygen prints, one each: -# "key_id: " / "public_hex: " / "seed_hex: " -# xtask/src/main.rs:2708-2712 debug-rollout derives its signing identity FROM -# SPT_DEBUG_RELEASE_SEED. :2717 panics "seed is hex" on a bad -# one — where A7's S3 died. -# xtask/src/main.rs:2504 DEBUG_ROLLOUT_STAGED version=.. channel=.. platforms=.. stage_dir=.. -# xtask/src/main.rs:2295 DEBUG_MARKED_APPLIED version=.. releases=.. -# relcache.rs:35/39/266 The staged set is /release.json (a SignedUpdateSet -# with metadata_json + signature_hex) and -# /artifacts/.bin. -# xtask/src/main.rs:2738-2746 --build-current builds with -# `cargo build --release -p spt --bin spt` at the workspace -# root and takes target/release/spt.exe. A CARGO PRODUCER -# RUNS INSIDE THIS VERB, so the capacity floor precedes it. +# serveverb.rs:376-391 report_lan_cleanup: an UNELEVATED cleanup goes to +# request_lan_firewall, which the opt-out REFUSES — so an unelevated +# opt-out stop RETAINS the pair. That is what keeps the pair alive +# between t2 and t3. +# serveverb.rs:191 serve reaches the broker through ensure_running, so the firewall +# teardown must stay AHEAD of the daemon stop or the teardown spawns +# a fresh daemon. +# windows.rs:713-756 decide() checks pair_satisfied_by (:723) FIRST, so reaching the +# enforcement arm PROVES the pair matched. +# windows.rs:816-817 reconcile() re-verifies after writing: RECONCILED from the ELEVATED +# setup does imply verify() Ok(true) at that instant, and +# mismatch_message is reachable only from that re-verification. +# windows.rs:11-30 THE OWNED NAMES ARE CONSTANTS: spt-core-bootstrap-inbound-tcp and +# -lan, under group "spt-core bootstrap TCP". A production pair on +# 5470 carries THE SAME NAMES, so a query by name can return more +# than one object. That is why the capture preserves every match +# with its own match_index and marks ambiguity instead of taking +# items[0]. +# bootstrap_firewall.rs:19-25 SPT_INSTALL_NO_FIREWALL gates request_lan_firewall and +# reconcile_lan_firewall only; verify() is NOT gated. # -# NO `set -e`: it can exit before a failure is RECORDED and before state-aware -# cleanup runs. Every command's exit is captured immediately in a guarded branch. +# NO `set -e`: it can exit before a failure is RECORDED and before state-aware cleanup runs. +# Every command's exit is captured immediately in a guarded branch. # ============================================================================= # ---- configuration --------------------------------------------------------- @@ -233,20 +127,29 @@ BIN="$SP/fp-bin" # INSTRUMENTS — never written to by a run RUN_ROOT="$SP/fp-run" # one timestamped subdir per run H="$SP/fp-home" # isolated SPT_HOME, this experiment only -EXE="$W/target/release/spt.exe" # RELEASE, built by debug-rollout --build-current +EXE="$W/target/release/spt.exe" # THE EXECUTABLE r10 ALREADY BUILT. Nothing here builds. +EXE_SHA='72d309011415b419aabfdb0b4065df1183bfd0069a9f95b5779da62e43349b10' PORT=29470 # never 5470 GUARD_PORT=5470 # the production port this run must not disturb -TRIPLE='x86_64-pc-windows-msvc' -LANE='fp-85f84d73' -KEY_ID='fp-debug-2026' SUBJECT_SHA='85f84d738fa702f35c83910f314aae17849d125c' SUBJECT_BLOB='848a23fe18e5ca819774f9881ef13504221992f3' -FLOOR_GIB=96 # producer-admission floor -HARD_STOP_GIB=32 # below this a resource red is an UNTESTED lane -HANDOFF_WAIT_S=900 # bounded wait for a liam receipt in the normal flow -CLEANUP_HANDOFF_WAIT_S=300 # separate, shorter bound inside cleanup, so a missing - # receipt cannot hold the independent teardown steps open +# The owned pair's names are PRODUCT CONSTANTS (windows.rs:11-19), not a choice of this rig. +RULE_TAILNET='spt-core-bootstrap-inbound-tcp' +RULE_LAN='spt-core-bootstrap-inbound-tcp-lan' +# POSITIVE CONTROL: a standing rule, read-only, same property set, same route, same process. +# A property ABSENT on BOTH it and the pair is an INSTRUMENT LIMIT, not a finding about the +# pair. It is a knob because it names a rule on THIS host; the capture records whether it was +# actually present, and a control that was NOT present makes the pair's absences unreadable — +# reported by d2_validate as sound=false, never assumed either way. +CONTROL_RULE='Tailscale-In' +ABSENT_CONTROL='spt-core-bootstrap-inbound-tcp-d2-absent-control' +EXP_BUDGET_S=300 # plan §4: experimental total, from run start +CLEANUP_REPORT_S=180 # plan §4: cleanup REPORTING deadline, from the end of activity +HANDOFF_WAIT_S=900 # bounded wait for a liam receipt; narrowed at the point of + # waiting to what remains of the experimental budget +CLEANUP_HANDOFF_WAIT_S=300 # likewise narrowed to what remains of the reporting deadline CI_REPO='BigscreenVR/spt-bs-core' # the CODE repo (D3). Issues live elsewhere. +RUN_EPOCH=$(date +%s) # the experimental clock starts at process start ORIGINAL_RC=0 # the FIRST failure's code; cleanup never changes it ORIGINAL_WHY='' @@ -254,14 +157,38 @@ CLEANUP_ENTERED=0 CLEANUP_FAILURES=0 D1_OK=unknown -A_COMPLETED=0 # completed VALID Arm-A trials -A_REQUIRED=3 # the registered loop below (for n in 1 2 3) -B_COMPLETED=0 # completed VALID Arm-B trials; the only thing that -B_REQUIRED=3 # earns populated timing. Required count is the - # registered loop below (for n in 1 2 3). HANDOFF_SEQ=0 HO_SEQ=''; HO_NONCE=''; HO_RECEIPT=''; HO_OUT=''; HO_ERR='' - +# D2 state. Every value below is REPORTED, and each one starts at the reading that assumes +# the least: an unread exit is not a zero one, and an uncaptured point is a gap. +D2_T1=UNAVAILABLE +D2_T2=NOT_RUN +D2_T3=NOT_RUN +D2_T1_VALID=NOT_VALIDATED +D2_T2_VALID=NOT_VALIDATED +D2_T3_VALID=NOT_VALIDATED +D2_T1_QF=0 # query failures among the REQUIRED observations at each point: +D2_T2_QF=0 # observed and recorded, never counted as successful ones +D2_T3_QF=0 +VALIDATE_QF=0 +SETUP_RC=255 +TEARDOWN_RC=255 +SETUP_START_UTC=UNRECORDED +SETUP_END_UTC=UNRECORDED +PRE_SETUP_ABSENCE=UNRECORDED +RESIDUE_COUNT=UNMEASURED +RESIDUE_LIVE=0 # tracked identities re-queried and still running +RESIDUE_GONE=0 # tracked identities measured absent (or pid-reused) +RESIDUE_UNREADABLE=0 # attribution missing or unreadable: NEVER read as clean +IDENT_CAPTURE_RC=1 # the capture command's own exit; 1 until it has run +CAPTURE_USABLE=no # a capture supports CLEAR only when proven complete +CAPTURE_INTEGRITY='' # why it is or is not usable, in words +DAEMON_STOP_REFUSED=0 # IR-122's expected refusal, recorded with its native exit +DAEMON_STOP_RC=NOT_RUN # the refused command's OWN exit, preserved in every case +LISTENER_STATE=UNMEASURED # unread is read as LIVE: an unread port is not an empty one +CAPTURE_CONTRACT=NOT_SATISFIED # earned, never defaulted to satisfied +CLEANUP_VERDICT=PENDING # PENDING until VERIFIED is measured; a clock never earns it +EXPERIMENTAL_ENDED='' # ---- evidence dir: per-run, never reused, never truncated (F4/F5/D10) ------- RUN_ID="$(date -u +%Y%m%dT%H%M%SZ)" R="$RUN_ROOT/$RUN_ID" @@ -559,6 +486,275 @@ echo "$n" } +# ---- TWO BUDGETS, ENFORCED AND SEPARATE (plan §4; doyle 2026-09-13) -------- +# The EXPERIMENTAL budget bounds ACTIVITY. The CLEANUP budget bounds the REPORT. They are +# different clocks measuring different obligations, and the second one starts where the +# first one ends: +# +# EXPERIMENTAL (300 s, from run start). Reaching it ENDS ACTIVITY AND STARTS CLEANUP. +# IT NEVER SKIPS CLEANUP -- the deadline exits through the EXIT trap, which is the only +# way cleanup is ever entered, so a truncated run tears down exactly like a complete one. +# A phase cut short is REPORTED AS TRUNCATED, naming the phase; a truncated phase's +# absence of a field is "NOT CAPTURED", never "not present". +# +# CLEANUP REPORTING (180 s, from the end of activity). Reaching it means THE REPORT IS +# DUE. It does NOT mean the host is tidy and it never converts PENDING into VERIFIED: +# while a residual-identity authorization is outstanding, cleanup stays PENDING and the +# identities are reported for the next consumer to act on. +CLEANUP_EPOCH=0 +exp_left() { + local now used left + now=$(date +%s); used=$((now - RUN_EPOCH)); left=$((EXP_BUDGET_S - used)) + [ "$left" -lt 0 ] && left=0 + echo "$left" +} +cleanup_left() { + [ "$CLEANUP_EPOCH" -eq 0 ] && { echo "$CLEANUP_REPORT_S"; return; } + local now used left + now=$(date +%s); used=$((now - CLEANUP_EPOCH)); left=$((CLEANUP_REPORT_S - used)) + [ "$left" -lt 0 ] && left=0 + echo "$left" +} +end_experimental() { # WHY — idempotent: the reporting clock starts exactly once + [ -n "$EXPERIMENTAL_ENDED" ] && return 0 + EXPERIMENTAL_ENDED="$1" + CLEANUP_EPOCH=$(date +%s) + stamp "experimental_END why=$1" + record "EXPERIMENTAL_END ($1) at $((CLEANUP_EPOCH - RUN_EPOCH))s of the ${EXP_BUDGET_S}s budget; the ${CLEANUP_REPORT_S}s cleanup REPORTING deadline starts now" +} +deadline_check() { # LABEL — called before each activity step + local left; left=$(exp_left) + if [ "$left" -gt 0 ]; then + record "BUDGET before '$1': ${left}s of ${EXP_BUDGET_S}s remain" + return 0 + fi + record "EXPERIMENTAL_DEADLINE reached before '$1' — activity ENDS HERE and cleanup begins; the deadline does not skip it" + record " TRUNCATED phase=$1 got 0s. Whatever this phase would have captured is NOT CAPTURED, which is not the same statement as 'not present'." + end_experimental "experimental deadline before $1" + set_original 7 "experimental deadline (${EXP_BUDGET_S}s) reached before $1" + exit 7 +} + +# ---- the D2 capture point -------------------------------------------------- +# THE ARGUMENT FORM IS MEASURED, NOT ASSUMED (control receipt, 2026-09-13). MEASURED ON THIS +# BOX, FOR THIS INVOCATION SHAPE -- a [string[]] parameter reached from bash through +# powershell.exe -- and the finding is scoped to exactly that; it is not a claim that -File +# is broken in general: +# -File