handoff-package.ts
PURPOSE
Bundles one weapon’s worth of VFX workbench artifacts into a markdown doc + machine-readable manifest JSON. The runtime-wiring session consumes the package to wire baked atlases, live shaders, anchors, and motion templates into the game’s render path. Implements 2026-04-19 parent spec §11 and 2026-04-20 §9.
OWNS
HandoffPackageinterface —{ markdownPath, markdown, manifest }.HandoffManifestinterface —weaponId,kitId,generatedAt(ISO), array of component entries (componentId,kind,category,atlasPath,liveShaderPath,anchors), plus pass-throughrelationships,previewMotion,entriesfrom the kit.buildHandoffPackage(kit, componentsById)— sole exported builder. Returns the full package.- Output path convention:
docs/vfx-handoff/<weaponId>.md.
READS FROM
./kit-schema—KitDeftype (entries, relationships, previewMotion, forWeaponId, notes, name, id)../component-schema—ComponentDeftype (id, kind, category, anchors).componentsById: Map<string, ComponentDef>— caller-supplied lookup; missing refs are flagged inline as**MISSING**rather than thrown.
PUSHES TO
Pure function — returns the package object. Caller is responsible for writing the markdown file and consuming the manifest. No filesystem I/O, no globals, no side effects beyond new Date().toISOString().
DOES NOT
- Does NOT write files to disk.
- Does NOT validate that referenced atlas PNGs or live-shader
.tsfiles actually exist on disk. - Does NOT load components — caller resolves the
componentsByIdmap upstream. - Does NOT throw on missing components — emits a
**MISSING**markdown stub instead so the runtime agent can resolve it. - Does NOT mutate the input kit or component map.
- Does NOT touch the runtime — only generates handoff artifacts; runtime wiring is the consumer’s job.
Signals
Path conventions (hard-coded):
- Baked atlas:
src/starship-survivors/data/vfx/atlas/<category>/<id>.png - Live shader GLSL:
src/starship-survivors/data/vfx/live-shaders/<id>.live.ts - Markdown output:
docs/vfx-handoff/<weaponId>.md
Manifest component shape per entry:
kind: 'baked' | 'live_shader'— mutually exclusive withatlasPath/liveShaderPath(the other isnull).anchors: string[]— derived fromObject.keys(comp.anchors ?? {}).
Entry points
buildHandoffPackage(kit: KitDef, componentsById: Map<string, ComponentDef>): HandoffPackage— the only export besides type interfaces.
Pattern notes
- Dual output: human-readable markdown for the runtime agent to read + structured JSON manifest for programmatic consumption. The runtime-wiring session reads both.
- Defensive on missing data, strict on shape: a missing
ComponentDefproduces a flagged stub; type contracts are enforced via TS. - Markdown built via line-array +
.filter(Boolean).join('\n')to keep conditional sections (notes, params, missing-component blocks) readable. - Runtime wiring checklist inlined as a markdown checklist (
- [ ]) coveringinitVfxComponents()boot wiring,reserveAtlasRegion/patchAtlasRegionfor baked,initLiveShaderRuntimes()for live shaders, weapon-def kit reference,drawBulletarchetype branch replacement withspriteBatch.add(...), Canvas 2D fallback retention. - Per-entry section displays kit-entry id, component id, kind, category, role, instance count (with fixed-count parenthetical if applicable), atlas or shader path, anchors, optional notes.
- Relationships section falls back to italicized “no relationships declared” prose when empty.
- Atlas / shader path appendices at the bottom of the markdown for quick scan; each falls back to italicized “none in this kit” when empty.
EXTRACT-CANDIDATE
Shared concepts that could be lifted across other workbench/handoff generators:
- Markdown-via-array + filter(Boolean) pattern is repeated across workbench docs; a helper
mdSection(lines: Array<string | false | null>)would deduplicate. - Path convention constants (
atlas/<category>/<id>.png,live-shaders/<id>.live.ts,docs/vfx-handoff/<weaponId>.md) are duplicated wherever baked-vs-live components are consumed — candidate for avfx-paths.tsmodule shared withvfx-component-runtime.tsand the atlas baker. - Missing-ref stub (
**MISSING** — no <Type> found for this id) is a generic pattern; extract amissingRefMarkdown(kind, id)if other handoff generators land. - Manifest pass-through of kit fields (
relationships,previewMotion,entries) suggests a typedKitHandoffViewcould be derived directly fromKitDefviaPick.