Graph Resources — Tasks
Companion: design.md. Each phase ships alone and leaves the repo green. After any code change run the four mandatory checks (
npm run test:affected,npm run typecheck,npm run lint,npm run dev:nodetool -- harness gate --base origin/main).
Phase 1 — Types and entity nodes
- Protocol:
StoryboardRef. Add topackages/protocol/src/api-types.tsnext toScriptRef, with thewritableflag (design §2.1);storyboardRefDefaultinpackages/core-nodes/src/nodes/ref-defaults.ts;nodetool.constant.Storyboardandnodetool.constant.Entityinconstant.ts;StoryboardRef+Entityinpackages/dsl/src/types.ts; thestoryboardandentitynames inscripts/verify-backend-bundle.mjs. Test: DSL generation emitsstoryboard/entitytyped inputs for the constant nodes. - Lineage fields.
templateId/recastKeyonStoryboardDocument(packages/models/src/storyboard.ts,api-schemas/storyboards.ts),templateIdonScriptDocumentandTimelineSequence,sourceonEntityMarker(creative.tszod + reader). Tests: old fixtures parse unchanged; the fields round-trip. entityFromAssetto models. Move topackages/models/src/entity.ts; the agent capability imports it. No behaviour change; existingcapabilities-entitiestests stay green.- Model interfaces.
getStoryboard/createStoryboard/updateStoryboard,listEntities/getEntity/upsertEntity,listGameTemplatesonProcessingContextModelInterfaces(packages/runtime/src/context.ts), forwarders on the context, implementations inpackages/websocket/src/session/model-interfaces.tsand the CLI context builder.upsertEntitymatchessource.key, then (project, kind, name). Tests: ownership refusal, upsert returns the same id twice. resolveEntities.packages/runtime/src/entities.ts: fill an entity value from the library whendescriptoris empty andgetEntityis wired; pass through otherwise. Unit test both branches.nodetool.entity.*.LoadEntity,ListEntities,CreateEntityinpackages/core-nodes/src/nodes/entity.tsper design §4.1. Node tests against an in-memory context.list[entity]on generators. Retypeentitiesonnodetool.image.TextToImage,nodetool.video.ImageToVideo,nodetool.video.TextToVideo,nodetool.creative.ApplyEntities; callresolveEntitiesbeforeinjectEntities. Test: a saved graph carrying the oldlist[dict]value still runs.- Web pickers.
StoryboardProperty(overDocumentPickerProperty, newuseStoryboardshook if none) andEntityProperty(reusingEntityAssetPickerDialog) inweb/src/components/properties/;PropertyInput.resolver.tsxcases;data_types.tsentries. Jest: picker renders, selection writes the ref shape.
Phase 2 — packages/storyboard and the storyboard nodes
- Package scaffold.
packages/storyboardwithAGENTS.md+CLAUDE.md, an entry inpackages/AGENTS.md, workspace + turbo wiring, dependency orderprotocol → timeline → storyboard.npm run check:agents-docsgreen. recastStoryboard. Per design §3.1 with the fixture suite: explicitreplaces, single-of-kind, ambiguous kind appends, whole-word rename (Nova/Novakcase), explicitentity_idsrewrite, hash-based invalidation keeping product-free shots, lineage stamping,recastKeystable under cast order and different for the swapped assignment, re-derive overexisting(edited template action invalidates one shot, renamed destination entity under the same id invalidates only the shots naming it, added shot appears, dropped shot reported).planShotRenders+renderShots. Lift the plan and the IO frompackages/agents/src/capabilities/storyboards.ts; the capability’srender_storyboard_stills/render_storyboard_clips/filterStalecall the package. Test assertingfilterStaleandplan.freshagree on the capability’s fixtures; storyboard tool-loop eval unchanged.nodetool.storyboard.*.LoadStoryboard,StoryboardShots,RecastStoryboard,RenderStills,RenderClips,AssembleTimelineinpackages/video-nodes/src/nodes/storyboard.tsper design §4.2, tagged server. Node tests:reuse_existingreturns the prior copy,only_staleskips fresh shots,require_keyframeskips, the write contract (picker ref refused on first run and for a derived board,allow_writesadmits, derived refs carrywritable),AssembleTimelineclones the template cut for a copy and keeps its foreign clips, takes the linked path whenscript_idis set, and writestimeline_id.- Web lineage chip. “Recast from " in the storyboard header when `templateId` is set, linking to the source board.
Phase 3 — Script and timeline derivations
fillScript.packages/protocol/src/script-fill.ts, tests for filled/unresolved reporting and take retention.nodetool.script.WriteScript/FillScript. Inpackages/video-nodes/src/nodes/script.tsper design §4.3;WriteScriptmapscastentities to speakers (entityId,voice.voicefromvoice_id). Node tests with a stubbed provider.cloneTimelineForBoard,fillTimelineText,retargetSequence. Inpackages/timelineper design §3.2; fixtures with a text clip, a music bed on a foreign track, a keyframed transform, and the validator run on every output. Clone fixture: owned clips re-stamped and cleared, foreign clips and tracks byte-identical.nodetool.timeline.FillTimelineText/RetargetTimeline. Per design §4.4; both create a new sequence withtemplateId.
Phase 4 — Game nodes
slotPrompt.packages/protocol/src/game-slot-prompt.ts; tests per slot kind asserting sizes and thatcheckermatches eachnodetool.game.*checker’s prop names.packages/game-nodes.LoadGameTemplate,SlotPrompt,ExportGodotProjectper design §4.5, withAGENTS.md/CLAUDE.mdand thepackages/AGENTS.mdentry;base-nodesre-exports. Export test against the platformer golden fixture inpackages/godot.- Checker
slotinput.SpriteSheet,Tileset,SeamlessImage,SoundEffect,MusicLoopacceptslot: game_slotand derive their numeric props from it when connected. Tests: connected slot wins over stale hand-typed values.
Phase 5 — Examples, harness, docs
- Example workflows.
Per-SKU Ad Factory,Localized Explainer,Platformer Asset Pack,Three Ratiosunderpackages/base-nodes/nodetool/examples/nodetool-base/, models unset, each passingvalidate_workflowonce models are stamped. - Fake-mode fixtures. The same graphs with
nodetool.fake.*generators andprovider: fakeon the render nodes, runnable bynodetool debugwith no keys, E4 included. The E1 run asserts the filled overlay text is on the exported sequence; the E4 run asserts the source cut’s clip placements are unchanged on both retargets. - Harness registry.
graph-resourcesentry inpackages/cli/src/harness/registry.tswhose selfcheck runs the pure suites and the fake-mode debug runs;nodetool harness auditclean;harness gatemaps diffs underpackages/storyboard/,packages/game-nodes/, the new node files and the examples to it. - Docs and skills. Node table in
docs/creative-agent.md§ Graph templates; the new node types in.claude/skills/video-workflow/SKILL.mdand.claude/skills/godot-game/SKILL.md(the graph path next to theinvoke_nodeloop);docs/harnesses.mdentry for the harness; the AGENTS.md harness table row. Move this design’s status line to shipped per phase.