FE-656: Add patch / event-stream data model design for side-chat V4#82
Closed
kostandinang wants to merge 5 commits into
Closed
FE-656: Add patch / event-stream data model design for side-chat V4#82kostandinang wants to merge 5 commits into
kostandinang wants to merge 5 commits into
Conversation
FE-656 Side chat
Side chat — graph-launched chat with patch-list stagingTL;DRProblem / Motivation
Acceptance criteria
ConceptPopover-to-panel chat anchored to items in the structured spec view. Two entry modes (per-row The side-chat is the unified user-driven mutation surface. It subsumes three previously-separate horizon items: D128 graph-launched refinement, trigger-popover composer, revisit / edit mode + cascade preview. Phasing
Acceptance-criteria mapping
Design doc & PR
|
Concretizes A71/A72/A73 from memory/SPEC.md into a proposed data structure (branches, events, patches, item_versions) that supports branched turns, staged patches with batched apply, and architect-loop HITL review through the same surface as the side-chat. V1/V2/V3 still ship on the current store-of-stores; this is the substrate V4 swaps onto.
The §3.5 ER diagram now carries the key enums on each entity (branch.origin_kind/status, event.kind, patch.op/kind/impact_tier), so the diagram is self-contained for the substrate vocabulary. The new §3.6 maps today's V1-V3 terminology (turn, observer capture, side-chat apply, spec state) onto the V4 substrate, anchors where 'turn' fits as one event kind among seven, and clarifies how D80 and D113 relate to the new layering.
- Fold §1 ("Why this exists") into a one-line lead on §1 (decisions
snapshot); the TL;DR already covers the why.
- Compress §2.6's four-paragraph narrative after the vocabulary
diagram into one paragraph naming the shift.
- Tighten §3.3 supersession from a procedural sketch + commentary
to two short paragraphs.
- Compress §4.3's five-alternative comparison (M1/M2/M3a/M3b/M3c)
into one paragraph.
- Merge §6.1, §6.2, §6.3 (main branch / canonical view) into a
single short §5 — most of the prior table's rows were "unchanged"
noise.
- Trim §6.5 (revisit) — structurally identical to §6.4, just a UI tag.
- Trim §9.2 from a six-decision recap to one line.
- Trim open questions from 7 to the 4 most consequential.
- Delete §12 (recommendation summary) — restated TL;DR + decisions.
Net: 605 → 518 lines (~14%). Renumbered sections sequentially after
removing §1 and §12. No content claims changed.
be73f13 to
ab049f5
Compare
Today's schema is one `knowledge_item` table discriminated by `kind`, not "per-kind tables" or a "store-of-stores". Updates the TL;DR, §1, and §2.6 to describe the real schema. Substrate proposal unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Preamble status, "When does this ship?", and D113 line now reference the real schema (`knowledge_item`) instead of "stores". Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
10 tasks
Contributor
Author
|
As we discussed with @lunelson and concluded on a simpler model, closing this PR and following subsequently with the new design. |
graphite-app Bot
pushed a commit
that referenced
this pull request
May 7, 2026
https://www.loom.com/share/b0d96bc2f0a849d8b57b043bb648a9aa ## Stack Context This PR is the side-chat **V1.2 vertical slice** under FE-656, stacked on **PR #81** (V1.1 — Class 1 Explore: chat anchored to spec items). V1.1 proved the chat seam; **V1.2 proves the durable mutation seam** — the side-chat can now produce real, persistent changes to a spec. PR #88 is sized as one coherent slice. **V1.2-D** (top-bar canonical Apply/Undo), **V1.2-E** (floating selection menu), and **V1.2-F** (multi-item pinning) are deferred to follow-up PRs per `memory/PLAN.md`. ## What End-to-end Annotate flow: the user opens the side-chat on a knowledge item, types a note, hits Save, and it persists to the database. Existing notes for the pinned item render above the chat log as a collapsible `Notes` section. The slice lands as three cards plus follow-on UX work: - **A** — Annotation server seam: new `annotation` table + REST endpoints. - **B** — `PatchListProvider` client module: React provider + hooks for staging and applying patches. - **C** — End-to-end wiring: side-chat composer talks to the patch list and the server. - **Auto-apply + UX coherence** — user-typed annotations save on submit (no extra Apply click); three clear states for in-flight / saved / failed. - **C2 — Show existing annotations** — collapsible `Notes` section above the chat log. ## Why V1.1 vertically proved the chat seam end-to-end (graph → side-chat → SSE → streaming reply). Without V1.2, the side-chat is read-only — Class 4 Annotate, V2 Edit / Drill-down / Propose-edge, and V4 architect-loop emissions all need somewhere to write. V1.2 establishes that surface. Two design choices worth attention before merge: ### D132 — Patch-list module shape `/ln-design` explored four shapes in parallel (minimal-API, plug-in registry, event-log-public, react-context-native). The synthesis takes the React-native public surface (mirrors `SideChatHost` exactly) but uses an event-log internal primitive. Rationale: - **Idiomatic for this codebase** — Zero contributor-onboarding cost. - **A71-ready internally** — When the future `appendPatch(spec, patch[])` server primitive lands, migration is "swap the reducer," not "rewrite the public API." - **Closed discriminated union** — V2 patch kinds force a typecheck failure at the provider mount until their applier is supplied. Silent drift impossible. ### D131 — User-driven annotations auto-apply Originally framed as "uniform staging required for all patch kinds." User feedback during this PR pushed back: re-reviewing what you just typed adds nothing for annotations. Distinction is now explicit in D131: - **Annotate** (user-driven, low-stakes, just-typed) → auto-apply on Save. The patch list still records the patch, surfaces it transiently, and provides Undo on the resulting batch. - **Edit / Drill-down / Propose-edge** (V2, mutates durable content) → keep the explicit Apply step. Review-before-commit matters when the operation has cascading effects. - **Architect-loop emissions** (V4, system-driven) → keep the explicit Apply step. The user wasn't in the moment of authoring; review is the whole point. The patch-list module supports both paths — kind-specific behavior is wired in `SideChatHost` via the auto-apply `useEffect`, not in the module itself. ## Spec / plan deltas `memory/SPEC.md`: - **D132** — patch-list module shape (React-context-native public, event-log-shaped internally) - **D133** — annotation as a new durable entity, item-anchored in V1, span-anchor-ready in schema - **D131** revised — adds the user-driven vs review-required distinction; supersedes the "uniform staging required" framing `memory/PLAN.md`: - Active 1 reflects V1.2 vertical slice landed; V1.2-D / E / F still owed. - Earlier "comment-store extension" framing corrected — D133 supersedes it. ## Stacked on - **PR #81** (`ka/fe-656-side-chat`, V1.1 Explore) — must merge first. - **PR #82** (`ka/fe-656-side-chat_v4`, V4 patch / event-stream data model) — sibling on the same parent, independent of V1.2. ## Linear [FE-656](https://linear.app/hashintel/issue/FE-656) — same issue as V1.1 (one Linear issue per frontier item per `CLAUDE.md`). ## Test plan **Automated** — `npm run verify` passes (793/793 tests, includes the 9 V1.1-polish tests merged in). **Manual walkthrough** (in browser, dev server running): - [ ] **Happy path.** Open a spec → graph view → click `💬` on any item row → click `Annotate` → type Summary + Body → click `Save`. Expect: brief `Saving annotation…`, then `✓ Annotation saved` with Undo. New note appears in the `Notes (1)` section above the chat log. - [ ] **Persistence.** Reload the page. Re-open chat on the same item. Note still there. - [ ] **Multiple annotations.** Save a second note on the same item. `Notes (2)` lists both, each independently expandable. - [ ] **Cross-item isolation.** Save a note on item A, switch chat to item B. B's panel does not show A's notes. - [ ] **Undo.** Save a note → click Undo. Notes section refetches; the just-undone note is gone. - [ ] **Composer validation.** `Save` disabled until both Summary and Body are non-empty (whitespace-only doesn't count). - [ ] **Cancel.** `Esc` or `Cancel` button in composer returns to chat without saving. - [ ] **Streaming exclusivity.** While a chat reply is streaming, the `Annotate` button is disabled. - [ ] **Notes collapse.** Click the `Notes (N) ›` chevron to collapse the entire section. Click individual rows to expand bodies. - [ ] **Failure path** *(stop dev server mid-save).* Stuck-staged panel appears with `Retry` and `× Discard`. Restart server → `Retry` succeeds. **Server sanity:** ```bash curl -s http://localhost:3000/api/specifications/<id>/annotations | jq npm run studio # query the `annotation` table directly ``` ## Known transitional gaps (deferred to follow-ups) - **Top-bar canonical surface** (V1.2-D). Until this lands, in-panel Undo is the only undo affordance. Per D131 the in-panel list is "convenience UI, not source of truth"; V1.2-D moves canonical Undo to the persistent app top-bar. - **Span-anchored annotations** (V2/V3). Schema reserves `selection_start` / `selection_end` columns; V1 leaves them NULL. - **Annotation deletion UI** beyond Undo. Broader management lands in a later card. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

TL;DR
Adds the design document for the patch / event-stream data model that side-chat V4 will swap onto. V1 / V2 / V3 stay on the current schema (one
knowledge_itemtable, turn-scoped provenance viaturn_knowledge_item); this design describes the substrate the next phase migrates onto.The model replaces direct in-place mutation of
knowledge_itemwith four concepts:live,speculative,stale,discarded,merged,archived). Stale is recoverable; discarded is permanent.kind ∈ { turn, side-chat-apply, architect-proposal, observer-capture, merge, branch-create, branch-status-change }.event_id IS NULL) or applied.(item_id, branch_id); rebuildable from the log.Branching covers five intent-driven triggers: edit past turn, side-chat apply, drill-down, architect proposal, revisit closed phase. Each has a default lifecycle policy (which sibling stays live, what auto-stales, what supersedes what).
Status
Draft / future-facing. Not a V4 implementation — V4 isn't a frontier item in
memory/PLAN.mdyet. This is a stake-in-the-ground so V1 / V2 / V3 are designed as if the substrate already existed; V4 becomes a substrate swap rather than a redesign.What this changes in
memory/SPEC.mdBranchentities with explicitorigin_kind. Spirit preserved (no chaos), letter updated (forks now exist).References
docs/design/PATCH_EVENT_STREAM_MODEL.md(this PR)docs/design/SIDE_CHAT.md§9 phasing — V4 line names this substrate as the dependencyknowledge_item+turn_knowledge_item)ka/fe-656-side-chat(V1 implementation work) — off main, can advance on its own review timelineReview checklist
origin_kind) are internally consistent with §3 lifecycle policies