Something went wrong. Try again.
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071/** * Plan-context seam — render the active-branch latest plan as a system-prompt section * (saga d4ks8c.4). * * Build (and any) mode reuses the latest valid plan without the turn loop ever branching * on a mode name: `AgentSession.assembleSystemPrompt` calls * `renderPlanPromptSection(all, activeTailId)` with the session's lineage tail and appends * the result when present. "No plan means no prompt change" — the helper returns `undefined` * when there is no valid plan, so the assembled prompt is untouched. * * The active-branch lookup follows `parentId` ancestors from `activeTailId`; file order is * NOT the authority, so an off-branch plan can never leak into the build prompt. * * This is the generic seam between persisted checkpoint data and the model-facing prompt: * it reads opaque `checkpoint` entries (produced generically from any mode's `onTurnEnd` * `checkpoint` intent) and renders a clearly delimited Markdown section. Modes do not * hard-code plan lookup; the session does not special-case `mode === 'build'`. */import type { SessionEntry } from '@/types/session-entry';import type { PlanArtifact } from '@/contracts/plan-artifact';import { latestPlanArtifact } from '@/core/session/lineage';
/** Delimiter lines bounding the plan section (stable so clients/tests can locate it). */export const PLAN_SECTION_START = '## Active Plan';export const PLAN_SECTION_END = '<!-- /active-plan -->';
/** * Render `plan` as a clearly delimited Markdown section. Pure: deterministic formatting * (heading, numbered steps, verbatim rendered text, then a closing sentinel). The * `sourceMessageId` is included as a provenance breadcrumb so `recall`/clients can re-link * the plan to its source assistant message. */export function formatPlanSection(plan: PlanArtifact): string { const lines: string[] = [PLAN_SECTION_START, '']; lines.push( 'A prior planning turn extracted the implementation plan below. Follow these steps ' + 'in order; adapt only when a step is blocked or superseded by newer information.', ); lines.push(''); lines.push(`_source message: ${plan.sourceMessageId}_`); lines.push(''); for (const step of plan.steps) { lines.push(`${step.index + 1}. ${step.text}`); } lines.push(''); // The verbatim `## Implementation Plan` section text the model emitted, included // losslessly so clients/renderers can show the human-facing plan exactly as written. lines.push('```markdown'); lines.push(plan.renderedText); lines.push('```'); lines.push(''); lines.push(PLAN_SECTION_END); return lines.join('\n');}
/** * Resolve the latest valid plan on the active branch and render it as a delimited * system-prompt section. `activeTailId` is the lineage tail (the leaf entry of the active * branch); the lookup walks only its `parentId` ancestors. Returns `undefined` when there * is no valid plan on the chain (no prompt change). Generic: never inspects a mode name — * only persisted checkpoint data. */export function renderPlanPromptSection( all: SessionEntry[], activeTailId: string | undefined,): string | undefined { const plan = latestPlanArtifact(all, activeTailId); if (plan === undefined) return undefined; return formatPlanSection(plan);}