@@ -48,6 +48,40 @@ falls back to a guessed local rule or stops the supervisor. Watchability of
4848every active binding is projected into ` st2 agents --json ` as part of the
4949declared Resource projection so absence of coverage is observable.
5050
51+ ## Supervisor-chain composition (RESYNC-R09..R10)
52+
53+ ``` text
54+ root goal carrier ───────────────┐
55+ v
56+ root seat <- supervisor - lead seat <- supervisor - worker seat
57+ goal carrier ────────────────> worker watch set
58+ worker goal carrier ────────────────────────────> worker watch set
59+ ```
60+
61+ For each active binding whose registered profile declares ` notify-chain ` , watch
62+ resolution first resolves the binding's own carrier, then validates and walks
63+ the seat's supervisor chain against the pass's complete discovered spec vector.
64+ At every non-retired ancestor it resolves active bindings with the same profile
65+ scheme against that ancestor's own declaration directory. Each inherited
66+ subscription retains the ancestor's binding label qualified by owner bus ID
67+ (` goal@hetz.root ` ), so mutations in two layers cannot share a supersession key.
68+ A retired ancestor contributes no layer, but traversal continues to its
69+ ancestors.
70+
71+ Chain membership comes only from a profile's trusted opt-in flag and exact URI
72+ scheme. Binding labels do not define composition, native local bindings never
73+ gain it implicitly, and profiles without the flag remain agent-local. A
74+ missing, ambiguous, cyclic, cross-host, or otherwise unwalkable supervisor edge
75+ produces a reconcile diagnostic and no invented ancestor subscription. Profile
76+ resolution failures remain contained to the failed carrier.
77+
78+ The live-install API takes both the canonical seat and the complete discovered
79+ spec vector. It resolves the complete own-plus-ancestor set under the
80+ supervisor's current profile registry, sends one targeted watch-set replacement,
81+ and waits for the worker acknowledgement. Reinstalling the same identity and
82+ paths preserves carrier baselines, occurrence sequences, dirty state, and
83+ pending transitions.
84+
5185## Classification
5286
5387Classification is decided before a path enters the watch set:
@@ -79,18 +113,25 @@ meaningful.
79113 same-path replacement, mirroring ` CatalogDeclarationWatcher ` .
80114- The watcher owns no reconcile authority: a resync mutation does not wake a
81115 full-catalog pass. It shares only the observation primitives.
82- - After lifecycle execution, each reconcile pass atomically replaces the watch
116+ - Before lifecycle execution, each pass synchronously upserts the complete
117+ catalog-aware watch set for every successfully compiled canonical seat it
118+ observed alive. A successful canonical launch or restart performs the same
119+ acknowledged upsert at the exact live transition before execution advances
120+ to any later task. Both paths resolve supervisor-chain carriers against the
121+ complete discovered spec vector, never a one-spec view.
122+ - After lifecycle execution, each reconcile pass atomically refreshes the watch
83123 set with agents whose canonical seat was observed alive or successfully
84- launched/restarted in that pass. Desired declarations, dead keep-retained
85- seats, and companion-only launches never become watched. If strict discovery
86- temporarily rejects a declaration whose exact canonical seat remains
87- observed alive, its prior declaration subscription survives with its carrier
88- state and pending transition; it drops as soon as that seat is not live.
89- Existing valid subscriptions are matched by declaration path and binding
90- label. Each refresh takes bus id, canonical seat id, carrier path, label, and
91- class from the current declaration while retaining carrier state, the
92- per-subscription occurrence sequence, any immutable pending transition, and
93- dirty state; only new subscriptions seed silently with sequence zero.
124+ launched/restarted in that pass. This refresh owns removals, malformed
125+ declaration retention, and hot profile replacement. Desired declarations,
126+ dead keep-retained seats, and companion-only launches never become watched.
127+ If strict discovery temporarily rejects a declaration whose exact canonical
128+ seat remains observed alive, its prior declaration subscription survives with
129+ its carrier state and pending transition; it drops as soon as that seat is
130+ not live. Existing valid subscriptions are matched by declaration path and
131+ binding label. Each refresh takes bus id, canonical seat id, carrier path,
132+ label, and class from the current declaration while retaining carrier state,
133+ the per-subscription occurrence sequence, any immutable pending transition,
134+ and dirty state; only new subscriptions seed silently with sequence zero.
94135- A previously blind path is state-diffed both before and after its recovered
95136 parent watch is registered, closing the poll-to-registration gap.
96137- Installation failure degrades to timer-based carrier polling over the watch
@@ -149,3 +190,5 @@ ring.
149190- No remote/non-local carrier watching.
150191- No write attribution beyond static classes (RESYNC-T01).
151192- No catch-up replay of missed changes (RESYNC-T03).
193+ - No implicit supervisor-chain inference for native bindings or profiles that
194+ do not declare ` notify-chain ` .
0 commit comments