carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

Reviewed the pinned plans and code read-only. No files changed or tests ran. All 28 cited witness names exist. The snapshot/anchor header choices match litestreamfacts, but the implementation series has the following blockers.

Code links below point to the pinned main checkout; claim-plan links identify unmerged dependencies.

  1. P1 — Plan 1, Task 2: duplicate Go identifier prevents compilation. Plan:400 declares type MoveLanding; line 433 declares const MoveLanding in the same package. Both extend provision.go:907. Rename the journal type, update its consumers, and compile the complete proposed declarations.
  1. P1 — Plan 2, Task 3: stop reconstruction introduces an import cycle. Plan:589 makes activator import stopevidence, which already imports activator and holds *activator.StopEvidence in evidence.go:10. The proposed a.cgroups also is not a field of Service. Move reconstruction above both packages or extract shared evidence types, and explicitly wire the backend’s cgroup manager.
  1. P1 — Index / Plan 3, Task 5: the quoted strict-spawn signature is wrong. Index:78 gives (*exec.Cmd, error). Claim Plan 6:878 returns (*exec.Cmd, *cgroup.Prepared, error) and requires retaining that prepared handle through process completion and checked cleanup. Correct the signature and make ownership of the handle explicit, including failed starts.
  1. P1 — Plan 1, Task 5: receipt recovery can seal stale data. Plan:1246 accepts a receipt’s version on ETag equality without validating the receipt against the current source. After copying A/v1, copying B/v2, and crashing before receipt persistence, the next round can seal v1 despite listing B. The relevant branches and persistence are mirror.go:186 and mirror.go:342. Require a complete matching receipt; recopy otherwise. Test crashes between copy acknowledgement and receipt persistence, including an absent receipt.
  1. P1 — Plan 1, Task 6: real staging leases can never pass the guard. Plan:1374 requires over 16 minutes remaining. Real acquisition uses a 15-minute TTL in lease.go:37, with an earlier SafeUntil. The passing test supplies an artificial 30-minute lease. Define a staging lease duration compatible with the signature margin, propagate its actual bound into cleanup, and test real acquisition settings.
  1. P1 — Plan 1, Tasks 6/14: checking time does not implement sign-at-check. Plan:1365 checks time before invoking ordinary SDK calls. Those calls still sign later and may re-sign retries; see mirror.go:474. A paused worker can therefore sign after its lease ends, violating §7.3/K5 and the cleanup bound. Specify timestamp-bound signing and retry behavior for every staging mutation. Test pauses between check and send, and retries after expiry.
  1. P1 — Plan 1, Task 14: move.json replay requires a read forbidden by M17. Plan:2848 requires the source to decode the target object after a 412. The source cannot read target moves/*; PutIfAbsent:277 returns only ErrExists, without the existing body or version. Define target-owned validation or another replay protocol within the approved grant. Test a successful PUT followed by a lost ledger write with all source GETs of target staging denied.
  1. P1 — Plan 1, Task 7: the archive loses a legal file named env. Plan:1585 reserves env for the overlay while adding application files under bare relative names. Extraction at line 1780 redirects both to <host>.env, consumed by backend_exec.go:1164. Use separate files/… and overlay namespaces, reject duplicate destinations, and round-trip a file and directory named env alongside an overlay.
  1. P1 — Plan 1, Tasks 11/14: readiness has a circular target-box prerequisite. Task 11:2461 requires the target box in touched; Task 14 adds only its region. The first target-box addition is Plan 2:789, after the flip. A first move to that box cannot become ready. Add the target box at the required earlier CAS and test from a claim that has never touched it.
  1. P1 — Plan 1, Tasks 11/12, and Plan 6, Task 3: empty ETags do not overwrite. Readiness writes:2621 use Put(..., "") for recurring reports; the console fingerprint does likewise. Plan 6:80 explicitly misstates this API. Store:38 defines it as create-only. Reports cannot refresh after their first write. Use read/ETag/CAS replacement for mutable reports and explicit idempotency for logs; test repeated writes through the real store.
  1. P1 — Plan 1, Tasks 4/12: the protocol floor fails open. Plan:2650 permits activation when reading the floor fails. Boot recovery normally runs before networking, as documented in systemapply.go:109, making this especially consequential. The door also uses readEdgesFiles, which discards completeness information: instancesplacement.go:198. Preserve an armed floor locally and refuse unknown activation eligibility; require complete protocol evidence at the door. Test offline recovery and unreadable actor reports.
  1. P1 — Plan 2, Task 5: immutable stop evidence is published before its final proof exists. Plan:691 creates stopped-source.json before the checkpoint and final TXID at line 692. Yet Complete() requires replica evidence, and landing requires a complete report. checkpoint.go:20 obtains that result only after synchronization. Either stopping cannot finish or the immutable report is incomplete. Separate preliminary stopping from final evidence, then publish the complete report before ExecToNone. Test every intervening crash.
  1. P1 — Plan 2, Task 5: a crash can skip final archive publication and still flip. Plan:694 persists archived before copying the final archive and adding its versions to the seal. The next phase immediately flips. A restart can therefore install an earlier archive, losing files written before stopping. Make archive publication and seal completion replayable prerequisites of MoveFlip; inject crashes after the record CAS and copy response. The proposed create-only archive test does not establish this barrier.
  1. P1 — Plan 2, Task 6: timer admission can race past drain and snapshot. Plan:716 checks the hold before acquiring the runner slot. In runner.go:143, route reading precedes claim; a paused tick can resume after the cut observes Busy=false, then advance bookkeeping at line 350. Acquire the slot before a fresh hold check, or implement an atomic freeze/drain handshake. Test that interleaving, rather than only an already-held row.
  1. P1 — Plan 2, Task 8: snapshot encoding fails above SQLite’s lock-page boundary. Plan:750 encodes every page. The pinned LTX encoder:219 rejects the lock page; litestream skips it. Skip ltx.LockPgno(pageSize) while preserving the database page count. Add a sparse or synthetic database test extending beyond 1 GiB.
  1. P1 — Plan 2, Task 8: generation-build replay restores over an existing output file. Plan:753 always restores into <WorkDir>/<host>.db. After a crash following restore or snapshot upload, litestream replica.go:601 refuses that existing file. Define verified reuse or fresh operation-owned scratch. The replay test must reuse the same work directory and cover an interrupted restore.
  1. P1 — Plan 2, Task 10 / Plan 4, Task 3: local retirement silently does nothing. Plan 2:793 passes a fresh ID to RetireArtifacts, but its preceding queue call creates no local obligation. local.go:62 requires a matching persisted chore and treats an unknown ID as completed. Old files can survive installation. Queue the local chore and inventory first, persist its ID, and test actual filesystem retirement. Plan 5’s destination patch must also include local_linux.go:201.
  1. P1 — Plan 3, Tasks 4/5: the first probe compares prepared files against the source generation. Plan:302 runs StartCheck before admission. Prepared markers name the move generation, while the flip intentionally preserves holder.generation; only AdmitWriter:27 changes it. The first probe therefore refuses its own files. Separate prepared-input validation from admitted-generation checks, and run the latter within the shared admitted-start sequence. Test from the real source-generation state.
  1. P1 — Plan 3, Tasks 3/6: the claim never reaches a phase accepted by commit. Plan:324 advances record phases only; the claim remains landing/checking. Commit at line 253 accepts only probing or probed. AdmitWriter:35 checks, but does not advance, the phase. The test manually sets probed, hiding the gap. Specify replayable claim-phase synchronization and test flip through commit without fixture-only phase edits.
  1. P1 — Plan 4, Task 10: declare-lost can override a winning record commit. Plan:191 calls DeclareLost using a captured record before attempting MoveRollBack. The target can commit the record between those operations. The claim declaration then revokes authority, while rollback refuses. Claim Plan 8:1444 cannot atomically validate that other object. Win and persist the record decision first, then apply its claim half. Add the commit-winning interleaving test.
  1. P1 — Plan 4, Task 10 / Plan 6, Task 1: the loss payload does not match claim Plan 8. Plan 4:191 constructs LossOperatorAttestation{Address: addr}; Claim Plan 8:476 has no Address field. The submitted cloud observation also omits required account/request IDs and required attestations. Specify the actual schema end to end and test creating a real accepted signed LossRecord, rather than a simplified fake.
  1. P1 — Plan 4, Tasks 2/5/10: lost-target recovery cannot consume the declaration result. ReturnToSource:73 requires empty Exec and evidence_target. Claim Plan 8:1511 journals loss.<id>, writes Exec="none", retains the phase, and removes the target participant. No adapter establishes recovery’s prerequisites. Define that transition explicitly, including coverage and obligations, and run the source recovery pass against a real declaration result.
  1. P1 — Plan 5, Task 7: orphan claims are excluded from recovery. Plan:133 iterates records with Move != nil, then promises to release claims whose record has no move. Those claims are never visited; ListAllRecords:1401 is not claim discovery. Additionally, ReleaseMove rejects their moving/"" phase. Add claim-to-record orphan discovery and a guarded orphan transition. Test the complete pass after a request-door crash.
  1. P1 — Plan 6, Tasks 1/2: remembered polling state cannot determine the terminal result. Plan:52 derives the exit code from the last observed state. A disconnected or paused CLI can miss the whole rollback and next receive none, which apiinstancemove.go:88 returns after clearing Move. Persist and expose an operation-bound terminal outcome. Test skipped intermediate states and reconnection after close; the scripted test that always observes rolling_back is insufficient.
  1. P1 — Plan 7, Task 1: the probe app’s launch contract differs from the real backend. Plan:46 specifies socket/database discovery through environment variables. backend_exec.go:942 launches --socket … --db …; its agent-owned environment does not provide the proposed replacements. Require those flags and test launching through the actual exec-backend contract.
  1. P2 — Index / Plan 7: activation depends on unlisted claim Plan 8b. Index:30 identifies Plan 8 as the loss dependency. Claim Plan 8:5678 explicitly defers authenticated floor identity, actor census, and live quarantine/loss/readmission wiring to 8b. Mark those activation prerequisites separately from library build dependencies. A direct local-retirement fallback cannot substitute for returning-box quarantine.
  1. P2 — Plan 4, Tasks 1/5/10: recovery callers request forbidden transitions. Task 1:57 allows rollback MoveStuck only from probing, but Task 5 calls it on verification mismatch. Task 10 omits the legal released + Dirty loss window and requests returning → released, prohibited by the forward-only phase sequence. Define explicit mismatch and declared-loss transitions, with retry unable to bypass verification. Test them through the actual transition closures.
  1. P2 — Plan 4, Task 6 / Plan 5, Task 1: reverting has no staging-cleanup producer or dispatcher. Plan 4:143 waits for staging cleanup attributed to Plan 5. Plan 5:53 queues and dispatches it only for aborting. Explicitly queue and run the scoped target cleanup during reverting. Test residue removal and release after acknowledgement.
  1. P2 — Plan 1, Task 11: the T4 MinIO test will not run in the cited CI gate. Plan:2628 adds a host-package test gated by MinIO environment. .amadan/ci.d/30-minio-contract:330 runs only internal/objstore and TestDeliveredContractMinio. Add the host test to that live invocation and assert its PASS line. Also add isolated failing cases for the readiness hooks currently stubbed to pass.
  1. P2 — Plans 5/6: the published task order has a dependency cycle and delayed gates. Plan 5:138 requires Plan 6 Task 5 first, while Plan 6 requires Plan 5 merged. Plan 6 Task 1 also adds dispatch before Task 6 supplies the mandatory heading, so docsite’s gate:58 fails that earlier commit. Move the paging primitive earlier and place dispatch with its documentation. Put copy approval/checking before the earlier tasks wire pending strings, rather than introducing the gate last.
  1. P2 — Plan 6, Task 7: copy completeness needs an independent inventory. Plan:131 derives reviewed entries from approved rows, but that cannot detect a deleted required row by itself. The existing approvedcopytest.go:87 deliberately compares against a separately pinned inventory. Specify that inventory and negative fixtures for deleted IDs, changed text, and pending text reaching call sites through helpers or formatting.
  1. P2 — Plan 7, Tasks 1/3: the “clean rollback” rehearsal writes before refusing readiness. Plan:50 starts database-writing loops unconditionally; the switch at line 51 changes only readiness. During the backend’s post-spawn readiness wait, backend_exec.go:989, those writes make the target dirty. Implement a before-write failure mode that suppresses every database/timer mutation, and assert unchanged digests separately from the after-write mode.

The proposed tests do not yet establish “red before the fix” across the series: several use states impossible under the real APIs, manually supply missing transitions, omit the decisive crash interleaving, or are excluded from CI.

PLAN: NOT READY

The locked design can remain intact, but the plans need revision before implementation. As written, they contain compile failures, staging and readiness paths that cannot progress, crash windows that can select stale data or lose files, and recovery paths that do not compose with the actual claim APIs. Resolve those interfaces and ordering gaps, then require integration tests that use the real store, claim transitions, park engine, and admitted-start sequence at the identified crash boundaries.