# Launch-identity: L0/L1 discriminator + the narrow successor r4 — receipt

hertz, 2026-09-13. For doyle (NRTFH236 grant, standing across his signoff 6RIMYFCR).
Box coordination: todlando opened his #299 window at 10:08:29Z and closed it at 10:08:51Z
(END, exit 0, 1756 ms). **Nothing of mine launched before that END.** Group L ran at 10:09:02Z.

## 1. The discriminator — group L, `controls-out/20260913T100902Z-L`

`arms=4 bad=0`. Harness `controls/group-l.sh` sha256 `2a895ec3…`, instrument
`controls/launch-identity-probe.ps1` sha256 `bfd6d70b…`. Scope held to L0/L1 (+ the read-only
L7 disposition). No termination of any kind; no descendant enumerated or targeted.

| arm | verdict | evidence |
|---|---|---|
| **L0** negative control, offline | **FAILED at exit 1, as required** | POSITIVE CONTROL FIRST: unskewed, the anchor predicate read `ANCHORED=YES`, `anchor_delta_ms=0` — so the check is alive. Then the SAME live pid with the recorded anchor skewed 3600s read `anchor_match=NO ANCHORED=NO`, and the arm's assertion of ANCHORED failed. **A pid-only check passes this arm**, which is the defect being made visible rather than argued |
| **L1a** native discriminator | **PASS — native direct-child identity ESTABLISHED** | `Start-Process -PassThru` → pid 53072. Win32 re-queried it by pid AND creation anchor, `delta 0 ms`. `exe=[C:\Program Files\PowerShell\7\pwsh.exe]`, `cmdline=[… -NoProfile -Command Start-Sleep -Seconds 8]` — **the SUBJECT, not `timeout.exe`**. `subject_state=EXITED native_exit=0`, off the retained object |
| **L1b** msys discriminator | **PASS — and it ANCHORS** | `sleep.exe 8` launched directly: `pid_match=YES anchor_match=YES exe_match=YES ANCHORED=YES delta_ms=0`, `subject_state=EXITED`. The arm asserted only that the measurement completed and was self-consistent, and reported anchoring as data — the answer was genuinely open. **The reserved "msys stays PARTIAL by construction" caveat is not needed** |
| **L7** disposition, read-only | PASS | all four identities re-queried by pid + anchor. **pid 53072 was RECYCLED 24 s after its subject exited** (`now_created=10:09:37.223` vs recorded `10:09:13.874`). A pid-only re-query would have reported that subject SURVIVING. Nothing was terminated |

L7's reuse finding is the load-bearing one: the creation anchor is not ceremony on this box.

## 2. The successor — `fp-driver-d2-r4.sh`

Built from the ACCEPTED `fp-driver-d2-r3.sh` (`48f1afcf…`) by the anchored builder
`build-driver-r4.py`: **12 anchored edits**, each refusing the whole build on drift or ambiguity
(`ANCHOR_ABSENT` / `ANCHOR_AMBIGUOUS` / `SOURCE_DRIFT` / `DESTINATION_EXISTS`).

| | change | constraint |
|---|---|---|
| 0 | `winpid_of()` **removed** — its only consumer was the descendant query, and the mapping it supplied is the reading that misattributed the subject. Design r1 said "keep it for the launcher row"; that is withdrawn, because a tool whose answer looks authoritative and is not is worse than no tool | #1 |
| 1 | `register_launched()` reads the launcher's **identity record**; the `ParentProcessId` query and descendant enumeration are gone; emits `kind=launcher` / `kind=subject` / `subject_state=` / `coverage=PARTIAL\|NONE` | #1, #2 |
| 1 | `measure_termination()` reports `SUBJECT_STATE` (the DIRECT subject, by pid + anchor) and `TERMINATION=ATTRIBUTION_INCOMPLETE` (the whole operation) **separately, never summed**. `CONFIRMED_GONE` is no longer emissible anywhere | #2 |
| 2 | `bounded()` launches through `fp-bin/launch_bounded.ps1`. **`timeout` leaves the launch boundary**; the launcher creates the subject, retains the handle, writes the identity, enforces the bound. Arguments cross on disk one per line (an array through `pwsh -File` collapses). The launcher's own streams go to `.launch-log.N`, never into the subject's OUT/ERR or the driver's log | #1, #3 |
| 3 | `win_exe()` resolves the program to a Windows path **at the call**, so an unresolvable program is refused where it is still true that nothing was launched | #3 |
| 4-6 | the records the change falsified are corrected: `BOUND_EXPIRED` no longer claims it "attempted to stop the operation"; the `KILL_GRACE_S` reserve is described as the launcher's return, not an escalation | — |
| 7-8 | the header's `KILL_GRACE_S` note and the four-point design comment rewritten to what is now true | — |
| 9 | `capture_run_identities()` **:1239**: the interposed `env` is gone. `SPT_D2_HOME` is exported around the call and inherited, and unset immediately after, so the intended executable IS the direct child | #3 |
| 10 | the instrument gate takes `launch_bounded.ps1` as a **seventh** dependency and hashes it into `INSTRUMENTS.sha256` | — |
| 11 | the ledger counts direct subjects and coverage rows, and states that no whole operation is reported CONFIRMED_GONE | #2 |

