@chongyan/autospec 1.0.1 → 1.0.2

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 (283) hide show
  1. package/LICENSE +21 -21
  2. package/README.en.md +447 -321
  3. package/README.md +418 -286
  4. package/knowledge/01-principles/00-principles-hierarchy.md +247 -0
  5. package/knowledge/01-principles/01-first-principles.md +241 -0
  6. package/knowledge/01-principles/02-strategic-principles.md +286 -0
  7. package/knowledge/01-principles/03-tactical-principles.md +385 -0
  8. package/knowledge/01-principles/04-operational-principles.md +275 -0
  9. package/knowledge/01-principles/05-domain-principles.md +539 -0
  10. package/knowledge/01-principles/06-methodology-principles.md +281 -0
  11. package/knowledge/01-principles/07-cognitive-principles.md +277 -0
  12. package/knowledge/01-principles/08-auto-fix-principles.md +320 -0
  13. package/knowledge/01-principles/09-constitution.md +220 -0
  14. package/knowledge/{principles/evolution.md → 01-principles/10-evolution-mechanism.md} +160 -14
  15. package/knowledge/01-principles/README.en.md +385 -0
  16. package/knowledge/01-principles/README.md +385 -0
  17. package/knowledge/{process/overview.md → 02-process/00-overview.md} +90 -5
  18. package/knowledge/02-process/README.en.md +143 -0
  19. package/knowledge/02-process/README.md +186 -0
  20. package/knowledge/{guides/support/pipeline-protocol.md → 03-guides/00-pipeline-protocol.md} +10 -10
  21. package/knowledge/{guides/support/team-orchestrator.md → 03-guides/01-team-orchestrator.md} +53 -8
  22. package/knowledge/{guides/stages/requirement-analyzer.md → 03-guides/02-analyze-requirement.md} +3 -3
  23. package/knowledge/{guides/stages/ai-effect-evaluator.md → 03-guides/08-evaluate-ai-effect.md} +14 -7
  24. package/knowledge/{guides/support/skill-distiller.md → 03-guides/19-distill-skill.md} +3 -3
  25. package/knowledge/{guides/support/skill-updater.md → 03-guides/20-update-skill.md} +1 -1
  26. package/knowledge/{guides/support/methodology-extractor.md → 03-guides/22-extract-methodology.md} +2 -2
  27. package/knowledge/{guides/support/complexity-assessor.md → 03-guides/24-assess-complexity.md} +6 -4
  28. package/knowledge/{guides/support/tech-stack-analyzer.md → 03-guides/26-analyze-tech-stack.md} +1 -1
  29. package/knowledge/{guides/domain-driven-design.md → 03-guides/42-apply-ddd.md} +1 -1
  30. package/knowledge/{process/ai-sdlc.md → 03-guides/43-run-ai-sdlc.md} +1 -1
  31. package/knowledge/{guides/knowledge-management.md → 03-guides/44-manage-knowledge.md} +4 -4
  32. package/knowledge/03-guides/README.en.md +212 -0
  33. package/knowledge/03-guides/README.md +212 -0
  34. package/knowledge/{checklists/requirement.md → 04-checklists/00-requirement.md} +1 -1
  35. package/knowledge/{checklists/design.md → 04-checklists/01-design.md} +1 -1
  36. package/knowledge/{checklists/code.md → 04-checklists/02-code.md} +16 -1
  37. package/knowledge/{checklists/release.md → 04-checklists/04-release.md} +1 -1
  38. package/knowledge/04-checklists/README.en.md +119 -0
  39. package/knowledge/04-checklists/README.md +123 -0
  40. package/knowledge/{config/validation-patterns.yaml → 05-config/00-validation-patterns.yaml} +1 -1
  41. package/knowledge/{config/team-tasks.yaml → 05-config/02-team-tasks.yaml} +2 -2
  42. package/knowledge/05-config/03-role-composition.yaml +346 -0
  43. package/knowledge/{config/skill-compositions.yaml → 05-config/05-skill-compositions.yaml} +24 -24
  44. package/knowledge/05-config/README.en.md +54 -0
  45. package/knowledge/05-config/README.md +132 -0
  46. package/knowledge/06-environment/00-template-registry.md +310 -0
  47. package/knowledge/06-environment/01-detection-patterns.yaml +1692 -0
  48. package/knowledge/{environment → 06-environment}/README.en.md +4 -0
  49. package/knowledge/{environment → 06-environment}/README.md +66 -25
  50. package/knowledge/{standards/coding-style.md → 07-standards/00-coding-style.md} +123 -4
  51. package/knowledge/{standards/code-review.md → 07-standards/01-code-review.md} +3 -3
  52. package/knowledge/{standards/data-consistency.md → 07-standards/02-data-consistency.md} +1 -1
  53. package/knowledge/{standards/document-versioning.md → 07-standards/03-document-versioning.md} +1 -1
  54. package/knowledge/{standards/risk-detection.md → 07-standards/04-risk-detection.md} +5 -5
  55. package/knowledge/07-standards/README.en.md +119 -0
  56. package/knowledge/07-standards/README.md +123 -0
  57. package/knowledge/08-organization/00-vision-mission.md +113 -0
  58. package/knowledge/{organization/ai-native-team.md → 08-organization/01-ai-native-culture.md} +1 -1
  59. package/knowledge/{organization/team-metrics.md → 08-organization/02-team-metrics.md} +1 -1
  60. package/knowledge/08-organization/03-committee-structure.md +54 -0
  61. package/knowledge/08-organization/04-governance-metrics.md +55 -0
  62. package/knowledge/08-organization/05-improvement-process.md +71 -0
  63. package/knowledge/08-organization/README.en.md +165 -0
  64. package/knowledge/08-organization/README.md +165 -0
  65. package/knowledge/09-templates/00-requirement-proposal.md +344 -0
  66. package/knowledge/09-templates/01-architecture-design.md +494 -0
  67. package/knowledge/09-templates/02-api-design.md +408 -0
  68. package/knowledge/09-templates/03-database-design.md +313 -0
  69. package/knowledge/09-templates/04-product-design.md +237 -0
  70. package/knowledge/09-templates/05-domain-business.md +388 -0
  71. package/knowledge/09-templates/06-test-design.md +268 -0
  72. package/knowledge/09-templates/07-evaluation-design.md +372 -0
  73. package/knowledge/09-templates/08-component-knowledge.md +272 -0
  74. package/knowledge/09-templates/09-best-practices.md +218 -0
  75. package/knowledge/{environment/middleware-knowledge.md → 09-templates/10-middleware-knowledge.md} +106 -1
  76. package/knowledge/09-templates/README.en.md +222 -0
  77. package/knowledge/09-templates/README.md +216 -0
  78. package/knowledge/README.en.md +372 -0
  79. package/knowledge/README.md +354 -99
  80. package/package.json +1 -1
  81. package/plugins/.claude-plugin/plugin.json +460 -81
  82. package/plugins/agents/roles/ceo.md +1 -1
  83. package/plugins/agents/roles/product-owner.md +1 -1
  84. package/plugins/agents/roles/tech-lead.md +1 -1
  85. package/plugins/agents/support/consistency-checker.md +36 -3
  86. package/plugins/agents/support/monitoring-agent.md +215 -0
  87. package/plugins/agents/support/safety-auditor.md +2 -2
  88. package/plugins/agents/support/stage-gate-evaluator.md +95 -11
  89. package/plugins/agents/support/test-coverage-reviewer.md +1 -1
  90. package/plugins/benchmarks/templates/README.md +165 -13
  91. package/plugins/benchmarks/templates/commands/apply-template.yaml +108 -0
  92. package/plugins/benchmarks/templates/commands/archive-template.yaml +65 -0
  93. package/plugins/benchmarks/templates/commands/env-export-template.yaml +64 -0
  94. package/plugins/benchmarks/templates/commands/env-sync-template.yaml +104 -0
  95. package/plugins/benchmarks/templates/commands/env-template-template.yaml +96 -0
  96. package/plugins/benchmarks/templates/commands/env-template.yaml +58 -0
  97. package/plugins/benchmarks/templates/commands/env-update-template.yaml +110 -0
  98. package/plugins/benchmarks/templates/commands/env-validate-template.yaml +95 -0
  99. package/plugins/benchmarks/templates/commands/field-evolve-template.yaml +104 -0
  100. package/plugins/benchmarks/templates/commands/project-evolve-template.yaml +104 -0
  101. package/plugins/benchmarks/templates/commands/propose-template.yaml +88 -0
  102. package/plugins/benchmarks/templates/commands/review-template.yaml +124 -0
  103. package/plugins/benchmarks/templates/commands/run-template.yaml +127 -0
  104. package/plugins/benchmarks/templates/commands/test-template.yaml +149 -0
  105. package/plugins/benchmarks/templates/pipeline/experiment-template.yaml +92 -0
  106. package/plugins/benchmarks/templates/pipeline/hotfix-template.yaml +81 -0
  107. package/plugins/benchmarks/templates/skills/agile-iteration-template.yaml +78 -0
  108. package/plugins/benchmarks/templates/skills/benchmark-executor-template.yaml +114 -0
  109. package/plugins/benchmarks/templates/skills/benchmark-generator-template.yaml +52 -0
  110. package/plugins/benchmarks/templates/skills/delivery-stage-template.yaml +130 -0
  111. package/plugins/benchmarks/templates/skills/design-stage-template.yaml +131 -0
  112. package/plugins/benchmarks/templates/skills/experiment-iteration-template.yaml +60 -0
  113. package/plugins/benchmarks/templates/skills/exploration-phase-template.yaml +114 -0
  114. package/plugins/benchmarks/templates/skills/field-evolve-analyzer-template.yaml +51 -0
  115. package/plugins/benchmarks/templates/skills/field-evolve-distiller-template.yaml +34 -0
  116. package/plugins/benchmarks/templates/skills/field-evolve-executor-template.yaml +50 -0
  117. package/plugins/benchmarks/templates/skills/field-evolve-fixer-template.yaml +52 -0
  118. package/plugins/benchmarks/templates/skills/field-evolve-learner-template.yaml +33 -0
  119. package/plugins/benchmarks/templates/skills/field-evolve-scanner-template.yaml +74 -0
  120. package/plugins/benchmarks/templates/skills/field-evolve-template.yaml +71 -0
  121. package/plugins/benchmarks/templates/skills/field-evolve-verifier-template.yaml +51 -0
  122. package/plugins/benchmarks/templates/skills/hotfix-iteration-template.yaml +54 -0
  123. package/plugins/benchmarks/templates/skills/implementation-stage-template.yaml +127 -0
  124. package/plugins/benchmarks/templates/skills/layer1-validation-template.yaml +121 -0
  125. package/plugins/benchmarks/templates/skills/project-evolve-analyzer-template.yaml +51 -0
  126. package/plugins/benchmarks/templates/skills/project-evolve-fixer-template.yaml +52 -0
  127. package/plugins/benchmarks/templates/skills/project-evolve-generator-template.yaml +34 -0
  128. package/plugins/benchmarks/templates/skills/project-evolve-learner-template.yaml +50 -0
  129. package/plugins/benchmarks/templates/skills/project-evolve-reviewer-template.yaml +50 -0
  130. package/plugins/benchmarks/templates/skills/project-evolve-scanner-template.yaml +75 -0
  131. package/plugins/benchmarks/templates/skills/project-evolve-template.yaml +72 -0
  132. package/plugins/benchmarks/templates/skills/project-evolve-verifier-template.yaml +51 -0
  133. package/plugins/benchmarks/templates/skills/skill-forge-template.yaml +117 -0
  134. package/plugins/benchmarks/templates/skills/startup-guard-template.yaml +103 -0
  135. package/plugins/benchmarks/templates/skills/testing-stage-template.yaml +146 -0
  136. package/plugins/benchmarks/templates/skills/waterfall-iteration-template.yaml +55 -0
  137. package/plugins/commands/README.en.md +2 -2
  138. package/plugins/commands/README.md +2 -2
  139. package/plugins/commands/apply.md +102 -16
  140. package/plugins/commands/archive.md +60 -4
  141. package/plugins/commands/env-sync.md +1047 -406
  142. package/plugins/commands/env-template.md +11 -135
  143. package/plugins/commands/env-update.md +1 -1
  144. package/plugins/commands/env-validate.md +3 -3
  145. package/plugins/commands/explore.md +118 -1
  146. package/plugins/commands/field-evolve.md +51 -175
  147. package/plugins/commands/project-evolve.md +167 -68
  148. package/plugins/commands/propose.md +97 -6
  149. package/plugins/commands/review.md +5 -5
  150. package/plugins/commands/run.md +841 -13
  151. package/plugins/commands/status.md +138 -17
  152. package/plugins/commands/test.md +389 -0
  153. package/plugins/hooks/constitution-guard.js +1 -1
  154. package/plugins/hooks/environment-autocommit.js +366 -24
  155. package/plugins/hooks/environment-manager.js +3 -2
  156. package/plugins/hooks/execution-tracker.js +109 -4
  157. package/plugins/hooks/layer1-validator.js +117 -1
  158. package/plugins/hooks/lib/auto-fix-loop.js +605 -0
  159. package/plugins/hooks/lib/environment-config-loader.js +11 -7
  160. package/plugins/hooks/lib/hook-state-manager.js +98 -0
  161. package/plugins/hooks/lib/memory-extractor.js +27 -5
  162. package/plugins/hooks/lib/memory-manager.js +1 -1
  163. package/plugins/hooks/lib/test-auto-fix.test.js +194 -0
  164. package/plugins/hooks/monitoring-trigger.js +467 -0
  165. package/plugins/skills/README.en.md +15 -3
  166. package/plugins/skills/README.md +21 -11
  167. package/plugins/skills/agile-iteration/SKILL.md +187 -0
  168. package/plugins/skills/delivery-stage/SKILL.md +133 -12
  169. package/plugins/skills/design-stage/SKILL.md +103 -12
  170. package/plugins/skills/experiment-evaluator/SKILL.md +271 -0
  171. package/plugins/skills/experiment-iteration/SKILL.md +154 -0
  172. package/plugins/skills/exploration-phase/SKILL.md +93 -10
  173. package/plugins/skills/field-evolve-analyzer/SKILL.md +65 -0
  174. package/plugins/skills/field-evolve-distiller/SKILL.md +66 -0
  175. package/plugins/skills/field-evolve-executor/SKILL.md +94 -0
  176. package/plugins/skills/field-evolve-executor/executor.js +342 -0
  177. package/plugins/skills/field-evolve-fixer/SKILL.md +69 -0
  178. package/plugins/skills/field-evolve-learner/SKILL.md +65 -0
  179. package/plugins/skills/field-evolve-scanner/SKILL.md +87 -0
  180. package/plugins/skills/field-evolve-scanner/scripts/fallback-scanner.js +288 -0
  181. package/plugins/skills/field-evolve-verifier/SKILL.md +64 -0
  182. package/plugins/skills/hotfix-iteration/SKILL.md +279 -0
  183. package/plugins/skills/implementation-stage/SKILL.md +156 -15
  184. package/plugins/skills/layer1-validation/SKILL.md +1 -1
  185. package/plugins/skills/pending-dashboard/SKILL.md +9 -8
  186. package/plugins/skills/project-evolve-analyzer/SKILL.md +95 -0
  187. package/plugins/skills/project-evolve-fixer/SKILL.md +99 -0
  188. package/plugins/skills/project-evolve-generator/SKILL.md +149 -0
  189. package/plugins/skills/project-evolve-learner/SKILL.md +103 -0
  190. package/plugins/skills/project-evolve-reviewer/SKILL.md +104 -0
  191. package/plugins/skills/project-evolve-scanner/SKILL.md +95 -0
  192. package/plugins/skills/project-evolve-scanner/scripts/dependency-reuse-checker.js +395 -0
  193. package/plugins/skills/project-evolve-scanner/scripts/subsystem-coverage.js +315 -0
  194. package/plugins/skills/project-evolve-verifier/SKILL.md +105 -0
  195. package/plugins/skills/requirement-stage/SKILL.md +47 -13
  196. package/plugins/skills/skill-forge/SKILL.md +2 -2
  197. package/plugins/skills/testing-stage/SKILL.md +583 -8
  198. package/plugins/skills/waterfall-iteration/SKILL.md +115 -0
  199. package/scripts/cli/index.js +1 -1
  200. package/scripts/cli/init.js +30 -4
  201. package/scripts/cli/list.js +3 -2
  202. package/scripts/config/commands.config.js +8 -8
  203. package/scripts/config/hooks.config.js +1 -1
  204. package/scripts/install/constants.js +204 -165
  205. package/scripts/state.js +210 -1
  206. package/knowledge/config/README.en.md +0 -44
  207. package/knowledge/config/README.md +0 -44
  208. package/knowledge/config/role-composition.yaml +0 -98
  209. package/knowledge/config/team-triggers.yaml +0 -198
  210. package/knowledge/domain/README.md +0 -115
  211. package/knowledge/domain/flows/README.md +0 -194
  212. package/knowledge/domain/glossary.md +0 -143
  213. package/knowledge/domain/rules.md +0 -138
  214. package/knowledge/environment/component-knowledge.md +0 -316
  215. package/knowledge/environment/detection-patterns.yaml +0 -502
  216. package/knowledge/environment/template-registry.md +0 -321
  217. package/knowledge/guides/requirement-engineering.md +0 -329
  218. package/knowledge/guides/system-design.md +0 -352
  219. package/knowledge/principles/constitution.md +0 -134
  220. package/knowledge/principles/core-principles.md +0 -368
  221. package/knowledge/principles/design-philosophy.md +0 -877
  222. package/knowledge/process/README.en.md +0 -38
  223. package/knowledge/process/README.md +0 -48
  224. package/knowledge/templates/ai-evaluation.md +0 -150
  225. package/knowledge/templates/api-design.md +0 -117
  226. package/knowledge/templates/database-design.md +0 -132
  227. package/knowledge/templates/domain-driven-design.md +0 -321
  228. package/knowledge/templates/product-proposal.md +0 -201
  229. package/knowledge/templates/system-design.md +0 -227
  230. package/knowledge/templates/task-breakdown.md +0 -107
  231. package/knowledge/templates/test-case.md +0 -170
  232. package/plugins/commands/validate.md +0 -108
  233. package/plugins/skills/benchmark-executor/README.md +0 -93
  234. package/plugins/skills/evolution-process/SKILL.md +0 -291
  235. package/plugins/skills/project-evolution/SKILL.md +0 -847
  236. package/scripts/evolution/evolution-router.js +0 -273
  237. package/scripts/evolution/evolution-signal-collector.js +0 -307
  238. package/scripts/evolution/knowledge-loader.js +0 -346
  239. package/scripts/evolution/marketplace.js +0 -317
  240. package/scripts/evolution/version-manager.js +0 -371
  241. /package/knowledge/{process → 02-process}/01-requirement.md +0 -0
  242. /package/knowledge/{process → 02-process}/02-design.md +0 -0
  243. /package/knowledge/{process → 02-process}/03-implementation.md +0 -0
  244. /package/knowledge/{process → 02-process}/04-review.md +0 -0
  245. /package/knowledge/{process → 02-process}/05-testing.md +0 -0
  246. /package/knowledge/{process → 02-process}/06-delivery.md +0 -0
  247. /package/knowledge/{guides/stages/design-planner.md → 03-guides/03-design-solution.md} +0 -0
  248. /package/knowledge/{guides/stages/code-implementer.md → 03-guides/04-implement-code.md} +0 -0
  249. /package/knowledge/{guides/stages/test-planner.md → 03-guides/05-plan-testing.md} +0 -0
  250. /package/knowledge/{guides/stages/test-generator.md → 03-guides/06-generate-tests.md} +0 -0
  251. /package/knowledge/{guides/stages/release-checker.md → 03-guides/07-check-release.md} +0 -0
  252. /package/knowledge/{guides/stages/requirement-reviewer.md → 03-guides/09-review-requirement.md} +0 -0
  253. /package/knowledge/{guides/stages/design-reviewer.md → 03-guides/10-review-design.md} +0 -0
  254. /package/knowledge/{guides/stages/code-reviewer.md → 03-guides/11-review-code.md} +0 -0
  255. /package/knowledge/{guides/stages/test-reviewer.md → 03-guides/12-review-testing.md} +0 -0
  256. /package/knowledge/{guides/stages/security-reviewer.md → 03-guides/13-audit-security.md} +0 -0
  257. /package/knowledge/{guides/stages/consistency-checker.md → 03-guides/14-check-consistency.md} +0 -0
  258. /package/knowledge/{guides/stages/unit-test-runner.md → 03-guides/15-run-unit-tests.md} +0 -0
  259. /package/knowledge/{guides/stages/integration-test-runner.md → 03-guides/16-run-integration-tests.md} +0 -0
  260. /package/knowledge/{guides/stages/test-context-analyzer.md → 03-guides/17-analyze-test-context.md} +0 -0
  261. /package/knowledge/{guides/support/practice-logger.md → 03-guides/18-log-practice.md} +0 -0
  262. /package/knowledge/{guides/support/skill-validator.md → 03-guides/21-validate-skill.md} +0 -0
  263. /package/knowledge/{guides/support/scope-inference.md → 03-guides/23-infer-scope.md} +0 -0
  264. /package/knowledge/{guides/support/component-discovery.md → 03-guides/25-discover-component.md} +0 -0
  265. /package/knowledge/{guides/support/environment-scanner.md → 03-guides/27-scan-environment.md} +0 -0
  266. /package/knowledge/{guides/support/environment-validator.md → 03-guides/28-validate-environment.md} +0 -0
  267. /package/knowledge/{guides/support/knowledge-generator.md → 03-guides/29-generate-knowledge.md} +0 -0
  268. /package/knowledge/{guides/support/ai-capability-analyzer.md → 03-guides/30-analyze-ai-capability.md} +0 -0
  269. /package/knowledge/{guides/support/ai-component-analyzer.md → 03-guides/31-analyze-ai-component.md} +0 -0
  270. /package/knowledge/{guides/support/ai-agent-analyzer.md → 03-guides/32-analyze-ai-agent.md} +0 -0
  271. /package/knowledge/{guides/support/ai-rag-analyzer.md → 03-guides/33-analyze-ai-rag.md} +0 -0
  272. /package/knowledge/{guides/support/ai-task-assessor.md → 03-guides/34-assess-ai-task.md} +0 -0
  273. /package/knowledge/{guides/support/ai-pipeline-evaluator.md → 03-guides/35-evaluate-ai-pipeline.md} +0 -0
  274. /package/knowledge/{guides/support/ai-artifact-evaluator.md → 03-guides/36-evaluate-ai-artifact.md} +0 -0
  275. /package/knowledge/{guides/support/ai-evaluation-planner.md → 03-guides/37-plan-ai-evaluation.md} +0 -0
  276. /package/knowledge/{guides/support/ai-path-evaluator.md → 03-guides/38-evaluate-ai-path.md} +0 -0
  277. /package/knowledge/{guides/support/ai-data-validator.md → 03-guides/39-validate-ai-data.md} +0 -0
  278. /package/knowledge/{guides/support/ai-anomaly-analyzer.md → 03-guides/40-detect-ai-anomaly.md} +0 -0
  279. /package/knowledge/{guides/support/ai-test-diagnostics.md → 03-guides/41-diagnose-ai-test.md} +0 -0
  280. /package/knowledge/{guides/support/test-runner.md → 03-guides/45-test-runner.md} +0 -0
  281. /package/knowledge/{checklists/test.md → 04-checklists/03-test.md} +0 -0
  282. /package/knowledge/{config/team-stage.yaml → 05-config/01-team-stage.yaml} +0 -0
  283. /package/knowledge/{config/role-extensions.yaml → 05-config/04-role-extensions.yaml} +0 -0
