Owner 2026-09-30: the confirm dialog's pre-flight impact read had to go — what full death takes is obvious, the per-open fetch flickered, and richer facts would only confuse as deletion semantics evolve (rewiring is on the table). The screen is now: Delete node? / Delete N nodes?, the names in the mono block, one permanence line, Cancel / Delete. No loading state, no gone state (a 404 mid-run lands in the honest failure line), no sessions join — the joins prop died too. The dead path is deleted end to end: GET /api/graph/nodes/[id], graphNodeImpact (server), nodeDeletionImpact (core) and their tests. WORDING: node/node(s) is THE UI word for graph objects, standardized across every surface's copy (owner, same ruling): the dialog titles, the chain table's counts/search/summary/delete aria-labels, the practice dialog's cluster counts, selection line, and empty-cluster hint. Internal identifiers (selection.propositions) unchanged. Rewritten dialog pins (tests/delete-node-dialog.test.tsx): minimal contract — no facts/loading/fetch copy, singular/plural titles, the cap, 409 dock phrasing, busy states, no 'proposition' left in the dialog.
27 lines
1.4 KiB
TypeScript
27 lines
1.4 KiB
TypeScript
import { deleteGraphNode } from "@/src/server";
|
|
|
|
/**
|
|
* DELETE /api/graph/nodes/[id] — single-node deletion, FULL DEATH (owner
|
|
* ruling 2026-09-23: the user pointing at the node is intent — references
|
|
* from other sessions do not preserve it). The node's every line, every
|
|
* edge touching it, every quiz/observation event naming it, its mapping
|
|
* lines, and its position die in one atomic ledger rewrite
|
|
* (core/graph-deletion.ts deleteNodeTraces); derived data (birth
|
|
* partition, clusters) self-heals on read.
|
|
*
|
|
* Guards (server/graph.ts deleteGraphNode): 409 while ANY extraction run
|
|
* is registered — a mid-flight run holds pre-deletion findings and could
|
|
* re-reference the dying node; the run is never aborted (its spend belongs
|
|
* to another session), the UI retries once the dock drains. No turn/jobs
|
|
* gates: they never write the graph ledgers, and this orchestration is
|
|
* synchronous end to end — nothing interleaves. The response carries what
|
|
* was removed plus the new graphRevision (the refetch signal).
|
|
*/
|
|
export async function DELETE(_req: Request, { params }: { params: Promise<{ id: string }> }) {
|
|
const { id } = await params;
|
|
const outcome = deleteGraphNode(id);
|
|
if (!outcome.ok) {
|
|
return Response.json({ error: outcome.error, code: outcome.code }, { status: outcome.status });
|
|
}
|
|
return Response.json({ stats: outcome.stats, graphRevision: outcome.graphRevision });
|
|
} |