autosnippet 2.11.0 → 2.13.0

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 +111 -37
  2. package/bin/cli.js +144 -0
  3. package/config/default.json +5 -0
  4. package/dashboard/dist/assets/{icons-D4IWpDIk.js → icons-nJfgG6f_.js} +97 -102
  5. package/dashboard/dist/assets/index-BkFYJ3vq.js +121 -0
  6. package/dashboard/dist/assets/index-DqK6Cy2z.css +1 -0
  7. package/dashboard/dist/index.html +3 -3
  8. package/lib/core/AstAnalyzer.js +179 -0
  9. package/lib/external/mcp/handlers/bootstrap/pipeline/BootstrapSnapshot.js +541 -0
  10. package/lib/external/mcp/handlers/bootstrap/pipeline/EpisodicMemory.js +694 -0
  11. package/lib/external/mcp/handlers/bootstrap/pipeline/IncrementalBootstrap.js +220 -0
  12. package/lib/external/mcp/handlers/bootstrap/pipeline/ToolResultCache.js +189 -0
  13. package/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +454 -9
  14. package/lib/external/mcp/handlers/bootstrap.js +93 -0
  15. package/lib/external/mcp/handlers/guard.js +7 -1
  16. package/lib/external/mcp/handlers/search.js +3 -3
  17. package/lib/external/mcp/handlers/structure.js +5 -5
  18. package/lib/external/mcp/tools.js +2 -2
  19. package/lib/http/api-spec.js +0 -383
  20. package/lib/http/routes/guardRules.js +27 -0
  21. package/lib/infrastructure/database/migrations/001_initial_schema.js +315 -0
  22. package/lib/injection/ServiceContainer.js +40 -0
  23. package/lib/service/automation/handlers/GuardHandler.js +11 -0
  24. package/lib/service/automation/handlers/SearchHandler.js +4 -4
  25. package/lib/service/chat/AnalystAgent.js +65 -3
  26. package/lib/service/chat/ChatAgent.js +115 -23
  27. package/lib/service/chat/EpisodicConsolidator.js +343 -0
  28. package/lib/service/chat/ProducerAgent.js +2 -0
  29. package/lib/service/chat/ProjectSemanticMemory.js +865 -0
  30. package/lib/service/chat/WorkingMemory.js +316 -0
  31. package/lib/service/chat/tools.js +234 -0
  32. package/lib/service/guard/ComplianceReporter.js +335 -0
  33. package/lib/service/guard/GuardCheckEngine.js +171 -16
  34. package/lib/service/guard/GuardFeedbackLoop.js +125 -0
  35. package/lib/service/guard/GuardService.js +15 -3
  36. package/lib/service/guard/RuleLearner.js +116 -1
  37. package/lib/service/guard/SourceFileCollector.js +94 -0
  38. package/lib/service/guard/ViolationsStore.js +59 -1
  39. package/lib/service/knowledge/CodeEntityGraph.js +787 -0
  40. package/lib/service/search/SearchEngine.js +8 -8
  41. package/package.json +1 -1
  42. package/templates/guard-ci.yml +80 -0
  43. package/templates/pre-commit-guard.sh +33 -0
  44. package/dashboard/dist/assets/index-CWBNcF9z.css +0 -1
  45. package/dashboard/dist/assets/index-DHtzhbuG.js +0 -120
  46. package/lib/infrastructure/database/migrations/005_unified_schema_reset.js +0 -181
  47. package/lib/infrastructure/database/migrations/006_add_kind_column.js +0 -41
  48. package/lib/infrastructure/database/migrations/007_guard_violations_table.js +0 -38
  49. package/lib/infrastructure/database/migrations/008_add_source_file_column.js +0 -59
  50. package/lib/infrastructure/database/migrations/009_recipes_v2_columns.js +0 -44
  51. package/lib/infrastructure/database/migrations/010_create_audit_and_sessions.js +0 -58
  52. package/lib/infrastructure/database/migrations/011_recipe_i18n_columns.js +0 -61
  53. package/lib/infrastructure/database/migrations/012_add_trigger_column.js +0 -55
  54. package/lib/infrastructure/database/migrations/013_create_knowledge_edges.js +0 -80
  55. package/lib/infrastructure/database/migrations/014_add_candidate_indexes.js +0 -14
  56. package/lib/infrastructure/database/migrations/015_create_token_usage.js +0 -27
  57. package/lib/infrastructure/database/migrations/016_unified_knowledge_entries.js +0 -395
  58. package/lib/infrastructure/database/migrations/017_camelcase_knowledge_entries.js +0 -107
