@chongyan/autospec 1.0.1

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 (243) hide show
  1. package/LICENSE +21 -0
  2. package/README.en.md +472 -0
  3. package/README.md +476 -0
  4. package/bin/autospec.js +3 -0
  5. package/knowledge/README.md +144 -0
  6. package/knowledge/checklists/code.md +182 -0
  7. package/knowledge/checklists/design.md +196 -0
  8. package/knowledge/checklists/release.md +70 -0
  9. package/knowledge/checklists/requirement.md +169 -0
  10. package/knowledge/checklists/test.md +46 -0
  11. package/knowledge/config/README.en.md +44 -0
  12. package/knowledge/config/README.md +44 -0
  13. package/knowledge/config/role-composition.yaml +98 -0
  14. package/knowledge/config/role-extensions.yaml +140 -0
  15. package/knowledge/config/skill-compositions.yaml +142 -0
  16. package/knowledge/config/team-stage.yaml +95 -0
  17. package/knowledge/config/team-tasks.yaml +139 -0
  18. package/knowledge/config/team-triggers.yaml +198 -0
  19. package/knowledge/config/validation-patterns.yaml +137 -0
  20. package/knowledge/domain/README.md +115 -0
  21. package/knowledge/domain/flows/README.md +194 -0
  22. package/knowledge/domain/glossary.md +143 -0
  23. package/knowledge/domain/rules.md +138 -0
  24. package/knowledge/environment/README.en.md +36 -0
  25. package/knowledge/environment/README.md +87 -0
  26. package/knowledge/environment/component-knowledge.md +316 -0
  27. package/knowledge/environment/detection-patterns.yaml +502 -0
  28. package/knowledge/environment/middleware-knowledge.md +237 -0
  29. package/knowledge/environment/template-registry.md +321 -0
  30. package/knowledge/guides/domain-driven-design.md +345 -0
  31. package/knowledge/guides/knowledge-management.md +369 -0
  32. package/knowledge/guides/requirement-engineering.md +329 -0
  33. package/knowledge/guides/stages/ai-effect-evaluator.md +93 -0
  34. package/knowledge/guides/stages/code-implementer.md +205 -0
  35. package/knowledge/guides/stages/code-reviewer.md +111 -0
  36. package/knowledge/guides/stages/consistency-checker.md +177 -0
  37. package/knowledge/guides/stages/design-planner.md +401 -0
  38. package/knowledge/guides/stages/design-reviewer.md +83 -0
  39. package/knowledge/guides/stages/integration-test-runner.md +105 -0
  40. package/knowledge/guides/stages/release-checker.md +205 -0
  41. package/knowledge/guides/stages/requirement-analyzer.md +195 -0
  42. package/knowledge/guides/stages/requirement-reviewer.md +83 -0
  43. package/knowledge/guides/stages/security-reviewer.md +89 -0
  44. package/knowledge/guides/stages/test-context-analyzer.md +250 -0
  45. package/knowledge/guides/stages/test-generator.md +241 -0
  46. package/knowledge/guides/stages/test-planner.md +183 -0
  47. package/knowledge/guides/stages/test-reviewer.md +76 -0
  48. package/knowledge/guides/stages/unit-test-runner.md +83 -0
  49. package/knowledge/guides/support/ai-agent-analyzer.md +362 -0
  50. package/knowledge/guides/support/ai-anomaly-analyzer.md +213 -0
  51. package/knowledge/guides/support/ai-artifact-evaluator.md +192 -0
  52. package/knowledge/guides/support/ai-capability-analyzer.md +193 -0
  53. package/knowledge/guides/support/ai-component-analyzer.md +169 -0
  54. package/knowledge/guides/support/ai-data-validator.md +276 -0
  55. package/knowledge/guides/support/ai-evaluation-planner.md +374 -0
  56. package/knowledge/guides/support/ai-path-evaluator.md +274 -0
  57. package/knowledge/guides/support/ai-pipeline-evaluator.md +219 -0
  58. package/knowledge/guides/support/ai-rag-analyzer.md +339 -0
  59. package/knowledge/guides/support/ai-task-assessor.md +418 -0
  60. package/knowledge/guides/support/ai-test-diagnostics.md +133 -0
  61. package/knowledge/guides/support/complexity-assessor.md +268 -0
  62. package/knowledge/guides/support/component-discovery.md +183 -0
  63. package/knowledge/guides/support/environment-scanner.md +207 -0
  64. package/knowledge/guides/support/environment-validator.md +207 -0
  65. package/knowledge/guides/support/knowledge-generator.md +234 -0
  66. package/knowledge/guides/support/methodology-extractor.md +55 -0
  67. package/knowledge/guides/support/pipeline-protocol.md +438 -0
  68. package/knowledge/guides/support/practice-logger.md +359 -0
  69. package/knowledge/guides/support/scope-inference.md +174 -0
  70. package/knowledge/guides/support/skill-distiller.md +91 -0
  71. package/knowledge/guides/support/skill-updater.md +45 -0
  72. package/knowledge/guides/support/skill-validator.md +72 -0
  73. package/knowledge/guides/support/team-orchestrator.md +323 -0
  74. package/knowledge/guides/support/tech-stack-analyzer.md +139 -0
  75. package/knowledge/guides/support/test-runner.md +254 -0
  76. package/knowledge/guides/system-design.md +352 -0
  77. package/knowledge/organization/ai-native-team.md +318 -0
  78. package/knowledge/organization/team-metrics.md +228 -0
  79. package/knowledge/principles/constitution.md +134 -0
  80. package/knowledge/principles/core-principles.md +368 -0
  81. package/knowledge/principles/design-philosophy.md +877 -0
  82. package/knowledge/principles/evolution.md +553 -0
  83. package/knowledge/process/01-requirement.md +113 -0
  84. package/knowledge/process/02-design.md +123 -0
  85. package/knowledge/process/03-implementation.md +90 -0
  86. package/knowledge/process/04-review.md +80 -0
  87. package/knowledge/process/05-testing.md +90 -0
  88. package/knowledge/process/06-delivery.md +88 -0
  89. package/knowledge/process/README.en.md +38 -0
  90. package/knowledge/process/README.md +48 -0
  91. package/knowledge/process/ai-sdlc.md +475 -0
  92. package/knowledge/process/overview.md +319 -0
  93. package/knowledge/standards/code-review.md +876 -0
  94. package/knowledge/standards/coding-style.md +940 -0
  95. package/knowledge/standards/data-consistency.md +1085 -0
  96. package/knowledge/standards/document-versioning.md +210 -0
  97. package/knowledge/standards/risk-detection.md +186 -0
  98. package/knowledge/templates/ai-evaluation.md +150 -0
  99. package/knowledge/templates/api-design.md +117 -0
  100. package/knowledge/templates/database-design.md +132 -0
  101. package/knowledge/templates/domain-driven-design.md +321 -0
  102. package/knowledge/templates/product-proposal.md +201 -0
  103. package/knowledge/templates/system-design.md +227 -0
  104. package/knowledge/templates/task-breakdown.md +107 -0
  105. package/knowledge/templates/test-case.md +170 -0
  106. package/package.json +53 -0
  107. package/plugins/.claude-plugin/plugin.json +134 -0
  108. package/plugins/agents/roles/ai-engineer.md +129 -0
  109. package/plugins/agents/roles/backend-engineer.md +165 -0
  110. package/plugins/agents/roles/ceo.md +94 -0
  111. package/plugins/agents/roles/data-engineer.md +135 -0
  112. package/plugins/agents/roles/devops-engineer.md +181 -0
  113. package/plugins/agents/roles/frontend-engineer.md +129 -0
  114. package/plugins/agents/roles/product-owner.md +98 -0
  115. package/plugins/agents/roles/quality-engineer.md +129 -0
  116. package/plugins/agents/roles/security-engineer.md +180 -0
  117. package/plugins/agents/roles/tech-lead.md +97 -0
  118. package/plugins/agents/support/blind-comparator.md +88 -0
  119. package/plugins/agents/support/consistency-checker.md +103 -0
  120. package/plugins/agents/support/failure-diagnostician.md +141 -0
  121. package/plugins/agents/support/independent-reviewer.md +80 -0
  122. package/plugins/agents/support/safety-auditor.md +121 -0
  123. package/plugins/agents/support/skill-benchmarker.md +86 -0
  124. package/plugins/agents/support/skill-forger.md +105 -0
  125. package/plugins/agents/support/stage-gate-evaluator.md +121 -0
  126. package/plugins/agents/support/test-coverage-reviewer.md +73 -0
  127. package/plugins/benchmarks/templates/README.md +44 -0
  128. package/plugins/benchmarks/templates/commands/explore-template.yaml +48 -0
  129. package/plugins/benchmarks/templates/pipeline/agile-template.yaml +84 -0
  130. package/plugins/benchmarks/templates/pipeline/waterfall-template.yaml +106 -0
  131. package/plugins/benchmarks/templates/skills/requirement-analyzer-template.yaml +48 -0
  132. package/plugins/commands/README.en.md +96 -0
  133. package/plugins/commands/README.md +96 -0
  134. package/plugins/commands/apply.md +191 -0
  135. package/plugins/commands/archive.md +76 -0
  136. package/plugins/commands/env-export.md +79 -0
  137. package/plugins/commands/env-sync.md +640 -0
  138. package/plugins/commands/env-template.md +223 -0
  139. package/plugins/commands/env-update.md +264 -0
  140. package/plugins/commands/env-validate.md +176 -0
  141. package/plugins/commands/env.md +79 -0
  142. package/plugins/commands/explore.md +76 -0
  143. package/plugins/commands/field-evolve.md +536 -0
  144. package/plugins/commands/memory.md +249 -0
  145. package/plugins/commands/project-evolve.md +821 -0
  146. package/plugins/commands/propose.md +93 -0
  147. package/plugins/commands/review.md +140 -0
  148. package/plugins/commands/run.md +224 -0
  149. package/plugins/commands/status.md +62 -0
  150. package/plugins/commands/validate.md +108 -0
  151. package/plugins/hooks/README.en.md +56 -0
  152. package/plugins/hooks/README.md +56 -0
  153. package/plugins/hooks/ai-project-guard.js +329 -0
  154. package/plugins/hooks/artifact-evaluation-hook.js +237 -0
  155. package/plugins/hooks/constitution-guard.js +211 -0
  156. package/plugins/hooks/environment-autocommit.js +264 -0
  157. package/plugins/hooks/environment-manager.js +778 -0
  158. package/plugins/hooks/execution-tracker.js +354 -0
  159. package/plugins/hooks/frozen-zone-guard.js +140 -0
  160. package/plugins/hooks/layer1-validator.js +423 -0
  161. package/plugins/hooks/lib/artifact-evaluator.js +414 -0
  162. package/plugins/hooks/lib/benchmarks/change-detector.js +390 -0
  163. package/plugins/hooks/lib/benchmarks/evaluator.js +605 -0
  164. package/plugins/hooks/lib/benchmarks/integration-example.js +169 -0
  165. package/plugins/hooks/lib/data-and-ai-detector.js +275 -0
  166. package/plugins/hooks/lib/detection-pattern-loader.js +865 -0
  167. package/plugins/hooks/lib/directory-discovery.js +395 -0
  168. package/plugins/hooks/lib/environment-config-loader.js +341 -0
  169. package/plugins/hooks/lib/environment-detector.js +553 -0
  170. package/plugins/hooks/lib/environment-evolver.js +564 -0
  171. package/plugins/hooks/lib/environment-registry.js +813 -0
  172. package/plugins/hooks/lib/execution-path.js +427 -0
  173. package/plugins/hooks/lib/hook-error-recorder.js +245 -0
  174. package/plugins/hooks/lib/hook-logger.js +538 -0
  175. package/plugins/hooks/lib/hook-runner.js +97 -0
  176. package/plugins/hooks/lib/hook-runner.sh +44 -0
  177. package/plugins/hooks/lib/hook-state-manager.js +480 -0
  178. package/plugins/hooks/lib/memory-extractor.js +377 -0
  179. package/plugins/hooks/lib/memory-manager.js +673 -0
  180. package/plugins/hooks/lib/metrics-analyzer.js +489 -0
  181. package/plugins/hooks/lib/project-evolution/auto-fixer.js +511 -0
  182. package/plugins/hooks/lib/project-evolution/memory-manager.js +346 -0
  183. package/plugins/hooks/lib/project-evolution/pattern-detector.js +476 -0
  184. package/plugins/hooks/lib/project-evolution/semantic-indexer.js +480 -0
  185. package/plugins/hooks/lib/project-structure-detector.js +326 -0
  186. package/plugins/hooks/lib/rollback-tracker.js +346 -0
  187. package/plugins/hooks/lib/source-code-scanner.js +596 -0
  188. package/plugins/hooks/lib/technology-stack-detector.js +374 -0
  189. package/plugins/hooks/lib/test-failure-analyzer.js +375 -0
  190. package/plugins/hooks/lib/test-failure-fixer.js +268 -0
  191. package/plugins/hooks/lib/trace-context.js +277 -0
  192. package/plugins/hooks/lib/validation-patterns.js +415 -0
  193. package/plugins/hooks/memory-sync.js +171 -0
  194. package/plugins/hooks/pipeline-observer.js +413 -0
  195. package/plugins/hooks/scope-sentinel.js +204 -0
  196. package/plugins/hooks/trace-initialization.js +169 -0
  197. package/plugins/memory/templates/code-quality.yaml +149 -0
  198. package/plugins/memory/templates/multi-system.yaml +155 -0
  199. package/plugins/memory/templates/team-habits.yaml +119 -0
  200. package/plugins/memory/templates/testing.yaml +121 -0
  201. package/plugins/skills/README.en.md +47 -0
  202. package/plugins/skills/README.md +104 -0
  203. package/plugins/skills/benchmark-executor/README.md +93 -0
  204. package/plugins/skills/benchmark-executor/SKILL.md +647 -0
  205. package/plugins/skills/benchmark-generator/SKILL.md +349 -0
  206. package/plugins/skills/delivery-stage/SKILL.md +203 -0
  207. package/plugins/skills/design-stage/SKILL.md +216 -0
  208. package/plugins/skills/evolution-process/SKILL.md +291 -0
  209. package/plugins/skills/exploration-phase/SKILL.md +133 -0
  210. package/plugins/skills/implementation-stage/SKILL.md +179 -0
  211. package/plugins/skills/layer1-validation/SKILL.md +79 -0
  212. package/plugins/skills/pending-dashboard/SKILL.md +109 -0
  213. package/plugins/skills/project-evolution/SKILL.md +847 -0
  214. package/plugins/skills/requirement-stage/SKILL.md +183 -0
  215. package/plugins/skills/skill-forge/SKILL.md +223 -0
  216. package/plugins/skills/skill-forge/references/description-guide.md +92 -0
  217. package/plugins/skills/skill-forge/references/quality-rubric.md +104 -0
  218. package/plugins/skills/skill-forge/references/skill-template.md +106 -0
  219. package/plugins/skills/startup-guard/SKILL.md +38 -0
  220. package/plugins/skills/testing-stage/SKILL.md +195 -0
  221. package/scripts/cli/global-init.js +288 -0
  222. package/scripts/cli/global.js +324 -0
  223. package/scripts/cli/index.js +55 -0
  224. package/scripts/cli/init.js +382 -0
  225. package/scripts/cli/list.js +69 -0
  226. package/scripts/cli/org.js +340 -0
  227. package/scripts/cli/update.js +44 -0
  228. package/scripts/config/commands.config.js +145 -0
  229. package/scripts/config/hooks.config.js +197 -0
  230. package/scripts/evolution/evolution-router.js +273 -0
  231. package/scripts/evolution/evolution-signal-collector.js +307 -0
  232. package/scripts/evolution/knowledge-loader.js +346 -0
  233. package/scripts/evolution/marketplace.js +317 -0
  234. package/scripts/evolution/version-manager.js +371 -0
  235. package/scripts/install/agents.js +106 -0
  236. package/scripts/install/commands.js +133 -0
  237. package/scripts/install/constants.js +424 -0
  238. package/scripts/install/hook-logger.js +536 -0
  239. package/scripts/install/hooks.js +110 -0
  240. package/scripts/install/index.js +39 -0
  241. package/scripts/install/skills.js +95 -0
  242. package/scripts/postinstall.js +25 -0
  243. package/scripts/state.js +376 -0
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Memory Sync Hook - 会话结束时同步记忆
3
+ *
4
+ * 触发时机:Stop 事件
5
+ * 功能:
6
+ * 1. 从对话中提取记忆
7
+ * 2. 更新工作记忆
8
+ * 3. 生成会话摘要
9
+ * 4. 触发记忆 GC(如果需要)
10
+ */
11
+
12
+ import path from 'path';
13
+ import { fileURLToPath } from 'url';
14
+ import { extractFromText, writeExtractions, extractSessionSummary, shouldExtract } from './lib/memory-extractor.js';
15
+ import {
16
+ hasGlobalMemory,
17
+ hasProjectMemory,
18
+ initGlobalMemory,
19
+ initProjectMemory,
20
+ updateCurrentContext,
21
+ clearCurrentContext,
22
+ updateMemory
23
+ } from './lib/memory-manager.js';
24
+ import { MEMORY_FILES, MEMORY_SCOPE } from '../scripts/install/constants.js';
25
+
26
+ const __filename = fileURLToPath(import.meta.url);
27
+ const __dirname = path.dirname(__filename);
28
+
29
+ /**
30
+ * 查找项目根目录
31
+ * @returns {string|null} 项目根目录
32
+ */
33
+ function findProjectRoot() {
34
+ let currentDir = process.cwd();
35
+
36
+ for (let i = 0; i < 10; i++) {
37
+ if (path.basename(currentDir) === '.autospec') {
38
+ return path.dirname(currentDir);
39
+ }
40
+
41
+ const autospecDir = path.join(currentDir, '.autospec');
42
+ if (require('fs').existsSync(autospecDir)) {
43
+ return currentDir;
44
+ }
45
+
46
+ const parentDir = path.dirname(currentDir);
47
+ if (parentDir === currentDir) {
48
+ break;
49
+ }
50
+ currentDir = parentDir;
51
+ }
52
+
53
+ return null;
54
+ }
55
+
56
+ /**
57
+ * 记忆同步主函数
58
+ * @param {Object} context - Hook 上下文
59
+ */
60
+ export async function main(context = {}) {
61
+ const projectRoot = findProjectRoot();
62
+
63
+ if (!projectRoot) {
64
+ // 不在 AutoSpec 项目中,静默退出
65
+ return {
66
+ status: 'skipped',
67
+ reason: 'not_in_autospec_project'
68
+ };
69
+ }
70
+
71
+ const results = {
72
+ timestamp: new Date().toISOString(),
73
+ projectRoot,
74
+ actions: []
75
+ };
76
+
77
+ try {
78
+ // 1. 确保记忆系统已初始化
79
+ if (!hasGlobalMemory()) {
80
+ initGlobalMemory();
81
+ results.actions.push({ action: 'init_global_memory', status: 'success' });
82
+ }
83
+
84
+ if (!hasProjectMemory(projectRoot)) {
85
+ initProjectMemory(projectRoot);
86
+ results.actions.push({ action: 'init_project_memory', status: 'success' });
87
+ }
88
+
89
+ // 2. 从对话中提取记忆(如果有对话内容)
90
+ if (context.conversationText || context.messages) {
91
+ const text = context.conversationText ||
92
+ (context.messages || []).map(m => m.content || '').join('\n');
93
+
94
+ if (text && text.length > 100) {
95
+ const extractions = extractFromText(text, context);
96
+
97
+ if (extractions.length > 0) {
98
+ const writeResults = writeExtractions(projectRoot, extractions, {
99
+ autoConfirm: false // 默认需要用户确认
100
+ });
101
+
102
+ results.actions.push({
103
+ action: 'extract_memories',
104
+ status: 'success',
105
+ extracted: extractions.length,
106
+ written: writeResults.success.length,
107
+ pending: writeResults.pending.length,
108
+ failed: writeResults.failed.length
109
+ });
110
+
111
+ // 如果有待确认的记忆,记录到 memory-meta.json
112
+ if (writeResults.pending.length > 0) {
113
+ updateMemory(MEMORY_SCOPE.PROJECT, MEMORY_FILES.MEMORY_META, {
114
+ pendingExtractions: writeResults.pending
115
+ }, projectRoot);
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ // 3. 生成会话摘要(如果有会话信息)
122
+ if (context.sessionInfo) {
123
+ const sessionSummary = extractSessionSummary(projectRoot, context.sessionInfo);
124
+ results.actions.push({
125
+ action: 'session_summary',
126
+ status: 'success',
127
+ sessionId: sessionSummary.id
128
+ });
129
+ }
130
+
131
+ // 4. 更新记忆元数据统计
132
+ updateMemory(MEMORY_SCOPE.PROJECT, MEMORY_FILES.MEMORY_META, {
133
+ lastSessionDate: new Date().toISOString(),
134
+ 'statistics.totalSessions': (prev => (prev || 0) + 1)
135
+ }, projectRoot);
136
+
137
+ // 5. 清理工作记忆(可选)
138
+ if (context.clearWorkingMemory) {
139
+ clearCurrentContext(projectRoot);
140
+ results.actions.push({ action: 'clear_working_memory', status: 'success' });
141
+ }
142
+
143
+ return {
144
+ status: 'success',
145
+ ...results
146
+ };
147
+
148
+ } catch (error) {
149
+ console.error('[AutoSpec memory-sync] 同步失败:', error.message);
150
+ return {
151
+ status: 'error',
152
+ error: error.message,
153
+ ...results
154
+ };
155
+ }
156
+ }
157
+
158
+ // 如果直接运行此脚本
159
+ if (process.argv[1] === __filename) {
160
+ main({
161
+ conversationText: process.env.AUTOSPEC_CONVERSATION || '',
162
+ sessionInfo: process.env.AUTOSPEC_SESSION_INFO ? JSON.parse(process.env.AUTOSPEC_SESSION_INFO) : null
163
+ }).then(result => {
164
+ console.log(JSON.stringify(result, null, 2));
165
+ }).catch(error => {
166
+ console.error(error);
167
+ process.exit(1);
168
+ });
169
+ }
170
+
171
+ export default { main };
@@ -0,0 +1,413 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * AutoSpec Hook: Pipeline Observer
5
+ *
6
+ * 全链路事件采集和分析 Hook
7
+ * - PostToolUse: 采集标准化事件
8
+ * - Stop: 生成评测报告
9
+ *
10
+ * 职责:
11
+ * 1. 采集标准化事件
12
+ * 2. 实时计算指标
13
+ * 3. 检测异常模式
14
+ * 4. Stop 时触发评测报告生成
15
+ */
16
+
17
+ import { createHookLogger, safeJsonParse, handleHookError, readStdin, findProjectRootAsync } from './lib/hook-logger.js';
18
+ import { getState, getMetrics, updateMetrics } from './lib/hook-state-manager.js';
19
+ import { getTraceId, recordEvent } from './lib/trace-context.js';
20
+ import { recordPathEvent, recordTool, recordDecision, PATH_EVENT_TYPES } from './lib/execution-path.js';
21
+ import { calculateFrameworkQualityScore, detectErrorPatterns } from './lib/metrics-analyzer.js';
22
+
23
+ const logger = createHookLogger('pipeline-observer');
24
+
25
+ /**
26
+ * PostToolUse 处理
27
+ */
28
+ async function handlePostToolUse(input, projectRoot) {
29
+ const toolName = input.tool_name;
30
+ const toolInput = input.tool_input || {};
31
+ const response = input.tool_response || {};
32
+
33
+ // 记录工具调用到执行路径
34
+ recordTool(projectRoot, toolName, detectAction(toolName, toolInput));
35
+
36
+ // 采集特定事件
37
+ switch (toolName) {
38
+ case 'AskUserQuestion':
39
+ handleUserQuestion(projectRoot, toolInput, response);
40
+ break;
41
+
42
+ case 'Agent':
43
+ handleAgentCall(projectRoot, toolInput, response);
44
+ break;
45
+
46
+ case 'Bash':
47
+ handleBashCommand(projectRoot, toolInput, response);
48
+ break;
49
+ }
50
+
51
+ // 实时检测异常模式
52
+ checkAnomalies(projectRoot);
53
+ }
54
+
55
+ /**
56
+ * Stop 处理:生成评测报告 + 自动触发一致性检测
57
+ */
58
+ async function handleStop(projectRoot) {
59
+ logger.info('Session ending, generating evaluation report');
60
+
61
+ // 计算质量分数
62
+ const qualityScore = calculateFrameworkQualityScore(projectRoot);
63
+
64
+ // 检测错误模式
65
+ const errorPatterns = detectErrorPatterns(getMetrics(projectRoot, false));
66
+
67
+ // 更新 metrics.json
68
+ const metrics = getMetrics(projectRoot, false);
69
+ metrics.qualityScore = qualityScore;
70
+ metrics.errorPatterns = errorPatterns;
71
+ metrics.pipelineEnd = new Date().toISOString();
72
+
73
+ updateMetrics(projectRoot, metrics);
74
+
75
+ // 记录事件
76
+ const traceId = getTraceId(projectRoot);
77
+ if (traceId) {
78
+ recordEvent(projectRoot, 'pipeline_end', {
79
+ source: 'pipeline-observer',
80
+ action: 'generate_evaluation',
81
+ data: {
82
+ qualityScore: qualityScore.overall,
83
+ errorPatternCount: errorPatterns.length
84
+ }
85
+ });
86
+ }
87
+
88
+ // 自动触发一致性检测(如果有多个产出物)
89
+ const consistencyResult = await autoTriggerConsistencyCheck(projectRoot, metrics);
90
+
91
+ // 输出评测摘要
92
+ outputEvaluationSummary(qualityScore, errorPatterns, consistencyResult);
93
+ }
94
+
95
+ /**
96
+ * 自动触发一致性检测
97
+ */
98
+ async function autoTriggerConsistencyCheck(projectRoot, metrics) {
99
+ const artifacts = metrics?.artifacts || {};
100
+ const artifactPaths = Object.keys(artifacts);
101
+
102
+ // 如果有 2 个以上产出物,触发一致性检测
103
+ if (artifactPaths.length < 2) {
104
+ return null;
105
+ }
106
+
107
+ logger.info('Auto-triggering consistency check', { artifactCount: artifactPaths.length });
108
+
109
+ // 记录一致性检测触发事件
110
+ const traceId = getTraceId(projectRoot);
111
+ if (traceId) {
112
+ recordEvent(projectRoot, 'consistency_check_triggered', {
113
+ source: 'pipeline-observer',
114
+ action: 'auto_consistency_check',
115
+ data: {
116
+ artifactCount: artifactPaths.length,
117
+ artifacts: artifactPaths
118
+ }
119
+ });
120
+ }
121
+
122
+ // 返回一致性检测提示
123
+ return {
124
+ triggered: true,
125
+ artifactCount: artifactPaths.length,
126
+ message: `
127
+ [AutoSpec] 自动触发一致性检测
128
+
129
+ 检测到 ${artifactPaths.length} 个产出物,建议执行一致性分析:
130
+ - 需求→设计 覆盖检查
131
+ - 设计→实现 覆盖检查
132
+ - 术语一致性检查
133
+
134
+ 详细评测请执行: /autospec:evaluate
135
+ `
136
+ };
137
+ }
138
+
139
+ /**
140
+ * 处理用户问题
141
+ */
142
+ function handleUserQuestion(projectRoot, toolInput, response) {
143
+ const questions = toolInput.questions || [];
144
+
145
+ // 记录决策点
146
+ recordDecision(projectRoot, 'human', {
147
+ questionCount: questions.length,
148
+ questionTypes: questions.map(q => q.header || 'unknown')
149
+ });
150
+
151
+ // 记录事件
152
+ const traceId = getTraceId(projectRoot);
153
+ if (traceId) {
154
+ recordEvent(projectRoot, 'human_intervention', {
155
+ source: 'pipeline-observer',
156
+ tool: 'AskUserQuestion',
157
+ action: 'ask_user',
158
+ data: {
159
+ questionCount: questions.length,
160
+ questions: questions.map(q => ({ header: q.header, question: q.question }))
161
+ }
162
+ });
163
+ }
164
+ }
165
+
166
+ /**
167
+ * 处理 Agent 调用
168
+ */
169
+ function handleAgentCall(projectRoot, toolInput, response) {
170
+ const subagentType = toolInput.subagent_type || 'unknown';
171
+
172
+ // 记录决策点(Agent 调用通常是自动决策)
173
+ recordDecision(projectRoot, 'auto', {
174
+ agentType: subagentType
175
+ });
176
+
177
+ // 记录事件
178
+ const traceId = getTraceId(projectRoot);
179
+ if (traceId) {
180
+ const success = !response.error;
181
+ recordEvent(projectRoot, success ? 'agent_success' : 'agent_fail', {
182
+ source: 'pipeline-observer',
183
+ tool: 'Agent',
184
+ action: 'call_agent',
185
+ data: {
186
+ subagentType,
187
+ success
188
+ }
189
+ });
190
+ }
191
+ }
192
+
193
+ /**
194
+ * 处理 Bash 命令
195
+ */
196
+ function handleBashCommand(projectRoot, toolInput, response) {
197
+ const command = toolInput.command || '';
198
+
199
+ // 检测命令类型
200
+ const commandType = detectCommandType(command);
201
+
202
+ if (commandType) {
203
+ const traceId = getTraceId(projectRoot);
204
+ if (traceId) {
205
+ const success = response.exitCode === 0;
206
+ recordEvent(projectRoot, success ? 'command_success' : 'command_fail', {
207
+ source: 'pipeline-observer',
208
+ tool: 'Bash',
209
+ action: commandType,
210
+ data: {
211
+ command: command.substring(0, 100),
212
+ exitCode: response.exitCode
213
+ }
214
+ });
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * 检测工具动作
221
+ */
222
+ function detectAction(toolName, toolInput) {
223
+ switch (toolName) {
224
+ case 'Read':
225
+ return 'read_file';
226
+ case 'Write':
227
+ return 'write_file';
228
+ case 'Edit':
229
+ return 'edit_file';
230
+ case 'Bash':
231
+ return 'run_command';
232
+ case 'Agent':
233
+ return `call_${toolInput.subagent_type || 'agent'}`;
234
+ case 'AskUserQuestion':
235
+ return 'ask_user';
236
+ default:
237
+ return 'unknown';
238
+ }
239
+ }
240
+
241
+ /**
242
+ * 检测命令类型
243
+ */
244
+ function detectCommandType(command) {
245
+ if (/npm\s+(test|run\s+test)/.test(command)) return 'test';
246
+ if (/npm\s+(run\s+)?build/.test(command)) return 'build';
247
+ if (/npm\s+run\s+lint/.test(command)) return 'lint';
248
+ if (/pytest|jest|mocha/.test(command)) return 'test';
249
+ if (/tsc|typescript/.test(command)) return 'typecheck';
250
+ return null;
251
+ }
252
+
253
+ /**
254
+ * 检测异常模式
255
+ */
256
+ function checkAnomalies(projectRoot) {
257
+ const metrics = getMetrics(projectRoot, true);
258
+
259
+ // 检测连续失败
260
+ const recentErrors = (metrics?.totals?.errors || []).slice(-5);
261
+ if (recentErrors.length >= 3) {
262
+ const timeWindow = 5 * 60 * 1000; // 5 分钟
263
+ const now = Date.now();
264
+ const recentFailures = recentErrors.filter(e =>
265
+ now - new Date(e.time).getTime() < timeWindow
266
+ );
267
+
268
+ if (recentFailures.length >= 3) {
269
+ // 触发自动诊断建议
270
+ outputAnomalyWarning('consecutive_failures', {
271
+ count: recentFailures.length,
272
+ timeWindow: '5min',
273
+ suggestion: '短时间内多次失败,建议暂停检查环境配置',
274
+ requiredAction: '建议暂停当前流程,执行诊断后再继续',
275
+ diagnosisCommand: '读取 framework/skills/support/ai-anomaly-analyzer.md 获取诊断建议'
276
+ });
277
+ }
278
+ }
279
+
280
+ // 检测 Layer1 连续失败
281
+ const layer1Fails = (metrics?.totals?.errors || []).filter(e => e.type === 'layer1_fail');
282
+ if (layer1Fails.length >= 3) {
283
+ outputAnomalyWarning('layer1_consecutive_failures', {
284
+ count: layer1Fails.length,
285
+ suggestion: 'Layer1 验证连续失败,可能存在系统性问题',
286
+ requiredAction: '建议检查:1) 测试依赖是否就绪 2) 代码实现是否符合设计 3) 环境配置是否正确'
287
+ });
288
+ }
289
+ }
290
+
291
+ /**
292
+ * 输出异常告警
293
+ */
294
+ function outputAnomalyWarning(type, details) {
295
+ const message = `
296
+ [AutoSpec Anomaly Warning] 检测到异常模式
297
+
298
+ 类型: ${type}
299
+ 详情: ${JSON.stringify(details, null, 2)}
300
+
301
+ 建议: ${details.suggestion}
302
+ ${details.requiredAction ? `\n**建议操作**: ${details.requiredAction}` : ''}
303
+ ${details.diagnosisCommand ? `\n诊断: ${details.diagnosisCommand}` : ''}
304
+ `;
305
+
306
+ process.stdout.write(JSON.stringify({
307
+ hookSpecificOutput: {
308
+ hookEventName: 'PostToolUse',
309
+ additionalContext: message
310
+ }
311
+ }));
312
+ }
313
+
314
+ /**
315
+ * 输出评测摘要
316
+ */
317
+ function outputEvaluationSummary(qualityScore, errorPatterns, consistencyResult = null) {
318
+ const gradeEmoji = {
319
+ 'A': '🟢',
320
+ 'B': '🟡',
321
+ 'C': '🟠',
322
+ 'D': '🔴',
323
+ 'F': '⚫'
324
+ };
325
+
326
+ const emoji = gradeEmoji[qualityScore.grade] || '⚪';
327
+
328
+ let summary = `
329
+ [AutoSpec Evaluation Summary] ${emoji}
330
+
331
+ ## 质量评分
332
+ - 综合评分: ${qualityScore.overall}/100 (${qualityScore.grade})
333
+ - 过程指标: ${qualityScore.breakdown.process.score}/100
334
+ - 结果指标: ${qualityScore.breakdown.result.score}/100
335
+ - 路径指标: ${qualityScore.breakdown.path.score}/100
336
+
337
+ ## 错误模式
338
+ ${errorPatterns.length > 0
339
+ ? errorPatterns.map(p => `- [${p.severity}] ${p.suggestion}`).join('\n')
340
+ : '- 无显著错误模式'
341
+ }
342
+
343
+ ${consistencyResult?.message || ''}
344
+ `;
345
+
346
+ // 低分时输出强制建议
347
+ if (qualityScore.overall < 70) {
348
+ summary += `
349
+ ## ⚠️ 质量告警
350
+
351
+ 综合评分低于 70 分,建议:
352
+ 1. 执行 /autospec:evaluate 获取详细评测报告
353
+ 2. 检查流程执行情况,优化低分维度
354
+ 3. 如有进化触发,执行 /autospec:evolve
355
+ `;
356
+ } else {
357
+ summary += `
358
+ ## 建议
359
+ 流程执行良好,继续保持。
360
+
361
+ 详细报告请执行: /autospec:evaluate
362
+ `;
363
+ }
364
+
365
+ process.stdout.write(JSON.stringify({
366
+ hookSpecificOutput: {
367
+ hookEventName: 'Stop',
368
+ additionalContext: summary
369
+ }
370
+ }));
371
+ }
372
+
373
+ async function main() {
374
+ let input;
375
+ try {
376
+ const rawInput = await readStdin(1000);
377
+ input = safeJsonParse(rawInput, null, 'hook input');
378
+
379
+ if (!input) {
380
+ logger.debug('Empty or invalid input, skipping');
381
+ process.exit(0);
382
+ }
383
+ } catch (err) {
384
+ logger.error('Failed to parse input', { error: err.message });
385
+ process.exit(0);
386
+ }
387
+
388
+ const cwd = input.cwd || process.cwd();
389
+ const projectRoot = await findProjectRootAsync(cwd);
390
+
391
+ if (!projectRoot) {
392
+ logger.debug('No .autospec directory found, skipping');
393
+ process.exit(0);
394
+ }
395
+
396
+ const eventName = input.event_name;
397
+
398
+ if (eventName === 'PostToolUse') {
399
+ await handlePostToolUse(input, projectRoot);
400
+ } else if (eventName === 'Stop') {
401
+ await handleStop(projectRoot);
402
+ }
403
+
404
+ process.exit(0);
405
+ }
406
+
407
+ main().catch((err) => {
408
+ const result = handleHookError('pipeline-observer', err, {
409
+ eventName: 'PostToolUse'
410
+ });
411
+ process.stdout.write(JSON.stringify(result.hookSpecificOutput));
412
+ process.exit(0);
413
+ });