carlos run logs: finish logs a run's ending only once its result has landed (#325, Astra round 3)
Human
Prompt
re-up copy review?
From this commit's own message. The prompt ledger has no entries for it — which is what a squashed, rebased or amended commit looks like, and what every commit looks like in a repo without a ledger.
Summary
Astra round 3 (1 P2, accepted): a result that never landed left the run picked for a later agent's close-out, which logged a second, contradictory ending. finish now logs only after its result write lands; the close-out owns the ending otherwise. Regression test (failed result writes, then restart) mutation-checked; census re-pinned.
4 files changed,
+59
−12
internal/host/runevents_linux_test.go+42 −0internal/host/runexec.go+14 −9internal/provision/plan9_b8_census_test.go+2 −2internal/provision/testdata/plan14-root-reads-run-lifecycle-logs-325.tsv+1 −1
CI passed — run details
CI log
=== gate ===
cd launchctx && go vet ./... && go test ./... -count=1
ok amadan.net/carlos/platform.git/launchctx 0.013s
? 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 333.474s
? github.com/carlosframework/platform/cmd/changelog [no test files]
ok github.com/carlosframework/platform/cmd/console 3.447s
ok github.com/carlosframework/platform/cmd/moveprobe 94.495s
ok github.com/carlosframework/platform/cmd/zddprobe 0.708s
ok github.com/carlosframework/platform/internal/activator 249.866s
ok github.com/carlosframework/platform/internal/agentsock 0.073s
ok github.com/carlosframework/platform/internal/alerting 0.009s
ok github.com/carlosframework/platform/internal/analytics 0.095s
ok github.com/carlosframework/platform/internal/appconfig 2.742s
ok github.com/carlosframework/platform/internal/apperr 0.419s
ok github.com/carlosframework/platform/internal/applog 0.330s
ok github.com/carlosframework/platform/internal/awsinv 0.005s
ok github.com/carlosframework/platform/internal/boxchoice 0.020s
ok github.com/carlosframework/platform/internal/boxid 1.002s
? 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.071s
ok github.com/carlosframework/platform/internal/caps 0.019s
ok github.com/carlosframework/platform/internal/certwarm 0.072s
ok github.com/carlosframework/platform/internal/cgroup 0.914s
ok github.com/carlosframework/platform/internal/changelog 0.503s
ok github.com/carlosframework/platform/internal/claimactivation 1.303s
ok github.com/carlosframework/platform/internal/clamd 0.069s
? github.com/carlosframework/platform/internal/cliflag [no test files]
ok github.com/carlosframework/platform/internal/console 418.627s
? 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.526s
ok github.com/carlosframework/platform/internal/dbdoor/dbdoortest 0.019s
ok github.com/carlosframework/platform/internal/dbverify 0.071s
ok github.com/carlosframework/platform/internal/dnsrec 0.071s
ok github.com/carlosframework/platform/internal/docsite 0.068s
ok github.com/carlosframework/platform/internal/domains 2.744s
ok github.com/carlosframework/platform/internal/doorkey 0.018s
ok github.com/carlosframework/platform/internal/economics 0.070s
ok github.com/carlosframework/platform/internal/edge 46.154s
? github.com/carlosframework/platform/internal/edgeproof [no test files]
ok github.com/carlosframework/platform/internal/edgesfile 0.015s
ok github.com/carlosframework/platform/internal/fleetapi 0.407s
ok github.com/carlosframework/platform/internal/gate 1.968s
ok github.com/carlosframework/platform/internal/genselect 0.051s
ok github.com/carlosframework/platform/internal/geo 0.051s
ok github.com/carlosframework/platform/internal/geoip 0.106s
ok github.com/carlosframework/platform/internal/historyreadback 0.419s
ok github.com/carlosframework/platform/internal/host 190.192s
ok github.com/carlosframework/platform/internal/hostactors 7.080s
ok github.com/carlosframework/platform/internal/hostactors/awsmembership 0.006s
ok github.com/carlosframework/platform/internal/hostbox 3.854s
ok github.com/carlosframework/platform/internal/hostclaim 1.465s
ok github.com/carlosframework/platform/internal/hostenv 0.006s
ok github.com/carlosframework/platform/internal/hostevidence 0.011s
ok github.com/carlosframework/platform/internal/hostexec 7.677s
ok github.com/carlosframework/platform/internal/hostfence 0.088s
ok github.com/carlosframework/platform/internal/hostfiles 10.982s
ok github.com/carlosframework/platform/internal/hostfloor 0.056s
ok github.com/carlosframework/platform/internal/hostguard 1.113s
ok github.com/carlosframework/platform/internal/hostops 3.172s
? github.com/carlosframework/platform/internal/hostops/fencerelease [no test files]
ok github.com/carlosframework/platform/internal/hostops/internal/fencerelease 0.008s
ok github.com/carlosframework/platform/internal/hostquarantine 0.035s
ok github.com/carlosframework/platform/internal/hostrelocate 1.174s
ok github.com/carlosframework/platform/internal/hostresolve 0.358s
ok github.com/carlosframework/platform/internal/hostwrite 0.004s
ok github.com/carlosframework/platform/internal/infraview 0.003s
ok github.com/carlosframework/platform/internal/instancectl 5.258s
ok github.com/carlosframework/platform/internal/instanceexec 2.830s
ok github.com/carlosframework/platform/internal/instancefs 0.007s
ok github.com/carlosframework/platform/internal/instancekey 0.003s
ok github.com/carlosframework/platform/internal/instanceupdates 0.013s
ok github.com/carlosframework/platform/internal/layout 2.662s
ok github.com/carlosframework/platform/internal/lbhealth 0.004s
ok github.com/carlosframework/platform/internal/lease 9.960s
ok github.com/carlosframework/platform/internal/lease/leasetest 0.007s
ok github.com/carlosframework/platform/internal/ledger 0.034s
ok github.com/carlosframework/platform/internal/mail 0.387s
ok github.com/carlosframework/platform/internal/maintenance 0.094s
ok github.com/carlosframework/platform/internal/maintenanceexec 5.760s
ok github.com/carlosframework/platform/internal/maintenanceguard 0.269s
ok github.com/carlosframework/platform/internal/metrics 0.006s
ok github.com/carlosframework/platform/internal/moves 24.155s
ok github.com/carlosframework/platform/internal/moves/archive 1.413s
ok github.com/carlosframework/platform/internal/objstore 0.575s
ok github.com/carlosframework/platform/internal/ops 0.317s
ok github.com/carlosframework/platform/internal/park 0.389s
ok github.com/carlosframework/platform/internal/privatefile 0.004s
ok github.com/carlosframework/platform/internal/provision 40.394s
ok github.com/carlosframework/platform/internal/publicrelease 0.016s
? github.com/carlosframework/platform/internal/regionname [no test files]
ok github.com/carlosframework/platform/internal/registry 6.199s
ok github.com/carlosframework/platform/internal/relay 7.276s
ok github.com/carlosframework/platform/internal/release 29.073s
ok github.com/carlosframework/platform/internal/rollout 4.889s
ok github.com/carlosframework/platform/internal/rolloutwords 0.007s
ok github.com/carlosframework/platform/internal/rootaws 0.009s
ok github.com/carlosframework/platform/internal/rootparticipation 0.058s
ok github.com/carlosframework/platform/internal/rootstate 0.027s
ok github.com/carlosframework/platform/internal/runs 0.496s
ok github.com/carlosframework/platform/internal/s3compat 0.049s
ok github.com/carlosframework/platform/internal/safefile 0.005s
ok github.com/carlosframework/platform/internal/schedule 3.181s
ok github.com/carlosframework/platform/internal/seeds 0.012s
ok github.com/carlosframework/platform/internal/sim/hostlife 22.905s
ok github.com/carlosframework/platform/internal/sim/litestreamfacts 4.981s
ok github.com/carlosframework/platform/internal/status 0.122s
ok github.com/carlosframework/platform/internal/steering 0.013s
ok github.com/carlosframework/platform/internal/stopevidence 0.581s
ok github.com/carlosframework/platform/internal/svcrole 0.003s
ok github.com/carlosframework/platform/internal/telemetry 0.005s
ok github.com/carlosframework/platform/internal/termfence 0.004s
ok github.com/carlosframework/platform/internal/tunnelclient 0.006s
ok github.com/carlosframework/platform/internal/unixdial 0.004s
ok github.com/carlosframework/platform/internal/updatewords 0.005s
ok github.com/carlosframework/platform/internal/usage 0.006s
ok github.com/carlosframework/platform/internal/version 0.006s
ok github.com/carlosframework/platform/internal/vet 1.755s
=== 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: 49414306 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.022s
=== RUN TestT4StorageProbeMinio
2026/10/20 15:58:20 moves: T4: STORE: list: operation error S3: ListObjectsV2, https response error StatusCode: 403, RequestID: 18E0481385F680BD, 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.00s)
PASS
ok github.com/carlosframework/platform/internal/host 0.021s
minio contract: PASS
diff --git a/internal/host/runevents_linux_test.go b/internal/host/runevents_linux_test.go| index bcbda343e..16f51b560 100644 |
| --- a/internal/host/runevents_linux_test.go |
| +++ b/internal/host/runevents_linux_test.go |
| @@ -1,14 +1,17 @@ |
| package host |
| import ( |
| + "context" |
| "errors" |
| "reflect" |
| "strings" |
| "testing" |
| + "time" |
| "github.com/carlosframework/platform/internal/activator" |
| "github.com/carlosframework/platform/internal/applog" |
| "github.com/carlosframework/platform/internal/instancectl" |
| + "github.com/carlosframework/platform/internal/provision" |
| "github.com/carlosframework/platform/internal/release" |
| ) |
| @@ -70,3 +73,42 @@ func TestRunNotStartedLogsOnlyItsEnd(t *testing.T) { |
| } |
| } |
| } |
| + |
| +// A run whose result never landed logs no ending of its own: the run stays |
| +// picked, and the next agent's close-out writes and logs the one ending, |
| +// so the log never holds two that contradict each other (Astra round 3). |
| +func TestRunWhoseResultNeverLandedLeavesTheEndingToTheCloseOut(t *testing.T) { |
| + defer func(d time.Duration) { runFinishBound = d }(runFinishBound) |
| + runFinishBound = 300 * time.Millisecond |
| + dir := release.NewDirStore(t.TempDir()) |
| + rec, req := pickedRun(t, dir, 60) |
| + req.By = "member@example.com" |
| + h := &fakeHandle{polls: make(chan instancectl.CmdStatus, 1)} |
| + h.polls <- instancectl.CmdStatus{State: instancectl.CmdDone, InvocationID: "inv1", Result: "exit-code", Status: "0", Code: "1"} |
| + var events eventLog |
| + w := execWorker(t, &failingPuts{Store: dir, part: "/result.json"}, &fakeLauncher{handle: h}, "boot-1") |
| + w.events = &events |
| + rt, _ := runOwnedRoute(runHost)(runHost) |
| + w.execute(context.Background(), rec, req, *rt, newRunHandle()) |
| + if r := currentRun(t, dir); r.State != provision.RunPicked { |
| + t.Fatalf("run %+v, want still picked", r) |
| + } |
| + // The agent restarts once storage has recovered. |
| + cur, err := provision.GetRecord(context.Background(), dir, rec.Account, rec.App, rec.Host) |
| + if err != nil { |
| + t.Fatal(err) |
| + } |
| + var l execLog |
| + next := testWorker(dir, runOwnedRoute(runHost), "box-1", "boot-2", &l) |
| + next.events = &events |
| + next.consider(context.Background(), *cur) |
| + var endings []string |
| + for _, e := range events.all() { |
| + if !strings.Contains(e.msg, " started by ") { |
| + endings = append(endings, e.msg) |
| + } |
| + } |
| + if len(endings) != 1 || !strings.Contains(endings[0], "the box's agent restarted") { |
| + t.Fatalf("endings %q, want only the close-out's", endings) |
| + } |
| +} |
diff --git a/internal/host/runexec.go b/internal/host/runexec.go| index c0a72d7f3..f3c0004cc 100644 |
| --- a/internal/host/runexec.go |
| +++ b/internal/host/runexec.go |
| @@ -441,16 +441,21 @@ func (w *runsWorker) finish(ctx context.Context, rec provision.Record, req runs. |
| }) |
| if err != nil { |
| log.Printf("agent: runs: %s %s: result: %v", rec.Host, req.ID, err) |
| - } else if err := untilLanded(fctx, func(ctx context.Context) error { |
| - _, err := provision.SetRecordRun(ctx, w.store, rec.Account, rec.App, rec.Host, runFinishOurs(req.ID, w.box, w.boot)) |
| - return err |
| - }); err != nil && !errors.Is(err, provision.ErrRunConflict) && !errors.Is(err, os.ErrNotExist) { |
| - log.Printf("agent: runs: %s %s: done: %v", rec.Host, req.ID, err) |
| + } else { |
| + // The ending is logged only once the result has landed (amadan |
| + // #325: run lines are at most once). A result that never landed |
| + // leaves the run picked, and a later agent's closeInterrupted |
| + // writes and logs its own ending; logging this one too would put |
| + // two contradictory endings in the log. A run with no handle never |
| + // had its unit started. |
| + w.runEvent(rec, runEndedLine(req.ID, res, handle != nil)) |
| + if err := untilLanded(fctx, func(ctx context.Context) error { |
| + _, err := provision.SetRecordRun(ctx, w.store, rec.Account, rec.App, rec.Host, runFinishOurs(req.ID, w.box, w.boot)) |
| + return err |
| + }); err != nil && !errors.Is(err, provision.ErrRunConflict) && !errors.Is(err, os.ErrNotExist) { |
| + log.Printf("agent: runs: %s %s: done: %v", rec.Host, req.ID, err) |
| + } |
| } |
| - // What the box saw end, written or not: a result that never landed |
| - // is ended as lost by the sweep, but the command's own ending was |
| - // this. A run with no handle never had its unit started. |
| - w.runEvent(rec, runEndedLine(req.ID, res, handle != nil)) |
| w.cleanUp(rec, req, handle) |
| } |
diff --git a/internal/provision/plan9_b8_census_test.go b/internal/provision/plan9_b8_census_test.go| index 207be0618..07840ae95 100644 |
| --- a/internal/provision/plan9_b8_census_test.go |
| +++ b/internal/provision/plan9_b8_census_test.go |
| @@ -1102,8 +1102,8 @@ var plan9B8CensusInventory = []censusEntry{ |
| // The run sweep clears a terminal run past retention through SetRecordRun (RunClear). |
| {"internal/console/runsweep.go", "Server.sweepTerminalRun", "record-writer", "key:SetRecordRun", "78e3510bbf056dbf28446391b552c87060094ca803a3b1a8b7d7013163ee136b"}, |
| // The box records a run's end through SetRecordRun (runFinishOurs). |
| - // Re-reviewed for run-lifecycle-logs-325 (amadan #325, proposed): emits the run's end as a member log event; record writes unchanged. |
| - {"internal/host/runexec.go", "runsWorker.finish", "record-writer", "key:SetRecordRun", "8353643af2281da9b08b629d387d1d91ba0c8db2b2afbedc24cbfb3042854039"}, |
| + // Re-reviewed for run-lifecycle-logs-325 (amadan #325, proposed): emits the run's end as a member log event once its result has landed (at most once); record writes unchanged. |
| + {"internal/host/runexec.go", "runsWorker.finish", "record-writer", "key:SetRecordRun", "42f8628f74fcdfd3a0a56d302caa6f423f6c8fe8726c3561028e94ad97037041"}, |
| // The box closes a run an agent restart interrupted through SetRecordRun (runFinishOurs). |
| // Re-reviewed for run-lifecycle-logs-325 (amadan #325, proposed): reads result.json before and after its create-only write and emits the run's end as a member log event only when the result is its own and its done CAS landed (at most once); record writes unchanged. |
| {"internal/host/runs.go", "runsWorker.closeInterrupted", "record-writer", "key:SetRecordRun", "b540e246a977470c50d3ebbbef080f9b8a824490fd3bb8bd6f98537bc882adee"}, |
diff --git a/internal/provision/testdata/plan14-root-reads-run-lifecycle-logs-325.tsv b/internal/provision/testdata/plan14-root-reads-run-lifecycle-logs-325.tsv| index 29d2dce11..adfc3c4b2 100644 |
| --- a/internal/provision/testdata/plan14-root-reads-run-lifecycle-logs-325.tsv |
| +++ b/internal/provision/testdata/plan14-root-reads-run-lifecycle-logs-325.tsv |
| @@ -1,6 +1,6 @@ |
| # Census overlay run-lifecycle-logs-325 (amadan #325: the box's carlos run worker emits run started and run ended as info-level member log events through the agent's EventSink), loaded LAST, after bootstrap-carlos-follows-316. Proposed; ruling asked of the census owner on #280. |
| # No root read, file read or record write is added: the events are pure string formatting plus one EventSink.Event call, so runAgent (which passes the sink to armRunsPass) and runsWorker.execute (which emits the two events) keep their class, task and read sites, and only their digests, runAgent's Route offset and the internal/host envelope move. execute is accepted-legacy, so its declaration is re-pinned and the seal moves. |
| -@coverage internal/host 2866a11e1992a250b09dd560c7186c4fa42ad1019c6415dc03d82ccaca9dd832 |
| +@coverage internal/host 8dadfcbb1f519c7596269266cd8fc61a103ab376f175b40d4946d8ac5ca35eb0 |
| @legacy 6f7ae8c101088f20464d1a727c898190b04726de1f08ee6040212be2ad840caa internal/host/runexec.go runsWorker.execute legacy accepted-legacy accepted-legacy;rev3=census-ruling-carlos-run;basis=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): runs one picked run to its result in the bucket; every root action goes through instance control;rev3=PROPOSED-325;identity=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos);basis=emits the run's start and end as member log events through the agent's EventSink; reads unchanged file:Prepare@1838,whole:Route@2539 1b075de70048003120c62153a50f6d83bd3eff6615f9ea5008ddc747846c8fbb |
| internal/host/runexec.go runsWorker.execute legacy accepted-legacy accepted-legacy;rev3=census-ruling-carlos-run;basis=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): runs one picked run to its result in the bucket; every root action goes through instance control;rev3=PROPOSED-325;identity=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos);basis=emits the run's start and end as member log events through the agent's EventSink; reads unchanged file:Prepare@1838,whole:Route@2539 1b075de70048003120c62153a50f6d83bd3eff6615f9ea5008ddc747846c8fbb |
| internal/host/agent.go runAgent authority B,C,D,F rev3=census-ruling-seeded-instances;basis=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos): main's body with wireSeedPlacement called in the activator start's Configure step, before armMovesPass, and the startup sweep's result stored for the import rollback in Recover; read sites unchanged, offsets moved; main's B,C,D,F authority retained PROPOSED E46: captured claim selection and root journal mutation; root RPC outside service host exclusion; SQL/route data never grants root authority. Executing identity: service controller; root for inventory/retirement callbacks.;rev3=PROPOSED-325;identity=the agent (/opt/carlos/carlos agent, carlos-edge.service, user carlos);basis=passes the agent's log sink to armRunsPass; reads unchanged file:Exec@13802,file:Open@731,registry:App@10065,whole:Route@10057,whole:Route@23122 9250dbd16a071a1f01e835f0fb8419e4de59effaa6f1d178b23547957ff66d86 |