---
name: f026-pickertruth-wave-progress
description: "BUILD-F026-PICKERTRUTH executor progress (todlando) — picker/presence truth wave on f026-pickertruth, doyle-gated per sha"
metadata: 
  node_type: memory
  type: project
  originSessionId: 9a4e6fb9-938a-4c4a-8ca8-94ad317aaf89
---

BUILD-F026-PICKERTRUTH — todlando executing on branch **f026-pickertruth** off main@e96f7d0 (v0.21.0), doyle gates per sha. Triage: docs/NEXT-MILESTONE-PICKER-TRIAGE.md. 9 REQs minted W0 + 3 added mid-wave.

## LANDED (doyle-gated green unless noted)
- **W0** @5adc527 — 9 REQ mints (stages=[]) + triage doc. PASS.
- **W1 #2** @ad609d5 — REQ-HAZARD-CONTROL-STAMP-LIFETIME: broker reap clears control/viewer stamps (stamp_reaped in exit-waiter). KH 7.27. PASS.
- **W1 #3** @ea400a6 — REQ-PICKER-CONTROLLED-LOCAL: locally-controlled renders CONTROLLED in own picker+list (EndpointRow.controlled, display_status driven_by||controlled). PASS.
- **W1 #9** @1f34005 — REQ-MSG-SELF-DETECT-ANCESTRY: detect_self_id leg(c) PID-ancestry (proc::parent_pid_of/process_ancestry + roster::match_self_by_ancestry NEAREST-first). Fixes cli@<node> mis-stamp. PASS.
- **W2 #1** @520c070 — REQ-PICKER-PROJECT-HISTORY-TRUTH: sessions.log-derived history (owlery-excluded, dedup project_id) + ProjectRef{id,dir} + disambiguate_project_ids. Folded #9 nearest-first. PASS.
- **W2 SI-1** @a18d4e2 — REQ-STORE-CONTEXT-BRANCH-FILL: RCA = daemon used RELATIVE commune_dir ".claude" VERBATIM → ingest read daemon-cwd not endpoint-cwd → BranchStore pristine box-wide. Fix: resolve-at-ingest against info.cwd (pulse_tick), owlery-gated project routing. KH 7.28 class rule. PASS FINAL.
- **W1-addendum convergence** @c8e2c93 — REQ-HAZARD-CONTROL-STAMP-CONVERGENCE (7.29): broker re-asserts stamps to session-table truth divergence-gated on KIND_SESSIONS (fixes stamp-before-bind loss = hall-b/ball-b picker-created uncontrolled-forever). PASS FINAL (combined isolated-worktree gate @77d46c5: clippy workspace clean, nextest daemon+live 576/576).
- **gap_a rewrite** @77d46c5 — convergence made driven_by_selfheal gap_a red (CORRECT interaction: broker has_controller==false DEFINITIVE clear vs brain controller_by==None ambiguous; pure-sha legs exonerated ad609d5 + a18d4e2 — the original red was moving-tree contamination). Ruling-rewrite: broker-MAY-clear + brain-MUST-NOT-clear (reconcile on pre-fetched live_sessions). KH 7.15↔7.29 cross-refs + 7.29 coverage boundary (has_controller==false leg ONLY; wedged-open remote stays EVICT/SEED, oracle=D4c NetPresence). PASS FINAL. **W1 STAMP STORY COMPLETE — all 8 commits @5adc527..77d46c5 doyle-gated PASS.**