**No termination is added anywhere.** Tree kill is withdrawn from this step: on expiry the driver
records `subject_state=UNREADABLE reason=bound-expired-no-termination-authorized`, measures the
subject's disposition, and stops nothing. **That is a real consequence — an expired step's subject
may keep running** — and the driver now says so in its own output instead of printing a claim.

## 3. Pins

| file | sha256 |
|---|---|
| `fp-driver-d2-r3.sh` (source, ACCEPTED) | `48f1afcf620351d91e1e992f266b24a677d81148addb3b81c72a0639bd884f95` |
| `fp-driver-d2-r4.sh` | `5fb75766eba3a89d91578b27742498f80d1b20d26206791b5d55f141a36dc78a` |
| `build-driver-r4.py` | `0f07f3e189486c3da7927f276f69b5ee3a371137562eab4342a79c6d64f300e0` |
| `fp-driver-d2-r3-to-r4.diff` (393 lines) | `8bc09041047e805b063cc16403c33c6f2b48a8323f705f6f2635ca021ed42b5b` |
| `fp-bin-launch_bounded.ps1` (source for `fp-bin/launch_bounded.ps1`) | `c0050c3e245fa9c17096935496af3515f12359ca50c0a76647e717999be4ea76` |
| `controls/group-l.sh` | `2a895ec38fa9b97fbe69c1ef57285c69d6bf9e6fa53052366597a43d2a4f349f` |
| `controls/launch-identity-probe.ps1` | `bfd6d70baa4f97909b7a615f4d610a748cab4ef46685cc6dce368f6912679bbe` |
| `LAUNCH-IDENTITY-DESIGN.md` (r2 + §6 results, §7 status) | `2ea2ca0d23cf4070ce5a4a5ce5af7c55000813a66b25287062dfbe10017c6878` |

## 4. What is NOT established

* **r4 is UNEXERCISED.** It parses (`bash -n`) and every anchor matched exactly once, and that is
  all. Exercising `bounded()` end to end is an L2 arm, and L2 is HELD under the current scope. A
  successor that has only been read is not a successor that has been measured.
* `launch_bounded.ps1` has **not been run**; the probe that measured the same mechanism
  (`launch-identity-probe.ps1`) is a different file, and their agreement is a design argument, not
  a measurement of the instrument r4 actually calls.
* The instrument is **not placed**. It is a source artifact here; placement is provisioning.
* The historical gap stays permanent (doyle 64YIGUUN): the five wrapper identities already
  measured GONE stay that, and the subjects they bounded stay UNREADABLE for good.
* Group A's arms encode r2/r3 expectations (`CONFIRMED_GONE`/`SURVIVING`). They pin the r2 driver,
  so they are unaffected — but any future control over r4 needs expectations written to r4's
  vocabulary, not r2's.

## 5. What I would ask for next, in order

1. **L2** (a real call site through the new boundary: subject exe named, exit verbatim) — the
   smallest arm that turns "parses" into "measured".
2. **L4** (the `:1239` shape with the intermediary removed) and **L6** (coverage cannot reach
   CLEAR).
3. Then, as a SEPARATE proposal, **enforced containment** (a job object with kill-on-close) —
   the only thing that would make `coverage=COMPLETE` mean anything — together with L3/L5 and the
   termination controls that are held behind it.
