ID:WORK-149Status:done
Promote shared rune-reference infrastructure to packages/runes
Priority:highComplexity:simpleAssignee:claudeSource:SPEC-041
7bd70554b9df5aThree pieces of rune-introspection infrastructure live in places that block reuse: RuneInfo and describeRune() are inside packages/ai/src/prompt.ts (locked behind the AI dependency), and serializeContentModel() lives in packages/editor/src/server.ts (locked behind the editor). The new refrakt reference command needs all three without pulling in either package.
Move them to a single shared module — packages/runes/src/reference.ts — and have the existing consumers re-import from there. No behavior change; this is pure refactor that unlocks everything else in SPEC-041.
packages/runes/src/reference.ts exists and exports RuneInfo, describeRune(), EXCLUDED_RUNES, HIDDEN_ATTRIBUTES, and serializeContentModel() (alongside its stripContentModel helper)packages/runes/src/index.ts re-exports the public surface from reference.tspackages/ai/src/prompt.ts imports RuneInfo, describeRune, EXCLUDED_RUNES, HIDDEN_ATTRIBUTES from @refrakt-md/runes instead of defining them locallypackages/editor/src/server.ts imports serializeContentModel from @refrakt-md/runes instead of defining it locallypackages/cli/src/commands/edit.ts imports serializeContentModel from @refrakt-md/runes (replacing its serializeContentModelForEditor duplicate)packages/ai no longer re-exports RuneInfo from its own surface (or, if kept for backcompat, the type alias points at the runes-package definition)npm run build succeeds across all packagesnpm test passes — existing prompt-builder tests, editor serialization tests, and CLI edit-command tests all continue to pass without modificationpackages/runes/src/reference.ts. Copy RuneInfo, describeRune, describeAttribute, attributeTypeName, EXCLUDED_RUNES, HIDDEN_ATTRIBUTES from packages/ai/src/prompt.ts. Copy serializeContentModel and stripContentModel from packages/editor/src/server.ts:261-307.packages/runes/src/index.ts.packages/ai/src/prompt.ts with imports. Keep BASE_INSTRUCTIONS and buildPrompt (the LLM-prompt-specific code) in place — only the rune-description machinery moves.serializeContentModel with an import.serializeContentModelForEditor with an import (the function names should converge — drop the ForEditor suffix).None — this is the foundation work item.
serializeContentModel after this work)Completed: 2026-04-19
Branch: claude/scaffold-landing-docs-cli-DB31i
RuneInfo, describeRune, EXCLUDED_RUNES, HIDDEN_ATTRIBUTES, serializeContentModel, stripContentModel (and helpers attributeTypeName, describeAttribute, stripField). Imports RUNE_EXAMPLES and types from @refrakt-md/types.describeRune, serializeContentModel, stripContentModel, EXCLUDED_RUNES, HIDDEN_ATTRIBUTES (values) and RuneInfo (type) from ./reference.js.describeRune, EXCLUDED_RUNES, and RuneInfo from @refrakt-md/runes. Re-exports RuneInfo for backcompat (type alias points at the runes-package definition).serializeContentModel/stripContentModel/stripField (lines 845-903). Imports serializeContentModel from @refrakt-md/runes alongside the existing runes/RUNE_EXAMPLES/schemaContentModels imports. Dropped the now-unused ContentModel type import.serializeContentModelForEditor/stripModel/stripFieldDef duplicate (lines 181-216). Adds serializeContentModel to the existing await import('@refrakt-md/runes') destructure and uses it at line 136.npm run build succeeds across all packages.runes/plan/ — unrelated, and the same tests pass cleanly when run in isolation.RUNE_EXAMPLES still lives in packages/runes/src/examples.js; reference.ts imports it directly. No new dependencies were introduced.