Initial commit from Spec Kit CN template

This commit is contained in:
2025-12-24 20:57:09 +08:00
commit f9a6fe619f
21 changed files with 3103 additions and 0 deletions
+184
View File
@@ -0,0 +1,184 @@
---
description: 在任务生成后, 对 spec.md、plan.md 和 tasks.md 执行非破坏性的跨制品一致性和质量分析.
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 目标
在实施之前, 识别三个核心制品(`spec.md``plan.md``tasks.md`)之间的不一致、重复、模糊和规范不足的项目. 此命令**必须**在 `/speckit.tasks` 成功生成完整的 `tasks.md` 后运行.
## 操作约束
**严格只读**: **不要**修改任何文件. 输出结构化分析报告. 提供可选的修复计划(用户必须明确批准后才能手动调用任何后续编辑命令).
**章程权威**: 项目章程(`.specify/memory/constitution.md`)在此分析范围内是**不可协商的**. 章程冲突自动为严重问题, 需要调整规范、计划或任务——而不是稀释、重新解释或默默忽略原则. 如果原则本身需要更改, 那必须在 `/speckit.analyze` 之外的单独、明确的章程更新中进行.
## 执行步骤
### 1. 初始化分析上下文
从仓库根目录运行一次 `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` 并解析 JSON 以获取 FEATURE_DIR 和 AVAILABLE_DOCS. 推导绝对路径:
- SPEC = FEATURE_DIR/spec.md
- PLAN = FEATURE_DIR/plan.md
- TASKS = FEATURE_DIR/tasks.md
如果任何必需文件缺失, 则以错误消息中止(指示用户运行缺失的先决条件命令).
对于参数中的单引号, 如 "I'm Groot", 使用转义语法: 例如 'I'\''m Groot'(或尽可能使用双引号: "I'm Groot").
### 2. 加载制品(渐进式展示)
仅从每个制品加载最小必需的上下文:
**从 spec.md: **
- 概述/上下文
- 功能需求
- 非功能需求
- 用户故事
- 边缘情况(如果存在)
**从 plan.md: **
- 架构/技术栈选择
- 数据模型引用
- 阶段
- 技术约束
**从 tasks.md: **
- 任务 ID
- 描述
- 阶段分组
- 并行标记 [P]
- 引用的文件路径
**从章程: **
- 加载 `.specify/memory/constitution.md` 进行原则验证
### 3. 构建语义模型
创建内部表示(输出中不包含原始制品):
- **需求清单**: 每个功能和非功能需求, 带有稳定键(基于祈使短语推导 slug; 例如, "User can upload file" → `user-can-upload-file`)
- **用户故事/操作清单**: 带有验收标准的离散用户操作
- **任务覆盖映射**: 将每个任务映射到一个或多个需求或故事(通过关键词/显式引用模式推断, 如 ID 或关键短语)
- **章程规则集**: 提取原则名称和 MUST/SHOULD 规范性声明
### 4. 检测过程(高效令牌分析)
专注于高信号发现. 限制总共 50 个发现; 在溢出摘要中聚合其余部分.
#### A. 重复检测
- 识别近似重复的需求
- 标记较低质量的表述以进行合并
#### B. 模糊性检测
- 标记缺乏可测量标准的模糊形容词(快速、可扩展、安全、直观、稳健)
- 标记未解决的占位符(TODO、TKTK、???、`<placeholder>` 等)
#### C. 规范不足
- 有动词但缺少对象或可测量结果的需求
- 缺少验收标准对齐的用户故事
- 引用规范/计划中未定义的文件或组件的任务
#### D. 章程对齐
- 与 MUST 原则冲突的任何需求或计划元素
- 章程中缺失的强制部分或质量门控
#### E. 覆盖缺口
- 没有关联任务的需求
- 没有映射需求/故事的任务
- 未在任务中反映的非功能需求(例如, 性能、安全性)
#### F. 不一致性
- 术语漂移(相同概念在不同文件中命名不同)
- 计划中引用但在规范中缺失的数据实体(反之亦然)
- 任务排序矛盾(例如, 集成任务在基础设置任务之前而没有依赖说明)
- 冲突需求(例如, 一个要求 Next.js 而另一个指定 Vue)
### 5. 严重性分配
使用此启发式方法对发现进行优先级排序:
- **严重**: 违反章程 MUST、缺失核心规范制品, 或零覆盖的需求阻止基线功能
- **高**: 重复或冲突需求、模糊的安全/性能属性、不可测试的验收标准
- **中**: 术语漂移、缺失非功能任务覆盖、规范不足的边缘情况
- **低**: 风格/措辞改进、不影响执行顺序的轻微冗余
### 6. 生成紧凑分析报告
输出 Markdown 报告(不写入文件), 结构如下:
## 规范分析报告
| ID | 类别 | 严重性 | 位置 | 摘要 | 建议 |
|----|------|--------|------|------|------|
| A1 | 重复 | 高 | spec.md:L120-134 | 两个相似需求... | 合并表述; 保留更清晰的版本 |
(每个发现添加一行; 生成以类别首字母为前缀的稳定 ID. )
**覆盖摘要表: **
| 需求键 | 有任务? | 任务 ID | 备注 |
|--------|----------|---------|------|
**章程对齐问题: **(如果有)
**未映射任务: **(如果有)
**指标: **
- 总需求数
- 总任务数
- 覆盖率%(有 >=1 个任务的需求)
- 模糊性计数
- 重复计数
- 严重问题计数
### 7. 提供下一步操作
在报告末尾, 输出简洁的下一步操作块:
- 如果存在严重问题: 建议在 `/speckit.implement` 之前解决
- 如果只有低/中问题: 用户可以继续, 但提供改进建议
- 提供明确的命令建议: 例如, "运行 /speckit.specify 进行细化"、"运行 /speckit.plan 调整架构"、"手动编辑 tasks.md 为 'performance-metrics' 添加覆盖"
### 8. 提供修复
询问用户: "你希望我为前 N 个问题建议具体的修复编辑吗?"(不要自动应用它们. )
## 操作原则
### 上下文效率
- **最小高信噪比令牌**: 专注于可操作的发现, 而不是详尽的文档
- **渐进式展示**: 增量加载制品; 不要将所有内容倾倒到分析中
- **高效令牌输出**: 限制发现表为 50 行; 总结溢出部分
- **确定性结果**: 无更改重新运行应产生一致的 ID 和计数
### 分析指南
- **绝不修改文件**(这是只读分析)
- **绝不虚构缺失部分**(如果缺失, 准确报告)
- **优先处理章程违规**(这些总是严重的)
- **使用示例而非详尽规则**(引用具体实例, 而不是通用模式)
- **优雅报告零问题**(发出带有覆盖统计的成功报告)
## 上下文
$ARGUMENTS
+287
View File
@@ -0,0 +1,287 @@
---
description: 基于用户需求为当前功能生成自定义检查清单.
---
## 清单目的: "需求编写的单元测试"
**核心概念**: 清单是**需求编写的单元测试** - 它们验证特定领域中需求的质量、清晰度和完整性.
**不用于验证/测试**:
- ❌ 不是"验证按钮点击正确"
- ❌ 不是"测试错误处理有效"
- ❌ 不是"确认 API 返回 200"
- ❌ 不是检查代码/实现是否符合规范
**用于需求质量验证**:
- ✅ "是否为所有卡片类型定义了视觉层次需求?"(完整性)
- ✅ "'突出显示'是否通过具体尺寸/位置进行了量化?"(清晰度)
- ✅ "所有交互元素的悬停状态需求是否一致?"(一致性)
- ✅ "是否为键盘导航定义了可访问性需求?"(覆盖度)
- ✅ "规范是否定义了 logo 图像加载失败时的处理?"(边缘情况)
**比喻**: 如果你的规范是用英文编写的代码, 那么清单就是它的单元测试套件. 你测试的是需求是否编写良好、完整、明确并准备好实施 - 而不是实现是否有效.
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 执行步骤
1. **设置**: 从仓库根目录运行 `.specify/scripts/powershell/check-prerequisites.ps1 -Json` 并解析JSON以获取FEATURE_DIR和AVAILABLE_DOCS列表.
- 所有文件路径必须是绝对路径.
- 对于参数中的单引号如"I'm Groot", 使用转义语法: 例如 'I'\''m Groot'(或者尽可能使用双引号: "I'm Groot").
2. **澄清意图(动态)**: 推导最多三个初始上下文澄清问题(无预编目录). 它们必须:
- 从用户的表述 + 从规范/计划/任务中提取的信号生成
- 只询问实质上改变清单内容的信息
- 如果在`$ARGUMENTS`中已经明确, 则单独跳过
- 优先考虑精确性而非广度
Generation algorithm:
1. Extract signals: feature domain keywords (e.g., auth, latency, UX, API), risk indicators ("critical", "must", "compliance"), stakeholder hints ("QA", "review", "security team"), and explicit deliverables ("a11y", "rollback", "contracts").
2. Cluster signals into candidate focus areas (max 4) ranked by relevance.
3. Identify probable audience & timing (author, reviewer, QA, release) if not explicit.
4. Detect missing dimensions: scope breadth, depth/rigor, risk emphasis, exclusion boundaries, measurable acceptance criteria.
5. Formulate questions chosen from these archetypes:
- Scope refinement (e.g., "Should this include integration touchpoints with X and Y or stay limited to local module correctness?")
- Risk prioritization (e.g., "Which of these potential risk areas should receive mandatory gating checks?")
- Depth calibration (e.g., "Is this a lightweight pre-commit sanity list or a formal release gate?")
- Audience framing (e.g., "Will this be used by the author only or peers during PR review?")
- Boundary exclusion (e.g., "Should we explicitly exclude performance tuning items this round?")
- Scenario class gap (e.g., "No recovery flows detected—are rollback / partial failure paths in scope?")
Question formatting rules:
- If presenting options, generate a compact table with columns: Option | Candidate | Why It Matters
- Limit to AE options maximum; omit table if a free-form answer is clearer
- Never ask the user to restate what they already said
- Avoid speculative categories (no hallucination). If uncertain, ask explicitly: "Confirm whether X belongs in scope."
Defaults when interaction impossible:
- Depth: Standard
- Audience: Reviewer (PR) if code-related; Author otherwise
- Focus: Top 2 relevance clusters
Output the questions (label Q1/Q2/Q3). After answers: if ≥2 scenario classes (Alternate / Exception / Recovery / Non-Functional domain) remain unclear, you MAY ask up to TWO more targeted followups (Q4/Q5) with a one-line justification each (e.g., "Unresolved recovery path risk"). Do not exceed five total questions. Skip escalation if user explicitly declines more.
3. **理解用户请求**: 结合 `$ARGUMENTS` + 澄清答案:
- 推导清单主题(例如: security, review, deploy, ux)
- 整合用户明确提到的必需项目
- 将焦点选择映射到类别框架
- 从规范/计划/任务中推断任何缺失的上下文(不要虚构)
4. **加载功能上下文**: 从 FEATURE_DIR 读取:
- spec.md: 功能需求和范围
- plan.md(如果存在): 技术细节、依赖关系
- tasks.md(如果存在): 实施任务
**上下文加载策略**:
- 仅加载与活动焦点区域相关的必要部分(避免全文转储)
- 优先将长部分总结为简洁的场景/需求要点
- 使用渐进式披露: 仅在检测到差距时添加后续检索
- 如果源文档很大, 生成临时摘要项目而不是嵌入原始文本
5. **生成清单** - 创建"需求的单元测试":
- Create `FEATURE_DIR/checklists/` directory if it doesn't exist
- Generate unique checklist filename:
- Use short, descriptive name based on domain (e.g., `ux.md`, `api.md`, `security.md`)
- Format: `[domain].md`
- If file exists, append to existing file
- Number items sequentially starting from CHK001
- Each `/speckit.checklist` run creates a NEW file (never overwrites existing checklists)
**核心原则 - 测试需求, 而非实现**:
每个清单项目必须评估需求本身, 检查:
- **完整性**: 所有必要的需求是否存在?
- **清晰度**: 需求是否明确无歧义且具体?
- **一致性**: 需求之间是否相互一致?
- **可测量性**: 需求是否可以客观验证?
- **覆盖度**: 是否涵盖了所有场景/边缘情况?
**类别结构** - 按需求质量维度分组项目:
- **需求完整性**(所有必要的需求是否已记录?)
- **需求清晰度**(需求是否具体且无歧义?)
- **需求一致性**(需求是否一致且无冲突?)
- **验收标准质量**(成功标准是否可测量?)
- **场景覆盖度**(是否涵盖了所有流程/情况?)
- **边缘情况覆盖度**(是否定义了边界条件?)
- **非功能性需求**(性能、安全性、可访问性等 - 是否已指定?)
- **依赖关系和假设**(是否已记录和验证?)
- **歧义和冲突**(什么 NEEDS CLARIFICATION)
**如何编写清单项目 - "需求编写的单元测试"**:
**WRONG** (Testing implementation):
- "Verify landing page displays 3 episode cards"
- "Test hover states work on desktop"
- "Confirm logo click navigates home"
**CORRECT** (Testing requirements quality):
- "Are the exact number and layout of featured episodes specified?" [Completeness]
- "Is 'prominent display' quantified with specific sizing/positioning?" [Clarity]
- "Are hover state requirements consistent across all interactive elements?" [Consistency]
- "Are keyboard navigation requirements defined for all interactive UI?" [Coverage]
- "Is the fallback behavior specified when logo image fails to load?" [Edge Cases]
- "Are loading states defined for asynchronous episode data?" [Completeness]
- "Does the spec define visual hierarchy for competing UI elements?" [Clarity]
**项目结构**:
Each item should follow this pattern:
- Question format asking about requirement quality
- Focus on what's WRITTEN (or not written) in the spec/plan
- Include quality dimension in brackets [Completeness/Clarity/Consistency/etc.]
- Reference spec section `[Spec §X.Y]` when checking existing requirements
- Use `[Gap]` marker when checking for missing requirements
**按质量维度分类的示例**:
完整性:
- "Are error handling requirements defined for all API failure modes? [Gap]"
- "Are accessibility requirements specified for all interactive elements? [Completeness]"
- "Are mobile breakpoint requirements defined for responsive layouts? [Gap]"
清晰度:
- "Is 'fast loading' quantified with specific timing thresholds? [Clarity, Spec §NFR-2]"
- "Are 'related episodes' selection criteria explicitly defined? [Clarity, Spec §FR-5]"
- "Is 'prominent' defined with measurable visual properties? [Ambiguity, Spec §FR-4]"
一致性:
- "Do navigation requirements align across all pages? [Consistency, Spec §FR-10]"
- "Are card component requirements consistent between landing and detail pages? [Consistency]"
覆盖度:
- "Are requirements defined for zero-state scenarios (no episodes)? [Coverage, Edge Case]"
- "Are concurrent user interaction scenarios addressed? [Coverage, Gap]"
- "Are requirements specified for partial data loading failures? [Coverage, Exception Flow]"
可测量性:
- "Are visual hierarchy requirements measurable/testable? [Acceptance Criteria, Spec §FR-1]"
- "Can 'balanced visual weight' be objectively verified? [Measurability, Spec §FR-2]"
**场景分类与覆盖度**(需求质量焦点):
- Check if requirements exist for: Primary, Alternate, Exception/Error, Recovery, Non-Functional scenarios
- For each scenario class, ask: "Are [scenario type] requirements complete, clear, and consistent?"
- If scenario class missing: "Are [scenario type] requirements intentionally excluded or missing? [Gap]"
- Include resilience/rollback when state mutation occurs: "Are rollback requirements defined for migration failures? [Gap]"
**可追溯性要求**:
- MINIMUM: ≥80% of items MUST include at least one traceability reference
- Each item should reference: spec section `[Spec §X.Y]`, or use markers: `[Gap]`, `[Ambiguity]`, `[Conflict]`, `[Assumption]`
- If no ID system exists: "Is a requirement & acceptance criteria ID scheme established? [Traceability]"
**发现和解决问题**(需求质量问题):
Ask questions about the requirements themselves:
- Ambiguities: "Is the term 'fast' quantified with specific metrics? [Ambiguity, Spec §NFR-1]"
- Conflicts: "Do navigation requirements conflict between §FR-10 and §FR-10a? [Conflict]"
- Assumptions: "Is the assumption of 'always available podcast API' validated? [Assumption]"
- Dependencies: "Are external podcast API requirements documented? [Dependency, Gap]"
- Missing definitions: "Is 'visual hierarchy' defined with measurable criteria? [Gap]"
**内容整合**:
- Soft cap: If raw candidate items > 40, prioritize by risk/impact
- Merge near-duplicates checking the same requirement aspect
- If >5 low-impact edge cases, create one item: "Are edge cases X, Y, Z addressed in requirements? [Coverage]"
**🚫 ABSOLUTELY PROHIBITED** - These make it an implementation test, not a requirements test:
- ❌ Any item starting with "Verify", "Test", "Confirm", "Check" + implementation behavior
- ❌ References to code execution, user actions, system behavior
- ❌ "Displays correctly", "works properly", "functions as expected"
- ❌ "Click", "navigate", "render", "load", "execute"
- ❌ Test cases, test plans, QA procedures
- ❌ Implementation details (frameworks, APIs, algorithms)
**✅ REQUIRED PATTERNS** - These test requirements quality:
- ✅ "Are [requirement type] defined/specified/documented for [scenario]?"
- ✅ "Is [vague term] quantified/clarified with specific criteria?"
- ✅ "Are requirements consistent between [section A] and [section B]?"
- ✅ "Can [requirement] be objectively measured/verified?"
- ✅ "Are [edge cases/scenarios] addressed in requirements?"
- ✅ "Does the spec define [missing aspect]?"
6. **结构参考**: 按照 `.specify/templates/checklist-template.md` 中的规范模板生成清单, 包括标题、元部分、类别标题和 ID 格式. 如果模板不可用, 使用: H1 标题、purpose/created 元行、包含 `- [ ] CHK### <requirement item>` 行的 `##` 类别部分, ID 从 CHK001 开始全局递增.
7. **报告**: 输出创建清单的完整路径、项目数量, 并提醒用户每次运行都会创建新文件. 总结:
- 选择的焦点区域
- 深度级别
- 执行者/时间
- 任何整合的用户明确指定的必需项目
**重要说明**: 每次 `/speckit.checklist` 命令调用都会创建一个使用简短描述性名称的清单文件, 除非文件已存在. 这允许:
- 创建多种不同类型的清单(例如: `ux.md`, `test.md`, `security.md`)
- 使用简单、易记的文件名来表明清单用途
-`checklists/` 文件夹中轻松识别和导航
为避免混乱, 请使用描述性类型, 并在完成后清理过时的清单.
## 示例清单类型和示例项目
**UX 需求质量**: `ux.md`
示例项目(测试需求, 而非实现):
- "Are visual hierarchy requirements defined with measurable criteria? [Clarity, Spec §FR-1]"
- "Is the number and positioning of UI elements explicitly specified? [Completeness, Spec §FR-1]"
- "Are interaction state requirements (hover, focus, active) consistently defined? [Consistency]"
- "Are accessibility requirements specified for all interactive elements? [Coverage, Gap]"
- "Is fallback behavior defined when images fail to load? [Edge Case, Gap]"
- "Can 'prominent display' be objectively measured? [Measurability, Spec §FR-4]"
**API 需求质量**: `api.md`
示例项目:
- "Are error response formats specified for all failure scenarios? [Completeness]"
- "Are rate limiting requirements quantified with specific thresholds? [Clarity]"
- "Are authentication requirements consistent across all endpoints? [Consistency]"
- "Are retry/timeout requirements defined for external dependencies? [Coverage, Gap]"
- "Is versioning strategy documented in requirements? [Gap]"
**性能需求质量**: `performance.md`
示例项目:
- "Are performance requirements quantified with specific metrics? [Clarity]"
- "Are performance targets defined for all critical user journeys? [Coverage]"
- "Are performance requirements under different load conditions specified? [Completeness]"
- "Can performance requirements be objectively measured? [Measurability]"
- "Are degradation requirements defined for high-load scenarios? [Edge Case, Gap]"
**安全需求质量**: `security.md`
示例项目:
- "Are authentication requirements specified for all protected resources? [Coverage]"
- "Are data protection requirements defined for sensitive information? [Completeness]"
- "Is the threat model documented and requirements aligned to it? [Traceability]"
- "Are security requirements consistent with compliance obligations? [Consistency]"
- "Are security failure/breach response requirements defined? [Gap, Exception Flow]"
## 反例: 什么不要做
**❌ 错误 - 这些测试实现, 而非需求: **
```markdown
- [ ] CHK001 - Verify landing page displays 3 episode cards [Spec §FR-001]
- [ ] CHK002 - Test hover states work correctly on desktop [Spec §FR-003]
- [ ] CHK003 - Confirm logo click navigates to home page [Spec §FR-010]
- [ ] CHK004 - Check that related episodes section shows 3-5 items [Spec §FR-005]
```
**✅ 正确 - 这些测试需求质量: **
```markdown
- [ ] CHK001 - Are the number and layout of featured episodes explicitly specified? [Completeness, Spec §FR-001]
- [ ] CHK002 - Are hover state requirements consistently defined for all interactive elements? [Consistency, Spec §FR-003]
- [ ] CHK003 - Are navigation requirements clear for all clickable brand elements? [Clarity, Spec §FR-010]
- [ ] CHK004 - Is the selection criteria for related episodes documented? [Gap, Spec §FR-005]
- [ ] CHK005 - Are loading state requirements defined for asynchronous episode data? [Gap]
- [ ] CHK006 - Can "visual hierarchy" requirements be objectively measured? [Measurability, Spec §FR-001]
```
**关键区别: **
- 错误: 测试系统是否正常工作
- 正确: 测试需求是否编写正确
- 错误: 验证行为
- 正确: 验证需求质量
- 错误: "它是否做 X"
- 正确: "X 是否明确指定?"
+179
View File
@@ -0,0 +1,179 @@
---
description: 通过提出最多 5 个高度针对性的澄清问题, 识别当前功能规范中未充分说明的领域, 并将答案编码回规范中.
handoffs:
- label: 构建技术计划
agent: speckit.plan
prompt: 为规范创建计划。我正在构建...
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 概述
目标: 检测并减少活跃功能规范中的模糊性或缺失的决策点, 并将澄清内容直接记录在规范文件中.
注意: 此澄清工作流应在调用 `/speckit.plan` 之前运行(并完成). 如果用户明确表示他们跳过澄清(例如, 探索性原型), 你可以继续, 但必须警告下游返工风险增加.
执行步骤:
1. 从仓库根目录运行 `.specify/scripts/powershell/check-prerequisites.ps1 -Json -PathsOnly` **一次**(组合 `--json --paths-only` 模式 / `-Json -PathsOnly`). 解析最小 JSON 负载字段:
- `FEATURE_DIR`
- `FEATURE_SPEC`
- (可选捕获 `IMPL_PLAN``TASKS` 用于未来的链式流程. )
- 如果 JSON 解析失败, 中止并指示用户重新运行 `/speckit.specify` 或验证功能分支环境.
- 对于参数中包含单引号的情况(如 "I'm Groot"), 使用转义语法: 例如 'I'\''m Groot'(或优先使用双引号: "I'm Groot").
2. 加载当前规范文件. 使用此分类法执行结构化模糊性和覆盖范围扫描. 对于每个类别, 标记状态: 清晰 / 部分 / 缺失. 生成用于优先级排序的内部覆盖范围图(除非不会提问, 否则不输出原始图).
功能范围与行为:
- 核心用户目标和成功标准
- 明确的超出范围声明
- 用户角色 / 角色区分
领域与数据模型:
- 实体、属性、关系
- 身份和唯一性规则
- 生命周期 / 状态转换
- 数据量 / 规模假设
交互与 UX 流程:
- 关键用户旅程 / 序列
- 错误 / 空白 / 加载状态
- 可访问性或本地化说明
非功能性质量属性:
- 性能(延迟、吞吐量目标)
- 可扩展性(水平 / 垂直、限制)
- 可靠性和可用性(正常运行时间、恢复期望)
- 可观察性(日志、指标、追踪信号)
- 安全性和隐私(身份验证 / 授权、数据保护、威胁假设)
- 合规性 / 监管约束(如有)
集成与外部依赖:
- 外部服务 / API 和故障模式
- 数据导入 / 导出格式
- 协议 / 版本控制假设
边缘情况与故障处理:
- 负面场景
- 速率限制 / 节流
- 冲突解决(例如, 并发编辑)
约束与权衡:
- 技术约束(语言、存储、托管)
- 明确的权衡或被拒绝的替代方案
术语与一致性:
- 规范术语表术语
- 避免的同义词 / 已弃用术语
完成信号:
- 验收标准可测试性
- 可衡量的完成定义风格指标
其他 / 占位符:
- TODO 标记 / 未解决的决策
- 缺少量化的模糊形容词("robust"、"intuitive")
对于每个处于部分或缺失状态的类别, 添加候选问题机会, 除非:
- 澄清不会实质性地改变实施或验证策略
- 信息更适合推迟到规划阶段(内部记录)
3. (内部)生成候选澄清问题的优先级队列(最多5个). 不要一次性输出所有问题. 应用这些约束:
- 整个会话最多10个问题.
- 每个问题必须可以用以下任一方式回答:
* 简短的多项选择(2-5个不同的、互斥的选项), 或
* 单词 / 短语答案(明确约束: "Answer in <=5 words").
- 仅包含答案实质上影响架构、数据建模、任务分解、测试设计、UX 行为、运营准备或合规性验证的问题.
- 确保类别覆盖平衡: 尝试首先覆盖最高影响的未解决类别; 避免在单个高影响领域(例如, 安全态势)未解决时询问两个低影响问题.
- 排除已回答的问题、琐碎的风格偏好或规划级别的执行细节(除非阻碍正确性).
- 偏好减少下游返工风险或防止不一致验收测试的澄清.
- 如果超过5个类别仍未解决, 通过(影响 * 不确定性)启发式选择前5个.
4. 顺序提问流程(交互式):
- 一次只提出**确切一个**问题.
- 对于多项选择题:
* **分析所有选项**并基于以下确定**最合适的选项**:
- 项目类型的最佳实践
- 类似实现中的常见模式
- 风险降低(安全性、性能、可维护性)
- 与规范中可见的任何明确项目目标或约束的一致性
* 在顶部突出显示你的**推荐选项**并附上清晰推理(1-2句话解释为什么这是最佳选择).
* 格式为: `**Recommended:** Option [X] - <reasoning>`
* 然后将所有选项渲染为 Markdown 表格:
| Option | Description |
|--------|-------------|
| A | <Option A description> |
| B | <Option B description> |
| C | <Option C description> | (根据需要添加 D/E, 最多5个)
| Short | Provide a different short answer (<=5 words) | (仅在自由形式替代方案合适时包含)
* 表格后添加: `You can reply with the option letter (e.g., "A"), accept the recommendation by saying "yes" or "recommended", or provide your own short answer.`
- 对于简答题风格(没有有意义的不同选项):
* 基于最佳实践和上下文提供你的**建议答案**.
* 格式为: `**Suggested:** <your proposed answer> - <brief reasoning>`
* 然后输出: `Format: Short answer (<=5 words). You can accept the suggestion by saying "yes" or "suggested", or provide your own answer.`
- 用户回答后:
* 如果用户回复 "yes"、"recommended" 或 "suggested", 使用你之前陈述的推荐 / 建议作为答案.
* 否则, 验证答案映射到一个选项或符合 <=5 个词的约束.
* 如果模糊, 要求快速消除歧义(计数仍属于同一问题; 不前进).
* 一旦满意, 将其记录在工作内存中(尚未写入磁盘)并移动到下一个排队的问题.
- 在以下情况时停止进一步提问:
* 所有关键模糊性早期解决(剩余排队项目变得不必要), 或
* 用户发出完成信号("done"、"good"、"no more"), 或
* 你达到5个已问问题.
- 永远不要提前揭示未来的排队问题.
- 如果开始时没有有效问题, 立即报告没有关键模糊性.
5. 每次接受答案后的集成(增量更新方法):
- 维护规范的内存表示(开始时加载一次)加上原始文件内容.
- 对于此会话中第一个集成的答案:
* 确保 `## Clarifications` 部分存在(如果缺失, 根据规范模板在最高级别的上下文 / 概述部分之后创建).
* 在其下, 创建(如果不存在)今天的 `### Session YYYY-MM-DD` 子标题.
- 接受后立即追加项目符号行: `- Q: <question> → A: <final answer>`.
- 然后立即将澄清应用到最合适的部分:
* 功能模糊性 → 更新或在功能需求中添加项目符号.
* 用户交互 / 角色区分 → 更新用户故事或角色子部分(如果存在), 包含澄清的角色、约束或场景.
* 数据形状 / 实体 → 更新数据模型(添加字段、类型、关系)保持顺序; 简洁地记录添加的约束.
* 非功能性约束 → 在非功能性 / 质量属性部分添加 / 修改可衡量标准(将模糊形容词转换为指标或明确目标).
* 边缘情况 / 负面流程 → 在边缘情况 / 错误处理下添加新项目符号(或如果模板提供占位符则创建此类子部分).
* 术语冲突 → 在整个规范中规范化术语; 仅在必要时通过添加一次 `(formerly referred to as "X")` 保留原始术语.
- 如果澄清使早期模糊声明无效, 替换该声明而不是重复; 不留用过时的矛盾文本.
- 每次集成后保存规范文件以最小化上下文丢失风险(原子覆盖).
- 保持格式: 不重新排序不相关的部分; 保持标题层次结构完整.
- 保持每个插入的澄清最小化和可测试(避免叙述性偏离).
6. 验证(每次写入后执行, 最终再进行一次完整检查):
- 澄清会话每个接受的答案只包含一个项目符号(无重复).
- 总共询问(接受)的问题 ≤ 5.
- 更新的部分不包含新答案旨在解决的持续模糊占位符.
- 没有矛盾的早期声明保留(扫描已删除的现在无效的替代选择).
- Markdown 结构有效; 仅允许新标题: `## Clarifications``### Session YYYY-MM-DD`.
- 术语一致性: 所有更新部分使用相同的规范术语.
7. 将更新的规范写回 `FEATURE_SPEC`.
8. 报告完成(提问循环结束或提前终止后):
- 询问和回答的问题数量.
- 更新规范的路径.
- 涉及的部分(列出名称).
- 覆盖范围摘要表, 列出每个分类类别及状态: 已解决(曾是部分 / 缺失并已处理)、已推迟(超过问题配额或更适合规划)、清晰(已足够)、未完成(仍是部分 / 缺失但影响低).
- 如果有任何未完成或已推迟的剩余, 建议是继续到 `/speckit.plan` 还是在规划后再次运行 `/speckit.clarify`.
- 建议的下一个命令.
行为规则:
- 如果没有发现有意义的模糊性(或所有潜在问题都是低影响的), 回应: "No critical ambiguities detected worth formal clarification." 并建议继续.
- 如果规范文件缺失, 指示用户首先运行 `/speckit.specify`(不要在此创建新规范).
- 永远不要超过总共5个询问的问题(单个问题的澄清重试不计为新问题).
- 避免推测性技术堆栈问题, 除非缺失阻碍功能清晰性.
- 尊重用户提前终止信号("stop"、"done"、"proceed").
- 如果由于完全覆盖而没有提问, 输出紧凑的覆盖范围摘要(所有类别清晰)然后建议前进.
- 如果达到配额但仍有未解决的高影响类别, 在已推迟下明确标记它们并附上理由.
优先级排序的上下文: $ARGUMENTS
+81
View File
@@ -0,0 +1,81 @@
---
description: 从交互式或提供的原则输入创建或更新项目章程, 确保所有依赖模板保持同步.
handoffs:
- label: 构建规范
agent: speckit.specify
prompt: 基于更新的章程实现功能规范。我想要构建...
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 概述
你正在更新位于 `.specify/memory/constitution.md` 的项目章程. 该文件是一个包含方括号占位符标记的模板(例如 `[PROJECT_NAME]``[PRINCIPLE_1_NAME]`). 你的工作是(a)收集/推导具体值, (b)精确填充模板, 以及(c)将任何修改传播到相关依赖项中.
遵循此执行流程:
1. 加载位于 `.specify/memory/constitution.md` 的现有章程模板.
- 识别每个 `[ALL_CAPS_IDENTIFIER]` 形式的占位符标记.
**重要提示**: 用户可能需要比模板中使用的原则更少或更多. 如果指定了数字, 请遵循该数字 - 遵循通用模板. 你将相应地更新文档.
2. 为占位符收集/推导值:
- 如果用户输入(对话)提供了值, 则使用它.
- 否则从现有仓库上下文推断(README、文档、先前的章程版本(如果嵌入)).
- 对于治理日期: `RATIFICATION_DATE` 是原始采用日期(如果未知, 请询问或标记 TODO), `LAST_AMENDED_DATE` 是今天(如果进行了更改), 否则保留之前的日期.
- `CONSTITUTION_VERSION` 必须根据语义版本控制规则递增:
* MAJOR(主版本): 向后不兼容的治理/原则删除或重新定义.
* MINOR(次版本): 新原则/部分添加或实质性扩展指导.
* PATCH(补丁版本): 澄清、措辞、拼写错误修复、非语义优化.
- 如果版本递增类型不明确, 请在最终确定之前提出理由.
3. 起草更新后的章程内容:
- 用具体文本替换每个占位符(除了项目选择尚未定义的故意保留的模板槽位外, 不留下括号标记——明确说明任何保留的槽位).
- 保留标题层次结构, 一旦替换可以删除注释, 除非它们仍然提供澄清指导.
- 确保每个原则部分: 简洁的名称行、捕获不可协商规则的段落(或项目符号列表)、如果不明显则提供明确的理由.
- 确保治理部分列出修改程序、版本控制策略和合规审查期望.
4. 一致性传播检查清单(将先前的检查清单转换为主动验证):
- 读取 `.specify/templates/plan-template.md` 并确保任何"章程检查"或规则与更新的原则保持一致.
- 读取 `.specify/templates/spec-template.md` 进行范围/需求对齐——如果章程添加/删除强制部分或约束, 则更新.
- 读取 `.specify/templates/tasks-template.md` 并确保任务分类反映新的或删除的原则驱动的任务类型(例如, 可观测性、版本控制、测试纪律).
- 读取 `.specify/templates/commands/*.md` 中的每个命令文件(包括此文件)以验证在需要通用指导时没有过时的引用(如仅限 CLAUDE 的代理特定名称).
- 读取任何运行时指导文档(例如 `README.md``docs/quickstart.md` 或代理特定指导文件(如果存在)). 更新对已更改原则的引用.
5. 生成同步影响报告(在更新后作为 HTML 注释前置到章程文件顶部):
- 版本更改: 旧版本 → 新版本
- 修改的原则列表(如果重命名, 则为旧标题 → 新标题)
- 添加的部分
- 删除的部分
- 需要更新的模板(✅ 已更新 / ⚠ 待处理)及文件路径
- 如果有任何占位符故意延迟, 则提供后续 TODO.
6. 最终输出前的验证:
- 没有剩余的未解释的括号标记.
- 版本行与报告匹配.
- 日期采用 ISO 格式 YYYY-MM-DD.
- 原则是声明性的、可测试的, 并且没有模糊语言("should" → 在适当的地方用 MUST/SHOULD 理由替换).
7. 将完成的章程写回 `.specify/memory/constitution.md`(覆盖).
8. 向用户输出最终摘要, 包括:
- 新版本和递增理由.
- 任何标记为手动后续处理的文件.
- 建议的提交消息(例如 `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).
格式和样式要求:
- 完全按照模板使用 Markdown 标题(不要降级/升级级别).
- 换行长理由行以保持可读性(理想情况下 <100 个字符), 但不要用尴尬的换行强制执行.
- 在部分之间保持单个空行.
- 避免尾随空白.
如果用户提供部分更新(例如, 仅一个原则修订), 仍然执行验证和版本决策步骤.
如果缺少关键信息(例如, 批准日期确实未知), 请插入 `TODO(<FIELD_NAME>): explanation` 并包含在同步影响报告中的延迟项下.
不要创建新模板; 始终操作现有的 `.specify/memory/constitution.md` 文件.
+74
View File
@@ -0,0 +1,74 @@
---
description: 针对项目中的bug进行精确修复,尽量减少对其他代码的影响
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前,你**必须**考虑用户输入(如果不为空)。用户应该提供bug描述、相关文件路径和可能的修复方向。
## 目标
提供一个结构化的bug修复流程,通过精确的修改定位和最小化的代码变更,修复项目中的bug,同时避免引入新的问题或破坏现有功能。
## 操作约束
**最小化修改原则**:只修改与bug直接相关的代码,避免对其他功能造成影响。
**完整性保证**:确保bug修复是完整的,不仅解决表面症状,还要处理根本原因。
**测试优先**:在进行修复前,确保有适当的测试来验证bug的存在和修复的有效性。
**文档更新**:如果bug修复影响了API或行为,确保更新相应的文档。
## 执行步骤
### 1. 初始化bug修复上下文
从仓库根目录运行一次 `.specify/scripts/powershell/check-prerequisites.ps1 -Json` 并解析 JSON 以获取项目环境信息。这将帮助我们了解项目的基本结构和工具链。
### 2. 收集和分析bug信息
- **理解bug**:根据用户输入,明确理解bug的症状、复现步骤和预期行为
- **定位相关文件**:确定可能包含bug的文件和代码区域
- **分析错误日志**:如果有错误日志,分析异常堆栈和错误信息
- **版本历史检查**:查看最近的代码变更,识别可能引入bug的提交
### 3. 创建修复环境
- **创建bug修复分支**:基于当前主分支创建一个专门的bug修复分支
- **设置测试环境**:确保有适当的测试环境可以验证bug和修复
- **备份相关文件**:在修改前备份可能受影响的关键文件
### 4. 实施修复
- **精确修改**:针对已识别的问题进行最小化的代码修改
- **遵循代码风格**:确保修复代码遵循项目现有的代码风格和规范
- **添加必要注释**:为修复添加清晰的注释,说明修复的原因和方法
- **考虑边界情况**:确保修复不会在边界情况下导致新的问题
### 5. 验证修复
- **执行测试**:运行项目的测试套件,确保所有测试通过
- **复现验证**:使用原始的复现步骤,确认bug已被修复
- **回归测试**:执行可能受影响功能的回归测试
- **性能检查**:如果适用,验证修复不会对性能造成负面影响
### 6. 文档和提交
- **更新文档**:如果修复影响了API或功能行为,更新相应的文档
- **编写清晰的提交信息**:提交信息应包含bug描述、修复方法和相关问题引用
- **代码审查准备**:准备修复的代码审查材料,包括问题描述、修复策略和测试结果
## 输出格式
修复过程完成后,输出一个结构化的报告,包括:
1. **Bug摘要**:对bug的简要描述和影响范围
2. **修复概述**:所做的修改概述和修复原理
3. **验证结果**:测试结果和验证方法
4. **潜在风险**:任何可能的风险或需要后续关注的问题
5. **建议的后续步骤**:例如代码审查、部署计划等
+131
View File
@@ -0,0 +1,131 @@
---
description: 通过处理和执行 tasks.md 中定义的所有任务来执行实施计划
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 概要
1. 从仓库根目录运行 `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` 并解析 FEATURE_DIR 和 AVAILABLE_DOCS 列表. 所有路径必须是绝对路径. 对于参数中的单引号如 "I'm Groot", 使用转义语法: 例如 'I'\''m Groot'(或尽可能使用双引号: "I'm Groot").
2. **检查清单状态**(如果 FEATURE_DIR/checklists/ 存在):
- 扫描 checklists/ 目录中的所有清单文件
- 对于每个清单, 统计:
* 总项目数: 所有匹配 `- [ ]``- [X]``- [x]` 的行
* 已完成项目数: 匹配 `- [X]``- [x]` 的行
* 未完成项目数: 匹配 `- [ ]` 的行
- 创建状态表:
```
| Checklist | Total | Completed | Incomplete | Status |
|-----------|-------|-----------|------------|--------|
| ux.md | 12 | 12 | 0 | ✓ PASS |
| test.md | 8 | 5 | 3 | ✗ FAIL |
| security.md | 6 | 6 | 0 | ✓ PASS |
```
- 计算总体状态:
* **PASS**: 所有清单都有 0 个未完成项目
* **FAIL**: 一个或多个清单有未完成项目
- **如果任何清单未完成**:
* 显示包含未完成项目数的表格
* **停止**并询问: "Some checklists are incomplete. Do you want to proceed with implementation anyway? (yes/no)"
* 在继续之前等待用户响应
* 如果用户说 "no" 或 "wait" 或 "stop", 停止执行
* 如果用户说 "yes" 或 "proceed" 或 "continue", 继续到步骤 3
- **如果所有清单都已完成**:
* 显示显示所有清单通过的表格
* 自动继续到步骤 3
3. 加载和分析实施上下文:
- **必需**: 读取 tasks.md 获取完整任务列表和执行计划
- **必需**: 读取 plan.md 获取技术栈、架构和文件结构
- **如果存在**: 读取 data-model.md 获取实体和关系
- **如果存在**: 读取 contracts/ 获取 API 规范和测试要求
- **如果存在**: 读取 research.md 获取技术决策和约束
- **如果存在**: 读取 quickstart.md 获取集成场景
4. **项目设置验证**:
- **必需**: 基于实际项目设置创建/验证忽略文件:
**检测和创建逻辑**:
- 检查以下命令是否成功以确定是否为 git 仓库(如果是, 创建/验证 .gitignore):
```sh
git rev-parse --git-dir 2>/dev/null
```
- 检查 Dockerfile* 是否存在或 plan.md 中是否提到 Docker → 创建/验证 .dockerignore
- 检查 .eslintrc* 或 eslint.config.* 是否存在 → 创建/验证 .eslintignore
- 检查 .prettierrc* 是否存在 → 创建/验证 .prettierignore
- 检查 .npmrc 或 package.json 是否存在 → 创建/验证 .npmignore(如果发布)
- 检查 terraform 文件(*.tf)是否存在 → 创建/验证 .terraformignore
- 检查是否需要 .helmignore(存在 helm charts)→ 创建/验证 .helmignore
**如果忽略文件存在**: 验证它包含基本模式, 仅追加缺失的关键模式
**如果忽略文件缺失**: 为检测到的技术创建完整模式集
**按技术的通用模式**(来自 plan.md 技术栈):
- **Node.js/JavaScript**: `node_modules/`, `dist/`, `build/`, `*.log`, `.env*`
- **Python**: `__pycache__/`, `*.pyc`, `.venv/`, `venv/`, `dist/`, `*.egg-info/`
- **Java**: `target/`, `*.class`, `*.jar`, `.gradle/`, `build/`
- **C#/.NET**: `bin/`, `obj/`, `*.user`, `*.suo`, `packages/`
- **Go**: `*.exe`, `*.test`, `vendor/`, `*.out`
- **Ruby**: `.bundle/`, `log/`, `tmp/`, `*.gem`, `vendor/bundle/`
- **PHP**: `vendor/`, `*.log`, `*.cache`, `*.env`
- **Rust**: `target/`, `debug/`, `release/`, `*.rs.bk`, `*.rlib`, `*.prof*`, `.idea/`, `*.log`, `.env*`
- **Kotlin**: `build/`, `out/`, `.gradle/`, `.idea/`, `*.class`, `*.jar`, `*.iml`, `*.log`, `.env*`
- **C++**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.so`, `*.a`, `*.exe`, `*.dll`, `.idea/`, `*.log`, `.env*`
- **C**: `build/`, `bin/`, `obj/`, `out/`, `*.o`, `*.a`, `*.so`, `*.exe`, `Makefile`, `config.log`, `.idea/`, `*.log`, `.env*`
- **Swift**: `.build/`, `DerivedData/`, `*.swiftpm/`, `Packages/`
- **R**: `.Rproj.user/`, `.Rhistory`, `.RData`, `.Ruserdata`, `*.Rproj`, `packrat/`, `renv/`
- **通用**: `.DS_Store`, `Thumbs.db`, `*.tmp`, `*.swp`, `.vscode/`, `.idea/`
**工具特定模式**:
- **Docker**: `node_modules/`, `.git/`, `Dockerfile*`, `.dockerignore`, `*.log*`, `.env*`, `coverage/`
- **ESLint**: `node_modules/`, `dist/`, `build/`, `coverage/`, `*.min.js`
- **Prettier**: `node_modules/`, `dist/`, `build/`, `coverage/`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
- **Terraform**: `.terraform/`, `*.tfstate*`, `*.tfvars`, `.terraform.lock.hcl`
- **Kubernetes/k8s**: `*.secret.yaml`, `secrets/`, `.kube/`, `kubeconfig*`, `*.key`, `*.crt`
5. 解析 tasks.md 结构并提取:
- **任务阶段**: 设置、测试、核心、集成、完善
- **任务依赖**: 顺序执行与并行执行规则
- **任务详情**: ID、描述、文件路径、并行标记 [P]
- **执行流程**: 顺序和依赖要求
6. 按照任务计划执行实施:
- **分阶段执行**: 在进入下一阶段之前完成每个阶段
- **遵循依赖**: 按顺序运行顺序任务, 并行任务 [P] 可以一起运行
- **遵循 TDD 方法**: 在相应的实施任务之前执行测试任务
- **基于文件的协调**: 影响相同文件的任务必须顺序运行
- **验证检查点**: 在继续之前验证每个阶段的完成
7. 实施执行规则:
- **首先设置**: 初始化项目结构、依赖、配置
- **代码前测试**: 如果需要为合约、实体和集成场景编写测试
- **核心开发**: 实施模型、服务、CLI 命令、端点
- **集成工作**: 数据库连接、中间件、日志、外部服务
- **完善和验证**: 单元测试、性能优化、文档
8. 进度跟踪和错误处理:
- 在每个完成的任务后报告进度
- 如果任何非并行任务失败, 停止执行
- 对于并行任务 [P], 继续成功的任务, 报告失败的任务
- 提供带有调试上下文的清晰错误消息
- 如果实施无法继续, 建议下一步操作
- **重要** 对于已完成的任务, 确保在任务文件中将任务标记为 [X].
9. 完成验证:
- 验证所有必需任务已完成
- 检查实施的功能是否与原始规范匹配
- 验证测试通过且覆盖率满足要求
- 确认实施遵循技术计划
- 报告最终状态并附上已完成工作的摘要
注意: 此命令假设 tasks.md 中存在完整的任务分解. 如果任务不完整或缺失, 建议首先运行 `/tasks` 重新生成任务列表.
+89
View File
@@ -0,0 +1,89 @@
---
description: 执行实施规划工作流, 使用计划模板生成设计制品.
handoffs:
- label: 创建任务
agent: speckit.tasks
prompt: 将计划分解为任务
send: true
- label: 创建检查清单
agent: speckit.checklist
prompt: 为需求创建质量检查清单
send: true
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 大纲
1. **设置**: 从仓库根目录运行 `.specify/scripts/powershell/setup-plan.ps1 -Json` 并解析 JSON 获取 FEATURE_SPEC、IMPL_PLAN、SPECS_DIR、BRANCH. 对于参数中的单引号如 "I'm Groot", 使用转义语法: 例如 'I'\''m Groot'(或尽可能使用双引号: "I'm Groot").
2. **加载上下文**: 读取 FEATURE_SPEC 和 `.specify/memory/constitution.md`. 加载 IMPL_PLAN 模板(已复制).
3. **执行计划工作流**: 按照 IMPL_PLAN 模板中的结构:
- 填充技术上下文(将未知项标记为 NEEDS CLARIFICATION)
- 从章程文档填充章程检查部分
- 评估关卡(如果违规无正当理由则报错)
- 阶段 0: 生成 research.md(解决所有 NEEDS CLARIFICATION)
- 阶段 1: 生成 data-model.md、contracts/、quickstart.md
- 阶段 1: 通过运行代理脚本更新代理上下文
- 设计后重新评估章程检查
4. **停止并报告**: 命令在阶段 2 规划后结束. 报告分支、IMPL_PLAN 路径和生成的制品.
## 阶段
### 阶段 0: 大纲与研究
1. **从上述技术上下文中提取未知项**:
- 每个 NEEDS CLARIFICATION → 研究任务
- 每个依赖项 → 最佳实践任务
- 每个集成 → 模式任务
2. **生成和分发研究代理**:
```
For each unknown in Technical Context:
Task: "Research {unknown} for {feature context}"
For each technology choice:
Task: "Find best practices for {tech} in {domain}"
```
3. **在 `research.md` 中整合发现**, 使用格式:
- Decision: [选择了什么]
- Rationale: [为什么选择]
- Alternatives considered: [还评估了什么]
**输出**: research.md, 所有 NEEDS CLARIFICATION 已解决
### 阶段 1: 设计与合同
**前提条件**: `research.md` 完成
1. **从功能规范中提取实体** → `data-model.md`:
- 实体名称、字段、关系
- 来自需求的验证规则
- 状态转换(如适用)
2. **从功能需求生成 API 合同**:
- 每个用户操作 → 端点
- 使用标准 REST/GraphQL 模式
- 将 OpenAPI/GraphQL 模式输出到 `/contracts/`
3. **代理上下文更新**:
- 运行 `.specify/scripts/powershell/update-agent-context.ps1 -AgentType claude`
- 这些脚本检测正在使用哪个 AI 代理
- 更新相应的代理特定上下文文件
- 仅添加当前计划中的新技术
- 保留标记之间的手动添加内容
**输出**: data-model.md、/contracts/*、quickstart.md、代理特定文件
## 关键规则
- 使用绝对路径
- 关卡失败或未解决的澄清事项时报错
+237
View File
@@ -0,0 +1,237 @@
---
description: 从自然语言功能描述创建或更新功能规范.
handoffs:
- label: 构建技术计划
agent: speckit.plan
prompt: 为规范创建计划。我正在构建...
- label: 澄清规范需求
agent: speckit.clarify
prompt: 分析规范的完整性和清晰度
send: true
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 概述
用户在触发消息中 `/speckit.specify` 后输入的文本**就是**功能描述. 假设你始终可以在本次对话中访问它, 即使下面字面上显示 `$ARGUMENTS`. 除非用户提供了空命令, 否则不要要求用户重复.
基于该功能描述, 执行以下操作:
1. **为分支生成一个简短名称**(2-4个词):
- 分析功能描述并提取最有意义的关键词
- 创建一个2-4个词的简短名称, 捕捉功能的核心
- 尽可能使用动-名词格式(例如, "add-user-auth", "fix-payment-bug")
- 保留技术术语和缩写(OAuth2、API、JWT等)
- 保持简洁但足够描述性, 便于快速理解功能
- 示例:
- "I want to add user authentication" → "user-auth"
- "Implement OAuth2 integration for the API" → "oauth2-api-integration"
- "Create a dashboard for analytics" → "analytics-dashboard"
- "Fix payment processing timeout bug" → "fix-payment-timeout"
2. 从仓库根目录运行脚本 `.specify/scripts/powershell/create-new-feature.ps1 -Json "$ARGUMENTS"` **使用简短名称参数**并解析其 JSON 输出以获取 BRANCH_NAME 和 SPEC_FILE. 所有文件路径必须是绝对路径.
**重要说明**:
- 将第1步创建的2-4词简短名称作为参数附加到 `.specify/scripts/powershell/create-new-feature.ps1 -Json "$ARGUMENTS"` 命令, 功能描述作为最终参数.
- Bash 示例: `--short-name "your-generated-short-name" "功能描述内容"`
- PowerShell 示例: `-ShortName "your-generated-short-name" "功能描述内容"`
- 对于参数中包含单引号的情况(如 "I'm Groot"), 使用转义语法: 例如 'I'\''m Groot'(或优先使用双引号: "I'm Groot")
- 你必须且只能运行此脚本一次
- JSON 输出会显示在终端中 - 请始终参考该输出来获取你要查找的实际内容
3. 加载 `.specify/templates/spec-template.md` 以了解必需的章节.
4. 遵循此执行流程:
1. 从输入解析用户描述
如果为空: 错误 "未提供功能描述"
2. 从描述中提取关键概念
识别: 参与者、操作、数据、约束
3. 对于不明确的方面:
- 基于上下文和行业标准做出有根据的猜测
- 仅在以下情况下标记为 [NEEDS CLARIFICATION: 具体问题]:
- 选择显著影响功能范围或用户体验
- 存在多个合理的解释且有不同的含义
- 没有合理的默认值
- **限制: 最多 3 个 [NEEDS CLARIFICATION] 标记**
- 按影响优先级排序: 范围 > 安全/隐私 > 用户体验 > 技术细节
4. 填写用户场景和测试章节
如果没有明确的用户流程: 错误 "无法确定用户场景"
5. 生成功能需求
每个需求必须是可测试的
对未指定的细节使用合理的默认值(在假设章节中记录假设)
6. 定义成功标准
创建可衡量的、技术无关的结果
包括定量指标(时间、性能、数量)和定性措施(用户满意度、任务完成)
每个标准必须无需实现细节即可验证
7. 识别关键实体(如果涉及数据)
8. 返回: 成功(规范准备好进行规划)
5. 使用模板结构将规范写入 SPEC_FILE, 用从功能描述(参数)派生的具体细节替换占位符, 同时保持章节顺序和标题.
6. **规范质量验证**: 编写初始规范后, 根据质量标准进行验证:
a. **创建规范质量检查清单**: 使用检查清单模板结构在 `FEATURE_DIR/checklists/requirements.md` 生成检查清单文件, 包含这些验证项目:
```markdown
# 规范质量检查清单: [功能名称]
**目的**: 在继续规划之前验证规范的完整性和质量
**创建时间**: [日期]
**功能**: [指向 spec.md 的链接]
## 内容质量
- [ ] 无实现细节(语言、框架、API)
- [ ] 专注于用户价值和业务需求
- [ ] 为非技术利益相关者编写
- [ ] 所有必需章节已完成
## 需求完整性
- [ ] 没有 [NEEDS CLARIFICATION] 标记剩余
- [ ] 需求是可测试且明确的
- [ ] 成功标准是可衡量的
- [ ] 成功标准是技术无关的(无实现细节)
- [ ] 所有验收场景已定义
- [ ] 边缘情况已识别
- [ ] 范围明确界定
- [ ] 依赖关系和假设已识别
## 功能准备就绪
- [ ] 所有功能需求都有明确的验收标准
- [ ] 用户场景覆盖主要流程
- [ ] 功能满足成功标准中定义的可衡量结果
- [ ] 没有实现细节泄漏到规范中
## 备注
- 标记为不完整的项目需要在 `/speckit.clarify` 或 `/speckit.plan` 之前更新规范
```
b. **运行验证检查**: 根据每个检查清单项目审查规范:
- 对于每个项目, 确定是否通过或失败
- 记录发现的具体问题(引用相关规范章节)
c. **处理验证结果**:
- **如果所有项目都通过**: 标记检查清单完成并继续步骤 7
- **如果项目失败(不包括 [NEEDS CLARIFICATION])**:
1. 列出失败的项目和具体问题
2. 更新规范以解决每个问题
3. 重新运行验证直到所有项目都通过(最多 3 次迭代)
4. 如果 3 次迭代后仍然失败, 在检查清单备注中记录剩余问题并警告用户
- **如果 [NEEDS CLARIFICATION] 标记仍然存在**:
1. 从规范中提取所有 [NEEDS CLARIFICATION: ...] 标记
2. **限制检查**: 如果存在超过 3 个标记, 仅保留 3 个最关键的(按范围/安全/用户体验影响)并为其余部分做出有根据的猜测
3. 对于每个需要的澄清(最多 3 个), 以以下格式向用户呈现选项:
```markdown
## 问题 [N]: [主题]
**上下文**: [引用相关规范章节]
**我们需要了解**: [来自 NEEDS CLARIFICATION 标记的具体问题]
**建议答案**:
| 选项 | 答案 | 含义 |
|--------|--------|--------------|
| A | [第一个建议答案] | [这对功能意味着什么] |
| B | [第二个建议答案] | [这对功能意味着什么] |
| C | [第三个建议答案] | [这对功能意味着什么] |
| 自定义 | 提供你自己的答案 | [解释如何提供自定义输入] |
**你的选择**: _[等待用户响应]_
```
4. **关键 - 表格格式**: 确保 markdown 表格格式正确:
- 使用一致的间距, 管道符对齐
- 每个单元格内容周围应有空格: `| 内容 |` 而不是 `|内容|`
- 标题分隔符必须至少有 3 个破折号: `|--------|`
- 测试表格在 markdown 预览中正确渲染
5. 按顺序编号问题(Q1、Q2、Q3 - 最多 3 个)
6. 在等待响应之前一起呈现所有问题
7. 等待用户响应所有问题的选择(例如, "Q1: A, Q2: 自定义 - [详情], Q3: B")
8. 通过用用户选择或提供的答案替换每个 [NEEDS CLARIFICATION] 标记来更新规范
9. 在所有澄清解决后重新运行验证
d. **更新检查清单**: 每次验证迭代后, 使用当前的通过/失败状态更新检查清单文件
7. 报告完成情况, 包括分支名称、规范文件路径、检查清单结果以及下一阶段(`/speckit.clarify` 或 `/speckit.plan`)的准备就绪状态.
**注意**: 脚本在写入之前创建并检出新分支并初始化规范文件.
## 通用指南
## 快速指南
- 专注于用户需要**什么**和**为什么**.
- 避免如何实现(不涉及技术栈、API、代码结构).
- 为业务利益相关者编写, 而不是为开发者.
- 不要创建嵌入规范中的任何检查清单. 那将是一个单独的命令.
### 章节要求
- **必需章节**: 每个功能必须完成
- **可选章节**: 仅在与功能相关时包含
- 当章节不适用时, 完全删除它(不要保留为 "N/A")
### AI 生成
当从用户提示创建此规范时:
1. **做出有根据的猜测**: 使用上下文、行业标准和常见模式来填补空白
2. **记录假设**: 在假设章节中记录合理的默认值
3. **限制澄清**: 最多 3 个 [NEEDS CLARIFICATION] 标记 - 仅用于关键决策:
- 显著影响功能范围或用户体验
- 存在多个合理的解释且有不同的含义
- 缺乏任何合理的默认值
4. **优先澄清**: 范围 > 安全/隐私 > 用户体验 > 技术细节
5. **像测试人员一样思考**: 每个模糊的需求都应该在"可测试且明确"的检查清单项目上失败
6. **NEEDS CLARIFICATION 的常见领域**(仅在没有合理默认值时):
- 功能范围和边界(包含/排除特定用例)
- 用户类型和权限(如果可能存在多个冲突的解释)
- 安全/合规要求(当具有法律/财务重要性时)
**合理默认值的示例**(不要询问这些):
- 数据保留: 该行业的行业标准实践
- 性能目标: 标准 Web/移动应用期望, 除非另有说明
- 错误处理: 用户友好的消息和适当的回退
- 认证方法: Web 应用的标准基于会话或 OAuth2
- 集成模式: RESTful API, 除非另有说明
### 成功标准指南
成功标准必须是:
1. **可衡量的**: 包括具体指标(时间、百分比、计数、速率)
2. **技术无关的**: 不提及框架、语言、数据库或工具
3. **以用户为中心的**: 从用户/业务角度描述结果, 而不是系统内部
4. **可验证的**: 无需了解实现细节即可测试/验证
**好的示例**:
- "用户可以在 3 分钟内完成结账"
- "系统支持 10,000 个并发用户"
- "95% 的搜索在 1 秒内返回结果"
- "任务完成率提高 40%"
**坏的示例**(以实现为中心):
- "API 响应时间在 200ms 以下"(太技术化, 使用"用户立即看到结果")
- "数据库可以处理 1000 TPS"(实现细节, 使用面向用户的指标)
- "React 组件高效渲染"(框架特定)
- "Redis 缓存命中率超过 80%"(技术特定)
+120
View File
@@ -0,0 +1,120 @@
---
description: 基于可用的设计文档, 为功能特性生成可执行的、按依赖关系排序的 tasks.md 文件.
handoffs:
- label: 分析一致性
agent: speckit.analyze
prompt: 运行项目一致性分析
send: true
- label: 实施项目
agent: speckit.implement
prompt: 实施项目
send: true
---
## 用户输入
```text
$ARGUMENTS
```
在继续之前, 你**必须**考虑用户输入(如果不为空).
## 概述
1. **设置**: 从仓库根目录运行 `.specify/scripts/powershell/check-prerequisites.ps1 -Json` 并解析 FEATURE_DIR 和 AVAILABLE_DOCS 列表. 所有路径必须是绝对路径. 对于参数值中的单引号如 "I'm Groot", 使用转义语法: 例如 'I'\''m Groot'(或尽可能使用双引号: "I'm Groot").
2. **加载设计文档**: 从 FEATURE_DIR 读取:
- **必需**: plan.md(技术栈、库、结构), spec.md(带优先级的用户故事)
- **可选**: data-model.md(实体), contracts/(API 端点), research.md(决策), quickstart.md(测试场景)
- 注意: 并非所有项目都有所有文档. 基于可用内容生成任务.
3. **执行任务生成流程**(遵循模板结构):
- 加载 plan.md 并提取技术栈、库、项目结构
- **加载 spec.md 并提取带优先级的用户故事(P1、P2、P3 等)**
- 如果存在 data-model.md: 提取实体 → 映射到用户故事
- 如果存在 contracts/: 每个文件 → 映射端点到用户故事
- 如果存在 research.md: 提取决策 → 生成设置任务
- **按用户故事组织生成任务(重点)**:
- 设置任务(所有故事需要的共享基础设施)
- **基础任务(任何用户故事开始前必须完成的先决条件)**
- 对于每个用户故事(按优先级顺序 P1、P2、P3...):
- 组合完成该故事所需的所有任务
- 包含该故事特定的模型、服务、端点、UI 组件
- 标记哪些任务是 [P] 可并行的
- 如果请求测试: 包含该故事特定的测试
- 完善/集成任务(横切关注点)
- **测试是可选的**: 仅在功能规范中明确请求或用户要求 TDD 方法时生成测试任务
- 应用任务规则:
- 不同文件 = 标记 [P] 表示并行
- 相同文件 = 顺序执行(无 [P])
- 如果请求测试: 测试在实现之前(TDD 顺序)
- 按顺序编号任务(T001、T002...)
- 生成显示用户故事完成顺序的依赖关系图
- 为每个用户故事创建并行执行示例
- 验证任务完整性(每个用户故事都有所有必需任务, 可独立测试)
4. **生成 tasks.md**: 使用 `.specify/templates/tasks-template.md` 作为结构, 填充:
- 来自 plan.md 的正确功能名称
- 阶段 1: 设置任务(项目初始化)
- 阶段 2: 基础任务(所有用户故事的阻塞先决条件)
- 阶段 3+: 每个用户故事一个阶段(按 spec.md 中的优先级顺序)
- 每个阶段包括: 故事目标、独立测试标准、测试(如果请求)、实现任务
- 每个任务的清晰 [Story] 标签(US1、US2、US3...)
- 每个故事内可并行任务的 [P] 标记
- 每个故事阶段后的检查点标记
- 最终阶段: 完善与横切关注点
- 按执行顺序编号的任务(T001、T002...)
- 每个任务的清晰文件路径
- 显示故事完成顺序的依赖关系部分
- 每个故事的并行执行示例
- 实现策略部分(MVP 优先, 增量交付)
5. **报告**: 输出生成的 tasks.md 路径和摘要:
- 总任务数
- 每个用户故事的任务数
- 识别的并行机会
- 每个故事的独立测试标准
- 建议的 MVP 范围(通常只是用户故事 1)
任务生成上下文: $ARGUMENTS
tasks.md 应该立即可执行 - 每个任务必须足够具体, 以便 LLM 可以在没有额外上下文的情况下完成它.
## 任务生成规则
**重要**: 测试是可选的. 仅当用户在功能规范中明确请求测试或 TDD 方法时才生成测试任务.
**关键**: 任务必须按用户故事组织, 以实现独立的实现和测试.
1. **来自用户故事(spec.md)** - 主要组织方式:
- 每个用户故事(P1、P2、P3...)都有自己的阶段
- 将所有相关组件映射到它们的故事:
- 该故事所需的模型
- 该故事所需的服务
- 该故事所需的端点/UI
- 如果请求测试: 该故事特定的测试
- 标记故事依赖关系(大多数故事应该是独立的)
2. **来自合约**:
- 将每个合约/端点 → 映射到它服务的用户故事
- 如果请求测试: 每个合约 → 在该故事阶段的实现之前的合约测试任务 [P]
3. **来自数据模型**:
- 将每个实体 → 映射到需要它的用户故事
- 如果实体服务多个故事: 放在最早的故事或设置阶段
- 关系 → 适当故事阶段的服务层任务
4. **来自设置/基础设施**:
- 共享基础设施 → 设置阶段(阶段 1)
- 基础/阻塞任务 → 基础阶段(阶段 2)
- 示例: 数据库模式设置、认证框架、核心库、基础配置
- 这些必须在任何用户故事可以实现之前完成
- 故事特定的设置 → 在该故事的阶段内
5. **排序**:
- 阶段 1: 设置(项目初始化)
- 阶段 2: 基础(阻塞先决条件 - 必须在用户故事之前完成)
- 阶段 3+: 按优先级顺序的用户故事(P1、P2、P3...)
- 每个故事内: 测试(如果请求)→ 模型 → 服务 → 端点 → 集成
- 最终阶段: 完善与横切关注点
- 每个用户故事阶段应该是一个完整的、可独立测试的增量
+28
View File
@@ -0,0 +1,28 @@
---
description: 将现有任务转换为可操作的、按依赖关系排序的 GitHub 议题,基于可用的设计制品。
tools: ['github/github-mcp-server/issue_write']
---
## 用户输入
```text
$ARGUMENTS
```
你必须**在继续之前考虑用户输入**(如果非空)。
## 大纲
1. 从仓库根目录运行 `.specify/scripts/powershell/check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks` 并解析 FEATURE_DIR 和 AVAILABLE_DOCS 列表。所有路径必须是绝对路径。对于参数中的单引号如 "I'm Groot",使用转义语法:例如 'I'\''m Groot'(或尽可能使用双引号:"I'm Groot")。
1. 从执行的脚本中,提取 **任务** 的路径。
1. 通过运行以下命令获取 Git 远程仓库:
```bash
git config --get remote.origin.url
```
**仅当远程仓库是 GITHUB URL 时才继续下一步**
1. 对于列表中的每个任务,使用 GitHub MCP 服务器在与 Git 远程仓库对应的仓库中创建一个新议题。
**在任何情况下都不要在与远程 URL 不匹配的仓库中创建议题**
+50
View File
@@ -0,0 +1,50 @@
# [PROJECT_NAME] 项目章程
<!-- 示例: Spec 章程, TaskFlow 章程等 -->
## 核心原则
### [PRINCIPLE_1_NAME]
<!-- 示例: I. 库优先 -->
[PRINCIPLE_1_DESCRIPTION]
<!-- 示例: 每个功能都从独立的库开始; 库必须是自包含的、可独立测试的、有文档的; 需要明确的目的 - 不允许仅用于组织的库 -->
### [PRINCIPLE_2_NAME]
<!-- 示例: II. CLI 接口 -->
[PRINCIPLE_2_DESCRIPTION]
<!-- 示例: 每个库都通过 CLI 暴露功能; 文本输入/输出协议: stdin/args → stdout, 错误 → stderr; 支持 JSON + 人类可读格式 -->
### [PRINCIPLE_3_NAME]
<!-- 示例: III. 测试优先(不可协商) -->
[PRINCIPLE_3_DESCRIPTION]
<!-- 示例: TDD 强制要求: 编写测试 → 用户批准 → 测试失败 → 然后实现; 严格执行红-绿-重构循环 -->
### [PRINCIPLE_4_NAME]
<!-- 示例: IV. 集成测试 -->
[PRINCIPLE_4_DESCRIPTION]
<!-- 示例: 需要集成测试的重点领域: 新库契约测试、契约变更、服务间通信、共享模式 -->
### [PRINCIPLE_5_NAME]
<!-- 示例: V. 可观测性, VI. 版本控制和破坏性变更, VII. 简单性 -->
[PRINCIPLE_5_DESCRIPTION]
<!-- 示例: 文本 I/O 确保可调试性; 需要结构化日志; 或者: MAJOR.MINOR.BUILD 格式; 或者: 从简单开始, YAGNI 原则 -->
## [SECTION_2_NAME]
<!-- 示例: 附加约束、安全要求、性能标准等 -->
[SECTION_2_CONTENT]
<!-- 示例: 技术栈要求、合规标准、部署策略等 -->
## [SECTION_3_NAME]
<!-- 示例: 开发工作流程、审查流程、质量门禁等 -->
[SECTION_3_CONTENT]
<!-- 示例: 代码审查要求、测试门禁、部署审批流程等 -->
## 治理
<!-- 示例: 章程优先于所有其他实践; 修正需要文档化、批准、迁移计划 -->
[GOVERNANCE_RULES]
<!-- 示例: 所有 PR/审查必须验证合规性; 复杂性必须得到证明; 使用 [GUIDANCE_FILE] 进行运行时开发指导 -->
**版本**: [CONSTITUTION_VERSION] | **批准日期**: [RATIFICATION_DATE] | **最后修正**: [LAST_AMENDED_DATE]
<!-- 示例: 版本: 2.1.1 | 批准日期: 2025-06-13 | 最后修正: 2025-07-16 -->
@@ -0,0 +1,148 @@
#!/usr/bin/env pwsh
# Consolidated prerequisite checking script (PowerShell)
#
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
# It replaces the functionality previously spread across multiple scripts.
#
# Usage: ./check-prerequisites.ps1 [OPTIONS]
#
# OPTIONS:
# -Json Output in JSON format
# -RequireTasks Require tasks.md to exist (for implementation phase)
# -IncludeTasks Include tasks.md in AVAILABLE_DOCS list
# -PathsOnly Only output path variables (no validation)
# -Help, -h Show help message
[CmdletBinding()]
param(
[switch]$Json,
[switch]$RequireTasks,
[switch]$IncludeTasks,
[switch]$PathsOnly,
[switch]$Help
)
$ErrorActionPreference = 'Stop'
# Show help if requested
if ($Help) {
Write-Output @"
Usage: check-prerequisites.ps1 [OPTIONS]
Consolidated prerequisite checking for Spec-Driven Development workflow.
OPTIONS:
-Json Output in JSON format
-RequireTasks Require tasks.md to exist (for implementation phase)
-IncludeTasks Include tasks.md in AVAILABLE_DOCS list
-PathsOnly Only output path variables (no prerequisite validation)
-Help, -h Show this help message
EXAMPLES:
# Check task prerequisites (plan.md required)
.\check-prerequisites.ps1 -Json
# Check implementation prerequisites (plan.md + tasks.md required)
.\check-prerequisites.ps1 -Json -RequireTasks -IncludeTasks
# Get feature paths only (no validation)
.\check-prerequisites.ps1 -PathsOnly
"@
exit 0
}
# Source common functions
. "$PSScriptRoot/common.ps1"
# Get feature paths and validate branch
$paths = Get-FeaturePathsEnv
if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit:$paths.HAS_GIT)) {
exit 1
}
# If paths-only mode, output paths and exit (support combined -Json -PathsOnly)
if ($PathsOnly) {
if ($Json) {
[PSCustomObject]@{
REPO_ROOT = $paths.REPO_ROOT
BRANCH = $paths.CURRENT_BRANCH
FEATURE_DIR = $paths.FEATURE_DIR
FEATURE_SPEC = $paths.FEATURE_SPEC
IMPL_PLAN = $paths.IMPL_PLAN
TASKS = $paths.TASKS
} | ConvertTo-Json -Compress
} else {
Write-Output "REPO_ROOT: $($paths.REPO_ROOT)"
Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
Write-Output "FEATURE_DIR: $($paths.FEATURE_DIR)"
Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
Write-Output "TASKS: $($paths.TASKS)"
}
exit 0
}
# Validate required directories and files
if (-not (Test-Path $paths.FEATURE_DIR -PathType Container)) {
Write-Output "ERROR: Feature directory not found: $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.specify first to create the feature structure."
exit 1
}
if (-not (Test-Path $paths.IMPL_PLAN -PathType Leaf)) {
Write-Output "ERROR: plan.md not found in $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.plan first to create the implementation plan."
exit 1
}
# Check for tasks.md if required
if ($RequireTasks -and -not (Test-Path $paths.TASKS -PathType Leaf)) {
Write-Output "ERROR: tasks.md not found in $($paths.FEATURE_DIR)"
Write-Output "Run /speckit.tasks first to create the task list."
exit 1
}
# Build list of available documents
$docs = @()
# Always check these optional docs
if (Test-Path $paths.RESEARCH) { $docs += 'research.md' }
if (Test-Path $paths.DATA_MODEL) { $docs += 'data-model.md' }
# Check contracts directory (only if it exists and has files)
if ((Test-Path $paths.CONTRACTS_DIR) -and (Get-ChildItem -Path $paths.CONTRACTS_DIR -ErrorAction SilentlyContinue | Select-Object -First 1)) {
$docs += 'contracts/'
}
if (Test-Path $paths.QUICKSTART) { $docs += 'quickstart.md' }
# Include tasks.md if requested and it exists
if ($IncludeTasks -and (Test-Path $paths.TASKS)) {
$docs += 'tasks.md'
}
# Output results
if ($Json) {
# JSON output
[PSCustomObject]@{
FEATURE_DIR = $paths.FEATURE_DIR
AVAILABLE_DOCS = $docs
} | ConvertTo-Json -Compress
} else {
# Text output
Write-Output "FEATURE_DIR:$($paths.FEATURE_DIR)"
Write-Output "AVAILABLE_DOCS:"
# Show status of each potential document
Test-FileExists -Path $paths.RESEARCH -Description 'research.md' | Out-Null
Test-FileExists -Path $paths.DATA_MODEL -Description 'data-model.md' | Out-Null
Test-DirHasFiles -Path $paths.CONTRACTS_DIR -Description 'contracts/' | Out-Null
Test-FileExists -Path $paths.QUICKSTART -Description 'quickstart.md' | Out-Null
if ($IncludeTasks) {
Test-FileExists -Path $paths.TASKS -Description 'tasks.md' | Out-Null
}
}
+137
View File
@@ -0,0 +1,137 @@
#!/usr/bin/env pwsh
# Common PowerShell functions analogous to common.sh
function Get-RepoRoot {
try {
$result = git rev-parse --show-toplevel 2>$null
if ($LASTEXITCODE -eq 0) {
return $result
}
} catch {
# Git command failed
}
# Fall back to script location for non-git repos
return (Resolve-Path (Join-Path $PSScriptRoot "../../..")).Path
}
function Get-CurrentBranch {
# First check if SPECIFY_FEATURE environment variable is set
if ($env:SPECIFY_FEATURE) {
return $env:SPECIFY_FEATURE
}
# Then check git if available
try {
$result = git rev-parse --abbrev-ref HEAD 2>$null
if ($LASTEXITCODE -eq 0) {
return $result
}
} catch {
# Git command failed
}
# For non-git repos, try to find the latest feature directory
$repoRoot = Get-RepoRoot
$specsDir = Join-Path $repoRoot "specs"
if (Test-Path $specsDir) {
$latestFeature = ""
$highest = 0
Get-ChildItem -Path $specsDir -Directory | ForEach-Object {
if ($_.Name -match '^(\d{3})-') {
$num = [int]$matches[1]
if ($num -gt $highest) {
$highest = $num
$latestFeature = $_.Name
}
}
}
if ($latestFeature) {
return $latestFeature
}
}
# Final fallback
return "main"
}
function Test-HasGit {
try {
git rev-parse --show-toplevel 2>$null | Out-Null
return ($LASTEXITCODE -eq 0)
} catch {
return $false
}
}
function Test-FeatureBranch {
param(
[string]$Branch,
[bool]$HasGit = $true
)
# For non-git repos, we can't enforce branch naming but still provide output
if (-not $HasGit) {
Write-Warning "[specify] Warning: Git repository not detected; skipped branch validation"
return $true
}
if ($Branch -notmatch '^[0-9]{3}-') {
Write-Output "ERROR: Not on a feature branch. Current branch: $Branch"
Write-Output "Feature branches should be named like: 001-feature-name"
return $false
}
return $true
}
function Get-FeatureDir {
param([string]$RepoRoot, [string]$Branch)
Join-Path $RepoRoot "specs/$Branch"
}
function Get-FeaturePathsEnv {
$repoRoot = Get-RepoRoot
$currentBranch = Get-CurrentBranch
$hasGit = Test-HasGit
$featureDir = Get-FeatureDir -RepoRoot $repoRoot -Branch $currentBranch
[PSCustomObject]@{
REPO_ROOT = $repoRoot
CURRENT_BRANCH = $currentBranch
HAS_GIT = $hasGit
FEATURE_DIR = $featureDir
FEATURE_SPEC = Join-Path $featureDir 'spec.md'
IMPL_PLAN = Join-Path $featureDir 'plan.md'
TASKS = Join-Path $featureDir 'tasks.md'
RESEARCH = Join-Path $featureDir 'research.md'
DATA_MODEL = Join-Path $featureDir 'data-model.md'
QUICKSTART = Join-Path $featureDir 'quickstart.md'
CONTRACTS_DIR = Join-Path $featureDir 'contracts'
}
}
function Test-FileExists {
param([string]$Path, [string]$Description)
if (Test-Path -Path $Path -PathType Leaf) {
Write-Output "$Description"
return $true
} else {
Write-Output "$Description"
return $false
}
}
function Test-DirHasFiles {
param([string]$Path, [string]$Description)
if ((Test-Path -Path $Path -PathType Container) -and (Get-ChildItem -Path $Path -ErrorAction SilentlyContinue | Where-Object { -not $_.PSIsContainer } | Select-Object -First 1)) {
Write-Output "$Description"
return $true
} else {
Write-Output "$Description"
return $false
}
}
@@ -0,0 +1,327 @@
#!/usr/bin/env pwsh
# Create a new feature
[CmdletBinding()]
param(
[switch]$Json,
[string]$ShortName,
[int]$Number = 0,
[switch]$Help,
[Parameter(ValueFromRemainingArguments = $true)]
[string[]]$FeatureDescription
)
$ErrorActionPreference = 'Stop'
# Show help if requested
if ($Help) {
Write-Host "Usage: ./create-new-feature.ps1 [-Json] [-ShortName <name>] [-Number N] <feature description>"
Write-Host ""
Write-Host "Options:"
Write-Host " -Json Output in JSON format"
Write-Host " -ShortName <name> Provide a custom short name (2-4 words) for the branch"
Write-Host " -Number N Specify branch number manually (overrides auto-detection)"
Write-Host " -Help Show this help message"
Write-Host ""
Write-Host "Examples:"
Write-Host " ./create-new-feature.ps1 'Add user authentication system' -ShortName 'user-auth'"
Write-Host " ./create-new-feature.ps1 'Implement OAuth2 integration for API'"
exit 0
}
# Check if feature description provided
if (-not $FeatureDescription -or $FeatureDescription.Count -eq 0) {
Write-Error "Usage: ./create-new-feature.ps1 [-Json] [-ShortName <name>] <feature description>"
exit 1
}
$featureDesc = ($FeatureDescription -join ' ').Trim()
# Resolve repository root. Prefer git information when available, but fall back
# to searching for repository markers so the workflow still functions in repositories that
# were initialized with --no-git.
function Find-RepositoryRoot {
param(
[string]$StartDir,
[string[]]$Markers = @('.git', '.specify')
)
$current = Resolve-Path $StartDir
while ($true) {
foreach ($marker in $Markers) {
if (Test-Path (Join-Path $current $marker)) {
return $current
}
}
$parent = Split-Path $current -Parent
if ($parent -eq $current) {
# Reached filesystem root without finding markers
return $null
}
$current = $parent
}
}
function Get-HighestNumberFromSpecs {
param([string]$SpecsDir)
$highest = 0
if (Test-Path $SpecsDir) {
Get-ChildItem -Path $SpecsDir -Directory | ForEach-Object {
if ($_.Name -match '^(\d+)') {
$num = [int]$matches[1]
if ($num -gt $highest) { $highest = $num }
}
}
}
return $highest
}
function Get-HighestNumberFromBranches {
param()
$highest = 0
try {
$branches = git branch -a 2>$null
if ($LASTEXITCODE -eq 0) {
foreach ($branch in $branches) {
# Clean branch name: remove leading markers and remote prefixes
$cleanBranch = $branch.Trim() -replace '^\*?\s+', '' -replace '^remotes/[^/]+/', ''
# Extract feature number if branch matches pattern ###-*
if ($cleanBranch -match '^(\d+)-') {
$num = [int]$matches[1]
if ($num -gt $highest) { $highest = $num }
}
}
}
} catch {
# If git command fails, return 0
Write-Verbose "Could not check Git branches: $_"
}
return $highest
}
function Get-NextBranchNumber {
param(
[string]$ShortName,
[string]$SpecsDir
)
# Fetch all remotes to get latest branch info (suppress errors if no remotes)
try {
git fetch --all --prune 2>$null | Out-Null
} catch {
# Ignore fetch errors
}
# Find remote branches matching the pattern using git ls-remote
$remoteBranches = @()
try {
$remoteRefs = git ls-remote --heads origin 2>$null
if ($remoteRefs) {
$remoteBranches = $remoteRefs | Where-Object { $_ -match "refs/heads/(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
if ($_ -match "refs/heads/(\d+)-") {
[int]$matches[1]
}
}
}
} catch {
# Ignore errors
}
# Check local branches
$localBranches = @()
try {
$allBranches = git branch 2>$null
if ($allBranches) {
$localBranches = $allBranches | Where-Object { $_ -match "^\*?\s*(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
if ($_ -match "(\d+)-") {
[int]$matches[1]
}
}
}
} catch {
# Ignore errors
}
# Check specs directory
$specDirs = @()
if (Test-Path $SpecsDir) {
try {
$specDirs = Get-ChildItem -Path $SpecsDir -Directory | Where-Object { $_.Name -match "^(\d+)-$([regex]::Escape($ShortName))$" } | ForEach-Object {
if ($_.Name -match "^(\d+)-") {
[int]$matches[1]
}
}
} catch {
# Ignore errors
}
}
# Combine all sources and get the highest number
$maxNum = 0
foreach ($num in ($remoteBranches + $localBranches + $specDirs)) {
if ($num -gt $maxNum) {
$maxNum = $num
}
}
# Return next number
return $maxNum + 1
}
function ConvertTo-CleanBranchName {
param([string]$Name)
return $Name.ToLower() -replace '[^a-z0-9]', '-' -replace '-{2,}', '-' -replace '^-', '' -replace '-$', ''
}
$fallbackRoot = (Find-RepositoryRoot -StartDir $PSScriptRoot)
if (-not $fallbackRoot) {
Write-Error "Error: Could not determine repository root. Please run this script from within the repository."
exit 1
}
try {
$repoRoot = git rev-parse --show-toplevel 2>$null
if ($LASTEXITCODE -eq 0) {
$hasGit = $true
} else {
throw "Git not available"
}
} catch {
$repoRoot = $fallbackRoot
$hasGit = $false
}
Set-Location $repoRoot
$specsDir = Join-Path $repoRoot 'specs'
New-Item -ItemType Directory -Path $specsDir -Force | Out-Null
# Function to generate branch name with stop word filtering and length filtering
function Get-BranchName {
param([string]$Description)
# Common stop words to filter out
$stopWords = @(
'i', 'a', 'an', 'the', 'to', 'for', 'of', 'in', 'on', 'at', 'by', 'with', 'from',
'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had',
'do', 'does', 'did', 'will', 'would', 'should', 'could', 'can', 'may', 'might', 'must', 'shall',
'this', 'that', 'these', 'those', 'my', 'your', 'our', 'their',
'want', 'need', 'add', 'get', 'set'
)
# Convert to lowercase and extract words (alphanumeric only)
$cleanName = $Description.ToLower() -replace '[^a-z0-9\s]', ' '
$words = $cleanName -split '\s+' | Where-Object { $_ }
# Filter words: remove stop words and words shorter than 3 chars (unless they're uppercase acronyms in original)
$meaningfulWords = @()
foreach ($word in $words) {
# Skip stop words
if ($stopWords -contains $word) { continue }
# Keep words that are length >= 3 OR appear as uppercase in original (likely acronyms)
if ($word.Length -ge 3) {
$meaningfulWords += $word
} elseif ($Description -match "\b$($word.ToUpper())\b") {
# Keep short words if they appear as uppercase in original (likely acronyms)
$meaningfulWords += $word
}
}
# If we have meaningful words, use first 3-4 of them
if ($meaningfulWords.Count -gt 0) {
$maxWords = if ($meaningfulWords.Count -eq 4) { 4 } else { 3 }
$result = ($meaningfulWords | Select-Object -First $maxWords) -join '-'
return $result
} else {
# Fallback to original logic if no meaningful words found
$result = ConvertTo-CleanBranchName -Name $Description
$fallbackWords = ($result -split '-') | Where-Object { $_ } | Select-Object -First 3
return [string]::Join('-', $fallbackWords)
}
}
# Generate branch name
if ($ShortName) {
# Use provided short name, just clean it up
$branchSuffix = ConvertTo-CleanBranchName -Name $ShortName
} else {
# Generate from description with smart filtering
$branchSuffix = Get-BranchName -Description $featureDesc
}
# Determine branch number
if ($Number -eq 0) {
if ($hasGit) {
# Check existing branches on remotes
$Number = Get-NextBranchNumber -ShortName $branchSuffix -SpecsDir $specsDir
} else {
# Fall back to local directory check
$Number = (Get-HighestNumberFromSpecs -SpecsDir $specsDir) + 1
}
}
$featureNum = ('{0:000}' -f $Number)
$branchName = "$featureNum-$branchSuffix"
# GitHub enforces a 244-byte limit on branch names
# Validate and truncate if necessary
$maxBranchLength = 244
if ($branchName.Length -gt $maxBranchLength) {
# Calculate how much we need to trim from suffix
# Account for: feature number (3) + hyphen (1) = 4 chars
$maxSuffixLength = $maxBranchLength - 4
# Truncate suffix
$truncatedSuffix = $branchSuffix.Substring(0, [Math]::Min($branchSuffix.Length, $maxSuffixLength))
# Remove trailing hyphen if truncation created one
$truncatedSuffix = $truncatedSuffix -replace '-$', ''
$originalBranchName = $branchName
$branchName = "$featureNum-$truncatedSuffix"
Write-Warning "[specify] Branch name exceeded GitHub's 244-byte limit"
Write-Warning "[specify] Original: $originalBranchName ($($originalBranchName.Length) bytes)"
Write-Warning "[specify] Truncated to: $branchName ($($branchName.Length) bytes)"
}
if ($hasGit) {
try {
git checkout -b $branchName | Out-Null
} catch {
Write-Warning "Failed to create git branch: $branchName"
}
} else {
Write-Warning "[specify] Warning: Git repository not detected; skipped branch creation for $branchName"
}
$featureDir = Join-Path $specsDir $branchName
New-Item -ItemType Directory -Path $featureDir -Force | Out-Null
$template = Join-Path $repoRoot '.specify/templates/spec-template.md'
$specFile = Join-Path $featureDir 'spec.md'
if (Test-Path $template) {
Copy-Item $template $specFile -Force
} else {
New-Item -ItemType File -Path $specFile | Out-Null
}
# Set the SPECIFY_FEATURE environment variable for the current session
$env:SPECIFY_FEATURE = $branchName
if ($Json) {
$obj = [PSCustomObject]@{
BRANCH_NAME = $branchName
SPEC_FILE = $specFile
FEATURE_NUM = $featureNum
HAS_GIT = $hasGit
}
$obj | ConvertTo-Json -Compress
} else {
Write-Output "BRANCH_NAME: $branchName"
Write-Output "SPEC_FILE: $specFile"
Write-Output "FEATURE_NUM: $featureNum"
Write-Output "HAS_GIT: $hasGit"
Write-Output "SPECIFY_FEATURE environment variable set to: $branchName"
}
@@ -0,0 +1,61 @@
#!/usr/bin/env pwsh
# Setup implementation plan for a feature
[CmdletBinding()]
param(
[switch]$Json,
[switch]$Help
)
$ErrorActionPreference = 'Stop'
# Show help if requested
if ($Help) {
Write-Output "Usage: ./setup-plan.ps1 [-Json] [-Help]"
Write-Output " -Json Output results in JSON format"
Write-Output " -Help Show this help message"
exit 0
}
# Load common functions
. "$PSScriptRoot/common.ps1"
# Get all paths and variables from common functions
$paths = Get-FeaturePathsEnv
# Check if we're on a proper feature branch (only for git repos)
if (-not (Test-FeatureBranch -Branch $paths.CURRENT_BRANCH -HasGit $paths.HAS_GIT)) {
exit 1
}
# Ensure the feature directory exists
New-Item -ItemType Directory -Path $paths.FEATURE_DIR -Force | Out-Null
# Copy plan template if it exists, otherwise note it or create empty file
$template = Join-Path $paths.REPO_ROOT '.specify/templates/plan-template.md'
if (Test-Path $template) {
Copy-Item $template $paths.IMPL_PLAN -Force
Write-Output "Copied plan template to $($paths.IMPL_PLAN)"
} else {
Write-Warning "Plan template not found at $template"
# Create a basic plan file if template doesn't exist
New-Item -ItemType File -Path $paths.IMPL_PLAN -Force | Out-Null
}
# Output results
if ($Json) {
$result = [PSCustomObject]@{
FEATURE_SPEC = $paths.FEATURE_SPEC
IMPL_PLAN = $paths.IMPL_PLAN
SPECS_DIR = $paths.FEATURE_DIR
BRANCH = $paths.CURRENT_BRANCH
HAS_GIT = $paths.HAS_GIT
}
$result | ConvertTo-Json -Compress
} else {
Write-Output "FEATURE_SPEC: $($paths.FEATURE_SPEC)"
Write-Output "IMPL_PLAN: $($paths.IMPL_PLAN)"
Write-Output "SPECS_DIR: $($paths.FEATURE_DIR)"
Write-Output "BRANCH: $($paths.CURRENT_BRANCH)"
Write-Output "HAS_GIT: $($paths.HAS_GIT)"
}
@@ -0,0 +1,442 @@
#!/usr/bin/env pwsh
<#!
.SYNOPSIS
Update agent context files with information from plan.md (PowerShell version)
.DESCRIPTION
Mirrors the behavior of scripts/bash/update-agent-context.sh:
1. Environment Validation
2. Plan Data Extraction
3. Agent File Management (create from template or update existing)
4. Content Generation (technology stack, recent changes, timestamp)
5. Multi-Agent Support (claude, gemini, copilot, cursor-agent, qwen, opencode, codex, windsurf, kilocode, auggie, roo, codebuddy, amp, shai, q)
.PARAMETER AgentType
Optional agent key to update a single agent. If omitted, updates all existing agent files (creating a default Claude file if none exist).
.EXAMPLE
./update-agent-context.ps1 -AgentType claude
.EXAMPLE
./update-agent-context.ps1 # Updates all existing agent files
.NOTES
Relies on common helper functions in common.ps1
#>
param(
[Parameter(Position=0)]
[ValidateSet('claude','gemini','copilot','cursor-agent','qwen','opencode','codex','windsurf','kilocode','auggie','roo','codebuddy','amp','shai','q')]
[string]$AgentType
)
$ErrorActionPreference = 'Stop'
# Import common helpers
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
. (Join-Path $ScriptDir 'common.ps1')
# Acquire environment paths
$envData = Get-FeaturePathsEnv
$REPO_ROOT = $envData.REPO_ROOT
$CURRENT_BRANCH = $envData.CURRENT_BRANCH
$HAS_GIT = $envData.HAS_GIT
$IMPL_PLAN = $envData.IMPL_PLAN
$NEW_PLAN = $IMPL_PLAN
# Agent file paths
$CLAUDE_FILE = Join-Path $REPO_ROOT 'CLAUDE.md'
$GEMINI_FILE = Join-Path $REPO_ROOT 'GEMINI.md'
$COPILOT_FILE = Join-Path $REPO_ROOT '.github/agents/copilot-instructions.md'
$CURSOR_FILE = Join-Path $REPO_ROOT '.cursor/rules/specify-rules.mdc'
$QWEN_FILE = Join-Path $REPO_ROOT 'QWEN.md'
$AGENTS_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$WINDSURF_FILE = Join-Path $REPO_ROOT '.windsurf/rules/specify-rules.md'
$KILOCODE_FILE = Join-Path $REPO_ROOT '.kilocode/rules/specify-rules.md'
$AUGGIE_FILE = Join-Path $REPO_ROOT '.augment/rules/specify-rules.md'
$ROO_FILE = Join-Path $REPO_ROOT '.roo/rules/specify-rules.md'
$CODEBUDDY_FILE = Join-Path $REPO_ROOT 'CODEBUDDY.md'
$AMP_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$SHAI_FILE = Join-Path $REPO_ROOT 'SHAI.md'
$Q_FILE = Join-Path $REPO_ROOT 'AGENTS.md'
$TEMPLATE_FILE = Join-Path $REPO_ROOT '.specify/templates/agent-file-template.md'
# Parsed plan data placeholders
$script:NEW_LANG = ''
$script:NEW_FRAMEWORK = ''
$script:NEW_DB = ''
$script:NEW_PROJECT_TYPE = ''
function Write-Info {
param(
[Parameter(Mandatory=$true)]
[string]$Message
)
Write-Host "INFO: $Message"
}
function Write-Success {
param(
[Parameter(Mandatory=$true)]
[string]$Message
)
Write-Host "$([char]0x2713) $Message"
}
function Write-WarningMsg {
param(
[Parameter(Mandatory=$true)]
[string]$Message
)
Write-Warning $Message
}
function Write-Err {
param(
[Parameter(Mandatory=$true)]
[string]$Message
)
Write-Host "ERROR: $Message" -ForegroundColor Red
}
function Validate-Environment {
if (-not $CURRENT_BRANCH) {
Write-Err 'Unable to determine current feature'
if ($HAS_GIT) { Write-Info "Make sure you're on a feature branch" } else { Write-Info 'Set SPECIFY_FEATURE environment variable or create a feature first' }
exit 1
}
if (-not (Test-Path $NEW_PLAN)) {
Write-Err "No plan.md found at $NEW_PLAN"
Write-Info 'Ensure you are working on a feature with a corresponding spec directory'
if (-not $HAS_GIT) { Write-Info 'Use: $env:SPECIFY_FEATURE=your-feature-name or create a new feature first' }
exit 1
}
if (-not (Test-Path $TEMPLATE_FILE)) {
Write-Err "Template file not found at $TEMPLATE_FILE"
Write-Info 'Run specify init to scaffold .specify/templates, or add agent-file-template.md there.'
exit 1
}
}
function Extract-PlanField {
param(
[Parameter(Mandatory=$true)]
[string]$FieldPattern,
[Parameter(Mandatory=$true)]
[string]$PlanFile
)
if (-not (Test-Path $PlanFile)) { return '' }
# Lines like **Language/Version**: Python 3.12
$regex = "^\*\*$([Regex]::Escape($FieldPattern))\*\*: (.+)$"
Get-Content -LiteralPath $PlanFile -Encoding utf8 | ForEach-Object {
if ($_ -match $regex) {
$val = $Matches[1].Trim()
if ($val -notin @('NEEDS CLARIFICATION','N/A')) { return $val }
}
} | Select-Object -First 1
}
function Parse-PlanData {
param(
[Parameter(Mandatory=$true)]
[string]$PlanFile
)
if (-not (Test-Path $PlanFile)) { Write-Err "Plan file not found: $PlanFile"; return $false }
Write-Info "Parsing plan data from $PlanFile"
$script:NEW_LANG = Extract-PlanField -FieldPattern 'Language/Version' -PlanFile $PlanFile
$script:NEW_FRAMEWORK = Extract-PlanField -FieldPattern 'Primary Dependencies' -PlanFile $PlanFile
$script:NEW_DB = Extract-PlanField -FieldPattern 'Storage' -PlanFile $PlanFile
$script:NEW_PROJECT_TYPE = Extract-PlanField -FieldPattern 'Project Type' -PlanFile $PlanFile
if ($NEW_LANG) { Write-Info "Found language: $NEW_LANG" } else { Write-WarningMsg 'No language information found in plan' }
if ($NEW_FRAMEWORK) { Write-Info "Found framework: $NEW_FRAMEWORK" }
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Info "Found database: $NEW_DB" }
if ($NEW_PROJECT_TYPE) { Write-Info "Found project type: $NEW_PROJECT_TYPE" }
return $true
}
function Format-TechnologyStack {
param(
[Parameter(Mandatory=$false)]
[string]$Lang,
[Parameter(Mandatory=$false)]
[string]$Framework
)
$parts = @()
if ($Lang -and $Lang -ne 'NEEDS CLARIFICATION') { $parts += $Lang }
if ($Framework -and $Framework -notin @('NEEDS CLARIFICATION','N/A')) { $parts += $Framework }
if (-not $parts) { return '' }
return ($parts -join ' + ')
}
function Get-ProjectStructure {
param(
[Parameter(Mandatory=$false)]
[string]$ProjectType
)
if ($ProjectType -match 'web') { return "backend/`nfrontend/`ntests/" } else { return "src/`ntests/" }
}
function Get-CommandsForLanguage {
param(
[Parameter(Mandatory=$false)]
[string]$Lang
)
switch -Regex ($Lang) {
'Python' { return "cd src; pytest; ruff check ." }
'Rust' { return "cargo test; cargo clippy" }
'JavaScript|TypeScript' { return "npm test; npm run lint" }
default { return "# Add commands for $Lang" }
}
}
function Get-LanguageConventions {
param(
[Parameter(Mandatory=$false)]
[string]$Lang
)
if ($Lang) { "${Lang}: Follow standard conventions" } else { 'General: Follow standard conventions' }
}
function New-AgentFile {
param(
[Parameter(Mandatory=$true)]
[string]$TargetFile,
[Parameter(Mandatory=$true)]
[string]$ProjectName,
[Parameter(Mandatory=$true)]
[datetime]$Date
)
if (-not (Test-Path $TEMPLATE_FILE)) { Write-Err "Template not found at $TEMPLATE_FILE"; return $false }
$temp = New-TemporaryFile
Copy-Item -LiteralPath $TEMPLATE_FILE -Destination $temp -Force
$projectStructure = Get-ProjectStructure -ProjectType $NEW_PROJECT_TYPE
$commands = Get-CommandsForLanguage -Lang $NEW_LANG
$languageConventions = Get-LanguageConventions -Lang $NEW_LANG
$escaped_lang = $NEW_LANG
$escaped_framework = $NEW_FRAMEWORK
$escaped_branch = $CURRENT_BRANCH
$content = Get-Content -LiteralPath $temp -Raw -Encoding utf8
$content = $content -replace '\[PROJECT NAME\]',$ProjectName
$content = $content -replace '\[DATE\]',$Date.ToString('yyyy-MM-dd')
# Build the technology stack string safely
$techStackForTemplate = ""
if ($escaped_lang -and $escaped_framework) {
$techStackForTemplate = "- $escaped_lang + $escaped_framework ($escaped_branch)"
} elseif ($escaped_lang) {
$techStackForTemplate = "- $escaped_lang ($escaped_branch)"
} elseif ($escaped_framework) {
$techStackForTemplate = "- $escaped_framework ($escaped_branch)"
}
$content = $content -replace '\[EXTRACTED FROM ALL PLAN.MD FILES\]',$techStackForTemplate
# For project structure we manually embed (keep newlines)
$escapedStructure = [Regex]::Escape($projectStructure)
$content = $content -replace '\[ACTUAL STRUCTURE FROM PLANS\]',$escapedStructure
# Replace escaped newlines placeholder after all replacements
$content = $content -replace '\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]',$commands
$content = $content -replace '\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]',$languageConventions
# Build the recent changes string safely
$recentChangesForTemplate = ""
if ($escaped_lang -and $escaped_framework) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang} + ${escaped_framework}"
} elseif ($escaped_lang) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_lang}"
} elseif ($escaped_framework) {
$recentChangesForTemplate = "- ${escaped_branch}: Added ${escaped_framework}"
}
$content = $content -replace '\[LAST 3 FEATURES AND WHAT THEY ADDED\]',$recentChangesForTemplate
# Convert literal \n sequences introduced by Escape to real newlines
$content = $content -replace '\\n',[Environment]::NewLine
$parent = Split-Path -Parent $TargetFile
if (-not (Test-Path $parent)) { New-Item -ItemType Directory -Path $parent | Out-Null }
Set-Content -LiteralPath $TargetFile -Value $content -NoNewline -Encoding utf8
Remove-Item $temp -Force
return $true
}
function Update-ExistingAgentFile {
param(
[Parameter(Mandatory=$true)]
[string]$TargetFile,
[Parameter(Mandatory=$true)]
[datetime]$Date
)
if (-not (Test-Path $TargetFile)) { return (New-AgentFile -TargetFile $TargetFile -ProjectName (Split-Path $REPO_ROOT -Leaf) -Date $Date) }
$techStack = Format-TechnologyStack -Lang $NEW_LANG -Framework $NEW_FRAMEWORK
$newTechEntries = @()
if ($techStack) {
$escapedTechStack = [Regex]::Escape($techStack)
if (-not (Select-String -Pattern $escapedTechStack -Path $TargetFile -Quiet)) {
$newTechEntries += "- $techStack ($CURRENT_BRANCH)"
}
}
if ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) {
$escapedDB = [Regex]::Escape($NEW_DB)
if (-not (Select-String -Pattern $escapedDB -Path $TargetFile -Quiet)) {
$newTechEntries += "- $NEW_DB ($CURRENT_BRANCH)"
}
}
$newChangeEntry = ''
if ($techStack) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${techStack}" }
elseif ($NEW_DB -and $NEW_DB -notin @('N/A','NEEDS CLARIFICATION')) { $newChangeEntry = "- ${CURRENT_BRANCH}: Added ${NEW_DB}" }
$lines = Get-Content -LiteralPath $TargetFile -Encoding utf8
$output = New-Object System.Collections.Generic.List[string]
$inTech = $false; $inChanges = $false; $techAdded = $false; $changeAdded = $false; $existingChanges = 0
for ($i=0; $i -lt $lines.Count; $i++) {
$line = $lines[$i]
if ($line -eq '## Active Technologies') {
$output.Add($line)
$inTech = $true
continue
}
if ($inTech -and $line -match '^##\s') {
if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
$output.Add($line); $inTech = $false; continue
}
if ($inTech -and [string]::IsNullOrWhiteSpace($line)) {
if (-not $techAdded -and $newTechEntries.Count -gt 0) { $newTechEntries | ForEach-Object { $output.Add($_) }; $techAdded = $true }
$output.Add($line); continue
}
if ($line -eq '## Recent Changes') {
$output.Add($line)
if ($newChangeEntry) { $output.Add($newChangeEntry); $changeAdded = $true }
$inChanges = $true
continue
}
if ($inChanges -and $line -match '^##\s') { $output.Add($line); $inChanges = $false; continue }
if ($inChanges -and $line -match '^- ') {
if ($existingChanges -lt 2) { $output.Add($line); $existingChanges++ }
continue
}
if ($line -match '\*\*Last updated\*\*: .*\d{4}-\d{2}-\d{2}') {
$output.Add(($line -replace '\d{4}-\d{2}-\d{2}',$Date.ToString('yyyy-MM-dd')))
continue
}
$output.Add($line)
}
# Post-loop check: if we're still in the Active Technologies section and haven't added new entries
if ($inTech -and -not $techAdded -and $newTechEntries.Count -gt 0) {
$newTechEntries | ForEach-Object { $output.Add($_) }
}
Set-Content -LiteralPath $TargetFile -Value ($output -join [Environment]::NewLine) -Encoding utf8
return $true
}
function Update-AgentFile {
param(
[Parameter(Mandatory=$true)]
[string]$TargetFile,
[Parameter(Mandatory=$true)]
[string]$AgentName
)
if (-not $TargetFile -or -not $AgentName) { Write-Err 'Update-AgentFile requires TargetFile and AgentName'; return $false }
Write-Info "Updating $AgentName context file: $TargetFile"
$projectName = Split-Path $REPO_ROOT -Leaf
$date = Get-Date
$dir = Split-Path -Parent $TargetFile
if (-not (Test-Path $dir)) { New-Item -ItemType Directory -Path $dir | Out-Null }
if (-not (Test-Path $TargetFile)) {
if (New-AgentFile -TargetFile $TargetFile -ProjectName $projectName -Date $date) { Write-Success "Created new $AgentName context file" } else { Write-Err 'Failed to create new agent file'; return $false }
} else {
try {
if (Update-ExistingAgentFile -TargetFile $TargetFile -Date $date) { Write-Success "Updated existing $AgentName context file" } else { Write-Err 'Failed to update agent file'; return $false }
} catch {
Write-Err "Cannot access or update existing file: $TargetFile. $_"
return $false
}
}
return $true
}
function Update-SpecificAgent {
param(
[Parameter(Mandatory=$true)]
[string]$Type
)
switch ($Type) {
'claude' { Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code' }
'gemini' { Update-AgentFile -TargetFile $GEMINI_FILE -AgentName 'Gemini CLI' }
'copilot' { Update-AgentFile -TargetFile $COPILOT_FILE -AgentName 'GitHub Copilot' }
'cursor-agent' { Update-AgentFile -TargetFile $CURSOR_FILE -AgentName 'Cursor IDE' }
'qwen' { Update-AgentFile -TargetFile $QWEN_FILE -AgentName 'Qwen Code' }
'opencode' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'opencode' }
'codex' { Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Codex CLI' }
'windsurf' { Update-AgentFile -TargetFile $WINDSURF_FILE -AgentName 'Windsurf' }
'kilocode' { Update-AgentFile -TargetFile $KILOCODE_FILE -AgentName 'Kilo Code' }
'auggie' { Update-AgentFile -TargetFile $AUGGIE_FILE -AgentName 'Auggie CLI' }
'roo' { Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code' }
'codebuddy' { Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI' }
'amp' { Update-AgentFile -TargetFile $AMP_FILE -AgentName 'Amp' }
'shai' { Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI' }
'q' { Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI' }
default { Write-Err "Unknown agent type '$Type'"; Write-Err 'Expected: claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q'; return $false }
}
}
function Update-AllExistingAgents {
$found = $false
$ok = $true
if (Test-Path $CLAUDE_FILE) { if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }; $found = $true }
if (Test-Path $GEMINI_FILE) { if (-not (Update-AgentFile -TargetFile $GEMINI_FILE -AgentName 'Gemini CLI')) { $ok = $false }; $found = $true }
if (Test-Path $COPILOT_FILE) { if (-not (Update-AgentFile -TargetFile $COPILOT_FILE -AgentName 'GitHub Copilot')) { $ok = $false }; $found = $true }
if (Test-Path $CURSOR_FILE) { if (-not (Update-AgentFile -TargetFile $CURSOR_FILE -AgentName 'Cursor IDE')) { $ok = $false }; $found = $true }
if (Test-Path $QWEN_FILE) { if (-not (Update-AgentFile -TargetFile $QWEN_FILE -AgentName 'Qwen Code')) { $ok = $false }; $found = $true }
if (Test-Path $AGENTS_FILE) { if (-not (Update-AgentFile -TargetFile $AGENTS_FILE -AgentName 'Codex/opencode')) { $ok = $false }; $found = $true }
if (Test-Path $WINDSURF_FILE) { if (-not (Update-AgentFile -TargetFile $WINDSURF_FILE -AgentName 'Windsurf')) { $ok = $false }; $found = $true }
if (Test-Path $KILOCODE_FILE) { if (-not (Update-AgentFile -TargetFile $KILOCODE_FILE -AgentName 'Kilo Code')) { $ok = $false }; $found = $true }
if (Test-Path $AUGGIE_FILE) { if (-not (Update-AgentFile -TargetFile $AUGGIE_FILE -AgentName 'Auggie CLI')) { $ok = $false }; $found = $true }
if (Test-Path $ROO_FILE) { if (-not (Update-AgentFile -TargetFile $ROO_FILE -AgentName 'Roo Code')) { $ok = $false }; $found = $true }
if (Test-Path $CODEBUDDY_FILE) { if (-not (Update-AgentFile -TargetFile $CODEBUDDY_FILE -AgentName 'CodeBuddy CLI')) { $ok = $false }; $found = $true }
if (Test-Path $SHAI_FILE) { if (-not (Update-AgentFile -TargetFile $SHAI_FILE -AgentName 'SHAI')) { $ok = $false }; $found = $true }
if (Test-Path $Q_FILE) { if (-not (Update-AgentFile -TargetFile $Q_FILE -AgentName 'Amazon Q Developer CLI')) { $ok = $false }; $found = $true }
if (-not $found) {
Write-Info 'No existing agent files found, creating default Claude file...'
if (-not (Update-AgentFile -TargetFile $CLAUDE_FILE -AgentName 'Claude Code')) { $ok = $false }
}
return $ok
}
function Print-Summary {
Write-Host ''
Write-Info 'Summary of changes:'
if ($NEW_LANG) { Write-Host " - Added language: $NEW_LANG" }
if ($NEW_FRAMEWORK) { Write-Host " - Added framework: $NEW_FRAMEWORK" }
if ($NEW_DB -and $NEW_DB -ne 'N/A') { Write-Host " - Added database: $NEW_DB" }
Write-Host ''
Write-Info 'Usage: ./update-agent-context.ps1 [-AgentType claude|gemini|copilot|cursor-agent|qwen|opencode|codex|windsurf|kilocode|auggie|roo|codebuddy|amp|shai|q]'
}
function Main {
Validate-Environment
Write-Info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
if (-not (Parse-PlanData -PlanFile $NEW_PLAN)) { Write-Err 'Failed to parse plan data'; exit 1 }
$success = $true
if ($AgentType) {
Write-Info "Updating specific agent: $AgentType"
if (-not (Update-SpecificAgent -Type $AgentType)) { $success = $false }
}
else {
Write-Info 'No agent specified, updating all existing agent files...'
if (-not (Update-AllExistingAgents)) { $success = $false }
}
Print-Summary
if ($success) { Write-Success 'Agent context update completed successfully'; exit 0 } else { Write-Err 'Agent context update completed with errors'; exit 1 }
}
Main
+23
View File
@@ -0,0 +1,23 @@
# [PROJECT NAME] 开发指南
基于所有功能计划自动生成. 最后更新时间: [DATE]
## 活跃技术
[EXTRACTED FROM ALL PLAN.MD FILES]
## 项目结构
```
[ACTUAL STRUCTURE FROM PLANS]
```
## 命令
[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]
## 代码风格
[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]
## 最近变更
[LAST 3 FEATURES AND WHAT THEY ADDED]
<!-- 手动添加内容开始 -->
<!-- 手动添加内容结束 -->
+40
View File
@@ -0,0 +1,40 @@
# [检查清单类型] 检查清单: [功能名称]
**目的**: [此检查清单涵盖内容的简要描述]
**创建时间**: [日期]
**功能**: [链接到 spec.md 或相关文档]
**注意**: 此检查清单由 `/speckit.checklist` 命令基于功能上下文和需求生成.
<!--
============================================================================
重要说明: 以下检查清单项目仅为示例项目, 仅供说明用途.
/speckit.checklist 命令必须根据以下内容替换为实际项目:
- 用户的具体检查清单请求
- 来自 spec.md 的功能需求
- 来自 plan.md 的技术上下文
- 来自 tasks.md 的实施细节
请勿在生成的检查清单文件中保留这些示例项目.
============================================================================
-->
## [类别 1]
- [ ] CHK001 第一个检查清单项目, 具有明确的行动
- [ ] CHK002 第二个检查清单项目
- [ ] CHK003 第三个检查清单项目
## [类别 2]
- [ ] CHK004 另一个类别项目
- [ ] CHK005 具有特定标准的项目
- [ ] CHK006 此类别中的最后一个项目
## 备注
- 完成项目时勾选: `[x]`
- 内联添加评论或发现
- 链接到相关资源或文档
- 项目按顺序编号, 便于参考
+101
View File
@@ -0,0 +1,101 @@
# 实施计划: [FEATURE]
**分支**: `[###-feature-name]` | **日期**: [DATE] | **规范**: [link]
**输入**: 来自 `/specs/[###-feature-name]/spec.md` 的功能规范
**注意**: 此模板由 `/speckit.plan` 命令填充. 执行工作流程请参见 `.specify/templates/commands/plan.md`.
## 摘要
[从功能规范中提取: 主要需求 + 研究得出的技术方法]
## 技术背景
<!--
需要操作: 将此部分内容替换为项目的技术细节.
此处的结构以咨询性质呈现, 用于指导迭代过程.
-->
**语言/版本**: [例如: Python 3.11、Swift 5.9、Rust 1.75 或 NEEDS CLARIFICATION]
**主要依赖**: [例如: FastAPI、UIKit、LLVM 或 NEEDS CLARIFICATION]
**存储**: [如适用, 例如: PostgreSQL、CoreData、文件 或 N/A]
**测试**: [例如: pytest、XCTest、cargo test 或 NEEDS CLARIFICATION]
**目标平台**: [例如: Linux 服务器、iOS 15+、WASM 或 NEEDS CLARIFICATION]
**项目类型**: [单一/网页/移动 - 决定源代码结构]
**性能目标**: [领域特定, 例如: 1000 请求/秒、10k 行/秒、60 fps 或 NEEDS CLARIFICATION]
**约束条件**: [领域特定, 例如: <200ms p95、<100MB 内存、离线可用 或 NEEDS CLARIFICATION]
**规模/范围**: [领域特定, 例如: 10k 用户、1M 行代码、50 个屏幕 或 NEEDS CLARIFICATION]
## 章程检查
*门控: 必须在阶段 0 研究前通过. 阶段 1 设计后重新检查. *
[基于章程文件确定的门控条件]
## 项目结构
### 文档(此功能)
```
specs/[###-feature]/
├── plan.md # 此文件 (/speckit.plan 命令输出)
├── research.md # 阶段 0 输出 (/speckit.plan 命令)
├── data-model.md # 阶段 1 输出 (/speckit.plan 命令)
├── quickstart.md # 阶段 1 输出 (/speckit.plan 命令)
├── contracts/ # 阶段 1 输出 (/speckit.plan 命令)
└── tasks.md # 阶段 2 输出 (/speckit.tasks 命令 - 非 /speckit.plan 创建)
```
### 源代码(仓库根目录)
<!--
需要操作: 将下面的占位符树结构替换为此功能的具体布局.
删除未使用的选项, 并使用真实路径(例如: apps/admin、packages/something)扩展所选结构.
交付的计划不得包含选项标签.
-->
```
# [如未使用请删除] 选项 1: 单一项目(默认)
src/
├── models/
├── services/
├── cli/
└── lib/
tests/
├── contract/
├── integration/
└── unit/
# [如未使用请删除] 选项 2: Web 应用程序(检测到"前端" + "后端"时)
backend/
├── src/
│ ├── models/
│ ├── services/
│ └── api/
└── tests/
frontend/
├── src/
│ ├── components/
│ ├── pages/
│ └── services/
└── tests/
# [如未使用请删除] 选项 3: 移动端 + API(检测到 "iOS/Android" 时)
api/
└── [同上后端结构]
ios/ 或 android/
└── [平台特定结构: 功能模块、UI 流程、平台测试]
```
**结构决策**: [记录所选结构并引用上面捕获的真实目录]
## 复杂度跟踪
*仅在章程检查有必须证明的违规时填写*
| 违规 | 为什么需要 | 拒绝更简单替代方案的原因 |
|-----------|------------|-------------------------------------|
| [例如: 第 4 个项目] | [当前需求] | [为什么 3 个项目不够] |
| [例如: 仓储模式] | [特定问题] | [为什么直接数据库访问不够] |
+115
View File
@@ -0,0 +1,115 @@
# 功能规范: [FEATURE NAME]
**功能分支**: `[###-feature-name]`
**创建时间**: [DATE]
**状态**: 草稿
**输入**: 用户描述: "$ARGUMENTS"
## 用户场景与测试 *(必填)*
<!--
重要说明: 用户故事应按重要性排序, 作为用户旅程进行优先级划分.
每个用户故事/旅程必须能够独立测试——这意味着即使只实现其中一个,
你仍然应该有一个可行的 MVP(最小可行产品)来交付价值.
为每个故事分配优先级(P1、P2、P3 等), 其中 P1 是最关键的.
将每个故事视为独立的功能切片, 可以:
- 独立开发
- 独立测试
- 独立部署
- 独立向用户演示
-->
### 用户故事 1 - [简要标题] (优先级: P1)
[用通俗语言描述这个用户旅程]
**优先级原因**: [解释价值以及为什么具有此优先级]
**独立测试**: [描述如何独立测试 - 例如: "可以通过 [具体操作] 完全测试并交付 [具体价值]"]
**验收场景**:
1. **给定** [初始状态], **当** [操作时], **那么** [预期结果]
2. **给定** [初始状态], **当** [操作时], **那么** [预期结果]
---
### 用户故事 2 - [简要标题] (优先级: P2)
[用通俗语言描述这个用户旅程]
**优先级原因**: [解释价值以及为什么具有此优先级]
**独立测试**: [描述如何独立测试]
**验收场景**:
1. **给定** [初始状态], **当** [操作时], **那么** [预期结果]
---
### 用户故事 3 - [简要标题] (优先级: P3)
[用通俗语言描述这个用户旅程]
**优先级原因**: [解释价值以及为什么具有此优先级]
**独立测试**: [描述如何独立测试]
**验收场景**:
1. **给定** [初始状态], **当** [操作时], **那么** [预期结果]
---
[根据需要添加更多用户故事, 每个都分配优先级]
### 边界情况
<!--
需要操作: 本节内容表示占位符.
请用正确的边界情况填写.
-->
- 当 [边界条件] 时会发生什么?
- 系统如何处理 [错误场景]
## 需求 *(必填)*
<!--
需要操作: 本节内容表示占位符.
请用正确的功能需求填写.
-->
### 功能需求
- **FR-001**: 系统必须 [具体能力, 例如: "允许用户创建账户"]
- **FR-002**: 系统必须 [具体能力, 例如: "验证电子邮件地址"]
- **FR-003**: 用户必须能够 [关键交互, 例如: "重置密码"]
- **FR-004**: 系统必须 [数据需求, 例如: "持久化用户偏好设置"]
- **FR-005**: 系统必须 [行为, 例如: "记录所有安全事件"]
*标记不明确需求的示例: *
- **FR-006**: 系统必须通过 [NEEDS CLARIFICATION: 未指定认证方法 - 电子邮件/密码、SSO、OAuth?] 认证用户
- **FR-007**: 系统必须保留用户数据 [NEEDS CLARIFICATION: 未指定保留期限]
### 关键实体 *(如果功能涉及数据则包含)*
- **[实体 1]**: [它代表什么, 关键属性(不含实现细节)]
- **[实体 2]**: [它代表什么, 与其他实体的关系]
## 成功标准 *(必填)*
<!--
需要操作: 定义可衡量的成功标准.
这些标准必须与技术无关且可衡量.
-->
### 可衡量的结果
- **SC-001**: [可衡量的指标, 例如: "用户可以在 2 分钟内完成账户创建"]
- **SC-002**: [可衡量的指标, 例如: "系统处理 1000 个并发用户而不降低性能"]
- **SC-003**: [用户满意度指标, 例如: "90% 的用户在首次尝试时成功完成主要任务"]
- **SC-004**: [业务指标, 例如: "将与 [X] 相关的支持工单减少 50%"]
+249
View File
@@ -0,0 +1,249 @@
---
description: "功能实现任务列表模板"
---
# 任务: [FEATURE NAME]
**输入**: 来自 `/specs/[###-feature-name]/` 的设计文档
**前置条件**: plan.md(必需)、spec.md(用户故事必需)、research.md、data-model.md、contracts/
**测试**: 以下示例包含测试任务. 测试是可选的 - 仅在功能规范中明确要求时才包含.
**组织结构**: 任务按用户故事分组, 以便每个故事能够独立实施和测试.
## 格式: `[ID] [P] [Story] 描述`
- **[P]**: 可以并行运行(不同文件, 无依赖关系)
- **[Story]**: 此任务属于哪个用户故事(例如: US1、US2、US3)
- 在描述中包含确切的文件路径
## 路径约定
- **单一项目**: 仓库根目录下的 `src/``tests/`
- **Web 应用**: `backend/src/``frontend/src/`
- **移动应用**: `api/src/``ios/src/``android/src/`
- 以下显示的路径假设为单一项目 - 根据 plan.md 结构进行调整
<!--
============================================================================
重要说明: 以下任务仅为说明目的的示例任务.
/speckit.tasks 命令必须根据以下内容替换为实际任务:
- 来自 spec.md 的用户故事(及其优先级 P1、P2、P3...)
- 来自 plan.md 的功能需求
- 来自 data-model.md 的实体
- 来自 contracts/ 的端点
任务必须按用户故事组织, 以便每个故事能够:
- 独立实施
- 独立测试
- 作为 MVP 增量交付
不要在生成的 tasks.md 文件中保留这些示例任务.
============================================================================
-->
## 阶段 1: 设置(共享基础设施)
**目的**: 项目初始化和基本结构
- [ ] T001 根据实施计划创建项目结构
- [ ] T002 使用 [framework] 依赖项初始化 [language] 项目
- [ ] T003 [P] 配置代码检查和格式化工具
---
## 阶段 2: 基础(阻塞前置条件)
**目的**: 在任何用户故事可以实施之前必须完成的核心基础设施
**⚠️ 关键**: 在此阶段完成之前, 无法开始任何用户故事工作
基础任务示例(根据你的项目调整):
- [ ] T004 设置数据库架构和迁移框架
- [ ] T005 [P] 实施身份验证/授权框架
- [ ] T006 [P] 设置 API 路由和中间件结构
- [ ] T007 创建所有故事依赖的基础模型/实体
- [ ] T008 配置错误处理和日志记录基础设施
- [ ] T009 设置环境配置管理
**检查点**: 基础就绪 - 现在可以开始并行实施用户故事
---
## 阶段 3: 用户故事 1 - [Title](优先级: P1)🎯 MVP
**目标**: [此故事交付内容的简要描述]
**独立测试**: [如何验证此故事独立运行]
### 用户故事 1 的测试(可选 - 仅在要求测试时)⚠️
**注意: 先编写这些测试, 确保在实施前它们失败**
- [ ] T010 [P] [US1] 在 tests/contract/test_[name].py 中为 [endpoint] 编写合约测试
- [ ] T011 [P] [US1] 在 tests/integration/test_[name].py 中为 [user journey] 编写集成测试
### 用户故事 1 的实施
- [ ] T012 [P] [US1] 在 src/models/[entity1].py 中创建 [Entity1] 模型
- [ ] T013 [P] [US1] 在 src/models/[entity2].py 中创建 [Entity2] 模型
- [ ] T014 [US1] 在 src/services/[service].py 中实施 [Service](依赖于 T012、T013)
- [ ] T015 [US1] 在 src/[location]/[file].py 中实施 [endpoint/feature]
- [ ] T016 [US1] 添加验证和错误处理
- [ ] T017 [US1] 为用户故事 1 操作添加日志记录
**检查点**: 此时, 用户故事 1 应该完全功能化且可独立测试
---
## 阶段 4: 用户故事 2 - [Title](优先级: P2)
**目标**: [此故事交付内容的简要描述]
**独立测试**: [如何验证此故事独立运行]
### 用户故事 2 的测试(可选 - 仅在要求测试时)⚠️
- [ ] T018 [P] [US2] 在 tests/contract/test_[name].py 中为 [endpoint] 编写合约测试
- [ ] T019 [P] [US2] 在 tests/integration/test_[name].py 中为 [user journey] 编写集成测试
### 用户故事 2 的实施
- [ ] T020 [P] [US2] 在 src/models/[entity].py 中创建 [Entity] 模型
- [ ] T021 [US2] 在 src/services/[service].py 中实施 [Service]
- [ ] T022 [US2] 在 src/[location]/[file].py 中实施 [endpoint/feature]
- [ ] T023 [US2] 与用户故事 1 组件集成(如需要)
**检查点**: 此时, 用户故事 1 和 2 都应该独立运行
---
## 阶段 5: 用户故事 3 - [Title](优先级: P3)
**目标**: [此故事交付内容的简要描述]
**独立测试**: [如何验证此故事独立运行]
### 用户故事 3 的测试(可选 - 仅在要求测试时)⚠️
- [ ] T024 [P] [US3] 在 tests/contract/test_[name].py 中为 [endpoint] 编写合约测试
- [ ] T025 [P] [US3] 在 tests/integration/test_[name].py 中为 [user journey] 编写集成测试
### 用户故事 3 的实施
- [ ] T026 [P] [US3] 在 src/models/[entity].py 中创建 [Entity] 模型
- [ ] T027 [US3] 在 src/services/[service].py 中实施 [Service]
- [ ] T028 [US3] 在 src/[location]/[file].py 中实施 [endpoint/feature]
**检查点**: 所有用户故事现在应该独立功能化
---
[根据需要添加更多用户故事阶段, 遵循相同模式]
---
## 阶段 N: 完善与横切关注点
**目的**: 影响多个用户故事的改进
- [ ] TXXX [P] 在 docs/ 中更新文档
- [ ] TXXX 代码清理和重构
- [ ] TXXX 跨所有故事的性能优化
- [ ] TXXX [P] 在 tests/unit/ 中添加额外的单元测试(如要求)
- [ ] TXXX 安全加固
- [ ] TXXX 运行 quickstart.md 验证
---
## 依赖关系与执行顺序
### 阶段依赖关系
- **设置(阶段 1)**: 无依赖关系 - 可立即开始
- **基础(阶段 2)**: 依赖于设置完成 - 阻塞所有用户故事
- **用户故事(阶段 3+)**: 都依赖于基础阶段完成
- 然后用户故事可以并行进行(如果有人员)
- 或按优先级顺序进行(P1 → P2 → P3)
- **完善(最终阶段)**: 依赖于所有期望的用户故事完成
### 用户故事依赖关系
- **用户故事 1(P1)**: 可在基础(阶段 2)后开始 - 无其他故事依赖
- **用户故事 2(P2)**: 可在基础(阶段 2)后开始 - 可与 US1 集成但应独立可测试
- **用户故事 3(P3)**: 可在基础(阶段 2)后开始 - 可与 US1/US2 集成但应独立可测试
### 每个用户故事内部
- 测试(如包含)必须在实施前编写并失败
- 模型在服务之前
- 服务在端点之前
- 核心实施在集成之前
- 故事完成后才移至下一个优先级
### 并行机会
- 所有标记为 [P] 的设置任务可以并行运行
- 所有标记为 [P] 的基础任务可以并行运行(在阶段 2 内)
- 基础阶段完成后, 所有用户故事可以并行开始(如果团队容量允许)
- 用户故事中所有标记为 [P] 的测试可以并行运行
- 故事中标记为 [P] 的模型可以并行运行
- 不同用户故事可以由不同团队成员并行处理
---
## 并行示例: 用户故事 1
```bash
# 一起启动用户故事 1 的所有测试(如要求测试):
任务: "在 tests/contract/test_[name].py 中为 [endpoint] 编写合约测试"
任务: "在 tests/integration/test_[name].py 中为 [user journey] 编写集成测试"
# 一起启动用户故事 1 的所有模型:
任务: "在 src/models/[entity1].py 中创建 [Entity1] 模型"
任务: "在 src/models/[entity2].py 中创建 [Entity2] 模型"
```
---
## 实施策略
### 仅 MVP(仅用户故事 1)
1. 完成阶段 1: 设置
2. 完成阶段 2: 基础(关键 - 阻塞所有故事)
3. 完成阶段 3: 用户故事 1
4. **停止并验证**: 独立测试用户故事 1
5. 如准备好则部署/演示
### 增量交付
1. 完成设置 + 基础 → 基础就绪
2. 添加用户故事 1 → 独立测试 → 部署/演示(MVP! )
3. 添加用户故事 2 → 独立测试 → 部署/演示
4. 添加用户故事 3 → 独立测试 → 部署/演示
5. 每个故事在不破坏先前故事的情况下增加价值
### 并行团队策略
有多个开发人员时:
1. 团队一起完成设置 + 基础
2. 基础完成后:
- 开发人员 A: 用户故事 1
- 开发人员 B: 用户故事 2
- 开发人员 C: 用户故事 3
3. 故事独立完成和集成
---
## 注意事项
- [P] 任务 = 不同文件, 无依赖关系
- [Story] 标签将任务映射到特定用户故事以实现可追溯性
- 每个用户故事应该独立可完成和可测试
- 在实施前验证测试失败
- 在每个任务或逻辑组后提交
- 在任何检查点停止以独立验证故事
- 避免: 模糊任务、相同文件冲突、破坏独立性的跨故事依赖