package/README.md CHANGED
@@ -31,13 +31,15 @@ AI 编码助手生成的代码往往脱离项目上下文——不知道团队
31
31
 
32
32
  | 概念 | 说明 |
33
33
  |------|------|
34
- | **Recipe** | 知识库的基本单元——一段代码模式 + 使用说明 + 元数据,存储在 SQLite 中,可导出为 Markdown 到 `AutoSnippet/recipes/` |
34
+ | **Recipe** | 知识库的基本单元——一段代码模式 + 使用说明 + 元数据,以 Markdown 文件(`AutoSnippet/recipes/*.md`)为 Source of Truth,SQLite 作为检索缓存 |
35
35
  | **Candidate** | 待审核的候选知识——来自 AI 扫描、手动提交、剪贴板或 Bootstrap 冷启动,经 Dashboard 人工审核后晋升为 Recipe |
36
- | **Dashboard** | Web 管理后台(`asd ui`),10 个功能视图:Recipes / Candidates / AI Chat / SPM Explorer / 知识图谱 / 依赖图 / Guard / Skills / Xcode 模拟器 / Help |
36
+ | **Dashboard** | Web 管理后台(`asd ui`),10+ 功能视图:Recipes / Candidates / Knowledge / AI Chat / SPM Explorer / 知识图谱 / 依赖图 / Guard / Skills / Xcode 模拟器 / Help |
37
37
  | **Guard** | 代码审查引擎——基于知识库中的规则对代码做合规检查,支持文件 / Target / 项目三级范围 |
38
38
  | **Skills** | 13 个 Cursor Agent 技能包——覆盖候选生成、冷启动、Guard 审计、意图路由、生命周期管理等场景 |
39
- | **Bootstrap** | 冷启动引擎——自动扫描 SPM Target + AST 分析,9 维度启发式提取代码模式,AI 精炼后生成 Candidate |
40
- | **ChatAgent** | Agent 协作对话系统(Analyst + Producer),支持项目感知、信心信号、组合工具链和跨对话轻量记忆 |
39
+ | **Bootstrap** | 冷启动引擎——自动扫描 SPM Target + AST 分析,9 维度启发式提取代码模式,AI 精炼后生成 Candidate;支持增量模式(IncrementalBootstrap),文件变更检测 + 受影响维度重跑 |
40
+ | **Agent Memory** | 四层记忆架构——WorkingMemory(会话级)→ EpisodicMemory(跨维度共享)→ ProjectSemanticMemory(项目级永久语义记忆)→ ToolResultCache(工具结果去重),支撑 Bootstrap 和 ChatAgent 的跨对话知识积累 |
41
+ | **ChatAgent** | 多 Agent 协作对话系统(Analyst + Producer),支持项目感知、信心信号、组合工具链和跨对话记忆 |
42
+ | **CodeEntityGraph** | 代码实体关系图谱——基于 AST 解析构建 class / protocol / category / module 间的继承、遵循、依赖、数据流等关系,供 Bootstrap 和搜索使用 |
41
43
 
42
44
  ## 快速开始
43
45
 
@@ -63,36 +65,102 @@ asd status # 自检项目根、AI Provider、索引、Dashboard
63
65
 
64
66
  ## 工作流
65
67
 
66
- ### 知识沉淀闭环
68
+ ### 端到端使用流程
69
+
70
+ 从零开始到知识库持续运转的完整路径——以 Cursor 为例:
71
+
72
+ ```
73
+ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
74
+ │ ① 初始化 │──→│ ② 冷启动 │──→│ ③ 逐Target │──→│ ④ 审核发布 │──→│ ⑤ 注入 IDE │
75
+ │ asd setup │ │ Bootstrap │ │ 扫描 │ │ Dashboard │ │ Cursor │
76
+ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ └──────┬──────┘
77
+
78
+ ┌───────────────────────────────────────────────────────────────────────┘
79
+
80
+ ┌─────────────┐ ┌─────────────┐
81
+ │ ⑥ AI 按 │──→│ ⑦ 新模式 │──→ 回到 ③
82
+ │ 规范生成 │ │ 再沉淀 │
83
+ └─────────────┘ └─────────────┘
84
+ ```
85
+
86
+ **① 初始化项目**
87
+
88
+ ```bash
89
+ cd /path/to/your-project
90
+ asd setup # 创建 AutoSnippet/ 目录、数据库、配置文件
91
+ asd install:full # 安装 Cursor Skills (13个) + MCP 配置 + Cursor Rules
92
+ asd ui # 启动 Dashboard + API 服务 + 文件监听
93
+ ```
94
+
95
+ 完成后,你的项目目录下会生成 `.cursor/mcp.json`、`.cursor/skills/`、`.cursor/rules/` 等集成文件,Cursor 已经可以通过 MCP 与 AutoSnippet 通信。
96
+
97
+ **② 冷启动——全局扫描建立基线**
98
+
99
+ 在 Cursor 中用自然语言触发冷启动:
100
+
101
+ ```
102
+ 你:「对项目做一次全量冷启动,提取所有代码模式」
103
+ ```
104
+
105
+ Bootstrap 引擎自动完成:SPM Target 发现 → 文件收集 → AST 结构分析 → 9 维度启发式扫描(架构 / 命名 / 网络 / 数据流 / 错误处理等) → Analyst Agent 深度分析 → Producer Agent 格式化提交。
106
+
107
+ 冷启动结束后,Dashboard Candidates 页面会出现数十条候选知识条目。
108
+
109
+ **③ 逐 Target 精细扫描**
110
+
111
+ 冷启动覆盖全局,但每个 Target 的独特模式需要针对性提取:
67
112
 
68
113
  ```
69
- ┌─────────────────────────────────────────────────────────────┐
70
- │ │
71
- │ ① 扫描提取 ② 人工审核 │
72
- │ Cursor AI 扫描 Target ──→ Candidates ──→ Recipe 入库 │
73
- │ asd ais <Target> Dashboard │
74
- │ Bootstrap 冷启动 / 剪贴板 │
75
- │ │
76
- │ ③ AI 按规范生成 ④ 持续沉淀 │
77
- │ Cursor/Copilot 检索 Recipe ──→ 生成代码 ──→ 好代码再入库 │
78
- │ MCP 工具 / Xcode Snippet │
79
- │ │
80
- └─────────────────────────────────────────────────────────────┘
114
+ 你:「扫描 NetworkModule 这个 Target,把里面的请求封装模式提取出来」
115
+ 你:「分析 UIComponents Target 的自定义控件实现」
81
116
  ```
82
117
 
83
- ### 三种使用方式
118
+ Cursor 调用 `get_targets` → `get_target_files` → 逐文件 AI 分析 → `submit_knowledge_batch`,将发现的代码模式作为 Candidate 提交到知识库。你可以逐个 Target 推进,每个 Target 的扫描结果会独立进入审核队列。
119
+
120
+ **④ 审核发布——人工把关质量**
121
+
122
+ 打开 Dashboard(`asd ui`),进入 **Candidates** 页面:
123
+
124
+ - 候选按置信度排序,高信心的排在前面
125
+ - 点击候选卡片展开详情:查看代码片段、AI 分析理由、来源文件
126
+ - **接受** → 候选晋升为 Recipe,进入活跃知识库
127
+ - **编辑后接受** → 审核时可修改标题、描述、代码、标签
128
+ - **拒绝** → 低质量或重复的候选直接归档
129
+
130
+ 批量操作:一键接受所有高信心候选,或一键拒绝低质量条目。
131
+
132
+ **⑤ 注入 Cursor——知识即规则**
84
133
 
85
- **① Cursor AI(推荐)**:自然语言驱动,Cursor 通过 13 个 Skills + 38 个 MCP 工具与知识库交互。
134
+ Recipe 发布后,Cursor 立即可以通过三种通道获取知识:
135
+
136
+ | 通道 | 机制 | 时效 |
137
+ |------|------|------|
138
+ | **MCP 工具检索** | Cursor 通过 `autosnippet_search` 等 38 个工具实时查询知识库 | 实时 |
139
+ | **Cursor Rules** | `asd upgrade` 将 Recipe 导出为 `.cursor/rules/autosnippet-*.mdc` 文件 | 手动触发 |
140
+ | **Agent Skills** | 13 个 Skill 文档引导 Cursor 在正确场景自动调用知识库 | 常驻 |
141
+
142
+ **⑥ AI 按规范生成代码**
143
+
144
+ 当你在 Cursor 中编写代码时,AI 会自动检索知识库:
86
145
 
87
146
  ```
88
- 用户:「扫描 NetworkModule 这个 Target,提取最佳实践」
89
- Cursor → get_targetsget_target_files 逐文件提取 submit_knowledge_batch
90
- Dashboard Candidates 页面审核 → 保存为 Recipe
147
+ 你:「写一个网络请求方法,获取用户信息」
148
+ Cursor → 检索知识库命中 Recipe: "Network Layer Pattern"
149
+ 按团队封装的 NetworkManager 生成代码,而非裸调 URLSession
91
150
  ```
92
151
 
93
- **② Dashboard Web UI**:可视化管理一切——Recipe 编辑、Candidate 审核、AI Chat 对话、知识图谱、SPM 探索、Guard 审查、冷启动向导。
152
+ Guard 规则也在同步工作——如果生成的代码违反了知识库中的规则(如 `kind=rule` 的条目),会实时提醒和纠正。
153
+
154
+ **⑦ 持续沉淀——知识库越用越好**
94
155
 
95
- **③ 命令行 CLI**:`asd` 命令覆盖全部操作,适合自动化和脚本集成。
156
+ 日常开发中发现新的代码模式或团队约定?随时沉淀:
157
+
158
+ - 在 Cursor 中:`「把这段 error handling 模式提取为知识库条目」`
159
+ - 在 Xcode 中:代码注释写 `// as:create` 然后 `⌘S`
160
+ - 在 Dashboard 中:AI Chat 对话式提交
161
+ - 通过剪贴板:复制代码后自动检测并建议入库
162
+
163
+ 知识库形成飞轮:**代码沉淀 → Recipe 增长 → AI 生成质量提升 → 团队效率提高 → 更多代码模式沉淀**。
96
164
 
97
165
  ## Dashboard
98
166
 
@@ -100,13 +168,14 @@ Cursor → get_targets → get_target_files → 逐文件提取 → submit_knowl
100
168
 
101
169
  ![Dashboard](./resources/ASImage02.png)
102
170
 
103
- **10 个功能视图**:
171
+ **功能视图**:
104
172
 
105
173
  | 视图 | 说明 |
106
174
  |------|------|
107
175
  | **Recipes** | 浏览、编辑、发布、弃用知识条目;详情抽屉支持 Markdown 编辑与关联关系管理 |
108
176
  | **Candidates** | 审核 AI / 手动提交的候选,一键入库或批量操作,支持 AI 润色 |
109
- | **AI Chat** | ChatAgent 智能对话(Analyst 分析 + Producer 生产),项目感知 + 跨对话记忆 |
177
+ | **Knowledge** | 统一知识条目浏览(V3 格式),双列卡片布局,代码预览 + 详情抽屉 |
178
+ | **AI Chat** | ChatAgent 智能对话(Analyst 分析 + Producer 生产),项目感知 + 四层记忆架构 |
110
179
  | **SPM Explorer** | SPM Target 浏览与扫描,候选 vs Recipe 对比抽屉,头文件编辑 |
111
180
  | **Dep Graph** | 依赖关系图可视化 |
112
181
  | **Knowledge Graph** | Recipe 关联关系的知识图谱可视化(依赖 / 扩展 / 冲突等),AI 自动发现关系,按 category 分组 |
@@ -123,9 +192,9 @@ Cursor → get_targets → get_target_files → 逐文件提取 → submit_knowl
123
192
 
124
193
  AutoSnippet 为 Cursor 提供完整的 MCP + Skills 集成:
125
194
 
