Skip to content

Commit 86453e5

Browse files
authored
Merge pull request #36 from vitry/fix/zcode-conversation-progress-0163
fix: support ZCode 0.16.3 conversation progress
2 parents e603b6f + 807cdc9 commit 86453e5

15 files changed

Lines changed: 952 additions & 213 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes follow Semantic Versioning.
44

55
## Unreleased
66

7+
- Fixed ZCode CLI 0.16.3 conversation progress compatibility: bounded initial, online-overflow, and recovery snapshots now establish silent sequence baselines; all five production delta operations are structurally accepted; and only validated tool/turn rows can emit bounded public progress. Online deltas require the exact exclusive baseline, and any overlap or ordinal/sequence gap fences further online progress until an authoritative snapshot or a recovery delta covering the trusted sequence resets it. Online frame state and watermarks now commit transactionally after asynchronous descriptions settle, so ignored frames cannot leak later tool summaries. Structurally accepted zero-event frames remain diagnostic-only and no longer suppress or stop snapshot fallback; only a frame with bounded public semantic progress establishes online health. Snapshot history, state patches, row text deltas, and removed-row content are never rendered, while fragments remain unsupported and fall back through the existing observational progress path.
78
- Fixed terminal ZCode failure handling so failures are no longer replaced by `ZCODE_RESULT_MISSING`: failed and cancelled jobs remain queryable through `$zcode:result`, stored errors appear in result and status output, and natural-language result references without an ID select the latest finished owned job. This does not repair upstream provider SSE or network failures.
89
- Added an instance-bound Rescue launcher rendered by the owned parent hook, so Root and child reuse one exact plugin-instance command instead of constructing companion paths. Installed and source-development namespaces remain intentionally isolated; `source-session-unproven` and unsafe-launcher failures are terminal with no setup retry or cross-instance redirect. Existing data locations remain unchanged, while the managed Role digest requires the normal owned upgrade through `$zcode:setup`.
910
- Added exact stopped-child Rescue continuation: Root privately prepares the next bound turn and follows up the same stopped child, which reuses `invoke-prepared rescue` with no second `SubagentStart`; fresh work still creates a new child.
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# Conversation Progress Incident Completion Plan
2+
3+
**Goal:** Complete PR #36 so it fixes both the ZCode 0.16.3 conversation-frame incompatibility and the incident-specific fallback/state-integrity failures.
4+
5+
**Constraints:** Preserve bounded parsing, sequence/recovery fencing, source/marketplace byte identity, and existing lifecycle behavior. A structurally accepted online frame is not semantically healthy until it emits at least one public progress event.
6+
7+
## Task 1: Make online frame application transactional
8+
9+
**Files:**
10+
- Modify: `scripts/lib/conversation-progress.mjs`
11+
- Modify: `marketplace/plugins/zcode/scripts/lib/conversation-progress.mjs`
12+
- Modify: `tests/conversation-progress.test.mjs`
13+
14+
1. Add a regression test where an online frame mutates a tool state, then waits on an async path description while a gap/overflow is marked. Recover and complete the same tool; assert data from the ignored frame is never emitted and its watermark was not committed.
15+
2. Run the focused test and confirm it fails for the state leak.
16+
3. Stage online-frame row/tool state, public events, terminal state, and watermarks locally. Commit them only after all async descriptions finish and the frame is still admissible.
17+
4. Copy the implementation to the marketplace mirror and verify byte identity.
18+
5. Run `node --test tests/conversation-progress.test.mjs`.
19+
20+
## Task 2: Keep fallback active until semantic online progress exists
21+
22+
**Files:**
23+
- Modify: `scripts/lib/progress.mjs`
24+
- Modify: `marketplace/plugins/zcode/scripts/lib/progress.mjs`
25+
- Modify: `tests/progress.test.mjs`
26+
- Modify: `tests/integration/companion.test.mjs`
27+
28+
1. Reverse the zero-event expectations: structurally accepted empty online frames still increment diagnostics but neither clean up an active snapshot fallback nor block compatibility-boundary activation.
29+
2. Add an incident-shaped regression: repeated sequence/row-shape rejects activate fallback; interleaved accepted empty online frames preserve heartbeat snapshot reads; the first nonempty online event exits fallback exactly once; later empty frames do not regress state.
30+
3. Run focused tests and confirm they fail before implementation.
31+
4. Track semantic online health separately from structural acceptance and use it for fallback activation/cleanup.
32+
5. Copy the implementation to the marketplace mirror and verify byte identity.
33+
6. Run `node --test tests/progress.test.mjs tests/integration/companion.test.mjs`.
34+
35+
## Task 3: Align the design contract and changelog
36+
37+
**Files:**
38+
- Modify: `docs/superpowers/specs/2026-08-15-rescue-forwarder-progress-compatibility-design.md`
39+
- Modify: `CHANGELOG.md`
40+
- Modify marketplace copies only where plugin contract tests require them.
41+
42+
1. State that ignored online frames commit neither state nor watermarks.
43+
2. Distinguish structural acceptance from semantic health: only a nonempty bounded public event exits or permanently suppresses fallback.
44+
3. Document the incident regression and user-visible consequence.
45+
46+
## Task 4: Independent review and verification
47+
48+
1. Run independent spec and standards reviews against `origin/main...HEAD`; fix all blockers and repeat reviews.
49+
2. Run focused progress suites, `npm run check`, and `git diff --check origin/main...HEAD`.
50+
3. Push the existing PR branch, then watch all six GitHub Actions matrix checks to success. Diagnose, fix, and rerun if any check fails.

docs/superpowers/specs/2026-08-09-rescue-native-subagent-progress-design.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -505,11 +505,13 @@ a fixed follow-up. Wait timeout/interruption tests prove no duplicate spawn.
505505

506506
### Progress
507507

508-
Fixture tests feed initial and online conversation frames for Bash, Edit, Write,
509-
Read, Grep, Glob, WebSearch, unknown tools, success, failure, and terminal turn
510-
states. They cover 96-character shortening, multibyte bounds, controls, huge
511-
strings, duplicates, reordering, cross-session frames, path traversal, post-
512-
terminal events, and subscription fallback.
508+
Fixture tests feed initial, online-overflow, and recovery snapshots plus all five
509+
ZCode 0.16.3 delta operations for Bash, Edit, Write, Read, Grep, Glob, WebSearch,
510+
unknown tools, success, failure, and terminal turn states. They cover exclusive
511+
sequence baselines, 500-operation and one-MiB bounds, 64-event fanout,
512+
96-character shortening, multibyte bounds, controls, huge strings, duplicates,
513+
reordering, cross-session frames, path traversal, post-terminal events, and
514+
subscription fallback.
513515

514516
Adversarial tests prove that reasoning, assistant drafts, tool output, file
515517
contents, environment data, capability-like strings outside approved command or

docs/superpowers/specs/2026-08-15-rescue-forwarder-progress-compatibility-design.md

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,27 +141,77 @@ The conversation describer changes from silent `null` rejection to an internal
141141
fixed rejection result. Valid-frame behavior and all existing public bounds stay
142142
unchanged.
143143

144+
### ZCode 0.16.3 complete-frame compatibility
145+
146+
The structural boundary accepts wire-version-3 complete frames with the exact
147+
outer topic and subscription binding. A bounded protocol-version-1 snapshot may
148+
arrive as an initial frame, an online overflow reset, or a recovery frame. Its
149+
session identity, log epoch, sequence, revision, and bounded 60-row window are
150+
validated, but its historical rows are never replayed or interpreted. The
151+
snapshot silently replaces the observational sequence and lifecycle baseline.
152+
153+
Delta payloads follow ZCode 0.16.3's exclusive sequence baseline and accept at
154+
most 500 operations within the one-MiB complete-frame bound. The supported
155+
operations are `row.appended`, `row.upserted`, `row.removed`, `row.delta`, and
156+
`state.updated`. Only exact, allowlisted `toolCall` and `turnHeader` rows from
157+
append/upsert operations may produce public events. Removal updates local
158+
deduplication state silently; row text appends and state patches are bounded,
159+
validated, and ignored. No snapshot, patch, text append, unknown row, assistant
160+
draft, tool output, or historical terminal row is rendered. Public event fanout
161+
remains capped at 64 per frame and tracked lifecycle state at 256 rows.
162+
163+
After any accepted baseline, a normal online delta must have the next logical
164+
ordinal and `fromSeq` exactly equal to the last accepted `toSeq`. Overlapping
165+
replays and ordinal or sequence gaps are rejected before applying operations;
166+
the rejected frame does not advance either trusted watermark. Further online
167+
deltas remain fenced until a valid recovery delivery or a bounded authoritative
168+
snapshot establishes a new baseline. An online overflow snapshot may reset from
169+
sequence zero while fenced.
170+
171+
Online delta application is transactional across asynchronous path
172+
normalization. Tool and row lifecycle state, public events, terminal intent,
173+
and both trusted watermarks remain staged until every description has settled
174+
and the frame is still admissible. A gap, overflow, or terminal latch observed
175+
while a description is pending discards the entire staged frame, so a later
176+
recovery or terminal update cannot expose content from an ignored frame.
177+
178+
A delta recovery is valid only when its range covers the last trusted sequence:
179+
`fromSeq` is no greater than the trusted `toSeq`, and its new `toSeq` does not
180+
move backward. A recovery range that begins after the trusted sequence leaves a
181+
hole, is rejected without advancing either watermark, and keeps recovery
182+
fencing active. An equal-sequence empty recovery remains a valid no-op baseline.
183+
184+
Fragment frames remain unsupported. Their rejection is observational and uses
185+
the existing bounded session-snapshot fallback; it cannot affect authoritative
186+
completion, cancellation, or result handling.
187+
144188
### Compatibility state
145189