@@ -3,12 +3,14 @@
3
3
  /**
4
4
  * AutoSpec Hook: Environment Autocommit
5
5
  *
6
- * 环境知识自动提交 Hook
6
+ * 环境知识自动提交 Hook(智能决策版)
7
7
  * 触发时机:Stop 事件
8
- * 功能:
9
- * 1. 检测 .autospec/environment/ 目录的变化
10
- * 2. 自动执行 git add + commit
11
- * 3. 可配置是否自动 push
8
+ *
9
+ * 智能决策机制:
10
+ * 1. 变更分类评估:纯新增/配置更新/文档更新 自动提交;删除/敏感字段 需确认
11
+ * 2. 安全检查:文件大小异常/敏感信息泄露/格式验证
12
+ * 3. 版本管理:本地提交自动执行;推送远端默认关闭;冲突检测
13
+ * 4. 决策报告:生成提交/跳过/需确认的决策报告
12
14
  */
13
15
 
14
16
  import fs from 'fs';
@@ -17,6 +19,32 @@ import { createHookLogger, readStdin, findProjectRootAsync } from './lib/hook-lo
17
19
 
18
20
  const logger = createHookLogger('environment-autocommit');
19
21
 
22
+ // 敏感字段模式(需要确认)
23
+ const SENSITIVE_PATTERNS = [
24
+ /password/i,
25
+ /secret/i,
26
+ /api[_-]?key/i,
27
+ /token/i,
28
+ /private[_-]?key/i,
29
+ /credential/i,
30
+ /auth/i,
31
+ /encrypt/i,
32
+ /salt/i,
33
+ /hash/i
34
+ ];
35
+
36
+ // 配置文件模式(高安全度)
37
+ const CONFIG_PATTERNS = [
38
+ /port/i,
39
+ /host/i,
40
+ /endpoint/i,
41
+ /version/i,
42
+ /timeout/i,
43
+ /retry/i,
44
+ /pool/i,
45
+ /connection/i
46
+ ];
47
+
20
48
  /**
21
49
  * 检查是否为 git 仓库
22
50
  */
