/sdd-stack
输入:$ARGUMENTS。你需引导用户完成关于技术栈的访谈,并仅在用户确认概览后写入文件。
0. 提问前:先发现事实
环境事实是你的工作,不要询问用户。请检查(或委派给子Agent):
- 已有的清单文件和代码(
package.json、pyproject.toml、go.mod、Dockerfile、.github/workflows/、顶层目录); .agents/specs/stack.md和architecture.md(如果已填写且没有--revisar参数,则显示摘要,仅询问缺失的部分);.specify/memory/constitution.md(已决定的限制,例如:LGPD、单一数据库);sddkit suggest --json(已检测到的技术栈)。
已在代码中决定的内容视为已确定选择,不作为问题提出。
1. 方法
- 如果 Skill
grilling已安装在.agents/skills/中 → 遵循其方法(按决策树边界进行轮询,每个问题附带推荐答案,直到边界为空)。 - 如果未安装 → 使用相同格式:每轮中,已满足前置条件的所有问题,编号列出,每个问题如下所示:
❓ **Q1 — <标题>**:<问题,包含2-4个选项,每个选项用一行说明其权衡>
➡️ <你的推荐及其原因,用1-2行说明>
撰写每个问题,使得回答“是”即接受推荐。优先选择成熟稳定、团队成员已熟悉的技术,而非前沿技术;除非有强烈理由,否则为整个项目选择单一语言;尽量使用满足范围所需的最少组件(每个额外服务都增加运营成本)。如果回答与先前问题或章程相矛盾,请指出并询问以哪个为准。
2. 技术栈决策树
按以下依赖顺序遍历;跳过不适用的分支(例如:无UI → 不问前端问题)。
- 产品: 是什么(Web应用、API、移动应用、桌面应用、CLI、库、Worker)、谁使用、预期规模(用户、数据、峰值)、限制(LGPD、离线、成本、期限)。
- 团队: 团队掌握的语言;谁将维护。
- 形态: 模块化单体、带包的Monorepo、或分离的服务;哪些需要异步处理。
- 语言和运行时(主版本):例如:TypeScript/Node 22、Python 3.12。
- 前端(如果有UI):框架(React/Next、Vue/Nuxt、Svelte、Astro...)、渲染方式(SPA、SSR、静态)、组件库和样式(MUI、shadcn+Tailwind...)、服务端状态(TanStack Query...)、国际化(i18n)、可访问性。
- 移动/桌面端(如果有):原生、React Native/Expo、Flutter、Tauri、Electron。
- 后端/API: 框架(Express、Fastify、NestJS、Hono、FastAPI、Django...)、风格(REST、GraphQL、tRPC)、契约和验证(Zod、Pydantic、OpenAPI)。
7b. 后端范式(仅当有后端时;绝不用于前端,前端遵循框架的习惯):
- 风格:OOP与SOLID(实体包含不变量、服务依赖接口)、函数式(纯函数、不可变数据、在边缘产生副作用)或务实主义(简单模块,仅当存在2个以上实现时才抽象——
ponytail的默认方式)。 - 架构:简单分层(Controller → Service → Repository)、Clean/六边形架构(领域层不依赖框架,端口和适配器)或DDD(限界上下文、聚合)。推荐领域能承受的最简单方式:仅当业务规则丰富时才采用Clean/DDD。
- 哪些文件夹是后端(例如:
server/**、services/**、modules/**)。这将限定范式作用域于后端。
- 风格:OOP与SOLID(实体包含不变量、服务依赖接口)、函数式(纯函数、不可变数据、在边缘产生副作用)或务实主义(简单模块,仅当存在2个以上实现时才抽象——
- 数据: 数据库(PostgreSQL、MySQL、MongoDB、SQLite)、ORM/访问层(Prisma、Drizzle、SQLAlchemy...)、迁移、缓存。
- 异步: 队列/任务(BullMQ、Celery、pg-boss...)、事件、实时通信(WebSocket/SSE)。
- 认证与授权: 提供方或自建、会话/JWT、角色/权限。
- 外部集成: 支付(PIX...)、邮件、AI(Anthropic SDK...)、MCP。
- 托管与运维: 运行位置(Vercel、带Docker的VPS、云托管)、环境、密钥、可观测性(日志、错误、指标)。
- 质量: 测试(单元、集成、使用Playwright的E2E)、Lint/格式化、类型检查、CI(GitHub Actions)、提交规范(Conventional Commits/commitlint)。
3. 确认
当决策树边界为空时,以表格形式展示摘要(层 · 选择 · 版本 · 原因 · 弃用方案),并询问:“就这样定下来吗?” 在得到“是”之前,不要写入任何内容。
4. 写入文件
.agents/specs/stack.md:将内容(包括[PREENCHER标记)替换为:## 按组件— 每层包含技术、主版本和主要库的包名(例如:react、@prisma/client、bullmq、fastapi):sddkit使用这些名称来建议角色和技能;## 基础设施— 数据库、队列、缓存、托管、CI、可观测性;## 决策记录— 每项重要选择及其原因和弃用方案(使用当前日期)。
.agents/specs/architecture.md:填写## 概览部分(组件及其通信方式;如果超过2个组件,则包含一个Mermaid图表)并移除[PREENCHER标记。如果已有代码,同时填写## 代码地图部分(每个区域一行:入口、关键文件夹、测试)。其他部分留待有代码时填写。- 后端范式(如果在7b中决定且不是“务实主义”):
.agents/specs/coding-standards.md:添加## 后端 — 范式部分,包含风格、架构、后端文件夹、3-5条具体规则及简短示例,以及执行这些规则的工具(如下)。明确说明前端不遵循此部分。- 向sddkit添加记忆,使得Agent在所有会话中都能了解作用域:
sddkit memory add "范式 <风格>/<架构> 仅适用于后端(<文件夹>);前端遵循框架习惯" -t paradigma sddkit memory add "在后端,coding-standards.md中的'后端 — 范式'部分优先于ponytail关于接口和层的规定" -t paradigma sddkit memory add "<最重要的具体规则>" -t paradigma-backend --paths "<后端文件夹>" - 技能(目录中为可选,仅由后端角色
api、data、event-module、queue-worker加载):OOP/SOLID →sddkit add solid;Clean/六边形架构 →sddkit add clean-architecture;DDD →sddkit add domain-driven-design。函数式:没有良好的通用技能;coding-standards.md中的规则和Lint工具承担此角色。 - 确定性强制(Lint限制在后端文件夹内;如果尚未有代码,这将成为
/sdd-feature设置的第一个任务):- 分层/Clean/六边形/DDD:
dependency-cruiser或eslint-plugin-boundaries(TypeScript)、import-linter(Python)—— 领域层不应导入基础设施或框架; - TypeScript函数式:在ESLint配置中使用
files: ["<后端文件夹>"]区块启用eslint-plugin-functional(禁止类、禁止变、禁止let); - OOP:没有Lint工具强制要求OOP;请使用上述分层规则并结合代码审查。
- 分层/Clean/六边形/DDD:
- 章程: 如果出现了不可协商的限制(例如:“PostgreSQL是唯一可信数据源”),请提出文本并建议使用
/speckit-constitution—— 不要直接编辑章程文件。 - 告知用户在终端中运行:
sddkit init # 读取已声明的技术栈并推荐相关角色和技能(不删除任何现有内容) sddkit doctor
最终报告(≤ 8行)
每一行概述一层技术栈 · 后端范式及其强制方式 · 写入的文件 · 建议加入章程的限制 · 后续步骤(sddkit init,然后 /sdd-feature)。