mirror of
https://github.com/garrytan/gstack.git
synced 2026-05-17 17:51:27 +08:00
* feat: EXIT PLAN MODE GATE for plan-mode review skills Add a terminal BLOCKING checklist that verifies the plan file ends with `## GSTACK REVIEW REPORT` before ExitPlanMode is called. Lives at EOF of all four plan-* review skills (eng/ceo/design/devex) and inside codex Step 2A. Tones down the preamble's "Plan Status Footer" to a neutral forward reference so review-report rules don't bleed into operational skills (/ship /qa /review). Single source of truth: `generateExitPlanModeGate` in scripts/resolvers/review.ts, registered as EXIT_PLAN_MODE_GATE in scripts/resolvers/index.ts. New test in test/gen-skill-docs.test.ts strips fenced code blocks before matching `## ` headings and asserts the gate is the terminal heading in all four plan-* review SKILL.md files. Codex's SKILL.md uses toContain (mid-file by design — Step 2B/2C are not plan-touching modes). Decisions locked via /plan-eng-review + /codex outside-voice: - D1=A: 4 plan-* reviews + codex (autoplan, office-hours deferred) - D2=B → D4=A: tone preamble down to neutral forward reference - D3=A: add automated test in test/gen-skill-docs.test.ts - D5=B: keep codex gate inside Step 2A (mid-file acceptable per gate self-gating) Codex pre-merge findings folded in: line numbers obsolete (use EOF), test regex must strip fences, fresh skill list (not stale REVIEW_SKILLS constant), gate check 4 short-circuits when no plan file in context. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore: bump version and changelog (v1.39.1.0) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: package.json build script uses subshells, not brace groups The three `{ git rev-parse HEAD 2>/dev/null || true; } > path/.version` brace groups in the build script regressed when v1.38.0.0 merged into this branch (resolved with --ours during conflict). Bun on Windows can't parse brace groups in this position; the v1.38.0.0 invariant requires `(...)` subshells. Windows CI test `package.json build scripts — POSIX shell compat` caught it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
86 lines
5.2 KiB
TypeScript
86 lines
5.2 KiB
TypeScript
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, the skill is BLOCKED — stop and report \`BLOCKED — AskUserQuestion unavailable\` per the AskUserQuestion Format rule. 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
|
|
|
|
Skills 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. Writing the plan file is the one edit allowed in plan mode.`;
|
|
}
|