Skip to content

feat(universe-builder): Phase B — enrich expand contract with canon + plumb canon into arc prompts#267

Open
atomantic wants to merge 10 commits into
mainfrom
feat/ub-redesign-phase-b
Open

feat(universe-builder): Phase B — enrich expand contract with canon + plumb canon into arc prompts#267
atomantic wants to merge 10 commits into
mainfrom
feat/ub-redesign-phase-b

Conversation

@atomantic
Copy link
Copy Markdown
Owner

Summary

Phase B of the Universe Builder redesign (PLAN.md Next Up #1). Builds on the Phase A schema (#264) by enriching the LLM "Generate From Idea" contract to return first-class named canon and plumbing that canon into downstream prompts.

  • Server expand contract now returns characters[] / settings[] / objects[] with rich metadata (physicalDescription, palette, slugline, recurringDetails, etc.) alongside the existing categories + composite sheets. Each category also gets a kind tag so the Phase C UI knows which canon trunk to render it under.
  • Client handleExpand merges returned canon into the draft's universe.characters/.settings/.objects arrays. Existing entries always win on name/slugline collision so a re-expand can't clobber hand-authored or series-extracted records.
  • arcPlanner picks up a new worldCanonText context field via renderCanonForPrompt(world) — the LLM now sees named cast/places/objects alongside the existing worldCategoriesText exploratory variations. Folds in the "arcPlanner prompt context — include canon" backlog item.
  • Migration 019 auto-updates the pipeline-arc-resolve.md + pipeline-volume-verify.md templates to include the new {{worldCanonText}} block when unmodified; customized prompts get a manual-merge warning (mirrors the migration-003 pattern).

Files changed

  • server/services/universeBuilderExpand.jsbuildExpansionPrompt asks for canon + kind; isExpansionShape recognizes canon arrays; normalizeCanonArray(raw, kind) runs LLM output through sanitizeBibleList with BIBLE_SOURCE.UNIVERSE_EXPAND stamped pre-sanitize.
  • server/lib/universePromptRenderers.js — new renderCanonForPrompt(world), table-driven per-kind formatting.
  • server/services/pipeline/arcPlanner.js — wires worldCanonText into loadWorldContext + EMPTY_WORLD_CONTEXT.
  • client/src/pages/UniverseBuilder.jsxmergeCanonByName helper (dedupe by name + slugline, identity-preserving on empty input); handleExpand merges canon via pickCanon; toast dedupe via expandToast helper.
  • data.sample/prompts/stages/pipeline-{arc-resolve,volume-verify}.md — new "World canon" block above the categories block.
  • scripts/migrations/019-arc-verify-resolve-canon-context.js — hash-driven one-shot template upgrade.
  • scripts/setup-data.js — bumped shipped-MD5 entries (OLD becomes array of two hashes; NEW gets the post-019 hash).
  • server/routes/universeBuilder.js — JSDoc update to advertise the new expand return shape.

Test plan

  • cd server && npm test — 5108 passing, 5 skipped (was 5102 in Phase A, +6 new)
  • cd client && npm run build — clean
  • New tests:
    • EXPANSION_PROMPT contains characters/settings/objects + physicalDescription + slugline + significance (prompt contract)
    • EXPANSION_PROMPT teaches kind enum on categories (LLM hint matches Zod enum)
    • normalizeCanonArray x4 (non-array → []; character → bible shape; setting requires name OR slugline; object requires name)
    • arcPlanner: worldCanonText contains Mira Holt + field detective + The Tongue (canon context flows into prompt); placeholder branch asserts none
  • /simplify review applied: HIGH ×1 (BIBLE_SOURCE constant); MED ×4 (toast dedupe, table-driven renderer, mergeCanonByName short-circuit, pickCanon helper); 1 MED deferred → PLAN.md (mergeExpandIntoDraft extraction)
  • Manual smoke: open a universe, click "Generate From Idea", confirm canon entries appear in the canon section after expand
  • Manual smoke: trigger arc planning on a series with a linked universe, verify the prompt context (logged at data/runs/<id>/output.txt) includes the World canon block

Migration safety

Migration 019 is unmodified-only — data/prompts/stages/pipeline-arc-resolve.md and pipeline-volume-verify.md are replaced ONLY when their on-disk hash matches one of the two prior shipped hashes (pre-005 or current). Customized prompts get a warning + manual-merge instructions and stay unchanged. Idempotent: re-runs against the new hash are no-ops.

Known deferred

  • mergeExpandIntoDraft(draft, result) extraction from the now ~155-line handleExpand. Pure merge logic can be lifted out + unit-tested. Captured in PLAN.md under "Code quality / dedup".
  • Sweep for other prompt builders that read world.categories without world.canon (PLAN.md backlog item).

🤖 Generated with Claude Code

…rrays + plumb canon into arc prompts

Universe Builder "Generate From Idea" now returns rich first-class canon
alongside categories:
  - characters[]: name, physicalDescription, personality, background, prompt, tags
  - settings[]:   name, slugline, description, palette, recurringDetails, ...
  - objects[]:    name, description, significance, prompt, tags

The expand LLM is also taught to tag each category with `kind` so the Phase A
data model lands them under the right canon trunk in the upcoming UI. Client
handleExpand merges canon into draft (existing entries always win on name/
slugline collision — server-side dedupe via sanitizeBibleList).

arcPlanner now feeds named canon into LLM prompts via a new worldCanonText
context field (sibling to worldCategoriesText). Migration 019 auto-updates
the pipeline-arc-resolve and pipeline-volume-verify templates on launch for
unmodified installs; customized prompts get a manual-merge warning.
Copilot AI review requested due to automatic review settings May 17, 2026 12:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enriches Universe Builder expansion output with first-class canon entities and makes linked-world canon available to downstream arc/volume prompt contexts.

Changes:

  • Expands the server/client “Generate From Idea” contract to include characters, settings, objects, and category kind.
  • Adds canon prompt rendering and wires worldCanonText into arc planner context/templates.
  • Adds migration/setup-data hash handling and tests/documentation for the new contract.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
server/services/universeBuilderExpand.js Adds canon arrays and category kind guidance to expansion output.
server/services/universeBuilderExpand.test.js Adds tests for canon normalization and prompt contract text.
server/lib/universePromptRenderers.js Adds canon-to-prompt rendering helper.
server/services/pipeline/arcPlanner.js Adds worldCanonText to linked-world context.
server/services/pipeline/arcPlanner.test.js Verifies canon context flows into arc planner calls.
server/routes/universeBuilder.js Updates route docs for expand response shape.
client/src/pages/UniverseBuilder.jsx Merges returned canon into the draft and auto-save payload.
data.sample/prompts/stages/pipeline-arc-resolve.md Adds World canon block to resolve prompt.
data.sample/prompts/stages/pipeline-volume-verify.md Adds World canon block to volume verification prompt.
scripts/migrations/019-arc-verify-resolve-canon-context.js Adds hash-gated prompt template migration.
scripts/setup-data.js Updates shipped prompt hashes for drift detection.
PLAN.md Marks Phase B canon context work as folded in and records follow-ups.
.changelog/NEXT.md Adds user-facing release notes for expansion canon and prompt canon context.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread client/src/pages/UniverseBuilder.jsx
Comment thread server/services/universeBuilderExpand.js
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
Comment thread scripts/migrations/019-arc-verify-resolve-canon-context.js Outdated
Also forward LLM-returned category `kind` through normalizeCategories so
custom buckets land under the right canon trunk; use normalizeSlugline for
settings dedupe so dash/punct-variant sluglines collide; rename migration
019 to reflect the files it actually updates (pipeline-arc-resolve.md +
pipeline-volume-verify.md, not arc-verify).
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

Comment thread client/src/pages/UniverseBuilder.jsx
Comment thread server/services/pipeline/arcPlanner.js
Comment thread scripts/migrations/019-arc-resolve-volume-verify-canon-context.js Outdated
Comment thread server/services/universeBuilderExpand.js Outdated
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
… in all arc/volume prompts

Five Copilot follow-ups:

- handleExpand: build mergedCategories with both 'kind' (existing draft wins,
  LLM-returned kind as fallback) and 'variations', so the LLM/user-tagged
  bucket trunk survives the round-trip through ensureDraftCategories.
- arc-overview.md + arc-verify.md: render {{worldCanonText}} so the canon
  context fed by arcPlanner actually reaches the prompt (previously only
  arc-resolve + volume-verify referenced it).
- Migration 019 now updates all four arc/volume templates, renamed to
  019-arc-volume-prompts-canon-context.js; setup-data.js hash bumps mirror.
- normalizeCanonArray strips LLM-supplied id/createdAt/updatedAt before
  sanitize so a hallucinated/example id can't introduce duplicate canon ids.
- mergeCanonByName is kind-aware — settings use normalizeSlugline for both
  name and slugline (matches storyBible MERGE_CONFIG.setting.keyFields), so
  dash/punct-variant identifiers collide instead of duplicating.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Comment thread server/services/universeBuilderExpand.js Outdated
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
Comment thread .changelog/NEXT.md Outdated
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
…oast + complete changelog

Four Copilot follow-ups:

- normalizeCanonArray strips locked/sourceSeriesId/imageRefs/primaryImageRef
  alongside the previously-stripped id/timestamps. Without this, a
  hallucinated 'locked: true' from the LLM would silently lock new canon
  entries (blocking user edits via the lock UI), and stale sourceSeriesId/
  imageRefs would falsely attribute provenance + pin visuals.
- expandToast now reports NEW canon entries added by this expand (post-merge
  minus pre-existing), not the draft's running total. Re-expanding on a
  populated universe no longer claims credit for entries the user authored.
- mergeCanonByName is alias-aware for character/object kinds, matching the
  server's MERGE_CONFIG keyFields. Existing 'Ashley' with alias 'Ash'
  collides with an LLM-returned 'Ash' instead of duplicating.
- Changelog NEXT.md names all four templates updated by migration 019
  (arc-overview, arc-verify, arc-resolve, volume-verify), not just the
  two originally listed.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 3 comments.

Comment thread scripts/migrations/019-arc-volume-prompts-canon-context.js Outdated
Comment thread client/src/pages/UniverseBuilder.jsx
Comment thread server/services/universeBuilderExpand.js Outdated
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 15 out of 15 changed files in this pull request and generated 4 comments.

Comment thread server/services/universeBuilderExpand.js
Comment thread data.sample/prompts/stages/pipeline-arc-overview.md
Comment thread data.sample/prompts/stages/pipeline-arc-verify.md
Comment thread scripts/migrations/019-arc-volume-prompts-canon-context.js Outdated
… boundary; gate Linked World prompt block on hasLinkedWorld; add migration 019 test
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Comment thread server/services/universeBuilderExpand.js Outdated
Comment thread scripts/migrations/019-arc-volume-prompts-canon-context.test.js Outdated
Comment thread scripts/migrations/019-arc-volume-prompts-canon-context.test.js
Comment thread server/lib/universePromptRenderers.js
…rompt rendering, drift-catch + OLD→NEW migration test via applyMigration helper
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.

Comment thread client/src/pages/UniverseBuilder.jsx Outdated
Comment thread server/lib/universePromptRenderers.js Outdated
Comment thread server/lib/universePromptRenderers.js Outdated
Comment thread PLAN.md Outdated
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
… enrich canon renderer with personality/slugline/recurringDetails, fix mergeCanonByName within-batch dedupe, correct PLAN doc
@atomantic atomantic requested a review from Copilot May 17, 2026 14:24
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 17 out of 17 changed files in this pull request and generated 4 comments.

Comment thread client/src/pages/UniverseBuilder.jsx
Comment thread scripts/migrations/019-arc-volume-prompts-canon-context.test.js
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
…e on setSaving to prevent double-submit, exclude *.test.js from migration runner, refresh stale comment
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.

Comment thread client/src/pages/UniverseBuilder.jsx
Comment thread server/services/universeBuilder.js
Comment thread client/src/pages/UniverseBuilder.jsx Outdated
Comment thread client/src/pages/UniverseBuilder.jsx
…e payload, drop premature cap in characters-bucket fold, capture canon-clobber risk in PLAN
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants