sdd-flow-kit 1.0.11 → 1.0.16
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 +17 -4
- package/dist/postinstall.js +34 -18
- package/dist/steps/setupProject.js +22 -5
- package/dist/steps/startFlow.js +4 -1
- package/package.json +1 -1
- package/src/templates/artifacts/03-/345/276/205/347/241/256/350/256/244/351/227/256/351/242/230/346/270/205/345/215/225.template.md +7 -3
- package/src/templates/artifacts/06-agent-skill.template.md +29 -2
- package/src/templates/prompts/02-sdd-loop-prompt.md +12 -5
- package/src/templates/rules/sdd-no-implement-until-apply.mdc.template +41 -0
package/README.md
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
检查是否安装 - `ls .cursor/skills/sdd-flow-kit/SKILL.md`
|
|
19
19
|
- `ls .claude/skills/sdd-flow-kit/SKILL.md`
|
|
20
20
|
- `ls docs/*-doc-skill/SKILL.md`
|
|
21
|
-
3.
|
|
22
|
-
- `node ./node_modules/sdd-flow-kit/dist/postinstall.js
|
|
21
|
+
3. 若 skill 未生成,执行手动兜底:
|
|
22
|
+
- `node ./node_modules/sdd-flow-kit/dist/postinstall.js`(轻量,秒级)
|
|
23
|
+
- 或 `npx sdd-flow-kit install -y`(完整环境)
|
|
23
24
|
|
|
24
25
|
4. (可选)预演安装:`npx sdd-flow-kit install --dry-run --plan-json`
|
|
25
26
|
5. (可选)环境健检:`npx sdd-flow-kit doctor --agent claude-code`
|
|
@@ -44,11 +45,23 @@
|
|
|
44
45
|
|
|
45
46
|
团队推荐安装命令(稳妥):
|
|
46
47
|
|
|
47
|
-
`pnpm add -D sdd-flow-kit
|
|
48
|
+
`pnpm add -D sdd-flow-kit`
|
|
49
|
+
|
|
50
|
+
> `postinstall` 仅做**轻量**初始化(写入 skill / Cursor 规则 / docs-skill / `.opsx/config.json`),**不会**交互提问,也**不会**跑 `npx opsx-workflow`(避免 `pnpm i` 卡住)。
|
|
51
|
+
> 完整环境(分支切换 + opsx-workflow)请另执行:`npx sdd-flow-kit install -y`
|
|
52
|
+
> 跳过 postinstall:`SDD_FLOW_KIT_SKIP_POSTINSTALL=1 pnpm add -D sdd-flow-kit`
|
|
48
53
|
|
|
49
54
|
#### 使用说明
|
|
50
55
|
|
|
51
|
-
|
|
56
|
+
##### 需求澄清:用户无需背提示词
|
|
57
|
+
|
|
58
|
+
`install` 会写入 `.cursor/rules/sdd-flow-kit-gates.mdc` 与触发 Skill。
|
|
59
|
+
澄清阶段你**直接粘贴确认点**(编号列表即可),AI 应自动进入文档模式,只改 `openspec/PRD/**`,不改 `src/`。
|
|
60
|
+
写业务代码仅在 `/opsx-propose` 完成且你同意 `/opsx-apply` 之后。
|
|
61
|
+
|
|
62
|
+
阶段口语(可选,非必须):`继续` / `做提案` → propose;`开始 apply` → 实现。
|
|
63
|
+
|
|
64
|
+
1. `install`(等价 `setup`):提示选择开发环境(cursor/claude-code/codex/openclaw,默认 claude-code)与开发分支(无则自动创建),并检测/安装 openspec+superpower 基础环境,同时写入项目级 Skill 与 Cursor 门禁规则
|
|
52
65
|
2. 安装完成后,本工具主要负责“流程环境与模板”落地;业务需求由你在目标 AI 工具中自然语言驱动
|
|
53
66
|
3. `start`/`run`/`invoke` 属于进阶能力(脚本化或一键编排时使用)
|
|
54
67
|
4. `doctor`:检查 git/npx/agent CLI/openspec/tool 目录,输出可机读诊断结果
|
package/dist/postinstall.js
CHANGED
|
@@ -8,13 +8,6 @@ const promises_1 = __importDefault(require("node:fs/promises"));
|
|
|
8
8
|
const node_process_1 = __importDefault(require("node:process"));
|
|
9
9
|
const setupProject_1 = require("./steps/setupProject");
|
|
10
10
|
const ALLOWED_PROJECTS = ["OMS", "ADI", "欢盟", "AD Tools"];
|
|
11
|
-
function resolveProjectKindFromEnv() {
|
|
12
|
-
const raw = (node_process_1.default.env.SDD_FLOW_KIT_PROJECT ?? "").trim();
|
|
13
|
-
if (ALLOWED_PROJECTS.includes(raw)) {
|
|
14
|
-
return raw;
|
|
15
|
-
}
|
|
16
|
-
return "OMS";
|
|
17
|
-
}
|
|
18
11
|
async function inferProjectKind(projectRoot) {
|
|
19
12
|
const fromEnv = (node_process_1.default.env.SDD_FLOW_KIT_PROJECT ?? "").trim();
|
|
20
13
|
if (ALLOWED_PROJECTS.includes(fromEnv)) {
|
|
@@ -30,7 +23,6 @@ async function inferProjectKind(projectRoot) {
|
|
|
30
23
|
return "欢盟";
|
|
31
24
|
if (hit("ad-tools") || hit("adtools") || hit("tools"))
|
|
32
25
|
return "AD Tools";
|
|
33
|
-
// 尝试读取项目 package.json 的 name 做二次推断
|
|
34
26
|
try {
|
|
35
27
|
const pkgText = await promises_1.default.readFile(node_path_1.default.join(projectRoot, "package.json"), "utf8");
|
|
36
28
|
const pkg = JSON.parse(pkgText);
|
|
@@ -50,33 +42,57 @@ async function inferProjectKind(projectRoot) {
|
|
|
50
42
|
}
|
|
51
43
|
return "OMS";
|
|
52
44
|
}
|
|
45
|
+
async function inferAgent(projectRoot) {
|
|
46
|
+
const fromEnv = (node_process_1.default.env.SDD_FLOW_KIT_AGENT ?? "").trim();
|
|
47
|
+
const allowed = ["cursor", "claude-code", "codex", "openclaw"];
|
|
48
|
+
if (allowed.includes(fromEnv))
|
|
49
|
+
return fromEnv;
|
|
50
|
+
const exists = async (rel) => {
|
|
51
|
+
try {
|
|
52
|
+
await promises_1.default.access(node_path_1.default.join(projectRoot, rel));
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
if (await exists(".cursor"))
|
|
60
|
+
return "cursor";
|
|
61
|
+
if (await exists(".claude"))
|
|
62
|
+
return "claude-code";
|
|
63
|
+
if (await exists(".codex"))
|
|
64
|
+
return "codex";
|
|
65
|
+
if (await exists(".openclaw"))
|
|
66
|
+
return "openclaw";
|
|
67
|
+
return "cursor";
|
|
68
|
+
}
|
|
53
69
|
async function main() {
|
|
54
|
-
|
|
70
|
+
if (node_process_1.default.env.SDD_FLOW_KIT_SKIP_POSTINSTALL === "1") {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
55
73
|
const initCwd = node_process_1.default.env.INIT_CWD ? node_path_1.default.resolve(node_process_1.default.env.INIT_CWD) : null;
|
|
56
74
|
const pkgDir = node_path_1.default.resolve(__dirname, "..");
|
|
57
75
|
const projectRoot = initCwd ?? node_process_1.default.cwd();
|
|
58
|
-
// 避免在本包自身仓库开发安装依赖时重复触发自动初始化。
|
|
59
76
|
if (projectRoot === pkgDir)
|
|
60
77
|
return;
|
|
61
|
-
const isInteractive = Boolean(node_process_1.default.stdin.isTTY && node_process_1.default.stdout.isTTY);
|
|
62
78
|
const projectKind = await inferProjectKind(projectRoot);
|
|
79
|
+
const agent = await inferAgent(projectRoot);
|
|
63
80
|
// eslint-disable-next-line no-console
|
|
64
|
-
console.log(`[sdd-flow-kit] postinstall
|
|
81
|
+
console.log(`[sdd-flow-kit] postinstall (light) at: ${projectRoot}`);
|
|
65
82
|
// eslint-disable-next-line no-console
|
|
66
|
-
console.log(`[sdd-flow-kit]
|
|
83
|
+
console.log(`[sdd-flow-kit] agent=${agent}, project=${projectKind}`);
|
|
67
84
|
await (0, setupProject_1.setupProject)({
|
|
68
85
|
projectRoot,
|
|
69
|
-
agent
|
|
70
|
-
|
|
71
|
-
|
|
86
|
+
agent,
|
|
87
|
+
yes: true,
|
|
88
|
+
light: true,
|
|
72
89
|
dryRun: false,
|
|
73
90
|
projectKind,
|
|
74
91
|
});
|
|
75
92
|
// eslint-disable-next-line no-console
|
|
76
|
-
console.log("[sdd-flow-kit] setup
|
|
93
|
+
console.log("[sdd-flow-kit] light setup done (skills/rules only). Full env: npx sdd-flow-kit install -y");
|
|
77
94
|
}
|
|
78
95
|
main().catch((err) => {
|
|
79
|
-
// 不阻断依赖安装,仅告警
|
|
80
96
|
// eslint-disable-next-line no-console
|
|
81
97
|
console.warn("[sdd-flow-kit] postinstall setup skipped:", err instanceof Error ? err.message : err);
|
|
82
98
|
});
|
|
@@ -183,6 +183,11 @@ async function installAgentSkill(projectRoot) {
|
|
|
183
183
|
await (0, fs_1.writeTextFileEnsuredDir)(target, content);
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
+
async function installSddCursorRule(projectRoot) {
|
|
187
|
+
const rulePath = node_path_1.default.join(projectRoot, ".cursor", "rules", "sdd-flow-kit-gates.mdc");
|
|
188
|
+
const template = await (0, templates_1.loadTemplateText)("rules/sdd-no-implement-until-apply.mdc.template");
|
|
189
|
+
await (0, fs_1.writeTextFileEnsuredDir)(rulePath, template);
|
|
190
|
+
}
|
|
186
191
|
function renderVars(template, vars) {
|
|
187
192
|
let out = template;
|
|
188
193
|
for (const [k, v] of Object.entries(vars)) {
|
|
@@ -263,20 +268,29 @@ async function setupProject(options) {
|
|
|
263
268
|
const plannedActions = [];
|
|
264
269
|
const branches = listLocalBranches(options.projectRoot);
|
|
265
270
|
const branchExists = branches.includes(selectedBranch);
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
:
|
|
269
|
-
|
|
271
|
+
let branchResult;
|
|
272
|
+
if (options.light) {
|
|
273
|
+
branchResult = { branch: selectedBranch, created: false };
|
|
274
|
+
plannedActions.push("light mode: skipped git branch checkout");
|
|
275
|
+
}
|
|
276
|
+
else if (options.dryRun) {
|
|
277
|
+
branchResult = { branch: selectedBranch, created: !branchExists };
|
|
270
278
|
plannedActions.push(branchExists
|
|
271
279
|
? `would checkout existing branch: ${selectedBranch}`
|
|
272
280
|
: `would create and checkout branch: ${selectedBranch}`);
|
|
273
281
|
}
|
|
282
|
+
else {
|
|
283
|
+
branchResult = ensureBranch(options.projectRoot, selectedBranch);
|
|
284
|
+
}
|
|
274
285
|
let environmentReady = await isEditorEnvironmentReady(options.projectRoot, selectedAgent);
|
|
275
286
|
let setupExecuted = false;
|
|
276
287
|
let skillInstalled = false;
|
|
277
288
|
let docsSkillInstalled = false;
|
|
278
289
|
let opsxConfigInstalled = false;
|
|
279
|
-
if (
|
|
290
|
+
if (options.light) {
|
|
291
|
+
plannedActions.push("light mode: skipped npx @lixin5257xxx/opsx-workflow setup");
|
|
292
|
+
}
|
|
293
|
+
else if (!environmentReady) {
|
|
280
294
|
const { cmd, args } = buildSetupCommand(options.projectRoot, selectedAgent);
|
|
281
295
|
if (options.dryRun) {
|
|
282
296
|
plannedActions.push(`would run: ${cmd} ${args.join(" ")}`);
|
|
@@ -304,9 +318,11 @@ async function setupProject(options) {
|
|
|
304
318
|
const { dir } = docSkillDirName(selectedKind);
|
|
305
319
|
plannedActions.push(`would install docs skill: ${node_path_1.default.join(options.projectRoot, "docs", dir)}`);
|
|
306
320
|
plannedActions.push(`would install opsx config: ${node_path_1.default.join(options.projectRoot, ".opsx", "config.json")}`);
|
|
321
|
+
plannedActions.push(`would install cursor rule: ${node_path_1.default.join(options.projectRoot, ".cursor", "rules", "sdd-flow-kit-gates.mdc")}`);
|
|
307
322
|
}
|
|
308
323
|
else {
|
|
309
324
|
await installAgentSkill(options.projectRoot);
|
|
325
|
+
await installSddCursorRule(options.projectRoot);
|
|
310
326
|
skillInstalled = true;
|
|
311
327
|
await installDocsSkill(options.projectRoot, selectedKind);
|
|
312
328
|
docsSkillInstalled = true;
|
|
@@ -325,6 +341,7 @@ async function setupProject(options) {
|
|
|
325
341
|
`skillInstalled: ${skillInstalled}`,
|
|
326
342
|
`docsSkillInstalled: ${docsSkillInstalled}`,
|
|
327
343
|
`opsxConfigInstalled: ${opsxConfigInstalled}`,
|
|
344
|
+
`light: ${Boolean(options.light)}`,
|
|
328
345
|
`dryRun: ${Boolean(options.dryRun)}`,
|
|
329
346
|
"",
|
|
330
347
|
"plannedActions:",
|
package/dist/steps/startFlow.js
CHANGED
|
@@ -70,7 +70,9 @@ async function startFlowScaffold(options) {
|
|
|
70
70
|
version: options.version,
|
|
71
71
|
runId,
|
|
72
72
|
outputRoot,
|
|
73
|
-
status: "
|
|
73
|
+
status: "awaiting_user_confirmation",
|
|
74
|
+
docModeOnly: true,
|
|
75
|
+
phase: "A_or_B",
|
|
74
76
|
createdAtISO: new Date().toISOString(),
|
|
75
77
|
}, null, 2));
|
|
76
78
|
// runDir 自述
|
|
@@ -90,6 +92,7 @@ async function startFlowScaffold(options) {
|
|
|
90
92
|
"## Step 3:人工核验(暂停点)",
|
|
91
93
|
"用户补充待确认点并确认闭环后,才进入 Step 4。",
|
|
92
94
|
"门禁:未闭环时禁止生成 01/02/04,禁止 /opsx-propose。",
|
|
95
|
+
"**重要**:用户粘贴确认点时,AI 仅更新 `openspec/PRD` 文档,**禁止**修改 `src/` 等业务代码。",
|
|
93
96
|
"",
|
|
94
97
|
"## Step 4:生成 01 / 02 / 闭环03 / 04",
|
|
95
98
|
"用户确认后产出:",
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# 03-待确认问题清单
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
| (断点/起点缺失/推测缺口) | (描述矛盾点) | (引用文件/模块) | (需要用户确认/提供信息) |
|
|
3
|
+
> **门禁**:本文件为「未闭合」时,AI **只能**改本文件,禁止生成 01/02/04,**禁止**改 `src/` 等业务代码。
|
|
4
|
+
> **给用户**:澄清完成后,在对话里**直接粘贴确认点**即可,无需加任何前缀口令。
|
|
6
5
|
|
|
6
|
+
**矛盾点池状态**:`未闭合` | `已闭合`(二选一,由 AI 维护)
|
|
7
|
+
|
|
8
|
+
| 问题类型 | 问题描述 | 代码位置 (如有) | 建议/待确认项 | 用户确认结论 |
|
|
9
|
+
|---|---|---|---|---|
|
|
10
|
+
| (断点/起点缺失/推测缺口) | (描述矛盾点) | (引用文件/模块,只读) | (需要用户确认) | (用户回复后填写) |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sdd-flow-kit-trigger
|
|
3
|
-
description:
|
|
3
|
+
description: 开发某版本需求、SDD 流程、待确认问题澄清、用户回复确认点/矛盾点结论时触发。澄清与确认阶段仅改 openspec/PRD 文档,禁止写 src 等业务代码;仅 /opsx-apply 后可实现。
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# SDD Flow Trigger Skill
|
|
@@ -13,6 +13,23 @@ description: 当用户说“开发 <产品> <版本> 需求/版本/PRD”或类
|
|
|
13
13
|
- `开发XXX-V1.2.3版本`(无空格连写)
|
|
14
14
|
- `开发 XXX PRD`
|
|
15
15
|
- 或明确要求“按 SDD 流程”推进某版本需求
|
|
16
|
+
- **用户回复待确认点 / 粘贴确认结论 / 说「按上面确认继续」**(即使未再说「开发 XX 需求」也视为 SDD 流程续跑)
|
|
17
|
+
|
|
18
|
+
## ⚠️ 最高优先级:文档模式 vs 实现模式
|
|
19
|
+
|
|
20
|
+
| 模式 | 何时 | 允许改动的路径 | 禁止 |
|
|
21
|
+
|------|------|----------------|------|
|
|
22
|
+
| **文档模式** | 阶段 A/B/C,含「用户发来确认点」 | 仅 `openspec/PRD/**`(及阶段 C 的 `openspec/changes/**`) | 任何 `src/`、`pages/`、`components/` 等业务代码 |
|
|
23
|
+
| **实现模式** | 仅阶段 D,且用户同意 `/opsx-apply` | 按 openspec change 与 pipeline 要求 | 跳过 propose |
|
|
24
|
+
|
|
25
|
+
**常见错误**:用户粘贴确认点后,你一边更新 `03` 一边改 `.tsx` —— **绝对禁止**。确认回复 = 只做文档,同一回合不得 touch 业务代码。
|
|
26
|
+
|
|
27
|
+
### 用户侧:零口令(不要要求加前缀)
|
|
28
|
+
- 用户**直接粘贴**确认点、编号结论、「按 1/2/3 继续」即可;**禁止**要求用户输入【仅文档模式】等固定话术。
|
|
29
|
+
- 你须在收到后**自动**判定为阶段 B 的文档模式;先读 `openspec/PRD/<runId>/.session-state.json`(`docModeOnly: true` 时严禁写业务代码)与 `03-待确认问题清单.md`。
|
|
30
|
+
- 阶段切换口语即可,无需背提示词:
|
|
31
|
+
- 提案:`继续` / `做提案` / `propose`(执行 `/opsx-propose`)
|
|
32
|
+
- 实现:`开始 apply` / `执行 apply`(且 change 已 apply-ready)
|
|
16
33
|
|
|
17
34
|
## 触发后执行规则(分阶段,禁止跳步)
|
|
18
35
|
|
|
@@ -39,6 +56,13 @@ description: 当用户说“开发 <产品> <版本> 需求/版本/PRD”或类
|
|
|
39
56
|
### 阶段 B — 用户确认后(仅文档 01/02/03/04)
|
|
40
57
|
**触发条件**:用户已回复待确认点,或明确表示“矛盾点池已闭合 / 按确认点继续”。
|
|
41
58
|
|
|
59
|
+
**「用户发来确认点」专用指令(本回合严格执行)**
|
|
60
|
+
1. 先读 `openspec/PRD/<runId>/03-待确认问题清单.md`,把用户消息逐条写入「用户确认结论」列。
|
|
61
|
+
2. 将状态改为 **矛盾点池状态:已闭合**。
|
|
62
|
+
3. 再生成 `01`、`02`、`04`(路径均在 `openspec/PRD/<runId>/`)。
|
|
63
|
+
4. **本回合禁止**:`StrReplace`/`Write` 任何业务源码;禁止「顺手实现一版」。
|
|
64
|
+
5. 结束语简短即可(例:「已更新 01/02/03/04,未改业务代码。有 UI 参考请发路径,或回复继续做提案。」)——**不要**要求用户背固定口令。
|
|
65
|
+
|
|
42
66
|
**本阶段只允许产出:**
|
|
43
67
|
1. 更新 `03-待确认问题清单.md`(标注 **矛盾点池状态:已闭合**,写入用户确认结论)
|
|
44
68
|
2. 生成最终版 `01-需求分析报告.md`
|
|
@@ -46,10 +70,11 @@ description: 当用户说“开发 <产品> <版本> 需求/版本/PRD”或类
|
|
|
46
70
|
4. 生成 `04-技术文档草稿.md`
|
|
47
71
|
|
|
48
72
|
**本阶段禁止:**
|
|
73
|
+
- 修改 `src/`、`pages/`、`components/`、`api/` 等实现代码(`02-改动点清单` 只是**计划**,不是实施许可)
|
|
49
74
|
- 执行 `/opsx-propose` 或 `/opsx-apply`
|
|
50
75
|
- 生成 openspec change 目录或宣称“开发完成”
|
|
51
76
|
|
|
52
|
-
完成后告知用户:“01/02/03/04
|
|
77
|
+
完成后告知用户:“01/02/03/04 已就绪。发 UI 参考路径,或回复「继续」我将执行 /opsx-propose。”
|
|
53
78
|
|
|
54
79
|
---
|
|
55
80
|
|
|
@@ -83,7 +108,9 @@ description: 当用户说“开发 <产品> <版本> 需求/版本/PRD”或类
|
|
|
83
108
|
---
|
|
84
109
|
|
|
85
110
|
## 严禁(全局)
|
|
111
|
+
- 澄清/确认阶段写业务代码(最常见违规)
|
|
86
112
|
- 未闭合时一次性生成 `01~05` 或直接进入提案/实现
|
|
113
|
+
- 把 `02-改动点清单.md` 当作可以立刻改文件的指令
|
|
87
114
|
- 跳过用户确认点
|
|
88
115
|
- 在错误仓库执行 OPSX(如 fallback 到其它项目的 poquan-web 路径)
|
|
89
116
|
|
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
你现在的角色是【前端架构分析专家】与【资深业务分析师】。
|
|
3
3
|
你正在执行 **SDD (Software Design Description) 模式**。这是一个基于“循环探索”的工程环节,目的是在编码前,基于 PRD 和现有知识库,产出完备的需求分析与改动清单。
|
|
4
4
|
|
|
5
|
+
### ⛔ 实现禁令(全文最高优先级)
|
|
6
|
+
- **文档模式**:只允许创建/修改 `openspec/PRD/<runId>/` 下的 `.md` 文件。
|
|
7
|
+
- **禁止**在本环节修改任何业务源码(`src/`、`pages/`、`components/`、`api/` 等),即使用户发来「确认点」也不行。
|
|
8
|
+
- `02-改动点清单.md` 是**改动计划表**,不是实施指令;写代码只能发生在 `/opsx-apply` 之后。
|
|
9
|
+
- 用户回复确认结论时:**仅**更新 `03` → 生成 `01/02`(及后续 `04`),并在回复中声明「未写业务代码」。
|
|
10
|
+
|
|
5
11
|
### 🔄 循环工作流 (Loop Protocol)
|
|
6
12
|
请严格遵守以下循环逻辑,直到满足“循环结束条件”:
|
|
7
13
|
1. **输入**:接收 PRD 文档 和 `openspec/` 目录下的现有知识库。
|
|
@@ -65,22 +71,23 @@
|
|
|
65
71
|
> **触发条件**:当你发现 PRD 与现有代码库不一致,或代码逻辑存在盲区时。
|
|
66
72
|
|
|
67
73
|
**任务**:
|
|
68
|
-
1.
|
|
74
|
+
1. **不要强行编写解决方案,不要改任何 `.tsx/.ts/.vue` 文件。**
|
|
69
75
|
2. 列出所有 **断点**、**起点缺失** 和 **推测缺口**。
|
|
70
76
|
3. 输出 `03-待确认问题清单.md`,并暂停生成最终报告,等待人工输入。
|
|
71
77
|
4. 明确标注:`矛盾点池状态:未闭合`。
|
|
78
|
+
5. 结束语(告诉用户可直接回复,无需口令):`请直接在对话里粘贴你的确认点(编号列表即可),我会只更新 openspec/PRD 文档,不会改业务代码。`
|
|
72
79
|
|
|
73
80
|
---
|
|
74
81
|
|
|
75
82
|
#### 路径 B:交付模式 (矛盾点池已闭合)
|
|
76
83
|
> **触发条件**:用户已回复待确认点,或明确表示矛盾点池已闭合(不得在未获用户确认时自行进入)。
|
|
77
84
|
|
|
78
|
-
**任务(本路径仅文档,不含 openspec
|
|
85
|
+
**任务(本路径仅文档,不含 openspec,不含写代码)**:
|
|
79
86
|
1. 更新 `03-待确认问题清单.md`,标注“**矛盾点池状态:已闭合**”,写入用户确认结论。
|
|
80
|
-
2. 生成最终版 `01-需求分析报告.md` 和 `02-改动点清单.md
|
|
87
|
+
2. 生成最终版 `01-需求分析报告.md` 和 `02-改动点清单.md`(清单中的路径是**计划**,不得在本回合修改这些文件)。
|
|
81
88
|
3. 确认 `02-改动点清单.md` 中仅包含代码文件改动,不涉及 `openspec/spec/` 内容。
|
|
82
|
-
4. **禁止**
|
|
83
|
-
5.
|
|
89
|
+
4. **禁止** 修改 `src/` 等业务代码;**禁止** `/opsx-propose` 或 `/opsx-apply`。
|
|
90
|
+
5. 输出时附带:`01/02/03/04 已更新,未改业务代码。需要提案时回复「继续」或提供 UI 参考路径。`
|
|
84
91
|
|
|
85
92
|
---
|
|
86
93
|
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: SDD 门禁:存在 openspec/PRD 待确认或用户回复澄清结论时自动文档模式,禁止改业务代码;仅 /opsx-apply 后可实现
|
|
3
|
+
alwaysApply: true
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# SDD 流程:禁止提前写代码
|
|
7
|
+
|
|
8
|
+
## 自动进入「文档模式」(用户无需加任何前缀)
|
|
9
|
+
|
|
10
|
+
**不要要求用户粘贴【仅文档模式】等口令。** 满足以下任一条件时,你必须默认文档模式,即使用户只发了编号列表或「确认了」:
|
|
11
|
+
|
|
12
|
+
1. 仓库存在 `openspec/PRD/*/03-待确认问题清单.md`,且其中 **矛盾点池状态:未闭合**(或用户本条消息明显是在回答其中的待确认项)。
|
|
13
|
+
2. 上一轮你刚输出过待确认问题 / 请用户确认 / 矛盾点池未闭合。
|
|
14
|
+
3. 用户消息为:编号结论、选用方案、是/否、补充业务规则、粘贴 PRD 片段说明——且当前对话上下文在 SDD/`openspec/PRD` 需求流程中。
|
|
15
|
+
4. `openspec/PRD/*/.session-state.json` 中 `docModeOnly` 为 `true`(若存在则必读)。
|
|
16
|
+
|
|
17
|
+
**识别到上述情况后**:在本回合**内部**执行文档模式,不要要求用户改说法。
|
|
18
|
+
|
|
19
|
+
当用户处于 **需求澄清 / 待确认回复 / 矛盾点确认** 时,你必须遵守:
|
|
20
|
+
|
|
21
|
+
## 本回合只允许(文档模式)
|
|
22
|
+
- 读写 `openspec/PRD/**` 下的 markdown(`01`~`05`、`source/`、`RUNME.md`)
|
|
23
|
+
- 只读扫描 `src/`、`pages/`、`components/` 等用于分析,**不得修改**
|
|
24
|
+
|
|
25
|
+
## 本回合严禁
|
|
26
|
+
- 修改或新建任何业务实现代码:`src/**`、`app/**`、`pages/**`、`components/**`、`api/**`、`store/**`、`hooks/**` 等
|
|
27
|
+
- 运行会改动业务代码的 refactor / fix / feature 实现
|
|
28
|
+
- 在未执行 `/opsx-propose` 前创建 `openspec/changes/**`(除非用户明确要求进入提案阶段)
|
|
29
|
+
- 在用户未明确同意前执行 `/opsx-apply`
|
|
30
|
+
|
|
31
|
+
## 用户直接粘贴确认点(最常见误触,勿要求用户加前缀)
|
|
32
|
+
1. 定位最新或对话相关的 `openspec/PRD/<runId>/`(读 `RUNME.md` 或 `.session-state.json`)。
|
|
33
|
+
2. **仅**更新 `03`(写入用户结论,标为已闭合)。
|
|
34
|
+
3. 再生成/更新 `01`、`02`、`04`。
|
|
35
|
+
4. 回复简短说明文档已更新即可;**不要**在同一回合改 `.tsx/.ts/.vue`。
|
|
36
|
+
5. 主动问一句是否需要 UI 参考路径;用户说「继续/可以/做提案」即进入 `/opsx-propose`(仍不写业务代码)。
|
|
37
|
+
|
|
38
|
+
## 唯一允许写业务代码的时机
|
|
39
|
+
- 用户已走完:`/opsx-propose` → openspec change 已 apply-ready → 用户明确同意 **`/opsx-apply`**(如「开始 apply」「执行 apply」)。
|
|
40
|
+
|
|
41
|
+
若用户只说「确认了」「按上面来」但未进入 apply 阶段,**仍禁止**写业务代码。
|