@modus-ai/modus 0.1.4 → 0.1.6

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 (58) hide show
  1. package/README.md +76 -28
  2. package/dist/cli/index.js +206 -12
  3. package/dist/cli/index.js.map +1 -1
  4. package/dist/commands/doctor.d.ts +2 -0
  5. package/dist/commands/doctor.d.ts.map +1 -0
  6. package/dist/commands/doctor.js +180 -0
  7. package/dist/commands/doctor.js.map +1 -0
  8. package/dist/commands/init.d.ts +18 -0
  9. package/dist/commands/init.d.ts.map +1 -1
  10. package/dist/commands/init.js +314 -201
  11. package/dist/commands/init.js.map +1 -1
  12. package/dist/commands/skill.d.ts +7 -0
  13. package/dist/commands/skill.d.ts.map +1 -0
  14. package/dist/commands/skill.js +175 -0
  15. package/dist/commands/skill.js.map +1 -0
  16. package/dist/commands/status.d.ts +2 -0
  17. package/dist/commands/status.d.ts.map +1 -0
  18. package/dist/commands/status.js +133 -0
  19. package/dist/commands/status.js.map +1 -0
  20. package/dist/commands/update.d.ts.map +1 -1
  21. package/dist/commands/update.js +15 -6
  22. package/dist/commands/update.js.map +1 -1
  23. package/dist/generators/claude.d.ts +9 -0
  24. package/dist/generators/claude.d.ts.map +1 -0
  25. package/dist/generators/claude.js +256 -0
  26. package/dist/generators/claude.js.map +1 -0
  27. package/dist/generators/codebuddy.d.ts +7 -0
  28. package/dist/generators/codebuddy.d.ts.map +1 -1
  29. package/dist/generators/codebuddy.js +35 -3
  30. package/dist/generators/codebuddy.js.map +1 -1
  31. package/dist/generators/copilot.d.ts +9 -0
  32. package/dist/generators/copilot.d.ts.map +1 -0
  33. package/dist/generators/copilot.js +154 -0
  34. package/dist/generators/copilot.js.map +1 -0
  35. package/dist/generators/cursor.d.ts +9 -0
  36. package/dist/generators/cursor.d.ts.map +1 -0
  37. package/dist/generators/cursor.js +220 -0
  38. package/dist/generators/cursor.js.map +1 -0
  39. package/dist/generators/index.d.ts +9 -0
  40. package/dist/generators/index.d.ts.map +1 -0
  41. package/dist/generators/index.js +26 -0
  42. package/dist/generators/index.js.map +1 -0
  43. package/dist/utils/analytics.d.ts +14 -0
  44. package/dist/utils/analytics.d.ts.map +1 -0
  45. package/dist/utils/analytics.js +81 -0
  46. package/dist/utils/analytics.js.map +1 -0
  47. package/dist/utils/config.d.ts +25 -0
  48. package/dist/utils/config.d.ts.map +1 -1
  49. package/dist/utils/config.js.map +1 -1
  50. package/package.json +1 -1
  51. package/templates/commands/auto.md +38 -0
  52. package/templates/commands/modus.md +14 -2
  53. package/templates/hooks/session-start.py +103 -1
  54. package/templates/hooks/stop-update-skills.py +58 -0
  55. package/templates/skills/modus-auto/SKILL.md +210 -0
  56. package/templates/skills/modus-init/SKILL.md +208 -11
  57. package/templates/skills/modus-plan/SKILL.md +154 -19
  58. package/templates/skills/modus-spec/SKILL.md +131 -6
@@ -7,6 +7,54 @@ the session so every conversation starts with business knowledge pre-loaded.
7
7
  import json
8
8
  import os
9
9
  import sys
10
+ import urllib.request
11
+ import hashlib
12
+ import socket
13
+
14
+
15
+ def _track(project_dir: str, event: dict) -> None:
16
+ """Send a usage event to the Modus Collector. Silently swallows all errors."""
17
+ if os.environ.get("MODUS_ANALYTICS_DISABLED") == "1":
18
+ return
19
+ try:
20
+ import yaml # type: ignore[import-untyped]
21
+ config_path = os.path.join(project_dir, "modus", "config.yaml")
22
+ with open(config_path, encoding="utf-8") as f:
23
+ config = yaml.safe_load(f) or {}
24
+ analytics = config.get("analytics") or {}
25
+ if analytics.get("enabled") is False:
26
+ return
27
+ collector_url = (analytics.get("collectorUrl") or "").strip()
28
+ if not collector_url:
29
+ return
30
+ token = (analytics.get("token") or "").strip()
31
+ # Anonymize user id
32
+ try:
33
+ import subprocess
34
+ email = subprocess.check_output(
35
+ ["git", "config", "--global", "user.email"],
36
+ timeout=2, stderr=subprocess.DEVNULL
37
+ ).decode().strip()
38
+ user_id = hashlib.md5(email.encode()).hexdigest()[:16] if email else None
39
+ except Exception:
40
+ user_id = hashlib.md5(socket.gethostname().encode()).hexdigest()[:16]
41
+
42
+ body = json.dumps({
43
+ **event,
44
+ "user_id": user_id,
45
+ "project_id": config.get("tapdProjectId"),
46
+ "team_name": config.get("teamName"),
47
+ }).encode()
48
+ req = urllib.request.Request(
49
+ f"{collector_url}/track",
50
+ data=body,
51
+ headers={"Content-Type": "application/json",
52
+ **({"Authorization": f"Bearer {token}"} if token else {})},
53
+ method="POST",
54
+ )
55
+ urllib.request.urlopen(req, timeout=2)
56
+ except Exception:
57
+ pass # Intentionally silent
10
58
 
11
59
 
12
60
  def read_file_safe(path: str, max_bytes: int = 8000) -> str:
@@ -17,12 +65,54 @@ def read_file_safe(path: str, max_bytes: int = 8000) -> str:
17
65
  return ""
18
66
 
19
67
 
68
+ def _silent_auto_update(project_dir: str) -> bool:
69
+ """
70
+ Compare the modus CLI version that generated the current project files
71
+ (stored in modus/config.yaml modusBuildVersion) with the currently installed
72
+ modus version. If they differ, silently re-run `modus update` so users get
73
+ new templates automatically after an npm upgrade — no manual action needed.
74
+
75
+ Returns True if an update was performed.
76
+ """
77
+ try:
78
+ import subprocess
79
+ import yaml # type: ignore[import-untyped]
80
+
81
+ config_path = os.path.join(project_dir, "modus", "config.yaml")
82
+ with open(config_path, encoding="utf-8") as f:
83
+ config = yaml.safe_load(f) or {}
84
+
85
+ stored_version = (config.get("modusBuildVersion") or "").strip()
86
+ if not stored_version:
87
+ return False # Never stamped — skip (pre-feature install)
88
+
89
+ result = subprocess.run(
90
+ ["modus", "--version"],
91
+ capture_output=True, text=True, timeout=5,
92
+ )
93
+ current_version = result.stdout.strip()
94
+ if not current_version or current_version == stored_version:
95
+ return False # Up to date
96
+
97
+ # Versions differ — silently regenerate all platform files
98
+ subprocess.run(
99
+ ["modus", "update", "--root", project_dir],
100
+ capture_output=True, timeout=60,
101
+ )
102
+ return True
103
+ except Exception:
104
+ return False # Non-fatal — never break the session
105
+
106
+
20
107
  def main() -> int:
21
108
  input_data = json.loads(sys.stdin.read())
22
109
  project_dir = os.environ.get("CODEBUDDY_PROJECT_DIR") or os.environ.get(
23
110
  "CLAUDE_PROJECT_DIR", input_data.get("cwd", "")
24
111
  )
25
112
 
113
+ # Auto-update: silently regenerate files if modus CLI was upgraded since last init/update
114
+ was_updated = _silent_auto_update(project_dir)
115
+
26
116
  context_parts: list[str] = []
27
117
 
28
118
  # 1. knowledge-catalog — Level 1 index (~200 tokens)
@@ -65,10 +155,18 @@ def main() -> int:
65
155
  if not context_parts:
66
156
  output = {"continue": True}
67
157
  else:
158
+ update_notice = "\n🔄 [Modus 已自动升级] 平台文件已静默刷新至最新版本。" if was_updated else ""
68
159
  additional_context = (
69
160
  "=== Modus 项目上下文(自动注入)===\n\n"
70
161
  + "\n\n".join(context_parts)
71
- + "\n\n提示:使用 /modus:vibe、/modus:plan、/modus:spec 或 /modus:harness 开始工作。"
162
+ + update_notice
163
+ + "\n\n**[自动 Vibe 模式已启用]**\n"
164
+ "本会话无需用户输入 /modus:vibe,请自动以「懂项目的开发者」身份响应:\n"
165
+ "1. 根据用户请求,从知识目录中匹配相关业务域\n"
166
+ "2. 按需加载对应的 Business Skill(.codebuddy/skills/modus-biz-*/SKILL.md)\n"
167
+ "3. 以 Skill 中的业务规则、命名约定和已知坑作为约束回答或编码\n"
168
+ "4. 若用户显式运行 /modus:plan、/modus:spec 或 /modus:harness,切换到对应模式\n"
169
+ "完整 Vibe 工作流程见 modus-vibe Skill。"
72
170
  )
73
171
  output = {
74
172
  "continue": True,
@@ -79,6 +177,10 @@ def main() -> int:
79
177
  }
80
178
 
81
179
  print(json.dumps(output, ensure_ascii=False))
180
+
181
+ # Report session start event (non-blocking best-effort)
182
+ _track(project_dir, {"event_type": "session.started"})
183
+
82
184
  return 0
83
185
 
84
186
 
@@ -8,8 +8,55 @@ to trigger a knowledge write-back.
8
8
  import json
9
9
  import os
10
10
  import sys
11
+ import urllib.request
12
+ import hashlib
13
+ import socket
11
14
  from datetime import datetime, timezone
12
15
 
16
+
17
+ def _track(project_dir: str, event: dict) -> None:
18
+ """Send a usage event to the Modus Collector. Silently swallows all errors."""
19
+ if os.environ.get("MODUS_ANALYTICS_DISABLED") == "1":
20
+ return
21
+ try:
22
+ import yaml # type: ignore[import-untyped]
23
+ config_path = os.path.join(project_dir, "modus", "config.yaml")
24
+ with open(config_path, encoding="utf-8") as f:
25
+ config = yaml.safe_load(f) or {}
26
+ analytics = config.get("analytics") or {}
27
+ if analytics.get("enabled") is False:
28
+ return
29
+ collector_url = (analytics.get("collectorUrl") or "").strip()
30
+ if not collector_url:
31
+ return
32
+ token = (analytics.get("token") or "").strip()
33
+ try:
34
+ import subprocess
35
+ email = subprocess.check_output(
36
+ ["git", "config", "--global", "user.email"],
37
+ timeout=2, stderr=subprocess.DEVNULL
38
+ ).decode().strip()
39
+ user_id = hashlib.md5(email.encode()).hexdigest()[:16] if email else None
40
+ except Exception:
41
+ user_id = hashlib.md5(socket.gethostname().encode()).hexdigest()[:16]
42
+
43
+ body = json.dumps({
44
+ **event,
45
+ "user_id": user_id,
46
+ "project_id": config.get("tapdProjectId"),
47
+ "team_name": config.get("teamName"),
48
+ }).encode()
49
+ req = urllib.request.Request(
50
+ f"{collector_url}/track",
51
+ data=body,
52
+ headers={"Content-Type": "application/json",
53
+ **({"Authorization": f"Bearer {token}"} if token else {})},
54
+ method="POST",
55
+ )
56
+ urllib.request.urlopen(req, timeout=2)
57
+ except Exception:
58
+ pass
59
+
13
60
  TRACKED_ARTIFACTS = [
14
61
  "01-analysis.md",
15
62
  "02-sprint-contract.md",
@@ -70,6 +117,17 @@ def main() -> int:
70
117
  print(json.dumps({"continue": True}))
71
118
  return 0
72
119
 
120
+ # Report each newly detected subagent artifact to the analytics collector
121
+ for item in pending:
122
+ for artifact in item["new_artifacts"]:
123
+ sub_agent = artifact.replace(".md", "").replace("-", "")[:32]
124
+ _track(project_dir, {
125
+ "event_type": "subagent.executed",
126
+ "sub_agent": sub_agent,
127
+ "result": "success",
128
+ "payload": {"story_id": item["story_id"]},
129
+ })
130
+
73
131
  lines = ["[Modus] 检测到以下 Harness 产出物尚未同步到 Skills 知识库:"]
74
132
  for item in pending:
75
133
  lines.append(f" Story {item['story_id']}: {', '.join(item['new_artifacts'])}")
@@ -0,0 +1,210 @@
1
+ ---
2
+ name: modus-auto
3
+ description: Use this skill when executing /modus:auto command. Reads a TAPD Story URL, scores it across 4 dimensions (complexity/risk/clarity/contract-impact), recommends the best Modus mode (vibe/plan/spec/harness), presents reasoning, waits for human mode selection, then auto-launches the chosen mode with context pre-filled. Trigger on /modus:auto command.
4
+ allowed-tools: Read, Write, Glob, Bash
5
+ disable: false
6
+ ---
7
+
8
+ # modus-auto(智能模式推荐)
9
+
10
+ **触发条件:** 用户运行 `/modus:auto [TAPD Story URL]` 时使用此 Skill。
11
+
12
+ ## 职责
13
+
14
+ 读取 TAPD Story 内容,从四个维度评分,推荐最合适的 Modus 模式(vibe/plan/spec/harness),展示推荐理由和备选对比,等待用户选择,确认参数后自动透传 TAPD 内容启动所选模式。
15
+
16
+ ---
17
+
18
+ ## 执行流程
19
+
20
+ ### Step 1:读取 TAPD Story
21
+
22
+ 通过 TAPD MCP 读取 Story 内容:
23
+
24
+ ```bash
25
+ # 从 URL 提取 story-id,调用 TAPD MCP 获取内容
26
+ story_id = extract_from_url(tapd_url)
27
+ story = tapd_mcp.get_story(story_id)
28
+ ```
29
+
30
+ 提取以下字段:
31
+ - 标题、描述、验收标准
32
+ - 优先级、预估工时
33
+ - 涉及模块(从标题/描述中判断)
34
+ - 迭代/Sprint 信息
35
+
36
+ 若 TAPD MCP 不可用,提示用户手动粘贴 Story 内容,继续执行。
37
+
38
+ ### Step 2:读取知识目录
39
+
40
+ 读取 `modus/knowledge-catalog.md`,了解可用的业务 Skill 及其成熟度。用于判断哪些域已有充足上下文。
41
+
42
+ ### Step 3:四维评分
43
+
44
+ 对 Story 内容进行结构化分析,输出每个维度的评分:
45
+
46
+ #### 维度一:复杂度 (Complexity)
47
+
48
+ | 分值 | 判定条件 |
49
+ |------|----------|
50
+ | 低 (1) | 单文件修改、bug fix、文案/配置调整 |
51
+ | 中 (2) | 1-2 个业务域、5 个以内文件变更、新增接口但无架构变化 |
52
+ | 高 (3) | 跨 3+ 个域、需新建数据表、涉及消息队列/异步流程 |
53
+
54
+ 判断依据:Story 描述中的关键词("新增表"、"重构"、"接入 MQ"、涉及文件数估算)
55
+
56
+ #### 维度二:风险 (Risk)
57
+
58
+ | 分值 | 判定条件 |
59
+ |------|----------|
60
+ | 低 (1) | 纯新增功能,不修改现有逻辑 |
61
+ | 中 (2) | 修改已有接口或业务逻辑,影响单一模块 |
62
+ | 高 (3) | 涉及支付/权限/多租户隔离/金额计算/数据迁移/接口废弃 |
63
+
64
+ #### 维度三:需求明确度 (Clarity)
65
+
66
+ | 分值 | 判定条件 |
67
+ |------|----------|
68
+ | 高 (3) | 验收标准完整(有具体输入输出)、边界条件明确 |
69
+ | 中 (2) | 有基本描述,部分细节待确认 |
70
+ | 低 (1) | 描述模糊、无验收标准、需大量澄清 |
71
+
72
+ #### 维度四:接口契约影响 (Contract Impact)
73
+
74
+ | 分值 | 判定条件 |
75
+ |------|----------|
76
+ | 无 (0) | 纯内部逻辑,不影响对外接口 |
77
+ | 有 (1) | 新增接口、修改现有接口签名/返回值、废弃接口 |
78
+
79
+ ### Step 4:判定推荐模式
80
+
81
+ 根据四维评分,按以下判定树确定推荐模式:
82
+
83
+ ```
84
+ 复杂度=低 且 风险=低 且 接口契约影响=无
85
+ → 推荐 vibe(直接编码,无需文档)
86
+
87
+ 复杂度=低/中 且 明确度=高 且 接口契约影响=无
88
+ → 推荐 plan(功能规划,有 proposal+design+tasks)
89
+
90
+ 任意维度满足以下任一:
91
+ - 接口契约影响=有
92
+ - 风险=高
93
+ - 需要可测试的验收标准
94
+ → 推荐 spec(规范驱动,含 delta specs + GIVEN/WHEN/THEN)
95
+
96
+ 以下情况推荐 harness:
97
+ - 明确度=低(需求不清晰,AI 自动分析更可靠)
98
+ - 复杂度=高 且 风险=高
99
+ - 用户希望全自动从需求到部署
100
+ → 推荐 harness(双 Loop 全自动流程)
101
+ ```
102
+
103
+ ### Step 5:展示推荐与对比
104
+
105
+ **输出格式:**
106
+
107
+ ```
108
+ 📊 需求分析结果 — {Story 标题}
109
+ ─────────────────────────────────────────
110
+ 复杂度: {低/中/高} — {一句话理由}
111
+ 风险: {低/中/高} — {一句话理由}
112
+ 需求明确度: {低/中/高} — {一句话理由}
113
+ 接口契约: {无/有} — {一句话理由}
114
+
115
+ 🎯 推荐模式:/modus:{mode}
116
+ 理由:{2-3 句话说明为何这个模式最合适}
117
+
118
+ 📋 其他选项对比:
119
+ plan — {适用场景,以及为何当前需求不优先选它}
120
+ spec — {适用场景,以及为何当前需求不优先选它}
121
+ harness — {适用场景,以及为何当前需求不优先选它}
122
+ vibe — {适用场景,以及为何当前需求不优先选它}
123
+
124
+ 请选择要使用的模式:
125
+ A. /modus:vibe — 直接编码
126
+ B. /modus:plan — 功能规划 ← 推荐
127
+ C. /modus:spec — 规范驱动开发
128
+ D. /modus:harness — 全自动 Harness
129
+ ```
130
+
131
+ ⏸️ **等待用户选择**
132
+
133
+ ### Step 6:二次确认窗口
134
+
135
+ 用户选择模式后,展示参数确认窗口:
136
+
137
+ **若选择 vibe:**
138
+ ```
139
+ 确认参数:
140
+ 任务描述: {从 Story 标题/描述提取的一句话任务描述}
141
+ 涉及业务域: {自动判断的域列表}
142
+
143
+ 直接开始编码?[Y/n]
144
+ ```
145
+
146
+ **若选择 plan:**
147
+ ```
148
+ 确认参数:
149
+ 需求描述: {从 Story 内容生成的 plan prompt}
150
+ 涉及域: {order, payment}
151
+ 是否快速模式(跳过 design.md): [y/N]
152
+
153
+ 确认后将启动 /modus:plan,输入以上描述。[Y/n]
154
+ ```
155
+
156
+ **若选择 spec:**
157
+ ```
158
+ 确认参数:
159
+ 需求描述: {从 Story 内容生成的 spec prompt}
160
+ 涉及域: {order}
161
+ 规格级别: Full(因为涉及接口契约变更)/ Lite(--lite flag)
162
+
163
+ 确认后将启动 /modus:spec,输入以上描述。[Y/n]
164
+ ```
165
+
166
+ **若选择 harness:**
167
+ ```
168
+ 确认参数:
169
+ TAPD Story URL: {原始 URL}
170
+ 将直接透传给 /modus:harness
171
+
172
+ 确认?[Y/n]
173
+ ```
174
+
175
+ ⏸️ **等待用户确认**
176
+
177
+ ### Step 7:启动所选模式
178
+
179
+ 用户确认后,根据选择自动触发对应模式:
180
+
181
+ - **vibe**:以已整理的任务描述调用 `/modus:vibe`,上下文包含 Story 摘要
182
+ - **plan**:以整理好的 prompt 调用 `/modus:plan`,自动跳过 Step 3 的澄清阶段(已通过 auto 确认)
183
+ - **spec**:以整理好的 prompt 调用 `/modus:spec`,携带 Story 验收标准作为 Scenario 参考输入
184
+ - **harness**:直接调用 `/modus:harness {tapd_url}`
185
+
186
+ ---
187
+
188
+ ## 四维评分快速参考卡
189
+
190
+ | 模式 | 适用场景 | 不适合场景 |
191
+ |------|----------|-----------|
192
+ | `vibe` | 单文件改动、低风险 bug fix | 需要文档沉淀的功能 |
193
+ | `plan` | 明确需求、中等复杂度、无接口契约变更 | 需要可测试规格、高风险 |
194
+ | `spec` | 接口变更、高风险、需要 GIVEN/WHEN/THEN 验收 | 简单 bug fix、模糊需求 |
195
+ | `harness` | 模糊需求、高复杂高风险、需要全自动流程 | 紧急小改动 |
196
+
197
+ ---
198
+
199
+ ## 无 TAPD URL 时的处理
200
+
201
+ 若用户直接运行 `/modus:auto`(不带 URL),提示:
202
+
203
+ ```
204
+ 请提供 TAPD Story URL,例如:
205
+ /modus:auto https://tapd.cn/company/stories/view/1234567890
206
+
207
+ 或粘贴 Story 内容(以 ---END--- 结束输入):
208
+ ```
209
+
210
+ 接受手动粘贴的 Story 内容,跳过 MCP 读取,直接进入 Step 3 分析。
@@ -23,6 +23,75 @@ disable: false
23
23
 
24
24
  若 `modus/config.yaml` 不存在,将在 Step 5 创建默认配置。
25
25
 
26
+ ### Step 0.5:扫描已有 AI 工具配置
27
+
28
+ 在扫描业务代码之前,先读取项目中已有的 AI 工具配置文件,将存量规则、上下文和 MCP 配置融入 Modus 知识库,避免重复发明轮子。
29
+
30
+ #### 扫描目标清单
31
+
32
+ 按优先级逐一检查以下路径是否存在:
33
+
34
+ | 工具 | 检查路径 | 提取内容 |
35
+ |------|---------|----------|
36
+ | **Claude Code** | `CLAUDE.md`、`.claude/CLAUDE.md`、`CLAUDE.local.md` | 项目规则、技术栈、构建命令、命名约定 |
37
+ | **Claude Code** | `.claude/rules/*.md`、`.claude/rules/*.mdc` | 路径级别的细粒度规则 |
38
+ | **Claude Code** | `.claude/settings.json` | MCP 服务器配置 |
39
+ | **Claude Code** | `.claude/commands/*.md` | 已有自定义斜杠命令(避免重复生成) |
40
+ | **Cursor** | `.cursor/rules/*.md`、`.cursor/rules/*.mdc` | 项目规则(含 frontmatter `description`/`globs`) |
41
+ | **Cursor** | `.cursor/mcp.json` | MCP 服务器配置 |
42
+ | **Cursor** | `AGENTS.md`(根目录或子目录) | Agent 指令说明 |
43
+ | **CodeBuddy** | `.codebuddy/rules/*.mdc` | 项目规则 |
44
+ | **CodeBuddy** | `.codebuddy/settings.json` | MCP 服务器配置 |
45
+ | **Continue.dev** | `.continue/config.json`、`.continue/config.yaml` | 上下文提供者、模型配置 |
46
+ | **OpenCode** | `AGENT.md`、`.claude-internal/AGENT.md` | 项目 Agent 指令 |
47
+
48
+ #### 提取与融合规则
49
+
50
+ 读取上述文件后,执行以下归类:
51
+
52
+ 1. **项目描述 / 背景**(`context` 字段)
53
+ - 从 `CLAUDE.md` / `AGENTS.md` 的开头段落提取项目一句话描述
54
+ - 若 `modus/config.yaml` 中 `context` 为空,自动填入(需用户确认)
55
+
56
+ 2. **技术栈信息**(`techStack` 字段)
57
+ - 从 `CLAUDE.md` 中寻找构建命令、框架名称等技术栈线索
58
+ - 与代码文件检测结果合并,用于 Step 5 的技术知识 Skill
59
+
60
+ 3. **编码规范 / 团队约定**(→ `modus-team-conventions` Skill)
61
+ - 将各工具中找到的约定规则(命名规范、禁止模式、最佳实践等)汇总
62
+ - 在 Step 4 生成团队约定 Skill 时,把这些规则作为**基础输入**,标注来源(如 `[来源: .cursor/rules/naming.mdc]`)
63
+ - 避免重复:如果规则已在其他 Skill 中描述,仅添加引用
64
+
65
+ 4. **MCP 服务器配置**(→ `modus/config.yaml` `mcpServers` 字段)
66
+ - 若 `modus init` CLI 已自动检测并写入 `mcpServers`,则跳过
67
+ - 否则从 `.claude/settings.json` / `.cursor/mcp.json` 提取,写入 `modus/config.yaml`
68
+
69
+ 5. **已有自定义命令**(仅记录,不重复生成)
70
+ - 列出 `.claude/commands/` 中已有的命令名称
71
+ - 在 `/modus:init` 完成回报中提示用户这些命令已存在
72
+
73
+ #### 向用户展示扫描结果
74
+
75
+ ```
76
+ 🔍 扫描已有 AI 工具配置...
77
+
78
+ ✓ Claude Code — 找到 3 个文件
79
+ CLAUDE.md(项目指令 + 构建命令)
80
+ .claude/rules/java-conventions.mdc(Java 编码规范)
81
+ .claude/settings.json(MCP: tapd, git)
82
+
83
+ ✓ Cursor — 找到 2 个文件
84
+ .cursor/rules/naming.mdc(命名规范)
85
+ .cursor/mcp.json(MCP: tapd)
86
+
87
+ 将把以上规则融入 modus-team-conventions Skill,MCP 配置写入 modus/config.yaml。
88
+ 继续?[Y/n]
89
+ ```
90
+
91
+ 若用户确认,继续 Step 1;若无任何已有配置,直接进入 Step 1。
92
+
93
+ ---
94
+
26
95
  ### Step 1:项目扫描与业务分类
27
96
 
28
97
  启动一个「项目分析 SubAgent」,执行以下操作:
@@ -59,35 +128,149 @@ disable: false
59
128
  - 增加遗漏的业务域
60
129
  - 删除不需要的域
61
130
 
62
- ### Step 3:生成业务 Skill(Layer 2
131
+ ### Step 3:生成业务 Skill(Layer 2)—— 并行执行
63
132
 
64
- 用户确认后,为每个业务域调用「Skills Builder SubAgent」(`modus-harness-00-skills-builder` Skill,模式 A),生成对应的业务 Skill 文件:
133
+ 用户确认后,**同时**为每个业务域启动独立的「Skills Builder SubAgent」(`modus-harness-00-skills-builder` Skill,模式 A),并行生成所有业务 Skill 文件。各域之间完全独立,无需等待彼此完成。
65
134
 
66
135
  **目标路径:** `.codebuddy/skills/modus-biz-{domain}/SKILL.md`
67
136
 
137
+ **并行调度规则:**
138
+
139
+ ```
140
+ 用户确认域列表后,立即并行启动 N 个 SubAgent:
141
+
142
+ SubAgent-1 (order域) ──► 扫描订单相关文件 ──► 生成 modus-biz-order/SKILL.md
143
+ SubAgent-2 (payment域) ──► 扫描支付相关文件 ──► 生成 modus-biz-payment/SKILL.md
144
+ SubAgent-3 (user域) ──► 扫描用户相关文件 ──► 生成 modus-biz-user/SKILL.md
145
+ │ │
146
+ └──────────────── 所有 SubAgent 完成 ──────────┘
147
+
148
+ 进入 Step 4(串行)
149
+ ```
150
+
151
+ **每个 SubAgent 的任务(模式 A 标准流程):**
152
+ 1. 接收域名称 + 代表性文件路径列表(来自 Step 1 的分析结果)
153
+ 2. 深度扫描该域的 Service/Manager/Mapper/Domain/Entity 层文件
154
+ 3. 提取:核心实体、业务规则、API 契约、关键代码模式
155
+ 4. 生成标准格式的 Skill 文件(含 `key_files`、`maturity: draft`)
156
+
157
+ **聚合等待:** 所有 SubAgent 完成后,收集各 SubAgent 的完成状态摘要,在主流程中汇总展示:
158
+
159
+ ```
160
+ ✓ modus-biz-order 已生成(8 个 key_files,5 条业务规则,3 个 API)
161
+ ✓ modus-biz-payment 已生成(6 个 key_files,4 条业务规则,2 个 API)
162
+ ✓ modus-biz-user 已生成(5 个 key_files,3 条业务规则,4 个 API)
163
+ ```
164
+
68
165
  每个 Skill 文件遵循 Business Skill 标准格式(含 maturity/last_referenced/usage_count 字段)。
69
166
 
167
+ ### Step 3.5:多平台同步(Business Skills)
168
+
169
+ Business Skills 全部生成后,读取 `modus/config.yaml` 的 `platforms` 字段,将每个业务 Skill 同步到其他已选平台。
170
+
171
+ **读取 platforms 配置:**
172
+
173
+ ```bash
174
+ # 检查已选平台
175
+ grep -A5 "^platforms:" modus/config.yaml
176
+ ```
177
+
178
+ **各平台同步规则(仅处理 codebuddy 以外的平台):**
179
+
180
+ #### Claude Code(`.claude/agents/modus-biz-{domain}.md`)
181
+
182
+ 对每个业务域,创建 Claude Sub-Agent 定义文件:
183
+
184
+ ```markdown
185
+ ---
186
+ name: modus-biz-{domain}
187
+ description: Business knowledge for the {domain} domain — {核心职责一句话}
188
+ ---
189
+
190
+ {.codebuddy/skills/modus-biz-{domain}/SKILL.md 的完整内容}
191
+ ```
192
+
193
+ #### Cursor(`.cursor/rules/modus-biz-{domain}.mdc`)
194
+
195
+ 对每个业务域,创建 Cursor 规则文件(带 frontmatter):
196
+
197
+ ```markdown
198
+ ---
199
+ description: "Business rules and conventions for the {domain} domain — {核心职责一句话}"
200
+ alwaysApply: false
201
+ ---
202
+
203
+ {.codebuddy/skills/modus-biz-{domain}/SKILL.md 的完整内容}
204
+ ```
205
+
206
+ #### GitHub Copilot(`.github/copilot-instructions.md`)
207
+
208
+ 将每个业务域的 Skill 内容以带标记的段落形式追加或更新(幂等):
209
+
210
+ ```markdown
211
+ <!-- modus:biz-skill:{domain}:start -->
212
+
213
+ ### Business Skill: {domain}
214
+
215
+ {.codebuddy/skills/modus-biz-{domain}/SKILL.md 的完整内容}
216
+
217
+ <!-- modus:biz-skill:{domain}:end -->
218
+ ```
219
+
220
+ **若文件中已存在对应域的标记段落,替换其内容(不重复追加)。**
221
+
222
+ **同步完成输出:**
223
+
224
+ ```
225
+ 📡 多平台同步:
226
+ ✓ Claude .claude/agents/modus-biz-order.md
227
+ ✓ Claude .claude/agents/modus-biz-payment.md
228
+ ✓ Cursor .cursor/rules/modus-biz-order.mdc
229
+ ✓ Cursor .cursor/rules/modus-biz-payment.mdc
230
+ ✓ Copilot .github/copilot-instructions.md(已更新 2 个域段落)
231
+ ```
232
+
233
+ 若 `platforms` 只包含 `codebuddy`(或字段不存在),跳过此步骤。
234
+
235
+ ---
236
+
70
237
  ### Step 4:生成团队约定 Skill(Layer 0-T)
71
238
 
72
239
  调用「Skills Builder SubAgent」(模式 E:团队约定初始化):
73
240
 
74
- 从以下来源提取团队规范:
75
- 1. 项目中已有的 `CONTRIBUTING.md`、`.editorconfig`、`checkstyle.xml`、`pmd.xml` 等规范文件
76
- 2. `modus/config.yaml` 中的 `constitution.hard_rules`
77
- 3. 代码中高频出现的注解模式(如 `@Transactional`、`@DistributedLock` 的用法)
241
+ 从以下来源提取团队规范(**按优先级排列**):
242
+
243
+ 1. **Step 0.5 扫描结果**(最高优先级)
244
+ - 从 `CLAUDE.md` / `AGENTS.md` / `.cursor/rules/` / `.codebuddy/rules/` 提取的编码规范
245
+ - 每条规则注明来源,例如:`[来源: .cursor/rules/naming.mdc]`
246
+ - 若同一规则在多个工具中重复,合并为一条并列出所有来源
247
+
248
+ 2. 项目中已有的 `CONTRIBUTING.md`、`.editorconfig`、`checkstyle.xml`、`pmd.xml` 等规范文件
249
+
250
+ 3. `modus/config.yaml` 中的 `constitution.hard_rules`
251
+
252
+ 4. 代码中高频出现的注解模式(如 `@Transactional`、`@DistributedLock` 的用法)
78
253
 
79
254
  生成文件:`.codebuddy/skills/modus-team-conventions/SKILL.md`
80
255
 
256
+ **注意:** 若 Step 0.5 中已有来自其他工具的规则,在 Skill 文件开头添加来源声明:
257
+ ```markdown
258
+ > 本 Skill 融合了以下 AI 工具的已有配置:Claude Code (CLAUDE.md)、Cursor (.cursor/rules/)
259
+ > 原始文件保持不变,Modus 仅在此处做统一索引。
260
+ ```
261
+
81
262
  ### Step 5:生成技术知识 Skill(Layer 1)
82
263
 
83
- 调用「Skills Builder SubAgent」(模式 E:技术知识初始化),初始化一个空的技术知识骨架:
264
+ 调用「Skills Builder SubAgent」(模式 E:技术知识初始化),初始化技术知识骨架:
84
265
 
85
266
  生成文件:`.codebuddy/skills/modus-tech-wiki/SKILL.md`
86
267
 
87
- 初始内容包含:
88
- - 已发现的技术栈(从 `pom.xml` `build.gradle` 提取)
89
- - 框架版本信息
90
- - 占位符章节(反模式库、架构决策、跨项目经验——待后续工作流积累)
268
+ 初始内容来源(按优先级):
269
+ 1. **Step 0.5 扫描结果中的技术信息**
270
+ - `CLAUDE.md` 中记录的构建命令、测试命令(如 `mvn test`、`npm run test`)
271
+ - `.continue/config.json` 中的模型/上下文提供者配置
272
+ 2. 从构建文件提取的技术栈(`pom.xml` → Spring Boot 版本、`package.json` → 框架版本等)
273
+ 3. 占位符章节(反模式库、架构决策、跨项目经验——待后续工作流积累)
91
274
 
92
275
  ### Step 6:生成知识全景目录(knowledge-catalog.md)
93
276
 
@@ -151,13 +334,24 @@ constitution:
151
334
  ```
152
335
  ✅ Modus 知识库初始化完成
153
336
 
337
+ 已融合的已有 AI 工具配置(若有):
338
+ Claude Code — CLAUDE.md + .claude/rules/ (3 条规则已写入 modus-team-conventions)
339
+ Cursor — .cursor/rules/ (2 条规则已写入 modus-team-conventions)
340
+ MCP 服务器 — tapd (来自 .claude/settings.json) 已写入 modus/config.yaml
341
+
154
342
  生成了 N 个业务 Skill(Layer 2):
155
343
  - .codebuddy/skills/modus-biz-order/SKILL.md [draft]
156
344
  - .codebuddy/skills/modus-biz-payment/SKILL.md [draft]
157
345
  - ...
158
346
 
347
+ 多平台同步(来自 modus/config.yaml platforms 配置):
348
+ - Claude Code → .claude/agents/modus-biz-*.md(N 个域)
349
+ - Cursor → .cursor/rules/modus-biz-*.mdc(N 个域)
350
+ - Copilot → .github/copilot-instructions.md(N 个域段落)
351
+
159
352
  初始化基础 Skill:
160
353
  - .codebuddy/skills/modus-team-conventions/SKILL.md (Layer 0-T) [draft]
354
+ └─ 融合来源:CLAUDE.md, .cursor/rules/, CONTRIBUTING.md, 代码注解模式
161
355
  - .codebuddy/skills/modus-tech-wiki/SKILL.md (Layer 1) [draft]
162
356
 
163
357
  知识目录:
@@ -166,6 +360,9 @@ constitution:
166
360
  💡 建议:填写 modus/config.yaml 中的 constitution 字段,
167
361
  记录项目硬性约束(技术栈、命名规范等),后续所有命令将自动加载。
168
362
 
363
+ 已有自定义命令(不会与 Modus 命令冲突):
364
+ .claude/commands/deploy.md、.claude/commands/review.md(来自 Claude Code)
365
+
169
366
  现在可以使用:
170
367
  /modus:vibe — 氛围编程(自动加载业务上下文)
171
368
  /modus:plan — 功能规划