146190
Each foreground Rescue progress reporter has one of four observational states:
147191

148192
- `probing`: subscription may still produce a usable online frame;
149-
- `online`: at least one usable online frame has been accepted;
193+
- `online`: at least one accepted online frame emitted a bounded public semantic
194+
event;
150195
- `snapshot-fallback`: no usable semantic frame was available by the first
151196
heartbeat boundary, or a bounded rejected-frame threshold was reached; or
152197
- `lifecycle-only`: both semantic frames and snapshot fallback are unavailable.
153198

154199
Initial snapshots do not switch the reporter to `online` because historical
155-
activity must not suppress fallback for the current turn. Once an online frame
156-
is accepted, snapshot polling stops. State changes do not affect the
157-
authoritative completion wait.
200+
activity must not suppress fallback for the current turn. Structural acceptance
201+
still increments `acceptedOnline` for diagnostics, but an accepted frame with no
202+
public events is not evidence of usable progress: it neither exits nor blocks
203+
snapshot fallback, and it leaves `probing`, `snapshot-fallback`, or
204+
`lifecycle-only` unchanged. The first accepted online frame with at least one
205+
bounded public event switches the reporter to `online` and stops snapshot
206+
polling exactly once; later empty frames do not regress that state. State changes
207+
do not affect the authoritative completion wait.
158208

159209
### Bounded session snapshot fallback
160210

161-
At the first heartbeat boundary with no accepted online frame, the reporter
162-
reads the same session through the existing authenticated client. While fallback
163-
is active, it repeats at most once per heartbeat interval. Only one read may be
164-
in flight, and a read that has not settled is not duplicated.
211+
At the first heartbeat boundary with no semantically usable online frame, the
212+
reporter reads the same session through the existing authenticated client.
213+
While fallback is active, it repeats at most once per heartbeat interval. Only
214+
one read may be in flight, and a read that has not settled is not duplicated.
165215

166216
Snapshot processing uses the existing schema-validated session response and the
167217
accepted current-turn boundary. It ignores messages that existed before send

marketplace/plugins/zcode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ All notable changes follow Semantic Versioning.
44

55
## Unreleased
66

7+
- Fixed ZCode CLI 0.16.3 conversation progress compatibility: bounded initial, online-overflow, and recovery snapshots now establish silent sequence baselines; all five production delta operations are structurally accepted; and only validated tool/turn rows can emit bounded public progress. Online deltas require the exact exclusive baseline, and any overlap or ordinal/sequence gap fences further online progress until an authoritative snapshot or a recovery delta covering the trusted sequence resets it. Online frame state and watermarks now commit transactionally after asynchronous descriptions settle, so ignored frames cannot leak later tool summaries. Structurally accepted zero-event frames remain diagnostic-only and no longer suppress or stop snapshot fallback; only a frame with bounded public semantic progress establishes online health. Snapshot history, state patches, row text deltas, and removed-row content are never rendered, while fragments remain unsupported and fall back through the existing observational progress path.
78
- Fixed terminal ZCode failure handling so failures are no longer replaced by `ZCODE_RESULT_MISSING`: failed and cancelled jobs remain queryable through `$zcode:result`, stored errors appear in result and status output, and natural-language result references without an ID select the latest finished owned job. This does not repair upstream provider SSE or network failures.
89
- Added an instance-bound Rescue launcher rendered by the owned parent hook, so Root and child reuse one exact plugin-instance command instead of constructing companion paths. Installed and source-development namespaces remain intentionally isolated; `source-session-unproven` and unsafe-launcher failures are terminal with no setup retry or cross-instance redirect. Existing data locations remain unchanged, while the managed Role digest requires the normal owned upgrade through `$zcode:setup`.
910
- Added exact stopped-child Rescue continuation: Root privately prepares the next bound turn and follows up the same stopped child, which reuses `invoke-prepared rescue` with no second `SubagentStart`; fresh work still creates a new child.

0 commit comments

Comments
 (0)