diff --git a/README.md b/README.md index 2509cd6..6aed503 100644 --- a/README.md +++ b/README.md @@ -47,15 +47,17 @@ python3 cn86-sms-keyword-verification/scripts/lubansms_keyword_cli.py demo --key - 用 `CC Switch` 管理 `GPT-5.4 Pro xhigh`、`Claude Opus 4.6` 和 fallback 模型的内部开发流程 - 从 `新项目脚手架 / 老项目补 Spec / Spec-Code Gap Closure` 三条主路径里选一条执行 -- 需要把 `CLAUDE.md`、`ANALYSIS.md`、`TODO.yaml`、`SPECS/`、handoff、acceptance checklist 一次性种到目标项目 +- 需要把 `CLAUDE.md`、`AGENTS.md`、`ANALYSIS.md`、`TODO.yaml`、`SPECS/`、handoff、acceptance checklist 一次性种到目标项目 运行示例: ```bash python3 cc-switch-dev-workflow/scripts/inspect_cc_switch_runtime.py --format markdown -python3 cc-switch-dev-workflow/scripts/bootstrap_workflow_workspace.py \ +python3 cc-switch-dev-workflow/scripts/init_workflow_repo.py \ --target-dir /absolute/path/to/project \ - --playbook new-project-from-scaffold + --playbook new-project-from-scaffold \ + --project-name "Project Name" \ + --goal "One-sentence project goal" ``` ## 维护建议 diff --git a/cc-switch-dev-workflow/SKILL.md b/cc-switch-dev-workflow/SKILL.md index 025309c..c820989 100644 --- a/cc-switch-dev-workflow/SKILL.md +++ b/cc-switch-dev-workflow/SKILL.md @@ -31,7 +31,17 @@ tags: [cc-switch, workflow, spec-driven, multi-agent, hono, nextjs, typescript] python3 scripts/inspect_cc_switch_runtime.py --format markdown ``` -3. 如果用户明确要初始化项目目录,用: +3. 如果用户明确要一键初始化目标 repo,并直接生成首轮 `CLAUDE.md / AGENTS.md / ANALYSIS.md / TODO.yaml / SPECS/`,优先用: + +```bash +python3 scripts/init_workflow_repo.py \ + --target-dir /absolute/path/to/project \ + --playbook new-project-from-scaffold \ + --project-name "Project Name" \ + --goal "One-sentence goal" +``` + +4. 如果只需要轻量骨架和模板拷贝,再用: ```bash python3 scripts/bootstrap_workflow_workspace.py \ @@ -39,7 +49,7 @@ python3 scripts/bootstrap_workflow_workspace.py \ --playbook new-project-from-scaffold ``` -4. 只把高密度产物传给下一阶段,禁止把整段原始聊天直接 handoff 给下一个 agent。 +5. 只把高密度产物传给下一阶段,禁止把整段原始聊天直接 handoff 给下一个 agent。 ## Default Operating Rules @@ -82,6 +92,7 @@ python3 scripts/bootstrap_workflow_workspace.py \ 在大多数项目里,至少会出现这些产物: - `CLAUDE.md` +- `AGENTS.md` - `ANALYSIS.md` - `TODO.yaml` - `SPECS/*.md` diff --git a/cc-switch-dev-workflow/agents/openai.yaml b/cc-switch-dev-workflow/agents/openai.yaml index 07f3577..fcc95a3 100644 --- a/cc-switch-dev-workflow/agents/openai.yaml +++ b/cc-switch-dev-workflow/agents/openai.yaml @@ -1,4 +1,4 @@ interface: display_name: "CC Switch Dev Workflow" short_description: "Run the internal spec-driven multi-agent delivery workflow" - default_prompt: "Use $cc-switch-dev-workflow to choose the right playbook, align against my local CC Switch config, and run the 7-stage software delivery workflow." + default_prompt: "Use $cc-switch-dev-workflow to choose the right playbook, align against my local CC Switch config, and initialize my repo with CLAUDE.md, AGENTS.md, ANALYSIS.md, TODO.yaml, and first-round specs." diff --git a/cc-switch-dev-workflow/references/knowledge-base/README.md b/cc-switch-dev-workflow/references/knowledge-base/README.md index b6fdf7a..b3ea293 100644 --- a/cc-switch-dev-workflow/references/knowledge-base/README.md +++ b/cc-switch-dev-workflow/references/knowledge-base/README.md @@ -43,7 +43,7 @@ 1. 从 [`sources/README.md`](./sources/README.md) 确认规则来源和冲突取舍。 2. 从 [`playbooks/`](./playbooks/) 选择最贴近当前项目的执行路径。 3. 按 [`workflows/README.md`](./workflows/README.md) 所列阶段运行,每阶段只保留高密度产物进入下一阶段。 -4. 统一使用 [`templates/README.md`](./templates/README.md) 中的模板生成 `CLAUDE.md`、`ANALYSIS.md`、`TODO.yaml`、Spec 和 handoff 文档。 +4. 统一使用 [`templates/README.md`](./templates/README.md) 中的模板生成 `CLAUDE.md`、`AGENTS.md`、`ANALYSIS.md`、`TODO.yaml`、Spec 和 handoff 文档。 5. 发生技术栈偏离、模型切换、来源冲突时,先写入 [`decisions/README.md`](./decisions/README.md) 中的 ADR,再继续执行。 ## Exit Criteria @@ -58,6 +58,7 @@ ## Related Templates - [`templates/claude-md-template.md`](./templates/claude-md-template.md) +- [`templates/agents-md-template.md`](./templates/agents-md-template.md) - [`templates/analysis-template.md`](./templates/analysis-template.md) - [`templates/todo-yaml-template.md`](./templates/todo-yaml-template.md) - [`templates/agent-handoff-template.md`](./templates/agent-handoff-template.md) @@ -80,7 +81,7 @@ | 阶段 | 目标 | 核心产物 | 默认主模型 | 默认辅模型 | |---|---|---|---|---| -| 0 Setup | 项目初始化与规则对齐 | `.meetings/`, `.ralphy/config.yaml`, `CLAUDE.md` | `GPT-5.4 Pro xhigh` | `Claude Opus 4.6` | +| 0 Setup | 项目初始化与规则对齐 | `.meetings/`, `.ralphy/config.yaml`, `CLAUDE.md`, `AGENTS.md` | `GPT-5.4 Pro xhigh` | `Claude Opus 4.6` | | 1 Research | 形成调研结论 | `ANALYSIS.md`, `TODO.yaml`, `.research/*.md` | `GPT-5.4 Pro xhigh` | `Claude Opus 4.6` | | 2 Spec | 形成可实施规范 | `SPECS/*.md` | `GPT-5.4 Pro xhigh` | `Claude Opus 4.6` | | 3 Code | 按 Spec 实施代码 | `.plans/*.md`, 代码与测试 | `GPT-5.4 Pro xhigh` | `Claude Opus 4.6` | diff --git a/cc-switch-dev-workflow/references/knowledge-base/playbooks/existing-project-spec-backfill-and-refactor.md b/cc-switch-dev-workflow/references/knowledge-base/playbooks/existing-project-spec-backfill-and-refactor.md index 686821c..37e5ba9 100644 --- a/cc-switch-dev-workflow/references/knowledge-base/playbooks/existing-project-spec-backfill-and-refactor.md +++ b/cc-switch-dev-workflow/references/knowledge-base/playbooks/existing-project-spec-backfill-and-refactor.md @@ -16,6 +16,7 @@ ## Outputs - 补齐后的 `CLAUDE.md` +- 补齐后的 `AGENTS.md` - `.research/*.md` - `SPECS/*.md` - 重构和补齐计划 @@ -74,7 +75,7 @@ ``` ## Stage Deliverables -- Setup:补写 `CLAUDE.md`、确认轨道与边界 +- Setup:补写 `CLAUDE.md` 与 `AGENTS.md`、确认轨道与边界 - Research:反向整理 `.research/*.md` - Spec:形成 `SPECS/*.md` 并完成人工审核 - Alignment:对齐现有实现与 Spec @@ -82,6 +83,7 @@ ## Acceptance Checklist - 老项目已有清晰的 `CLAUDE.md` +- 老项目已有清晰的 `AGENTS.md` - `SPECS/*.md` 不是代码镜像,而是系统契约 - Alignment 后没有高优先级缺口残留 - Refinement 后的结构与命名更清晰,不是更复杂 diff --git a/cc-switch-dev-workflow/references/knowledge-base/playbooks/new-project-from-scaffold.md b/cc-switch-dev-workflow/references/knowledge-base/playbooks/new-project-from-scaffold.md index fdb14f3..ca6273b 100644 --- a/cc-switch-dev-workflow/references/knowledge-base/playbooks/new-project-from-scaffold.md +++ b/cc-switch-dev-workflow/references/knowledge-base/playbooks/new-project-from-scaffold.md @@ -16,6 +16,7 @@ ## Outputs - `CLAUDE.md` +- `AGENTS.md` - `.ralphy/config.yaml` - `.research/*.md` - `SPECS/*.md` @@ -77,7 +78,7 @@ ``` ## Stage Deliverables -- Setup:`.meetings/`, `.ralphy/config.yaml`, `CLAUDE.md` +- Setup:`.meetings/`, `.ralphy/config.yaml`, `CLAUDE.md`, `AGENTS.md` - Research:`ANALYSIS.md`, `TODO.yaml`, `.research/*.md` - Spec:`SPECS/*.md`, 审查结论, 人工审核结论 - Code:`.plans/*.md`, 代码与测试 @@ -86,5 +87,6 @@ ## Acceptance Checklist - 技术轨道只有一个主路线 - `CLAUDE.md` 已固定规则与禁用项 +- `AGENTS.md` 已为 Codex 固定读文件顺序、边界和升级点 - `SPECS/*.md` 已通过人工审核 - 第一轮代码实施与 Alignment 已经形成闭环 diff --git a/cc-switch-dev-workflow/references/knowledge-base/templates/README.md b/cc-switch-dev-workflow/references/knowledge-base/templates/README.md index 141e7d2..fdf2104 100644 --- a/cc-switch-dev-workflow/references/knowledge-base/templates/README.md +++ b/cc-switch-dev-workflow/references/knowledge-base/templates/README.md @@ -4,6 +4,7 @@ 提供知识库中的标准模板集合,统一输入输出格式,降低 agent 自由发挥空间。 ## When to Use +- 新建 `AGENTS.md` - 新建 `CLAUDE.md` - 新建 `ANALYSIS.md` - 新建 `TODO.yaml` @@ -44,6 +45,7 @@ | 模板 | 用途 | |---|---| +| [`agents-md-template.md`](./agents-md-template.md) | Codex 项目执行说明 | | [`claude-md-template.md`](./claude-md-template.md) | 项目执行说明 | | [`analysis-template.md`](./analysis-template.md) | 阶段分析报告 | | [`todo-yaml-template.md`](./todo-yaml-template.md) | 任务清单 | diff --git a/cc-switch-dev-workflow/references/knowledge-base/templates/agents-md-template.md b/cc-switch-dev-workflow/references/knowledge-base/templates/agents-md-template.md new file mode 100644 index 0000000..6321eb2 --- /dev/null +++ b/cc-switch-dev-workflow/references/knowledge-base/templates/agents-md-template.md @@ -0,0 +1,97 @@ +# Template: AGENTS.md + +## Purpose +为 Codex 提供项目级执行约束,让实现、审查和交接都遵守同一套边界。 + +## When to Use +- Setup 阶段 +- 项目需要同时支持 `Claude Code` 和 `Codex` 时 +- 需要给 Codex 一个稳定的项目执行入口时 + +## Inputs +- 清洗后的会议纪要 +- 技术轨道决策 +- 项目目标与边界 +- 已确认的 workflow / playbook + +## Outputs +- `AGENTS.md` + +## Primary Agent/Model +`GPT-5.4 Pro xhigh` + +## Secondary Agent/Model +`Claude Opus 4.6` + +## Required Skills +- `agent-md-writing` +- 若未安装,按 `claude-md-template.md` 的约束等价改写 + +## Steps +1. 用下方模板生成草案。 +2. 把 `CLAUDE.md` 中的稳定规则压缩为 Codex 可直接执行的指令。 +3. 明确 Read First 文件、禁止项、审批点和 handoff 方式。 + +## Exit Criteria +- Codex 在只读 `AGENTS.md` 的情况下,也能知道项目目标、技术边界、流程门禁和升级点 + +## Failure Recovery +- 若 `AGENTS.md` 只是重复愿景、不写边界与门禁,回到模板重写 + +## Related Templates +- [`claude-md-template.md`](./claude-md-template.md) +- [`agent-handoff-template.md`](./agent-handoff-template.md) + +## Template +```markdown +# AGENTS.md + +## Mission +- Project: +- Goal: +- Audience: +- In Scope: +- Out of Scope: + +## Read First +- `CLAUDE.md` +- `ANALYSIS.md` +- `TODO.yaml` +- Selected playbook: +- Key specs: + +## Workflow Contract +- Follow stages: +- Current playbook: +- Reset points: +- Human approval gates: + +## Stack Guardrails +- Track: +- Language: +- UI: +- Styling: +- Auth: +- Data Fetching: +- Router: +- Service Layer: +- ORM: +- Database: + +## Model Routing +- Primary planning and implementation: +- Secondary review: +- Fallback: + +## Boundaries +- Do not introduce: +- Do not modify: +- Do not bypass: +- Ask before: + +## Execution Defaults +- Preferred testing posture: +- Refactor rhythm: +- Handoff format: +- Done means: +``` diff --git a/cc-switch-dev-workflow/references/knowledge-base/workflows/stage-0-setup.md b/cc-switch-dev-workflow/references/knowledge-base/workflows/stage-0-setup.md index f15d36c..b2b895d 100644 --- a/cc-switch-dev-workflow/references/knowledge-base/workflows/stage-0-setup.md +++ b/cc-switch-dev-workflow/references/knowledge-base/workflows/stage-0-setup.md @@ -18,6 +18,7 @@ - 清洗后的 `.meetings/` - `.ralphy/config.yaml` - `CLAUDE.md` +- `AGENTS.md` - 已确认的技术轨道 ## Primary Agent/Model @@ -34,11 +35,11 @@ 1. 清洗会议纪要,只保留项目相关决策。 2. 选择 `Next.js 全栈` 或 `Hono + React SSR/TanStack` 轨道。 3. 初始化 `.ralphy/config.yaml`。 -4. 生成 `CLAUDE.md`,写明哲学、白名单、边界、测试与技能要求。 +4. 生成 `CLAUDE.md` 和 `AGENTS.md`,写明哲学、白名单、边界、测试与技能要求。 5. 产出 Setup handoff,供 Research 或 Spec 阶段读取。 ## Exit Criteria -- `CLAUDE.md` 存在且可直接约束 agent +- `CLAUDE.md` 和 `AGENTS.md` 存在且可直接约束 agent - 技术轨道已固定 - 原始会议纪要不再被直接拿去执行 @@ -48,6 +49,7 @@ ## Related Templates - [`../templates/claude-md-template.md`](../templates/claude-md-template.md) +- [`../templates/agents-md-template.md`](../templates/agents-md-template.md) - [`../templates/agent-handoff-template.md`](../templates/agent-handoff-template.md) ## Stable Knowledge Vs Runtime Context diff --git a/cc-switch-dev-workflow/scripts/bootstrap_workflow_workspace.py b/cc-switch-dev-workflow/scripts/bootstrap_workflow_workspace.py index 1c1c427..c664274 100755 --- a/cc-switch-dev-workflow/scripts/bootstrap_workflow_workspace.py +++ b/cc-switch-dev-workflow/scripts/bootstrap_workflow_workspace.py @@ -25,19 +25,45 @@ def copy_file(source: Path, target: Path, force: bool) -> str: return f"write {target}" -def main() -> int: - parser = argparse.ArgumentParser(description="Bootstrap a repo with the CC Switch workflow files.") - parser.add_argument("--target-dir", required=True, help="Absolute or relative project directory to seed.") - parser.add_argument("--playbook", required=True, choices=sorted(PLAYBOOK_FILES)) - parser.add_argument("--force", action="store_true", help="Overwrite existing files.") - args = parser.parse_args() +def write_text(target: Path, content: str, force: bool) -> str: + if target.exists() and not force: + return f"skip {target}" + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(content.rstrip() + "\n", encoding="utf-8") + return f"write {target}" + +def build_minimal_ralphy_config(playbook: str) -> str: + return f"""project: + workflow: cc-switch-dev-workflow + playbook: {playbook} + +commands: + test: pnpm test + lint: pnpm lint + build: pnpm build + typecheck: pnpm exec tsc --noEmit + +rules: + - Read CLAUDE.md, AGENTS.md, ANALYSIS.md, TODO.yaml, and .workflow/selected-playbook.md before implementation. + - Keep one primary stack track; do not introduce a second router, auth, ORM, or styling system. + - Keep task titles self-contained with path and reference. + - Use handoff summaries instead of forwarding raw chat history. +""" + + +def seed_workspace( + target_dir: Path, + playbook: str, + force: bool, + include_core_docs: bool = True, + include_ralphy_config: bool = True, +) -> list[str]: skill_root = Path(__file__).resolve().parent.parent knowledge_base = skill_root / "references" / "knowledge-base" templates_root = knowledge_base / "templates" playbooks_root = knowledge_base / "playbooks" workflows_root = knowledge_base / "workflows" - target_dir = Path(args.target_dir).expanduser().resolve() required_dirs = [ target_dir / ".meetings", @@ -47,27 +73,50 @@ def main() -> int: target_dir / ".acceptance", target_dir / ".workflow", target_dir / ".decisions", + target_dir / ".ralphy", target_dir / "SPECS", ] for directory in required_dirs: directory.mkdir(parents=True, exist_ok=True) - writes = [] + writes: list[str] = [] template_map = { - templates_root / "claude-md-template.md": target_dir / "CLAUDE.md", - templates_root / "analysis-template.md": target_dir / "ANALYSIS.md", - templates_root / "todo-yaml-template.md": target_dir / "TODO.yaml", templates_root / "spec-template.md": target_dir / "SPECS" / "_template.md", templates_root / "tdd-plan-template.md": target_dir / ".plans" / "_tdd-plan-template.md", templates_root / "agent-handoff-template.md": target_dir / ".handoff" / "_agent-handoff-template.md", templates_root / "acceptance-checklist-template.md": target_dir / ".acceptance" / "_acceptance-checklist.md", - playbooks_root / PLAYBOOK_FILES[args.playbook]: target_dir / ".workflow" / "selected-playbook.md", + playbooks_root / PLAYBOOK_FILES[playbook]: target_dir / ".workflow" / "selected-playbook.md", workflows_root / "README.md": target_dir / ".workflow" / "stage-index.md", knowledge_base / "README.md": target_dir / ".workflow" / "knowledge-base-overview.md", } + if include_core_docs: + template_map.update( + { + templates_root / "claude-md-template.md": target_dir / "CLAUDE.md", + templates_root / "agents-md-template.md": target_dir / "AGENTS.md", + templates_root / "analysis-template.md": target_dir / "ANALYSIS.md", + templates_root / "todo-yaml-template.md": target_dir / "TODO.yaml", + } + ) + for source, target in template_map.items(): - writes.append(copy_file(source, target, args.force)) + writes.append(copy_file(source, target, force)) + + if include_ralphy_config: + writes.append(write_text(target_dir / ".ralphy" / "config.yaml", build_minimal_ralphy_config(playbook), force)) + return writes + + +def main() -> int: + parser = argparse.ArgumentParser(description="Bootstrap a repo with the CC Switch workflow files.") + parser.add_argument("--target-dir", required=True, help="Absolute or relative project directory to seed.") + parser.add_argument("--playbook", required=True, choices=sorted(PLAYBOOK_FILES)) + parser.add_argument("--force", action="store_true", help="Overwrite existing files.") + args = parser.parse_args() + + target_dir = Path(args.target_dir).expanduser().resolve() + writes = seed_workspace(target_dir, args.playbook, args.force) manifest = { "skill": "cc-switch-dev-workflow", diff --git a/cc-switch-dev-workflow/scripts/init_workflow_repo.py b/cc-switch-dev-workflow/scripts/init_workflow_repo.py new file mode 100755 index 0000000..5908d67 --- /dev/null +++ b/cc-switch-dev-workflow/scripts/init_workflow_repo.py @@ -0,0 +1,692 @@ +#!/usr/bin/env python3 +"""Initialize a target repo with first-round workflow artifacts for Claude and Codex.""" + +from __future__ import annotations + +import argparse +import json +import re +from datetime import datetime, timezone +from pathlib import Path +from typing import Any + +from bootstrap_workflow_workspace import PLAYBOOK_FILES, seed_workspace + +try: + from inspect_cc_switch_runtime import collect_summary +except ImportError: # pragma: no cover + collect_summary = None + + +TRACKS: dict[str, dict[str, str]] = { + "hono-react-ssr-tanstack": { + "label": "Hono + React SSR/TanStack", + "language": "TypeScript", + "ui": "React", + "styling": "Tailwind CSS + shadcn/ui", + "auth": "Better Auth", + "data_fetching": "TanStack Query", + "router": "TanStack Router", + "service_layer": "Hono", + "orm": "Drizzle", + "database": "PostgreSQL", + "reason": "default tie-break track for clear boundaries and better agent task slicing", + }, + "nextjs-fullstack": { + "label": "Next.js Full Stack", + "language": "TypeScript", + "ui": "React", + "styling": "Tailwind CSS + shadcn/ui", + "auth": "Better Auth", + "data_fetching": "TanStack Query where needed", + "router": "Next.js App Router", + "service_layer": "Next.js route handlers / server actions", + "orm": "Drizzle", + "database": "PostgreSQL", + "reason": "single-framework delivery track when page and service logic should stay tightly integrated", + }, +} + +PLAYBOOK_CONTEXT: dict[str, dict[str, Any]] = { + "new-project-from-scaffold": { + "label": "New Project From Scaffold", + "spec_file": "000-foundation-and-bootstrap-constraints.md", + "goal_hint": "Bootstrap a new repo with one approved stack track, one workflow contract, and first-round planning artifacts.", + "default_in_scope": [ + "Fix the project on one approved stack track", + "Generate first-round workflow documents and handoff", + "Prepare the repo for Research -> Spec -> Code", + ], + "default_out_of_scope": [ + "Feature-complete product implementation", + "Adding a second framework track", + "Ad-hoc exceptions without ADR approval", + ], + }, + "existing-project-spec-backfill-and-refactor": { + "label": "Existing Project Spec Backfill And Refactor", + "spec_file": "000-foundation-and-backfill-contract.md", + "goal_hint": "Stabilize an existing codebase by backfilling rules, workflow contract, and the first spec/refactor queue.", + "default_in_scope": [ + "Baseline the current repo and write first-round workflow docs", + "Backfill initial spec contract and alignment backlog", + "Prepare refactor work under an explicit rule layer", + ], + "default_out_of_scope": [ + "Large implementation rewrites before baseline review", + "Unbounded refactors without spec backing", + "Running two primary stack tracks in parallel", + ], + }, + "spec-code-alignment-gap-closure": { + "label": "Spec-Code Alignment Gap Closure", + "spec_file": "000-gap-closure-working-contract.md", + "goal_hint": "Re-establish spec/code consistency with a first-round gap-analysis contract and execution queue.", + "default_in_scope": [ + "Classify current spec/code gaps", + "Generate first-round alignment docs and tasks", + "Prepare implementation and review gates for closure work", + ], + "default_out_of_scope": [ + "Rewriting the product without gap evidence", + "Changing accepted specs without review", + "Treating elegance as a substitute for compliance", + ], + }, +} + + +def parse_list(values: list[str] | None) -> list[str]: + if not values: + return [] + result: list[str] = [] + for raw in values: + parts = [part.strip() for part in raw.split(",")] + result.extend(part for part in parts if part) + return result + + +def slugify(text: str) -> str: + lowered = text.strip().lower() + slug = re.sub(r"[^a-z0-9]+", "-", lowered) + return slug.strip("-") or "project" + + +def load_package_json(target_dir: Path) -> dict[str, Any]: + package_json = target_dir / "package.json" + if not package_json.exists(): + return {} + try: + data = json.loads(package_json.read_text(encoding="utf-8")) + except json.JSONDecodeError: + return {} + return data if isinstance(data, dict) else {} + + +def detect_track(target_dir: Path, playbook: str) -> tuple[str, str]: + package_data = load_package_json(target_dir) + dependencies = set() + for key in ("dependencies", "devDependencies"): + block = package_data.get(key, {}) + if isinstance(block, dict): + dependencies.update(block.keys()) + + if "hono" in dependencies or "@tanstack/react-router" in dependencies: + return "hono-react-ssr-tanstack", "detected from package.json dependencies" + + if "next" in dependencies or any((target_dir / name).exists() for name in ("next.config.js", "next.config.mjs", "next.config.ts")): + return "nextjs-fullstack", "detected from package.json or next.config.*" + + if playbook == "new-project-from-scaffold": + return "hono-react-ssr-tanstack", "default tie-break from framework decision matrix" + + return "hono-react-ssr-tanstack", "default target track pending setup confirmation" + + +def pick_track(target_dir: Path, playbook: str, requested_track: str) -> tuple[str, str]: + if requested_track != "auto": + return requested_track, "explicitly requested" + return detect_track(target_dir, playbook) + + +def write_text(target: Path, content: str, force: bool) -> str: + if target.exists() and not force: + return f"skip {target}" + target.parent.mkdir(parents=True, exist_ok=True) + target.write_text(content.rstrip() + "\n", encoding="utf-8") + return f"write {target}" + + +def bullets(items: list[str], fallback: str) -> str: + rows = items or [fallback] + return "\n".join(f"- {item}" for item in rows) + + +def runtime_model_line(runtime: dict[str, Any]) -> tuple[str, str, str]: + current_providers = runtime.get("current_providers", {}) + codex = current_providers.get("codex") or {} + claude = current_providers.get("claude") or {} + primary = ( + f"GPT-5.4 Pro xhigh via Codex provider {codex.get('name', 'n/a')} " + f"({codex.get('endpoint_host', 'n/a')})" + ) + secondary = ( + f"Claude Opus 4.6 via Claude provider {claude.get('name', 'n/a')} " + f"({claude.get('endpoint_host', 'n/a')})" + ) + fallback = "GLM / Kimi / Minimax only when primary models are blocked, then return through a compact handoff." + return primary, secondary, fallback + + +def render_claude(context: dict[str, Any]) -> str: + track = context["track_profile"] + return f"""# CLAUDE.md + +## Project +- Name: {context['project_name']} +- Goal: {context['goal']} +- Audience: {context['audience']} + +## Scope +### In Scope +{bullets(context['in_scope'], 'Confirm scope during Setup.')} + +### Out of Scope +{bullets(context['out_of_scope'], 'Confirm out-of-scope boundaries during Setup.')} + +## Design Philosophy +- KISS: Prefer the smallest design that can satisfy the current spec. +- DRY: Reuse validated patterns; do not fork architectural styles without approval. +- YAGNI: Do not build optional abstraction layers before the spec requires them. +- Type Safety First: Keep the application main path in TypeScript with strict checks. +- Preferred Architectural Shape: {track['label']} with one primary route, one auth path, one ORM path. + +## Default Stack +- Track: {track['label']} ({context['track_reason']}) +- Language: {track['language']} +- UI: {track['ui']} +- Styling: {track['styling']} +- Auth: {track['auth']} +- Data Fetching: {track['data_fetching']} +- Router: {track['router']} +- Service Layer: {track['service_layer']} +- ORM: {track['orm']} +- Database: {track['database']} + +## Model Routing +- Primary planning and implementation: {context['primary_model']} +- Secondary review: {context['secondary_model']} +- Fallback: {context['fallback_model']} + +## Hard Boundaries +- Do not introduce: Python/PHP on the product application main path, JavaScript-only defaults, or a second primary framework track. +- Do not modify: Approved specs, workflow gate definitions, or acceptance criteria without updating related docs and ADRs. +- Do not bypass: Spec review, gap analysis, handoff structure, or acceptance checks. +- Exceptions require: ADR in `.decisions/`, plus project owner and technical lead approval. + +## Process Requirements +- Follow stages: Setup -> Research -> Spec -> Code -> Alignment -> Refinement -> Acceptance. +- Source of truth: `CLAUDE.md`, `AGENTS.md`, `ANALYSIS.md`, `TODO.yaml`, `SPECS/`, `.workflow/selected-playbook.md`. +- Required review gates: Setup boundary confirmation, Spec review before Code, Acceptance review before release. +- Required testing posture: Run typecheck, lint, build, and targeted tests for changed behavior. +- Required refactor rhythm: Simplify after each implementation step and refactor after each batch. + +## Skills And Templates +- Preferred skills: `cc-switch-dev-workflow`, stage-specific planning/review/implementation skills, and the approved gap/refactor skills when applicable. +- Required templates: `templates/claude-md-template.md`, `templates/agents-md-template.md`, `templates/analysis-template.md`, `templates/todo-yaml-template.md`, `templates/spec-template.md`, `templates/agent-handoff-template.md`. + +## Definition Of Done +- Spec approved: The current spec is reviewable, testable, and accepted by the responsible human reviewer. +- Tests pass: Required checks pass or remaining failures are explicitly documented with owner approval. +- Alignment complete: No high-priority spec/code gaps remain hidden. +- Acceptance signed off: Final acceptance checklist is reviewed by a human owner. +""" + + +def render_agents(context: dict[str, Any]) -> str: + track = context["track_profile"] + return f"""# AGENTS.md + +## Mission +- Project: {context['project_name']} +- Goal: {context['goal']} +- Audience: {context['audience']} + +## Scope +### In Scope +{bullets(context['in_scope'], 'Confirm scope during Setup.')} + +### Out of Scope +{bullets(context['out_of_scope'], 'Confirm out-of-scope boundaries during Setup.')} + +## Read First +- `CLAUDE.md` +- `AGENTS.md` +- `ANALYSIS.md` +- `TODO.yaml` +- `.workflow/selected-playbook.md` +- `SPECS/{context['spec_file']}` + +## Workflow Contract +- Follow stages: Setup -> Research -> Spec -> Code -> Alignment -> Refinement -> Acceptance. +- Current playbook: {context['playbook_label']} +- Reset points: after Research -> Spec, after Spec review -> Code, and after any fallback detour. +- Human approval gates: stack exceptions, spec approval, and final acceptance. + +## Stack Guardrails +- Track: {track['label']} ({context['track_reason']}) +- Language: {track['language']} +- UI: {track['ui']} +- Styling: {track['styling']} +- Auth: {track['auth']} +- Data Fetching: {track['data_fetching']} +- Router: {track['router']} +- Service Layer: {track['service_layer']} +- ORM: {track['orm']} +- Database: {track['database']} + +## Model Routing +- Primary planning and implementation: {context['primary_model']} +- Secondary review: {context['secondary_model']} +- Fallback: {context['fallback_model']} + +## Boundaries +- Do not introduce: a second primary framework route, Python/PHP application code, or speculative abstractions. +- Do not modify: accepted specs or workflow gate docs without updating references and ADRs. +- Do not bypass: required testing, simplification/refactor checkpoints, or the handoff contract. +- Ask before: changing stack track, introducing exceptions, deleting validated files, or contradicting accepted specs. + +## Execution Defaults +- Preferred testing posture: typecheck + lint + build + changed-scope tests. +- Refactor rhythm: every implementation batch must be followed by simplify/refactor review. +- Handoff format: Goal / Scope / Non-Goals / Source of Truth / Constraints / Deliverable / Validation / Escalation. +- Done means: approved spec, documented plan, validated changes, and explicit acceptance state. +""" + + +def render_analysis(context: dict[str, Any]) -> str: + return f"""# ANALYSIS + +## Goal +- {context['goal']} + +## Scope +### Included +{bullets(context['in_scope'], 'Confirm scope during Setup.')} + +### Excluded +{bullets(context['out_of_scope'], 'Confirm out-of-scope boundaries during Setup.')} + +## Inputs +- Selected playbook: `.workflow/selected-playbook.md` +- Workflow overview: `.workflow/knowledge-base-overview.md` +- Stage index: `.workflow/stage-index.md` +- Runtime alignment source: `{context['runtime_source']}` + +## Findings +- Current track decision: {context['track_profile']['label']} ({context['track_reason']}). +- Current primary model path: {context['primary_model']}. +- Current secondary review path: {context['secondary_model']}. +- First-round repo artifacts should stabilize Setup and unlock Research/Spec without revisiting raw notes. + +## Priority +1. Confirm the single stack track and hard boundaries in `CLAUDE.md` and `AGENTS.md`. +2. Review and tighten `SPECS/{context['spec_file']}` so it becomes a real source of truth. +3. Expand `TODO.yaml` into executable plan/impl tasks before implementation starts. + +## Structure +- Workflow Foundation: stage contract, handoff contract, human gates. +- Stack And Model Policy: approved track, model routing, exception interface. +- Execution Queue: Research, Spec expansion, implementation planning, simplification/refactor checkpoints. + +## Risks +- The selected track may still need human confirmation if the repo baseline contradicts the default. +- Existing code or undocumented requirements may widen scope after initial Research. +- Fallback models must not become the default execution path. + +## Decisions Needed +- Confirm project goal wording and success boundary. +- Confirm stack track if the repo baseline differs from the default detection. +- Confirm the first product-domain spec that should follow the bootstrap spec. + +## Exit Criteria +- `CLAUDE.md`, `AGENTS.md`, `ANALYSIS.md`, `TODO.yaml`, `.ralphy/config.yaml`, and `SPECS/{context['spec_file']}` are present and internally consistent. +""" + + +def build_tasks(context: dict[str, Any]) -> list[tuple[str, str]]: + date_stamp = context["date_stamp"] + spec_path = f"SPECS/{context['spec_file']}" + if context["playbook"] == "new-project-from-scaffold": + return [ + ( + f"Plan repository foundation in .plans/{date_stamp}-foundation-bootstrap.md using .workflow/selected-playbook.md, CLAUDE.md, AGENTS.md, and {spec_path}", + "Scope: repo root. Validation: track choice, bootstrap spec sections, and first implementation boundary are explicit.", + ), + ( + f"Implement repository scaffold in repo root, covering {spec_path}, and use tdd-implementing to follow .plans/{date_stamp}-foundation-bootstrap.md", + "Validation: create the approved stack skeleton, baseline commands, and initial checks without introducing a second track.", + ), + ( + f"Review repo root for simplification opportunities after foundation scaffold and use code-simplifying skill", + "Keep behavior unchanged and remove setup noise before the next feature spec.", + ), + ( + f"Review repo root for refactoring opportunities and use code-refactoring skill to generate .plans/{date_stamp}-foundation-refactor.md", + "Focus: DRY, KISS, and stable module boundaries for future specs.", + ), + ] + + if context["playbook"] == "existing-project-spec-backfill-and-refactor": + return [ + ( + f"Plan baseline audit in .plans/{date_stamp}-baseline-audit.md using .workflow/selected-playbook.md, CLAUDE.md, AGENTS.md, and {spec_path}", + "Scope: current repo modules, boundaries, tests, and debt hotspots. Validation: produce a stable baseline for Spec backfill.", + ), + ( + f"Write or tighten {spec_path} and update ANALYSIS.md with current-repo findings before deeper refactor work", + "Validation: the spec reflects real boundaries, approved constraints, and the current alignment target.", + ), + ( + f"Generate alignment and refactor queue in TODO.yaml covering current repo modules and use spec-tasking plus code-refactoring references", + "Impact: create executable tasks that reference concrete paths, specs, and future plan files.", + ), + ( + f"Review current repo modules for simplification opportunities after baseline audit and use code-simplifying skill", + "Keep behavior unchanged and remove obvious complexity before larger refactor batches.", + ), + ] + + return [ + ( + f"Plan spec-code gap analysis in .plans/{date_stamp}-gap-analysis.md using .workflow/selected-playbook.md, CLAUDE.md, AGENTS.md, and {spec_path}", + "Scope: accepted specs, current code, failing or missing tests. Validation: classify Missing, Partial, Divergent, Untested, and Integration gaps.", + ), + ( + f"Generate alignment queue in TODO.yaml for current repo modules, referencing {spec_path} and .plans/{date_stamp}-gap-analysis.md", + "Validation: every task title names the target path and evidence source; insert simplify/refactor checkpoints by batch.", + ), + ( + f"Implement highest-priority gap closure in repo root, covering accepted specs, and use tdd-implementing to follow .plans/{date_stamp}-gap-analysis.md", + "Validation: close the highest-risk gaps first and record residual risks explicitly.", + ), + ( + f"Review gap-closure changes for simplification opportunities and use code-simplifying skill", + "Keep behavior aligned to spec and remove incidental complexity after each closure batch.", + ), + ] + + +def render_todo(context: dict[str, Any]) -> str: + tasks = build_tasks(context) + lines = ["tasks:"] + for title, description in tasks: + lines.append(f' - title: "{title}"') + lines.append(f' description: "{description}"') + lines.append(" completed: false") + lines.append("") + return "\n".join(lines).rstrip() + "\n" + + +def render_spec(context: dict[str, Any]) -> str: + track = context["track_profile"] + return f"""# Workflow Bootstrap And Project Constraints + +## Overview +- Defines: the first-round workflow contract, stack track, model routing, and document set for {context['project_name']}. +- Not Covered: feature-level product details beyond the initial bootstrap boundary. +- Related SPECS: add feature/domain specs after this file is accepted. + +## Terminology +- Workflow Bootstrap: the initial rule layer that makes later Research, Spec, and Code work deterministic. +- Approved Track: the single allowed stack path for the application main path. +- Handoff: the compact context package that moves work between agents or threads. + +## Domain Sections +### Delivery Workflow +- Rule: All work follows `{context['playbook_label']}` under the 7-stage contract: Setup -> Research -> Spec -> Code -> Alignment -> Refinement -> Acceptance. +- Acceptance: `CLAUDE.md`, `AGENTS.md`, `ANALYSIS.md`, `TODO.yaml`, `.ralphy/config.yaml`, and `.workflow/selected-playbook.md` exist and do not contradict each other. +> **Why**: The workflow must be stable before feature implementation starts. +> **Rejected**: Free-form prompting without a fixed stage contract. + +### Stack Track +- Rule: The application main path uses `{track['label']}` with `{track['language']}`, `{track['ui']}`, `{track['styling']}`, `{track['auth']}`, `{track['data_fetching']}`, `{track['router']}`, `{track['service_layer']}`, `{track['orm']}`, and `{track['database']}`. +- Acceptance: No second primary router, auth path, ORM, or styling system is introduced without ADR approval. +> **Why**: Agent output quality drops when multiple primary tracks coexist. +> **Rejected**: Dual-track implementations or untyped main-path languages. + +### Model Routing And Review +- Rule: Planning and implementation default to `{context['primary_model']}`; long-document digestion and second-view review default to `{context['secondary_model']}`. +- Acceptance: Any fallback usage is summarized back into the standard handoff contract before the main thread continues. +> **Why**: Multi-model workflows only stay reliable when routing is explicit. +> **Rejected**: Letting fallback models become the default path. + +### First-Round Deliverables +- Rule: The first-round working set must include a bootstrap spec, project execution files, a task queue, and an explicit handoff for the next stage. +- Acceptance: `SPECS/{context['spec_file']}`, `.handoff/setup-handoff.md`, and `.workflow/first-round-prompts.md` are present and point to the same source of truth. +> **Why**: The next agent should not need the raw setup conversation to continue. +> **Rejected**: Starting implementation from memory or scattered notes. + +## Forbidden +- Do not: introduce Python or PHP on the application main path, add a second primary stack track, or bypass spec review. +- Use instead: TypeScript + React on the approved track, standard handoff, and explicit ADRs for exceptions. +- Reason: reliability, testability, and agent consistency depend on fixed constraints. + +## References +- Internal: + - `CLAUDE.md` + - `AGENTS.md` + - `ANALYSIS.md` + - `TODO.yaml` + - `.workflow/selected-playbook.md` + - `.workflow/knowledge-base-overview.md` +- External: + - `references/knowledge-base/platform/framework-decision-matrix.md` + - `references/knowledge-base/platform/model-routing-policy.md` + - `references/knowledge-base/platform/stack-policy.md` +""" + + +def render_ralphy(context: dict[str, Any]) -> str: + return f"""project: + name: {context['project_slug']} + workflow: cc-switch-dev-workflow + playbook: {context['playbook']} + track: {context['track_profile']['label']} + +commands: + test: pnpm test + lint: pnpm lint + build: pnpm build + typecheck: pnpm exec tsc --noEmit + +rules: + - Read CLAUDE.md, AGENTS.md, ANALYSIS.md, TODO.yaml, and .workflow/selected-playbook.md before implementation. + - Keep one approved stack track and one approved model-routing policy. + - Every task title must be self-contained with path and reference. + - Run simplify and refactor checkpoints after each implementation batch. + +references: + - CLAUDE.md + - AGENTS.md + - ANALYSIS.md + - TODO.yaml + - SPECS/{context['spec_file']} + - .workflow/selected-playbook.md +""" + + +def render_prompts(context: dict[str, Any]) -> str: + return f"""# First-Round Prompts + +## Prompt 1: Setup Confirmation +基于当前仓库和以下初始化产物,确认项目边界和单一技术轨道:`CLAUDE.md`、`AGENTS.md`、`ANALYSIS.md`、`TODO.yaml`、`SPECS/{context['spec_file']}`、`.workflow/selected-playbook.md`。如果发现现有代码与默认轨道冲突,只输出差异、风险和建议,不直接改代码。 + +## Prompt 2: Research And Spec Expansion +基于 `ANALYSIS.md`、`.workflow/selected-playbook.md` 和 `SPECS/{context['spec_file']}`,扩展第一轮 `.research/*.md` 和后续产品/模块 Spec。只保留与目标 `{context['goal']}` 相关的结论、模块边界和拒绝理由。 + +## Prompt 3: Tasking And Implementation Plan +基于 `TODO.yaml`、`CLAUDE.md`、`AGENTS.md` 和 `SPECS/{context['spec_file']}`,生成下一轮 `.plans/*.md`,把每个真实任务拆成可执行的 Plan/Impl 对,并在批次后插入 simplify/refactor 检查点。 +""" + + +def render_handoff(context: dict[str, Any]) -> str: + return f"""# Handoff + +## Goal +- Start the first real workflow round for {context['project_name']} under the {context['playbook_label']} playbook. + +## Scope +- Confirm boundaries in `CLAUDE.md` and `AGENTS.md`. +- Tighten `SPECS/{context['spec_file']}`. +- Expand `TODO.yaml` into the next actionable plan files. + +## Non-Goals +- Do not implement broad product features yet. +- Do not change the approved stack track without review. +- Do not bypass spec or acceptance gates. + +## Source of Truth +- `CLAUDE.md` +- `AGENTS.md` +- `ANALYSIS.md` +- `TODO.yaml` +- `SPECS/{context['spec_file']}` +- `.workflow/selected-playbook.md` + +## Constraints +- Keep one primary stack track. +- Keep the main path in TypeScript + React. +- Use explicit handoff and reset rules when switching agents or models. + +## Deliverable +- Updated analysis, tightened spec, next `.plans/*.md`, and an implementation-ready task queue. + +## Validation +- The next agent can proceed without raw setup chat. +- The stack track, model routing, and task queue remain internally consistent. +- Human decisions required by the setup round are clearly listed. + +## Escalation +- Stop and ask when: the repo baseline contradicts the chosen track, the spec needs a structural exception, or the first implementation batch would violate accepted boundaries. +""" + + +def render_meetings_readme(context: dict[str, Any]) -> str: + lines = [ + "# Meetings", + "", + "Place raw notes, screenshots, or imported meeting summaries for this repo here.", + "", + "Current bootstrap context:", + f"- Project: {context['project_name']}", + f"- Playbook: {context['playbook_label']}", + f"- Goal: {context['goal']}", + ] + if context["source_notes"]: + lines.extend(["", "Suggested source notes:"]) + lines.extend(f"- {note}" for note in context["source_notes"]) + return "\n".join(lines) + "\n" + + +def build_context(args: argparse.Namespace, target_dir: Path) -> dict[str, Any]: + project_name = args.project_name or target_dir.name + project_slug = slugify(project_name) + playbook_profile = PLAYBOOK_CONTEXT[args.playbook] + track_key, track_reason = pick_track(target_dir, args.playbook, args.track) + runtime = collect_summary(Path.home() / ".cc-switch") if collect_summary else {} + primary_model, secondary_model, fallback_model = runtime_model_line(runtime) if runtime else ( + "GPT-5.4 Pro xhigh", + "Claude Opus 4.6", + "GLM / Kimi / Minimax only when blocked", + ) + + return { + "project_name": project_name, + "project_slug": project_slug, + "goal": args.goal or playbook_profile["goal_hint"], + "audience": args.audience or "Internal team and future implementing agents", + "playbook": args.playbook, + "playbook_label": playbook_profile["label"], + "spec_file": args.spec_file or playbook_profile["spec_file"], + "in_scope": parse_list(args.in_scope) or playbook_profile["default_in_scope"], + "out_of_scope": parse_list(args.out_of_scope) or playbook_profile["default_out_of_scope"], + "track_profile": TRACKS[track_key], + "track_reason": track_reason, + "primary_model": primary_model, + "secondary_model": secondary_model, + "fallback_model": fallback_model, + "runtime_source": str(Path.home() / ".cc-switch") if runtime else "knowledge-base default policy", + "date_stamp": datetime.now().strftime("%Y-%m-%d"), + "source_notes": parse_list(args.source_note), + } + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Generate first-round workflow artifacts for a target repo.") + parser.add_argument("--target-dir", required=True, help="Absolute or relative repo directory to initialize.") + parser.add_argument("--playbook", required=True, choices=sorted(PLAYBOOK_FILES)) + parser.add_argument("--project-name", help="Human-readable project name. Defaults to target directory name.") + parser.add_argument("--goal", help="Primary project goal for the bootstrap set.") + parser.add_argument("--audience", help="Primary audience for the product or repo.") + parser.add_argument("--in-scope", action="append", help="Comma-separated in-scope items. Can be passed multiple times.") + parser.add_argument("--out-of-scope", action="append", help="Comma-separated out-of-scope items. Can be passed multiple times.") + parser.add_argument("--source-note", action="append", help="Comma-separated raw note or source doc names to remember.") + parser.add_argument( + "--track", + choices=("auto", "hono-react-ssr-tanstack", "nextjs-fullstack"), + default="auto", + help="Preferred application track. Defaults to auto detection + workflow tie-break.", + ) + parser.add_argument("--spec-file", help="Custom bootstrap spec filename under SPECS/.") + parser.add_argument("--force", action="store_true", help="Overwrite existing generated files.") + return parser.parse_args() + + +def main() -> int: + args = parse_args() + target_dir = Path(args.target_dir).expanduser().resolve() + target_dir.mkdir(parents=True, exist_ok=True) + writes = seed_workspace( + target_dir, + args.playbook, + args.force, + include_core_docs=False, + include_ralphy_config=False, + ) + context = build_context(args, target_dir) + + generated_files = { + target_dir / "CLAUDE.md": render_claude(context), + target_dir / "AGENTS.md": render_agents(context), + target_dir / "ANALYSIS.md": render_analysis(context), + target_dir / "TODO.yaml": render_todo(context), + target_dir / "SPECS" / context["spec_file"]: render_spec(context), + target_dir / ".ralphy" / "config.yaml": render_ralphy(context), + target_dir / ".workflow" / "first-round-prompts.md": render_prompts(context), + target_dir / ".handoff" / "setup-handoff.md": render_handoff(context), + target_dir / ".meetings" / "README.md": render_meetings_readme(context), + } + + for target, content in generated_files.items(): + writes.append(write_text(target, content, True)) + + manifest_path = target_dir / ".workflow" / "bootstrap-manifest.json" + manifest = { + "skill": "cc-switch-dev-workflow", + "mode": "full-init", + "generated_at": datetime.now(timezone.utc).isoformat(), + "project_name": context["project_name"], + "playbook": args.playbook, + "track": context["track_profile"]["label"], + "track_reason": context["track_reason"], + "spec_file": context["spec_file"], + } + writes.append(write_text(manifest_path, json.dumps(manifest, indent=2, ensure_ascii=False), True)) + + print("\n".join(writes)) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())