Skip to content

feat: persist strict exec generations - #119

Merged
myobie merged 2 commits into
mainfrom
agent/no-cas-strict-exec
Jul 31, 2026
Merged

feat: persist strict exec generations#119
myobie merged 2 commits into
mainfrom
agent/no-cas-strict-exec

Conversation

@myobie

@myobie myobie commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • atomically publish future exec generations as versioned st2.exec-generation.v1 JSON
  • bind every strict record to the PID and kernel process-start token, and refuse mismatched or malformed generations
  • retain read-only compatibility with legacy numeric PID records using PR Add fail-closed diagnostic task inventory #117 retained O_NOFOLLOW, retained-inode, content/metadata, end-path, and process-generation proofs
  • preserve conservative reconciliation: ambiguous live ownership cannot launch a duplicate, and explicit kill refuses a generation that is indeterminate at observation time
  • reap an unpublished process group if exact generation capture or durable record publication fails
  • reap Darwin owned-child zombies through an in-memory kernel-parent capability set before observation; state records alone never authorize waitpid

Why

PR #118 retained-predecessor Ding behavior proof needs a live strict generation after replacement, but its former base PR #116 mixed that narrow exec observation boundary with CAS catalog authoring and lifecycle policy. This PR extracts only the no-CAS exec writer/reader dependency onto PR #117.

No CAS, catalog lock, authoring policy, lifecycle flip, or live catalog/runtime mutation is included.

Impact

New exec spawns write strict JSON instead of a plain PID. Existing numeric records remain readable and are never rewritten during observation. Test fixtures that inspect exec PID files accept both forms so predecessor compatibility remains covered.

For owned children, the backend remembers only PIDs it spawned and successfully published. waitpid(WNOHANG) is permitted only through that in-memory capability, allowing an owned Darwin zombie to become positive absence even when proc_pidinfo can no longer return its start token. Restarted backends, foreign processes, malformed records, and token mismatches retain the same fail-closed observation and signal refusal at observation time.

Exact retirement boundary

Generation v1 receipts authorize observation only. Exec kill still observes a generation and then separately signals its numeric process group; restart and final GC still remove the generation record by pathname. Those paths are not race-free across PID/PGID reuse or concurrent record replacement. This PR does not implement exact exec retirement and does not authorize production cutover. Issue #121 owns capability-pinned signaling, record retirement, and production cutover authority.

Verification

  • cargo test generation_observation_tests --lib -- --test-threads=1 — 12 passed, including exact owned-zombie reap and non-child mismatch refusal
  • cargo test --test exec_backend -- --test-threads=1 — 6 passed, including restart/final cleanup and whole process-group teardown
  • cargo test --test task_inventory_cli -- --test-threads=1 — 8 passed
  • cargo test --test nomad_survival -- --test-threads=1 — 8 passed
  • cargo test --test transport_isolation -- --test-threads=1 — 2 passed
  • cargo test --test targeted_reconcile -- --test-threads=1 — 3 passed
  • cargo test --test run -- --test-threads=1 — 26 passed
  • Linux cargo test --workspace --all-targets -- --test-threads=1 — green
  • independent macOS arm64 full workspace/all-target run — 438/438 passed; focused observer 12/12, exec 6/6, inventory 8/8, Nomad 8/8, transport 1/1, targeted 3/3, run 26/26
  • cargo clippy --workspace --all-targets -- -D warnings -A clippy::too_many_arguments -A clippy::type_complexity — green on Linux and macOS; the two allowances are pre-existing current-tool lints outside this diff
  • scoped Rustfmt and git diff --check — green
  • exact restacked head d0666e840ac8852ca733d11611781f17a10adf98
  • fresh focused Linux observer 12/12 and exec backend 6/6; exact-file Rustfmt and git diff --check are green
  • hosted Nix run 30626355901, job 91142441191 — success at exact restacked head d0666e840ac8852ca733d11611781f17a10adf98
  • semantic restack proof: final tree b778476ef13d6af52246ebdbf05d722ab6e3ce1e and binary delta SHA-256 74b6385b7ce0d988d2df9980cab19abe2febce33b45e577400caf2ca10e427e5 are identical before/after
  • fresh focused suites, full workspace/all-targets, Clippy, diff-scoped Rustfmt, and git diff --check are green at the restacked head
  • no test process residue; no production mutation

Review order

Review and merge the dependency stack base-to-tip: PR #117 → PR #119 → PR #118. Do not merge a child before its base. If a base merge rewrites ancestry, restack the child without semantic change and require a fresh exact-head hosted check before later merge handoff.

All required local and hosted product-code gates are green at the restacked head.

@myobie
myobie force-pushed the agent/no-cas-strict-exec branch from 4205b44 to 3afefa0 Compare July 31, 2026 02:21
@myobie
myobie marked this pull request as ready for review July 31, 2026 02:40
@myobie
myobie force-pushed the agent/no-cas-strict-exec branch from 3a03ed0 to d0666e8 Compare July 31, 2026 11:14
@myobie
myobie changed the base branch from agent/no-cas-task-inventory to main July 31, 2026 11:15
@myobie
myobie merged commit 7151d85 into main Jul 31, 2026
1 check passed
@schickling schickling added area:exec Exec backend and process-group management · Set: manual area:identity Agent, session, run, and launch-generation identity · Set: manual type:feature New user-visible or system capability · Set: manual labels Aug 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:exec Exec backend and process-group management · Set: manual area:identity Agent, session, run, and launch-generation identity · Set: manual type:feature New user-visible or system capability · Set: manual

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants