Repository navigation
C23: Graph v2 mutations and validateGraph core - #897
Merged
Merged
Conversation
Add the typed, agent-centred canvas graph model under apps/agent-forge/src/graph/v2: Graph/GraphNode with 15 node kinds, stable node-id helpers (toolNodeName, skillNodeName, childPrefix, baseNodeId, dedupeId, nextItemId, uniqueName) and the connection-rule table plus ordered instance refusals (canConnect). specTypes.ts is the single seam to the SDK spec types; AbortListenerSpec and EvalGateSpec are forward-declared there until their spec sections land. Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
# Conflicts: # apps/agent-forge/src/graph/v2/types.ts
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.
What changed
Pure, immutable graph mutations plus the single validation entry point for the canvas graph v2 (no canvas/Inspector wiring — that is the C24 cutover).
graph/v2/mutations.ts:NewNode,ownerForNewNode(selected agent → selected node's owner → root; root-only kinds alwaysagent, notesnull),addNode(dedupeId(baseNodeId(...))ids;note:n<ts><counter>for notes),removeNode(root returns same reference; inline agents remove their whole owner-chain subtree plus matchingemptySections/unplaced),duplicateNode(root + notes refused,KIND_RULES[kind].duplicateData ?? structuredClone, +40/+40),moveNode,setNodeData,patchNode(merges intodata.item/data.fieldsfor agents /data.stepfor flow /datafor notes;undefineddeletes the key),setCollapsed,connectNodes(canConnectrefusal verbatim, thenKIND_RULES[source.kind].connectFrom ??default re-own). Node ids are never recomputed after creation —nodeIdMaprekeys at save.graph/v2/reown.ts: the re-own effect (reownNode— id-stable,{x:24,y:48}entering a group, absolute position leaving one). Kept in a leaf module sokinds/*.tsconnect effects can share it without an import cycle throughkindRules.graph/v2/kindRules.ts:ConnectResult,KindRules<K>(validate/connectFrom/duplicateData), and theKIND_RULESregistry starting withagent.graph/v2/kinds/agent.ts:agentRules—connectFrom= re-own target to the source agent (C03 addsvalidate, C04duplicateData).graph/v2/validateGraph.ts:validateGraph(graph): Problem[]— aCORE_CHECKStable (one function per row: no main agent, duplicate node id, missing owner, root-only kind on a non-root owner, duplicate mcp/subagent keys per owner, duplicate memory names, non-unique guardrail/permission/hook/trigger/abort item ids across the graph, secondoutputon one agent) plusKIND_RULES[kind].validateper node inorderedNodesorder.specPathscomes from onegraphToSpeccall with a tolerant mirror for graphs it cannot re-emit (duplicate record keys, second output). Order: graph-level problems first, then node walk order, errors before warnings within a node.types.ts: addedROOT_ONLY_KINDS(trigger, abort, flow — derived fromROOT_ONLY_SECTIONS).How it was tested
npm run typecheck --workspace apps/agent-forge— cleannpm test --workspace apps/agent-forge -- --run src/graph/v2— 1444 tests pass (124 new mutation cases incl. the 100-seed mutation round-trip property, 16 validateGraph cases — one per core-check row with exact message/nodeId/fieldPath, ordering, clean worked example →[])npx vitest run(apps/agent-forge) — 2412 pass ·npm run typecheck:server,npm run test:server— 1121 pass · rootnpx tsc --noEmit— cleannpm run lint(root) — clean · Studio lint — 0 errors (31 pre-existing warnings, none in these files)npm run test:coverage— 7246 pass; 6 failures insrc/spec/v2/templates.test.tsREADME title checks (known CRLF line-ending environment issue, unrelated; create-lousho dist was built so its e2e passes)npm run fallow— clean (no dead code/exports, no cycles, no new clones)npm run docs:ratchet,npm run api:check,npm run docs:llms:check,npm run size-check— all passAcceptance criteria
Graphand never mutates its input (deep-freeze the input in tests)removeNode(g, 'agent')returnsgunchanged (same reference)connectNodesreturnscanConnect's refusal verbatim; agent → tool re-owns the toolGenerated with Devin