carlos / platform Public

plan: region HA 1a rev 5, answering Astra plan round 4 (LoadWake)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Paul Campbell pushed by claude agent, operated by paul@keymail.dev d1c17e05941166f6de3d6479e4b03b916cca9466 parent f02adba
2 files changed, +54 −7
  • docs/superpowers/plans/2026-10-05-region-ha-1a-foundations.md +37 −7
  • docs/superpowers/plans/CODEX-PLAN-REGION-HA-1A-BRIEF-5.md +17 −0

CI cancelled — superseded by a newer push — run details

diff --git a/docs/superpowers/plans/2026-10-05-region-ha-1a-foundations.md b/docs/superpowers/plans/2026-10-05-region-ha-1a-foundations.md
index 49ef606a4..1496539f1 100644
--- a/docs/superpowers/plans/2026-10-05-region-ha-1a-foundations.md
+++ b/docs/superpowers/plans/2026-10-05-region-ha-1a-foundations.md
@@ -5440,6 +5440,27 @@ func TestLoadWakeWithNoneReportsNotFound(t *testing.T) {
}
}
+// A manifest that names wake state whose object has gone is lost data,
+// not a host without timers.
+func TestLoadWakeWithItsObjectMissingIsAnError(t *testing.T) {
+ ctx, s := context.Background(), release.NewDirStore(t.TempDir())
+ p := open(t, s)
+ if err := StageWake(ctx, p, WakeState{V: 1, Host: "shop.test", NextDue: 5}); err != nil {
+ t.Fatal(err)
+ }
+ commit(t, p)
+ m, _, err := Load(ctx, s, pfx)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if err := s.Delete(ctx, pfx+m.Platform[WakeItem].Object); err != nil {
+ t.Fatal(err)
+ }
+ if _, found, err := LoadWake(ctx, s, pfx, m); err == nil || found {
+ t.Fatalf("found = %v, err = %v; a missing wake object must be an error", found, err)
+ }
+}
+
func TestImportWakeRefusesAnotherHostsState(t *testing.T) {
r := wakeReg(t)
seedHost(t, r, "shop.test")
@@ -5501,9 +5522,7 @@ package hostfiles
import (
"context"
"encoding/json"
- "errors"
"fmt"
- "os"
"github.com/carlosframework/platform/internal/registry"
"github.com/carlosframework/platform/internal/release"
@@ -5608,15 +5627,18 @@ func StageWake(ctx context.Context, p *Publisher, ws WakeState) error {
return p.StagePlatform(ctx, WakeItem, body)
}
-// LoadWake reads the wake state a manifest carries. The bool is false when
-// it carries none.
+// LoadWake reads the wake state a manifest carries. The bool is false only
+// when the manifest has no wake entry at all. A manifest that names wake
+// state whose object is missing or damaged is an error: that is lost
+// timers, not a host with none, and the caller must not install as if it
+// were.
func LoadWake(ctx context.Context, s release.Store, prefix string, m Manifest) (WakeState, bool, error) {
- body, err := ReadPlatform(ctx, s, prefix, m, WakeItem)
- if errors.Is(err, os.ErrNotExist) {
+ if _, ok := m.Platform[WakeItem]; !ok {
return WakeState{}, false, nil
}
+ body, err := ReadPlatform(ctx, s, prefix, m, WakeItem)
if err != nil {
- return WakeState{}, false, err
+ return WakeState{}, false, fmt.Errorf("hostfiles: the manifest names wake state that cannot be read: %w", err)
}
var ws WakeState
if err := json.Unmarshal(body, &ws); err != nil {
@@ -6690,3 +6712,11 @@ Findings are in `CODEX-PLAN-REGION-HA-1A-R3.md`. Round 3 marked every round 2 fi
| 2 | P2 Task 5: syncing a directory that vanished under a replacement file | fixed: only directories that still exist as real directories are synced; tested with `a/b/c` becoming `a` |
| 3 | P2 Task 7: the held-open test did not need `IN_MODIFY` | fixed: a second write through the same open descriptor must be published |
| 4 | P2 Task 7: `-run Watcher` missed one real-inotify test | fixed: the test is renamed so all seven match |
+
+## Astra plan round 4: dispositions
+
+Findings are in `CODEX-PLAN-REGION-HA-1A-R4.md`. Round 4 marked every outstanding finding resolved, found no task that uses a later task's identifier, and raised one.
+
+| # | Finding | Disposition |
+|---|---|---|
+| 1 | P2 Task 8: wake state named by the manifest but missing its object read as "no wake state" | fixed: `LoadWake` reports absence only when the manifest has no wake entry; any failure to read a named entry is an error; `TestLoadWakeWithItsObjectMissingIsAnError` |
diff --git a/docs/superpowers/plans/CODEX-PLAN-REGION-HA-1A-BRIEF-5.md b/docs/superpowers/plans/CODEX-PLAN-REGION-HA-1A-BRIEF-5.md
new file mode 100644
index 000000000..0a19cab58
--- /dev/null
+++ b/docs/superpowers/plans/CODEX-PLAN-REGION-HA-1A-BRIEF-5.md
@@ -0,0 +1,17 @@
+# Review brief: region HA plan 1a (foundations), round 5
+
+Read `CODEX-PLAN-REGION-HA-1A-BRIEF-1.md` first: its "Fixed: do not
+re-argue" and "What to check" sections still apply, to the plan at the
+commit named in the prompt.
+
+## Round 5
+
+This revision answers your round 4 (`CODEX-PLAN-REGION-HA-1A-R4.md`): one
+finding, in `LoadWake` (Task 8). The change was dry-run with the wake
+tests. Give a disposition for it, then report only new findings that
+this change introduces, or anything in the plan that is still unsafe or
+would not build. Do not re-raise anything marked resolved in any round.
+
+## Output
+
+As round 1. End with a verdict: ready to build, or not ready.