moves: pin the revert re-read's stall on loss- and fence-bound admissions (amadan #300)
revertProbeWrites replays the probe's admission with hostclaim.AdmitWriter, which cannot vouch for a loss-bound or fence-bound admission: their verified flags stay hostclaim's own (exposing them would be a forging surface). The re-read refuses such an admission with ErrConflict and the step stays at probing, as before the re-read existed. The refusal now names the kind and amadan #300; the later fix is a hostclaim-owned function that re-verifies those admissions. TestRevertProbedRefusesAnUnreplayableAdmission makes the stall explicit: a real loss-bound and a real fence-bound admission through the claim's writer (the recovery fixtures make both on a return) are refused, beside a plain admission over the same fixture that replays; and the revert step, its probe's one claim write shaped as a loss-bound admission, stays at probing with the row held. revertRun.probing is unchanged; only the internal/host envelope is re-pinned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3 files changed,
+112
−2
internal/host/movesrevert.go+11 −1internal/host/movesrevert_test.go+99 −0internal/provision/testdata/plan14-root-reads-home-part2.tsv+2 −1
CI passed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.011s
? amadan.net/carlos/platform.git/launchctx/controlname [no test files]
? amadan.net/carlos/platform.git/launchctx/wireid [no test files]
go vet ./...
gofmt -l .: clean
go test ./... -count=1 -timeout 30m
ok github.com/carlosframework/platform 287.273s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 2.749s
ok github.com/carlosframework/platform/cmd/moveprobe 93.186s
ok github.com/carlosframework/platform/cmd/zddprobe 0.699s
ok github.com/carlosframework/platform/internal/activator 250.501s
ok github.com/carlosframework/platform/internal/agentsock 0.026s
ok github.com/carlosframework/platform/internal/alerting 0.003s
ok github.com/carlosframework/platform/internal/analytics 0.023s
ok github.com/carlosframework/platform/internal/appconfig 2.391s
ok github.com/carlosframework/platform/internal/apperr 0.081s
ok github.com/carlosframework/platform/internal/applog 0.131s
ok github.com/carlosframework/platform/internal/awsinv 0.004s
ok github.com/carlosframework/platform/internal/boxchoice 0.008s
ok github.com/carlosframework/platform/internal/boxid 0.743s
? 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.009s
ok github.com/carlosframework/platform/internal/caps 0.012s
ok github.com/carlosframework/platform/internal/certwarm 0.002s
ok github.com/carlosframework/platform/internal/cgroup 0.689s
ok github.com/carlosframework/platform/internal/changelog 0.305s
ok github.com/carlosframework/platform/internal/clamd 0.055s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 389.906s
? 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 6.233s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.016s
ok github.com/carlosframework/platform/internal/dbverify 0.004s
ok github.com/carlosframework/platform/internal/dnsrec 0.004s
ok github.com/carlosframework/platform/internal/docsite 0.005s
ok github.com/carlosframework/platform/internal/domains 2.320s
ok github.com/carlosframework/platform/internal/doorkey 0.008s
ok github.com/carlosframework/platform/internal/economics 0.007s
ok github.com/carlosframework/platform/internal/edge 26.374s
? 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.135s
ok github.com/carlosframework/platform/internal/gate 1.659s
ok github.com/carlosframework/platform/internal/genselect 0.015s
ok github.com/carlosframework/platform/internal/geo 0.024s
ok github.com/carlosframework/platform/internal/geoip 0.032s
ok github.com/carlosframework/platform/internal/host 162.837s
ok github.com/carlosframework/platform/internal/hostactors 0.435s
ok github.com/carlosframework/platform/internal/hostbox 2.444s
ok github.com/carlosframework/platform/internal/hostclaim 0.514s
ok github.com/carlosframework/platform/internal/hostevidence 0.007s
ok github.com/carlosframework/platform/internal/hostexec 4.739s
ok github.com/carlosframework/platform/internal/hostfence 0.027s
ok github.com/carlosframework/platform/internal/hostfiles 10.487s
ok github.com/carlosframework/platform/internal/hostfloor 0.013s
ok github.com/carlosframework/platform/internal/hostguard 1.013s
ok github.com/carlosframework/platform/internal/hostops 1.547s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.002s
ok github.com/carlosframework/platform/internal/hostquarantine 0.002s
ok github.com/carlosframework/platform/internal/hostrelocate 0.420s
ok github.com/carlosframework/platform/internal/hostresolve 0.135s
ok github.com/carlosframework/platform/internal/hostwrite 0.002s
ok github.com/carlosframework/platform/internal/infraview 0.004s
ok github.com/carlosframework/platform/internal/instancectl 4.180s
ok github.com/carlosframework/platform/internal/instanceexec 2.710s
ok github.com/carlosframework/platform/internal/instancefs 0.024s
ok github.com/carlosframework/platform/internal/instancekey 0.023s
ok github.com/carlosframework/platform/internal/instanceupdates 0.025s
ok github.com/carlosframework/platform/internal/layout 1.511s
ok github.com/carlosframework/platform/internal/lease 9.805s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.024s
ok github.com/carlosframework/platform/internal/ledger 0.033s
ok github.com/carlosframework/platform/internal/mail 0.174s
ok github.com/carlosframework/platform/internal/maintenance 0.076s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.510s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.083s
ok github.com/carlosframework/platform/internal/metrics 0.004s
ok github.com/carlosframework/platform/internal/moves 20.898s
ok github.com/carlosframework/platform/internal/moves/archive 0.778s
ok github.com/carlosframework/platform/internal/objstore 0.170s
ok github.com/carlosframework/platform/internal/ops 0.179s
ok github.com/carlosframework/platform/internal/park 0.203s
ok github.com/carlosframework/platform/internal/privatefile 0.003s
ok github.com/carlosframework/platform/internal/provision 14.387s
ok github.com/carlosframework/platform/internal/publicrelease 0.007s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 4.885s
ok github.com/carlosframework/platform/internal/relay 7.216s
ok github.com/carlosframework/platform/internal/release 19.813s
ok github.com/carlosframework/platform/internal/rollout 3.623s
ok github.com/carlosframework/platform/internal/rolloutwords 0.003s
ok github.com/carlosframework/platform/internal/rootaws 0.007s
ok github.com/carlosframework/platform/internal/rootparticipation 0.006s
ok github.com/carlosframework/platform/internal/rootstate 0.025s
ok github.com/carlosframework/platform/internal/runs 0.568s
ok github.com/carlosframework/platform/internal/s3compat 0.004s
ok github.com/carlosframework/platform/internal/safefile 0.004s
ok github.com/carlosframework/platform/internal/schedule 2.453s
ok github.com/carlosframework/platform/internal/seeds 0.011s
ok github.com/carlosframework/platform/internal/sim/hostlife 8.707s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 3.946s
ok github.com/carlosframework/platform/internal/status 0.041s
ok github.com/carlosframework/platform/internal/steering 0.006s
ok github.com/carlosframework/platform/internal/stopevidence 0.336s
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.004s
ok github.com/carlosframework/platform/internal/tunnelclient 0.004s
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.004s
ok github.com/carlosframework/platform/internal/version 0.001s
ok github.com/carlosframework/platform/internal/vet 1.525s
=== 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: 47120546 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: cached, digest verified
mc: cached, 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.021s
=== RUN TestT4StorageProbeMinio
2026/10/16 03:06:18 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18DEE3A01E8A6739, 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.020s
minio contract: PASS
diff --git a/internal/host/movesrevert.go b/internal/host/movesrevert.go| index 5d36711cf..5a0af451d 100644 |
| --- a/internal/host/movesrevert.go |
| +++ b/internal/host/movesrevert.go |
| @@ -692,7 +692,14 @@ func revertProbeWrites(box, dataDir string, earlier, fresh hostclaim.Observed) e |
| return conflict("no admission") |
| } |
| last := f.Holder.Admissions[n-1] |
| - if last.Box != box || last.Mode != "cold" || last.LossID != "" || last.Generation == "" || last.Generation == e.Holder.Generation { |
| + if last.LossID != "" { |
| + // A loss-bound admission (as a fence-bound one, which AdmitWriter |
| + // refuses below) is verified only inside hostclaim, which does not |
| + // expose that; until a hostclaim-owned function re-verifies it |
| + // (amadan #300), the step stalls here as it did before the re-read. |
| + return conflict("a loss-bound admission, which only hostclaim can verify (amadan #300)") |
| + } |
| + if last.Box != box || last.Mode != "cold" || last.Generation == "" || last.Generation == e.Holder.Generation { |
| return conflict("the last admission is not a new generation for this box's writer") |
| } |
| in := hostclaim.Admission{ |
| @@ -708,6 +715,9 @@ func revertProbeWrites(box, dataDir string, earlier, fresh hostclaim.Observed) e |
| return err |
| } |
| if err := hostclaim.AdmitWriter(in)(admitted); err != nil { |
| + if errors.Is(err, hostclaim.ErrFence) { |
| + return conflict("a fence-bound admission, which only hostclaim can verify (amadan #300)") |
| + } |
| return conflict(err.Error()) |
| } |
| admitted.Gen = e.Gen + 1 |
diff --git a/internal/host/movesrevert_test.go b/internal/host/movesrevert_test.go| index ee8c7516b..4c195d9d4 100644 |
| --- a/internal/host/movesrevert_test.go |
| +++ b/internal/host/movesrevert_test.go |
| @@ -2,10 +2,12 @@ package host |
| import ( |
| "context" |
| + "crypto/ed25519" |
| "errors" |
| "fmt" |
| "os" |
| "path/filepath" |
| + "strconv" |
| "strings" |
| "testing" |
| "time" |
| @@ -771,6 +773,103 @@ func TestRevertProbedRefusesAForeignWrite(t *testing.T) { |
| } |
| } |
| +// TestRevertProbedRefusesAnUnreplayableAdmission pins today's stall, so it |
| +// is explicit and not silent (amadan #300). revertProbeWrites replays the |
| +// probe's admission with hostclaim.AdmitWriter, which cannot vouch for a |
| +// loss-bound admission (AdmitWriterWithLoss) or a fence-bound one |
| +// (AdmitWriterWithFencedTargetLoss): their verified flags are hostclaim's |
| +// own and are not exposed, since exposing them would be a forging surface. |
| +// So the re-read refuses such an admission with hostclaim.ErrConflict and |
| +// the step stays at probing, as it did before the re-read existed. The later |
| +// fix is a hostclaim-owned function that re-verifies those admissions (#300). |
| +// |
| +// The recovery fixtures produce both kinds only on a return (a restoring |
| +// claim); revertProbeWrites reads no op kind, so the real admissions made |
| +// through the claim's writer are checked against it directly, beside a plain |
| +// admission over the same fixture that does replay. The revert step itself |
| +// is then driven with a probe whose one claim write is shaped as a |
| +// loss-bound admission. |
| +func TestRevertProbedRefusesAnUnreplayableAdmission(t *testing.T) { |
| + admit := func(t *testing.T, f *rcFixture, pub ed25519.PublicKey) (hostclaim.Observed, hostclaim.Observed) { |
| + t.Helper() |
| + before := f.read() |
| + in := f.selectAdmission(before) |
| + after, err := f.lossWriter(pub).Admit(t.Context(), before, in.Admission, in.Baseline) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + if after.Claim.Gen != before.Claim.Gen+1 { |
| + t.Fatalf("the admission wrote gen %d over %d", after.Claim.Gen, before.Claim.Gen) |
| + } |
| + return before, after |
| + } |
| + t.Run("a plain admission replays", func(t *testing.T) { |
| + f := newRCFixture(t, rcClean) |
| + before, after := admit(t, f, nil) |
| + if err := revertProbeWrites(f.srcBox, f.dataDir, before, after); err != nil { |
| + t.Fatalf("the plain admission was refused: %v", err) |
| + } |
| + }) |
| + t.Run("loss-bound", func(t *testing.T) { |
| + f := newRCFixture(t, rcClean) |
| + pub := f.declare(false, []hostclaim.WriteSource{rcTargetSource("t2", 25), rcTargetSource(poOp, 20), rcCutSource()}, func(c *hostclaim.Claim) { |
| + c.Holder.Session = 25 |
| + c.Holder.Admissions = append(c.Holder.Admissions, hostclaim.AdmissionRecord{Session: 25, Box: "uk-box", Generation: "t2", Predecessor: poOp, Region: "uk", PredecessorRegion: "uk", Mode: "cold"}) |
| + }) |
| + before, after := admit(t, f, pub) |
| + if a := after.Claim.Holder.Admissions[len(after.Claim.Holder.Admissions)-1]; a.LossID != rcLossID { |
| + t.Fatalf("not a loss-bound admission: %+v", a) |
| + } |
| + if err := revertProbeWrites(f.srcBox, f.dataDir, before, after); !errors.Is(err, hostclaim.ErrConflict) || !strings.Contains(err.Error(), "amadan #300") { |
| + t.Fatalf("a loss-bound admission was replayed: %v", err) |
| + } |
| + }) |
| + t.Run("fence-bound", func(t *testing.T) { |
| + f := newRCFixture(t, rcClean) |
| + record := f.fence() |
| + before, after := admit(t, f, nil) |
| + if after.Claim.Op.Journal["fence_admitted."+record.ID] == "" { |
| + t.Fatalf("not a fence-bound admission: %+v", after.Claim.Op.Journal) |
| + } |
| + if err := revertProbeWrites(f.srcBox, f.dataDir, before, after); !errors.Is(err, hostclaim.ErrConflict) || !strings.Contains(err.Error(), "amadan #300") { |
| + t.Fatalf("a fence-bound admission was replayed: %v", err) |
| + } |
| + }) |
| + t.Run("the revert step stays at probing", func(t *testing.T) { |
| + h := newRevertHarness(t) |
| + h.fromStopped(t) |
| + h.arm(t) |
| + var admitted *hostclaim.Claim |
| + h.probe = func(recoveryProbeRequest) (recoveryProbeOutcome, error) { |
| + if admitted == nil { |
| + rewriteP1Claim(t, h.s, func(c *hostclaim.Claim) { |
| + hd := c.Holder |
| + session := c.Gen + 1 |
| + hd.Admissions = append(hd.Admissions, hostclaim.AdmissionRecord{Session: session, Box: h.srcBox, Generation: "lost-gen", Predecessor: hd.Generation, Mode: "cold", Region: "ie", PredecessorRegion: "ie", LossID: rcLossID}) |
| + hd.Session, hd.Stamp, hd.Generation, hd.WriterBox = session, session, "lost-gen", h.srcBox |
| + c.Op.Journal["loss_admitted."+rcLossID] = strconv.FormatUint(session, 10) |
| + }) |
| + admitted = h.claim(t) |
| + } |
| + return recoveryProbeAnswered, nil |
| + } |
| + err := h.w().revertSource(context.Background(), h.s, h.read(t, p1Host), nil) |
| + if admitted == nil { |
| + t.Fatal("the probe never ran") |
| + } |
| + if !errors.Is(err, hostclaim.ErrConflict) || !strings.Contains(err.Error(), "amadan #300") { |
| + t.Fatalf("the revert's probed took a loss-bound admission: %v", err) |
| + } |
| + c := h.claim(t) |
| + if c.Gen != admitted.Gen || c.Op.Phase != hostclaim.PhaseProbing || c.Op.Journal[hostclaim.JournalRevPhase] != hostclaim.PhaseProbing { |
| + t.Fatalf("the claim after the refusal: gen %d (admitted %d), %+v", c.Gen, admitted.Gen, c.Op) |
| + } |
| + if m := h.move(t); m.ReopenedAt != nil || h.route.HoldOp != p1ID { |
| + t.Fatalf("the refusal reopened: %+v, row %+v", m, h.route) |
| + } |
| + }) |
| +} |
| + |
| // TestRevertReplays: a crash after any of the revert's side effects, then a |
| // restarted agent, still reaches the close, with the evidence asked once it |
| // is journalled, the hold only ever restoring under the move id, and the |
diff --git a/internal/provision/testdata/plan14-root-reads-home-part2.tsv b/internal/provision/testdata/plan14-root-reads-home-part2.tsv| index 90bc3312b..06c8758fe 100644 |
| --- a/internal/provision/testdata/plan14-root-reads-home-part2.tsv |
| +++ b/internal/provision/testdata/plan14-root-reads-home-part2.tsv |
| @@ -7,6 +7,7 @@ |
| # Task 5: the Phase 1 move door admits a home target under host claims. Server.handleAPIInstanceMoveRequest gains its home refusals before any write (MV-N510 without host claims, MV-N511 for a home-named box, read from the same edges-file listing through movePlacements) and its sentences name the home; Server.startClaimModeMove's sentences name the home. Read sets unchanged (the same file:Exec and file:Read kinds), only offsets moved: both re-frozen at main's disposition (class, task and basis unchanged; kinds and digest refreshed), they add two frozen declarations; the seal moves. internal/console's source envelope is refreshed. |
| # Merge of main at ee35dee (2026-10-16): this overlay now loads after census-ruling-seed (FS-R6, FS-R10) and moves-overcap-cut-236. No unit of this overlay is in either; every row still matches its scan unchanged. Only the internal/activator and internal/host envelopes are re-pinned to the merged tree, and the seal moves with the merged freeze. |
| # The ruling's condition (2026-10-16): revertRun.probing takes the re-read claim only when it is the step's own read plus the probe wake's own writes, replayed with the claim's own transitions (hostclaim.AdmitWriter's cold admission for this box's writer, with its origin, then the restore's re-tag through FS-R11's claimRestoreObservation.retag) and compared exactly; anything else is a conflict, as the stale CAS was. A reverting op's probe attempts are journalled on the box, never reserved in the claim. The check reads nothing, so the read set is the same one file:Read: revertRun.probing is re-pinned at the same disposition (only its digest and the read's offset moved), its frozen declaration replaced, the internal/host envelope re-pinned, and the seal moves. |
| +# amadan #300 (2026-10-16): revertProbeWrites names a loss- or fence-bound admission, which only hostclaim can verify, in its refusal; revertRun.probing is unchanged and only the internal/host envelope is re-pinned. |
| @legacy 849ce111c61c3dcedd80595348d0a26c67fb47462d497fba63d52d2c94e1d5d0 internal/activator/backend_exec.go ExecBackend.LaunchEnvironment legacy accepted-legacy accepted-legacy;rev3=J1;basis=root-route whole:Route@139 e8853e15b427b80a701b5e10b565f7d4f0b778e0c8185da63266e2408f6b4113 |
| internal/activator/backend_exec.go ExecBackend.LaunchEnvironment legacy accepted-legacy accepted-legacy;rev3=J1;basis=root-route whole:Route@139 e8853e15b427b80a701b5e10b565f7d4f0b778e0c8185da63266e2408f6b4113 |
| @legacy 1680e7269c40013e72c2f0a39abc13ee75cecadf2b3b8aa3d3a0278c060458ce internal/activator/backend_exec.go ExecBackend.LaunchLayers legacy accepted-legacy accepted-legacy;rev3=J1;basis=root-route registry:Socket@751,whole:Route@179,whole:Route@747 66a14ac6d0a4c2c9333adf45a792407d8cc4fa389416feb31fcf58616fc5b611 |
| @@ -37,5 +38,5 @@ internal/console/apiinstancemove.go Server.handleAPIInstanceMoveRequest legacy a |
| internal/console/apiinstancemove.go Server.startClaimModeMove legacy accepted-legacy accepted-legacy;rev3=J4;basis=root-input file:Exec@3526,file:Exec@565 c4e47ebd1e84c89d72ed8bbb25e65af8e365f4993827682ca55de9fd2d2d90bb |
| @coverage internal/activator 9511daaa77f912b86ab84d8e30b7e6c6b1b6d0b2989e79ec6bda2c0471daf1d4 |
| @coverage internal/console a565401e44e7797120ad52136146d84c8e0d430ceeb6a6f1c5e1ea0ed7a78c7e |
| -@coverage internal/host 585d33e2b501102e08b0fc9fd9cc074720ee9800d262270b59dfeb90ee50d0ce |
| +@coverage internal/host cc00e77188da3a5a20b3099adee45d829e07bd417fa73bdb8ebb0add2af4e1c2 |
| @coverage internal/moves 51ae19338bf9f92d45cc166f9fb71cdd3280c617892f71bb9ce67b2b00a7ae27 |