@@ -24,6 +52,22 @@ function isGitRepo(dir) {
24
52
  return fs.existsSync(path.join(dir, '.git'));
25
53
  }
26
54
 
55
+ /**
56
+ * 检测是否有冲突
57
+ */
58
+ function hasConflicts(repoDir) {
59
+ const { execSync } = require('child_process');
60
+ try {
61
+ const status = execSync('git status --porcelain', {
62
+ cwd: repoDir,
63
+ encoding: 'utf-8'
64
+ });
65
+ return status.split('\n').some(line => line.startsWith('UU') || line.startsWith('AA') || line.startsWith('DD'));
66
+ } catch (e) {
67
+ return false;
68
+ }
69
+ }
70
+
27
71
  /**
28
72
  * 获取 git 状态
29
73
  */
@@ -41,6 +85,210 @@ function getGitStatus(repoDir) {
41
85
  }
42
86
  }
43
87
 
88
+ /**
89
+ * 获取文件变更类型和原始路径
90
+ */
91
+ function parseGitStatusLine(line) {
92
+ const statusCode = line.substring(0, 2);
93
+ const filePath = line.substring(3).trim();
94
+
95
+ // 状态码解析
96
+ const staged = statusCode[0];
97
+ const unstaged = statusCode[1];
98
+
99
+ let changeType = 'unknown';
100
+ if (staged === 'A' || unstaged === 'A') changeType = 'added';
101
+ else if (staged === 'M' || unstaged === 'M') changeType = 'modified';
102
+ else if (staged === 'D' || unstaged === 'D') changeType = 'deleted';
103
+ else if (staged === 'R') changeType = 'renamed';
104
+ else if (staged === 'C') changeType = 'copied';
105
+ else if (staged === '?' || unstaged === '?') changeType = 'untracked';
106
+
107
+ return { changeType, filePath, statusCode };
108
+ }
109
+
110
+ /**
111
+ * 获取文件内容
112
+ */
113
+ function getFileContent(repoDir, filePath) {
114
+ try {
115
+ const fullPath = path.join(repoDir, filePath);
116
+ if (!fs.existsSync(fullPath)) return null;
117
+ return fs.readFileSync(fullPath, 'utf-8');
118
+ } catch (e) {
119
+ return null;
120
+ }
121
+ }
122
+
123
+ /**
124
+ * 获取文件大小
125
+ */
126
+ function getFileSize(repoDir, filePath) {
127
+ try {
128
+ const fullPath = path.join(repoDir, filePath);
129
+ if (!fs.existsSync(fullPath)) return 0;
130
+ const stats = fs.statSync(fullPath);
131
+ return stats.size;
132
+ } catch (e) {
133
+ return 0;
134
+ }
135
+ }
136
+
137
+ /**
138
+ * 获取文件的 git 历史大小(用于比较)
139
+ */
140
+ function getGitFileSize(repoDir, filePath) {
141
+ const { execSync } = require('child_process');
142
+ try {
143
+ const size = execSync(`git cat-file -s HEAD:"${filePath}" 2>/dev/null || echo 0`, {
144
+ cwd: repoDir,
145
+ encoding: 'utf-8'
146
+ }).trim();
147
+ return parseInt(size, 10) || 0;
148
+ } catch (e) {
149
+ return 0;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * 检查是否包含敏感信息
155
+ */
156
+ function containsSensitiveInfo(content) {
157
+ if (!content) return false;
158
+ return SENSITIVE_PATTERNS.some(pattern => pattern.test(content));
159
+ }
160
+
161
+ /**
162
+ * 检查是否为纯配置更新(高安全度)
163
+ */
164
+ function isConfigUpdate(content) {
165
+ if (!content) return false;
166
+ // 如果内容主要是配置项(包含多个配置模式),则认为是配置更新
167
+ const configMatches = CONFIG_PATTERNS.filter(pattern => pattern.test(content));
168
+ return configMatches.length >= 2;
169
+ }
170
+
171
+ /**
172
+ * 检查 JSON/YAML 格式有效性
173
+ */
174
+ function validateFormat(filePath, content) {
175
+ const ext = path.extname(filePath).toLowerCase();
176
+
177
+ if (ext === '.json') {
178
+ try {
179
+ JSON.parse(content);
180
+ return { valid: true, error: null };
181
+ } catch (e) {
182
+ return { valid: false, error: `JSON 格式错误: ${e.message}` };
183
+ }
184
+ }
185
+
186
+ if (ext === '.yaml' || ext === '.yml') {
187
+ // 基础 YAML 检查(缩进、冒号等)
188
+ const lines = content.split('\n');
189
+ for (let i = 0; i < lines.length; i++) {
190
+ const line = lines[i];
191
+ // 检查混合缩进
192
+ if (line.match(/\t/) && line.match(/ /)) {
193
+ return { valid: false, error: `YAML 格式错误: 第 ${i + 1} 行混用空格和制表符` };
194
+ }
195
+ }
196
+ return { valid: true, error: null };
197
+ }
198
+
199
+ return { valid: true, error: null };
200
+ }
201
+
202
+ /**
203
+ * 评估单个文件的变更风险
204
+ */
205
+ function assessFileRisk(repoDir, changeInfo) {
206
+ const { changeType, filePath } = changeInfo;
207
+ const content = getFileContent(repoDir, filePath);
208
+ const currentSize = getFileSize(repoDir, filePath);
209
+ const originalSize = getGitFileSize(repoDir, filePath);
210
+
211
+ const assessment = {
212
+ filePath,
213
+ changeType,
214
+ decision: 'pending',
215
+ reason: [],
216
+ riskLevel: 'low'
217
+ };
218
+
219
+ // 1. 变更类型评估
220
+ if (changeType === 'deleted') {
221
+ assessment.decision = 'confirm';
222
+ assessment.reason.push('删除操作需要确认');
223
+ assessment.riskLevel = 'high';
224
+ return assessment;
225
+ }
226
+
227
+ if (changeType === 'added') {
228
+ assessment.decision = 'auto';
229
+ assessment.reason.push('纯新增文件');
230
+ }
231
+
232
+ // 2. 文件大小异常检查(变化 > 50% 需确认)
233
+ if (originalSize > 0 && currentSize > 0) {
234
+ const sizeChangeRatio = Math.abs(currentSize - originalSize) / originalSize;
235
+ if (sizeChangeRatio > 0.5) {
236
+ assessment.decision = 'confirm';
237
+ assessment.reason.push(`文件大小变化超过 50% (${(sizeChangeRatio * 100).toFixed(1)}%)`);
238
+ assessment.riskLevel = 'medium';
239
+ return assessment;
240
+ }
241
+ }
242
+
243
+ // 3. 敏感信息泄露扫描
244
+ if (containsSensitiveInfo(content)) {
245
+ assessment.decision = 'confirm';
246
+ assessment.reason.push('包含敏感字段(password/secret/key 等)');
247
+ assessment.riskLevel = 'high';
248
+ return assessment;
249
+ }
250
+
251
+ // 4. 格式有效性验证
252
+ if (content) {
253
+ const formatCheck = validateFormat(filePath, content);
254
+ if (!formatCheck.valid) {
255
+ assessment.decision = 'skip';
256
+ assessment.reason.push(formatCheck.error);
257
+ assessment.riskLevel = 'high';
258
+ return assessment;
259
+ }
260
+ }
261
+
262
+ // 5. 配置更新识别(高安全度)
263
+ if (changeType === 'modified' && content && isConfigUpdate(content)) {
264
+ assessment.decision = 'auto';
265
+ assessment.reason.push('配置值更新(端口、版本、超时等)');
266
+ assessment.riskLevel = 'low';
267
+ }
268
+
269
+ // 6. 文档内容更新
270
+ if (changeType === 'modified' && filePath.endsWith('.md')) {
271
+ assessment.decision = 'auto';
272
+ assessment.reason.push('文档内容更新');
273
+ assessment.riskLevel = 'low';
274
+ }
275
+
276
+ // 默认决策
277
+ if (assessment.decision === 'pending') {
278
+ if (changeType === 'modified') {
279
+ assessment.decision = 'auto';
280
+ assessment.reason.push('常规内容更新');
281
+ assessment.riskLevel = 'low';
282
+ } else {
283
+ assessment.decision = 'confirm';
284
+ assessment.reason.push('未识别的变更类型');
285
+ assessment.riskLevel = 'medium';
286
+ }
287
+ }
288
+
289
+ return assessment;
290
+ }
291
+
44
292
  /**
45
293
  * 获取当前分支名
46
294
  */
@@ -56,7 +304,7 @@ function getCurrentBranch(repoDir) {
56
304
  } catch (e) {
57
305
  return 'main';
58
306
  }
59
- }
307
+ }
60
308
 
61
309
  /**
62
310
  * 执行 git add
@@ -122,14 +370,26 @@ function loadConfig(projectRoot) {
122
370
  // 返回默认配置
123
371
  return {
124
372
  enabled: false,
125
- autoPush: false,
373
+ autoPush: false, // 默认关闭自动推送
126
374
  messageTemplate: 'chore: 更新环境知识 {date}',
127
- paths: ['.autospec/environment/']
375
+ paths: ['.autospec/environment/'],
376
+ smartCommit: true, // 启用智能决策
377
+ confirmOnDelete: true,
378
+ confirmOnSensitive: true,
379
+ maxAutoSizeChange: 0.5 // 50% 大小变化阈值
128
380
  };
129
381
  }
130
382
 
131
383
  try {
132
- return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
384
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
385
+ // 合并默认值
386
+ return {
387
+ smartCommit: true,
388
+ confirmOnDelete: true,
389
+ confirmOnSensitive: true,
390
+ maxAutoSizeChange: 0.5,
391
+ ...config
392
+ };
133
393
  } catch (e) {
134
394
  logger.warn('Failed to load autocommit config', { error: e.message });
135
395
  return { enabled: false };
@@ -139,19 +399,68 @@ function loadConfig(projectRoot) {
139
399
  /**
140
400
  * 生成提交消息
141
401
  */
