import type { TemplateContext } from '../types'; /** * Plan-mode-skill semantics block. * * Lives at the TOP of the preamble (position 1) so models read the authoritative * plan-mode rule before any other instructions. Replaces the vestigial * generate-plan-mode-handshake.ts that used to sit at this position and told * interactive review skills to emit an exit-and-rerun handshake instead of * running their interactive STOP-Ask workflow. * * Text is the same "Plan Mode Safe Operations" + "Skill Invocation During Plan * Mode" blocks that previously lived at the tail of generateCompletionStatus(). * Only the position changes. All skills (not just interactive: true) see this. * * Composition position: index 1 in scripts/resolvers/preamble.ts — after * generatePreambleBash (so _SESSION_ID / _BRANCH / _TEL env vars exist before * any plan-mode-aware telemetry) and before generateUpgradeCheck + onboarding * gates. See ceo-plan 2026-04-24 "remove vestigial plan-mode handshake" for * the full rationale. */ export function generatePlanModeInfo(_ctx: TemplateContext): string { return `## Plan Mode Safe Operations In plan mode, allowed because they inform the plan: \`$B\`, \`$D\`, \`codex exec\`/\`codex review\`, writes to \`~/.gstack/\`, writes to the plan file, and \`open\` for generated artifacts. ## Skill Invocation During Plan Mode If the user invokes a skill in plan mode, the skill takes precedence over generic plan mode behavior. **Treat the skill file as executable instructions, not reference.** Follow it step by step starting from Step 0; the first AskUserQuestion is the workflow entering plan mode, not a violation of it. AskUserQuestion (any variant — \`mcp__*__AskUserQuestion\` or native; see "AskUserQuestion Format → Tool resolution") satisfies plan mode's end-of-turn requirement. If no variant is callable, fall back to writing the decision brief into the plan file as a \`## Decisions to confirm\` section + ExitPlanMode — never silently auto-decide. At a STOP point, stop immediately. Do not continue the workflow or call ExitPlanMode there. Commands marked "PLAN MODE EXCEPTION — ALWAYS RUN" execute. Call ExitPlanMode only after the skill workflow completes, or if the user tells you to cancel the skill or leave plan mode.`; } export function generateCompletionStatus(ctx: TemplateContext): string { return `## Completion Status Protocol When completing a skill workflow, report status using one of: - **DONE** — completed with evidence. - **DONE_WITH_CONCERNS** — completed, but list concerns. - **BLOCKED** — cannot proceed; state blocker and what was tried. - **NEEDS_CONTEXT** — missing info; state exactly what is needed. Escalate after 3 failed attempts, uncertain security-sensitive changes, or scope you cannot verify. Format: \`STATUS\`, \`REASON\`, \`ATTEMPTED\`, \`RECOMMENDATION\`. ## Operational Self-Improvement Before completing, if you discovered a durable project quirk or command fix that would save 5+ minutes next time, log it: \`\`\`bash ${ctx.paths.binDir}/gstack-learnings-log '{"skill":"SKILL_NAME","type":"operational","key":"SHORT_KEY","insight":"DESCRIPTION","confidence":N,"source":"observed"}' \`\`\` Do not log obvious facts or one-time transient errors. ## Telemetry (run last) After workflow completion, log telemetry. Use skill \`name:\` from frontmatter. OUTCOME is success/error/abort/unknown. **PLAN MODE EXCEPTION — ALWAYS RUN:** This command writes telemetry to \`~/.gstack/analytics/\`, matching preamble analytics writes. Run this bash: \`\`\`bash _TEL_END=$(date +%s) _TEL_DUR=$(( _TEL_END - _TEL_START )) rm -f ~/.gstack/analytics/.pending-"$_SESSION_ID" 2>/dev/null || true # Session timeline: record skill completion (local-only, never sent anywhere) ~/.claude/skills/gstack/bin/gstack-timeline-log '{"skill":"SKILL_NAME","event":"completed","branch":"'$(git branch --show-current 2>/dev/null || echo unknown)'","outcome":"OUTCOME","duration_s":"'"$_TEL_DUR"'","session":"'"$_SESSION_ID"'"}' 2>/dev/null || true # Local analytics (gated on telemetry setting) if [ "$_TEL" != "off" ]; then echo '{"skill":"SKILL_NAME","duration_s":"'"$_TEL_DUR"'","outcome":"OUTCOME","browse":"USED_BROWSE","session":"'"$_SESSION_ID"'","ts":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'"}' >> ~/.gstack/analytics/skill-usage.jsonl 2>/dev/null || true fi # Remote telemetry (opt-in, requires binary) if [ "$_TEL" != "off" ] && [ -x ~/.claude/skills/gstack/bin/gstack-telemetry-log ]; then ~/.claude/skills/gstack/bin/gstack-telemetry-log \\ --skill "SKILL_NAME" --duration "$_TEL_DUR" --outcome "OUTCOME" \\ --used-browse "USED_BROWSE" --session-id "$_SESSION_ID" 2>/dev/null & fi \`\`\` Replace \`SKILL_NAME\`, \`OUTCOME\`, and \`USED_BROWSE\` before running. ## Plan Status Footer In plan mode before ExitPlanMode: if the plan file lacks \`## GSTACK REVIEW REPORT\`, run \`~/.claude/skills/gstack/bin/gstack-review-read\` and append the standard runs/status/findings table. With \`NO_REVIEWS\` or empty, append a 5-row placeholder with verdict "NO REVIEWS YET — run \`/autoplan\`". If a richer report exists, skip. PLAN MODE EXCEPTION — always allowed (it's the plan file).`; }