# PACER-PLAN — M3: the pacer milestone (JIT)

> Derived from repo requests **#1–#5** in the operator grill of 2026-07-26. Vocabulary is
> authoritative in `CONTEXT.md` (already re-keyed); the naming cluster is `docs/adr/0002`.
> M2 (`PACKAGING-PLAN.md`) is **absorbed here** — spt-core 0.44.0's install-dir-first spawn
> resolution dissolved its blocker.

## Goal

Ship **`PACER` 0.3.0**: the full rename (adapter `PACER`, repo `spt-pacer-tool`, binary
`pacer-shell`), every send signed `--from PACER-0`, the **stretch report**, the **classify**
control with a durable per-owner registry, and self-contained fat-archive packaging on
`min_spt_core_version = "0.44.0"` — one release, one clean-break cutover.

## Ruled decisions (grill summary — the *what*; CONTEXT.md holds the *meaning*)

| Area | Ruling |
|---|---|
| Naming | Adapter id `PACER` (caps) ⇒ instance `PACER-0`; repo/binary/prose lowercase; ADR-0002 |
| Signature | ALL sends `--from PACER-0` (canonical id from bind); alias-follow deferred (core ask filed) |
| Stretch report | idle→busy edge, floor **≥60s**, always sent incl. post-ping stretches, `--active-only`, dual time format, durations second-precision (`8m20s`) |
| Stretch id | 6 chars, lowercase alnum minus `0/o/1/l`, minted only for reportable stretches, pending window cap 10 FIFO, classified ids leave it, unknown/evicted id in a control ⇒ ignored |
| Classify | `!!classify=<id>:<name>!!` + verb `classify <id> <name>`; **additive** — every new code past the watermark applies in `seq` order (steering codes keep highest-seq-wins); snake_case `[a-z0-9_]` ≤32 |
| Registry | per owner; `name → {count, mean_secs, last_classified}`; running mean, no decay; cap 50 classes, evict least-recently-classified; report lists ≤15 by count desc, `+K more` tail names the state-file path |
| State | `<install_dir>/state/<owner>.json`, atomic rewrite (temp+rename); registry + pending ids + **digest watermark** (durable `acted_seq` rider — closes the restart-replay window) |
| Packaging | fat `adapter.spt`: root manifest + `x86_64-pc-windows-msvc/` + `x86_64-unknown-linux-gnu/` + `x86_64-unknown-linux-musl/` (claude-spt pattern); one-command install; PATH install path deleted from README |
| Floor | `min_spt_core_version = "0.44.0"` (shell spawn resolves install-dir-first there) |
| Cutover | clean break: teardown → `adapter remove rebound` → `adapter add --release BigscreenVR/spt-pacer-tool --gh` → `spawn PACER`; message doyle; no bridge |
| Status verb | gains pending unclassified ids + registry class count |
| Education | +3 lines: stretch report, `PACER-0` signature, classify code |

## Tasks (ordered)

1. **Probes before build** (each is a hazard req):
   - Caps adapter name: register a throwaway `PACER`-named probe manifest
     (`REQ-HAZARD-PACER-CAPS-NAME`). Fallback if refused: adapter `pacer`, resident upcases
     its from-label — return to operator before adopting.
   - `spt send --from PACER-0` smoke test: arbitrary string accepted (operator-confirmed),
     verify how it renders in the receiving agent's EVENT `from`.
   - ~~Musl-in-fat-archive~~ **RESOLVED (doyle, 2026-07-26): the docs sentence is stale —
     musl recognition landed in core v0.30.0 (MUSL-TIER); a musl node self-IDs as the musl
     triple and the extractor selects+flattens it like the other two. Pack it with
     confidence.** Docs fix rides spt-core PR #98.
   - **Docs-publish gate:** 0.44.0's install-dir-first *shell spawn* resolution is shipped
     but reaches the PUBLISHED docs only in PR #98 (per doyle). Build discipline gates on
     published docs — confirm #98 has published before declaring task 9 done.
2. **Rename sweep**: manifest (`name = "PACER"`, `version = "0.3.0"`,
   `min_spt_core_version = "0.44.0"`, binary refs → `pacer-shell`); crate/binary rename;
   `REQ-REBOUND-*` → `REQ-PACER-*` in `traceable-reqs.toml` + every tag; docs sweep
   (README, plans, KNOWN-HAZARDS, docs-site); CHANGELOG `[0.3.0]` rename entry.
   GitHub repo rename → `spt-pacer-tool` (redirect retained, not relied on); local dir rename.
3. **Signature**: `--from PACER-0` added centrally in `spt_send` (id captured at bind).
   `REQ-PACER-SIGNATURE`.
4. **Durable state**: state module — load/rewrite `<install_dir>/state/<owner>.json`; derive
   install dir from the conventional adapters root + own adapter name (no substitution key
   needed); registry + pending window + watermark. `REQ-PACER-STATE-DURABLE`.
   - Update-wipe canary: drop a canary file, run the 0.3.0→next `adapter update`, confirm
     `state/` survives re-extraction (`REQ-HAZARD-PACER-STATE-WIPE-ON-UPDATE`). If update
     wipes: back to operator with options before 0.3.1.
5. **Stretch report** per rulings; id minting at the qualifying idle→busy edge.
   `REQ-PACER-STRETCH-REPORT`.
6. **Classify**: parser form (quotation-guard + watermark inherited; additive semantics),
   registry fold-in, `classify` capability verb in manifest + dispatch.
   `REQ-PACER-CLASSIFY`.
7. **Status verb extension** (pending ids, class count) — extend the existing status tests.
8. **Education update** (+3 lines, stays terse); boundary re-send machinery unchanged.
9. **Packaging**: pack script builds the fat archive (3 triple subdirs, flattened-on-install
   contract); `[update]` avenue unchanged (`gh_release`, new repo name); README rewritten to
   the one-command install; 0.2.0's "binary onto your PATH" path deleted.
10. **Hazard tests**: caps-name fallback guard, state-file atomicity (kill mid-rewrite),
    classify replay (`seq` watermark), evicted-id ignore, report floor edge (59s vs 60s),
    report-after-ping carries final duration.
11. **Release 0.3.0**: gates green → tag → `gh release create` (fat `adapter.spt` asset) →
    verify by digest (runbook) → cutover: message doyle the three-line migration, tear down
    own `rebound-0`, re-add + `spawn PACER`, live E2E on the M1 rig (report + classify round
    trip) → close #1–#5 with ruling comments.
12. **Aftercare**: retire `PACKAGING-PLAN.md` (absorbed-note already prepended); amend
    ADR-0002 when the alias-over-link ask lands; watch doyle's musl answer.

## Requirement activation (at build start)

Sweep first (rename, task 2), then activate: `REQ-PACER-SIGNATURE`, `REQ-PACER-STRETCH-REPORT`,
`REQ-PACER-CLASSIFY`, `REQ-PACER-STATE-DURABLE` to `["doc","impl","unit"]` (+`"int"` where the
M1 rig can exercise the live leg), and the two new hazards with tests per KNOWN-HAZARDS
convention. Doc-stage evidence exists now (CONTEXT.md entries, ADR-0002, this plan) — tag it
when activating.

## Gate

`cargo build` + `cargo test` green, `traceable-reqs check` green, fat-archive install verified
on this node (`adapter add --release` → `spawn PACER` → bind online), live E2E: one stretch
report received and one classify code round-tripped into the registry file.
