@modus-ai/modus 0.2.10 → 0.2.11

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.
Files changed (35) hide show
  1. package/dist/commands/init.d.ts +2 -2
  2. package/dist/commands/init.d.ts.map +1 -1
  3. package/dist/commands/init.js +19 -3
  4. package/dist/commands/init.js.map +1 -1
  5. package/dist/generators/codebuddy.d.ts.map +1 -1
  6. package/dist/generators/codebuddy.js +10 -2
  7. package/dist/generators/codebuddy.js.map +1 -1
  8. package/dist/generators/continue.d.ts +16 -0
  9. package/dist/generators/continue.d.ts.map +1 -0
  10. package/dist/generators/continue.js +435 -0
  11. package/dist/generators/continue.js.map +1 -0
  12. package/dist/generators/cursor.d.ts.map +1 -1
  13. package/dist/generators/cursor.js +7 -1
  14. package/dist/generators/cursor.js.map +1 -1
  15. package/dist/generators/custom.d.ts.map +1 -1
  16. package/dist/generators/custom.js +8 -1
  17. package/dist/generators/custom.js.map +1 -1
  18. package/dist/generators/index.d.ts.map +1 -1
  19. package/dist/generators/index.js +4 -0
  20. package/dist/generators/index.js.map +1 -1
  21. package/dist/utils/config.d.ts +20 -1
  22. package/dist/utils/config.d.ts.map +1 -1
  23. package/dist/utils/config.js.map +1 -1
  24. package/dist/utils/file-system.d.ts +16 -0
  25. package/dist/utils/file-system.d.ts.map +1 -1
  26. package/dist/utils/file-system.js +40 -0
  27. package/dist/utils/file-system.js.map +1 -1
  28. package/package.json +1 -1
  29. package/templates/skills/modus-init/SKILL.md +274 -768
  30. package/templates/skills/modus-init/shared/frontmatter-spec.md +255 -0
  31. package/templates/skills/modus-init/shared/stack-detection.md +144 -0
  32. package/templates/skills/modus-init/shared/universal-skill-format.md +362 -0
  33. package/templates/skills/modus-init/strategies/fallback-init.md +150 -0
  34. package/templates/skills/modus-init/strategies/frontend-init.md +298 -0
  35. package/templates/skills/modus-init/strategies/java-init.md +278 -0
