Skip to content

Commit bba5811

Browse files
committed
docs(vrs): refresh host-local implementation map
1 parent f43629f commit bba5811

3 files changed

Lines changed: 47 additions & 46 deletions

File tree

docs/vrs/03-host-local/requirements.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ control-plane replacement in
66
[R03](../requirements.md#L38-L39),
77
[R04](../requirements.md#L43-L46), and
88
[R11](../requirements.md#L65-L70). Partition safety remains a fleet-level
9-
contract in [R18–R19](../requirements.md); this sub-VRS does not redefine it.
9+
contract in [R18/R26](../requirements.md); this sub-VRS does not redefine it.
1010

1111
## Requirements
1212

@@ -45,5 +45,5 @@ contract in [R18–R19](../requirements.md); this sub-VRS does not redefine it.
4545
Relocation requires the explicit coordinated migration contract in
4646
[issue #85](https://github.com/compoundingtech/st2/issues/85).
4747

48-
Current mechanisms, executable evidence, and unimplemented partition
49-
activation work are mapped in [spec.md](spec.md).
48+
Current mechanisms, executable evidence, and the remaining partition questions
49+
are mapped in [spec.md](spec.md).

docs/vrs/03-host-local/spec.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,22 @@ policy, or a second Doctor health model.
77

88
## Subject selection and ownership
99

10-
The CLI selects a catalog and an explicit or locally detected host. A
11-
[`HostLock`](../../../src/host_lock.rs#L1-L67) tracks resident ownership of
12-
that `(catalog, host)` subject independently from another host's slice of the
13-
same synced catalog.
10+
The CLI selects a catalog and an explicit or locally detected host.
11+
[`HostOwnership`](../../../src/host_lock.rs) canonicalizes that subject and
12+
retains its host-scoped kernel `flock` for the resident writer's lifetime,
13+
independently from another host's slice of the same synced catalog.
1414

1515
## Current mechanism and evidence
1616

1717
| Requirement | Current mechanism | Evidence |
1818
| --- | --- | --- |
19-
| HOST-R01 | Reconciliation filters every declaration through its resolved host; remote declarations are reported but not acted on. | [`reconcile`](../../../src/reconcile.rs#L106-L191); [host-placement tests](../../../tests/reconcile.rs#L135-L153) |
20-
| HOST-R02 | One pass discovers declarations, obtains an authoritative local session view, computes desired versus actual, and then adopts or executes the plan. A failed session listing skips the whole pass. | [reconcile pass](../../../src/run.rs#L737-L813); [reconcile-plan model](../../../src/reconcile.rs#L66-L81) |
21-
| HOST-R03 | The long-running CLI checks for a live owner of the same catalog and host, records its own PID, and reclaims stale ownership. | [catalog supervisor entry](../../../src/main.rs#L1738-L1838); [`HostLock` tests](../../../src/host_lock.rs#L83-L143) |
22-
| HOST-R04 | PTY and exec tasks survive normal or forced control-plane termination and binary replacement; the successor preserves PID and creation identity while adopting them. | [replacement acceptance](../../../tests/nomad_survival.rs#L592-L701) |
23-
| HOST-R05 | Normal supervisor exit leaves tasks running. Teardown and retirement are separate paths that target only the selected host's declared task IDs. | [`down` and teardown](../../../src/run.rs#L987-L1056); [explicit-lifecycle acceptance](../../../tests/nomad_survival.rs#L703-L780) |
24-
| HOST-R06 | The deterministic loop surfaces bounded crash-loop failure to the declared supervisor; the root-agent responsibility itself is owned by root R04. | [crash-loop surfacing](../../../src/run.rs#L1090-L1189); [R04](../requirements.md#L43-L46) |
25-
| HOST-R07 | Agent/task liveness and the resident supervisor lock are separate observations. A replacement adopts matching work visible in its selected current state. Sidecar-only work does not make an otherwise unrunnable agent live. No global catalog-liveness classifier is implemented. | [replacement adoption](https://github.com/compoundingtech/st2/blob/661c88b6e50cddbdf85e8ffaca9245c46491a1e0/tests/nomad_survival.rs#L608-L717); [separate supervisor report](https://github.com/compoundingtech/st2/blob/661c88b6e50cddbdf85e8ffaca9245c46491a1e0/src/main.rs#L985-L1008); [DING-only boundary](https://github.com/compoundingtech/st2/blob/661c88b6e50cddbdf85e8ffaca9245c46491a1e0/tests/reconcile.rs#L533-L561) |
19+
| HOST-R01 | Reconciliation filters every declaration through its resolved host; remote declarations are reported but not acted on. | [`reconcile_selected`](../../../src/reconcile.rs); [`other_host_specs_are_skipped`](../../../tests/reconcile.rs) |
20+
| HOST-R02 | One admitted pass discovers declarations, obtains an authoritative local runtime view, computes desired versus actual, and then adopts or executes the plan. A failed session listing skips the whole pass. | [`reconcile_pass_admitted`](../../../src/run.rs); [`up_once_marks_a_list_failure_as_a_skipped_pass`](../../../tests/run.rs) |
21+
| HOST-R03 | `HostOwnership` canonicalizes one catalog/host subject and retains its persistent-inode kernel `flock`; a simultaneous second claim refuses. PID text is diagnostic only. | [`HostOwnership` and `HostLock`](../../../src/host_lock.rs); [ownership tests](../../../src/host_lock.rs) |
22+
| HOST-R04 | PTY and exec tasks survive normal or forced control-plane termination and binary replacement; the successor preserves PID and creation identity while adopting them. | [replacement acceptance](../../../tests/nomad_survival.rs) |
23+
| HOST-R05 | Normal supervisor exit leaves tasks running. Teardown and retirement are separate paths that target only the selected host's declared task IDs. | [`down` and teardown](../../../src/run.rs); [explicit-lifecycle acceptance](../../../tests/nomad_survival.rs) |
24+
| HOST-R06 | The deterministic loop surfaces bounded crash-loop failure to the declared supervisor; the root-agent responsibility itself is owned by root R04. | [`surface_crash_loop`](../../../src/run.rs); [crash-loop acceptance](../../../tests/run.rs); [R04](../requirements.md#L43-L46) |
25+
| HOST-R07 | Agent/task liveness and resident supervisor ownership are separate observations. A replacement adopts matching work visible in its selected current state. Sidecar-only work does not make an otherwise unrunnable agent live. No global catalog-liveness classifier is implemented. | [replacement adoption](../../../tests/nomad_survival.rs); [supervisor reporting](../../../src/main.rs); [DING-only boundary](../../../tests/reconcile.rs) |
2626
| HOST-R08 | Stable catalog-root and PTY-root path lifetime is an accepted constraint. The guided coordinated relocation operation is not implemented. | [migration contract](https://github.com/compoundingtech/st2/issues/85) |
2727

2828
## Catalog liveness and path lifetime
@@ -52,29 +52,29 @@ paths and never scan arbitrary old roots.
5252

5353
## Partition boundary
5454

55-
The root [R18–R19](../requirements.md) contract requires a complete,
56-
validated, locally applied catalog to remain authoritative through transport
57-
loss. The current reconciler instead discovers the live catalog filesystem on
58-
each pass ([source](../../../src/run.rs#L737-L758)), while validation is a
59-
separate read-only command
60-
([source](../../../src/validate.rs#L1-L24)). st2 does not yet stage a candidate
61-
catalog, assign or compare catalog versions, atomically activate a validated
62-
snapshot, or retain an activation receipt. That durable last-known-good
63-
activation path is unimplemented.
55+
The root [R18/R26](../requirements.md) contract requires a complete, validated,
56+
locally applied catalog to remain authoritative through transport loss.
57+
[`st2 catalog snapshot` and `catalog apply`](../../../src/catalog_transaction.rs)
58+
implement the local activation boundary. Snapshot emits the exact declaration
59+
root digest. Apply captures and validates a complete candidate, takes the
60+
exclusive catalog lock, rechecks the expected predecessor digest, durably stages
61+
the bytes, publishes an incomplete marker, and atomically applies the
62+
projection. A crash resumes from that marker and content-addressed stage without
63+
reopening the original candidate. While the marker exists, declaration readers
64+
and lifecycle actions fail closed. The executable acceptance is in
65+
[`tests/catalog_apply.rs`](../../../tests/catalog_apply.rs).
6466

6567
Peer reachability is not currently a reconciler input. This is consistent with
6668
peer absence being neutral, but the declaration shape for an explicit local
6769
operation that depends on a peer or source is not yet specified.
6870

71+
The predecessor and target digests provide exact compare-and-swap authority;
72+
they do not define a fleet-wide ordering that proves one independently
73+
published catalog is newer than another.
74+
6975
## Open questions
7076

71-
- What identifies a complete candidate catalog and orders it after the locally
72-
applied version?
73-
- What atomic activation and durable receipt let a replacement control plane
74-
recover the last-known-good version after interruption?
77+
- What version or ordering contract proves that one complete candidate is newer
78+
than the locally applied digest across independently converging hosts?
7579
- How does a declaration express a local operation's dependency on a peer or
7680
source without turning peer presence into general health?
77-
- [`HostLock` acquisition](../../../src/host_lock.rs#L26-L48) is currently
78-
check-then-write rather than an atomic create. What ownership primitive
79-
closes simultaneous first-start races while retaining host-scoped
80-
stale-owner recovery?

docs/vrs/spec.md

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -437,26 +437,27 @@ validate ──► materialize ──► host-local st2 scheduler/reconciler
437437
- **R18:** Transport loss does not invalidate a host's locally applied desired
438438
state. Missing, partial, or invalid incoming catalog state cannot replace the
439439
last complete validated version or cause teardown.
440-
- **R19:** Hosts may temporarily apply different catalog versions and converge
440+
- **R26:** Hosts may temporarily apply different catalog versions and converge
441441
independently. Peer or source absence is neutral unless a declared local
442442
operation explicitly depends on it; reconnect is not itself evidence that a
443443
candidate catalog is complete, valid, or newer.
444444

445445
Current host isolation is source-backed: reconciliation filters declarations
446-
to one selected host
447-
([source](../../src/reconcile.rs#L106-L191)), a host-scoped lock detects an
448-
existing resident writer for the same local subject
449-
([source](../../src/host_lock.rs#L1-L67)), and running tasks survive control
450-
plane loss and adoption
451-
([evidence](../../tests/nomad_survival.rs#L592-L701)).
452-
453-
The durable catalog-activation half of R18–R19 is not implemented. Each pass
454-
currently discovers the live catalog directory directly
455-
([source](../../src/run.rs#L737-L758)); `st2 validate` is separate and
456-
read-only. There is no staged candidate boundary, catalog version ordering,
457-
atomic validated activation, or durable last-known-good receipt. The exact
458-
candidate-completeness, version, and activation-recovery contracts remain open
459-
design work.
446+
to one selected host ([source](../../src/reconcile.rs)), retained
447+
`HostOwnership` holds the kernel lock for one canonical catalog/host subject
448+
([source](../../src/host_lock.rs)), and running tasks survive control-plane loss
449+
and adoption ([evidence](../../tests/nomad_survival.rs)).
450+
451+
The local activation half of R18/R26 is implemented by
452+
[`catalog snapshot` and `catalog apply`](../../src/catalog_transaction.rs).
453+
Snapshot binds a complete declaration root. Apply validates a retained
454+
candidate, rechecks its expected predecessor digest under the exclusive lock,
455+
durably stages it, publishes a recovery marker, and atomically applies it.
456+
Interrupted apply resumes from the marker and content-addressed stage while
457+
other declaration reads and lifecycle actions remain fenced. CAS identifies an
458+
exact predecessor and target, but it does not define fleet-wide version
459+
ordering. The ordering contract and the shape of an explicit local dependency
460+
on a peer or source remain open; peer reachability is not a reconciler input.
460461

461462
## Message lifecycle
462463

0 commit comments

Comments
 (0)