@namewta/speculo 0.2.3 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -15
- package/dist/src/index.js +72 -8
- package/dist/src/index.js.map +1 -1
- package/dist/src/migrate.js +8 -8
- package/dist/src/migrate.js.map +1 -1
- package/dist/src/workflows.js +2 -2
- package/dist/src/workflows.js.map +1 -1
- package/package.json +1 -1
- package/template/.speculo/README.md +3 -3
- package/template/AGENTS.md +4 -0
- package/template/CLAUDE.md +3 -0
- package/template/canonical/README.md +114 -0
- package/template/canonical/canonical-domain-modeling.md +289 -0
- package/template/canonical/canonical-skill-example.md +608 -0
- package/template/canonical/canonical-teach.md +296 -0
- package/template/commands/archive-and-consolidate.md +49 -0
- package/template/commands/docs-sync.md +2 -2
- package/template/commands/retro.md +1 -1
- package/template/commands/status.md +2 -2
- package/template/skills/archive-and-consolidate/SKILL.md +179 -0
- package/template/skills/archive-and-consolidate/assets/archive-plan-template.md +34 -0
- package/template/skills/archive-and-consolidate/assets/cleanup-candidate-template.md +69 -0
- package/template/skills/archive-and-consolidate/assets/consolidation-plan-template.md +67 -0
- package/template/skills/archive-and-consolidate/references/archive-rules.md +48 -0
- package/template/skills/archive-and-consolidate/references/cleanup-rules.md +73 -0
- package/template/skills/archive-and-consolidate/references/consolidation-rules.md +70 -0
- package/template/skills/archive-and-consolidate/references/knowledge-graduation.md +50 -0
- package/template/skills/docs-sync/references/workflow-scope-contract.md +3 -3
- package/template/skills/speculo-retro/SKILL.md +1 -1
- package/template/skills/speculo-retro/references/issue-drafting-sop.md +1 -1
- package/template/skills/worktree-isolation/references/merge-and-cleanup.md +2 -2
- package/template/vendor/README.md +3 -3
- package/template/vendor/khazix-skills/neat-freak/SKILL.md +210 -0
- package/template/vendor/khazix-skills/neat-freak/references/agent-paths.md +72 -0
- package/template/vendor/khazix-skills/neat-freak/references/governance.md +88 -0
- package/template/vendor/khazix-skills/neat-freak/references/sync-matrix.md +77 -0
- package/template/vendor/khazix-skills/neat-freak/references/verification.md +92 -0
- package/template/vendor/khazix-skills/neat-freak/scripts/audit-inventory.sh +106 -0
- package/template/workflows/person/INDEX.md +12 -0
- package/template/workflows/person/M-mao-zedong-cognitive-os/M-mao-zedong-cognitive-os.md +73 -74
- package/template/workflows/specdev/D-diagnose-bugs/D-diagnose-bugs.md +85 -0
- package/template/workflows/specdev/D-diagnose-bugs/cleanup-postmortem.md +37 -0
- package/template/workflows/specdev/D-diagnose-bugs/feedback-loop-techniques.md +84 -0
- package/template/workflows/specdev/D-diagnose-bugs/hypothesis-format.md +46 -0
- package/template/workflows/specdev/D-diagnose-bugs/instrumentation-rules.md +51 -0
- package/template/workflows/specdev/G-grill-with-docs/G-grill-with-docs.md +54 -0
- package/template/workflows/specdev/G-grill-with-docs/adr-format.md +77 -0
- package/template/workflows/specdev/G-grill-with-docs/context-format.md +63 -0
- package/template/workflows/specdev/G-grill-with-docs/domain-modeling-rules.md +93 -0
- package/template/workflows/specdev/G-grill-with-docs/grilling-protocol.md +54 -0
- package/template/workflows/specdev/G-grill-with-docs/log-format.md +99 -0
- package/template/workflows/specdev/I-implement/I-implement.md +85 -0
- package/template/workflows/specdev/I-implement/code-review-process.md +83 -0
- package/template/workflows/specdev/I-implement/codebase-design-glossary.md +109 -0
- package/template/workflows/specdev/I-implement/deepening.md +37 -0
- package/template/workflows/specdev/I-implement/design-it-twice.md +44 -0
- package/template/workflows/specdev/I-implement/tdd-examples.md +139 -0
- package/template/workflows/specdev/I-implement/tdd-rules.md +31 -0
- package/template/workflows/specdev/I-init-setup/I-init-setup.md +132 -0
- package/template/workflows/specdev/I-init-setup/domain-layout.md +90 -0
- package/template/workflows/specdev/I-init-setup/status-labels.md +54 -0
- package/template/workflows/specdev/I-init-setup/tracking-convention.md +58 -0
- package/template/workflows/specdev/INDEX.md +88 -0
- package/template/workflows/specdev/S-spec/S-spec.md +91 -0
- package/template/workflows/specdev/T-tickets/T-tickets.md +241 -0
- package/template/workflows/specdev/W-wayfinder/W-wayfinder.md +209 -0
- package/template/workflows/specdev/_state/adr/.gitkeep +0 -0
- package/template/workflows/specdev/_state/archive/.gitkeep +0 -0
- package/template/workflows/specdev/_state/changes/.gitkeep +0 -0
- package/template/workflows/specdev/_state/context/.gitkeep +0 -0
- package/template/workflows/{matt-pocock → specdev}/_state/status.json +1 -1
- package/template/commands/finalize.md +0 -37
- package/template/commands/knowledge-prune.md +0 -20
- package/template/skills/change-lifecycle/SKILL.md +0 -25
- package/template/skills/change-lifecycle/assets/completion-summary-template.md +0 -25
- package/template/skills/change-lifecycle/assets/completion-verification-template.md +0 -29
- package/template/skills/change-lifecycle/references/completion-gate.md +0 -19
- package/template/skills/change-lifecycle/references/finalize-archive.md +0 -32
- package/template/skills/knowledge-prune/SKILL.md +0 -29
- package/template/skills/knowledge-prune/references/audit-rules.md +0 -24
- package/template/skills/runtime-context/SKILL.md +0 -54
- package/template/skills/runtime-context/references/path-resolution.md +0 -41
- package/template/workflows/matt-pocock/PERSISTENCE.md +0 -80
- package/template/workflows/matt-pocock/WORKFLOW.md +0 -103
- package/template/workflows/matt-pocock/_state/archive/.gitkeep +0 -1
- package/template/workflows/matt-pocock/_state/changes/.gitkeep +0 -1
- package/template/workflows/matt-pocock/atomic-skills/ask-matt.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/claude-handoff.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/code-review.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/codebase-design.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/diagnosing-bugs.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/domain-modeling.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/grill-me.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/grill-with-docs.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/grilling.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/handoff.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/implement.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/improve-codebase-architecture.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/loop-me.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/prototype.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/research.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/resolving-merge-conflicts.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/setup-matt-pocock-skills.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/tdd.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/teach.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/to-spec.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/to-tickets.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/triage.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/wayfinder.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/wizard.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/writing-beats.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/writing-fragments.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/writing-great-skills.md +0 -21
- package/template/workflows/matt-pocock/atomic-skills/writing-shape.md +0 -20
- package/template/workflows/matt-pocock/routes/architecture.md +0 -24
- package/template/workflows/matt-pocock/routes/diagnose.md +0 -22
- package/template/workflows/matt-pocock/routes/experimental.md +0 -18
- package/template/workflows/matt-pocock/routes/idea-to-delivery.md +0 -63
- package/template/workflows/matt-pocock/routes/merge-conflicts.md +0 -19
- package/template/workflows/matt-pocock/routes/productivity.md +0 -25
- package/template/workflows/matt-pocock/routes/research-prototype.md +0 -20
- package/template/workflows/matt-pocock/routes/review.md +0 -19
- package/template/workflows/matt-pocock/routes/setup.md +0 -42
- package/template/workflows/matt-pocock/routes/triage.md +0 -25
- package/template/workflows/matt-pocock/routes/wayfinder.md +0 -27
- package/template/workflows/person/PERSISTENCE.md +0 -56
- package/template/workflows/person/WORKFLOW.md +0 -50
- package/template/workflows/person/_state/.config/LESSONS.md +0 -3
- package/template/workflows/person/_state/.config/RULES.md +0 -3
- package/template/workflows/person/_state/.config/context/.gitkeep +0 -1
- package/template/workflows/person/_templates/mao-consultation-output-template.md +0 -55
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# 设计两次
|
|
2
|
+
|
|
3
|
+
当用户想要为选定的深化候选探索替代接口时,使用此并行子 Agent 模式。基于"Design It Twice"(Ousterhout)— 你的第一个想法不太可能是最好的。
|
|
4
|
+
|
|
5
|
+
使用 `<Path>{roots.workflows}/specdev/I-implement/codebase-design-glossary.md</Path>` 中的词汇 — **module**(模块)、**interface**(接口)、**seam**(接缝)、**adapter**(适配器)、**leverage**(杠杆)。
|
|
6
|
+
|
|
7
|
+
## 流程
|
|
8
|
+
|
|
9
|
+
### 1. 界定问题空间
|
|
10
|
+
|
|
11
|
+
在启动子 Agent 之前,为选定候选编写一份面向用户的问题空间说明:
|
|
12
|
+
|
|
13
|
+
- 任何新接口需要满足的约束条件
|
|
14
|
+
- 它将依赖的依赖项,以及它们属于哪个类别(参见 `<Path>{roots.workflows}/specdev/I-implement/deepening.md</Path>`)
|
|
15
|
+
- 一个粗略的示例代码草图来使约束具体化 — 不是提案,只是让约束变得具体的一种方式
|
|
16
|
+
|
|
17
|
+
将此展示给用户,然后立即进入第 2 步。用户在子 Agent 并行工作时阅读和思考。
|
|
18
|
+
|
|
19
|
+
### 2. 启动子 Agent
|
|
20
|
+
|
|
21
|
+
使用 Agent 工具并行启动 3+ 个子 Agent。每个子 Agent 必须为深化后的模块生成一个**截然不同的**接口。
|
|
22
|
+
|
|
23
|
+
为每个子 Agent 提供一份独立的技术简报(文件路径、耦合细节、来自 `<Path>{roots.workflows}/specdev/I-implement/deepening.md</Path>` 的依赖类别、接缝背后的内容)。简报独立于第 1 步中面向用户的问题空间说明。给每个 Agent 一个不同的设计约束:
|
|
24
|
+
|
|
25
|
+
- Agent 1:"最小化接口 — 目标 1–3 个入口点。最大化每个入口点的杠杆。"
|
|
26
|
+
- Agent 2:"最大化灵活性 — 支持多种用例和扩展。"
|
|
27
|
+
- Agent 3:"为最常见的调用方优化 — 让默认情况变得简单。"
|
|
28
|
+
- Agent 4(如适用):"围绕接缝设计端口与适配器,以处理跨接缝依赖。"
|
|
29
|
+
|
|
30
|
+
在简报中同时包含 `<Path>{roots.workflows}/specdev/I-implement/codebase-design-glossary.md</Path>` 词汇和 CONTEXT.md 词汇,以便每个子 Agent 能使用架构语言和项目的领域语言一致地命名事物。
|
|
31
|
+
|
|
32
|
+
每个子 Agent 输出:
|
|
33
|
+
|
|
34
|
+
1. 接口(类型、方法、参数 — 以及不变量、排序、错误模式)
|
|
35
|
+
2. 使用示例,展示调用方如何使用它
|
|
36
|
+
3. 实现在接缝背后隐藏了什么
|
|
37
|
+
4. 依赖策略和适配器(参见 `<Path>{roots.workflows}/specdev/I-implement/deepening.md</Path>`)
|
|
38
|
+
5. 权衡 — 哪里杠杆高,哪里杠杆薄
|
|
39
|
+
|
|
40
|
+
### 3. 展示和比较
|
|
41
|
+
|
|
42
|
+
按顺序展示各个设计,让用户能够消化每一个,然后用文字进行比较。通过 **depth**(深度,接口处的杠杆)、**locality**(局部性,变更集中的位置)和 **seam placement**(接缝位置)来对比。
|
|
43
|
+
|
|
44
|
+
比较之后,给出你自己的建议:你认为哪个设计最强以及原因。如果不同设计中的元素可以很好地组合,提出一个混合方案。要有主见 — 用户想要的是一个有力的判断,而不是一个菜单。
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# 好的测试与坏的测试
|
|
2
|
+
|
|
3
|
+
## 好的测试
|
|
4
|
+
|
|
5
|
+
**集成风格**:通过真实接口测试,而非 mock 内部部件。
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// 好:测试可观察的行为
|
|
9
|
+
test("user can checkout with valid cart", async () => {
|
|
10
|
+
const cart = createCart();
|
|
11
|
+
cart.add(product);
|
|
12
|
+
const result = await checkout(cart, paymentMethod);
|
|
13
|
+
expect(result.status).toBe("confirmed");
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
特征:
|
|
18
|
+
|
|
19
|
+
- 测试用户/调用方关心的行为
|
|
20
|
+
- 仅使用公共 API
|
|
21
|
+
- 经受住内部重构
|
|
22
|
+
- 描述 WHAT(做什么),而非 HOW(怎么做)
|
|
23
|
+
- 每个测试一个逻辑断言
|
|
24
|
+
|
|
25
|
+
## 坏的测试
|
|
26
|
+
|
|
27
|
+
**实现细节测试**:与内部结构耦合。
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// 坏:测试实现细节
|
|
31
|
+
test("checkout calls paymentService.process", async () => {
|
|
32
|
+
const mockPayment = jest.mock(paymentService);
|
|
33
|
+
await checkout(cart, payment);
|
|
34
|
+
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
危险信号:
|
|
39
|
+
|
|
40
|
+
- Mock 内部协作者
|
|
41
|
+
- 测试私有方法
|
|
42
|
+
- 断言调用次数/顺序
|
|
43
|
+
- 重构时测试失败但没有行为变化
|
|
44
|
+
- 测试名称描述 HOW 而非 WHAT
|
|
45
|
+
- 通过外部手段而非接口进行验证
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// 坏:绕过接口进行验证
|
|
49
|
+
test("createUser saves to database", async () => {
|
|
50
|
+
await createUser({ name: "Alice" });
|
|
51
|
+
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
|
52
|
+
expect(row).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// 好:通过接口进行验证
|
|
56
|
+
test("createUser makes user retrievable", async () => {
|
|
57
|
+
const user = await createUser({ name: "Alice" });
|
|
58
|
+
const retrieved = await getUser(user.id);
|
|
59
|
+
expect(retrieved.name).toBe("Alice");
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**同义反复测试**:预期值重述了实现,因此测试在构造上就通过了。
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// 坏:预期值以与代码计算方式相同的方式重新计算
|
|
67
|
+
test("calculateTotal sums line items", () => {
|
|
68
|
+
const items = [{ price: 10 }, { price: 5 }];
|
|
69
|
+
const expected = items.reduce((sum, i) => sum + i.price, 0);
|
|
70
|
+
expect(calculateTotal(items)).toBe(expected);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// 好:预期值是独立的、已知的字面量
|
|
74
|
+
test("calculateTotal sums line items", () => {
|
|
75
|
+
expect(calculateTotal([{ price: 10 }, { price: 5 }])).toBe(15);
|
|
76
|
+
});
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
# 何时使用 Mock
|
|
82
|
+
|
|
83
|
+
仅在**系统边界**处使用 Mock:
|
|
84
|
+
|
|
85
|
+
- 外部 API(支付、邮件等)
|
|
86
|
+
- 数据库(有时 — 优先使用测试数据库)
|
|
87
|
+
- 时间/随机性
|
|
88
|
+
- 文件系统(有时)
|
|
89
|
+
|
|
90
|
+
不要 Mock:
|
|
91
|
+
|
|
92
|
+
- 你自己的类/模块
|
|
93
|
+
- 内部协作者
|
|
94
|
+
- 任何你控制的东西
|
|
95
|
+
|
|
96
|
+
## 为可 Mock 性设计
|
|
97
|
+
|
|
98
|
+
在系统边界处,设计易于 mock 的接口:
|
|
99
|
+
|
|
100
|
+
**1. 使用依赖注入**
|
|
101
|
+
|
|
102
|
+
将外部依赖从外部传入,而不是在内部创建:
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// 易于 mock
|
|
106
|
+
function processPayment(order, paymentClient) {
|
|
107
|
+
return paymentClient.charge(order.total);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// 难以 mock
|
|
111
|
+
function processPayment(order) {
|
|
112
|
+
const client = new StripeClient(process.env.STRIPE_KEY);
|
|
113
|
+
return client.charge(order.total);
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**2. 偏好 SDK 风格接口而非通用获取器**
|
|
118
|
+
|
|
119
|
+
为每个外部操作创建特定的函数,而不是带有条件逻辑的通用函数:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// 好:每个函数可以独立 mock
|
|
123
|
+
const api = {
|
|
124
|
+
getUser: (id) => fetch(`/users/${id}`),
|
|
125
|
+
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
|
126
|
+
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// 坏:mock 需要在 mock 内部编写条件逻辑
|
|
130
|
+
const api = {
|
|
131
|
+
fetch: (endpoint, options) => fetch(endpoint, options),
|
|
132
|
+
};
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
SDK 方式的优点:
|
|
136
|
+
- 每个 mock 返回一个特定的形态
|
|
137
|
+
- 测试设置中无需条件逻辑
|
|
138
|
+
- 更容易看出测试涉及哪些端点
|
|
139
|
+
- 每个端点的类型安全
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# 测试驱动开发
|
|
2
|
+
|
|
3
|
+
TDD 是红 → 绿循环。此文件是该循环的参考指南,确保该循环产出的测试值得保留:什么是一个好的测试、测试放在哪里、反模式、以及循环的规则。每个章节在每次循环中都适用 —— 在循环之前和循环期间查阅,而不是之后。
|
|
4
|
+
|
|
5
|
+
在探索代码库时,读取 `{roots.state}/specdev/changes/{change}/CONTEXT.md`(如果存在),使测试名称和接口词汇与项目的领域语言保持一致,并尊重所涉及区域的 ADR。
|
|
6
|
+
|
|
7
|
+
## 什么是好的测试
|
|
8
|
+
|
|
9
|
+
测试通过公共接口验证行为,而不是实现细节。代码可以完全改变;测试不应该。一个好的测试读起来像规范 —— "用户可以使用有效购物车结账" 准确地告诉你存在什么能力 —— 并且在重构后能够存活,因为它不关心内部结构。
|
|
10
|
+
|
|
11
|
+
参见 `<Path>{roots.workflows}/specdev/I-implement/tdd-examples.md</Path>` 了解示例和 Mock 指南。
|
|
12
|
+
|
|
13
|
+
## 接缝 —— 测试放置的位置
|
|
14
|
+
|
|
15
|
+
**接缝(seam)** 是你进行测试的公共边界:你在该接口处观察行为而不触及内部。测试位于接缝处,绝不针对内部细节。
|
|
16
|
+
|
|
17
|
+
**仅在预先约定的接缝处进行测试。** 在编写任何测试之前,写下要测试的接缝并与用户确认。没有在未确认的接缝处编写测试。你无法测试一切 —— 提前约定接缝可以确保测试工作集中在关键路径和复杂逻辑上,而不是每个边缘情况。
|
|
18
|
+
|
|
19
|
+
问:"公共接口是什么,我们应该在哪些接缝处进行测试?"
|
|
20
|
+
|
|
21
|
+
## 反模式
|
|
22
|
+
|
|
23
|
+
- **与实现耦合** —— mock 内部协作者、测试私有方法、或通过旁路通道验证(查询数据库而不是使用接口)。特征:当重构时代码行为未变但测试却失败了。
|
|
24
|
+
- **同义反复** —— 断言以与代码相同的方式重新计算预期值(`expect(add(a, b)).toBe(a + b)`、以相同方式手动推导的快照、将常量断言为等于自身),因此它在构造上就必然通过,永远不可能与代码产生分歧。预期值必须来自独立的真相来源 —— 已知正确的字面量、手工计算示例、规范。
|
|
25
|
+
- **水平切片** —— 先写所有测试,再写所有实现。批量测试验证的是*想象中*的行为:你测试的是事物的*形态*而非面向用户的行为,测试变得对真实变更不敏感,并且你在理解实现之前就锁定了测试结构。应采用**垂直切片** —— 一个测试 → 一个实现 → 重复,每个测试都是一颗**曳光弹**,响应上一个循环的反馈。
|
|
26
|
+
|
|
27
|
+
## 循环的规则
|
|
28
|
+
|
|
29
|
+
- **先红后绿。** 先写失败的测试,然后只写足以通过测试的代码。不要预测未来的测试或添加推测性功能。
|
|
30
|
+
- **一次一个切片。** 每个循环一个接缝、一个测试、一个最小实现。
|
|
31
|
+
- **重构不属于循环。** 它属于审查阶段(参见 `<Path>{roots.workflows}/specdev/I-implement/code-review-process.md</Path>`),而不是红 → 绿实现循环的一部分。
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: specdev/init-setup
|
|
3
|
+
type: workflow-entry
|
|
4
|
+
workflow: specdev
|
|
5
|
+
name: 初始化设置
|
|
6
|
+
description: 为 specdev workflow 配置变更追踪、领域文档布局、状态标签和语言偏好。首次使用其他 specdev works 前运行一次。
|
|
7
|
+
keywords: [初始化, 配置, 设置, setup]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# 初始化设置
|
|
11
|
+
|
|
12
|
+
为 specdev workflow 搭建本地持久化配置——变更追踪约定、领域文档布局、状态标签映射和交互语言偏好。这是一个提示驱动的入口,先探索,展示发现结果,与用户确认,然后写入。
|
|
13
|
+
|
|
14
|
+
所有配置产物写入 `<Path>{roots.state}/specdev/</Path>` 下:
|
|
15
|
+
|
|
16
|
+
- **变更追踪约定** → `<Path>{roots.state}/specdev/.config/tracking.md</Path>` —— 变更以本地 markdown 目录形式管理
|
|
17
|
+
- **领域文档布局** → `<Path>{roots.state}/specdev/.config/domain-layout.md</Path>` —— 三文件模型(ADR/LOG/CONTEXT)的读写规则
|
|
18
|
+
- **状态标签映射** → `<Path>{roots.state}/specdev/.config/status-labels.md</Path>` —— 五个标准 triage 角色的标签字符串
|
|
19
|
+
- **语言与配置** → `<Path>{roots.state}/specdev/config.json</Path>` —— 交互语言、报告语言和持久化设置
|
|
20
|
+
|
|
21
|
+
首次使用 specdev 的任意 work 之前运行一次。之后可直接编辑 `<Path>{roots.state}/specdev/.config/</Path>` 下的文件进行调整,无需重新运行。
|
|
22
|
+
|
|
23
|
+
## 流程
|
|
24
|
+
|
|
25
|
+
### 1. 探索
|
|
26
|
+
|
|
27
|
+
查看当前仓库以了解 specdev 的初始配置状态。读取已有内容;不要假设:
|
|
28
|
+
|
|
29
|
+
- `<Path>{roots.state}/specdev/config.json</Path>` —— 全局配置文件是否已存在?若存在,读取其内容
|
|
30
|
+
- `<Path>{roots.state}/specdev/.config/tracking.md</Path>` —— 变更追踪约定是否已配置?
|
|
31
|
+
- `<Path>{roots.state}/specdev/.config/domain-layout.md</Path>` —— 领域文档布局是否已配置?
|
|
32
|
+
- `<Path>{roots.state}/specdev/.config/status-labels.md</Path>` —— 状态标签映射是否已配置?
|
|
33
|
+
- `<Path>{roots.state}/specdev/status.json</Path>` —— 当前是否有活跃变更?
|
|
34
|
+
- `<Path>{roots.state}/specdev/changes/</Path>` —— 已有哪些变更目录?
|
|
35
|
+
- `<Path>{roots.state}/specdev/archive/</Path>` —— 归档了哪些历史变更?
|
|
36
|
+
|
|
37
|
+
总结已存在的和缺失的内容。
|
|
38
|
+
|
|
39
|
+
**完成标准**:当前 `<Path>{roots.state}/specdev/</Path>` 和已有配置已摸底,已存在的和缺失的内容已明确。
|
|
40
|
+
|
|
41
|
+
然后进入配置阶段——**逐项**引导用户完成四项决策:展示一节,获得用户回答,然后进入下一节。不要一次抛出全部四项。每个配置阶段之前,简短解释它是什么、specdev 的 works 为什么需要它、选择不同会有什么变化。
|
|
42
|
+
|
|
43
|
+
### 2. 变更追踪
|
|
44
|
+
|
|
45
|
+
specdev 的变更追踪使用**本地 markdown** 作为唯一选项。变更以目录形式存放在 `<Path>{roots.state}/specdev/changes/<YYYY-MM-DD>-<topic>/</Path>` 下,通过 `<Path>{roots.state}/specdev/status.json</Path>` 的 `active` 数组追踪当前活跃变更。
|
|
46
|
+
|
|
47
|
+
变更追踪是 specdev 记录工作进度的地方。当你运行 `S-spec`、`I-implement`、`G-grill-with-docs` 等 work 时,它们会将产物写入当前变更目录。与 GitHub Issues 或 Jira 不同,本地 markdown 方式让所有工作产物(需求文档、设计决策、实现记录)与代码存放在同一仓库中,无需网络连接,且完全由 git 版本控制。
|
|
48
|
+
|
|
49
|
+
确认用户理解此约定后,将详细规则写入 `<Path>{roots.state}/specdev/.config/tracking.md</Path>`。
|
|
50
|
+
|
|
51
|
+
详细约定参见 `<Path>{roots.workflows}/specdev/I-init-setup/tracking-convention.md</Path>`。
|
|
52
|
+
|
|
53
|
+
**完成标准**:变更追踪约定已确认并写入 `<Path>{roots.state}/specdev/.config/tracking.md</Path>`。
|
|
54
|
+
|
|
55
|
+
### 3. 领域文档布局
|
|
56
|
+
|
|
57
|
+
specdev 使用**单上下文**布局。每个变更目录 `<Path>{roots.state}/specdev/changes/{change}/</Path>` 下维护三个文件:
|
|
58
|
+
|
|
59
|
+
- **CONTEXT.md** —— 项目领域术语与概念
|
|
60
|
+
- **ADR.md** —— 架构决策记录(本变更相关的决策)
|
|
61
|
+
- **LOG.md** —— 设计决策日志(按时间顺序记录每次设计调整)
|
|
62
|
+
|
|
63
|
+
部分 specdev work(如 `G-grill-with-docs`、`I-implement`)在探索代码库时会读取 CONTEXT.md 了解项目的领域语言,以及 ADR.md 了解过去的架构决策。单上下文意味着整个 specdev workflow 共享一套术语和决策记录,所有变更目录下的三文件模型均遵循相同约定。
|
|
64
|
+
|
|
65
|
+
确认用户理解此布局后,将消费方规则写入 `<Path>{roots.state}/specdev/.config/domain-layout.md</Path>`。
|
|
66
|
+
|
|
67
|
+
详细约定参见 `<Path>{roots.workflows}/specdev/I-init-setup/domain-layout.md</Path>`。
|
|
68
|
+
|
|
69
|
+
**完成标准**:领域文档布局已确认——三文件(ADR/LOG/CONTEXT)持久化到 `<Path>{roots.state}/specdev/changes/{change}/</Path>`,消费方规则已写入。
|
|
70
|
+
|
|
71
|
+
### 4. 状态标签
|
|
72
|
+
|
|
73
|
+
specdev 使用五个标准状态角色来追踪工作项的生命周期:
|
|
74
|
+
|
|
75
|
+
| 角色 | 默认标签 | 含义 |
|
|
76
|
+
|------|---------|------|
|
|
77
|
+
| `needs-triage` | `needs-triage` | 需要评估 |
|
|
78
|
+
| `needs-info` | `needs-info` | 等待补充信息 |
|
|
79
|
+
| `ready-for-agent` | `ready-for-agent` | 可执行(agent 无需额外人工上下文即可领取) |
|
|
80
|
+
| `ready-for-human` | `ready-for-human` | 需人工处理 |
|
|
81
|
+
| `wontfix` | `wontfix` | 不处理 |
|
|
82
|
+
|
|
83
|
+
当 `T-tickets`、`W-wayfinder` 等 work 处理工作项时,它们会将工作项移过一个状态机——需要评估、等待补充、可供 agent 领取、需人工处理、或不予处理。状态标签是这些状态在持久化文件中的字符串表示。默认每个角色的标签等于其名称,如果你的项目已有不同命名习惯,可以在此映射。
|
|
84
|
+
|
|
85
|
+
确认用户是否接受默认标签,或需要覆盖为自定义字符串。将映射写入 `<Path>{roots.state}/specdev/.config/status-labels.md</Path>`。
|
|
86
|
+
|
|
87
|
+
详细约定参见 `<Path>{roots.workflows}/specdev/I-init-setup/status-labels.md</Path>`。
|
|
88
|
+
|
|
89
|
+
**完成标准**:状态标签映射已确认并写入 `<Path>{roots.state}/specdev/.config/status-labels.md</Path>`。
|
|
90
|
+
|
|
91
|
+
### 5. 语言与配置
|
|
92
|
+
|
|
93
|
+
询问用户两项语言偏好:
|
|
94
|
+
|
|
95
|
+
- **交互语言** —— specdev 与用户交互时使用的语言。选项:`zh-CN`(简体中文)、`en`(英文)。默认:`zh-CN`。
|
|
96
|
+
- **报告语言** —— AI 生成产物(Markdown 文档、issue 正文、报告)的默认语言。默认与交互语言相同。
|
|
97
|
+
|
|
98
|
+
specdev 使用 `<Path>{roots.state}/specdev/config.json</Path>` 存储全局配置。所有 specdev works 在启动时读取此文件以自动选择交互语言和确认策略,无需每次手动指定。
|
|
99
|
+
|
|
100
|
+
将配置写入 `<Path>{roots.state}/specdev/config.json</Path>`:
|
|
101
|
+
|
|
102
|
+
```jsonc
|
|
103
|
+
{
|
|
104
|
+
"schema_version": 1,
|
|
105
|
+
"language": "<用户选择的交互语言>",
|
|
106
|
+
"persistence": {
|
|
107
|
+
"root_override": null
|
|
108
|
+
},
|
|
109
|
+
"defaults": {
|
|
110
|
+
"confirm_before_external_write": true,
|
|
111
|
+
"report_language": "<用户选择的报告语言>"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
如果 `<Path>{roots.state}/specdev/config.json</Path>` 已存在,仅更新用户本次修改的字段,保留其他现有值。
|
|
117
|
+
|
|
118
|
+
**完成标准**:语言偏好和配置已写入 `<Path>{roots.state}/specdev/config.json</Path>`。
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
配置完成后,提醒用户可以直接编辑 `<Path>{roots.state}/specdev/.config/</Path>` 下的文件进行调整。只有在需要从头重新配置时才需重新运行本入口。
|
|
123
|
+
|
|
124
|
+
## 子文件引用
|
|
125
|
+
|
|
126
|
+
以下子文件包含各配置阶段的详细约定和消费方规则,仅在对应步骤进入时加载:
|
|
127
|
+
|
|
128
|
+
| 文件 | 内容 | 触发条件 |
|
|
129
|
+
|------|------|---------|
|
|
130
|
+
| `<Path>{roots.workflows}/specdev/I-init-setup/tracking-convention.md</Path>` | 本地 markdown 变更追踪的读写约定 | 步骤 2「变更追踪」进入时 |
|
|
131
|
+
| `<Path>{roots.workflows}/specdev/I-init-setup/domain-layout.md</Path>` | 单上下文三文件模型的路径解析和消费方规则 | 步骤 3「领域文档布局」进入时 |
|
|
132
|
+
| `<Path>{roots.workflows}/specdev/I-init-setup/status-labels.md</Path>` | 五个标准状态角色的标签字符串映射 | 步骤 4「状态标签」进入时 |
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# 领域文档布局
|
|
2
|
+
|
|
3
|
+
specdev 各 work 在探索代码库时应如何使用该仓库的领域文档。
|
|
4
|
+
|
|
5
|
+
## 布局:单上下文
|
|
6
|
+
|
|
7
|
+
specdev 使用单上下文布局——整个 workflow 共享一套领域术语和架构决策。每个变更目录 `changes/<change>/` 下维护三文件模型:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
{state_root}/changes/<change>/
|
|
11
|
+
├── CONTEXT.md ← 项目领域术语与概念
|
|
12
|
+
├── ADR.md ← 本变更相关的架构决策记录
|
|
13
|
+
└── LOG.md ← 设计决策日志(按时间顺序记录每次设计调整)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- **CONTEXT.md** —— 定义项目特有的领域概念和术语表。各 work 在输出中引用领域概念时以本文档为准。
|
|
17
|
+
- **ADR.md** —— 记录本变更范围内的架构决策(格式:`## ADR-NNNN: 标题`)。如果变更跨多个上下文,决策记录在触发该决策的变更目录下。
|
|
18
|
+
- **LOG.md** —— 按时间倒序记录每次设计调整、决策变更及其原因。格式:`## YYYY-MM-DD HH:MM — 标题`,每次记录包含:**决策**(做什么)、**原因**(为什么)、**影响**(影响哪些 work/文件)。
|
|
19
|
+
|
|
20
|
+
> 与 vendor 技能(如 domain-modeling)描述的通用仓库布局不同,specdev 将所有领域文档限定在 `changes/<change>/` 目录内。当 vendor skill 指示"在仓库根目录创建 CONTEXT.md"时,specdev 的适配层将其翻译为写入 `{state_root}/changes/<change>/CONTEXT.md`。
|
|
21
|
+
|
|
22
|
+
## 路径解析规则
|
|
23
|
+
|
|
24
|
+
**本文件描述的路径均为相对于 `{state_root}` 的逻辑路径。** 实际写入时由 Speculo persistence 层映射到 `{roots.state}/specdev/` 命名空间下。
|
|
25
|
+
|
|
26
|
+
- `CONTEXT.md` → `{state_root}/changes/<current_change>/CONTEXT.md`
|
|
27
|
+
- `ADR.md` → `{state_root}/changes/<current_change>/ADR.md`
|
|
28
|
+
- `LOG.md` → `{state_root}/changes/<current_change>/LOG.md`
|
|
29
|
+
- `{state_root}` 由 runtime-context 解析为 `{roots.state}/specdev/`
|
|
30
|
+
- `<current_change>` 由 `status.json` 的 `active` 数组确定(取第一个活跃变更)
|
|
31
|
+
|
|
32
|
+
## 在探索之前
|
|
33
|
+
|
|
34
|
+
当 specdev work 需要领域上下文时,按以下顺序读取:
|
|
35
|
+
|
|
36
|
+
1. **`CONTEXT.md`**(位于当前变更目录内)—— 项目领域语言,由 `G-grill-with-docs` 或 `I-implement` 在探索代码库时创建或更新
|
|
37
|
+
2. **`ADR.md`**(位于当前变更目录内)—— 涉及当前变更的架构决策,由 `G-grill-with-docs` 在讨论架构时更新
|
|
38
|
+
3. **`LOG.md`**(位于当前变更目录内)—— 设计决策历史,由各 work 在设计调整时追加记录
|
|
39
|
+
|
|
40
|
+
如果这些文件都不存在,静默继续。不要标记它们的缺失或预先建议创建。`G-grill-with-docs` 和 `I-implement` 在领域知识或决策实际被确定时延迟创建它们。
|
|
41
|
+
|
|
42
|
+
## 使用术语表的词汇
|
|
43
|
+
|
|
44
|
+
输出中命名领域概念时,使用 `CONTEXT.md` 中定义的术语,不偏离到术语表明确避免的同义词。如果需要的新概念尚未在术语表中,记录到 `CONTEXT.md` 并通知用户。
|
|
45
|
+
|
|
46
|
+
如果 `CONTEXT.md` 不存在,在首次需要时由当前 work 创建骨架:
|
|
47
|
+
|
|
48
|
+
```markdown
|
|
49
|
+
# CONTEXT — <change 主题>
|
|
50
|
+
|
|
51
|
+
## 领域术语
|
|
52
|
+
|
|
53
|
+
| 术语 | 定义 | 别名 / 避免使用 |
|
|
54
|
+
|------|------|----------------|
|
|
55
|
+
| ... | ... | ... |
|
|
56
|
+
|
|
57
|
+
## 边界上下文
|
|
58
|
+
|
|
59
|
+
<!-- 如有多个子域,在此划分边界 -->
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## 标记 ADR 冲突
|
|
63
|
+
|
|
64
|
+
如果输出与现有 ADR 矛盾,明确提出而不是默默覆盖:
|
|
65
|
+
|
|
66
|
+
> _与 `<Path>{roots.state}/specdev/changes/<change>/ADR.md</Path>` 中的 ADR-NNNN 矛盾 — 但值得重新讨论,因为……_
|
|
67
|
+
|
|
68
|
+
同时将冲突记录追加到 `LOG.md`:
|
|
69
|
+
|
|
70
|
+
```markdown
|
|
71
|
+
## YYYY-MM-DD HH:MM — ADR 冲突标记
|
|
72
|
+
|
|
73
|
+
- **冲突**: 当前建议与 ADR-NNNN 矛盾
|
|
74
|
+
- **原因**: <重新讨论的理由>
|
|
75
|
+
- **影响**: 如采纳新方案,需更新 ADR.md 并记录迁移路径
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 写入 LOG.md
|
|
79
|
+
|
|
80
|
+
每次设计调整或决策变更时,在 `LOG.md` 顶部追加一条记录(时间倒序):
|
|
81
|
+
|
|
82
|
+
```markdown
|
|
83
|
+
## YYYY-MM-DD HH:MM — <简短标题>
|
|
84
|
+
|
|
85
|
+
- **决策**: <做了什么设计决定>
|
|
86
|
+
- **原因**: <为什么做这个决定>
|
|
87
|
+
- **影响**: <影响哪些 work、哪些文件、哪些后续步骤>
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`LOG.md` 不同于 `ADR.md`:ADR 记录的是相对稳定的架构决策,LOG 记录的是日常设计调整的过程脉络。如果某条 LOG 记录具有长期参考价值,提取为 ADR。
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# 状态标签
|
|
2
|
+
|
|
3
|
+
specdev 各 work 使用五种规范的状态角色来追踪工作项的生命周期。本文件将这些角色映射到持久化文件中使用的实际标签字符串。
|
|
4
|
+
|
|
5
|
+
| 角色 | 标签 | 含义 |
|
|
6
|
+
|------|------|------|
|
|
7
|
+
| `needs-triage` | `needs-triage` | 需要评估 —— 维护者需要判断此工作项的性质、优先级和归属 |
|
|
8
|
+
| `needs-info` | `needs-info` | 等待补充信息 —— 工作项描述不足,等待报告者或需求方提供更多上下文 |
|
|
9
|
+
| `ready-for-agent` | `ready-for-agent` | 可执行 —— 已完整定义,agent 无需额外人工上下文即可领取并开始工作 |
|
|
10
|
+
| `ready-for-human` | `ready-for-human` | 需人工处理 —— 工作项需要人工判断、审批或执行,不适合 agent 自动处理 |
|
|
11
|
+
| `wontfix` | `wontfix` | 不处理 —— 经评估后决定不予处理,保留记录以供追溯 |
|
|
12
|
+
|
|
13
|
+
## 使用方式
|
|
14
|
+
|
|
15
|
+
当 work 提及某个角色(例如"标记为需要评估"、"应用 ready-for-agent 状态")时,使用此表中对应的标签字符串写入持久化文件。
|
|
16
|
+
|
|
17
|
+
标签字符串写入位置取决于具体 work:
|
|
18
|
+
|
|
19
|
+
- **T-tickets** —— 写入工作项文件(`tickets/NN-<slug>.md`)顶部的 `Status:` 行
|
|
20
|
+
- **W-wayfinder** —— 写入 `wayfinder/map.md` 中工作项的状态标记
|
|
21
|
+
- **其他 work** —— 在变更目录的相应产物文件中以 frontmatter 或元数据行形式记录
|
|
22
|
+
|
|
23
|
+
## 状态流转
|
|
24
|
+
|
|
25
|
+
```
|
|
26
|
+
needs-triage ──→ needs-info ──→ needs-triage ──→ ready-for-agent
|
|
27
|
+
│ │
|
|
28
|
+
│ ├──→ ready-for-human
|
|
29
|
+
│ │
|
|
30
|
+
└──────────────────→ wontfix ←──────────────────┘
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
- `needs-triage` → `needs-info`:评估后发现信息不足,退回补充
|
|
34
|
+
- `needs-triage` → `ready-for-agent`:已完整定义,可供 agent 执行
|
|
35
|
+
- `needs-triage` → `ready-for-human`:需要人工处理
|
|
36
|
+
- `needs-triage` → `wontfix`:决定不予处理
|
|
37
|
+
- `needs-info` → `needs-triage`:补充信息后重新评估
|
|
38
|
+
- `ready-for-agent` → `wontfix`:执行过程中发现不再适用
|
|
39
|
+
|
|
40
|
+
## 自定义标签
|
|
41
|
+
|
|
42
|
+
如果你的项目已有不同的标签命名习惯(例如使用 `bug:triage` 而不是 `needs-triage`),编辑右侧的"标签"列以匹配你实际使用的字符串。左侧的"角色"列不变——各 work 通过角色名引用状态,不直接依赖标签字符串。
|
|
43
|
+
|
|
44
|
+
例如,如果你的项目使用中文标签:
|
|
45
|
+
|
|
46
|
+
| 角色 | 标签 |
|
|
47
|
+
|------|------|
|
|
48
|
+
| `needs-triage` | `待评估` |
|
|
49
|
+
| `needs-info` | `待补充` |
|
|
50
|
+
| `ready-for-agent` | `可执行` |
|
|
51
|
+
| `ready-for-human` | `需人工` |
|
|
52
|
+
| `wontfix` | `不处理` |
|
|
53
|
+
|
|
54
|
+
确保标签字符串在实际使用位置(tickets 文件、wayfinder 地图等)保持一致。
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# 变更追踪:本地 Markdown
|
|
2
|
+
|
|
3
|
+
specdev workflow 的变更以 markdown 目录形式存储在 `{roots.state}/specdev/changes/` 中。
|
|
4
|
+
|
|
5
|
+
## 约定
|
|
6
|
+
|
|
7
|
+
- 每个变更一个目录:`{roots.state}/specdev/changes/<YYYY-MM-DD>-<topic>/`
|
|
8
|
+
- 例如:`changes/2026-07-21-add-auth-layer/`
|
|
9
|
+
- 当前活跃变更通过 `{roots.state}/specdev/status.json` 的 `active` 数组追踪
|
|
10
|
+
- 归档变更移至:`{roots.state}/specdev/archive/YYYY-MM/<change>/`
|
|
11
|
+
- 例如:`archive/2026-07/2026-07-21-add-auth-layer/`
|
|
12
|
+
- 变更目录内的工作产物由各 work 定义,典型结构:
|
|
13
|
+
```
|
|
14
|
+
changes/<YYYY-MM-DD>-<topic>/
|
|
15
|
+
├── CONTEXT.md ← 领域术语与概念(由 domain-modeling 或 G-grill-with-docs 创建/更新)
|
|
16
|
+
├── ADR.md ← 架构决策记录(由 G-grill-with-docs 或 I-implement 创建/更新)
|
|
17
|
+
├── LOG.md ← 设计决策日志(按时间顺序记录每次设计调整)
|
|
18
|
+
├── spec.md ← 需求规格(由 S-spec 创建)
|
|
19
|
+
├── tickets/ ← 工作项(由 T-tickets 创建)
|
|
20
|
+
│ └── NN-<slug>.md
|
|
21
|
+
└── wayfinder/ ← 路线图(由 W-wayfinder 创建)
|
|
22
|
+
└── map.md
|
|
23
|
+
```
|
|
24
|
+
- `status.json` 结构:
|
|
25
|
+
```jsonc
|
|
26
|
+
{
|
|
27
|
+
"schema_version": 1,
|
|
28
|
+
"workflow": "specdev",
|
|
29
|
+
"active": [
|
|
30
|
+
"2026-07-21-add-auth-layer"
|
|
31
|
+
]
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 当 work 说"发布到变更目录"时
|
|
36
|
+
|
|
37
|
+
在 `{roots.state}/specdev/changes/<change>/` 下创建或更新指定文件。如果变更目录尚未加入 `active` 数组,将其追加到 `status.json` 的 `active` 中。
|
|
38
|
+
|
|
39
|
+
例如:`S-spec` 说"将规格发布到变更目录" → 写入 `<Path>{roots.state}/specdev/changes/<change>/spec.md</Path>`。
|
|
40
|
+
|
|
41
|
+
## 当 work 说"获取当前变更"时
|
|
42
|
+
|
|
43
|
+
读取 `<Path>{roots.state}/specdev/status.json</Path>` 的 `active` 数组,获取当前活跃变更列表。如果存在多个活跃变更,提示用户选择目标变更。如果无活跃变更,提示用户先运行 `S-spec` 或 `I-init-setup` 创建变更。
|
|
44
|
+
|
|
45
|
+
## 当 work 说"归档变更"时
|
|
46
|
+
|
|
47
|
+
将变更目录从 `{roots.state}/specdev/changes/<change>/` 移动到 `{roots.state}/specdev/archive/YYYY-MM/<change>/`(YYYY-MM 取变更日期中的年月),并从 `status.json` 的 `active` 数组中移除。
|
|
48
|
+
|
|
49
|
+
## Wayfinding 操作
|
|
50
|
+
|
|
51
|
+
供 `W-wayfinder` 使用。**地图**是一个文件,每个工作项有一个**子**文件。
|
|
52
|
+
|
|
53
|
+
- **地图**:`{roots.state}/specdev/changes/<change>/wayfinder/map.md` —— Notes / Decisions-so-far / Fog 正文。
|
|
54
|
+
- **子工单**:`{roots.state}/specdev/changes/<change>/tickets/NN-<slug>.md`,从 `01` 开始编号,正文中包含问题。`Type:` 行记录工单类型(`research` / `prototype` / `grilling` / `task`);`Status:` 行记录 `claimed` / `resolved`。
|
|
55
|
+
- **阻塞**:顶部附近的 `Blocked by: NN, NN` 行。当其列出的每个文件都处于 `resolved` 状态时,工单解除阻塞。
|
|
56
|
+
- **前沿**:扫描 `tickets/` 中处于开放、未阻塞且未认领状态的文件;按编号取第一个。
|
|
57
|
+
- **认领**:设置 `Status: claimed` 并在任何工作开始前保存。
|
|
58
|
+
- **解决**:在 `## Answer` 标题下追加答案,设置 `Status: resolved`,然后将上下文指针(gist + 链接)追加到 `map.md` 中地图的 Decisions-so-far 中。
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: specdev
|
|
3
|
+
type: workflow
|
|
4
|
+
workflow: specdev
|
|
5
|
+
name: SpecDev Workflow
|
|
6
|
+
description: 软件研发全流程——从初始化设置、设计访谈(带 ADR/LOG/CONTEXT)、spec 编写、ticket 拆分、寻路到 TDD 实现与双轴审查
|
|
7
|
+
keywords: [specdev, 软件研发, 设计, spec, tickets, 寻路, TDD, 实现, 审查]
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# SpecDev Workflow
|
|
11
|
+
|
|
12
|
+
本文件是 `specdev` 的唯一入口——包含运行时根、持久化约定、启动协议、状态字段、路径分配、副作用边界以及 work 条目索引。
|
|
13
|
+
|
|
14
|
+
## 运行时根
|
|
15
|
+
|
|
16
|
+
- **workflow 根**(`{roots.workflows}`)解析为 `<Path>{roots.workflows}/specdev/</Path>`,指向 work 入口和子文件所在目录
|
|
17
|
+
- **state 根**(`{roots.state}`)解析为 `<Path>{roots.state}/specdev/</Path>`,指向持久化状态和变更产物所在目录
|
|
18
|
+
|
|
19
|
+
## 持久化约定
|
|
20
|
+
|
|
21
|
+
在 state 根下维护以下结构:
|
|
22
|
+
|
|
23
|
+
| 名称 | 路径 | 说明 |
|
|
24
|
+
|------|------|------|
|
|
25
|
+
| 状态索引 | `<Path>{roots.state}/specdev/status.json</Path>` | workflow 全局状态 |
|
|
26
|
+
| 工作流配置 | `<Path>{roots.state}/specdev/.config/</Path>` | 变更追踪、领域文档布局、状态标签映射等配置约定 |
|
|
27
|
+
| 活跃变更 | `<Path>{roots.state}/specdev/changes/</Path>` | 进行中的 change 产物(ADR、LOG、CONTEXT、spec、tickets、map 等) |
|
|
28
|
+
| 永久 ADR | `<Path>{roots.state}/specdev/adr/</Path>` | changes 中经确认后的 ADR 提升至此,始终反映当前架构决策现状 |
|
|
29
|
+
| 永久词汇表 | `<Path>{roots.state}/specdev/context/</Path>` | changes 中经确认后的 CONTEXT 提升至此,始终反映当前领域术语现状 |
|
|
30
|
+
| 变更归档 | `<Path>{roots.state}/specdev/archive/</Path>` | 已完成并归档的历史 change,按 YYYY-MM/<change>/ 组织 |
|
|
31
|
+
|
|
32
|
+
`.config/` 目录包含三个由 `I-init-setup` 生成的配置文件,定义 specdev 各 work 的持久化和行为约定:
|
|
33
|
+
|
|
34
|
+
- **`tracking.md`** — 变更追踪约定:变更目录的命名规范(`<YYYY-MM-DD>-<topic>`)、目录结构、`status.json` 机制、归档规则
|
|
35
|
+
- **`domain-layout.md`** — 领域文档布局:三文件模型(CONTEXT.md / ADR.md / LOG.md)的路径解析规则和读取顺序
|
|
36
|
+
- **`status-labels.md`** — 状态标签映射:五个标准角色(`needs-triage` / `needs-info` / `ready-for-agent` / `ready-for-human` / `wontfix`)的标签字符串、状态流转图和自定义方式
|
|
37
|
+
|
|
38
|
+
`status.json`、`changes/`、`archive/` 为固定骨架,由 `speculo init` 创建。`adr/` 和 `context/` 为确认后创建——当 changes 中的 ADR、CONTEXT 经确认符合当前现状后,提升到这两个目录,始终保持与项目当前状态一致。
|
|
39
|
+
|
|
40
|
+
## 启动协议
|
|
41
|
+
|
|
42
|
+
1. **解析运行时** — 解析 workspace 配置和 workflow/state roots。已解析时复用。
|
|
43
|
+
2. **选择 change** — 读取 `<Path>{roots.state}/specdev/status.json</Path>`:
|
|
44
|
+
- 用户指定 → 直接使用
|
|
45
|
+
- 唯一活跃 change → 直接使用
|
|
46
|
+
- 无活跃 → 创建 `changes/<YYYY-MM-DD>-<kebab-topic>/`,注册到 `active` 数组
|
|
47
|
+
- 多个候选 → 先消歧
|
|
48
|
+
|
|
49
|
+
## 状态字段
|
|
50
|
+
|
|
51
|
+
`<Path>{roots.state}/specdev/status.json</Path>` 包含以下字段:
|
|
52
|
+
|
|
53
|
+
- **`schema_version`**(数字)— 状态 schema 版本号,当前为 1
|
|
54
|
+
- **`workflow`**(字符串)— workflow 标识,固定为 `"specdev"`
|
|
55
|
+
- **`active`**(字符串数组)— 当前活跃 change 的目录名列表,每个元素为 `"YYYY-MM-DD-<topic>"` 格式。空数组表示无活跃 change
|
|
56
|
+
- **`current_work`**(字符串或 null)— 当前正在执行的 work id,如 `"specdev/grill-with-docs"`。无正在执行的 work 时为 null
|
|
57
|
+
- **`work_history`**(对象数组)— work 调用记录,每条包含:
|
|
58
|
+
- `work_id` — work 标识
|
|
59
|
+
- `started_at` — 开始时间(ISO 8601)
|
|
60
|
+
- `completed_at` — 完成时间(ISO 8601),未完成时为 null
|
|
61
|
+
- `result` — 完成结果,如 `"completed"`、`"aborted"`
|
|
62
|
+
- `artifacts` — 产物的项目相对路径列表
|
|
63
|
+
|
|
64
|
+
## 路径分配
|
|
65
|
+
|
|
66
|
+
1. 产物写入当前 change 目录(`<Path>{roots.state}/specdev/changes/{change}/</Path>`)
|
|
67
|
+
2. 领域文档(ADR.md、LOG.md、CONTEXT.md)由 `G-grill-with-docs` 维护
|
|
68
|
+
3. Spec、tickets、map 等产物由对应 work 写入当前 change 目录
|
|
69
|
+
4. 项目代码、测试写入项目相对路径,验证指针记录到 change
|
|
70
|
+
5. 所有引用使用 `<Path>{roots.workflows}/specdev/...</Path>` 或 `<Path>{roots.state}/specdev/...</Path>` 格式,不引用外部
|
|
71
|
+
|
|
72
|
+
## 副作用边界
|
|
73
|
+
|
|
74
|
+
确认前不得执行:提交代码、合并/删除 worktree、发布/部署。结果记录到 `<Path>{roots.state}/specdev/changes/{change}/LOG.md</Path>`。敏感值不得写入。
|
|
75
|
+
|
|
76
|
+
## Work 条目
|
|
77
|
+
|
|
78
|
+
<!-- AUTO-INDEX-START -->
|
|
79
|
+
|
|
80
|
+
- **D-diagnose-bugs** — 诊断:针对疑难 bug 建立诊断循环——构建紧凑反馈回路、复现最小化、可证伪假设排名、插桩定位根因,确认后移交 I-implement 修复。
|
|
81
|
+
- **G-grill-with-docs** — 设计访谈(带文档):无情访谈打磨设计,同时持续产出 ADR.md、LOG.md 和 CONTEXT.md 三个领域文档。在设计讨论中捕获术语定义、记录架构决策、保存完整设计轨迹。
|
|
82
|
+
- **I-implement** — 实现:基于 spec 或 tickets 实现工作——以深层模块设计原则指导架构、以 TDD 红绿循环驱动编码、以双轴审查把关质量。
|
|
83
|
+
- **I-init-setup** — 初始化设置:为 specdev workflow 配置变更追踪、领域文档布局、状态标签和语言偏好。首次使用其他 specdev works 前运行一次。
|
|
84
|
+
- **S-spec** — 编写 Spec:将当前对话综合为一份完整的 spec 文档,包含问题陈述、解决方案、用户故事、实现决策和测试决策,持久化到变更目录。
|
|
85
|
+
- **T-tickets** — 拆分 Tickets:将 spec 或计划拆分为一组曳光弹式垂直切片 tickets,每个声明阻塞边,持久化到变更目录。支持宽重构的扩展-收缩排序。
|
|
86
|
+
- **W-wayfinder** — 寻路:为超出单次会话容量的大块工作绘制共享地图,逐个解决调查 tickets 直到通往目标的路径清晰可见。支持研究和决策型 ticket 类型。
|
|
87
|
+
|
|
88
|
+
<!-- AUTO-INDEX-END -->
|