chains-primary: stored chains replace typed edges; edges become a derived view
Owner rulings 2026-09-30: reasoning chains are the stored truth; the graph canvas renders a lossy derived image. No migration, no backcompat — old graph data was wiped. - contracts: GraphChain (arg_-minted id, premises, conclusion) replaces typed edges; GraphEdge survives only as the untyped derived arrow; GraphSnapshot carries stored chains; supports edges retired entirely - store: chains.jsonl ledger (edges.jsonl purged at load alongside legacy events.jsonl); readChains/appendChain seam; merge dedupes by (sorted premises, conclusion), re-assertions append under the same arg_ id - core: deriveView mints implication nodes (name ⟹, statement via formatChainLine) plus premise→imp→conclusion arrows; clusters stay proposition-only (birthSessionPartition); chainsForSelection now groups STORED chains (chain rides iff every member selected) — independent arguments for one conclusion never union; chainsToGraph/chainsToEdges die - extraction: extractor submits chains natively (expandFindings deleted); auditor receives propositions only; supports fan-out gone - deletion: full death of a proposition kills every referencing chain; arg_-prefixed node deletes kill that chain; chainsRemoved stats - UI: every arrow renders the ⟹ double shaft; supports toggle + thickness slider and detail-card edge sections deleted (card keeps name + proposition); chain table + practice pipeline read stored chains - tests: 1188 green across the new seams
This commit is contained in:
+10
-10
@@ -68,7 +68,7 @@ import {
|
||||
XIcon,
|
||||
} from "lucide-react";
|
||||
import { chainsForSelection, formatChainLine, fuzzyScore } from "@/src/core";
|
||||
import type { GraphEdge, GraphNode } from "@/src/core";
|
||||
import type { GraphChain, GraphNode } from "@/src/core";
|
||||
import { TopBar } from "@/components/top-bar";
|
||||
import { PracticeDialog } from "@/components/practice-dialog";
|
||||
import { DeleteNodeDialog } from "@/components/delete-node-dialog";
|
||||
@@ -99,7 +99,7 @@ interface ClusterGroup {
|
||||
* via props; the overlay wrapper below owns it. */
|
||||
export function ChainTableBody({
|
||||
nodes,
|
||||
edges,
|
||||
chains: storedChains,
|
||||
sessions,
|
||||
fileSources,
|
||||
query,
|
||||
@@ -118,7 +118,7 @@ export function ChainTableBody({
|
||||
onClose,
|
||||
}: {
|
||||
nodes: GraphNode[];
|
||||
edges: GraphEdge[];
|
||||
chains: GraphChain[];
|
||||
sessions: Record<string, string>;
|
||||
fileSources: Record<string, string>;
|
||||
query: string;
|
||||
@@ -140,7 +140,7 @@ export function ChainTableBody({
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const byId = useMemo(() => new Map(nodes.map((n) => [n.id, n])), [nodes]);
|
||||
const chains = useMemo(() => chainsForSelection(nodes, edges), [nodes, edges]);
|
||||
const chains = useMemo(() => chainsForSelection(nodes, storedChains), [nodes, storedChains]);
|
||||
const searching = query.trim() !== "";
|
||||
|
||||
// The fuzzy filter: a chain is visible when ANY member matches on
|
||||
@@ -223,8 +223,8 @@ export function ChainTableBody({
|
||||
// The derived shape under the floating bar (the agents' ACTUAL input).
|
||||
const derived = useMemo(() => {
|
||||
const selectedNodes = [...selection].map((id) => byId.get(id)).filter((n): n is GraphNode => n !== undefined);
|
||||
return chainsForSelection(selectedNodes, edges);
|
||||
}, [selection, byId, edges]);
|
||||
return chainsForSelection(selectedNodes, storedChains);
|
||||
}, [selection, byId, storedChains]);
|
||||
|
||||
const nameOf = (id: string) => byId.get(id)?.name ?? id;
|
||||
const dateOf = (id: string) => byId.get(id)?.createdAt.slice(0, 10) ?? "";
|
||||
@@ -583,14 +583,14 @@ function RowCheckbox({
|
||||
export function ChainTableOverlay({
|
||||
open,
|
||||
nodes,
|
||||
edges,
|
||||
chains: storedChains,
|
||||
sessions,
|
||||
fileSources,
|
||||
onClose,
|
||||
}: {
|
||||
open: boolean;
|
||||
nodes: GraphNode[];
|
||||
edges: GraphEdge[];
|
||||
chains: GraphChain[];
|
||||
sessions: Record<string, string>;
|
||||
fileSources: Record<string, string>;
|
||||
onClose: () => void;
|
||||
@@ -618,7 +618,7 @@ export function ChainTableOverlay({
|
||||
|
||||
const byId = new Map(nodes.map((n) => [n.id, n]));
|
||||
const selectedNodes = [...selection].map((id) => byId.get(id)).filter((n): n is GraphNode => n !== undefined);
|
||||
const derived = chainsForSelection(selectedNodes, edges);
|
||||
const derived = chainsForSelection(selectedNodes, storedChains);
|
||||
const nodeIds = [...selection].sort();
|
||||
|
||||
const toggleNodes = (ids: string[], next: boolean) =>
|
||||
@@ -645,7 +645,7 @@ export function ChainTableOverlay({
|
||||
>
|
||||
<ChainTableBody
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
chains={storedChains}
|
||||
sessions={sessions}
|
||||
fileSources={fileSources}
|
||||
query={query}
|
||||
|
||||
Reference in New Issue
Block a user