carlos / platform Public

Sidecar isolation spec: Astra round 2 findings (unedited)

Reviewed at 730ba093. R1-1 to R1-9 fixed or fixed in part; five new
findings (three P1, two P2); verdict reject.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev 6749a4d3042f5cecefcc4321bd7b572372326e62 parent 730ba09
1 file changed, +95 −0
  • docs/superpowers/specs/CODEX-FINDINGS-SIDECAR-ISOLATION-R2.md +95 −0

CI passed — run details

CI log
=== gate ===
.amadan/test-gate.sh
=== launchctx (0 s)
ok  	amadan.net/carlos/platform.git/launchctx	0.014s
?   	amadan.net/carlos/platform.git/launchctx/controlname	[no test files]
?   	amadan.net/carlos/platform.git/launchctx/wireid	[no test files]
=== vet (18 s)
=== gofmt (0 s)
gofmt -l .: clean
=== rest (171 s)
?   	github.com/carlosframework/platform/cmd/changelog	[no test files]
ok  	github.com/carlosframework/platform/cmd/console	3.788s
ok  	github.com/carlosframework/platform/cmd/moveprobe	11.954s
ok  	github.com/carlosframework/platform/cmd/zddprobe	0.797s
ok  	github.com/carlosframework/platform/internal/activator	59.919s
ok  	github.com/carlosframework/platform/internal/agentsock	0.026s
ok  	github.com/carlosframework/platform/internal/alerting	0.009s
ok  	github.com/carlosframework/platform/internal/analytics	0.023s
ok  	github.com/carlosframework/platform/internal/appconfig	3.017s
ok  	github.com/carlosframework/platform/internal/apperr	0.129s
ok  	github.com/carlosframework/platform/internal/applog	0.280s
ok  	github.com/carlosframework/platform/internal/awsinv	0.010s
ok  	github.com/carlosframework/platform/internal/boxchoice	0.009s
ok  	github.com/carlosframework/platform/internal/boxid	0.845s
?   	github.com/carlosframework/platform/internal/boxid/boxidtest	[no test files]
?   	github.com/carlosframework/platform/internal/boxid/internal/signtest	[no test files]
ok  	github.com/carlosframework/platform/internal/boxvolumes	0.013s
ok  	github.com/carlosframework/platform/internal/caps	0.022s
ok  	github.com/carlosframework/platform/internal/certwarm	0.007s
ok  	github.com/carlosframework/platform/internal/cgroup	0.787s
ok  	github.com/carlosframework/platform/internal/changelog	0.647s
ok  	github.com/carlosframework/platform/internal/claimactivation	1.288s
ok  	github.com/carlosframework/platform/internal/clamd	0.058s
?   	github.com/carlosframework/platform/internal/cliflag	[no test files]
?   	github.com/carlosframework/platform/internal/controlname	[no test files]
?   	github.com/carlosframework/platform/internal/controlsock	[no test files]
ok  	github.com/carlosframework/platform/internal/dbdoor	7.721s
ok  	github.com/carlosframework/platform/internal/dbdoor/dbdoortest	0.021s
ok  	github.com/carlosframework/platform/internal/dbquery	0.007s
ok  	github.com/carlosframework/platform/internal/dbreads	2.208s
?   	github.com/carlosframework/platform/internal/dbreads/dbreadstest	[no test files]
ok  	github.com/carlosframework/platform/internal/dbverify	0.021s
ok  	github.com/carlosframework/platform/internal/dnsrec	0.006s
ok  	github.com/carlosframework/platform/internal/docsite	0.014s
ok  	github.com/carlosframework/platform/internal/domains	2.804s
ok  	github.com/carlosframework/platform/internal/doorkey	0.014s
ok  	github.com/carlosframework/platform/internal/economics	0.006s
ok  	github.com/carlosframework/platform/internal/edge	45.803s
?   	github.com/carlosframework/platform/internal/edgeproof	[no test files]
ok  	github.com/carlosframework/platform/internal/edgesfile	0.008s
ok  	github.com/carlosframework/platform/internal/fleetapi	0.134s
ok  	github.com/carlosframework/platform/internal/gate	1.656s
ok  	github.com/carlosframework/platform/internal/genselect	0.015s
ok  	github.com/carlosframework/platform/internal/geo	0.018s
ok  	github.com/carlosframework/platform/internal/geoip	0.030s
ok  	github.com/carlosframework/platform/internal/historyreadback	0.159s
ok  	github.com/carlosframework/platform/internal/host	141.530s
ok  	github.com/carlosframework/platform/internal/hostactors	5.780s
ok  	github.com/carlosframework/platform/internal/hostactors/awsmembership	0.017s
ok  	github.com/carlosframework/platform/internal/hostbox	2.845s
ok  	github.com/carlosframework/platform/internal/hostclaim	0.817s
ok  	github.com/carlosframework/platform/internal/hostenv	0.017s
ok  	github.com/carlosframework/platform/internal/hostevidence	0.017s
ok  	github.com/carlosframework/platform/internal/hostexec	5.278s
ok  	github.com/carlosframework/platform/internal/hostfence	0.032s
ok  	github.com/carlosframework/platform/internal/hostfiles	10.297s
ok  	github.com/carlosframework/platform/internal/hostfloor	0.017s
ok  	github.com/carlosframework/platform/internal/hostguard	1.105s
ok  	github.com/carlosframework/platform/internal/hostops	1.963s
?   	github.com/carlosframework/platform/internal/hostops/fencerelease	[no test files]
ok  	github.com/carlosframework/platform/internal/hostops/internal/fencerelease	0.017s
ok  	github.com/carlosframework/platform/internal/hostquarantine	0.016s
ok  	github.com/carlosframework/platform/internal/hostrelocate	0.622s
ok  	github.com/carlosframework/platform/internal/hostresolve	0.225s
ok  	github.com/carlosframework/platform/internal/hostwrite	0.020s
ok  	github.com/carlosframework/platform/internal/infraview	0.018s
ok  	github.com/carlosframework/platform/internal/instancectl	5.232s
ok  	github.com/carlosframework/platform/internal/instanceexec	2.846s
ok  	github.com/carlosframework/platform/internal/instancefs	0.021s
ok  	github.com/carlosframework/platform/internal/instancekey	0.015s
ok  	github.com/carlosframework/platform/internal/instanceupdates	0.024s
ok  	github.com/carlosframework/platform/internal/layout	1.757s
ok  	github.com/carlosframework/platform/internal/lbhealth	0.018s
ok  	github.com/carlosframework/platform/internal/lease	10.312s
ok  	github.com/carlosframework/platform/internal/lease/leasetest	0.615s
ok  	github.com/carlosframework/platform/internal/ledger	0.047s
ok  	github.com/carlosframework/platform/internal/mail	0.267s
ok  	github.com/carlosframework/platform/internal/maintenance	0.083s
ok  	github.com/carlosframework/platform/internal/maintenanceexec	5.549s
ok  	github.com/carlosframework/platform/internal/maintenanceguard	0.085s
ok  	github.com/carlosframework/platform/internal/metrics	0.007s
ok  	github.com/carlosframework/platform/internal/moves	22.431s
ok  	github.com/carlosframework/platform/internal/moves/archive	0.938s
ok  	github.com/carlosframework/platform/internal/objstore	0.288s
ok  	github.com/carlosframework/platform/internal/ops	0.253s
ok  	github.com/carlosframework/platform/internal/park	0.328s
ok  	github.com/carlosframework/platform/internal/plans	0.007s
ok  	github.com/carlosframework/platform/internal/privatefile	0.005s
ok  	github.com/carlosframework/platform/internal/provision	24.078s
ok  	github.com/carlosframework/platform/internal/publicrelease	0.017s
?   	github.com/carlosframework/platform/internal/regionname	[no test files]
ok  	github.com/carlosframework/platform/internal/registry	5.594s
ok  	github.com/carlosframework/platform/internal/relay	7.246s
ok  	github.com/carlosframework/platform/internal/release	25.590s
ok  	github.com/carlosframework/platform/internal/rollout	3.845s
ok  	github.com/carlosframework/platform/internal/rolloutwords	0.003s
ok  	github.com/carlosframework/platform/internal/rootaws	0.010s
ok  	github.com/carlosframework/platform/internal/rootparticipation	0.065s
ok  	github.com/carlosframework/platform/internal/rootstate	0.031s
ok  	github.com/carlosframework/platform/internal/runs	0.509s
ok  	github.com/carlosframework/platform/internal/s3compat	0.006s
ok  	github.com/carlosframework/platform/internal/safefile	0.005s
ok  	github.com/carlosframework/platform/internal/schedule	2.684s
ok  	github.com/carlosframework/platform/internal/seeds	0.012s
ok  	github.com/carlosframework/platform/internal/sim/engines	2.694s
ok  	github.com/carlosframework/platform/internal/sim/hostlife	11.011s
ok  	github.com/carlosframework/platform/internal/sim/litestreamfacts	3.966s
ok  	github.com/carlosframework/platform/internal/status	0.085s
ok  	github.com/carlosframework/platform/internal/steering	0.007s
ok  	github.com/carlosframework/platform/internal/stopevidence	0.307s
ok  	github.com/carlosframework/platform/internal/svcrole	0.002s
ok  	github.com/carlosframework/platform/internal/telemetry	0.004s
ok  	github.com/carlosframework/platform/internal/termfence	0.005s
ok  	github.com/carlosframework/platform/internal/tunnelclient	0.005s
ok  	github.com/carlosframework/platform/internal/unixdial	0.002s
ok  	github.com/carlosframework/platform/internal/updatewords	0.004s
ok  	github.com/carlosframework/platform/internal/usage	0.007s
ok  	github.com/carlosframework/platform/internal/version	0.002s
ok  	github.com/carlosframework/platform/internal/vet	1.665s
=== internal_console@0 (80 s)
ok  	github.com/carlosframework/platform/internal/console	78.220s
=== internal_console@1 (44 s)
ok  	github.com/carlosframework/platform/internal/console	42.163s
=== internal_console@2 (41 s)
ok  	github.com/carlosframework/platform/internal/console	39.947s
=== internal_console@3 (41 s)
ok  	github.com/carlosframework/platform/internal/console	39.441s
=== internal_console@4 (42 s)
ok  	github.com/carlosframework/platform/internal/console	40.706s
=== internal_console@5 (41 s)
ok  	github.com/carlosframework/platform/internal/console	39.636s
=== internal_console@6 (38 s)
ok  	github.com/carlosframework/platform/internal/console	36.194s
=== internal_console@7 (47 s)
ok  	github.com/carlosframework/platform/internal/console	45.389s
=== root@0 (110 s)
ok  	github.com/carlosframework/platform	108.460s
=== root@1 (84 s)
ok  	github.com/carlosframework/platform	82.754s
=== root@2 (92 s)
ok  	github.com/carlosframework/platform	90.423s
=== cross ===
--- shard 0 of 5 ---
cross-compiling darwin/arm64
--- shard 1 of 5 ---
cross-compiling darwin/amd64
--- shard 2 of 5 ---
cross-compiling linux/arm64
linux/arm64 carlos binary: 50528418 bytes (ceiling 52000000)
--- shard 3 of 5 ---
cross-compiling windows/amd64
--- shard 4 of 5 ---
cross-compiling windows/arm64
=== minio-contract ===
minio contract: arm64, minio RELEASE.2025-09-07T16-13-09Z, mc RELEASE.2025-08-13T08-35-41Z
  minio: downloading https://github.com/minio/minio/releases/download/RELEASE.2025-09-07T16-13-09Z/minio.linux-arm64.RELEASE.2025-09-07T16-13-09Z
  minio: downloaded, digest verified
  mc: downloading https://github.com/minio/mc/releases/download/RELEASE.2025-08-13T08-35-41Z/mc.linux-arm64.RELEASE.2025-08-13T08-35-41Z
  mc: downloaded, digest verified
  minio healthy on 127.0.0.1:20999
Added `local` successfully.
Bucket created successfully `local/contract-bucket`.
Bucket created successfully `local/denied-bucket`.
Created policy `contract-only` successfully.
Added user `scopeduser` successfully.
Attached Policies: [contract-only]
To User: scopeduser
  buckets and scoped user ready
=== RUN   TestDeliveredContractMinio
=== RUN   TestDeliveredContractMinio/put
=== RUN   TestDeliveredContractMinio/get_round-trips_the_body
=== RUN   TestDeliveredContractMinio/list_shows_the_key
=== RUN   TestDeliveredContractMinio/head_and_list_agree_on_the_version
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict
=== RUN   TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed
=== RUN   TestDeliveredContractMinio/delete_removes_it
=== RUN   TestDeliveredContractMinio/cross-bucket_denial
--- PASS: TestDeliveredContractMinio (0.02s)
    --- PASS: TestDeliveredContractMinio/put (0.00s)
    --- PASS: TestDeliveredContractMinio/get_round-trips_the_body (0.00s)
    --- PASS: TestDeliveredContractMinio/list_shows_the_key (0.00s)
    --- PASS: TestDeliveredContractMinio/head_and_list_agree_on_the_version (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/not_by_PutObjectTagging (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_its_own_object/and_not_by_x-amz-tagging_on_upload (0.00s)
    --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route (0.01s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CreateMultipartUpload (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/not_by_CopyObject_with_a_REPLACE_tagging_directive (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/but_multipart_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_copy_itself_is_allowed (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/a_POST-policy_forged_tag_with_a_matching_version_is_still_not_a_verdict (0.00s)
        --- PASS: TestDeliveredContractMinio/the_app_cannot_tag_by_any_other_route/and_an_ordinary_tagged-with-something-else_upload_is_allowed (0.00s)
    --- PASS: TestDeliveredContractMinio/delete_removes_it (0.00s)
    --- PASS: TestDeliveredContractMinio/cross-bucket_denial (0.00s)
PASS
ok  	github.com/carlosframework/platform/internal/objstore	0.023s
=== RUN   TestT4StorageProbeMinio
2026/10/24 20:22:36 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E190D191BCF089, HostID: 7c420053e0fbcd7f41653fdd92ffa2802c903d05303b1aa15adc2e8bb65d183f, api error SignatureDoesNotMatch: The request signature we calculated does not match the signature you provided. Check your key and signing method.
--- PASS: TestT4StorageProbeMinio (0.01s)
PASS
ok  	github.com/carlosframework/platform/internal/host	0.022s
=== RUN   TestS3StoreMinioContract
=== RUN   TestS3StoreMinioContract/conditional_get_and_etag_listing
=== RUN   TestS3StoreMinioContract/bump_through_every_mutation_path
--- PASS: TestS3StoreMinioContract (0.03s)
    --- PASS: TestS3StoreMinioContract/conditional_get_and_etag_listing (0.01s)
    --- PASS: TestS3StoreMinioContract/bump_through_every_mutation_path (0.02s)
PASS
ok  	github.com/carlosframework/platform/internal/release	0.030s
Bucket created successfully `local/dbf-deploy`.
Bucket created successfully `local/dbf-data-ie`.
Bucket created successfully `local/dbf-data-uk`.
local/dbf-deploy versioning is enabled
Created policy `dbf-console` successfully.
Created policy `dbf-ukbox` successfully.
Added user `dbfconsole` successfully.
Added user `dbfukbox` successfully.
Attached Policies: [dbf-console]
To User: dbfconsole
Attached Policies: [dbf-ukbox]
To User: dbfukbox
=== RUN   TestDBForwardMinio
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/24 20:22:38 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000002
2026/10/24 20:22:38 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000002 maxTXID=0000000000000002 size=370
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000002
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000002 txid.db=0000000000000003
2026/10/24 20:22:38 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000003 maxTXID=0000000000000003 size=454
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000003 txid.db=0000000000000003
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000000 txid.db=0000000000000001
2026/10/24 20:22:38 INFO ltx file uploaded system=store db=source.db replica=file level=0 minTXID=0000000000000001 maxTXID=0000000000000001 size=720
2026/10/24 20:22:38 INFO replica sync system=store db=source.db replica=file txid.replica=0000000000000001 txid.db=0000000000000001
2026/10/24 20:22:38 console: CARLOS_SECRETS_PUBKEY is unset, so no region outside the home can be chosen automatically
2026/10/24 20:22:38 console: could not notify member@example.com of a CLI token issue: keymail: lookup member@example.com: keymail: GET /api/federation/lookup?addr=member%40example.com&from=console%40127.0.0.1%3A44063: could not determine target mailbox
    agent.go:135: dbreads: dbr_yrutgxbnsdtbm7taqat356xczm: planned 3 files (1544 bytes) and restored to 3 in 9ms
    agent.go:135: dbreads: dbr_yrutgxbnsdtbm7taqat356xczm: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/24 20:22:39 console: db read dbr_yrutgxbnsdtbm7taqat356xczm: relayed 1 chunks (102 bytes) in 1.004s, ended done
    agent.go:135: dbreads: dbr_qeinbomhvgjec4ebflwzoszaey: planned 1 files (720 bytes) and restored to 1 in 9ms
    agent.go:135: dbreads: dbr_qeinbomhvgjec4ebflwzoszaey: output 5 bytes in 1 confirmed chunks in 1ms
2026/10/24 20:22:40 console: db read dbr_qeinbomhvgjec4ebflwzoszaey: relayed 1 chunks (102 bytes) in 1.005s, ended done
    agent.go:135: dbreads: dbr_v2blfypxmgyx4tgzfino33w2ma: planned 3 files (1544 bytes) and held through 3 in 8ms
    agent.go:135: dbreads: dbr_v2blfypxmgyx4tgzfino33w2ma: output 1544 bytes in 1 confirmed chunks in 1ms
2026/10/24 20:22:41 console: db read dbr_v2blfypxmgyx4tgzfino33w2ma: relayed 1 chunks (1641 bytes) in 1.004s, ended done
=== RUN   TestDBForwardMinio/by_disconnect
=== NAME  TestDBForwardMinio
    agent.go:135: dbreads: dbr_u2ixdyxefua4lkphx7n2gswgk4: planned 3 files (1544 bytes) and restored to 3 in 10ms
2026/10/24 20:22:41 console: db read dbr_u2ixdyxefua4lkphx7n2gswgk4: relayed 0 chunks (0 bytes) in 15ms, ended client gone
    agent.go:135: dbreads: dbr_u2ixdyxefua4lkphx7n2gswgk4: output 5 bytes in 1 confirmed chunks in 104ms
=== RUN   TestDBForwardMinio/by_timeout
=== NAME  TestDBForwardMinio
    agent.go:135: dbreads: dbr_hyz4sr3hkmec6hn4hf7pyk2j5e: planned 3 files (1544 bytes) and restored to 3 in 9ms
2026/10/24 20:23:02 console: db read dbr_hyz4sr3hkmec6hn4hf7pyk2j5e: relayed 0 chunks (0 bytes) in 19.881s, ended no-result
    agent.go:135: dbreads: dbr_hyz4sr3hkmec6hn4hf7pyk2j5e: output 5 bytes in 1 confirmed chunks in 19.857s
--- PASS: TestDBForwardMinio (23.32s)
    --- PASS: TestDBForwardMinio/by_disconnect (0.22s)
    --- PASS: TestDBForwardMinio/by_timeout (19.99s)
PASS
ok  	github.com/carlosframework/platform/internal/console	23.338s
minio contract: PASS
diff --git a/docs/superpowers/specs/CODEX-FINDINGS-SIDECAR-ISOLATION-R2.md b/docs/superpowers/specs/CODEX-FINDINGS-SIDECAR-ISOLATION-R2.md
new file mode 100644
index 000000000..9426740ec
--- /dev/null
+++ b/docs/superpowers/specs/CODEX-FINDINGS-SIDECAR-ISOLATION-R2.md
@@ -0,0 +1,95 @@
+| Round 1 finding | Revision 2 assessment | Section |
+|---|---|---|
+| R1-1 — Unordered worker start and stop | **Fixes the failed-wake case.** Root cancellation, joining and lease retention are specified. Replacement attempts need additional handling, described in R2-1 below. | D19, §3.5.1 |
+| R1-2 — Rollback and recovery bypass downgrade protection | **Partially fixed.** The floor covers installation, `restoreFiles` and the recovery shell. The separately installed recovery guard remains a gap; see R2-2. | D11, §3.11; §8.3 |
+| R1-3 — Always-on workers have two replication owners | **Fixes the ownership rule.** The shared predicate correctly assigns workers to lease replication. Completing the transition requires the additional protection in R2-3. | D9, §3.9 |
+| R1-4 — Artifact absence does not prove absence of local history | **Accepted fix and reasonable decline.** Full extras move, and orphaned database companions refuse migration. The declined requirement would not prevent the same attacker from causing restoration on an ordinary flat wake: `restorePlain` already restores when the database is absent ([backend_exec.go:795](internal/activator/backend_exec.go#L795)). This reasoning does not prove that history never existed; it reasonably treats malicious flat-tier tampering as an existing exposure. | D8, §3.8; §12.1 |
+| R1-5 — Config-only standby boxes cannot migrate | **Fixed at design level.** Config and extras move while the database is journaled absent; the two-box failover test covers the original case. | D8, §3.8; §9 |
+| R1-6 — Spawn history misses dormant workloads; worker default is independent | **Fixes both original omissions.** Inventory includes dormant rows, recorded flat intent is respected, and the two defaults are assessed separately. The interval between assessment and activation remains a new gap; see R2-4. | D12, §4.1; D14, §4.3; D15, §4.4 |
+| R1-7 — Signal exits become successful finishes | **Fixed at design level.** The worker template drops the inherited success statuses, and requested stops remain the agent’s responsibility. | D1, §3.1; D6, §3.6 |
+| R1-8 — Wrong placement set and claim-mode false readiness | **Fixes the original cases.** Placement uses the reconciler’s predicates, and claim-mode launch refusal affects readiness. Excluding unknown and stale boxes introduces the remaining gap in R2-5. | D17, §5 |
+| R1-9 — Named cgroup count is incomplete | **Fixed at design level.** Retirement requires refusal from agent startup, a drain and a census of the whole edge subtree; unavailable observations block retirement. | D18, §6 |
+
+Reviewed revision 2 at `730ba093dffd58338aac556737d5b0fbbe994fd9` against main `fef28dc5aef58c8b0e8cf11e5f0faf22c4735465`. The code in this checkout matches that baseline. This was a static review; no files were modified and no tests were run.
+
+1. **R2-1 — P1: An uncertain replacement can fall back after a hold build has changed the database.**
+
+ **Section:** D19, §3.5.1, especially “Respawns”; D5, §3.5.
+
+ **Failure sequence:**
+ 1. An awake worker runs build A. `ReplaceWorker` begins a hold-mode replacement with build B.
+ 2. Root starts B, which changes the database schema. The start response is lost, so the agent receives no process handle and the proposed `legacyStartUncertain` error.
+ 3. The respawn leaves the old process and incarnation recorded on the entry.
+ 4. `ReplaceWorker` treats the unchanged incarnation as evidence that B never ran and restores A. A can then run against B’s incompatible database.
+
+ Retaining the lease does not resolve this: both builds run under the same lease. Even a correctly fenced stop before restoring A cannot undo B’s schema change.
+
+ **Main evidence:** [`startMayHaveRun` at containment.go:165](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/activator/containment.go:165) recognizes `startUncertain`, but not `legacyStartUncertain`. Respawn records that answer at [activator.go:3657](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/activator/activator.go:3657), and its error arm retains the old entry at [activator.go:3739](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/activator/activator.go:3739). The unchanged-incarnation branch calls `restoreLocked` without a hold-mode check at [workerswap.go:152](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/activator/workerswap.go:152).
+
+ **Suggested fix:** Carry uncertain execution through replacement results and entry state, not just failed wakes. Treat it as “may have executed” when deciding hold-mode fallback. Retain the obligation until `RoleGone` proves the attempted worker stopped; an uncertain hold attempt must not restore the previous build. Test a successful root start followed by a lost response after a schema-changing hold build runs.
+
+2. **R2-2 — P1: The workers floor does not establish protection in the independently installed recovery guard.**
+
+ **Section:** D11, §3.11; rollout arming order, §8.2 steps 1–3; root census, §8.3.
+
+ **Failure sequence:**
+ 1. A box has the existing guard installed at `/opt/carlos/system/guard/carlos`, with its systemd overrides.
+ 2. Release N replaces the ordinary binary and embedded units. D11 permits worker migration once the floor is armed and an older `carlos.prev` is marked excluded.
+ 3. An interrupted update requires recovery while that excluded previous binary remains available.
+ 4. Systemd executes the independently installed guard. Its old selection logic can choose `carlos.prev` without consulting the workers floor. The new recovery shell checks and the new binary’s `restoreFiles` check never run.
+
+ Updating `rootmovesfloor_boot.go` in release N does not update a separate, previously copied executable. Guard installation also need not mean worker launches are in claim mode.
+
+ **Main evidence:** The guard is an independent copy, explicitly outside the restore set, at [guardarm.go:148](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/guardarm.go:148). Its overrides replace both update and recovery `ExecStart` at [guardarm.go:163](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/guardarm.go:163). The guard selects the previous binary when a journal exists at [guardexec.go:70](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/guardexec.go:70); its additional root-floor route is at [guardexec.go:95](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/guardexec.go:95). An existing previous binary is retained when the current image is not recorded as known-good at [systemapply.go:804](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/systemapply.go:804).
+
+ **Suggested fix:** Make workers-floor arming depend on verified worker-aware recovery executors, including the independent guard and effective systemd overrides. Specify the guard replacement and verification order before enabling worker minting or migration. Enforce the workers floor in both guarded recovery branches, and test recovery with an older guard copy and an excluded previous binary. Add the guard installation and selection code to the root census.
+
+3. **R2-3 — P1: Removing a path from generated configuration does not prove that the old replicator released the database.**
+
+ **Section:** D9, §3.9, “The transition” and “The move is then path-blind”; §8.2 steps 1–3.
+
+ **Failure sequence:**
+ 1. An always-on worker has both lease replication and the existing box-wide replicator.
+ 2. The new generator writes configuration excluding the worker, but the caller crashes before restarting the replicator, or that restart fails.
+ 3. A subsequent generation sees unchanged configuration. The old daemon still holds the worker’s database.
+ 4. Worker migration proceeds after stopping the worker and its lease replicator. It renames the database and WAL while the box-wide daemon can still checkpoint them. The next nested wake introduces another database user while the old daemon retains its original handles.
+
+ D9 explicitly removes the previous wait for configuration reload and file release. The new ownership predicate describes the desired configuration, not the running daemon.
+
+ **Main evidence:** Configuration is written at [ops.go:149](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/ops/ops.go:149); restarting replication is delegated to the caller through `changed`/`unchanged` at [ops.go:169](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/ops/ops.go:169). The replicator is a separate service and checkpoints databases ([carlos-litestream.service:16](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/units/carlos-litestream.service:16), [line 23](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/units/carlos-litestream.service:23)). Migration renames artifacts individually at [pass.go:988](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/layout/pass.go:988). The competing-checkpointer corruption risk is documented at [litestream.go:230](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/ops/litestream.go:230).
+
+ **Suggested fix:** Require an acknowledged transition away from box-wide replication before a worker’s first migration. Confirm that the old daemon stopped and its replacement uses configuration excluding the worker. Keep that obligation retryable across configuration-write/restart failures; an unchanged file must not discharge it.
+
+4. **R2-4 — P2: The inventory guard can pass before a workload arrives, then change that workload’s defaults during the rollout.**
+
+ **Section:** D14, §4.3; D15, §4.4; §8.2 step 9.
+
+ **Failure sequence:**
+ 1. A release-N box with both variables unset reports no flat worker rows and an empty refusal inventory.
+ 2. The console approves N+1 and moves the channel.
+ 3. During the rollout delay, the still-running release-N console creates a worker. The box mints and runs it flat.
+ 4. N+1 activates. Its defaults now refuse flat execution and enable migration, although nobody assessed this worker’s path or network compatibility. A worker using the old absolute database path loses service.
+
+ This remains possible even if the console checks immediately before moving the pointer: activation happens later.
+
+ **Main evidence:** The promote supports rollout spreading at [apisystemupdate.go:365](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/console/apisystemupdate.go:365). Boxes schedule application after a jittered deadline at [systemleg.go:146](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/host/systemleg.go:146). Sidecar creation independently writes records at [apisidecars.go:373](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/console/apisidecars.go:373).
+
+ **Suggested fix:** Add a box-side activation check that closes admission while reassessing both default changes, or persist the existing defaults on established boxes until explicit opt-in. The console inventory remains useful for advance refusal, but cannot be the sole guarantee. Test a worker arriving after promotion and before activation.
+
+5. **R2-5 — P2: Dropping stale or incomplete snapshots can approve an isolation-required worker that an unchecked box runs flat.**
+
+ **Section:** D17, §5.
+
+ **Failure sequence:**
+ 1. Boxes A and B serve the same region, pool and placement. A freshly reports nested-worker readiness.
+ 2. B runs release N with `report` and workers off. Its snapshot becomes stale, or it predates the new placement fields.
+ 3. D17 excludes B and approves creation using A.
+ 4. B continues reconciling records, acquires the worker’s lease and starts it flat.
+
+ A stale status snapshot is not evidence that a box stopped participating. The appeal to §4 as the boundary is insufficient during release N, when `report` deliberately permits flat launches.
+
+ **Main evidence:** Reconciliation selects records using region, pool and placement without requiring a fresh status snapshot at [sidecar_reconcile.go:343](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/provision/sidecar_reconcile.go:343). The existing worker launch is the flat spawn at [backend_exec.go:3125](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/activator/backend_exec.go:3125). By comparison, the existing downgrade guard treats stale or missing observations as unknown at [layoutguard.go:39](/home/paulca/.cache/tmp/claude-1001/sec/design-sidecar-isolation/internal/console/layoutguard.go:39).
+
+ **Suggested fix:** Unknown or stale potentially eligible boxes must block creation unless authoritative placement information excludes them. Also define how joining or returning boxes are prevented from claiming isolation-required workers without readiness. A snapshot check alone cannot impose that requirement on a box running `report`.
+
+**Overall verdict: reject.**
\ No newline at end of file