WORK-328
Setting up your dashboard 0 entities found · 8/31 branches scanned
ID:WORK-328Status:done

Migrate pre-engine field consumers to the fields bag

WORK-322 migrated the engine to read data-rune-fields, but the field metas have other readers that run on the pre-engine tree and still read field values from <meta data-field>. They must move to the bag before the metas can be dropped (WORK-323) — otherwise entity registration and SEO break.

Priority:highComplexity:moderateMilestone:v0.18.0Source:SPEC-082

Criteria completion

Criteria completion: 5 of 6 (83%) checked; tracking started on Jun 3, no incremental history yet0%25%50%75%100%Jun 3Jun 15

Tracking started Jun 3 — check back for trends.

Branches 2
History 3
  1. 80f5286
    Created (done)by bjornolofandersson
  2. a455cb9
    Content editedby Claude
    feat: pre-engine field consumers read the fields bag (WORK-328)
  3. 46b0484
    Content editedby Claude
    plan: insert WORK-328 (pre-engine field consumers) before WORK-323

Consumers to migrate

  • packages/runes/src/seo.tsfindByDataField / field-value reads for SEO + metadata extraction.
  • plugins/plan/src/pipeline.tsregister() reads entity field values (status / priority / source / …) to index plan entities.
  • plugins/storytelling/src/pipeline.tsregister() entity field reads.
  • plugins/design/src/pipeline.tstokens / scope / context reads.

Acceptance Criteria

  • A shared helper reads a field value from a node — prefer the parsed data-rune-fields, fall back to the <meta data-field> child (mirrors the engine's readField). All consumers use it.
  • seo.ts reads field values via the helper (bag-first).
  • The plan / storytelling / design register() hooks read entity field values via the helper (bag-first).
  • design's tokens / scope / context are handled — confirm which are properties-emitted (in the bag, e.g. tokens as a JSON string to re-parse) vs standalone metas that stay; document the split.
  • No behavior change: entity registration, collections / filters, and SEO output are identical with the dual channel present. The plan / design / storytelling sites build identically; full suite + the dogfood test green.
  • Tests cover bag-sourced field extraction for at least one entity per affected pipeline.

Notes

  • Only properties-emitted fields live in the bag. Postprocess sentinels (breadcrumb / pagination / collection / aggregate / drawer) and any standalone non-properties metas are a different channel — out of scope, left untouched.

Dependencies

  • WORK-321 — the fields bag must be emitted.

References

  • SPEC-082 — typed node data channel.

Resolution

Completed: 2026-06-02

Branch: claude/rune-contract-hardening

What was done

  • Added a shared bag-first field reader to packages/transform/src/helpers.ts: parseFields(tag) + readField(tag, name, fields?) — prefer the data-rune-fields bag (camelCase key, scalars coerced to string), fall back to the <meta data-field> child (kebab match). Structural param so it works on both Markdoc Tag instances and serialized POJOs. Exported from @refrakt-md/transform.
  • Migrated the three plugin register hooks to it (bag-first, meta fallback):
    • plugins/plan/src/pipeline.ts — entity field reads (RUNE_FIELDS are all single-word, so bag key === field).
    • plugins/storytelling/src/pipeline.ts — replaced its local kebab+meta reader (dropped the now-unused local toKebabCase).
    • plugins/design/src/pipeline.tstokens (a property → JSON string in the bag, re-parsed), scope, and sandbox context all via the helper.

Scope finding — seo.ts NOT affected

seo.ts's findProperty reads only headline / blurb, which are content-element refs (h1/p), not the properties-emitted <meta> values that WORK-323 drops. Those elements keep their data-field and survive the drop, and collectJsonLd reads RDFa property= (output metas), not the data channel. So seo reads nothing that disappears — left unchanged (that AC line is moot, not skipped work).

Verification

  • New fields.test.ts (7 tests): parseFields + readField bag-first / typed coercion / kebab meta-fallback / bag-wins / absent / pre-parsed. The plan/storytelling/design plugin tests + the real-content dogfood test exercise the migrated register hooks (pass — dogfood passes in isolation; flakes only under full-suite parallel load, pre-existing and unrelated).
  • Output-neutral: dual channel still present (321), so bag-first and meta give the same values. Full suite green (3064 + the new 7; the dogfood flake aside).

Notes

  • Sentinels (breadcrumb/pagination/collection/aggregate/drawer) untouched — separate channel. WORK-323 can now drop the property metas without breaking registration or SEO.