# P15-086 Stage0 Decision

Status: `GO`. G04 and G05 authorize B28 partial subextent decoding for LZ4,
LZMA, and Deflate. Zstd is not authorized for partial decoding and must use the
exact full-decode fallback for ordinary strict subextent reads. Existing
partial-reference maps retain their bounded-prefix path. Shifted, interlaced,
unknown, and future backends also remain on full fallback unless a new gate
authorizes them.

The gate is bound to DUT BASE
`6bf5724619be70f805bbe7d1ba77dd70cdced69f`, FreeBSD source HEAD
`106727738dcfb6c001b46f25363b91cece970085`, erofs-utils generations v1.4,
v1.7, and v1.8.6 for LZ4, erofs-utils 1.8.6 for the stream codecs, liblz4
1.10.0, liblzma 5.8.1, zlib 1.3.1, and libzstd 1.5.7.

## Authoritative Run

The gate ran once from `/work/erofs-freebsd-pre` as:

```sh
timeout -k 10 240 repo-pre-15/tests/pre15/gates/P15-086.sh \
    --base 6bf5724619be70f805bbe7d1ba77dd70cdced69f \
    --output planning/pre15/evidence/20260815T154915Z-G04-G05-P15-086/gate-output
```

It returned 0 and recorded G04=`GO`, G05=`GO`, and B28=`AUTHORIZED`.
Evidence is rooted at
`planning/pre15/evidence/20260815T154915Z-G04-G05-P15-086/`. The authoritative
script SHA-256 is
`591e407f20a6c8ab5d506329b3bd39ff7bd7f78b66ac86b9db2c45a498b31184`, the
input SHA-256 is
`62f7f505aef846fa85085039b2f47e252e11602e6ef1bf41f56841cdc9089a2a`, and
the result SHA-256 is
`33ef86b73447cd8c8099dc33901b9c4fff6c8ecedda3837d25cac9463a369d4f`.

## Decision Rule

Each codec is decided independently. A codec is partial-capable only when real,
twice-reproduced EROFS input decodes every requested range to the exact full
slice, reports a consumed-byte boundary before the end of the stream, leaves
guard pages unchanged, preserves positive FreeBSD errno, and reduces peak
temporary bytes by at least 20 percent without exceeding the fixed hard budget.
Failure of the benefit subgate selects exact full fallback for that codec; an
incorrect slice, unbounded memory, missing corruption boundary, or missing
oracle stops P15-086.

## Reproducible Corpus

All images are fixed-time, fixed-UUID, root-owned, and generated twice with
identical bytes. Matching fsck reconstructs every legal source.

| Codec | Generator | Image SHA-256 | Logical bytes | Physical bytes | Leading zero bytes | Stream bytes |
|---|---|---|---:|---:|---:|---:|
| LZ4 | v1.4 | `8f940673ed9f7e00efc5c0f06d41b2216748ea84256b740751aabff0d632de2b` | 1,038,906 | 4,096 | 0 | 4,096 |
| LZ4 | v1.7 | `93451e563f4eaf95b2690381074b5dfb3da0257691043c51619fd7d4c68dba7e` | 1,038,906 | 4,096 | 0 | 4,096 |
| LZ4 | v1.8.6 | `853649c78b159161421a6e833e0c516216382f3e8d135fc80aacd509ddb27b2c` | 1,038,906 | 4,096 | 0 | 4,096 |
| Deflate | 1.8.6 | `5f98ff39be30b1396be8164e54a8ae80b144d181d5295a640b2e7814406d7a2d` | 22,878 | 4,096 | 1 | 4,095 |
| LZMA | 1.8.6 | `887d4a9baf629533c8d512177a84ca256a20135157d29a201408534f63230889` | 151,552 | 4,096 | 3,556 | 540 |
| Zstd | 1.8.6 | `93f6beb46e77187ea8b0fc1ad3a5a1cb565d546d9ce40d51278f26d67187d5fa` | 151,552 | 4,096 | 1,092 | 3,004 |

The LZ4 corpus spans all three historical generators required by G04. Stream
codec consumption is reported by independent liblzma, zlib, and libzstd
decoders after the common EROFS leading-zero padding is removed. LZ4 is checked
by an independent raw parser and liblz4 partial/full output.

## Hard Budget and Benefit

The fixed input cap is 1 MiB, the decoded-output cap is 12 MiB, and the caller
cap is 1 MiB. Codec workspace caps are 0 for LZ4, 512 KiB for Deflate, 9 MiB
for LZMA, and 4 MiB for Zstd. These caps cover the frozen format maxima rather
than only the selected 4 KiB pclusters.

