Skip to content

Commit 0581ca9

Browse files
docs(vrs): define the no-CAS launch drift boundary
Make launch drift visible without making it disruptive, and keep replacing live work an explicitly selected operation. R29 derives a versioned desired launch fingerprint from the minimal effective fields st2 already passes to a task. Only an st2 launch records an observed fingerprint, bound to that launch's exact runtime identity and creation incarnation; a missing or mismatched binding reports `unknown`. Healthy drifted and unknown tasks are adopted without implicit restart, so R11's nondisruptive adoption is preserved. R30 keeps ordinary recovery ordinary: an absent or dead active task launches from the latest current declaration, and replacing live work is a separate operation fenced by catalog, host, effective PTY root, task set, and an exact runtime identity recheck immediately before disruption. Every behavior remains complete with an ordinary catalog folder and without CAS, captured generations, or replacement journals. Numbered R29/R30 by appending: R20-R28 are in use, and the R12/R18 gaps are left as gaps so existing references stay unambiguous. agent-tool: Claude Code agent-tool-version: 2.1.220 agent-runtime: Claude Code 2.1.220 agent-session-lookup: unavailable tooling-profile: dotfiles@unknown-dirty
1 parent b868a07 commit 0581ca9

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

docs/vrs/requirements.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,3 +267,17 @@ accepted.
267267
rationale. Its receipt proves the declaration edit, never runtime
268268
convergence. Human listing, roster JSON, task inventory, and Doctor expose
269269
desired state without conflating it with presence or observed liveness.
270+
- **R29 Visible, nondisruptive launch drift:** st2 derives a versioned desired
271+
launch fingerprint from the minimal effective fields it already passes to a
272+
task. Only an st2 launch records an observed fingerprint, bound to that
273+
launch's exact runtime identity and creation incarnation. A missing or
274+
mismatched binding reports `unknown`; otherwise inspection reports
275+
`converged` or `drifted`. Healthy `drifted` and `unknown` tasks are adopted
276+
without implicit restart.
277+
- **R30 Explicit replacement boundary:** An absent or dead active task launches
278+
from the latest current declaration. Retirement stops live work and prevents
279+
relaunch. Replacing live work is a separate, explicitly selected operation
280+
fenced by catalog, host, effective PTY root, task set, and an exact runtime
281+
identity recheck immediately before disruption. Renaming remains
282+
retire-old/add-new. Every behavior remains complete with an ordinary catalog
283+
folder and without CAS, captured generations, or replacement journals.

docs/vrs/spec.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -723,3 +723,83 @@ the resident supervisor continues to reconcile the complete local catalog.
723723
plan, and current plan step. Prove that stale state is distinguishable and
724724
that a supervisor can follow plan progress without inspecting a PTY before
725725
adding the shape to `AGENT-SPEC.md`.
726+
- **DQ4 Relaunch boundary (R29-R30):** Preserve R11's nondisruptive adoption
727+
while making launch drift visible. For each declared task, derive the desired
728+
launch fingerprint from a deterministic, versioned encoding of only:
729+
backend kind, lowered shell source or direct argv, resolved working directory,
730+
and the st2-managed plus declared effective environment. Tags, descriptive
731+
metadata, unrelated inherited environment, file contents, and other boot-time
732+
snapshots are not part of this fingerprint.
733+
734+
As part of its own successful task launch, st2 records the observed
735+
fingerprint together with that launch's exact runtime identity and creation
736+
incarnation. The observed fingerprint is trustworthy only while the current
737+
live runtime exactly matches that binding. Inspection then reports:
738+
739+
| State | Meaning | Healthy-task action |
740+
| --- | --- | --- |
741+
| `converged` | desired and bound observed fingerprints match | adopt |
742+
| `drifted` | desired and bound observed fingerprints differ | adopt and report drift |
743+
| `unknown` | the observed binding is missing or does not match the live runtime | adopt and report unknown |
744+
745+
`unknown` includes a healthy legacy or externally adopted runtime, as well as
746+
a manual PTY restart or external child replacement whose runtime identity or
747+
creation incarnation no longer matches st2's launch record. Stale observed
748+
metadata is never reused for the new incarnation. Catalog publication,
749+
supervisor restart, metadata edits, and launch-field edits do not implicitly
750+
disrupt any healthy task.
751+
752+
Ordinary reconciliation remains sufficient after every interruption:
753+
754+
| Declaration | Process | Action |
755+
| --- | --- | --- |
756+
| active | absent or dead | reap stale state and launch the latest current desired contract |
757+
| active | alive | adopt and report `converged`, `drifted`, or `unknown` |
758+
| retired | alive | stop; do not relaunch |
759+
| retired | absent or dead | do not launch |
760+
761+
Replacing live drifted work is a separate explicit operation. Its scope is
762+
one selected catalog, pinned host, resolved effective PTY root, and selected
763+
task set. A future interface may preview drifted tasks and select one, a
764+
subset, or all of them; this contract does not reserve a command name. The
765+
operation must re-read the selected task and recheck its exact live runtime
766+
identity immediately before each stop. A missing, changed, wrong-host, or
767+
wrong-root target refuses without disruption.
768+
769+
Replacement does not capture an old launch contract or boot inputs. If st2
770+
stops after the identity check and is then interrupted, ordinary
771+
absent/dead reconciliation launches the latest current desired contract.
772+
There is no replay of an older generation, durable operation journal,
773+
operation ID, phase machine, terminal receipt, or atomic old-to-new runtime
774+
transition. A task rename is the explicit sequence retire old, then add new.
775+
776+
This entire lifecycle works from an ordinary copied or synchronized catalog
777+
folder. CAS may later add publication, history, or storage optimization, but
778+
fingerprinting, inspection, reconciliation, replacement, retirement,
779+
recovery, and rename must neither require nor become incomplete without it.
780+
781+
Executable acceptance proves:
782+
783+
1. metadata, tags, and Resource-only edits preserve the fingerprint and live
784+
runtime, while kind, launch, resolved-cwd, or effective-environment edits
785+
report `drifted` without changing runtime identity;
786+
2. a healthy legacy runtime reports `unknown` and remains unchanged, and a
787+
manual or external restart with a changed runtime identity or creation
788+
incarnation cannot reuse the prior observed fingerprint and reports
789+
`unknown`;
790+
3. natural exit or death launches once from the latest current declaration
791+
and records that launch's observed fingerprint;
792+
4. explicit replacement refuses stale identity or scope, and affects only
793+
the selected drifted tasks;
794+
5. interruption after stop heals through ordinary reconciliation to the
795+
latest current desired contract, without old-state replay;
796+
6. retirement stops and prevents relaunch, while rename works as
797+
retire-old/add-new; and
798+
7. the same proofs pass using only a plain local catalog folder with no CAS
799+
service, CAS metadata, database, or network dependency.
800+
801+
The executable acceptance above resolves this open implementation design.
802+
See [#40](https://github.com/compoundingtech/st2/issues/40),
803+
[#41](https://github.com/compoundingtech/st2/issues/41),
804+
[#44](https://github.com/compoundingtech/st2/issues/44), and
805+
[#60](https://github.com/compoundingtech/st2/issues/60).

0 commit comments

Comments
 (0)