harness: Run 9 (B) moveapp moved PASS (366 s offline, ~23 s of steps), defect 8 (source scheduler re-creates the env after open), nesting deferred
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 file changed,
+62
−0
harness/RUNLOG.md+62 −0
CI cancelled — superseded by a newer push — run details
CI log
=== gate === cd launchctx && go vet ./... && go test ./... -count=1 ok amadan.net/carlos/platform.git/launchctx 0.012s ? 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 amadan: job cancelled — a newer push superseded it
diff --git a/harness/RUNLOG.md b/harness/RUNLOG.md| index d4b8814e7..b2dea7040 100644 |
| --- a/harness/RUNLOG.md |
| +++ b/harness/RUNLOG.md |
| @@ -1751,3 +1751,65 @@ isn't there. (My first flip came 2 min 40 s after the seal because my own proces |
| `flip` and `open` straight after the previous door, or retry them every 15 s until the next pass. The script's `MVR` |
| does that and logs each try. |
| +Resumed at flip (`r9-move.host.sh moveapp move resume 2026-10-20T17:20:31.070Z`), after the 17:25:43Z timed pass had |
| +rewritten the reports: |
| + |
| +| step | at | took | result | |
| +|---|---|---|---| |
| +| flip | 17:26:22.520Z | 4.3 s (try 1) | `Stopped in ie. Starting in uk.` / `uk holds everything moveapp.dev.harness.test needs. Nothing is served yet. Run carlos move offline open ...` exit 0. Dennis: row `landing`, region uk, **flat** `/data/moveapp.dev.harness.test.db`; `<host>.env` `27ff170a...` (= sophie's byte for byte), instance key sha256 `067b3156...` (same digest), `config.env` with all seven names (the store binding), files `instance.key` `95b88862...` (same), timers `every-minute` and `once-1` (due 17:37:43Z) carried | |
| +| open | 17:26:27.150Z | 4.2 s (try 1) | `moveapp.dev.harness.test is served from uk. Run carlos move offline finish ... once ie has cleaned up.` exit 0. Sophie parks: `env file absent`, `parked: .../source`; fence lifted 17:26:28Z | |
| +| first request on dennis | 17:26:31.352Z | 5.7 s | 404 at 17:26:31.45Z (not ready yet), **200 at 17:26:37.054Z** (2.5 s request: the first wake plus root's stage pass) | |
| +| backhaul | 17:26:37Z | | through sophie's edge 200 (34 ms), through leo's 200 (24 ms) (H13b) | |
| +| finish | 17:26:39.342Z | 262.0 s (try 1; the CLI waits) | `Waiting for ada-letterpress to clean up ...` then **`Moved. moveapp.dev.harness.test is served from uk. It was offline for 356 seconds.`** `Move mv_twameyccfp7ryimabnjg32ltla of moveapp.dev.harness.test is done.` exit 0, at 17:31:01.377Z. Sophie 17:30:59Z `removed retired instance route ... (record gone)`, `tombstone lifted` | |
| + |
| +**Downtime budget.** Offline from start (17:20:31.070Z) to the first 200 on dennis (17:26:37.054Z): **366 s**; the |
| +console's own figure is 356 s. Of that, 2 min 40 s was my late first flip and about 1 min 10 s was waiting for the |
| +5-minute pass (finding 7). The work itself: start 2.2 s, seal 6.1 s, flip 4.3 s, open 4.2 s, first request 5.7 s: |
| +**about 23 s of steps**, plus operator time between them. For a budget: 25 s of steps per 4 MB instance, plus up to |
| +6 minutes for each of flip and open if the reports have gone stale. `finish` adds 4 to 5 minutes but nothing is |
| +offline by then. |
| + |
| +**B3. Verification on dennis: PASS on every item** |
| +- **Rows:** dennis `/report` (17:31:35Z): `bg` home seq 1-2046 then uk 2047-2644; `worker` home 1-1024 then uk |
| + 1025-1323; `tick` home 17 then uk 6. Contiguous: no row lost or repeated. 2046 > the 2042 read at 17:20:28Z: the |
| + four rows written between that read and the stop arrived too (`db-tail`: everything at or below TXID 117). |
| +- **Instance key:** `platform_key_sha256 067b3156...` on dennis = sophie's before; `<host>.env` byte-equal |
| + (`27ff170a...`). Files: `file_key_sha256 c5a85dd6...` unchanged (`instance.key` `95b88862...`). |
| +- **config.env with the store binding:** all seven names on dennis; the app wrote and read back |
| + `probe/0456deb532974a46.txt` (`... region uk at 2026-10-20T17:26:36Z`) with the store user; `has_secret true`. |
| +- **Timers:** both rows carried; `carlos schedule ls`: `moveapp.dev.harness.test (box dennis) every-minute ... → 200`. |
| + The ticks due while the instance was offline (17:21-17:26Z) did not fire (refused `maintenance fence active`, then |
| + gone with the row), as the plan's Risks say. once-1: see below. |
| +- **Source parked, never deleted:** `/data/.offline-moves/moveapp.dev.harness.test/mv_twameyccfp7ryimabnjg32ltla/` |
| + `sealer/`, `source/instance/`, `source/moveapp.dev.harness.test.json`; the parked report leaves |
| + `/data/instances/<host>` (the mount view), `/data/.instances/<host>` (empty) and `/opt/carlos/live/<host>` |
| + (root-owned, `-> /opt/carlos/versions/mp1/moveapp`) in place, as the plan says. |
| +- **Tombstone lifted at finish:** sophie `tombstone lifted` 17:30:59Z; the sealer's report phase `lifted`; data-ie |
| + `instances/<host>/lock.json` is now `{"generation":1,"expires_at":"1970-01-01T00:00:00Z","owner":"moved:mv_..."}`: |
| + lifted by an expired rewrite, not a delete (the object and its `moved:` owner remain). data-uk's lease is dennis's |
| + (`dennis:215`, 15-minute expiry). |
| +- **Record:** region `uk`, `move` null, `last_move {"id":"mv_twameyccfp7ryimabnjg32ltla","outcome":"done", |
| + "offline_s":356.08}`. |
| + |
| +**Defect 8 (code): after `open`, the source box's scheduler re-creates the parked instance's env file.** At |
| +17:27:04Z (the first every-minute tick after open), sophie wrote `/data/.instances/moveapp.dev.harness.test/` and in it |
| +a new `moveapp.dev.harness.test.env` (carlos 600, 84 bytes) holding only a fresh `CARLOS_ADMIN_TOKEN`. Its row was |
| +still in sophie's registry (`moving`, kept until finishing) with its timers, and open had lifted the fence, so the |
| +runner's `scheduleToken` ran `activator.EnsureAdminToken` on the nested env path |
| +(`internal/host/schedule_wiring.go:154-180`; the runner's call at `internal/schedule/runner.go:502-505`) before any |
| +serve check refused the held row. The row and its timers went at finishing (17:30:59Z); the file stays, outside the |
| +park directory, contradicting the parked report's "the instance directory stays, empty". Impact: a stray secret for a |
| +host that no longer lives there, and a non-empty instance directory a later return move's landing will meet. Fix |
| +direction: the runner must not ensure a token for a row that is held (status `moving`/`landing`), or open must drop |
| +the source's timers when it parks. |
| + |
| +### B4. The post-open nesting step: dennis defers it (outline P0.7 holds only for an idle app) |
| + |
| +After the first request the row is **flat** on dennis (`/data/moveapp.dev.harness.test.db`), as the outline says. |
| +Dennis's layout pass: 17:26:30Z `refused -> db is missing at /data/moveapp.dev.harness.test.db` (before the first |
| +wake), then 17:26:40Z and every pass since `deferred until asleep -> moveapp.dev.harness.test (awake (stopped for the |
| +move in 1h0m0s unless it sleeps first))`. The pass nests only an instance that is asleep, or stops it once a 1-hour |
| +grace runs out (`internal/layout/pass.go:318-322`); an app with a 1-minute schedule never reaches its 15-minute idle. |
| +`carlos status --layout`: `noor-marquetry (nested by default) moveapp.dev.harness.test flat` and the warning "runs |
| +nested instances beside flat ... Nested isolation on this box is not in force until none of those remains". |
| + |