Keep manager responses visible across child lifecycle steers - #2071
Closed
ryanbbrown wants to merge 1 commit into
Closed
Keep manager responses visible across child lifecycle steers#2071ryanbbrown wants to merge 1 commit into
ryanbbrown wants to merge 1 commit into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
A child can send a detailed report while its parent manager turn is active. The parent can then show a complete assistant response before BB accepts the child's normal lifecycle notification as a system auto-steer in the same turn. When the turn completes, that visible response can disappear.
The failure has two connected causes:
Worked forsummary.message_start. If Pi emitted two assistant messages in one steered turn with no tool boundary, both could use one canonical item ID. The later completion could replace the earlier text, and resolved-delta pruning could then remove the only canonical copy of the first response.The first cause affects completed timelines from all providers. The second affects Pi and makes this a high-severity canonical-data-loss bug, not only a display bug. Histories already pruned before this fix are not repaired; a native provider transcript can still contain text that BB's canonical event history no longer has.
Minimal reproduced order:
child-completedas a system auto-steer in that turn.Before this change, the first response became collapsed or was lost from canonical Pi history. It must remain a top-level row with its own item ID.
What changed
child-needs-attention,child-completed,child-failed,child-interrupted, andchild-outcome-batchsystem steers as visible exchange boundaries.message_start. The shared assembler then gives later assistant output a new canonical item ID. Retry and empty-abort boundaries retain their existing safe behavior.HOST_DAEMON_PROTOCOL_VERSIONfrom 143 to 144 because daemon-emitted canonical events can now use separate Pi assistant item IDs.This does not weaken pruning and does not add a compatibility fallback. It is not retroactive: it prevents new loss but cannot reconstruct canonical text that an older daemon already merged and pruned.
How you verified
Tests added for this change fail on the old behavior and pass with the fix.
pnpm exec turbo run build typecheck lint --output-logs=new-only: 88/88 tasks passed afterpnpm install --frozen-lockfilerestored missing managed-worktree dependencies; the lockfile did not change.pnpm exec turbo run test --output-logs=new-only: 68/68 tasks passed. The app result was 402 files, 3,096 passed tests, and 3 skipped tests.PromptBoxInternal.test.tsxtimeout. The full file then passed three forced runs at 101/101 tests each, and the full repository rerun passed.bb-apptarball smoke passed. The tarball smoke ran 12/12 tasks.git diff --checkpassed. Every changed file passes Prettier.pnpm run format:checkstill stops on the pre-existing unquoted-colon parse errors in.github/ISSUE_TEMPLATE/bug.yml:71and.github/ISSUE_TEMPLATE/feature.yml:42; neither file is changed by this PR.Disposable live QA used a separate SQLite data directory and ports 63894-63896. It used production Pi translation and assembly with synthetic Pi 0.84 events, real persistence and pruning, the public timeline route, and the React app. No provider API was called. The exact sequence remained top-level before completion, after completion, after full browser/timeline refetch, after pruning two resolved deltas, and after a full disposable server/app restart. The assistant row IDs remained distinct:
...|turn:qa-pi-t1|parent:root|item:qa-pi-i1...|turn:qa-pi-t1|parent:root|item:qa-pi-i2The accepted unlabeled reconnect control remained folded. Browser page errors were empty. QA did not exercise the process-local two-second notification batch or live WebSocket ingestion because fixture insertion does not publish realtime hub events; automated tests cover the accepted lifecycle event producer shape.
Related work
Related but not duplicate: #1355, #1656, #1657, #1981, #897, #1224, and #1834.