ai-spec-tool 0.1.2 → 0.1.3
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 +8 -1
- package/assets/.agents/skills/bugfix/SKILL.md +33 -17
- package/assets/.agents/skills/plan/SKILL.md +39 -319
- package/assets/.agents/skills/plan/assets/templates/plan.md +47 -0
- package/assets/.agents/skills/plan-executor/SKILL.md +88 -305
- package/assets/.agents/skills/plan-executor/assets/templates/module-plan.md +26 -0
- package/assets/.agents/skills/plan-executor/assets/templates/project-plan.md +24 -0
- package/assets/.agents/skills/plan-executor/assets/templates/summary-module.md +17 -0
- package/assets/.agents/skills/plan-executor/assets/templates/summary-plan.md +18 -0
- package/assets/.agents/skills/plan-executor/assets/templates/summary-project.md +16 -0
- package/assets/.agents/skills/rules-creator/SKILL.md +25 -5
- package/assets/.agents/skills/rules-creator/assets/architecture-gen.md +59 -210
- package/assets/.agents/skills/rules-creator/assets/conventions-gen.md +85 -0
- package/assets/.agents/skills/rules-creator/assets/glossary-gen.md +46 -0
- package/assets/.agents/skills/rules-creator/assets/interface-gen.md +62 -0
- package/assets/.agents/skills/rules-creator/assets/ui-architecture-gen.md +35 -286
- package/assets/.agents/skills/rules-creator/assets/ui-template-gen.md +24 -114
- package/assets/.agents/skills/spec-executor/SKILL.md +53 -109
- package/assets/AGENTS.md +14 -30
- package/assets/docs/_shared/adr/README.md +4 -0
- package/assets/docs/_shared/conventions.md +37 -0
- package/assets/docs/_shared/glossary.md +4 -0
- package/assets/docs/architecture/README.md +6 -0
- package/assets/docs/plan/README.md +11 -0
- package/assets/docs/plan/index.yaml +2 -0
- package/assets/docs/plan/summary.md +2 -0
- package/assets/docs/requirements/README.md +5 -0
- package/assets/docs/requirements/index.yaml +2 -0
- package/assets/docs/specs/README.md +6 -0
- package/bin/ai-spec-tool.js +60 -10
- package/package.json +1 -1
- package/assets/.agents/skills/rules-creator/assets/naming-rule-gen.md +0 -77
- package/assets/.agents/skills/rules-creator/assets/vision-gen.md +0 -613
|
@@ -1,122 +1,66 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: spec-executor
|
|
3
|
-
description:
|
|
3
|
+
description: 执行 processing 状态的 plan,按 module-plan 修改代码并更新 module-spec
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
7
|
-
|
|
8
|
-
##
|
|
9
|
-
- docs/
|
|
10
|
-
- docs/
|
|
11
|
-
- docs/
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
-
|
|
15
|
-
-
|
|
16
|
-
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
1
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
3. 若存在多个:
|
|
36
|
-
- **优先使用文件名 index**(如 `001-xxx.processing.md`)判断最老 → 取最小 index
|
|
37
|
-
- 若无 index 可用,则以文件修改时间最早者为准
|
|
6
|
+
# 前置依赖检查(统一规则)
|
|
7
|
+
|
|
8
|
+
## 依赖清单(必须存在且非占位)
|
|
9
|
+
- `docs/plan/*/plan.processing.md`
|
|
10
|
+
- `docs/_shared/conventions.md`
|
|
11
|
+
- `docs/_shared/glossary.md`
|
|
12
|
+
- 若 plan 含 `source_interface`:必须读取 `docs/requirements/<spec-id>.md`
|
|
13
|
+
- `docs/architecture/<project>/architecture.md`
|
|
14
|
+
- `docs/architecture/<project>/layer_rules.yaml`
|
|
15
|
+
- `docs/plan/<plan-id>/projects/<project>/project-plan.md`
|
|
16
|
+
- `docs/plan/<plan-id>/projects/<project>/modules/<module>-plan.md`
|
|
17
|
+
- 若 module 为 UI Component,需额外存在:
|
|
18
|
+
- `docs/specs/<project>/components/<module>-rules.md`
|
|
19
|
+
- `docs/architecture/<project>/ui/design-tokens.md`
|
|
20
|
+
- `docs/architecture/<project>/ui/layout-and-responsive.md`
|
|
21
|
+
- `docs/architecture/<project>/ui/patterns.md`
|
|
22
|
+
|
|
23
|
+
## 缺失判定
|
|
24
|
+
文件不存在 / 内容为空 / 首行含 `AI-SPEC-TOOL:PLACEHOLDER`
|
|
25
|
+
|
|
26
|
+
## 缺失时唯一输出
|
|
27
|
+
<<<
|
|
28
|
+
缺少依赖[<path>]
|
|
29
|
+
|
|
30
|
+
【下一步】请选择一项:
|
|
31
|
+
1. 开始创建依赖
|
|
32
|
+
请回复:1
|
|
33
|
+
>>>
|
|
34
|
+
用户回复 `1` 后切换 `rules-creator` 生成缺失文件。
|
|
38
35
|
|
|
39
36
|
---
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
-
|
|
45
|
-
- `modules[]`(知道涉及哪些 module / type)
|
|
46
|
-
- `execution_steps`(执行顺序)
|
|
47
|
-
|
|
48
|
-
**硬规则:**
|
|
49
|
-
- `execution_steps` 必须为有序列表(1. 2. 3.)
|
|
50
|
-
- **每一步只能提到一个 module**
|
|
51
|
-
- `execution_steps` 必须覆盖 plan 中所有 `modules[]`
|
|
52
|
-
- 若任一规则不满足:**停止并要求补齐 plan**
|
|
38
|
+
# 1) 选择要执行的 plan(强制,流程[1/3])
|
|
39
|
+
- 优先读取 `docs/plan/index.yaml` 取得 processing plan
|
|
40
|
+
- 若 index 缺失或未记录 processing plan:再扫描 `docs/plan/*/plan.processing.md`
|
|
41
|
+
- 若不存在:输出 `未发现可执行的 plan(plan.processing.md)`
|
|
53
42
|
|
|
54
43
|
---
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
- `
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
45
|
+
# 2) 执行步骤(强制,流程[2/3])
|
|
46
|
+
对 `execution_steps` 的每个 `<project>/<module>`:
|
|
47
|
+
1. 将 `<module>-plan.md` → `<module>-plan.processing.md`
|
|
48
|
+
2. 读取对应 `module-plan`
|
|
49
|
+
3. 按约束修改代码
|
|
50
|
+
4. 更新/生成 `docs/specs/<project>/<module>-spec.md`
|
|
51
|
+
- 必须写入 `last_updated_plan: <plan-id>`
|
|
52
|
+
- 必须写入 `source_interface: <path>`
|
|
53
|
+
5. 若 module 为 UI Component:
|
|
54
|
+
- 必须确认 module-plan 内有 UI 规范引用
|
|
55
|
+
- 必要时更新 `<module>-rules.md`
|
|
56
|
+
6. 将 `<module>-plan.processing.md` → `<module>-plan.done.md`
|
|
57
|
+
|
|
58
|
+
完成所有模块后:
|
|
59
|
+
- 将 `plan.processing.md` → `plan.done.md`
|
|
69
60
|
|
|
70
61
|
---
|
|
71
62
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
1. 阅读该 module 的 `.update.md` spec(只用于理解职责与边界)
|
|
77
|
-
2. 根据 plan 的 intent + rules + flows + spec 要求修改代码
|
|
78
|
-
- **必须遵守 docs/global/architecture.md 的依赖规则与目录落点**
|
|
79
|
-
- **不得违背 spec 的「不做什么 / 禁止依赖 / 禁止扩充方向」**
|
|
80
|
-
3. 若当前模块属于 UI 显示组件类型(见 `docs/global/ui/module-ui-types.md`):
|
|
81
|
-
- 执行前必须读取对应的 Component Rules
|
|
82
|
-
- 必须遵守 `docs/global/ui/design-tokens.md`、`layout-and-responsive.md`、`patterns.md` 的约束
|
|
83
|
-
- 若缺失任一 UI 规范文件:**停止并要求补齐**
|
|
84
|
-
- 若存在 `docs/global/ui/accessibility.md`:**应遵守其约束**(可选)
|
|
85
|
-
- **必须逐条对照 `docs/global/ui/patterns.md` 的「交互模式」并落实到实现**
|
|
86
|
-
- 若 Component Rules 未覆盖或与 patterns 冲突:**停止并要求先补齐 Component Rules / patterns**
|
|
87
|
-
4. 每完成一个 module 的代码改动:
|
|
88
|
-
- 将该 module spec 文件从
|
|
89
|
-
`<module-name>.update.md` → `<module-name>.md`
|
|
90
|
-
|
|
91
|
-
> 说明:如果模块不存在,需要创建其对应目录与基础结构;若已存在,只修改必要部分。
|
|
92
|
-
|
|
93
|
-
---
|
|
94
|
-
|
|
95
|
-
## 5) 完成收尾(强制)
|
|
96
|
-
|
|
97
|
-
当所有 module 都完成并已改名为 `.md`:
|
|
98
|
-
- 将 plan 文件从
|
|
99
|
-
`<plan>.processing.md` → `<plan>.done.md`
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## 6) 对话输出(唯一允许的文字输出)
|
|
104
|
-
|
|
105
|
-
完成后,只允许输出以下结构:
|
|
106
|
-
|
|
107
|
-
> 已完成 Plan 执行:
|
|
108
|
-
> `<plan文件名>`(需为可点击超链接)
|
|
109
|
-
>
|
|
110
|
-
> 已完成 Module:
|
|
111
|
-
> 1.`<module spec 文件名>`
|
|
112
|
-
> 2.`<module spec 文件名>`
|
|
113
|
-
> 3.`<module spec 文件名>`
|
|
114
|
-
|
|
115
|
-
---
|
|
116
|
-
|
|
117
|
-
## 7) 失败时的输出(强制)
|
|
118
|
-
|
|
119
|
-
若因缺失文件或规则不满足而停止,只允许输出:
|
|
120
|
-
|
|
121
|
-
> 无法执行:<原因>
|
|
122
|
-
> 请修正后再执行。
|
|
63
|
+
# 3) 对话输出(唯一允许的文字输出,流程[3/3])
|
|
64
|
+
- 输出已完成的 plan 路径
|
|
65
|
+
- 输出已完成的 module spec 路径
|
|
66
|
+
- 提示下一步选项:进入 plan
|
package/assets/AGENTS.md
CHANGED
|
@@ -1,30 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
-
|
|
14
|
-
|
|
15
|
-
→ 使用 skill: rules-creator
|
|
16
|
-
|
|
17
|
-
- 异常修复(bugfix)
|
|
18
|
-
用户提供报错信息或描述异常行为
|
|
19
|
-
→ 使用 skill: bugfix
|
|
20
|
-
|
|
21
|
-
- 功能增修(update)
|
|
22
|
-
用户希望修改或新增功能
|
|
23
|
-
- 若该功能不需要建立一个目前不存在的系统 → 直接修改代码与对应 spec
|
|
24
|
-
- 若该功能需要建立一个新的系统/修改已有系统就可以 → 使用 skill: plan
|
|
25
|
-
|
|
26
|
-
- 系统规划(plan)
|
|
27
|
-
用户明确需要一个新的系统、模块或功能体系
|
|
28
|
-
→ 使用 skill: plan
|
|
29
|
-
|
|
30
|
-
若意图并非以上,直接回答用户即可
|
|
1
|
+
先判断需求类型,再选择对应 skill(精简路由):
|
|
2
|
+
|
|
3
|
+
- 执行 Plan:
|
|
4
|
+
- 有 `docs/plan/<plan-id>/plan.processing.md` → `spec-executor`
|
|
5
|
+
- 有 `docs/plan/<plan-id>/plan.done.md` → 回复“此 plan 已完成”
|
|
6
|
+
- 有 `docs/plan/<plan-id>/plan.md` → `plan-executor`
|
|
7
|
+
- 生成/补齐规则文件 → `rules-creator`
|
|
8
|
+
- 异常修复 → `bugfix`
|
|
9
|
+
- **进入 plan 模式的严格条件**:
|
|
10
|
+
- 只有当用户明确说“要 plan/规划/制定计划/产出 Plan”才进入 `plan`
|
|
11
|
+
- 用户仅说“要新功能/需求/改动”时,先讨论澄清,不自动进入 `plan`
|
|
12
|
+
- 若功能与接口讨论已清晰无疑虑,再**提议**用户是否需要进入 `plan`
|
|
13
|
+
- 若已完成接口/DB 规格讨论,可先生成 Interface 规格书(rules-creator → interface)
|
|
14
|
+
- 其他 → 直接回答
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
<!-- AI-SPEC-TOOL:PLACEHOLDER -->
|
|
2
|
+
# 通用规范(Conventions)
|
|
3
|
+
|
|
4
|
+
(由 rules-creator 生成)
|
|
5
|
+
|
|
6
|
+
## 计划执行流程
|
|
7
|
+
- 生成多个 `project-plan.md` 后:先给出每个 project 的简短摘要,询问是否修改,确认后继续。
|
|
8
|
+
- 生成多个 `<module>-plan.md` 后:先给出每个 module 的简短摘要,询问是否修改,确认后才可进入 spec-executor。
|
|
9
|
+
- 所有多题澄清必须标注进度:`问题[当前/总数]`。
|
|
10
|
+
- 所有关键流程阶段必须标注进度:`流程[当前/总数]`。
|
|
11
|
+
- 优先使用 `docs/plan/index.yaml` 作为计划索引;若不存在再扫描目录。
|
|
12
|
+
- 生成 plan / project-plan / module-plan 后应产出对应 `summary.md` 以降低后续读取成本。
|
|
13
|
+
- summary 文件路径建议:
|
|
14
|
+
- `docs/plan/<plan-id>/summary.md`
|
|
15
|
+
- `docs/plan/<plan-id>/projects/<project>/summary.md`
|
|
16
|
+
- `docs/plan/<plan-id>/projects/<project>/modules/<module>.summary.md`
|
|
17
|
+
- summary 模板参考:
|
|
18
|
+
- `assets/templates/summary-plan.md`
|
|
19
|
+
- `assets/templates/summary-project.md`
|
|
20
|
+
- `assets/templates/summary-module.md`
|
|
21
|
+
- 若存在 Interface 规格书:
|
|
22
|
+
- 其路径必须写入 `plan.md / project-plan.md / module-plan.md`
|
|
23
|
+
- 最终写入每个 `module-spec.md` 的 frontmatter
|
|
24
|
+
|
|
25
|
+
## Interface 规格书
|
|
26
|
+
- 位置:`docs/requirements/<spec-id>.md`
|
|
27
|
+
- 索引:`docs/requirements/index.yaml`
|
|
28
|
+
- 命名:`001-支付流程` 形式
|
|
29
|
+
|
|
30
|
+
## 规格书优先规则
|
|
31
|
+
- 当接口与 DB 细节讨论已清晰,可先生成 Interface 规格书,再进入 plan。
|
|
32
|
+
|
|
33
|
+
### 进度标识示例
|
|
34
|
+
- `问题[1/4] 这次变更的目标是什么?`
|
|
35
|
+
- `问题[2/4] 这次的成功标准有哪些?`
|
|
36
|
+
- `流程[1/3] 读取 plan 并建立执行清单`
|
|
37
|
+
- `流程[2/3] 生成 project-plan 与 module-plan`
|
package/bin/ai-spec-tool.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
const fs = require("fs");
|
|
4
4
|
const path = require("path");
|
|
5
|
+
const readline = require("readline");
|
|
5
6
|
|
|
6
7
|
const ASSET_ROOT = path.resolve(__dirname, "..", "assets");
|
|
7
8
|
const TEMPLATE_AGENTS = path.join(ASSET_ROOT, "AGENTS.md");
|
|
8
9
|
const TEMPLATE_AGENTS_DIR = path.join(ASSET_ROOT, ".agents");
|
|
10
|
+
const TEMPLATE_DOCS_DIR = path.join(ASSET_ROOT, "docs");
|
|
9
11
|
|
|
10
12
|
const START = "<!-- AI-SPEC-TOOL:START -->";
|
|
11
13
|
const END = "<!-- AI-SPEC-TOOL:END -->";
|
|
@@ -32,7 +34,7 @@ function nextIncomingPath(destPath) {
|
|
|
32
34
|
return `${candidate}.${i}`;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
|
-
function copyFileSafe(srcPath, destPath, report) {
|
|
37
|
+
function copyFileSafe(srcPath, destPath, report, options) {
|
|
36
38
|
if (!fs.existsSync(destPath)) {
|
|
37
39
|
ensureDir(path.dirname(destPath));
|
|
38
40
|
fs.copyFileSync(srcPath, destPath);
|
|
@@ -43,12 +45,17 @@ function copyFileSafe(srcPath, destPath, report) {
|
|
|
43
45
|
report.skipped.push(destPath);
|
|
44
46
|
return;
|
|
45
47
|
}
|
|
48
|
+
if (options.force) {
|
|
49
|
+
fs.copyFileSync(srcPath, destPath);
|
|
50
|
+
report.updated.push(destPath);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
46
53
|
const incoming = nextIncomingPath(destPath);
|
|
47
54
|
fs.copyFileSync(srcPath, incoming);
|
|
48
55
|
report.conflicts.push({ target: destPath, incoming });
|
|
49
56
|
}
|
|
50
57
|
|
|
51
|
-
function copyDirSafe(srcDir, destDir, report) {
|
|
58
|
+
function copyDirSafe(srcDir, destDir, report, options) {
|
|
52
59
|
ensureDir(destDir);
|
|
53
60
|
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
54
61
|
entries.forEach((entry) => {
|
|
@@ -56,15 +63,42 @@ function copyDirSafe(srcDir, destDir, report) {
|
|
|
56
63
|
const src = path.join(srcDir, entry.name);
|
|
57
64
|
const dest = path.join(destDir, entry.name);
|
|
58
65
|
if (entry.isDirectory()) {
|
|
59
|
-
copyDirSafe(src, dest, report);
|
|
66
|
+
copyDirSafe(src, dest, report, options);
|
|
60
67
|
return;
|
|
61
68
|
}
|
|
62
69
|
if (entry.isFile()) {
|
|
63
|
-
copyFileSafe(src, dest, report);
|
|
70
|
+
copyFileSafe(src, dest, report, options);
|
|
64
71
|
}
|
|
65
72
|
});
|
|
66
73
|
}
|
|
67
74
|
|
|
75
|
+
function askYesNo(prompt) {
|
|
76
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
77
|
+
return new Promise((resolve) => {
|
|
78
|
+
rl.question(prompt, (answer) => {
|
|
79
|
+
rl.close();
|
|
80
|
+
const normalized = String(answer || "").trim().toLowerCase();
|
|
81
|
+
resolve(normalized === "y" || normalized === "yes");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
async function resolveConflictsInteractively(report, options) {
|
|
87
|
+
if (!report.conflicts.length || !options.ask) return;
|
|
88
|
+
if (!process.stdin.isTTY) return;
|
|
89
|
+
|
|
90
|
+
for (const conflict of report.conflicts) {
|
|
91
|
+
const prompt = `Overwrite ${conflict.target} with incoming? (y/N) `;
|
|
92
|
+
const yes = await askYesNo(prompt);
|
|
93
|
+
if (yes) {
|
|
94
|
+
fs.copyFileSync(conflict.incoming, conflict.target);
|
|
95
|
+
report.updated.push(conflict.target);
|
|
96
|
+
report.conflictsResolved.push(conflict.target);
|
|
97
|
+
fs.unlinkSync(conflict.incoming);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
68
102
|
function updateAgentsMd(targetPath, report) {
|
|
69
103
|
const template = readFile(TEMPLATE_AGENTS).trimEnd();
|
|
70
104
|
const block = `${START}\n${template}\n${END}\n`;
|
|
@@ -99,7 +133,7 @@ function updateAgentsMd(targetPath, report) {
|
|
|
99
133
|
report.updated.push(targetPath);
|
|
100
134
|
}
|
|
101
135
|
|
|
102
|
-
function init() {
|
|
136
|
+
async function init(options) {
|
|
103
137
|
const cwd = process.cwd();
|
|
104
138
|
const targetAgents = path.join(cwd, "AGENTS.md");
|
|
105
139
|
const targetAgentsDir = path.join(cwd, ".agents");
|
|
@@ -108,7 +142,8 @@ function init() {
|
|
|
108
142
|
added: [],
|
|
109
143
|
updated: [],
|
|
110
144
|
skipped: [],
|
|
111
|
-
conflicts: []
|
|
145
|
+
conflicts: [],
|
|
146
|
+
conflictsResolved: []
|
|
112
147
|
};
|
|
113
148
|
|
|
114
149
|
if (!fs.existsSync(TEMPLATE_AGENTS) || !fs.existsSync(TEMPLATE_AGENTS_DIR)) {
|
|
@@ -116,14 +151,22 @@ function init() {
|
|
|
116
151
|
process.exit(1);
|
|
117
152
|
}
|
|
118
153
|
|
|
119
|
-
copyDirSafe(TEMPLATE_AGENTS_DIR, targetAgentsDir, report);
|
|
154
|
+
copyDirSafe(TEMPLATE_AGENTS_DIR, targetAgentsDir, report, options);
|
|
155
|
+
if (fs.existsSync(TEMPLATE_DOCS_DIR)) {
|
|
156
|
+
const targetDocsDir = path.join(cwd, "docs");
|
|
157
|
+
copyDirSafe(TEMPLATE_DOCS_DIR, targetDocsDir, report, options);
|
|
158
|
+
}
|
|
120
159
|
updateAgentsMd(targetAgents, report);
|
|
160
|
+
await resolveConflictsInteractively(report, options);
|
|
121
161
|
|
|
122
162
|
console.log("ai-spec-tool init complete.");
|
|
123
163
|
console.log(`Added: ${report.added.length}`);
|
|
124
164
|
console.log(`Updated: ${report.updated.length}`);
|
|
125
165
|
console.log(`Skipped: ${report.skipped.length}`);
|
|
126
166
|
console.log(`Conflicts: ${report.conflicts.length}`);
|
|
167
|
+
if (report.conflictsResolved.length) {
|
|
168
|
+
console.log(`Resolved: ${report.conflictsResolved.length}`);
|
|
169
|
+
}
|
|
127
170
|
|
|
128
171
|
if (report.conflicts.length) {
|
|
129
172
|
console.log("\nConflicts (new versions saved as .incoming):");
|
|
@@ -134,13 +177,20 @@ function init() {
|
|
|
134
177
|
}
|
|
135
178
|
|
|
136
179
|
function main() {
|
|
137
|
-
const [command] = process.argv.slice(2);
|
|
180
|
+
const [command, ...args] = process.argv.slice(2);
|
|
181
|
+
const options = {
|
|
182
|
+
force: args.includes("--force"),
|
|
183
|
+
ask: args.includes("--ask")
|
|
184
|
+
};
|
|
138
185
|
if (!command || command === "help" || command === "--help" || command === "-h") {
|
|
139
|
-
console.log("ai-spec-tool\n\nUsage:\n ai-spec-tool init\n");
|
|
186
|
+
console.log("ai-spec-tool\n\nUsage:\n ai-spec-tool init [--force|--ask]\n");
|
|
140
187
|
return;
|
|
141
188
|
}
|
|
142
189
|
if (command === "init") {
|
|
143
|
-
init()
|
|
190
|
+
init(options).catch((err) => {
|
|
191
|
+
console.error(err?.message || err);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
});
|
|
144
194
|
return;
|
|
145
195
|
}
|
|
146
196
|
console.error(`Unknown command: ${command}`);
|
package/package.json
CHANGED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
# Naming Rule File Generator (Spec)
|
|
2
|
-
|
|
3
|
-
## 0) 生成目标(不可变,不询问用户)
|
|
4
|
-
- 输出文件:./docs/global/naming-rule.md
|
|
5
|
-
- 输出格式:Markdown
|
|
6
|
-
- 语言:中文为主
|
|
7
|
-
|
|
8
|
-
---
|
|
9
|
-
|
|
10
|
-
## 1) 交互入口(优先确认默认方案)
|
|
11
|
-
|
|
12
|
-
### 1.0 默认方案确认(必须最先执行)
|
|
13
|
-
|
|
14
|
-
在开始任何详细询问前,**先询问用户一句话**:
|
|
15
|
-
|
|
16
|
-
> 现在开始创建命名规范\n是否使用默认方案?
|
|
17
|
-
|
|
18
|
-
并同时简要展示默认方案内容:
|
|
19
|
-
|
|
20
|
-
- 文件 / 目录:kebab-case
|
|
21
|
-
- 变量 / 函数:camelCase
|
|
22
|
-
- 类 / 构造类型:PascalCase
|
|
23
|
-
- 缩写策略:允许常见缩写(API / URL / DB / ID)
|
|
24
|
-
|
|
25
|
-
回答「Y」或「N」
|
|
26
|
-
|
|
27
|
-
#### 用户响应处理规则
|
|
28
|
-
- 若用户回答「Y/y/是 / 使用默认 / OK」:
|
|
29
|
-
- 直接使用默认推荐值
|
|
30
|
-
- 跳过所有后续询问
|
|
31
|
-
- 进入生成流程(第 3 节)
|
|
32
|
-
- 若用户回答「N/n/否 / 自定义 / 调整」:
|
|
33
|
-
- 进入第 1.1 节,逐项询问
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 1.1 必问项(仅在用户拒绝默认方案时执行)
|
|
38
|
-
|
|
39
|
-
请依次询问以下问题,用户只需回复选项编号或关键字:
|
|
40
|
-
|
|
41
|
-
**Q1. 文件 / 目录命名风格**
|
|
42
|
-
- A) kebab-case(推荐)
|
|
43
|
-
- B) snake_case
|
|
44
|
-
- C) camelCase(不推荐)
|
|
45
|
-
- D) PascalCase(不推荐)
|
|
46
|
-
|
|
47
|
-
**Q2. 变量 / 函数命名风格**
|
|
48
|
-
- A) camelCase(推荐)
|
|
49
|
-
- B) snake_case
|
|
50
|
-
- C) kebab-case(不推荐)
|
|
51
|
-
|
|
52
|
-
**Q3. 类 / 构造类型命名风格**
|
|
53
|
-
- A) PascalCase(推荐)
|
|
54
|
-
- B) camelCase
|
|
55
|
-
- C) snake_case
|
|
56
|
-
|
|
57
|
-
**Q4. 缩写策略(防止风格漂移)**
|
|
58
|
-
- A) 不允许随意缩写(必须写全)
|
|
59
|
-
- B) 允许常见缩写(API / URL / DB / ID)
|
|
60
|
-
|
|
61
|
-
---
|
|
62
|
-
|
|
63
|
-
## 1.2 用户回答不足时的处理
|
|
64
|
-
- 若只回答部分问题:继续追问未回答项
|
|
65
|
-
- 若回答“随便 / 你定”:使用默认推荐值,并在生成结果中说明
|
|
66
|
-
- 避免开放式问题,始终优先使用选项
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## 2) 默认推荐值(与 1.0 展示内容保持一致)
|
|
71
|
-
- 文件 / 目录:kebab-case
|
|
72
|
-
- 变量 / 函数:camelCase
|
|
73
|
-
- 类 / 构造类型:PascalCase
|
|
74
|
-
- 缩写策略:允许常见缩写(API / URL / DB / ID)
|
|
75
|
-
- 测试文件:*.test.ts / *.spec.ts
|
|
76
|
-
- React 组件:PascalCase.tsx
|
|
77
|
-
- Hook:useXxx
|