| Codec | Workspace full/partial | Hard cap | Baseline peak | Candidate peak | Reduction | CPU median partial/full | Decision |
|---|---:|---:|---:|---:|---:|---:|---|
| LZ4 v1.8.6 | 0 / 0 | 14,680,064 | 1,047,098 | 12,288 | 98.826% | 10,688 / 208,150 ns | `GO` |
| Deflate | 39,928 / 39,928 | 15,204,352 | 70,998 | 52,216 | 26.454% | 14,207 / 61,627 ns | `GO` |
| LZMA | 98,992 / 98,992 | 24,117,248 | 258,736 | 111,280 | 56.991% | 21,384 / 80,329 ns | `GO` |
| Zstd | 95,992 / 313,080 | 18,874,368 | 255,736 | 325,368 | -27.228% | 109,253 / 91,015 ns | `FULL_FALLBACK` |

All three LZ4 generations have the same 98.826 percent memory reduction; their
partial/full CPU ratios are 4.845, 4.632, and 5.135 percent. The gate collected
nine samples of 25 decodes per mode and stopped at that fixed sample count.
CPU timings are diagnostic because host scheduling produced visible outliers;
the authorization is based on deterministic peak temporary bytes. No noisy CPU
sample is used to rescue a codec that misses the 20 percent memory threshold.

## Ranges, Corruption, and Errno

Prefix, cross-page, middle, and tail requests all match the corresponding full
slice. The tail request reaches the extent end and therefore exercises full
fallback. Prefix consumption is 1,032 bytes for LZ4, 805 for Deflate, 352 for
LZMA, and 1,457 for Zstd. Corruption begins later at stream offsets 4,032,
4,031, 476, and 2,940 respectively. Every partial prefix remains byte-exact;
the same full read and every one-byte truncation return positive `EINTEGRITY`
(97). Real corrupted EROFS images fail matching fsck. All output guards and
codec cleanup checks pass.

Partial success is only evidence that the requested slice is correct. It is not
reported as verification of bytes after the consumed boundary or of the full
extent.

## State and Cleanup Model

B28 adds no persistent cache, owner, waiter, pool, or unmount-drain state. A
cache hit remains first. A gate-authorized strict subextent miss decodes into a
request-local bounded prefix and never publishes a partial cache entry. Full
requests, unsupported ordinary strict subextent codecs, shifted/interlaced
maps, and arithmetic fallback retain the existing exact full-decode/cache
policy. Existing partial-reference maps remain bounded-prefix and
cache-ineligible. Failure frees the local output after input release; success
publishes no shared partial state. Reclaim, eviction, unmount, and key reuse
therefore retain their existing ownership model.

The owned temporary tree was removed and the evidence SHA-256 manifest verifies
in full. No QEMU process was started. Protected PID 26318, port 9222, and the
shared base image were not touched. The full feature suite was not run.

## Consequence

B28 may implement bounded-prefix decode only for LZ4, LZMA, and Deflate in the
exact planned write set for ordinary strict subextent reads. Zstd and all
non-authorized backends must retain exact full fallback there without returning
an unsupported error; existing partial-reference behavior remains unchanged.
B28 acceptance owns D, the targeted TC176 host case, both KLD configurations,
and strict-timeout TC176 QEMU. It must preserve guards, consumed-byte semantics,
positive errno, cache eligibility, provider/GEOM ownership, and cleanup
ordering.

## B28 Execution Outcome

B28 source/test commit
`7a0d7e4a4047ac6d6130a3be5cb677cb94979fe7` has the exact 11-path actual
write set. LZ4, LZMA, and Deflate ordinary strict subextent reads decode a
bounded prefix; Zstd and non-authorized backends use exact full fallback.
Existing partial-reference maps remain bounded-prefix and cache-ineligible.

Final D, targeted host TC176 subset
`20260815T163642Z-host-B28-partial-1356298-0`, and targeted zstdio0/zstdio1 K2
`20260815T163515Z-host-B28-partial-1355895-0` pass. Earlier host and K2
`RUNNER_FAIL` records are retained with their corrected oracle/build findings.
The strict-timeout QEMU run
`20260815T163824Z-qemu-B28-partial-1356729-0` is `INFRA_BLOCKED` because guest
SSH did not become ready before the boot deadline; it did not reach the target
marker, so no guest TC176 runtime PASS is claimed. Owned cleanup passes,
protected PID 26318 and port 9222 were untouched, and the full feature suite was
not run. Complete evidence is under
`planning/pre15/evidence/20260815T161336Z-B28/`.