126
- - **38 个 MCP 工具**:搜索(4 种模式)、Guard 检查、候选提交 / 校验 / 查重、知识图谱查询、Bootstrap 冷启动、Skills 管理等
195
+ - **38 个 MCP 工具**:搜索(4 种模式)、Guard 检查、候选提交 / 校验 / 查重、知识图谱查询、Bootstrap 冷启动、Skills 管理、知识生命周期等
127
196
  - **13 个 Agent Skills**:`autosnippet-candidates`、`autosnippet-guard`、`autosnippet-coldstart`、`autosnippet-intent` 等,引导 AI 正确使用工具
128
- - **写操作 Gateway 保护**:9 个写操作经过权限 / 宪法 / 审计三重检查
197
+ - **写操作 Gateway 保护**:11 个写操作经过权限 / 宪法 / 审计三重检查
129
198
 
130
199
  ```bash
131
200
  asd install:cursor-skill --mcp # 安装 Skills + MCP 配置
@@ -178,13 +247,13 @@ asd install:vscode-copilot # 配置 MCP 和 Copilot 指令
178
247
  | **系统** | `health`、`capabilities` |
179
248
  | **搜索** | `search`(统合入口)、`context_search`(4 层漏斗)、`keyword_search`、`semantic_search` |
180
249
  | **Recipe 浏览** | `list_recipes`、`get_recipe`、`list_rules`、`patterns`、`list_facts`、`recipe_insights`、`confirm_usage` |
181
- | **候选管理** | `validate_candidate`、`check_duplicate`、`submit_knowledge`、`submit_knowledge_batch`、`submit_knowledge_batch`、`enrich_candidates` |
250
+ | **候选管理** | `validate_candidate`、`check_duplicate`、`submit_knowledge`、`submit_knowledge_batch`、`enrich_candidates` |
182
251
  | **知识图谱** | `graph_query`、`graph_impact`、`graph_path`、`graph_stats` |
183
252
  | **项目结构** | `get_targets`、`get_target_files`、`get_target_metadata` |
184
253
  | **Guard** | `guard_check`、`guard_audit_files`、`scan_project` |
185
254
  | **冷启动** | `bootstrap_knowledge`、`bootstrap_refine` |
186
255
  | **Skills** | `list_skills`、`load_skill`、`create_skill`、`delete_skill`、`update_skill`、`suggest_skills` |
187
- | **治理** | `compliance_report` |
256
+ | **知识管理** | `knowledge_lifecycle`、`compliance_report` |
188
257
 
189
258
  ## 配置
190
259
 
@@ -237,18 +306,23 @@ your-project/
237
306
  │ AutoSnippet Core │
238
307
  │ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
239
308
  │ │ Gateway │ │ ChatAgent│ │ Bootstrap│ │ Dashboard │ │
240
- │ │ (权限/ │ │ (Dual │ │ (SPM + │ │ (React 19 +│ │
241
- │ │ 宪法/ │ │ Agent + │ │ AST + │ │ Vite 6 + │ │
242
- │ │ 审计) │ │ Memory) │ │ AI) │ │ Tailwind) │ │
309
+ │ │ (权限/ │ │ (Dual │ │ (Incremen│ │ (React 19 +│ │
310
+ │ │ 宪法/ │ │ Agent + │ │ tal + │ │ Vite 6 + │ │
311
+ │ │ 审计) │ │ Memory) │ │ AST+AI) │ │ Tailwind) │ │
243
312
  │ └──────────┘ └──────────┘ └──────────┘ └─────────────┘ │
244
313
  │ ┌────────────────────────────────────────────────────┐ │
245
- │ │ 13 Services: Recipe Candidate │ Guard │ Search │
314
+ │ │ Agent Memory (4-Tier): │ │
315
+ │ │ WorkingMemory → EpisodicMemory → │ │
316
+ │ │ ProjectSemanticMemory → ToolResultCache │ │
317
+ │ └────────────────────────────────────────────────────┘ │
318
+ │ ┌────────────────────────────────────────────────────┐ │
319
+ │ │ 14 Services: Recipe │ Candidate │ Guard │ Search │ │
246
320
  │ │ Knowledge Graph │ SPM │ Bootstrap │ Chat │ Skills │ │
247
- │ │ Quality │ Context │ Automation │ Snippet │ │
321
+ │ │ Quality │ Context │ Automation │ Snippet Cursor │
248
322
  │ └────────────────────────────────────────────────────┘ │
249
323
  │ ┌────────────────────────────────────────────────────┐ │
250
324
  │ │ Core: Gateway │ Constitution │ Permission │ AST │ │
251
- │ │ Session │ Capability │ │
325
+ │ │ Session │ Capability CodeEntityGraph │
252
326
  │ └────────────────────────────────────────────────────┘ │
253
327
  │ ┌────────────────────────────────────────────────────┐ │
254
328
  │ │ Storage: SQLite (better-sqlite3) + 向量索引 │ │
@@ -267,7 +341,7 @@ your-project/
267
341
  | **前端** | React 19 + TypeScript 5 + Vite 6 + Tailwind CSS 4 |
268
342
  | **AI** | Gemini / OpenAI / Claude(通过 AiProvider 抽象层) |
269
343
  | **AST** | Tree-sitter(Swift / ObjC) |
270
- | **搜索** | 4 层检索管线:InvertedIndex → CoarseRanker → MultiSignalRanker → RetrievalFunnel |
344
+ | **搜索** | 5 层检索管线:InvertedIndex → Semantic Rerank → CoarseRanker (E-E-A-T) → MultiSignalRanker → RetrievalFunnel |
271
345
  | **实时通信** | WebSocket(Socket.IO),Dashboard 实时更新 |
272
346
  | **动画** | Framer Motion |
273
347
  | **代码高亮** | Prism.js + react-syntax-highlighter |
package/bin/cli.js CHANGED
@@ -221,6 +221,150 @@ program
221
221
  }
222
222
  });
223
223
 
224
+ // ─────────────────────────────────────────────────────
225
+ // guard:ci 命令
226
+ // ─────────────────────────────────────────────────────
227
+ program
228
+ .command('guard:ci [path]')
229
+ .description('CI/CD 模式运行全项目 Guard 检查')
230
+ .option('--fail-on-error', '有 error 级违规时 exit 1', true)
231
+ .option('--fail-on-warning', '超过 warning 阈值时 exit 2')
232
+ .option('--max-warnings <n>', 'warning 阈值', '20')
233
+ .option('--report <format>', '报告格式: json | text | markdown', 'text')
234
+ .option('--output <file>', '报告输出文件')
235
+ .option('--min-score <n>', 'Quality Gate 最低分', '70')
236
+ .option('--max-files <n>', '最大扫描文件数', '500')
237
+ .action(async (scanPath, opts) => {
238
+ try {
239
+ const projectRoot = resolve(scanPath || '.');
240
+ const { bootstrap, container } = await initContainer({ projectRoot });
241
+ const reporter = container.get('complianceReporter');
242
+
243
+ const report = await reporter.generate(projectRoot, {
244
+ qualityGate: {
245
+ maxErrors: 0,
246
+ maxWarnings: parseInt(opts.maxWarnings, 10),
247
+ minScore: parseInt(opts.minScore, 10),
248
+ },
249
+ maxFiles: parseInt(opts.maxFiles, 10),
250
+ });
251
+
252
+ // 输出报告
253
+ if (opts.report === 'json') {
254
+ const output = JSON.stringify(report, null, 2);
255
+ if (opts.output) {
256
+ const { writeFileSync } = await import('fs');
257
+ writeFileSync(opts.output, output, 'utf8');
258
+ console.log(`Report written to ${opts.output}`);
259
+ } else {
260
+ console.log(output);
261
+ }
262
+ } else {
263
+ reporter.printReport(report, { format: opts.report });
264
+ }
265
+
266
+ // 如果也要写文件(非 JSON 格式)
267
+ if (opts.output && opts.report !== 'json') {
268
+ const { writeFileSync } = await import('fs');
269
+ writeFileSync(opts.output, JSON.stringify(report, null, 2), 'utf8');
270
+ console.log(`Report data written to ${opts.output}`);
271
+ }
272
+
273
+ await bootstrap.shutdown();
274
+
275
+ // Exit code
276
+ if (report.qualityGate.status === 'FAIL') {
277
+ process.exit(report.summary.errors > 0 ? 1 : 2);
278
+ }
279
+ process.exit(0);
280
+ } catch (err) {
281
+ console.error('Error:', err.message);
282
+ if (process.env.ASD_DEBUG === '1') console.error(err.stack);
283
+ process.exit(1);
284
+ }
285
+ });
286
+
287
+ // ─────────────────────────────────────────────────────
288
+ // guard:staged 命令
289
+ // ─────────────────────────────────────────────────────
290
+ program
291
+ .command('guard:staged')
292
+ .description('检查 git staged 文件')
293
+ .option('--fail-on-error', '有 error 时 exit 1', true)
294
+ .option('--json', '以 JSON 格式输出')
295
+ .action(async (opts) => {
296
+ try {
297
+ const { execSync } = await import('child_process');
298
+
299
+ // 获取 staged 文件列表
300
+ let stagedFiles;
301
+ try {
302
+ stagedFiles = execSync('git diff --cached --name-only --diff-filter=ACM', { encoding: 'utf8' })
303
+ .trim().split('\n').filter(Boolean);
304
+ } catch (err) {
305
+ console.error('❌ 无法获取 git staged 文件(是否在 git 仓库中?)');
306
+ process.exit(1);
307
+ }
308
+
309
+ if (stagedFiles.length === 0) {
310
+ console.log('✅ No staged files');
311
+ process.exit(0);
312
+ }
313
+
314
+ // 过滤源文件
315
+ const { SOURCE_EXTS } = await import('../lib/service/guard/SourceFileCollector.js');
316
+ const { extname: _extname } = await import('path');
317
+ const sourceFiles = stagedFiles.filter(f => SOURCE_EXTS.has(_extname(f).toLowerCase()));
318
+
319
+ if (sourceFiles.length === 0) {
320
+ console.log('✅ No source files in staged changes');
321
+ process.exit(0);
322
+ }
323
+
324
+ const { bootstrap, container } = await initContainer();
325
+ const engine = container.get('guardCheckEngine');
326
+ const { detectLanguage } = await import('../lib/service/guard/GuardCheckEngine.js');
327
+
328
+ // 读取文件内容并检查
329
+ const files = [];
330
+ for (const f of sourceFiles) {
331
+ const filePath = resolve(f);
332
+ if (existsSync(filePath)) {
333
+ files.push({ path: filePath, content: readFileSync(filePath, 'utf8') });
334
+ }
335
+ }
336
+
337
+ const result = engine.auditFiles(files, { scope: 'file' });
338
+ const { summary } = result;
339
+
340
+ if (opts.json) {
341
+ console.log(JSON.stringify(result, null, 2));
342
+ } else if (summary.totalViolations === 0) {
343
+ console.log(`✅ ${summary.filesChecked} staged files passed Guard check`);
344
+ } else {
345
+ console.log(`\n🛡️ Guard check on ${summary.filesChecked} staged files:`);
346
+ console.log(` ${summary.totalErrors} errors, ${summary.totalViolations - summary.totalErrors} warnings\n`);
347
+
348
+ const filesWithIssues = result.files.filter(f => f.summary.total > 0);
349
+ for (const file of filesWithIssues.slice(0, 10)) {
350
+ console.log(` 📄 ${basename(file.filePath)} (${file.summary.errors}E / ${file.summary.warnings}W)`);
351
+ for (const v of file.violations.slice(0, 5)) {
352
+ const icon = v.severity === 'error' ? '❌' : '⚠️';
353
+ console.log(` ${icon} L${v.line} [${v.ruleId}] ${v.message}`);
354
+ }
355
+ if (file.violations.length > 5) console.log(` ... ${file.violations.length - 5} more`);
356
+ }
357
+ }
358
+
359
+ await bootstrap.shutdown();
360
+ process.exit(summary.totalErrors > 0 ? 1 : 0);
361
+ } catch (err) {
362
+ console.error('Error:', err.message);
363
+ if (process.env.ASD_DEBUG === '1') console.error(err.stack);
364
+ process.exit(1);
365
+ }
366
+ });
367
+
224
368
  // ─────────────────────────────────────────────────────
225
369
  // watch 命令
226
370
  // ─────────────────────────────────────────────────────
@@ -47,5 +47,10 @@
47
47
  "enabled": true,
48
48
  "dimensions": 1536,
49
49
  "indexPath": "./data/vector-index"
50
+ },
51
+ "qualityGate": {
52
+ "maxErrors": 0,
53
+ "maxWarnings": 20,
54
+ "minScore": 70
50
55
  }
51
56
  }