generate-completion-status.ts
94 lines · scripts/resolvers/preamble/generate-completion-status.ts at 3f79d81
1import type { TemplateContext } from '../types';
2import { getHostConfig } from '../../../hosts/index';
4/**
5 * Plan-mode-skill semantics block.
6 *
7 * Lives at the TOP of the preamble (position 1) so models read the authoritative
8 * plan-mode rule before any other instructions. Replaces the vestigial
9 * generate-plan-mode-handshake.ts that used to sit at this position and told
10 * interactive review skills to emit an exit-and-rerun handshake instead of
11 * running their interactive STOP-Ask workflow.
12 *
13 * Text is the same "Plan Mode Safe Operations" + "Skill Invocation During Plan
14 * Mode" blocks that previously lived at the tail of generateCompletionStatus().
15 * Only the position changes. All skills (not just interactive: true) see this.
16 *
17 * Composition position: index 1 in scripts/resolvers/preamble.ts — after
18 * generatePreambleBash (so _SESSION_ID / _BRANCH / _TEL env vars exist before
19 * any plan-mode-aware telemetry) and before generateUpgradeCheck + onboarding
20 * gates. See ceo-plan 2026-04-24 "remove vestigial plan-mode handshake" for
21 * the full rationale.
22 *
23 * Hosts whose capabilities declare planMode:false have no plan mode to be in,
24 * so the section renders empty for them (#3168).
25 */
26export function generatePlanModeInfo(ctx: TemplateContext): string {
27 if (!getHostConfig(ctx.host).capabilities.planMode) return '';
28 if (ctx.planMode === false) return '';
29 const entryOrder = ctx.skillName === 'plan-eng-review'
30 ? 'starting from the Scope gate, then follow its Startup sequence'
31 : 'starting from the Scope gate (current target announcement or answered question), then preamble and Step 0';
32 const invocation = ['plan-design-review', 'plan-eng-review'].includes(ctx.skillName)
33 ? `Run the invoked skill within the host's plan-mode limits. **Execute the skill file** ${entryOrder}. Skill questions are valid; skip only questions the skill resolves. Any AskUserQuestion variant satisfies end-of-turn; use AskUserQuestion Format's tool resolution. If unavailable/failed: \`headless\` → BLOCKED; \`interactive\` → prose fallback (satisfies end-of-turn). At STOP, stop: no continuation or ExitPlanMode. Run "PLAN MODE EXCEPTION — ALWAYS RUN" commands only where the host permits. ExitPlanMode only after skill completion or if the user cancels the skill or tells you to leave plan mode.`
34 : `If the user invokes a skill in plan mode, run its workflow within the host's plan-mode limits. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; any AskUserQuestion the skill fires is the workflow operating within plan mode, not a violation of it — and a skill whose instructions resolve a question themselves (e.g. a plan-mode auto-select) may legitimately not ask it. AskUserQuestion (any variant — \`mcp__*__AskUserQuestion\` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If AskUserQuestion is unavailable or a call fails, follow the AskUserQuestion Format failure fallback: \`headless\` → BLOCKED; \`interactive\` → the prose fallback (also satisfies end-of-turn). At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" run only where the host permits them. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode.`;
35 return `## Plan Mode Safe Operations
37Host and system plan-mode restrictions and the user's current scope take precedence over any skill; a skill cannot grant itself an exception to read-only mode. Where the host permits them, these inform the plan: \`$B\`, \`$D\`, \`codex exec\`/\`codex review\`, temp prompts, writes to \`~/.gstack/\`, writes to the plan file, and \`open\` for generated artifacts. If the host blocks one, skip it, say so, and continue the permitted work.
39## Skill Invocation During Plan Mode
41${invocation}`;
42}
44export function generateCompletionStatus(ctx: TemplateContext): string {
45 return `## Completion Status Protocol
47When completing a skill workflow, report status using one of:
48- **DONE** — completed with evidence valid for the final consumed inputs; name reuse and anything not independently verified.
49- **DONE_WITH_CONCERNS** — completed, but list concerns.
50- **BLOCKED** — cannot proceed; state blocker and what was tried.
51- **NEEDS_CONTEXT** — missing info; state exactly what is needed.
53Escalate after 3 failed attempts, uncertain security-sensitive changes, or scope you cannot verify. Format: \`STATUS\`, \`REASON\`, \`ATTEMPTED\`, \`RECOMMENDATION\`.
55## Operational Self-Improvement
57Before completing, review the session for durable learnings and log each one.
58The review runs every time, not only when something felt noteworthy. A durable
59learning is a project quirk, command fix, pitfall, or pattern that would save
605+ minutes in a future session. If the review genuinely surfaces none, state
61"No durable learnings this session" in your completion summary — an explicit
62empty result, not a skipped step.
64\`\`\`bash
65${ctx.paths.binDir}/gstack-learnings-log '{"skill":"SKILL_NAME","type":"operational","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"observed"}'
66\`\`\`
68Do not log obvious facts or one-time transient errors.
70## Telemetry (run last)
72After workflow completion, log telemetry with ONE command. OUTCOME is
73success/error/abort/unknown; \`SESSION_ID\` and \`TEL_START\` are the values the
74preamble's skill-start output echoed. It also drains the artifacts-sync queue
75(the former skill-end sync step — do not run gstack-brain-sync separately).
77**PLAN MODE EXCEPTION — ALWAYS RUN:** This writes telemetry to
78\`$GSTACK_STATE_ROOT/analytics/\`, matching preamble analytics writes.
80\`\`\`bash
81${ctx.paths.binDir}/gstack-skill-end --skill "${ctx.skillName}" --outcome OUTCOME \\
82 --session-id "SESSION_ID" --tel-start "TEL_START" --used-browse USED_BROWSE \\
83 --error-message "ERROR_MESSAGE" --failed-step "FAILED_STEP" 2>/dev/null || true
84\`\`\`
86Replace \`OUTCOME\` and \`USED_BROWSE\` (yes/no) before running; substitute
87\`SESSION_ID\`/\`TEL_START\` from the skill-start echoes. \`ERROR_MESSAGE\`/\`FAILED_STEP\`
88are "" unless outcome is error. If the command is missing (stale install), skip
89telemetry — it never blocks the workflow.
91## Plan Status Footer
93Skills that run plan reviews (\`/plan-*-review\`, \`/codex review\`) include the EXIT PLAN MODE GATE blocking checklist at the end of the skill, which verifies the plan file ends with \`## GSTACK REVIEW REPORT\` before ExitPlanMode is called. Skills that don't run plan reviews (operational skills like \`/ship\`, \`/qa\`, \`/review\`) typically don't operate in plan mode and have no review report to verify; this footer is a no-op for them. ${ctx.skillName === 'plan-eng-review' ? 'Use the selected report file and honor the Review record and write policy for every artifact.' : 'Writing the plan file is the one edit allowed in plan mode.'}`;
94}