- **W2 #4** @5fa1f14 — REQ-GOSSIP-ADAPTER-PROJECTS (impl+unit+int): 3 additive gossip fields on Instance+ResourceRow (serde-default N-1): adapter:Option<String> (info.adapter), recent_projects:Vec<String> (recent_projects_for = sessions.log newest-first, owlery-excl via reused lifecycle::is_owlery_internal, bounded MAX_GOSSIPED_PROJECTS=8, project IDs ONLY), controlled:bool EXPLICIT (doyle flip, NOT controller_node.is_some()). advertise_local populates, resource_projection maps, from_resource_row stops faking (adapter_profile=row.adapter / project_history=row.recent_projects / controlled=row.controlled verbatim). ~20 Instance literals fixed (script-inserted, harness_only-last anchor). Tests: from_resource_row map+N-1 unit / serde+projection units (registry.rs) / recent_projects_for unit (registryhost.rs) / parity INT extended w/ locally-controlled remote row (controlled=true,controller_node=None→CONTROLLED) + real adapter+projects thru gather. clippy: large_enum_variant allows on Resolution+RegistryFeedRecord (Instance grew; codebase keeps unboxed, precedent = targeted allows). GOTCHA `owl send <TARGET> [FROM]` = body on STDIN (2nd positional is FROM not message; pipe/heredoc the body). model.rs:948 confirm-gate LEFT driven_by-gated (ANOTHER-node-controls action gate ≠ display any-controller). AWAITING doyle gate @5fa1f14.
- **W3 #8** @7a12f94 — REQ-ENDPOINT-LIST-PROJECT-COL (impl+unit): endpoint list col `id / <project>/ / type / status` + additive --json project. InstanceCell.project_ref Option<ProjectRef>: local head via picker::data::latest_project_ref (pub(crate) now; #1 sessions.log head, derived at call site so this_node_cell stays pure), remote head via #4 recent_projects.first (IDs only no dir). format_instance_rows inserts col + disambiguate_project_ids per group + '-' unknown. EndpointRowJson.project + LocalPerchJson.project skip-if-none. NO clap change = NO docs regen (output-only + additive JSON). daemon-status local rows leave project None. FOLDED doyle's #4 model.rs:948 comment (WHY driven_by not ep.controlled). Tests: instance_rows_project_column / remote_cell_project_ref / json_project_field_skip_if_none. bin-unit 303/303. AWAITING doyle gate @7a12f94.
- **W3 #7** @ab35d81 — REQ-API-ENDPOINT-INFO (impl+unit): new `spt api endpoint-info [<id>]` read-only JSON, bare self-resolves via detect_self_id like whoami, no auth. DTO EndpointInfoJson{id,endpoint_type=info.state,adapter,local_node:{label,key},attached_node:{label,key}|null,controlled,project,cwd,subnets}; NodeRefJson{label,key}. controlled(any-controller) + WHO stay DISTINCT (doyle ruling). attached_node = pure derive_attached_node(driven_by,controlled,self_key,self_label,resolve_label): remote->that node / controlled+no-driver->THIS node (controlled-keyed #3/#4 lesson) / else null — CONSTRAINT doc-comment: self-attribution valid ONLY local perch read (future remote leg must NOT copy). Reads info.json direct (state/adapter/controlled/cwd/driven_by), independent of #4 gossip. project via shared picker::data::latest_project_ref; remote labels from gossiped node_labels. reference.md REGENERATED (+21, xtask check clean, no internal codes). Handler in api/reporting.rs, variant ApiCmd::EndpointInfo{id:Option<String>}. Tests: derive 3-branch + reports_and_refuses. bin-unit 305/305. int DEFERRED (in-crate handler runs full path). perri release-ping consumable (claude-spt UserPromptSubmit local+attached surfacing). AWAITING doyle gate @ab35d81 (queue after #8).
- **GATE VERDICTS: ALL FOUR PASS FINAL (doyle) — #4 @5fa1f14 / #8 @7a12f94 / #7 @ab35d81 / #10 @d2e9440. 360/360 nextest -p spt, clippy workspace clean, traceable exit0, xtask check ok.**
- **COSMETIC DEBT (defer, doyle zero-action)**: main.rs is_broken_pipe_panic bare "os error 32"/"232" substring could match 32x/232x codes — moot under the compound 'failed printing to std' prefix; tighten to "os error 32)"/"232)" next time in main.rs.
- **RIG ADDENDUM (doyle)**: sweep leaked spt.exe by Path AFTER nextest AND BEFORE xtask check.
- **micro #10** @d2e9440 — REQ-CLI-BROKEN-PIPE-TOLERANT (impl+unit): main.rs install_broken_pipe_guard() FIRST in main (before de-elevation) — print-macro broken-pipe panic exits 0 silent (SIGPIPE-equiv), other panics chain default hook. Cross-platform via is_broken_pipe_panic (needs BOTH 'failed printing to std' prefix AND broken-pipe Display: Unix os-32 / Win os-232) so genuine write-fail still surfaces. unit broken_pipe_panic_classifier. No CLI/help change. AWAITING doyle gate @d2e9440.
- **W1 + W2 + W3 + micro#10 COMPLETE.** Session landed 5: #4(PASS FINAL)/comment/#8/#7/#10 all pushed. Commune checkpoint written .claude/todlando-commune.md.

- **W4 #13** @623ec06 — REQ-XTASK-SPT-BIN-TARGET-DIR (impl+unit): MINTED this session. xtask spt_bin honors CARGO_TARGET_DIR via pure target_debug_dir(root,Option<&str>) (absolute as-is / non-empty relative→root.join / None|empty→root/target; then /debug). Fixes isolated-gate NotFound → gate rig can set CARGO_TARGET_DIR freely now (no more unset workaround). unit target_debug_dir_honors_cargo_target_dir.
- **W4 #5** @1c0a02c — REQ-PICKER-START-PROJECT-CHOICE (impl+unit): Screen::ChooseProject + run_cwd/choose_cursor pub fields (default empty; run() stamps current_dir). Pure should_offer_project_choice(run_cwd,&[ProjectRef])->bool (len0 false / len1 fires iff non-empty dir != run_cwd / len>1 true) + build_project_choices (most-recent head / `Here:<cwd>` only if distinct / rest newest-first). Confirm Start branch → enter_choose_project_if_warranted (divert) else today bringup; choose_project_outcome(headless) bakes cwd (empty→None). Keeps Confirm TOP panel. 3 model + 1 view unit.
- **W4 #6** @a390490 — REQ-PICKER-RESUME-CONTEXT-PANEL (impl+unit): render_resume adopts Confirm 3-row layout, reuses EXTRACTED render_selection_summary top panel (shared by Confirm/ChooseProject/Resume), swaps only bottom. 1 view unit.
- **WAVE-FINAL GATE VERDICT (doyle @a390490): PASS FINAL — WAVE COMPLETE.** Isolated worktree: clippy workspace CLEAN · nextest --workspace **1505/1505** (1 skipped=env-gated acceptance, 8 leaky swept per ritual) · traceable exit 0 · xtask check OK. All 3 W4 diffs PASS. **[twohost] CONFIRM YES** (#4 cross-node gossip N-1 claims proven by two-host ladder; tag in PR TITLE — head_commit NULL on pull_request, v0.17.0 lesson).
- **FULL WAVE LEDGER — 15 commits @5adc527..a390490, every sha doyle-gated PASS:** W0 seed · W1 #2/#3/#9 + convergence + gap_a-rewrite · W2 #1/SI-1/#4 · W3 #8/#7 · W4 #5/#6 · micros #10/#13.
- **WAVE REOPENED (1 test-only fix) @ffca259 — Linux deterministic red at PR#46/v0.22.0 cut.** kitsubito Linux leg caught what the Windows-only wave gate missed: lifecycle::tests::resolve_endpoint_drop_dir_cases (SI-1 @a18d4e2) hardcoded `Path::new("C:/abs/drop")` — NOT absolute on Linux → resolver joins under cwd → left=doubled path. Prod resolve_endpoint_drop_dir CORRECT, untouched. Fix: inline cfg! per-OS literals (cwd + abs), tag intact. Rebased onto deployah bump 7e29ffc (fast-forward, no force). Pre-flight Win: clippy --workspace clean + nextest lifecycle 24/24. LESSON [[gate-cross-platform-leg]]: path-semantics waves need a Linux leg + drive-letter-literal grep `"[A-Za-z]:[/\\]` before PASS. doyle RE-GATE VERDICT @ffca259 = PASS (Win worktree clippy + 1505/1505 + CI attempt-1 all-green incl Linux test leg + twohost a/b). deployah CLEARED to cut v0.22.0.
- **GO v0.22.0: deployah drives.** bump-in-PR · counter recount from PUBLISHED spt-releases metadata · update-set-before-flip candidate (v0.19.1 stale-window note). CHANGELOG scope = every user-facing surface v0.21.0..HEAD: picker choose-project/resume panels · endpoint-list project column · api endpoint-info · broken-pipe exit0 · remote-row truthful adapter/history/controlled · CONTROLLED display fixes. doyle CHANGELOG-vets + independent-verifies at PR gate.

## DEFERRED (doyle ruling, off v0.22.0)
- **#11 dead-pid presence** — stays SEED, awaits doyle RCA + design next triage cycle (thin evidence, no ride without RCA). kin presence-dead-shows-online; #9 already alive-gates roster self-detect.
- **#12** missing-binary silent-unbound = perri F-027 — her registry domain + validation loop; correct home = next wave w/ perri consumable cycle.
- **EVICT** (D4c NetPresence oracle) — wedged-open remote stays EVICT/SEED path.
- **DOYLE GATE RIG (hardened this wave)**: (1) isolated worktree-of-sha + worktree-local DEFAULT target (no CARGO_TARGET_DIR — sidesteps #13 xtask bug, still throwaway); (2) BEFORE nextest: build -p spt --bins AND -p mock-adapter --bins (else mock-session/mock-shell absent → e2e insta-fail "must be built"); (3) sweep leaked spt.exe by Path AFTER nextest + BEFORE xtask check; (4) legs: clippy workspace → nextest per-seam → traceable → xtask check when CLI/docs touched. Busy-CWD dir skeletons (deleted-exe stragglers) are harmless, reboot clears.

## PROTOCOL LESSONS
- Shared checkout w/ doyle: NEVER gate a moving tree — doyle's a18d4e2 gate build compiled my convergence WIP → false gap_a-red attribution. Announce build quiet-windows; doyle gates on isolated worktree + throwaway target + pinned sha.
- Every wave item: mint REQ (stages=[] W0) → activate on delivery → red-first (verified by revert-probe) → traceable+clippy → commit → push → ping doyle sha. doyle interim-gates per sha, FINAL full-suite.
- perri secondaries (SI-1 project-slice, #12) → release-ping consumables, cite as HER F-0xx registry not our wave code.
