Skip to content

FE-674: Open downstream-review rows on hard-impact edit#115

Open
kostandinang wants to merge 6 commits into
ka/fe-657-direct-editsfrom
ka/fe-674-cascade-producer
Open

FE-674: Open downstream-review rows on hard-impact edit#115
kostandinang wants to merge 6 commits into
ka/fe-657-direct-editsfrom
ka/fe-674-cascade-producer

Conversation

@kostandinang
Copy link
Copy Markdown
Contributor

@kostandinang kostandinang commented May 8, 2026

What

When the user applies a hard-impact edit, the server now writes one pending review row per downstream item that depends on the edited source.

Stacked on #105. First of three V3.0 PRs.

Why

Before this, hard-impact apply was a no-op: the server returned { updated: false } and the client showed a "coming in V3" banner. Nothing actually changed in the spec or the queue.

How

  • Server applies the source edit + opens needs in one transaction; returns previous content so undo works.
  • New cascade-producer.ts maps relation → need kind: depends_on / constrains / verifies → needs_confirmation; derived_from / refines → supersedes.
  • Re-applying the same edit is idempotent (no duplicate needs).
  • Client banner copy updated to "Hard impact — cascade pending review". Entity queries invalidate so the structured list reflects the new source content.

Test plan

@cursor
Copy link
Copy Markdown

cursor Bot commented May 8, 2026

PR Summary

Medium Risk
Changes hard-impact edit semantics to perform DB writes (content mutation + reconciliation queue inserts) inside a transaction, which could affect data integrity and client undo behavior if the cascade logic is wrong.

Overview
Hard-impact knowledge-item edits now apply the content change and open reconciliation_need rows for each downstream typed edge, returning previousContent/previousRationale plus openedNeedIds (idempotent re-apply via openReconciliationNeedIfAbsent).

Adds a V3.0 relation→need-kind mapping (relationToKind), a getDownstreamEdges query to preserve edge relations, and request support/validation for optional causedByTurnId provenance. Client edit APIs/applier are updated to treat impact === 'hard' as the deferred-banner trigger (while still invalidating entity queries), and tests are expanded to cover cascade opening, kind mapping, idempotence, provenance, and updated undo expectations.

Reviewed by Cursor Bugbot for commit e77c0a6. Bugbot is set up for automated code reviews on this repo. Configure here.

@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented May 8, 2026

🤖 Augment PR Summary

Summary: This PR activates the V3.0 “Path 1” hard-impact cascade producer by applying hard-impact edits server-side and opening reconciliation_need rows for downstream dependency edges.

Changes:

  • Server: added cascade-producer.ts with a table-driven relationToKind mapping and a dedicated unit test.
  • Server DB: introduced getDownstreamEdges (preserves edge relation) and openReconciliationNeedIfAbsent to make need-opening idempotent.
  • Server route: handlePatchKnowledgeItem now applies hard-impact edits, enumerates downstream edges, opens one need per (downstream, mapped kind), and returns openedNeedIds + previous values.
  • Server route: threads optional causedByTurnId provenance into opened needs.
  • Client API types: hard-impact responses now report updated: true and include previousContent/previousRationale/openedNeedIds.
  • Client applier: deferred banner trigger moves to impact === 'hard', updates banner copy, and invalidates entity queries after hard applies.
  • Tests: expanded edit-route coverage for kind mapping, idempotent re-apply, provenance, and previous-value returns; updated applier tests accordingly.

Technical Notes: The hard-impact apply contract is now “apply + enqueue needs”; UI surface for Pending review remains deferred to the next card while keeping the banner as the temporary signal.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review completed. 2 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/server/edit-route.ts
Comment thread src/server/edit-route.ts
Comment thread src/client/lib/edit-applier.ts Outdated
@kostandinang kostandinang changed the base branch from ka/fe-657-direct-edits to graphite-base/115 May 11, 2026 09:02
@kostandinang kostandinang force-pushed the ka/fe-674-cascade-producer branch from fd82cc7 to 9755778 Compare May 11, 2026 09:19
@kostandinang kostandinang changed the base branch from graphite-base/115 to ka/fe-657-direct-edits May 11, 2026 09:19
Hard-impact propose_edit apply now mutates the source content/rationale and
opens one reconciliation_need row per typed dependency edge incident on the
changed item, returning openedNeedIds in the apply response. Replaces the V2
deferred no-op behavior with the substrate Path 1 producer per
docs/design/MULTI_CHAT.md §5.1 and SPEC.md D139 / I112.