@@ -0,0 +1,255 @@
1
+ ---
2
+ title: Frontmatter Spec — 业务 Skill 防腐字段规范(语言无关)
3
+ parent_skill: modus-init
4
+ load_when: "执行 Step 8 生成 Skill 前必读;执行 /modus:verify、/modus:refresh 前必读;任何栈的 strategy 文件都引用本文档"
5
+ ---
6
+
7
+ # Business Skill Frontmatter 规范(防腐机制核心)
8
+
9
+ > 本文档是**所有栈共用**的 frontmatter 字段规范(语言无关)。Java、Frontend、Go、Python 等所有 strategy 在生成 Skill 时**必须**完整填写下列字段。
10
+
11
+ ---
12
+
13
+ ## 一、基础元数据字段(必填)
14
+
15
+ | 字段 | 类型 | 含义 | 初始值 |
16
+ |------|------|------|--------|
17
+ | `name` | string | Skill 唯一标识符(与目录名一致) | `biz-{domain}` |
18
+ | `description` | string | 一句话描述,必须包含 `[MODUS:BIZ]` 标记 | 由 strategy 生成 |
19
+ | `version` | semver | 语义化版本号 | `1.0.0` |
20
+ | `updated` | date (YYYY-MM-DD) | 最后更新日期 | 今日 |
21
+ | `status` | enum | 成熟度状态 | `draft` |
22
+ | `format_version` | string | 节结构版本,格式 `v3-{stack}` | `v3-java` / `v3-frontend-react` / ... |
23
+ | `stack` | enum | 主语言栈(与 `modus/config.yaml.primaryStack` 一致) | 由栈检测决定 |
24
+ | `stale_after_days` | integer | 超过此天数自动降为 stale | `90` |
25
+
26
+ > **关于 `format_version`:** 节骨架(17 节编号 + 名称 + 知识标签)跨栈完全一致;只有节内填充按栈分流。`v3-{stack}` 仅用于让工具/Agent 识别该 Skill 是按哪个 strategy 生成的,便于增量补节时正确选用模板。
27
+
28
+ ---
29
+
30
+ ## 二、防腐机制核心字段(必填,缺少则无法检测代码变更)
31
+
32
+ | 字段 | 类型 | 用途 | 初始值规则 |
33
+ |------|------|------|-----------|
34
+ | **`last_referenced`** | date | 最后引用时间;超过 `stale_after_days` 自动降级 | = `updated` 日期 |
35
+ | **`usage_count`** | integer | 使用次数;判定成熟度升级(draft→verified→proven) | `0` |
36
+ | **`last_hash`** | SHA-1 string | 全局快速比对入口;不一致时展开 `file_hashes` 逐文件比对 | init 时按下方算法实算 |
37
+ | **`file_hashes`** | map[path→SHA-1] | 文件级 hash;全局 hash 不一致时使用,精准输出"变更文件清单" | 每个 key_files 单独 SHA-1 |
38
+ | **`last_verified_by`** | string | 最后人工验证人;升为 verified 时填写 | `""` |
39
+ | **`verified_at`** | date | 最后验证日期;由 `/modus:verify` 写入 | `""` |
40
+
41
+ ### 标准 hash 计算算法(所有命令统一使用)
42
+
43
+ ```
44
+ 1. 对 key_files 中每个文件【单独】计算 SHA-1(写入 file_hashes)
45
+ 2. 将「文件路径:SHA-1」对按【文件路径字母序】排序后拼接成字符串
46
+ 3. 整体再算一次 SHA-1,得到 last_hash
47
+ ```
48
+
49
+ **Bash 参考实现**(栈无关,所有 strategy 通用):
50
+
51
+ ```bash
52
+ for f in $(echo "{key_files}" | tr ' ' '\n' | sort); do
53
+ echo "$(shasum -a 1 "$f" | awk '{print $1}'):$f"
54
+ done | shasum -a 1 | awk '{print $1}'
55
+ ```
56
+
57
+ > ⚠️ **禁止使用「内容拼接后整体计算」的方式**——受文件顺序影响,且无法与 `file_hashes` 兼容。
58
+
59
+ ---
60
+
61
+ ## 三、key_files 填写规则(最多 20 个)
62
+
63
+ `key_files` 是 hash 检测的输入。各 strategy 按本栈优先级选取,**总数上限 20**,超出时按从后往前截断:
64
+
65
+ > 各栈具体的优先级清单见对应 `strategies/{stack}-init.md` 的"key_files 选取指南"章节。本文档只规定通用原则。
66
+
67
+ **通用通则:**
68
+ - 必选:业务核心逻辑文件(Service/Hook/Composable/Handler 等)
69
+ - 必选:状态/类型枚举(Status/Type/Schema)
70
+ - 强烈建议:错误处理(Exception/Error/ErrorBoundary 等)
71
+ - 有则加入:消息消费、配置开关、扩展点
72
+
73
+ ---
74
+
75
+ ## 四、质量评分字段(必填,用于知识库质量报告)
76
+
77
+ | 字段 | 类型 | 用途 |
78
+ |------|------|------|
79
+ | `domain_confidence` | integer 0-10 | 本域置信度评分,来自栈对应的扫描矩阵 |
80
+ | `invariant_count` | integer | Section 15 业务不变量条目数 |
81
+ | `glossary_size` | integer | Section 16 领域词汇表条目数 |
82
+ | `hidden_knowledge_rate` | integer 0-100 | 隐性知识补全率(来自 Step 7 访谈问卷) |
83
+ | `contract_version` | string | 本域对外暴露接口的当前版本(初始 `"1.0"`) |
84
+
85
+ ---
86
+
87
+ ## 五、跨域依赖字段(Section 10 回写阶段自动填入)
88
+
89
+ | 字段 | 类型 | 用途 |
90
+ |------|------|------|
91
+ | `upstream_skills` | string[] | 本域依赖的其他域 Skill 列表 |
92
+ | `downstream_skills` | string[] | 依赖本域的其他域 Skill 列表 |
93
+ | `stale_cascade` | boolean | 联动失效标记;upstream 任一 hash 变更时自动置为 true |
94
+
95
+ ---
96
+
97
+ ## 六、外部依赖感知字段(init 自动从构建文件提取)
98
+
99
+ | 字段 | 类型 | 含义 | 提取来源 |
100
+ |------|------|------|---------|
101
+ | `external_deps` | map[string→semver-range] | 本域规范依赖的外部库版本范围 | 按栈而异:见下表 |
102
+
103
+ ### 各栈提取来源
104
+
105
+ | stack | 提取自 | 排除规则 |
106
+ |-------|--------|---------|
107
+ | `java` | `pom.xml` `<dependencies>` | 排除 `java.*`、`javax.*`、`org.springframework.*`(框架级,不属于域规范) |
108
+ | `frontend-*` / `backend-node` | `package.json` `dependencies + devDependencies` | 排除 `@types/*`、`eslint-*`、`prettier-*`、`@testing-library/*`(工具链级) |
109
+ | `go` | `go.mod` `require` | 排除标准库(无前缀) |
110
+ | `python` | `pyproject.toml` `dependencies` | 排除标准库 |
111
+
112
+ ### 检测时机
113
+
114
+ | 时机 | 行为 |
115
+ |------|------|
116
+ | `/modus:init` 生成 Skill | 自动扫描该域代码 import 频率最高的前 5 个第三方库,记录 semver-range |
117
+ | `/modus:init --enhance` 增量更新 | 重新扫描,对比版本变化 |
118
+ | `modus update` | 检查 `external_deps` 中的库是否发生 **major version** 升级(如 `2.x → 3.x`),是则将该 Skill 降级为 `stale`,追加 `⚠️ 外部依赖 {lib} 升级({old} → {new}),规范需验证` |
119
+
120
+ ### 示例
121
+
122
+ ```yaml
123
+ # Java 域示例
124
+ external_deps:
125
+ spring-boot: "~2.7"
126
+ mybatis-plus: ">=3.5 <4.0"
127
+ dubbo: "~3.1"
128
+
129
+ # 前端 React 域示例
130
+ external_deps:
131
+ react: "^18.2"
132
+ "@tanstack/react-query": "^5.0"
133
+ zustand: "^4.4"
134
+ "react-hook-form": "^7.45"
135
+ zod: "^3.22"
136
+ ```
137
+
138
+ ---
139
+
140
+ ## ⛔ 防腐字段缺失的后果
141
+
142
+ 如果 frontmatter 缺少上述任一防腐字段(特别是 `last_referenced`、`usage_count`、`last_hash`、`file_hashes`、`key_files`、`stack`),将导致:
143
+ - 无法自动检测代码变更(hash 比对失效)
144
+ - 无法触发 Skill 更新
145
+ - 无法计算知识衰减
146
+ - 无法跨栈识别 Skill 来源
147
+ - **防腐机制完全失效**
148
+
149
+ > 所有 strategy 文件在 Step 8 中都必须二次校验 frontmatter 完整性,缺字段时自动补 `""` 或 `0` 占位,不允许直接漏写。
150
+
151
+ ---
152
+
153
+ ## 七、frontmatter 模板(语言无关参考)
154
+
155
+ > 各 strategy 在 Step 8 生成 Skill 时,应以此模板为基础,仅修改 `name` / `stack` / `format_version` / `key_files` 等栈相关字段。
156
+
157
+ ```yaml
158
+ ---
159
+ name: biz-{domain}
160
+ description: "[MODUS:BIZ] {中文域名}业务知识 — {核心职责一句话}"
161
+ version: 1.0.0
162
+ updated: {YYYY-MM-DD}
163
+ status: draft
164
+ format_version: v3-{stack} # v3-java / v3-frontend-react / v3-frontend-vue / ...
165
+ stack: {stack} # 与 modus/config.yaml.primaryStack 一致
166
+ stale_after_days: 90
167
+ last_referenced: {YYYY-MM-DD}
168
+ usage_count: 0
169
+ last_hash: "" # init 时按标准算法实算后写入
170
+ file_hashes: {} # init 时每个 key_files 单独 SHA-1
171
+ last_verified_by: ""
172
+ verified_at: ""
173
+ domain_confidence: 0
174
+ invariant_count: 0
175
+ glossary_size: 0
176
+ hidden_knowledge_rate: 0
177
+ contract_version: "1.0"
178
+ upstream_skills: []
179
+ downstream_skills: []
180
+ stale_cascade: false
181
+ external_deps: {} # 见本文档第六节
182
+ key_files: # 详见各 strategy 的优先级规则,最多 20 个
183
+ - {按栈而异,由 strategy 决定}
184
+ ---
185
+ ```
186
+
187
+ ---
188
+
189
+ ## 八、Status 生命周期与衰减规则
190
+
191
+ > 本节为所有栈通用,与 strategy 无关。
192
+
193
+ ### Status 生命周期
194
+
195
+ ```
196
+ draft → verified → proven
197
+ │ (超过阈值未引用)
198
+ verified ←─────────────┘
199
+
200
+ │ (超过阈值未引用)
201
+
202
+ stale
203
+ │ (超过 stale_after_days)
204
+
205
+ archived (需人工确认)
206
+ ```
207
+
208
+ | status | 含义 | 升级条件 | 禁止行为 |
209
+ |--------|------|---------|---------|
210
+ | `draft` | 初始生成,未经验证 | `/modus:verify` 通过四项检查 → `verified` | - |
211
+ | `verified` | 经至少 1 次真实使用验证 | `usage_count ≥ 2` 且不同工作流 → `proven` | - |
212
+ | `proven` | 经 ≥2 个不同工作流验证 | - | - |
213
+ | `stale` | hash 不匹配或衰减超期 | `/modus:refresh` → `draft` | **禁止直接引用** |
214
+ | `archived` | 域已废弃 | - | **禁止引用** |
215
+
216
+ ### 活跃度感知衰减(基于 `usage_count`)
217
+
218
+ | 活跃度 | usage_count | verified→stale 阈值 | proven→verified 阈值 |
219
+ |--------|------------|----------------------|----------------------|
220
+ | 活跃域 | ≥ 10 | 12 个月 | 24 个月 |
221
+ | 正常域 | 3-9 | **6 个月(默认)** | **12 个月(默认)** |
222
+ | 冷门域 | ≤ 2 | 3 个月 | 6 个月 |
223
+
224
+ ---
225
+
226
+ ## 九、同步副本管理规约
227
+
228
+ > 本节适用于所有平台(codebuddy / claude / cursor / continue / codex / copilot / 自定义)。
229
+
230
+ ### 权威源 vs. 副本
231
+
232
+ | 文件 | 角色 | 防腐字段权威性 | 更新方式 |
233
+ |------|------|-------------|---------|
234
+ | `modus/knowledge/biz-{domain}/SKILL.md` | **权威源** | 所有防腐字段的唯一权威存储 | 命令直接写入 |
235
+ | 各平台同步副本(`.codebuddy/skills/biz-*/`、`.claude/agents/modus-biz-*.md`、`.continue/skills/biz-*/` 等) | 只读快照 | 仅通过 `<!-- modus:meta -->` 注释暴露核心字段 | Step 9 同步时自动更新 |
236
+
237
+ **关键原则:**
238
+ - 所有防腐机制的触发(hash 比对、衰减计算、`usage_count` 更新)**只操作 `modus/knowledge/` 权威源**
239
+ - 副本变更不触发防腐机制
240
+ - 副本与权威源不一致时,以权威源为准,下次同步强制覆盖
241
+
242
+ ### 机器可读 meta 注释(供工具层解析)
243
+
244
+ 副本文件(如 `.claude/agents/modus-biz-{domain}.md`)顶层 frontmatter 之后必须插入:
245
+
246
+ ```markdown
247
+ <!-- modus:meta
248
+ last_hash: "{从权威源读取}"
249
+ status: "{从权威源读取}"
250
+ updated: "{从权威源读取}"
251
+ stack: "{从权威源读取}"
252
+ -->
253
+ ```
254
+
255
+ 工具层优先读取此注释,不解析正文中的二级 frontmatter。
@@ -0,0 +1,144 @@
1
+ ---
2
+ title: Stack Detection — modus-init Step 0.5 单一真相来源
3
+ parent_skill: modus-init
4
+ load_when: "Router SKILL.md 执行 Step 0.5 时读取本文档;其他命令(auto/harness/spec)需要确认主栈时也可读取"
5
+ ---
6
+
7
+ # 栈检测规则(Stack Detection)
8
+
9
+ > 本文档定义 `/modus:init` Router 在 **Step 0.5** 如何探测项目主语言栈,并将结果写入 `modus/config.yaml` 的 `primaryStack` 字段,从而路由到对应的 strategy 文件。
10
+
11
+ ---
12
+
13
+ ## 1. 检测顺序与决策树
14
+
15
+ 按以下顺序逐项检查项目根目录,**第一个命中的即为主栈**(不再继续):
16
+
17
+ ```mermaid
18
+ flowchart TD
19
+ START([Step 0.5 开始])
20
+ START --> JVM{"pom.xml / build.gradle\n / build.gradle.kts ?"}
21
+ JVM -->|是| JAVA["primaryStack = java"]
22
+ JVM -->|否| GO_CHK{"go.mod ?"}
23
+ GO_CHK -->|是| GO["primaryStack = go"]
24
+ GO_CHK -->|否| PY_CHK{"pyproject.toml /\nrequirements.txt / setup.py ?"}
25
+ PY_CHK -->|是| PY["primaryStack = python"]
26
+ PY_CHK -->|否| RUST_CHK{"Cargo.toml ?"}
27
+ RUST_CHK -->|是| RUST["primaryStack = rust"]
28
+ RUST_CHK -->|否| PKG_CHK{"package.json ?"}
29
+ PKG_CHK -->|否| FALLBACK["primaryStack = fallback\n(走通用 Glob 兜底)"]
30
+ PKG_CHK -->|是| DEPS["读取 dependencies +\ndevDependencies"]
31
+ DEPS --> NEST{"@nestjs/core /\nexpress / fastify / koa ?"}
32
+ NEST -->|是| NODE["primaryStack = backend-node"]
33
+ NEST -->|否| NUXT{"vue / nuxt / @vue/cli ?"}
34
+ NUXT -->|是| VUE["primaryStack = frontend-vue"]
35
+ NUXT -->|否| REACT{"react / next / @remix-run /\nvite + react?"}
36
+ REACT -->|是| REACTSTACK["primaryStack = frontend-react"]
37
+ REACT -->|否| OTHER_FE["primaryStack = frontend-other"]
38
+ ```
39
+
40
+ ---
41
+
42
+ ## 2. 探测信号矩阵(精确判定规则)
43
+
44
+ | 信号文件/字段 | 命中后的 primaryStack | 路由到的 strategy 文件 |
45
+ |--------------|----------------------|--------------------|
46
+ | `pom.xml` | `java` | `strategies/java-init.md` |
47
+ | `build.gradle` / `build.gradle.kts` | `java` | `strategies/java-init.md` |
48
+ | `go.mod` | `go` | `strategies/fallback-init.md`(Phase 4 起改为 `go-init.md`) |
49
+ | `pyproject.toml` / `requirements.txt` / `setup.py` | `python` | `strategies/fallback-init.md`(Phase 4 起改为 `python-init.md`) |
50
+ | `Cargo.toml` | `rust` | `strategies/fallback-init.md` |
51
+ | `package.json` 中 `dependencies/devDependencies` 含 `@nestjs/core` / `express` / `fastify` / `koa` | `backend-node` | `strategies/fallback-init.md`(Phase 4 起改为 `node-init.md`) |
52
+ | `package.json` 含 `vue` / `@vue/cli` / `nuxt` / `nuxt3` | `frontend-vue` | `strategies/frontend-init.md`(§Vue 子流程) |
53
+ | `package.json` 含 `react` / `next` / `@remix-run/react` / `@tanstack/router` | `frontend-react` | `strategies/frontend-init.md`(§React 子流程) |
54
+ | `package.json` 但无上述任意框架 | `frontend-other` | `strategies/frontend-init.md`(§通用前端兜底) |
55
+ | 以上全部未命中 | `fallback` | `strategies/fallback-init.md` |
56
+
57
+ ---
58
+
59
+ ## 3. 多栈共存(混合 monorepo)处理
60
+
61
+ 如果同一仓库**同时**存在多种栈标志(例如 `pom.xml` + `package.json`,典型的"前后端一仓"),按以下策略:
62
+
63
+ ### 3.1 自动模式(带 `--force` 时)
64
+
65
+ 按以下优先级选主栈:
66
+ ```
67
+ backend-java > backend-node > frontend-react > frontend-vue > python/go/rust > fallback
68
+ ```
69
+ > 优先选后端是因为:业务模型核心通常在后端,前端往往以"消费者"身份存在;harness/plan 命令更依赖后端语义。
70
+
71
+ ### 3.2 交互模式(默认)
72
+
73
+ 向用户展示检测结果,让其手动确认:
74
+
75
+ ```
76
+ 检测到本项目存在多个技术栈:
77
+ ✓ Java (pom.xml — Spring Boot) — 推荐主栈
78
+ ✓ React (package.json — react@18.x)
79
+
80
+ 请选择主栈(决定 modus init 使用哪份扫描规则):
81
+ [1] java — 后端 Java 项目(5 轮扫描,17 节业务 Skill)★ 推荐
82
+ [2] frontend-react — 前端 React 项目(前端版 5 轮扫描,17 节前端化 Skill)
83
+ [3] 两栈分别独立 init — 适用 monorepo 两个独立可发布单元
84
+ [4] 自定义 — 手动指定 primaryStack 值
85
+
86
+ > _
87
+ ```
88
+
89
+ 选项 [3] 为高级模式:
90
+ - 提示用户在 `modus/config.yaml` 中将项目升级为 workspace(`modus-workspace.yaml`)
91
+ - 每个子目录独立运行 `/modus:init --project <name>`
92
+ - 详见区块 A 主流程 Step 3 的"多项目工作区检测"
93
+
94
+ ---
95
+
96
+ ## 4. 写入 modus/config.yaml
97
+
98
+ 栈检测完成后,必须写入:
99
+
100
+ ```yaml
101
+ primaryStack: java # 见 PrimaryStack 类型定义
102
+ # 其他字段保持不变 ...
103
+ ```
104
+
105
+ 后续 `/modus:vibe`、`/modus:plan`、`/modus:spec`、`/modus:harness` 在加载知识时会读取该字段,决定如何渲染上下文。
106
+
107
+ ---
108
+
109
+ ## 5. Skill frontmatter 的 `stack` 字段
110
+
111
+ 每个生成的业务 Skill(`modus/knowledge/biz-*/SKILL.md`)必须在 frontmatter 中包含 `stack` 字段,与 `primaryStack` 保持一致:
112
+
113
+ ```yaml
114
+ ---
115
+ name: biz-order
116
+ stack: java # 与 modus/config.yaml.primaryStack 一致
117
+ format_version: v3-java # v3-{stack}:节骨架统一,节内填充按栈分流
118
+ # ...
119
+ ---
120
+ ```
121
+
122
+ > 通用知识库原则:**节号、节名、知识标签**跨栈完全一致;只有节内**填充语义**按 `stack` 分流。
123
+
124
+ ---
125
+
126
+ ## 6. 失败兜底
127
+
128
+ 如果检测过程中遇到异常(如 `package.json` 损坏无法解析),主流程必须:
129
+ - 不中断 init 流程
130
+ - `primaryStack = fallback`
131
+ - 在 Step 14 完成回报中给出明确警告:`⚠️ 栈检测降级为 fallback,原因:{异常摘要}。可手动修改 modus/config.yaml.primaryStack 后重跑 /modus:init`
132
+
133
+ ---
134
+
135
+ ## 7. 与 CLI `detectTechStack()` 的关系
136
+
137
+ `src/commands/init.ts` 中的 `detectTechStack()` 函数仅用于**`modus init` CLI 阶段的展示型描述**(如 `"Java Maven, MySQL"`),它输出的是**人类可读字符串**。
138
+
139
+ 本文档定义的栈检测发生在 **`/modus:init` Skill 阶段**(用户在 AI 工具中执行),输出的是**机器可路由的枚举值**。两者目标不同,互不替代:
140
+
141
+ | 阶段 | 工具 | 输出 | 用途 |
142
+ |------|------|------|------|
143
+ | `modus init`(CLI) | `detectTechStack()` | `"Java Maven, Spring Boot, React"` | 写入 `config.techStack`,展示给用户看 |
144
+ | `/modus:init`(Skill) | 本文档定义的检测 | `primaryStack: "java"` | 路由到对应 strategy 文件 |