--- fp-driver-d2-r10-AQ23KKNI.sh +++ fp-driver-d2-r10-P9RLK4VU.sh @@ -57,7 +57,7 @@ # 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 +# TWO BUDGETS, ENFORCED AND SEPARATE: the DERIVED experimental budget below 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 @@ -195,7 +195,7 @@ # executor's hash-verified PREPARED/NOT_STARTED acknowledgment # run under THIS bound; the experimental window does not exist # yet while they do. -EXP_BUDGET_S=300 # plan §4: experimental total, from GO -- NOT from run start +# EXP_BUDGET_S is derived below (P9RLK4VU), from GO -- NOT 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 @@ -209,15 +209,36 @@ # KILL_GRACE_S caller reporting reserve; native setup, termination and confirmation # live inside the launcher's own deadline. Only retained created handles # authorize termination. No PID-tree sweep or guard bypass exists. -# HANDOFF_CAP_S a POLICY ALLOCATION of the activity window -- how much of the 300s this -# run will spend waiting on another agent. 94s and 134s are two samples, -# not a distribution, and nothing here is derived from them. +# HANDOFF_CAP_S retained 120s policy for PREPARE, GO and cleanup handoffs. +# P9RLK4VU supersedes it for SETUP ONLY, whose receipt follows execution. LEDGER_RESERVE_S=30 KILL_GRACE_S=5 HANDOFF_CAP_S=120 # AQ23KKNI: independent execution allocation, not notification/handoff time. # 9s measured around a refused capture + existing 90s capture cap + 5s reserve + 16s margin. ELEVATED_LEG_BUDGET_S=120 +# P9RLK4VU, run 20260914T063552Z; timeline.txt and executor's measured latency: +# setup: 112s notification/read/launch latency + 120s leg + 8s receipt margin = 240s. +# post probes: two portfields calls at up to 45s + census 46s = 136s observed on this +# host. Add 64s for identity capture, D1 and bookkeeping: an ALLOWANCE, not a measured +# complete post-receipt path (that path was not reached in the fifth window). +# t3 measured 25s, also 25s in run 20260913T041410Z; t2 retains the 90s capture +# ceiling rather than inheriting 180s. Its 100s allocation adds the 5s launcher +# reporting reserve plus 5s shell/reporting margin. +# GO-to-request measured 54s: pre-dispatch allowance 74s adds 20s margin. +# Activity = 74 + 240 + (200 + 100) + 16 transition reserve = 630s. +# Prep 600 and cleanup-report 180 INCLUDING ledger 30 are unchanged. No window grant. +SETUP_LATENCY_S=112 +SETUP_HANDOFF_MARGIN_S=8 +SETUP_HANDOFF_CAP_S=$((SETUP_LATENCY_S + ELEVATED_LEG_BUDGET_S + SETUP_HANDOFF_MARGIN_S)) +POST_RECEIPT_PROBE_S=$((2 * 45 + 46 + 64)) +T2_NATIVE_CEILING_S=90 +T2_BOUND_S=$((T2_NATIVE_CEILING_S + KILL_GRACE_S)) +T2_ALLOWANCE_S=$((T2_BOUND_S + 5)) +POST_RECEIPT_S=$((POST_RECEIPT_PROBE_S + T2_ALLOWANCE_S)) +PRE_DISPATCH_ALLOWANCE_S=$((54 + 20)) +ACTIVITY_TAIL_RESERVE_S=16 +EXP_BUDGET_S=$((PRE_DISPATCH_ALLOWANCE_S + SETUP_HANDOFF_CAP_S + POST_RECEIPT_S + ACTIVITY_TAIL_RESERVE_S)) # THE TEARDOWN COMMAND IS PINNED, NEVER COMPOSED (doyle 2026-09-13). The removal this run may # need is the PRODUCT'S OWN rendered cleanup command, which only the shipped binary can emit. # Until it has been emitted, decoded, reviewed and pinned here, cleanup REFUSES to dispatch any @@ -608,10 +629,15 @@ local context="$1" local rf="$HO_RECEIPT" nonce="$HO_NONCE" local now; now=$(date +%s) - local started="$now" limit="$HANDOFF_WAIT_S" phase_deadline deadline remaining nap + local started="$now" limit="$HANDOFF_WAIT_S" phase_deadline deadline remaining nap cap="$HANDOFF_CAP_S" [ "$context" = cleanup ] && limit="$CLEANUP_HANDOFF_WAIT_S" + if [ "$context" = trial ] && [ "${SETUP_WAIT_STATUS:-}" = WAITING ]; then cap="$SETUP_HANDOFF_CAP_S"; fi deadline=$((started + limit)) - [ "$deadline" -gt "$((started + HANDOFF_CAP_S))" ] && deadline=$((started + HANDOFF_CAP_S)) + [ "$deadline" -gt "$((started + cap))" ] && deadline=$((started + cap)) + if [ "$context" = trial ] && [ "${SETUP_WAIT_STATUS:-}" = WAITING ]; then + # Request construction and notification spend the published deadline too. + [ "$deadline" -le "$SETUP_HANDOFF_DEADLINE" ] || deadline="$SETUP_HANDOFF_DEADLINE" + fi # Cleanup owns WORK_DEADLINE even if GO never happened; zero/unopened fails closed. if [ "$context" = cleanup ]; then phase_deadline="$WORK_DEADLINE" else phase_deadline=$(cur_deadline); fi @@ -746,6 +772,7 @@ EXP_DEADLINE=0 # RUN_EPOCH + EXP_BUDGET_S, set at go() REPORT_DEADLINE=0 # CLEANUP_EPOCH + CLEANUP_REPORT_S, set at end_experimental() WORK_DEADLINE=0 # REPORT_DEADLINE - LEDGER_RESERVE_S, same place +OBSERVATION_DEADLINE=0 # post-receipt probe/t2 suballocation; cleanup never uses it SETUP_COMPLETION=UNPROVEN # R6: proven only by a run-bound receipt with terminal fields CLEANUP_STOP_STATE=NOT_REACHED # which gate outcome step 1 took (IR-124) TEARDOWN_DISPATCH=NOT_REACHED # whether a teardown command was dispatched, and why not @@ -908,6 +935,26 @@ now=$(date +%s); used=$((now - RUN_EPOCH)); left=$((EXP_BUDGET_S - used)) [ "$left" -lt 0 ] && left=0 echo "$left" +} +require_setup_budget() { # AVAILABLE_SECONDS PHASE(before-go|before-dispatch) + local available="$1" phase="$2" + local required=$((SETUP_HANDOFF_CAP_S + POST_RECEIPT_S + ACTIVITY_TAIL_RESERVE_S)) + [ "$phase" = before-go ] && required=$((required + PRE_DISPATCH_ALLOWANCE_S)) + case "$available" in (''|*[!0-9]*) record "SETUP_BUDGET_REFUSED phase=$phase available=$available"; return 1 ;; esac + record "SETUP_BUDGET phase=$phase available=${available}s required=${required}s handoff=${SETUP_HANDOFF_CAP_S}s post_probes=${POST_RECEIPT_PROBE_S}s t2=${T2_ALLOWANCE_S}s transition=${ACTIVITY_TAIL_RESERVE_S}s" + if [ "$available" -lt "$required" ]; then + record "SETUP_BUDGET_REFUSED — no setup request may be dispatched; a smaller remaining window is not a smaller execution grant" + return 1 + fi + return 0 +} +observation_budget() { # LABEL ALLOCATION_SECONDS RESERVE_AFTER_SECONDS + local label="$1" allocation="$2" reserve="$3" now ceiling + now=$(date +%s) + OBSERVATION_DEADLINE=$((now + allocation)) + ceiling=$((EXP_DEADLINE - reserve)) + [ "$OBSERVATION_DEADLINE" -le "$ceiling" ] || OBSERVATION_DEADLINE="$ceiling" + record "OBSERVATION_BUDGET label=$label deadline=$OBSERVATION_DEADLINE reserve_after=${reserve}s" } # r5: actual argv vector, owned job confirmation, direct state kept separate. BOUNDED_STATE=NOT_REACHED @@ -1064,6 +1111,7 @@ cur_deadline() { if [ "$CLEANUP_EPOCH" -ne 0 ]; then echo "$WORK_DEADLINE" elif [ -z "$RUN_EPOCH" ]; then echo "$PREP_DEADLINE" + elif [ "$OBSERVATION_DEADLINE" -gt 0 ] && [ "$OBSERVATION_DEADLINE" -lt "$EXP_DEADLINE" ]; then echo "$OBSERVATION_DEADLINE" else echo "$EXP_DEADLINE"; fi } # THE EXECUTABLE MUST BE NAMED TO WINDOWS. A call site spells its program the way bash finds @@ -1105,7 +1153,7 @@ exit 8 } # GO - THE ONE PLACE THE EXPERIMENTAL CLOCK EVER STARTS (doyle 2026-09-13). It is a -# separate act from preparation on purpose: the 300s window pays for THIS RUN'S ACTIVITY, +# separate act from preparation on purpose: the derived window pays for THIS RUN'S ACTIVITY, # and it must not already be running while an elevated operator reads a request. MEASURED # REASON: run 20260913T041410Z spent 134s of its 300s at the setup handoff and reached # neither t1 nor t2. @@ -2627,7 +2675,7 @@ # bound to THIS run and THIS request and cannot be a stale or reused token from another. prep_check go-authorization handoff_request go-authorization \ - "AUTHORIZE ONLY -- RUN NOTHING. FOR THE DRI, NOT FOR THE ELEVATED EXECUTOR: readiness has already been acknowledged by the leg that would run this, and that acknowledgment is not this decision. Authorize the experimental window to OPEN for this run, knowing the 300s activity clock starts when it does." \ + "AUTHORIZE ONLY -- RUN NOTHING. FOR THE DRI, NOT FOR THE ELEVATED EXECUTOR: readiness has already been acknowledged by the leg that would run this, and that acknowledgment is not this decision. Authorize the experimental window to OPEN for this run, knowing the derived ${EXP_BUDGET_S}s activity clock starts when it does; setup handoff ${SETUP_HANDOFF_CAP_S}s, post-receipt observations ${POST_RECEIPT_S}s, pre-dispatch ${PRE_DISPATCH_ALLOWANCE_S}s and transition reserve ${ACTIVITY_TAIL_RESERVE_S}s." \ "AUTHORIZATION ONLY. Nothing is run to answer this. Reply in the receipt with THREE things: the token GO_AUTHORIZED on a line of its own and nothing else on that line; the line authorizer=doyle, likewise alone on its line; and the nonce of THIS request quoted exactly (anywhere). To WITHHOLD authorization, say so in words -- there is no negative token this check reads." \ doyle GO_ACK="$HO_RECEIPT"; GO_ACK_NONCE="$HO_NONCE" @@ -2670,6 +2718,7 @@ # an authorization that is verified late must not open a window the budget had already closed. # prep_check refuses with exit 8 -- a run that never started, with nothing to tear down. prep_check window-open +require_setup_budget "$EXP_BUDGET_S" before-go || die "derived activity budget cannot hold the planned sequence; GO refused" # THE WINDOW OPENS HERE AND NOWHERE ELSE. go "GO authorization verified (run-bound), both subject hashes measured by the executor, and the reviewed removal instrument verified" @@ -2685,6 +2734,7 @@ # The daemon has its own run-scoped job, alive before any autostart-capable dispatch. run_daemon_start || die "run-scoped daemon did not establish owned readiness; no setup is dispatched" run_daemon_require_ready || die "autostart-capable setup refused: no current owned daemon" +require_setup_budget "$(exp_left)" before-dispatch || die "remaining activity budget cannot hold setup and its observations; setup not dispatched" # MARKED BEFORE THE DISPATCH (C): a REFUSED setup can still leave rules behind. mark_state fw_mutation_may_have_occurred "an elevated reconcile is about to be REQUESTED; rules may exist from this moment even if the setup is refused" mark_state daemon_may_run "run-scoped job owns the prestarted daemon; setup may not autostart one" @@ -2713,8 +2763,9 @@ # finished, and it includes however long liam took to read the request and answer it. Both # intervals are recorded here, each under a name that says whose clock took it. HANDOFF_REQUEST_UTC="$(date -u +%Y-%m-%dT%H:%M:%SZ)" -SETUP_HANDOFF_DEADLINE=$(( $(date +%s) + HANDOFF_CAP_S )) -[ "$SETUP_HANDOFF_DEADLINE" -le "$EXP_DEADLINE" ] || SETUP_HANDOFF_DEADLINE="$EXP_DEADLINE" +SETUP_HANDOFF_DEADLINE=$(( $(date +%s) + SETUP_HANDOFF_CAP_S )) +SETUP_RECEIPT_LATEST=$((EXP_DEADLINE - POST_RECEIPT_S - ACTIVITY_TAIL_RESERVE_S)) +[ "$SETUP_HANDOFF_DEADLINE" -le "$SETUP_RECEIPT_LATEST" ] || SETUP_HANDOFF_DEADLINE="$SETUP_RECEIPT_LATEST" SETUP_WAIT_STATUS=WAITING handoff_request setup \ "create the owned pair with the product itself (never a hand netsh, so the rules carry the shipped desired_specs shape) AND take the t1 capture inside this same elevated leg" \ @@ -2784,19 +2835,10 @@ } >> "$R/handoff/$HO_SEQ-setup-request.txt" record "HANDOFF_T1_RIDER appended to the seq-$HO_SEQ setup request — the only elevated read this design has; omission is a labelled gap, not a pass" record "HANDOFF_REQUEST_UTC=$HANDOFF_REQUEST_UTC — a bound on THIS DRIVER's request, not on the command it asks for" -# The wait cannot outlive the experimental budget: the deadline ends activity, whoever is -# holding it up. -HANDOFF_WAIT_S=$(exp_left) -# THE CAP IS A POLICY ALLOCATION, NOT AN ESTIMATE (doyle CT6GS2Y6). It answers how much of the -# activity window this run will spend waiting on another agent, and it exists because one slow -# counterparty can otherwise consume the whole window and leave nothing for the observations the -# window exists to take -- run 20260913T041410Z spent 134s here and reached neither t1 nor t2. -# 94s and 134s are two samples, not a distribution, and no number here is derived from them. -if [ "$HANDOFF_WAIT_S" -gt "$HANDOFF_CAP_S" ]; then - record "HANDOFF_CAP applied: ${HANDOFF_CAP_S}s of the ${HANDOFF_WAIT_S}s that remain — the rest of the window is RESERVED for the post-mutation observations, which cannot be taken anywhere else" - HANDOFF_WAIT_S=$HANDOFF_CAP_S -fi -record "HANDOFF_WAIT bounded to ${HANDOFF_WAIT_S}s — the lesser of the cap and what remains of the experimental budget" +# Setup's derived allowance supersedes the retained 120s cap for this leg ONLY. +# The absolute request deadline also reserves post-receipt observations and transition. +HANDOFF_WAIT_S=$SETUP_HANDOFF_CAP_S +record "HANDOFF_WAIT setup_cap=${SETUP_HANDOFF_CAP_S}s absolute_deadline=$SETUP_HANDOFF_DEADLINE post_receipt_reserved=${POST_RECEIPT_S}s transition_reserved=${ACTIVITY_TAIL_RESERVE_S}s" # CONTEXT NAME KEPT VERBATIM: 'trial' is handoff_await's name for THE NORMAL FLOW, as # opposed to 'cleanup'. There are no trials here; renaming it would edit a function this # change has no reason to touch, so the name stays and this line says what it means. @@ -2817,6 +2859,7 @@ SETUP_WAIT_STATUS=TIMELY HANDOFF_RECEIPT_UTC="$(date -u +%Y-%m-%dT%H:%M:%SZ)" HANDOFF_WAIT_END_UTC="$HANDOFF_RECEIPT_UTC" +observation_budget post-receipt-probes "$POST_RECEIPT_PROBE_S" "$((T2_ALLOWANCE_S + ACTIVITY_TAIL_RESERVE_S))" SETUP_RC=$(handoff_exit) exits "setup_elevated_EXIT=$SETUP_RC" # THE LEG'S OWN MEASUREMENTS, read back from the files it was asked to write. @@ -2912,7 +2955,8 @@ deadline_check t2-capture record "D1 and t2 run NOW, before any teardown is requested, so the state at this outcome is captured while it still exists." d1_capture setup-outcome -d2_capture_at t2 "$(exp_left)" +observation_budget t2 "$T2_BOUND_S" "$ACTIVITY_TAIL_RESERVE_S" +d2_capture_at t2 "$T2_BOUND_S" D2_T2=$(tr -d ' ' < "$R/d2-t2.exit" 2>/dev/null || echo UNRECORDED) # t2's validation is DEFERRED with t1's — see the note at the t1 site. This is the 11s