Server:
- New src/server/cascade-producer.ts — table-driven relationToKind mapping
  (depends_on / constrains / verifies → needs_confirmation; derived_from /
  refines → supersedes). Reviewable in isolation via cascade-producer.test.ts.
- New db.getDownstreamEdges — like getDownstreamItems but preserves the edge
  relation alongside each downstream item id.
- New db.openReconciliationNeedIfAbsent — wraps openReconciliationNeed with a
  pre-check on the (source, target, kind) partial unique index so re-applying
  the same hard-impact edit reports openedNeedIds: [] rather than throwing.
- handlePatchKnowledgeItem hard branch: applies source change, enumerates
  downstream edges, opens one need per (downstream, relation), returns
  { impact: 'hard', updated: true, previousContent, previousRationale,
    openedNeedIds, affectedItems }.
- Optional causedByTurnId in the request payload threads side-chat turn
  provenance into the new reconciliation_need rows.

Client:
- edit-api EditItemResponse: hard variant flips updated: false → true and
  carries previousContent / previousRationale / openedNeedIds.
- edit-applier deferred-banner trigger moves from !response.updated to
  response.impact === 'hard'. The banner stays as the user-visible signal
  until card 2 ships the Pending review surface in patch-list-overlay.

Tests:
- 5 new cases in edit-route.test.ts cover the new contract (apply, kind
  mapping, idempotent re-apply, caused_by_turn_id provenance, prior values
  on hard apply).
- cascade-producer.test.ts asserts every relation enum value table-driven.
- edit-applier.test.ts updated for the new deferred trigger and undo error
  message.

Verified: npm run verify (1047 tests).
Wrap the source-content mutation and the per-edge reconciliation_need
inserts in a single db.transaction so a partial failure (FK violation,
write error) can't leave the knowledge item updated without its cascade
needs. Without the transaction, the source would mutate, the first
insert could fail, and the client would never see those rows in pending
review.

Also validate causedByTurnId before any write: the foreign key with
foreign_keys = ON would otherwise throw at insert time on a stale or
wrong-spec turn id and surface as a 500. We now look the turn up and
require it to belong to this specificationId, returning 400 on
mismatch. (A wrong-spec turn is just as broken as a missing one — it
would attribute the cascade to an unrelated chat.)
The V3.0 server contract always applies the content change and, for
hard-impact edits, also opens reconciliation_need rows. When an undo's
restore request gets reclassified as hard, the server has already
restored previousContent and opened cascade needs — but the client was
throwing 'Edit undo blocked' and skipping invalidateEntityQueriesAfterEdit,
leaving the page-visible item stale and silently swallowing the new
cascade needs (the undo failure surfaces from patch-list-host as a
silent return-false).

Drop the throw and invalidate unconditionally so the UI matches server
state. Newly-opened cascade needs land naturally in card 2's Pending
review surface.
@kostandinang kostandinang force-pushed the ka/fe-674-cascade-producer branch from 9755778 to 9944024 Compare May 11, 2026 09:47
@kostandinang kostandinang force-pushed the ka/fe-657-direct-edits branch from c71b58a to 4ae654f Compare May 11, 2026 09:47
The undo path no longer throws when the restore edit comes back as
hard-impact; the server always applies and the applier invalidates
unconditionally.
@kostandinang kostandinang requested a review from lunelson May 11, 2026 09:54
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 1337891. Configure here.

Comment thread src/client/lib/edit-applier.ts
@kostandinang kostandinang changed the title FE-674: Open reconciliation_need rows on hard-impact apply (V3.0 card 1) FE-674: Open downstream-review rows on hard-impact edit May 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant