Drop inert metas from rune children arrays 100 metas across 24 tag files are mapped in properties and emitted into children, where createComponentRenderable filters them straight back out (packages/runes/src/lib/component.ts:127-131). 133 other metas already omit that emission and render identically.Delete the emission. Nothing else.
high simple
Remove the unreachable schema.org channel from createComponentRenderable schema, typeof and schemaOrgType on TransformResult / InlineTransformResult have zero callers across all 121 runes. SPEC-130 moved every rune to the declarative table on createContentModelSchema({ schema }); the imperative surface it replaced was never deleted.So schemaTags (component.ts:57-61) is always empty, isSeoMeta (:84) is always false, emptySeoMetas (:110-125) is always empty, and roughly 40 lines of the helper are unreachable.
high simple
Consolidate extractText and adopt the exported textContent Two families of duplication, with different fixes.AST side — six byte-identical copies. extractText(node: Node) is defined identically in packages/runes/src/tags/form.ts, plugins/places/src/tags/map.ts, plugins/design/src/tags/{palette,typography,spacing}.ts and plugins/marketing/src/tags/comparison.ts.Renderable side — textContent is already exported and reimplemented anyway. @refrakt-md/runes exports it (seo.ts:23), and plugins/plan/src/pipeline.ts + plugins/storytelling/src/pipeline.ts define extractTextContent, while plugins/media/src/tags/track.ts defines a Tag-flavoured extractText.
medium simple
Add renderNodes and the bodyOnly content-model preset Two spellings, each repeated past the point of being idiom.renderNodes(nodes, config) → RenderableNodeCursor. The full form appears 153 times, 81 of them as exactly new RenderableNodeCursor(Markdoc.transform(asNodes(resolved.X), config) as RenderableTreeNode[]). There are 160 as RenderableTreeNode[] casts in the tag files.bodyOnly() — { type: 'sequence', fields: [{ name: 'body', match: 'any', optional: true, greedy: true }] } is the entire content model for 49 of the 94 declared in the tag files, in four whitespace variants.
medium simple
Add fieldMetas and groupByHeading The two utilities with actual design in them, as opposed to the spellings in WORK-602.fieldMetas(attrs, spec) collapses the declare-then-name-again cycle into one declaration, returning a Record<string, Tag> usable directly as properties. plugins/plan/src/tags/work.ts goes from 36 lines of plumbing to about 13:
medium moderate
Promote the three styles transform helpers into the named-transform enum RuneConfig.styles[…].transform is one of only two function-typed fields in the whole of RuneConfig (packages/transform/src/types.ts:301; the other is postTransform, which stays imperative by design). Unlike postTransform, it does not need to be a function: a declarative sibling already ships, and the function form is used by a closed set of three helpers.
medium simple