From c8bae3a4a3297d0fc1ace81fece507cf985e19a3 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Wed, 2 Sep 2026 14:37:36 +0000 Subject: [PATCH] Clarify remote manifest recovery --- internal/artifacts/current_state_commit.go | 2 +- internal/artifacts/remote_commit_test.go | 13 +++++++++++++ internal/manifest/store.go | 4 ++-- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/artifacts/current_state_commit.go b/internal/artifacts/current_state_commit.go index 067dc84..2378575 100644 --- a/internal/artifacts/current_state_commit.go +++ b/internal/artifacts/current_state_commit.go @@ -147,7 +147,7 @@ func readCurrentStateControlObject(ctx context.Context, store storage.ObjectStor func decodeCommittedManifest(ctx context.Context, data []byte) (*manifest.Manifest, error) { m, err := (&manifest.LocalStore{}).LoadReader(ctx, bytes.NewReader(data)) if err != nil { - return nil, fmt.Errorf("committed session manifest decode failed: %w", err) + return nil, fmt.Errorf("committed session manifest decode failed: %w; republish this session to replace unsupported remote state", err) } return m, nil } diff --git a/internal/artifacts/remote_commit_test.go b/internal/artifacts/remote_commit_test.go index fbdf23f..4e2784a 100644 --- a/internal/artifacts/remote_commit_test.go +++ b/internal/artifacts/remote_commit_test.go @@ -92,6 +92,19 @@ func TestLoadCurrentStateUsesMetadataFromOpenedObjectVersion(t *testing.T) { } } +func TestDecodeCommittedManifestGuidesRemoteRecovery(t *testing.T) { + _, err := decodeCommittedManifest(context.Background(), []byte(`{"session_id":"2026-05-03"}`)) + if err == nil { + t.Fatal("decodeCommittedManifest() error = nil, want unsupported schema failure") + } + if !strings.Contains(err.Error(), "schema_version is required") || !strings.Contains(err.Error(), "republish this session") { + t.Fatalf("decodeCommittedManifest() error = %v, want schema and republish guidance", err) + } + if strings.Contains(err.Error(), "local state") { + t.Fatalf("decodeCommittedManifest() error = %v, must not describe remote state as local", err) + } +} + func TestLoadCurrentStateRejectsPointerCommitIdentityMismatch(t *testing.T) { store := &storage.FakeBackend{} prefix := testCurrentSessionPrefix() diff --git a/internal/manifest/store.go b/internal/manifest/store.go index f9a237e..7f54986 100644 --- a/internal/manifest/store.go +++ b/internal/manifest/store.go @@ -398,9 +398,9 @@ func validateManifestSchemaVersion(kind, version, supported string) error { return nil } if version == "" { - return fmt.Errorf("%s schema_version is required; move aside and regenerate this unsupported local state (supported: %s)", kind, supported) + return fmt.Errorf("%s schema_version is required; replace or regenerate this unsupported state (supported: %s)", kind, supported) } - return fmt.Errorf("unsupported %s schema_version %q; move aside and regenerate this unsupported local state (supported: %s)", kind, version, supported) + return fmt.Errorf("unsupported %s schema_version %q; replace or regenerate this unsupported state (supported: %s)", kind, version, supported) } func validateSessionStages(stages map[string]*StageRecord) error {