---
name: v0180-items-3-5-and-f032
description: "2026-07-08 v0.18.0 SHIPPED (NEXT-WORKLOAD-PLAN Items 3-5, one release) + F-032 commune-ingest black-hole RCA filed to doyle"
metadata: 
  node_type: memory
  type: project
  originSessionId: 9f809150-e92c-474b-8ff6-ee237b441071
---

**2026-07-08 — v0.18.0 SHIPPED + node-applied** (0.17.4→0.18.0, re-registered; floor held 0.27.0). NEXT-WORKLOAD-PLAN Items 3-5 rolled into ONE release. Gate green: 245 tests, traceable-reqs check, skeleton-validate, manifest-schema, docs-drift all PASS. Binary changed (hook + translate) → win native (`ci/digest/build.sh`) + linux (cargo-zigbuild, zig 0.14.1 from `~/.sptc-zig`). GH release published w/ fat adapter.spt asset.

- **Item 3 = `/sptc:role [<directive>] [--include-desc]`** (REQ-ROLE-EDIT-ROUNDTRIP). Show/edit durable role (`spt endpoint role`, sole file writer; tracked/agents/<id>/live-role.md) + optional `endpoint description set`. THREE paths: (A) directive present OR harness-hosted → agent-mediated NL edit via injected `skills/role.md`; (B) bare + spt-hosted → tagged-input round-trip: UPS self-sends `{"role_edit":"v1","role":…[,"desc":…]}` --force-native → `translate.rs::commands_for_role_edit` TYPES current role into input box wrapped `<sptc_role_edit>`/`<sptc_desc_edit>`, NO enter (only choreography that leaves text in box; soft-newlines safe BECAUSE no enter to coalesce — inverse of rename/wake hazard); (C) operator edits+submits → UPS `commit_role_edit` catches block → `endpoint role --overwrite <tmp>` (write_spill stage) + `description set`, loud-on-fail (spt_strict). New plugin/sptc/skills/role skeleton + [strings.skills].role. Code: hook.rs role_args/extract_block/commit_role_edit/role_edit_payload + handle_user_prompt_submit 3-path branch + pending/saved/failed contexts; translate.rs role_edit_directive/commands_for_role_edit/strip_cr + dispatch_event branch.
- **Item 4 = version-gated update nudge** (REQ-UPDATE-NUDGE-VERSION-GATED). render_frames path: parse_update_notify_version (from=spt-update EVENT only, peer-msg can't trigger) + version_lt vs `spt --version`; append self-suppressing `<spt_update_available>` in UPS ONLY when local<available; NO agent-side `notif dismiss` (cross-node suppression hazard). Live gate case: node on 0.29.0, notify says 0.29.1.
- **Item 5 = commune-poll reword** (doc-only, no new REQ; folds under REQ-COMMUNE-CONTEXT-TIER-SLICING brief assert). live-ops.md + live.md: "file disappearing = success signal" → "ingested asynchronously, fire-and-forget; do NOT watch for the file to disappear". Doubly-correct given F-032.

**ACTIVATION SPLIT (important):** hook-side (Item 4 nudge, Item 3 commit-catch + initiate self-send, Item 5 strings) is LIVE NOW — hook binary resolves fresh per-event from install dir, no bounce. Item 3 translate-side draft-typing (`commands_for_role_edit`) rides the PERSISTENT translation binary → needs an ENDPOINT BOUNCE to pick up. `/sptc:role` COMMAND recognition (plugin skeleton, cplugs 0.1.12) needs operator: cplugs repo commit/push + `claude plugin install sptc@cplugs` + `/reload-plugins`. Skeleton staged to `~/.claude/plugins/marketplaces/cplugs/plugins/sptc`.

**F-032 → REQ-HAZARD-COMMUNE-INGEST-BLACKHOLE (doyle minted @6767a4d, CORE defect).** Diagnosed live: this session's SessionStart `<project-context>` was ~6 releases / 2 days STALE (v0.15.9), missing Items-3-5 next-steps — survived only because MEMORY.md (separate auto-memory) held them. RCA: last session (0841835d) wrote a CORRECT two-sliced commune (22:27:21Z, 5595B, `<project-context>` had v0.17.4 + Items 3-5), daemon DELETED the file (ingested) yet BOTH tiers stayed frozen at v0.15.9. doyle code-pinned: `route_slices` (spt-live/src/ingest.rs:156) GATES project tier on non-empty project_id — owlery-internal/unresolved cwd → empty project_id → `<project-context>` slice parsed but NEVER committed, while `ingest_drops` (ingest.rs:200) DELETES the drop unconditionally = the black-hole. Adapter EXONERATED. Operator invariant (encode as REQ-HAZARD): a disk file must ALWAYS represent the latest commune — the source commune OR the committed slices — never a volatile-memory-only window; commit-before-delete atomic ordering. Repro fixture (exact bytes) at `C:\Users\decid\AppData\Local\Temp\F-032-commune-2026-07-08T222721Z.md` (sha256 prefix 9bc27e18). **TRACE LESSON: live-agent session logs live under `~/.ccs/instances/bigscreen/projects/…`, NOT `~/.claude/projects/…` (CLAUDE_CONFIG_DIR relocation) — /trace default path misses them.**

**RESOLVED — adapter-musl-parity → v0.18.1 SHIPPED+applied (2026-07-08).** spt-core v0.30.0 (counter 51, deployah) added a static-musl Linux tier for pre-glibc-2.39 hosts. deployah pinned (cli.rs:4968 ADR-0024): fat-adapter extraction resolves by the RECIPIENT's own `current_platform()`; on a musl host spt-core IS the musl build → current_platform()=x86_64-unknown-linux-musl → extraction seeks the musl subdir STRICTLY (NoArtifactForPlatform, NO gnu fallback). So a gnu-only fat archive was UNEXTRACTABLE on musl hosts (not just glibc-broken). FIX v0.18.1: added x86_64-unknown-linux-musl as a THIRD triple in the fat adapter.spt (`rustup target add` + `cargo-zigbuild --target x86_64-unknown-linux-musl`); package-adapter.sh + tests/adapter-archive.sh both gained the MUSL_TRIPLE stage/tar/validate + allowlist legs. gnu stays default Linux. BACKWARD-SAFE: pre-0.30.0 core treats the musl subdir as a harmless stray shared-root entry on gnu/win hosts → **floor UNCHANGED (0.27.0)**. No logic change; win/gnu binaries reused. RECIPE UPDATE: the fat adapter.spt now needs THREE cargo-zigbuild targets (win native + gnu + musl) — musl only if the binary changed.

Related: [[v0173-send-stderr-noperch]] (prior session, Items 1-2), [[v0170-tag-messaging]].