142
- function generateCommitMessage(template, changes) {
402
+ function generateCommitMessage(template, assessments) {
143
403
  const date = new Date().toISOString().split('T')[0];
144
404
  let message = template.replace('{date}', date);
145
405
 
146
- // 如果有具体变更,添加到消息中
147
- if (changes.length > 0) {
148
- const summary = changes.map(c => path.basename(c)).join(', ');
149
- message += `\n\n变更文件: ${summary}`;
406
+ // 统计变更类型
407
+ const autoFiles = assessments.filter(a => a.decision === 'auto');
408
+ const confirmFiles = assessments.filter(a => a.decision === 'confirm');
409
+
410
+ if (autoFiles.length > 0) {
411
+ const summary = autoFiles.map(a => path.basename(a.filePath)).join(', ');
412
+ message += `\n\n自动提交 (${autoFiles.length} 个): ${summary}`;
413
+ }
414
+
415
+ if (confirmFiles.length > 0) {
416
+ const summary = confirmFiles.map(a => path.basename(a.filePath)).join(', ');
417
+ message += `\n\n需确认 (${confirmFiles.length} 个): ${summary}`;
150
418
  }
151
419
 
152
420
  return message;
153
421
  }
154
422
 
423
+ /**
424
+ * 生成决策报告
425
+ */
426
+ function generateDecisionReport(assessments) {
427
+ const auto = assessments.filter(a => a.decision === 'auto');
428
+ const confirm = assessments.filter(a => a.decision === 'confirm');
429
+ const skip = assessments.filter(a => a.decision === 'skip');
430
+
431
+ let report = '\n📊 智能提交决策报告\n';
432
+ report += '═'.repeat(50) + '\n';
433
+
434
+ if (auto.length > 0) {
435
+ report += `\n✅ 自动提交 (${auto.length} 个):\n`;
436
+ auto.forEach(a => {
437
+ report += ` • ${path.basename(a.filePath)} - ${a.reason[0]}\n`;
438
+ });
439
+ }
440
+
441
+ if (confirm.length > 0) {
442
+ report += `\n⚠️ 需人工确认 (${confirm.length} 个):\n`;
443
+ confirm.forEach(a => {
444
+ report += ` • ${path.basename(a.filePath)}\n`;
445
+ a.reason.forEach(r => {
446
+ report += ` - ${r}\n`;
447
+ });
448
+ });
449
+ }
450
+
451
+ if (skip.length > 0) {
452
+ report += `\n❌ 已跳过 (${skip.length} 个):\n`;
453
+ skip.forEach(a => {
454
+ report += ` • ${path.basename(a.filePath)} - ${a.reason[0]}\n`;
455
+ });
456
+ }
457
+
458
+ report += '\n' + '═'.repeat(50) + '\n';
459
+ report += `总计: ${assessments.length} 个文件 | 自动: ${auto.length} | 确认: ${confirm.length} | 跳过: ${skip.length}\n`;
460
+
461
+ return { report, auto, confirm, skip };
462
+ }
463
+
155
464
  /**
156
465
  * 处理 Stop 事件
157
466
  */
@@ -162,6 +471,19 @@ async function handleStop(projectRoot) {
162
471
  process.exit(0);
163
472
  }
164
473
 
474
+ // 检查是否有冲突
475
+ if (hasConflicts(projectRoot)) {
476
+ logger.warn('Git conflicts detected, skipping autocommit');
477
+ const output = {
478
+ hookSpecificOutput: {
479
+ hookEventName: 'Stop',
480
+ additionalContext: '[AutoSpec] 检测到 Git 冲突,跳过自动提交。请手动解决冲突后再提交。',
481
+ },
482
+ };
483
+ process.stdout.write(JSON.stringify(output));
484
+ process.exit(0);
485
+ }
486
+
165
487
  // 加载配置
166
488
  const config = loadConfig(projectRoot);
167
489
 
@@ -183,24 +505,43 @@ async function handleStop(projectRoot) {
183
505
  const envPaths = config.paths || ['.autospec/environment/'];
184
506
  const changedFiles = status.split('\n')
185
507
  .filter(line => line.trim())
186
- .map(line => line.substring(3).trim())
187
- .filter(file => envPaths.some(p => file.startsWith(p)));
508
+ .map(line => parseGitStatusLine(line))
509
+ .filter(info => envPaths.some(p => info.filePath.startsWith(p)));
188
510
 
189
511
  if (changedFiles.length === 0) {
190
512
  logger.debug('No environment knowledge changes');
191
513
  process.exit(0);
192
514
  }
193
515
 
194
- logger.info('Detected environment knowledge changes', { files: changedFiles });
516
+ logger.info('Detected environment knowledge changes', { files: changedFiles.map(f => f.filePath) });
517
+
518
+ // 智能决策评估
519
+ const assessments = changedFiles.map(info => assessFileRisk(projectRoot, info));
520
+ const { report, auto, confirm, skip } = generateDecisionReport(assessments);
521
+
522
+ logger.info(report);
523
+
524
+ // 如果没有可以自动提交的文件,直接退出
525
+ if (auto.length === 0) {
526
+ const output = {
527
+ hookSpecificOutput: {
528
+ hookEventName: 'Stop',
529
+ additionalContext: `[AutoSpec] 环境知识变更需要人工确认。${confirm.length} 个文件待确认,${skip.length} 个文件已跳过。`,
530
+ },
531
+ };
532
+ process.stdout.write(JSON.stringify(output));
533
+ process.exit(0);
534
+ }
195
535
 
196
- // 执行 git add
197
- const addResult = gitAdd(projectRoot, changedFiles);
536
+ // 执行 git add(只添加自动提交的文件)
537
+ const autoFilePaths = auto.map(a => a.filePath);
538
+ const addResult = gitAdd(projectRoot, autoFilePaths);
198
539
  if (!addResult) {
199
540
  process.exit(0);
200
541
  }
201
542
 
202
543
  // 生成提交消息
203
- const message = generateCommitMessage(config.messageTemplate || 'chore: 更新环境知识', changedFiles);
544
+ const message = generateCommitMessage(config.messageTemplate || 'chore: 更新环境知识', assessments);
204
545
 
205
546
  // 执行 git commit
206
547
  const commitResult = gitCommit(projectRoot, message);
@@ -210,9 +551,10 @@ async function handleStop(projectRoot) {
210
551
 
211
552
  logger.info('Committed environment knowledge changes', { message });
212
553
 
213
- // 如果配置了自动 push
554
+ // 如果配置了自动 push(默认关闭)
555
+ let pushResult = false;
214
556
  if (config.autoPush) {
215
- const pushResult = gitPush(projectRoot);
557
+ pushResult = gitPush(projectRoot);
216
558
  if (pushResult) {
217
559
  logger.info('Pushed environment knowledge changes');
218
560
  }
@@ -223,7 +565,7 @@ async function handleStop(projectRoot) {
223
565
  const output = {
224
566
  hookSpecificOutput: {
225
567
  hookEventName: 'Stop',
226
- additionalContext: `[AutoSpec] 环境知识已自动提交到 ${branch} 分支${config.autoPush ? '并推送' : ''}。变更文件: ${changedFiles.length} 个`,
568
+ additionalContext: `[AutoSpec] 环境知识已智能提交到 ${branch} 分支。自动: ${auto.length} 个${config.autoPush && pushResult ? '并推送' : ''},需确认: ${confirm.length} 个,跳过: ${skip.length} 个`,
227
569
  },
228
570
  };
229
571
 
@@ -261,4 +603,4 @@ async function main() {
261
603
  }
262
604
  }
263
605
 
264
- main();
606
+ main();
@@ -590,12 +590,13 @@ function detectDesignDocChanges(projectRoot) {
590
590
  }
591
591
 
592
592
  /**
593
- * 检测业务知识变更 - 扫描 knowledge/domain/ 目录
593
+ * 检测业务知识变更 - 扫描业务知识目录
594
594
  */
595
595
  function detectBusinessKnowledgeChanges(projectRoot) {
596
596
  const changes = [];
597
597
  const dirsToCheck = [
598
- 'knowledge/domain',
598
+ 'knowledge/09-templates/05-business-glossary.md',
599
+ 'knowledge/09-templates/06-business-rules.md',
599
600
  'docs/business'
600
601
  ];
601
602
 
@@ -19,7 +19,7 @@
19
19
 
20
20
  import { createHookLogger, safeJsonParse, handleHookError, readStdin, findProjectRootAsync } from './lib/hook-logger.js';
21
21
  import { recordHookExecution } from './lib/hook-error-recorder.js';
22
- import { getState } from './lib/hook-state-manager.js';
22
+ import { getState, getCurrentStageSubsystems, updateState } from './lib/hook-state-manager.js';
23
23
  import { generateEventId, getTraceId, appendTraceEvent } from './lib/trace-context.js';
24
24
  import fs from 'fs';
25
25
  import path from 'path';
@@ -173,7 +173,7 @@ async function main() {
173
173
  const toolName = input.tool_name;
174
174
 
175
175
  // Track Write operations for artifact generation
176
- if (toolName === 'Write') {
176
+ if (toolName === 'Write' || toolName === 'Edit') {
177
177
  const filePath = input.tool_input?.file_path || '';
178
178
 
179
179
  // Find project root
@@ -185,6 +185,60 @@ async function main() {
185
185
  process.exit(0);
186
186
  }
187
187
 
188
+ // ========== 子系统代码变更追踪 ==========
189
+ const state = getState(projectRoot, true);
190
+ const subsystems = getCurrentStageSubsystems(projectRoot);
191
+
192
+ if (subsystems.length > 0 && filePath && !filePath.includes('.autospec')) {
193
+ // 检测文件变更属于哪个子系统
194
+ const relativePath = filePath.replace(projectRoot + '/', '').replace(projectRoot + '\\\\', '');
195
+ const matchedSubsystem = subsystems.find(sub =>
196
+ relativePath.startsWith(sub.path + '/') ||
197
+ relativePath.startsWith(sub.path + '\\') ||
198
+ relativePath.startsWith(sub.name + '/')
199
+ );
200
+
201
+ if (matchedSubsystem) {
202
+ // 更新子系统的变更计数
203
+ const subsystemKey = `stages.${state.currentStage}.subsystems`;
204
+ const stageData = state.stages[state.currentStage];
205
+
206
+ if (stageData?.subsystems) {
207
+ const subsystem = stageData.subsystems.find(s => s.name === matchedSubsystem.name);
208
+ if (subsystem) {
209
+ // 初始化或更新变更计数
210
+ if (!subsystem.changeCount) {
211
+ subsystem.changeCount = 0;
212
+ }
213
+ subsystem.changeCount++;
214
+ subsystem.lastChangeAt = new Date().toISOString();
215
+
216
+ // 记录变更文件列表
217
+ if (!subsystem.changedFiles) {
218
+ subsystem.changedFiles = [];
219
+ }
220
+ if (!subsystem.changedFiles.includes(relativePath)) {
221
+ subsystem.changedFiles.push(relativePath);
222
+ }
223
+
224
+ // 标记子系统为进行中(如果还是 pending 状态)
225
+ if (subsystem.status === 'pending') {
226
+ subsystem.status = 'in_progress';
227
+ subsystem.startedAt = subsystem.startedAt || new Date().toISOString();
228
+ }
229
+
230
+ updateState(projectRoot, state);
231
+ logger.debug('Subsystem code change tracked', {
232
+ subsystem: matchedSubsystem.name,
233
+ file: relativePath,
234
+ changeCount: subsystem.changeCount
235
+ });
236
+ }
237
+ }
238
+ }
239
+ }
240
+ // ==========================================
241
+
188
242
  // Check if this is a key artifact
189
243
  const artifactInfo = detectArtifactType(filePath);
190
244
  if (artifactInfo) {
@@ -222,8 +276,9 @@ async function main() {
222
276
  const traceEvent = createEvent(projectRoot, 'artifact_created', {
223
277
  stage: artifactInfo.stage,
224
278
  tool: 'Write',
225
- action: 'create_artifact',
226
- data: {
279
+ action: "create_artifact",
280
+ data:
281
+ {
227
282
  file: filePath,
228
283
  artifactType: artifactInfo.type,
229
284
  // 完整内容用于深度评测(仅关键文件)
@@ -332,6 +387,56 @@ async function main() {
332
387
  }
333
388
  });
334
389
  appendTraceEvent(projectRoot, traceEvent);
390
+
391
+ // ========== 自动创建 practice-log 条目 ==========
392
+ // 当阶段完成时,自动记录到 practice-log
393
+ if (state.completedAt && !state.stageLogged) {
394
+ const practiceLogDir = path.join(projectRoot, '.autospec', 'practice-log');
395
+ if (!fs.existsSync(practiceLogDir)) {
396
+ fs.mkdirSync(practiceLogDir, { recursive: true });
397
+ }
398
+
399
+ const date = new Date().toISOString().split('T')[0];
400
+ const stageName = state.currentStage.replace('0', '').replace('-', '');
401
+ const logFile = path.join(practiceLogDir, `${date}-${stageName}.md`);
402
+
403
+ // 如果文件已存在,不重复创建
404
+ if (!fs.existsSync(logFile)) {
405
+ const template = `# 实践日志 - ${state.currentStage}
406
+
407
+ 日期:${date}
408
+ 阶段:${state.currentStage}
409
+ 完成时间:${state.completedAt}
410
+
411
+ ## 问题描述
412
+
413
+ <!-- 描述遇到的问题 -->
414
+
415
+ ## 解决方案
416
+
417
+ <!-- 描述解决方案 -->
418
+
419
+ ## 经验总结
420
+
421
+ <!-- 描述可以复用的经验 -->
422
+
423
+ ## 相关文件
424
+
425
+ <!-- 列出相关文件 -->
426
+
427
+ ## 标签
428
+
429
+ <!-- 添加标签,如:bugfix, optimization, pattern -->
430
+ `;
431
+ fs.writeFileSync(logFile, template, 'utf-8');
432
+ logger.info('Practice-log auto-created', { file: logFile });
433
+
434
+ // 标记已记录,防止重复
435
+ state.stageLogged = true;
436
+ fs.writeFileSync(statePath, JSON.stringify(state, null, 2), 'utf-8');
437
+ }
438
+ }
439
+ // ==============================================
335
440
  }
336
441
  } catch {
337
442
  // Ignore state.json parsing errors