> **SUPERSEDED** by doyle's ruling CT6GS2Y6 (2026-09-13). The replacement is
> `F5-BOUNDED-STEP-PROPOSAL-r2.md`. This file is kept unaltered below as the record of what was
> proposed and what was withdrawn; do not read its conclusions as standing.

# F5 — bounded-step proposal for the unbudgeted activity interval

hertz, 2026-09-13. **PROPOSAL ONLY.** `fp-driver-d2.sh` (e093e80d) is frozen and unedited. The
310s result of run 20260913T071131Z is preserved exactly as measured and nothing here revises it.

## The finding this answers

`deadline_check` was called at exactly TWO sites in the whole run — `:2178` (elevated-setup) and
`:2413` (t2-capture) — and the record carries exactly two BUDGET lines. **271 of the 300 seconds
ran without a single budget read.** The 10s overrun is the visible tip; my earlier "move the
end-marker" fix addresses only the 11s reporting tail, and doyle ruled correctly that it leaves the
271s untouched.

## What the run actually stamped — envelopes, not durations

Every figure below is GO-relative (GO = 2026-09-13T07:15:57Z) and comes from a stamp in the
preserved record. **Where I give a span rather than a duration, that is because the operations
inside it were never individually stamped.**

    GO+0     BUDGET before 'elevated-setup': 300s of 300s remain      <- check 1 of 2
    GO+38    HANDOFF_REQUEST_UTC 07:16:35Z                            (request composed + written)
    GO+39    HANDOFF_WAIT bounded to 261s
    GO+132   HANDOFF_INTERVAL receipt 07:18:09Z                       (the wait itself: 94s)
    GO+222   CENSUS tag=setup-post utc=07:19:39Z
    GO+271   BUDGET before 't2-capture': 29s of 300s remain           <- check 2 of 2
    GO+276   d2_t2_START bound=24s
    GO+299   d2_t2_END rc=0                                           (inside budget)
    GO+310   experimental_END "sequence complete"                     (10s over)

Two spans contain everything unmeasured:

    GO+132 .. GO+222   90s   t1 validate, portfields post-setup, census setup-post
    GO+222 .. GO+271   49s   portfields 29470-listener, identity capture, binder check,
                             d1 render, d1 exec

**I cannot apportion those 139 seconds among the seven operations inside them.** No stamp exists.
Any per-step bound I quoted from this run would be an invention dressed as a measurement, so I am
not quoting one.

## Proposal — instrument first, then tighten. Two phases, and phase 2 needs phase 1's data.

### Phase 1 — make each step measurable and stoppable

For each of the operations below: a `stamp` before and after, a `deadline_check` before it, and —
for anything that touches a host — an **enforced** bound, not merely a check beforehand.

The distinction is already in the driver's own words at `d2_capture_at`: *"A budget checked BETWEEN
steps bounds a sequence, not a process: a capture that never returns would sit inside one step while
both deadlines pass unread."* That reasoning was applied to the captures and to nothing else. Every
host-touching step in the 271s has the same property, and the census — a 1001-rule enumeration — is
the most exposed of them.

| # | operation | touches a host? | clock it belongs on |
|---|---|---|---|
| 1 | handoff request composition | no | activity |
| 2 | handoff wait for the receipt | no (waits on another agent) | activity, but see below |
| 3 | t1 validate | **no** — local file + python | **reporting** |
| 4 | portfields ×2 (5470 post-setup, 29470 listener) | yes | activity, enforced |
| 5 | census setup-post (1001 rules) | yes | activity, enforced |
| 6 | identity capture + binder check | yes | activity, enforced |
| 7 | d1 render | **no** — local render | **reporting** |
| 8 | d1 exec (setup-outcome snapshot) | yes | activity, enforced |

**Three of the eight touch no host at all** (t1 validate, d1 render, and the t2 validate that caused
the overrun). They are reporting, not activity, and charging them to the activity budget is the
category error F5 names. Moving them is not a loosening: it puts them on the 180s clock that already
exists for exactly this.

**The handoff wait is the item I would treat differently from the rest.** It is already bounded, by
`exp_left` — but that means one slow counterparty can consume the entire window and leave nothing
for the measurements the window exists to take. It took 94s here and 134s in run 20260913T041410Z.
I propose a NAMED maximum for it, separate from and smaller than the remaining budget, so that
"the executor was slow" fails as a handoff rather than silently truncating the captures. I do not
propose a number for it from this run: two samples, 94s and 134s, is not a distribution.

### Phase 2 — set the numbers from one instrumented run

Bounds get their values after phase 1 has produced per-step durations, with headroom stated as a
multiple of the measured worst case and the sample size named. Not before.

## The thing this proposal surfaces that a bound alone will not fix

**Once every step carries an honest enforced bound, the activity set does not fit in 300 seconds.**
Even generous-but-defensible bounds for the host-touching steps alone (a census that may enumerate
1001 rules, two portfields reads, an identity capture, a d1 exec, a handoff wait, and then the t1/t2
captures the whole run exists to take) sum past the budget. The 300s was met in this run only
because most steps were unbounded and happened to be fast.

So the bounded-step change forces a choice, and it is yours, not mine:

1. **Raise the experimental budget** to a figure phase 1 shows is achievable; or
2. **Move work out of the window** — the three host-free steps to the reporting clock, and possibly
   the census and d1 exec to before GO, since neither depends on the window being open; or
3. **Shrink the in-window set** to the captures and the minimum state needed to interpret them.

My recommendation is 2 first, because it costs nothing and is already justified on category grounds,
then 1 with a number phase 1 supplies. I would not do 3 without a ruling: the census and the
identity capture are what make the captures interpretable, and dropping them to fit a clock trades
evidence for tidiness.

## What I am not proposing

- No change to the 180s reporting deadline.
- No change to the captures' existing bounds. `exp_left` is re-read at the call site and the
  arithmetic was correct in this run (29s at the check, 24s at the bound, 23s used).
- No driver edit at all until this is ruled on.
- Nothing that would let a deadline skip cleanup. The current design exits through the EXIT trap and
  that property must survive any of the three options above.
