carlos / platform Public
Moves Phase 1, Plan 3: Probe, Commit and Open Implementation Plan
> For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking. Tasks 5, 6 and 7 need claim Plan 6 (feat/hostclaim-box) merged; build Tasks 1 to 4 and 8 first.
Goal: Prove the target can run the instance (the probe as a cold admission into the prepared generation, within the budgeted attempts and the cut deadline), commit by one record CAS, let the claim follow with its obligations, open the target row, and park the source.
Architecture: The probe policy is pure (internal/moves/probe.go): attempt windows, the retry backoff, deadline checks before the start and before readiness. activator.ProbeWake runs claim Plan 6's admitted-writer start sequence for a held row with that policy, spawning strictly with CARLOS_MOVE_PROBE=1 and requiring the readiness answer from the spawned tree. The commit is provision.MoveCommit conditional on now ≤ cut_deadline, then hostclaim.Commit queues a location park-replica for the source and a lane park-replica for the target and covers the source region's predecessors. The open is registry.ReleaseHold. The source's finalization retires its installation under the host guard and records source_parked_at.
Tech Stack: Go, internal/hostbox (claim Plan 6), internal/hostclaim, internal/genselect, internal/park, internal/hostguard, unix sockets with SO_PEERCRED (golang.org/x/sys/unix), cgroup v2.
Spec: rev 7.18 §5.1 (the start check, step 9), §7.5, §7.7, §7.9, §7.13, §7.14, §19.2 K6, K8. Index: 2026-10-06-moves-phase1-0-index.md. Plans 1 and 2 merged.
Global Constraints
- Gate before every commit (AGENTS.md); cross-compile; sandboxed
GOCACHE. Tests serial and niced.SO_PEERCREDcode is//go:build linuxwith a!linuxstub. - One attempt is one cold admission; its app may restart under the retry policy (doubling backoff from 1 s, five starts) within the attempt's 30 s readiness window; the deadline is checked before each start and before readiness is accepted (§7.7, R12-2;
TestProbeWindow). - A landing has at most three attempts and never more than T11 admitted; a probe never marks the host failed (§7.7).
- The commit is a record CAS conditional on
now ≤ cut_deadline; the claim follows unconditionally;holder.generationis never written by the commit (R10-3). - The open is the conditional
ReleaseHold(host, moveID); the target serves on the session its probe was admitted with; nothing rolls back after a commit. - Cold only (P7, index D14): every probe and every wake after the open is a cold admission; nothing here reads a certificate. The switch (D13) gates the probe and the open.
- No em dashes.
Review Focus
- A probe attempt whose readiness arrives exactly at the window's end must fail; one at 29 s must pass; one whose environment becomes ready only after the window must not start the app (R12-2). Test in Task 1 (
TestProbeWindow, ported). - A commit attempted one second after
cut_deadlinemust lose and the move must roll back, even if the probe passed (§7.4, INV-9). Test in Task 2 (TestCommitRefusedPastTheDeadline). - A target agent that crashes after the commit record CAS and before the claim CAS must, on restart, write the claim half and open, not probe again (witness
wCommitInterrupted). Test in Task 3 and Task 7 (TestCommitClaimHalfReplayed,TestOpenAfterCrashDoesNotReprobe). - A readiness answer from a process outside the host's cgroup (another local service on the same path) must be refused (§7.7,
SO_PEERCRED). Test in Task 5 (TestProbeRefusesForeignPeer). - The source must never park its installation until the record says
committed, and never while its ownhold_opis not the move's (a late finalization from an aborted move). Test in Task 8 (TestSourceParkWaitsForCommit).
---
File structure
| path | responsibility | |---|---| | internal/moves/probe.go | attempt policy and deadlines | | internal/moves/startcheck.go | the start check over the three markers and the claim | | internal/provision/provision.go | MoveCommit, MoveOpened, MoveSourceParked, MoveProbeAttempt | | internal/hostclaim/move.go | Commit | | internal/activator/probewake.go, peercred_linux.go, peercred_other.go | ProbeWake | | internal/host/movesland.go | probing, probed, commit, open | | internal/host/movesfinal.go | the source's finalization park | | internal/registry/registry.go | DeleteIfHold |
---
Task 1: The probe policy
Files: create internal/moves/probe.go, internal/moves/probe_test.go.
Interfaces:
moves.ProbeWindow = 30 * time.Second,ProbeSettle = 20 * time.Second,ProbeMaxStarts = 5,LandingAttempts = 3,RecoveryAttempts = 9;moves.Backoff(start int) time.Duration(1 s, 2 s, 4 s, 8 s before starts 2 to 5; 0 before the first);moves.ProbeAttempt{Index int; Opened time.Time; Starts int};(a *ProbeAttempt) Deadline() time.Time(Opened + ProbeWindow);(a *ProbeAttempt) MayStart(now, cutDeadline time.Time) error(ErrAttemptOverwhennow >= Deadline()ornow > cutDeadlineorStarts >= ProbeMaxStarts);(a *ProbeAttempt) AcceptReadiness(answeredAt, cutDeadline time.Time) error(ErrAttemptOverwhenansweredAt >= Deadline()oransweredAt > cutDeadline);moves.AttemptsFor(kind string, admitted int) int(landing:min(3, admitted); recovery: 9).
- [ ] Step 1: Write the failing test (port
TestProbeWindowfrominternal/sim/hostlife/witness_test.go:3459andwProbeWindowAt):
// Ported from the model's TestProbeWindow and wProbeWindowAt (R12-2,
// INV-19): readiness k seconds after the attempt's first start: 29 is
// accepted, 30 fails before the start, 31 fails at the deadline with the
// environment still unready.
func TestProbeWindow(t *testing.T) {
t0 := time.Date(2026, 10, 6, 9, 0, 0, 0, time.UTC)
far := t0.Add(time.Hour)
for k, want := range map[int]bool{29: true, 30: false, 31: false} {
a := &ProbeAttempt{Index: 1, Opened: t0}
if err := a.MayStart(t0, far); err != nil {
t.Fatal(err)
}
a.Starts++
err := a.AcceptReadiness(t0.Add(time.Duration(k)*time.Second), far)
if (err == nil) != want {
t.Fatalf("k=%d: %v", k, err)
}
}
// The environment becomes ready after the window: no start at all.
a := &ProbeAttempt{Index: 1, Opened: t0}
if err := a.MayStart(t0.Add(ProbeWindow), far); !errors.Is(err, ErrAttemptOver) {
t.Fatalf("start after the window: %v", err)
}
// Five starts, then the attempt is over whatever the clock says.
b := &ProbeAttempt{Index: 1, Opened: t0, Starts: 5}
if err := b.MayStart(t0.Add(time.Second), far); !errors.Is(err, ErrAttemptOver) {
t.Fatal("sixth start")
}
// The absolute cut deadline bounds the whole.
c := &ProbeAttempt{Index: 1, Opened: t0}
if err := c.AcceptReadiness(t0.Add(5*time.Second), t0.Add(4*time.Second)); !errors.Is(err, ErrAttemptOver) {
t.Fatal("readiness past the cut deadline")
}
if Backoff(1) != 0 || Backoff(2) != time.Second || Backoff(5) != 8*time.Second {
t.Fatal("backoff")
}
if AttemptsFor("landing", 2) != 2 || AttemptsFor("landing", 7) != 3 || AttemptsFor("recovery", 0) != 9 {
t.Fatal("attempts")
}
}- [ ] Step 2: Run, Step 3: implement per the interface (straightforward arithmetic;
ErrAttemptOver = errors.New("moves: probe attempt window or deadline expired"), already onmainat d649d8d4 ininternal/moves/install_contract.go(claim Plan 6): this task imports it and does not redefine it; every consumer useserrors.Is, so only the identity matters), Step 4: runnice -n 10 go test ./internal/moves -run TestProbeWindow -count=1→ PASS. - [ ] Step 5: Commit:
git commit -m "moves: the probe attempt policy, ported from the model (§7.7, R12-2)" ...
---
Task 2: Record transitions for commit, open and the source park
Files: modify internal/provision/provision.go, test internal/provision/move_test.go.
Interfaces:
MoveProbeAttempt(g MoveGuard, n int)(statelanding, phaseprobing; recordsLanding.Attempts = non theMoveLandingJournal, Plan 1 Task 2);MoveCommit(g, now time.Time) func(*Record) error(landing/probed,now <= *CutDeadline, elseErrMoveConflictwrappingErrCutDeadline; setsState = committed,CommittedAt);MoveOpened(g, now)(committed,OpenedAt);MoveSourceParked(g, now)(committed,SourceParkedAt);MoveClose(g, now time.Time)(committedwithOpenedAtandSourceParkedAtset →Move = nil, region alreadyTo, andrec.LastMove = &MoveOutcome{ID: g.ID, Outcome: "done", At: now, OfflineS: OpenedAt - CutAt}in the same write, index D11; Plan 5 calls it when both obligations are gone).
- [ ] Step 1: Write the failing test
func TestCommitRefusedPastTheDeadline(t *testing.T) {
g := MoveGuard{ID: "mv_abcdefghijklmnopqrstuvwxyz", Incarnation: strings.Repeat("ab", 32)}
now := time.Date(2026, 10, 6, 9, 0, 0, 0, time.UTC)
dl := now.Add(115 * time.Second)
rec := &Record{Region: "uk", Move: &MoveState{ID: g.ID, Incarnation: g.Incarnation, From: "ie", To: "uk", State: MoveLanding, LandingPhase: LandProbed, CutDeadline: &dl}}
if err := MoveCommit(g, dl.Add(time.Second))(rec); !errors.Is(err, ErrCutDeadline) || rec.Move.State != MoveLanding {
t.Fatalf("late commit: %v %s", err, rec.Move.State)
}
if err := MoveCommit(g, dl)(rec); err != nil || rec.Move.State != MoveCommitted || rec.Move.CommittedAt == nil {
t.Fatalf("commit at the deadline: %v", err)
}
if err := MoveCommit(g, dl)(rec); !errors.Is(err, ErrMoveConflict) {
t.Fatal("second commit")
}
if err := MoveClose(g, now)(rec); !errors.Is(err, ErrMoveConflict) {
t.Fatal("close before open and park")
}
if err := MoveOpened(g, now)(rec); err != nil || rec.Move.OpenedAt == nil {
t.Fatal(err)
}
if err := MoveSourceParked(g, now)(rec); err != nil {
t.Fatal(err)
}
if err := MoveClose(g, now)(rec); err != nil || rec.Move != nil || rec.Region != "uk" || rec.LastMove == nil || rec.LastMove.ID != g.ID || rec.LastMove.Outcome != "done" {
t.Fatalf("close: %v %+v", err, rec)
}
}- [ ] Step 2: Run, Step 3: implement:
// ErrCutDeadline is a commit attempted after cut_deadline (§7.4): the
// record CAS is the decision, so the deadline cannot be passed between the
// record write and the claim write.
var ErrCutDeadline = fmt.Errorf("%w: the cut deadline has passed", ErrMoveConflict)
func MoveCommit(g MoveGuard, now time.Time) func(*Record) error {
return func(rec *Record) error {
if err := g.check(rec); err != nil {
return err
}
if rec.Move.State != MoveLanding || rec.Move.LandingPhase != LandProbed {
return fmt.Errorf("%w: commit follows probed", ErrMoveConflict)
}
if rec.Move.CutDeadline == nil || now.After(*rec.Move.CutDeadline) {
return ErrCutDeadline
}
t := now.UTC()
rec.Move.State, rec.Move.CommittedAt = MoveCommitted, &t
return nil
}
}with MoveOpened, MoveSourceParked, MoveClose, MoveProbeAttempt in the same style.
- [ ] Step 4: Run → PASS. Step 5: Commit:
git commit -m "provision: commit conditional on the cut deadline, open, source park, close (§7.9)" ...
---
Task 3: hostclaim.Commit
Files: modify internal/hostclaim/move.go, test internal/hostclaim/move_test.go.
Interfaces:
hostclaim.Commit(opID, sourceRegion, sourceBox, targetRegion string, sourceScope, stagingScope ParkScope, newID func() string) func(*Claim) error: requiresKindLandingwith phaseprobingorprobedandExec == participants[1]; sets phase"committed"; appends locationpark-replicaforsourceRegionwithsourceScope(ownerregion:<source>),park-localforsourceBox, lanepark-replicafortargetRegionwithstagingScope; runsCoverRegionPredecessors(opID, "committed", sourceRegion); idempotent: a claim already atcommittedunder this op returnsnilwith no second set of obligations (witnesswCommitReplayed).holder.generationuntouched.PhaseCommitted = "committed".
- [ ] Step 1: Write the failing test (witnesses
wCommitCoverage,wCommitInterrupted,wCommitReplayed):
func TestCommitQueuesObligationsAndCoversTheSourceRegion(t *testing.T) {
c := movingTestClaim()
op := "mv_abcdefghijklmnopqrstuvwxyz"
_ = BeginMove(op, "ops", "ie-box", "uk-box", "uk", time.Now())(c)
_ = ExecToNone(op, "ie-box", "ev", JournalEvidenceSource)(c)
_ = SetMovePhase(op, KindMoving, PhaseMoving, PhaseSealed)(c)
c.Gen = 7
_ = Flip(op, "uk-box", 3, "")(c)
// The landing mirrors every record phase into the claim (Plan 2 Task
// 10), so the claim reaches probed through SetMovePhase, never a
// fixture edit.
for _, step := range [][2]string{{"checking", "parking"}, {"parking", "building"}, {"building", "published"}, {"published", "local"}, {"local", "configured"}, {"configured", "restored"}, {"restored", "probing"}, {"probing", "probed"}} {
if err := SetMovePhase(op, KindLanding, step[0], step[1])(c); err != nil {
t.Fatal(err)
}
}
// The target's probe admission left a record whose predecessor is in ie.
c.Holder.Generation = op
c.Holder.Admissions = []AdmissionRecord{{Region: "uk", PredecessorRegion: "ie", Session: 9, Box: "uk-box", Generation: op, Predecessor: "", Mode: "cold", Coverage: "sealed"}}
ids := 0
newID := func() string { ids++; return fmt.Sprintf("id%d", ids) }
src := ParkScope{Location: "instances/a.go.example.com/" + c.Holder.Incarnation, Incarnation: c.Holder.Incarnation, EvidenceAt: time.Now(), RequestLimit: 120 * time.Second}
stg := ParkScope{Location: "moves/a.go.example.com/" + op, Incarnation: c.Holder.Incarnation, EvidenceAt: time.Now(), RequestLimit: 120 * time.Second}
if err := Commit(op, "ie", "ie-box", "uk", src, stg, newID)(c); err != nil {
t.Fatal(err)
}
if c.Op.Kind != KindLanding || c.Op.Phase != PhaseCommitted || c.Op.Exec != "uk-box" || c.Holder.Generation != op {
t.Fatalf("after commit: %+v gen %q", c.Op, c.Holder.Generation)
}
kinds := map[string]int{}
for _, o := range c.Obligations {
kinds[o.Kind+"/"+o.Region+o.Box]++
}
if kinds["park-replica/ie"] != 1 || kinds["park-local/ie-box"] != 1 || kinds["park-replica/uk"] != 1 || len(c.Obligations) != 3 {
t.Fatalf("obligations: %+v", c.Obligations)
}
if !c.Holder.Admissions[0].Covered {
t.Fatal("the source-region predecessor is not covered (wCommitCoverage)")
}
// Replay: nothing doubles (wCommitReplayed).
if err := Commit(op, "ie", "ie-box", "uk", src, stg, newID)(c); err != nil || len(c.Obligations) != 3 {
t.Fatalf("replay: %v %d", err, len(c.Obligations))
}
// Not from moving.
d := movingTestClaim()
if err := Commit(op, "ie", "ie-box", "uk", src, stg, newID)(d); !errors.Is(err, ErrStaleOp) {
t.Fatalf("commit on a serving claim: %v", err)
}
}(The exact Covered field name and CoverRegionPredecessors' semantics are generation.go's; adjust the assertion to the field it sets.)
- [ ] Step 2: Run, Step 3: implement:
const PhaseCommitted = "committed"
// Commit is the claim half of the record's commit (§7.5, §7.9 step 1):
// phase committed plus, in the same write, a location park-replica for the
// source's location in its region and box, a lane park-replica for the target's
// staging, and CoverRegionPredecessors for the source region. It writes
// nothing into holder.generation (R10-3). Idempotent under the op.
func Commit(opID, sourceRegion, sourceBox, targetRegion string, sourceScope, stagingScope ParkScope, newID func() string) func(*Claim) error {
return func(c *Claim) error {
if err := RequireOp(opID)(c); err != nil {
return err
}
if c.Op.Kind != KindLanding {
return fmt.Errorf("%w: kind %q", ErrWrongState, c.Op.Kind)
}
if c.Op.Phase == PhaseCommitted {
return nil
}
if c.Op.Phase != "probing" && c.Op.Phase != "probed" {
return fmt.Errorf("%w: phase %q", ErrWrongState, c.Op.Phase)
}
if len(c.Op.Participants) != 2 || c.Op.Exec != c.Op.Participants[1] {
return fmt.Errorf("%w: exec %q is not the target", ErrWrongState, c.Op.Exec)
}
if err := sourceScope.Validate(c.Host); err != nil {
return err
}
if err := stagingScope.Validate(c.Host); err != nil {
return err
}
c.Op.Phase = PhaseCommitted
s, g := sourceScope, stagingScope
c.Obligations = append(c.Obligations,
Obligation{ID: newID(), Op: opID, Kind: "park-replica", Region: sourceRegion, Retirement: newID(), Owner: "region:" + sourceRegion, Park: &s},
Obligation{ID: newID(), Op: opID, Kind: "park-local", Box: sourceBox, Retirement: newID(), Owner: "box:" + sourceBox},
Obligation{ID: newID(), Op: opID, Kind: "park-replica", Region: targetRegion, Retirement: newID(), Owner: "region:" + targetRegion, Park: &g})
return CoverRegionPredecessors(opID, PhaseCommitted, sourceRegion)(c)
}
}- [ ] Step 4: Run → PASS. Step 5: Commit:
git commit -m "hostclaim: Commit queues the source and staging parks and covers the source region (§7.9, K8 groundwork)" ...
---
Task 4: The start check
Files: create internal/moves/startcheck.go, internal/moves/startcheck_test.go.
Interfaces:
moves.GenerationMarker{Op, Incarnation, Host, Box string; InstalledAt time.Time; ManifestSHA256 string; SnapshotKey, SnapshotVersion string; SnapshotTXID, SnapshotCRC64 uint64}(thegeneration.jsonshape,genselect.Marker's fields);moves.FilesGen{Op, Incarnation string};moves.DBGen{Op, Incarnation, Location string};moves.PreparedCheck(prepared string, holder hostclaim.Holder, filesGen *FilesGen, dbGen *DBGen) error(the pre-admission validation of a landing probe's inputs: both markers namepreparedand the holder's incarnation and location; Plan 3 Task 5 step 3);moves.StartCheck(c *hostclaim.Claim, marker *GenerationMarker, filesGen *FilesGen, dbGen *DBGen) error(the §5.1 start check against the claim after the admission CAS, Task 5 step 6) (§5.1 the start check: (1)markerabsent = origin; itsOpmust beholder.generationor the predecessor of the latest admission or of a chain of admissions each without a marker (walkholder.admissionsfrom the newest: a generation whosePredecessormatches is accepted); itsIncarnationthe holder's; (2)filesGenwhen present names the same generation and incarnation as the claim expects (holder.generation); (3)dbGenwhen present names the same generation andholder.location); errorsErrStartMarker,ErrStartFiles,ErrStartDBwith member-safe reasons.
- [ ] Step 1: Write the failing test: origin everywhere passes; marker naming the holder's generation passes; marker naming the predecessor of the latest admission passes (lagging); marker naming an unrelated generation refuses
ErrStartMarker;.files-genwith another op refusesErrStartFiles;<dbPath>.genwith another location refusesErrStartDB. - [ ] Step 2: Run, Step 3: implement, Step 4: run → PASS.
- [ ] Step 5: Commit:
git commit -m "moves: the start check over the three markers and the claim (§5.1, INV-4)" ...
---
Task 5: ProbeWake (BLOCKED-ON-CLAIM: C1, C2)
Files: create internal/activator/probewake.go, internal/activator/peercred_linux.go, internal/activator/peercred_other.go, internal/activator/probewake_test.go.
Interfaces:
- Consumes (claim Plan 6):
hostbox.Writer(Baseline,Admit,Published),hostbox.GenerationPrefix,spawnClaimed(ctx, enabled, manager, host, limit, selected, identity, build) (*exec.Cmd, *cgroup.Prepared, error)(the*cgroup.Preparedis kept for the process's life and, on every exit path including a failed start,KillAndEmptythenCloserun before the attempt is counted), and Plan 6 Task 9's admitted-start sequence exposed as(a *Service) startAdmitted(ctx, e *actEntry, admitted hostclaim.Observed, policy startPolicy) error(index: "exact interfaces needed"). Consumesgenselect.SelectPrepared(ctx, s, req, genselect.PreparedPin{Generation, SnapshotKey, SnapshotVersion, SnapshotTXID, SnapshotCRC64})to plan the prepared generation's restore from the install manifest. - Produces:
activator.ProbeConfig{Host string; Op string (the claim's op id: the move id, in every kind); HoldOp string (the row's hold_op: the move id for a landing or revert, the rollback id for a rollback's source); PreparedGeneration string (the generation a prepared install produced and the admission opens: the move id for a landing, the rollback id for a dirty return, "" for a clean recovery into the source's own generation); Kind string ("landing" | "recovery"); Prepared *moves.InstallManifest (non-nil exactly when PreparedGeneration != ""); Seal *moves.Seal; Inputs *provision.MoveInputs (the pin a landing probe enforces at spawn; nil for a recovery probe, which records what it rendered); CutDeadline time.Time; Attempt *moves.ProbeAttempt (Index set by the caller; Opened written by the probe at the first app start); RenderHeld func(ctx) (appconfig.HeldRender, error); ReadyPath string; LossID string (empty except for a lost-target return, Plan 4 Task 10, where the admission goes through hostclaim.AdmitWriterWithLoss)};activator.ProbeResult{Session uint64; Generation string; AnsweredAt time.Time};(a *Service) ProbeWake(ctx, cfg ProbeConfig) (ProbeResult, error): 1. the row must be held withhold_op == cfg.HoldOpand the claim must name this boxop.execunder opcfg.Op(K1, K6), elseErrProbeRefused; 2.render, err := cfg.RenderHeld(ctx)(the caller composesRenderHeld+MaterializeHeld; every probe kind, model 4); the launch-input pin, at spawn (§7.7, round-2 finding 14): for a landing probe (cfg.Inputs != nil) the renderedBundleETagsandOverlayETagmust equalcfg.Inputs', the materialized release must becfg.Inputs.Release, andmoves.ReportEnv(key, b.LaunchEnvironment(rt)).Digestmust equalcfg.Inputs.EnvReport; a mismatch isErrProbeFailed("configuration changed during the move")before any admission, and the landing rolls back; a recovery probe records what it rendered intoRollback.RecoveryInputs(through the caller'sRecordInputshook) and is bound to nothing (J2-R2-5). Plan 2'sconfiguredcheck stays as the early refusal; this one is the authoritative one, since the environment can change between the two; 3. prepared-input validation, before any admission, whencfg.PreparedGeneration != ""(a landing, or a dirty return):moves.PreparedCheck(cfg.PreparedGeneration, holder, filesGen, dbGen):.files-genand<dbPath>.genname that generation and the holder's incarnation and location, andcfg.Preparedexists withN == cfg.Seal.N. This is not the §5.1 start check againstholder.generation: before the first probe's admissionholder.generationis still the predecessor's (the source's after a flip, the target's after a dirtyReturnToSource, which deliberately keeps it, Plan 4 Task 2; onlyAdmitWritermoves it,generation.go:27), so a start check here would refuse the install's own files (round-2 finding 13). Whencfg.PreparedGeneration == ""(a clean recovery or a revert), the markers, when present, must nameholder.generationas observed; 4.cfg.Attempt.MayStart(now, cfg.CutDeadline)is checked withOpenedunset (the window has not begun); the cut deadline alone applies here; 5. the admission:decideper §7.14: cold;NewGeneration = cfg.Opwhenholder.generationis neithercfg.Opnor a descendant admitted from it, else a fresh id (newID());KeepStamp = holder.stamp > holder.session;Coverage = "sealed"whencfg.Seal != nil && cfg.Seal.FromDBand the generation is the prepared one, else"";Region,PredecessorRegionper the last admission record;RemoteMaxTXIDfrom the baseline plan (SelectPreparedfor the prepared generation;Writer.Baselinefor a fresh one); thenWriter.Admit; 6.startAdmittedwithstartPolicy{MaxStarts: moves.ProbeMaxStarts, Window: moves.ProbeWindow, Deadline: cfg.CutDeadline, Probe: true, Prepared: cfg.Prepared}(C1): the sequence purges and restores before the window opens, then setscfg.Attempt.Opened = nowat the first app start and journals it (round-2 finding 19: the 30 s window is the app's, the restore is priced separately in T11); the §5.1 start check runs here, inside the admitted sequence, withmoves.StartCheck(claimAfterCAS, marker, filesGen, dbGen)against the generation the admission CAS just named (holder.generation == cfg.Opfor a first probe; a fresh id for a restarted one, whose.files-genstill namescfg.Opand is accepted through the admission chain: Task 4'sStartChecktakes the claim and walksholder.admissions); the spawn goes throughspawnClaimedwithCARLOS_MOVE_PROBE=1in the child's environment and is strict; 7. readiness:GET cfg.ReadyPathover the row's socket withHost: <host>, 200 to 399, the peer'sSO_PEERCREDpid a member ofcarlos-exec@<host>(cgroup.Cleanup.Members),cfg.Attempt.AcceptReadiness(answeredAt, cfg.CutDeadline); a 20 s settle, the process still running, a second request; 8. the marker and publication arestartAdmitted's (first upload,generation.jsonby If-Match or If-None-Match,Writer.Published); the entry stays held:RetireExceptkeeps entries whose rowIsHold. A failure after the admission stops the tree (FenceAndStopwith a fresh generation) and returnsErrProbeFailedwith the reason; the attempt is over; the operation decides what next. peercred_linux.go:peerPID(conn net.Conn) (int, error)viaunix.GetsockoptUcred;peercred_other.goreturnsErrStopEvidenceUnsupported.
Tests: TestProbeRefusesUnheldRowOrForeignExec; TestFirstProbeFromTheSourceGenerationIsAdmitted (the claim as the flip left it: holder.generation is the source's "", .files-gen and <dbPath>.gen name the move id; the probe validates the prepared inputs, admits into the move id, and the start check after the CAS passes; a hand-built claim whose holder.generation is already the move id with a .files-gen naming another op refuses); TestProbeRendersBeforeStart (the RenderHeld hook is called before any spawn, model 4); TestProbeRefusesForeignPeer (Review Focus 4: a fake listener answering 200 from this test process, whose pid is not in the host cgroup → ErrProbeFailed naming the peer); TestProbeAttemptEndsAtTheWindow (the fake start answers at 31 s → ErrAttemptOver); TestProbeIsAColdAdmissionIntoThePreparedGeneration (with Plan 6's fake writer: Admit is called once with NewGeneration == op, Mode == "cold", Coverage == "sealed", before the spawn hook runs; a second attempt admits a fresh generation, KeepStamp false).
- [ ] Steps 1 to 4: run
nice -n 10 go test ./internal/activator -run TestProbe -count=1→ PASS. Cross-compile. - [ ] Step 5: Commit:
git commit -m "activator: ProbeWake, a cold admission into the prepared generation with the attempt policy (§7.7, §7.14)" ...
---
Task 6: The landing's probing and probed (BLOCKED-ON-CLAIM: C1)
Files: modify internal/host/movesland.go, internal/host/movesland_test.go.
Interfaces:
moveCfg.Probe func(ctx, activator.ProbeConfig) (activator.ProbeResult, error);moveCfg.RenderAndMaterialize func(ctx, rt registry.Route, op, version string) (appconfig.HeldRender, error).landingPassphases:restored → probing(MoveLandingPhase, then the claim'sSetMovePhase(id, KindLanding, "restored", "probing"), Plan 2 Task 10's mirroring rule, so the admission'sObservedPhaseisprobing); inprobing, attempts from the journal (Journal.Attempt):n = AttemptsFor("landing", targetReport.AttemptsAdmitted); for each attempt not yet recorded:MoveProbeAttempt(g, i)and journalAttempt = ibefore the call (the attempt is accounted here; itsOpenedis written by the probe at the first app start, Task 5 step 6, so the restore does not eat the window; a crash restarts only the probe, §7.13, and a journalled attempt with anOpenedwhose window passed counts as failed),cfg.Probe(...); success →MoveLandingPhase(probing → probed)thenSetMovePhase(id, KindLanding, "probing", "probed");ErrAttemptOver/ErrProbeFailed→ next attempt, if any; attempts exhausted orcut_deadlinepassed → the rollback marker (Plan 4 Task 1'sMoveRollBack; until it lands,markForRollback).- Tests:
TestLandingProbesWithinTheBudget(two admitted attempts: the first fails, the second passes →probed; a third is never attempted);TestLandingProbeCrashRestartsOnlyTheProbe(a fresh worker on a journal atprobingwithAttempt = 1does not rerunlocalorrestored: their journal steps are untouched and no second.files-genwrite happens);TestLandingExhaustedAttemptsMarkRollback.
- [ ] Steps 1 to 5. Commit:
git commit -m "host: the landing's probing and probed phases (§7.6, §7.7)" ...
---
Task 7: Commit and open on the target (BLOCKED-ON-CLAIM: C1, C2; Tasks 5 and 6 first)
Files: modify internal/host/movesland.go, internal/host/movesland_test.go; modify internal/registry/registry.go (DeleteIfHold).
Interfaces:
- In
landingPass, atprobed:provision.SetRecordMove(MoveCommit(g, cfg.Now()));ErrCutDeadline→ the rollback marker; success or an already-committedrecord → the claim half:hostclaim.Update(Commit(id, rec.Move.From, sourceBox, cfg.Region, sourceScope, stagingScope, newID))wheresourceScope = {Location: TrimSuffix(holder.location, "/"), Incarnation, EvidenceAt: the cut's stop evidence time (stopped-source.json'sCheckedAt), RequestLimit: 120 s}andstagingScope = {Location: moves.ScopeLocation(host, id), Incarnation, EvidenceAt: seal.Bound(), RequestLimit: 120 s}(the staging lane's own seal bound, claim rev 6.23; Plan 5 Task 3 proves the deadline); the claim half is written by whoever sees the record ahead (§7.5): this pass, or the console's pass (Plan 5). - The open:
cfg.ReleaseHold(host, id)(registry.ReleaseHold);changed == falsewith the row alreadyreadyandhold_op == ""is a replay and fine;MoveOpened(g, now);nudgeSerial; the activator's entry from the probe is the serving process: no restart. registry.DeleteIfHoldis Plan 1 Task 12's (D12); Task 8 uses it without depending on this task.
Tests: TestCommitThenOpenInOrder (witness wCommitBeforeOpen: driven from the flip through every landing phase with the real transitions, no fixture phase edits; the row is ready only after the record says committed and the claim says committed); TestOpenAfterCrashDoesNotReprobe (Review Focus 3: a worker restarted on a record at committed with the claim still landing/probed writes the claim half, opens, and never calls Probe); TestLateCommitRollsBack (Review Focus 2).
- [ ] Steps 1 to 5. Commit:
git commit -m "host: commit as a record CAS, the claim half, the conditional open (§7.5, §7.9 steps 1 and 2)" ...
---
Task 8: The source's finalization park
Files: create internal/host/movesfinal.go, internal/host/movesfinal_test.go; modify internal/host/movespass.go (records in committed whose From == cfg.Region run finalizeSource).
Interfaces:
finalizeSource(ctx, s, w, rec) error(§7.9 step 3), on the source box, only when the record iscommittedand either this box's row hashold_op == rec.Move.IDor the op journal (moves.Journalfor this op) hasSteps["row-deleted"](round-2 finding 12: a crash between the row's deletion andMoveSourceParkedmust not lock the close out; a replacement row with anotherhold_opis refused by the first condition and does not match the second); Review Focus 5: 1. the remote half:cfg.Park.Run(ctx, park.Work{Host, ID: <the park-replica obligation for cfg.Region under this op, D6>, Op: id})(the engine takesLeases.Acquireitself; the source holds no lease of its own here);ErrPendingis fine: the copies and version deletes are done whencfg.Park.Parkedis true; acknowledgement after the horizon is the regional runner's (C4); 2. the local half under the host guard:cfg.Local.RetireInstallation(ctx, host, hostguard.Capture(dataDir, host), <park-local obligation id>, id)parks the database with<dbPath>.gen, the files directory,<host>.env,<db>.corruptand the op journals into.parked/superseded-<id>/<host>/<retirement>/(the destinationpark.Localderives from the obligation's op; ifpark.Localhardcodes.parked/<inc>/..., add thesuperseded-<op>form beside Task 9's remote destination);CompleteObligation(opID, parkLocalID)throughhostclaim.Update; 3.cfg.ReplaceTimers(host, nil)(clears the timers rows); journalSteps["row-deleted"] = "pending", thencfg.DeleteIfHold(host, id)(the row), thenSteps["row-deleted"] = "done"(a replay that findspendingand no row with thishold_optreats the delete as done); the source box's config ack (appconfig.ConfigAckKey(cfg.Box, host), §6.3) is copied tomoves.ReportPrefix(...) + "config-ack-source.json"and deleted; 4.MoveSourceParked(g, now);nudgeSerial. Every step journaled inmoves.Journal; replayable.
Tests: TestSourceParkWaitsForCommit (Review Focus 5: a landing record, or a committed one whose row's hold_op is another op → nothing parked, nothing deleted); TestSourceParkSurvivesACrashAfterTheRowDelete (round-2 finding 12: the journal says row-deleted: pending, the row is gone; the replay stamps source_parked_at); TestSourceParkRetiresInstallationAndRow (the database, .gen, files dir and env are gone from live paths and present under .parked/superseded-<id>/; the row is gone; timers rows gone; source_parked_at set; the park-local obligation acknowledged); TestSourceParkReplayIsIdempotent.
- [ ] Steps 1 to 5. Commit:
git commit -m "host: the source's finalization park after the commit (§7.9 step 3)" ...
---
Task 9: Gate and copy
- [ ] Full gate, cross-compile (the
peercred_other.gostub). - [ ] Copy list for Plan 6: M-C6 "Stopped in <from>. Starting in <to>." (emitted at
probing), M-C7 (emitted at the open: "Moved. <host> is served from <to>. It was offline for <seconds> seconds.").
Self-review notes
Coverage: §7.7 every bullet (Tasks 1, 5), §7.14 the landing rows and the admitted writer's start (Task 5, through Plan 6's sequence), §5.1 start check (Task 4), §7.9 steps 1 to 3 (Tasks 2, 3, 7, 8), §7.5 commit row and "any actor writes the claim half" (Tasks 3, 7; Plan 5 adds the console), K6 (Task 5 step 1), §7.13 rows landing: probing, probed and committed, the claim still landing (Tasks 6, 7). Steps 4 and 5 of §7.9 (the target's staging park and the close) are Plan 5's.