Repository navigation
fix: restore ACP chat bindings and preserve pending canvas edits - #182
Merged
cxxxxxn (cxxxxxn) merged 5 commits intoSep 14, 2026
Merged
Conversation
…es and improve block provenance
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Three unresolved moderate findings affect delta performance, binding precedence, and provenance restoration.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Restores durable ACP chat bindings, preserves pending canvas edits during sync, and improves AI note provenance handling.
Changes:
- Restores durable Question-node bindings.
- Prevents lifecycle deltas from overwriting pending local content.
- Preserves provenance baselines across sequential AI edits.
- Adds dependency updates, regression tests, and architecture documentation.
File summaries
| File | Reviewed change |
|---|---|
pnpm-lock.yaml |
Locks the deep-equality dependency. |
packages/shared/src/types/canvas/node.ts |
Updates provenance contracts. |
packages/shared/src/canvas-engine/provenance/noteProvenance.ts |
Preserves and clears AI provenance. Moderate, 2 votes: Preserve the baseline canonical key or compare against full-document definitions to handle reference-style syntax correctly. |
packages/shared/src/canvas-engine/__tests__/noteProvenance.executor.test.ts |
Adds provenance regression coverage. |
docs/architecture/question-node.md |
Documents durable binding replay. |
docs/architecture/note-node.md |
Documents provenance restoration behavior. |
docs/architecture/canvas-realtime-sync.md |
Documents lifecycle delta merging. |
apps/web/src/utils/__tests__/blockProvenance.test.ts |
Tests provenance edge cases. |
apps/web/src/store/conversationOwner.ts |
Adds durable binding resolution. Moderate, 1 vote: Restrict binding precedence to established/fixed conversations so editable threads honor updated selections. |
apps/web/src/store/conversationOwner.test.ts |
Tests binding resolution. |
apps/web/src/store/canvasStore.ts |
Preserves pending content during delta application. Moderate, 1 vote: Construct localNodesById lazily to avoid unnecessary O(n) work on clean canvases. |
apps/web/src/store/canvasStore.agentDeltaConflict.test.ts |
Tests delta conflict behavior. |
apps/web/src/hooks/useAgentStream.ts |
Uses durable bindings for requests. |
apps/web/src/components/Panels/ChatPanel/index.tsx |
Hydrates bindings synchronously. |
apps/web/package.json |
Adds fast-deep-equal. |
Review details
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
apps/web/src/store/canvasStore.ts:1574
localNodesByIdis allocated by scanning every canvas node before thedirty.size === 0fast path is selected, and it is never read for the usual clean-canvas case. Every incoming agent delta batch therefore pays O(number of nodes) work introduced by this change; make the lookup lazy or construct it only whendirty.size > 0.
const preservedPendingNodeIds = new Set<string>();
const localNodesById = new Map(
get().nodes.map((node) => [node.id, node]),
);
apps/web/src/store/conversationOwner.ts:127
- This unconditionally treats any
source.agentBindingas authoritative, butChatPanelstill exposes the selector for selectable Question nodes with no user messages. For a selectable/idle node that already has a binding, choosing another agent only updates the cache; this function keeps returning the old node binding, and the first send routes with it again. Restrict owner precedence to established/fixed conversations (or pass the compose state) so editable threads continue to use their cache binding.
export function resolveConversationAgentBinding(
source: ConversationOwnerSource | undefined,
cachedBinding: AgentBinding,
): AgentBinding {
return source?.agentBinding ?? cachedBinding;
- Files reviewed: 14/15 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
+163
to
+167
| const baselineBlocks = fingerprintMarkdownBlocks( | ||
| existing.baselineMarkdown, | ||
| ); | ||
| // Occurrence suffixes identify duplicate positions, not block content. | ||
| // Only a return to the original normalized block cancels a modification. |
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.
Summary
Validation
Scope
Includes the three existing branch commits plus the review follow-up fixes. No real ACP service/browser end-to-end run was performed.
Related issues
Fixes #141.
Related to #172 and #98: this PR addresses false content-conflict detection for non-content updates, but does not resolve genuine label/content conflicts or the broader parallel-write/version-gap behavior. These issues should remain open.