Skip to content

Cross-issue prose continuity: inject prior issue's prose tail + next issue's beats into the prose stage#2233

Merged
atomantic merged 4 commits into
mainfrom
next/issue-2177
Jul 6, 2026
Merged

Cross-issue prose continuity: inject prior issue's prose tail + next issue's beats into the prose stage#2233
atomantic merged 4 commits into
mainfrom
next/issue-2177

Conversation

@atomantic

Copy link
Copy Markdown
Owner

Summary

CWQE Phase 12 (#2177). Previously each issue's prose stage drafted blind to its neighbors — every issue opened and closed in a vacuum, producing the "every chapter opens/closes the same way" tic and giving the editorial loop more to fix. This wires cross-issue continuity into the prose generation stage:

  • buildProseContextAugment (server/services/pipeline/textStages.js) injects the previous issue's actual closing prose (last ~2000 chars, cut on a paragraph boundary) as priorIssueProseTail and the next issue's opening beats as nextIssueBeats. Neighbor resolution is factored into a shared resolveVolumeNeighbors helper (also used by the idea-stage augment), loaded without run history.
  • Prompt template (data.reference/prompts/stages/pipeline-prose.md) renders both blocks conditionally under {{#hasNeighborContinuity}} with guidance to open so it flows from the prior ending (without repeating its closing image) and land the ending so it hands off to the next issue's beats. Injected content is fenced with an "quoted context only" injection guard.
  • Token-budgeted via contextBudget.js — the two blocks share a fraction of the resolved usable input budget (prior tail keeps priority), so a small-context local model degrades by trimming rather than erroring. The prior tail is trimmed from its head so the actual closing survives.
  • No fabricated continuity — when the prior issue's prose doesn't exist yet (non-linear/parallel generation, or the first issue of a volume) the block simply doesn't render.
  • Covers every full prose (re)generation path — manual draft, auto-runner, and Series Autopilot — because they all funnel through generateStage.
  • Migration 168 rewrites the installed pipeline-prose.md for existing installs (customization-safe; customized prompts are left intact and warned). Earlier prose-touching migrations (003/027/054/127/166) and the drift baseline are resynced to the new shipped hash.

This is one slice of the multi-phase #2177 epic — the pipeline-manuscript-fix.md revision path and the Phase 7 revision loop do not yet assemble the same neighbor context (task 4 of the issue), so the issue stays open.

Test plan

  • server/services/pipeline/textStages.test.js — 63 pass. New coverage: continuity injection for a middle issue, no prior tail on the first issue of a volume, prior block absent when the prior issue has no prose yet, ungrouped-issue (no season) yields no blocks, next-beats synopsis fallback, idea stage does NOT get the prose-tail blocks, extractProseTail length/boundary/absent behavior, extractNextIssueBeats precedence, and a small-context-window trim test that pins the trimmed tail keeps the CLOSING content (not the opening).
  • scripts/migrations/168-prose-cross-issue-continuity.test.js and scripts/setup-data-drift.test.js pass; migrations 003/027/054/127/166 tests pass with resynced hashes.

Refs #2177

atomantic added 4 commits July 6, 2026 09:30
…ats into the prose stage

The prose stage drafted each issue blind to the previous issue's actual
closing prose and the next issue's opening beats — so chapter boundaries
didn't flow and the narrative voice didn't carry across units. This adds a
cross-issue continuity block to the prose prompt (CWQE Phase 12): the previous
issue's closing prose tail (~2000 chars) and the next issue's beat-sheet head,
both token-budgeted via contextBudget.js so a small-context model degrades by
trimming rather than erroring. When the prior issue's prose doesn't exist yet
(non-linear/parallel generation, or first issue of a volume) the block simply
doesn't render — no fabricated continuity.

Wired into buildStageContext for the prose stage, so every full prose
(re)generation path gets it: manual route, autoRunner, and Series Autopilot.
Neighbor resolution is factored into a shared resolveVolumeNeighbors helper
(loading without run history) that the idea-stage augment now shares too.

pipeline-prose.md is a shipped template: migration 168 rewrites it on existing
installs (customization-safe), with the pipeline-prose lineage (003/027/054/
127/166) and the setup-data drift baseline resynced to the new shipped hash.

Closes #2177
… the closing survives

trimContextToBudget keeps the head of the string, so on a small-context
local model the prior-issue prose tail lost its literal closing lines —
the exact seam the prose template tells the model to open from. Size the
tail via extractProseTail (which keeps the end) capped at the budget
instead, and pin it with a regression assertion that the trimmed tail
contains the closing marker, not the opening.
…erged #2178

#2178 (editorial-premature-reveal-stage) merged to main and took migration
number 168, colliding with this branch's cross-issue-continuity migration.
Renumber ours to the next free slot (169) and fix the internal references:
the .test.js import path, describe() label, and migration-NNN- prefix, plus
the post-168 → post-169 lineage comments in the resynced prose-prompt
migrations (003/027/054/127/166). Content hashes are unchanged.
@atomantic atomantic merged commit 6828a05 into main Jul 6, 2026
2 checks passed
@atomantic atomantic deleted the next/issue-2177 branch July 6, 2026 16:41
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.

1 participant