diff --git a/scripts/gen-skill-docs.ts b/scripts/gen-skill-docs.ts index 3ecd9d56..0fb0fc63 100644 --- a/scripts/gen-skill-docs.ts +++ b/scripts/gen-skill-docs.ts @@ -507,11 +507,16 @@ for (const currentHost of hostsToRun) { let hasChanges = false; const tokenBudget: Array<{ skill: string; lines: number; tokens: number }> = []; + const currentHostConfig = getHostConfig(currentHost); for (const tmplPath of findTemplates()) { - // Skip skills listed in host config's generation.skipSkills - const currentHostConfig = getHostConfig(currentHost); + const dir = path.basename(path.dirname(tmplPath)); + + // includeSkills allowlist (union logic: include minus skip) + if (currentHostConfig.generation.includeSkills?.length) { + if (!currentHostConfig.generation.includeSkills.includes(dir)) continue; + } + // skipSkills denylist (subtracts from includeSkills or full set) if (currentHostConfig.generation.skipSkills?.length) { - const dir = path.basename(path.dirname(tmplPath)); if (currentHostConfig.generation.skipSkills.includes(dir)) continue; } @@ -539,6 +544,44 @@ for (const currentHost of hostsToRun) { tokenBudget.push({ skill: relOutput, lines, tokens }); } + // Generate gstack-lite and gstack-full for OpenClaw host + if (currentHost === 'openclaw' && !DRY_RUN) { + const openclawDir = path.join(ROOT, 'openclaw'); + if (!fs.existsSync(openclawDir)) fs.mkdirSync(openclawDir, { recursive: true }); + + const gstackLite = `# gstack-lite Planning Discipline + +Injected by Wintermute into spawned Claude Code sessions. Append to existing CLAUDE.md. + +## Planning Discipline +1. Read every file you will modify. Understand existing patterns first. +2. Before writing code, state your plan: what, why, which files, test case, risk. +3. When ambiguous, prefer: completeness over shortcuts, existing patterns over new ones, + reversible choices over irreversible ones, safe defaults over clever ones. +4. Self-review your changes before reporting done. Check for: missed files, broken + imports, untested paths, style inconsistencies. +5. Report when done: what shipped, what decisions you made, anything uncertain. +`; + fs.writeFileSync(path.join(openclawDir, 'gstack-lite-CLAUDE.md'), gstackLite); + console.log('GENERATED: openclaw/gstack-lite-CLAUDE.md'); + + const gstackFull = `# gstack-full Pipeline + +Injected by Wintermute for complete feature builds. Append to existing CLAUDE.md. + +## Full Pipeline +1. Read CLAUDE.md and understand the project context. +2. Run /autoplan to review your approach (CEO + eng + design review pipeline). +3. Implement the approved plan. Follow the planning discipline above. +4. Run /ship to create a PR with tests, changelog, and version bump. +5. Report back: PR URL, what shipped, decisions made, anything uncertain. + +Do not ask for human input until the PR is ready for review. +`; + fs.writeFileSync(path.join(openclawDir, 'gstack-full-CLAUDE.md'), gstackFull); + console.log('GENERATED: openclaw/gstack-full-CLAUDE.md'); + } + if (DRY_RUN && hasChanges) { console.error(`\nGenerated SKILL.md files are stale (${currentHost} host). Run: bun run gen:skill-docs --host ${currentHost}`); if (HOST_ARG_VAL !== 'all') process.exit(1); diff --git a/scripts/resolvers/preamble.ts b/scripts/resolvers/preamble.ts index 56989bef..17f8cfce 100644 --- a/scripts/resolvers/preamble.ts +++ b/scripts/resolvers/preamble.ts @@ -89,6 +89,8 @@ fi _ROUTING_DECLINED=$(${ctx.paths.binDir}/gstack-config get routing_declined 2>/dev/null || echo "false") echo "HAS_ROUTING: $_HAS_ROUTING" echo "ROUTING_DECLINED: $_ROUTING_DECLINED" +# Detect spawned session (OpenClaw or other orchestrator) +[ -n "$OPENCLAW_SESSION" ] && echo "SPAWNED_SESSION: true" || true \`\`\``; } @@ -226,6 +228,15 @@ Say "No problem. You can add routing rules later by running \`gstack-config set This only happens once per project. If \`HAS_ROUTING\` is \`yes\` or \`ROUTING_DECLINED\` is \`true\`, skip this entirely.`; } +function generateSpawnedSessionCheck(): string { + return `If \`SPAWNED_SESSION\` is \`"true"\`, you are running inside a session spawned by an +AI orchestrator (e.g., OpenClaw/Wintermute). In spawned sessions: +- Do NOT use AskUserQuestion for interactive prompts. Auto-choose the recommended option. +- Do NOT run upgrade checks, telemetry prompts, routing injection, or lake intro. +- Focus on completing the task and reporting results via prose output. +- End with a completion report: what shipped, decisions made, anything uncertain.`; +} + function generateAskUserFormat(_ctx: TemplateContext): string { return `## AskUserQuestion Format @@ -675,6 +686,7 @@ export function generatePreamble(ctx: TemplateContext): string { generateTelemetryPrompt(ctx), generateProactivePrompt(ctx), generateRoutingInjection(ctx), + generateSpawnedSessionCheck(), generateVoiceDirective(tier), ...(tier >= 2 ? [generateContextRecovery(ctx), generateAskUserFormat(ctx), generateCompletenessSection()] : []), ...(tier >= 3 ? [generateRepoModeSection(), generateSearchBeforeBuildingSection(ctx)] : []), diff --git a/setup b/setup index 19adc73d..fd298140 100755 --- a/setup +++ b/setup @@ -46,7 +46,19 @@ done case "$HOST" in claude|codex|kiro|factory|auto) ;; - *) echo "Unknown --host value: $HOST (expected claude, codex, kiro, factory, or auto)" >&2; exit 1 ;; + openclaw) + echo "" + echo "OpenClaw integration uses a different model — OpenClaw spawns Claude Code" + echo "sessions natively via ACP. gstack provides methodology artifacts, not a" + echo "full skill installation." + echo "" + echo "To integrate gstack with OpenClaw:" + echo " 1. Tell your OpenClaw agent: 'install gstack for openclaw'" + echo " 2. Or generate artifacts: bun run gen:skill-docs --host openclaw" + echo " 3. See docs/OPENCLAW.md for the full architecture" + echo "" + exit 0 ;; + *) echo "Unknown --host value: $HOST (expected claude, codex, kiro, factory, openclaw, or auto)" >&2; exit 1 ;; esac # ─── Resolve skill prefix preference ─────────────────────────