carlos / platform Public

plan: pin task 7's manifest source — the sibling is best-effort, the hot path is not

Task 3's review found the trap pair: converge-on-version-change reading
the sibling would turn a failed best-effort write into leave-alone on
the very version being pointed live, and Set: m.Capabilities verbatim
would collapse resolved-declares-nothing into did-not-resolve, making
capability removal unreachable. ensureStaged returns the manifest it
fetched; the sibling re-read is the drift pass's posture only.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Paul Campbell 7d786af9e7352784b71173ee842bef123d69b7ce parent 4a92787
1 file changed, +4 −0
  • docs/superpowers/plans/2026-08-03-app-capabilities.md +4 −0
diff --git a/docs/superpowers/plans/2026-08-03-app-capabilities.md b/docs/superpowers/plans/2026-08-03-app-capabilities.md
index bc2e42683..7dd336ba2 100644
--- a/docs/superpowers/plans/2026-08-03-app-capabilities.md
+++ b/docs/superpowers/plans/2026-08-03-app-capabilities.md
@@ -738,6 +738,10 @@ Because every route in every existing `release` test is exec-backed (`Backing ==
**What the reviewer should try to break:** the canary fast loop picking up a capability-bearing version every 2-3 seconds and **not** converging it — meaning a freshly promoted canary runs the new binary against the old unit shape until the hourly root pass catches up. Decide and document: that window is accepted (the drop-in is repaired within the hour, and the alternative is the sandbox denial above), or the fast loop must skip capability routes entirely. **Recommended: accept, and log one line from the fast loop when it repoints a capability route so the window is visible.** Also: a hibernating unit route reaching `adoptHost` with `restart == nil` — converge must still run (its drop-ins are unit text, not a wake), but nothing may start it.
+**Two pins (added post-Task-3-review, 2026-08-03) — the orchestrator's ruling, binding on this task:**
+1. **The version-change converge builds its `Plan` from the `*Manifest` that `ensureStaged` already has in hand — change `ensureStaged` to return `(*Manifest, error)` — never from a sibling re-read.** The sibling write is best-effort (Task 3's C1/I2 fixes); re-reading it on the hot path would turn a failed sibling write into `(nil, nil)` → leave-alone → the new version pointed live with the previous version's drop-ins, silently. The sibling re-read belongs to Task 8's drift pass only, where leave-alone is the correct posture.
+2. **"Resolved but declares nothing" must not collapse into "did not resolve".** `Manifest.Capabilities` is `*caps.Set`, nil for both a legacy manifest and a fetch that never happened. When a manifest RESOLVED and `m.Capabilities == nil`, the `Plan` must carry `&caps.Set{V: caps.Version}` (or a separate `Resolved` flag) so converge REMOVES stale drop-ins, per spec §4d's removal semantics. `Set: m.Capabilities` verbatim would mean a capability dropped from a manifest is never removed — the exact opposite of the design.
+
---
### Task 8: `RunAdopt` — the grant-drift pass, the three advisories, and the DBPath stamp