@mycodemap/mycodemap 0.1.1 → 0.3.4

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 (328) hide show
  1. package/CHANGELOG.md +163 -0
  2. package/README.md +241 -67
  3. package/dist/cli/commands/ci.d.ts +7 -1
  4. package/dist/cli/commands/ci.d.ts.map +1 -1
  5. package/dist/cli/commands/ci.js +38 -0
  6. package/dist/cli/commands/ci.js.map +1 -1
  7. package/dist/cli/commands/export.d.ts +6 -0
  8. package/dist/cli/commands/export.d.ts.map +1 -0
  9. package/dist/cli/commands/export.js +108 -0
  10. package/dist/cli/commands/export.js.map +1 -0
  11. package/dist/cli/commands/generate.d.ts.map +1 -1
  12. package/dist/cli/commands/generate.js +96 -0
  13. package/dist/cli/commands/generate.js.map +1 -1
  14. package/dist/cli/commands/server.d.ts +9 -0
  15. package/dist/cli/commands/server.d.ts.map +1 -0
  16. package/dist/cli/commands/server.js +68 -0
  17. package/dist/cli/commands/server.js.map +1 -0
  18. package/dist/cli/commands/ship/analyzer.d.ts +26 -0
  19. package/dist/cli/commands/ship/analyzer.d.ts.map +1 -0
  20. package/dist/cli/commands/ship/analyzer.js +143 -0
  21. package/dist/cli/commands/ship/analyzer.js.map +1 -0
  22. package/dist/cli/commands/ship/checker.d.ts +20 -0
  23. package/dist/cli/commands/ship/checker.d.ts.map +1 -0
  24. package/dist/cli/commands/ship/checker.js +86 -0
  25. package/dist/cli/commands/ship/checker.js.map +1 -0
  26. package/dist/cli/commands/ship/index.d.ts +17 -0
  27. package/dist/cli/commands/ship/index.d.ts.map +1 -0
  28. package/dist/cli/commands/ship/index.js +51 -0
  29. package/dist/cli/commands/ship/index.js.map +1 -0
  30. package/dist/cli/commands/ship/monitor.d.ts +19 -0
  31. package/dist/cli/commands/ship/monitor.d.ts.map +1 -0
  32. package/dist/cli/commands/ship/monitor.js +105 -0
  33. package/dist/cli/commands/ship/monitor.js.map +1 -0
  34. package/dist/cli/commands/ship/pipeline.d.ts +23 -0
  35. package/dist/cli/commands/ship/pipeline.d.ts.map +1 -0
  36. package/dist/cli/commands/ship/pipeline.js +146 -0
  37. package/dist/cli/commands/ship/pipeline.js.map +1 -0
  38. package/dist/cli/commands/ship/publisher.d.ts +11 -0
  39. package/dist/cli/commands/ship/publisher.d.ts.map +1 -0
  40. package/dist/cli/commands/ship/publisher.js +75 -0
  41. package/dist/cli/commands/ship/publisher.js.map +1 -0
  42. package/dist/cli/commands/ship/rules/confidence-rules.d.ts +48 -0
  43. package/dist/cli/commands/ship/rules/confidence-rules.d.ts.map +1 -0
  44. package/dist/cli/commands/ship/rules/confidence-rules.js +122 -0
  45. package/dist/cli/commands/ship/rules/confidence-rules.js.map +1 -0
  46. package/dist/cli/commands/ship/rules/quality-rules.d.ts +25 -0
  47. package/dist/cli/commands/ship/rules/quality-rules.d.ts.map +1 -0
  48. package/dist/cli/commands/ship/rules/quality-rules.js +134 -0
  49. package/dist/cli/commands/ship/rules/quality-rules.js.map +1 -0
  50. package/dist/cli/commands/ship/rules/version-rules.d.ts +24 -0
  51. package/dist/cli/commands/ship/rules/version-rules.d.ts.map +1 -0
  52. package/dist/cli/commands/ship/rules/version-rules.js +75 -0
  53. package/dist/cli/commands/ship/rules/version-rules.js.map +1 -0
  54. package/dist/cli/commands/ship/versioner.d.ts +12 -0
  55. package/dist/cli/commands/ship/versioner.d.ts.map +1 -0
  56. package/dist/cli/commands/ship/versioner.js +92 -0
  57. package/dist/cli/commands/ship/versioner.js.map +1 -0
  58. package/dist/cli/index.js +31 -1
  59. package/dist/cli/index.js.map +1 -1
  60. package/dist/cli-new/commands/export.d.ts +15 -0
  61. package/dist/cli-new/commands/export.d.ts.map +1 -0
  62. package/dist/cli-new/commands/export.js +107 -0
  63. package/dist/cli-new/commands/export.js.map +1 -0
  64. package/dist/cli-new/commands/query.d.ts +14 -0
  65. package/dist/cli-new/commands/query.d.ts.map +1 -0
  66. package/dist/cli-new/commands/query.js +120 -0
  67. package/dist/cli-new/commands/query.js.map +1 -0
  68. package/dist/cli-new/commands/server.d.ts +13 -0
  69. package/dist/cli-new/commands/server.d.ts.map +1 -0
  70. package/dist/cli-new/commands/server.js +94 -0
  71. package/dist/cli-new/commands/server.js.map +1 -0
  72. package/dist/cli-new/index.d.ts +11 -0
  73. package/dist/cli-new/index.d.ts.map +1 -0
  74. package/dist/cli-new/index.js +63 -0
  75. package/dist/cli-new/index.js.map +1 -0
  76. package/dist/cli-new/types/index.d.ts +88 -0
  77. package/dist/cli-new/types/index.d.ts.map +1 -0
  78. package/dist/cli-new/types/index.js +7 -0
  79. package/dist/cli-new/types/index.js.map +1 -0
  80. package/dist/domain/entities/CodeGraph.d.ts +134 -0
  81. package/dist/domain/entities/CodeGraph.d.ts.map +1 -0
  82. package/dist/domain/entities/CodeGraph.js +316 -0
  83. package/dist/domain/entities/CodeGraph.js.map +1 -0
  84. package/dist/domain/entities/Dependency.d.ts +78 -0
  85. package/dist/domain/entities/Dependency.d.ts.map +1 -0
  86. package/dist/domain/entities/Dependency.js +132 -0
  87. package/dist/domain/entities/Dependency.js.map +1 -0
  88. package/dist/domain/entities/Module.d.ts +75 -0
  89. package/dist/domain/entities/Module.d.ts.map +1 -0
  90. package/dist/domain/entities/Module.js +151 -0
  91. package/dist/domain/entities/Module.js.map +1 -0
  92. package/dist/domain/entities/Project.d.ts +50 -0
  93. package/dist/domain/entities/Project.d.ts.map +1 -0
  94. package/dist/domain/entities/Project.js +99 -0
  95. package/dist/domain/entities/Project.js.map +1 -0
  96. package/dist/domain/entities/Symbol.d.ts +75 -0
  97. package/dist/domain/entities/Symbol.d.ts.map +1 -0
  98. package/dist/domain/entities/Symbol.js +130 -0
  99. package/dist/domain/entities/Symbol.js.map +1 -0
  100. package/dist/domain/events/DomainEvent.d.ts +76 -0
  101. package/dist/domain/events/DomainEvent.d.ts.map +1 -0
  102. package/dist/domain/events/DomainEvent.js +153 -0
  103. package/dist/domain/events/DomainEvent.js.map +1 -0
  104. package/dist/domain/index.d.ts +10 -0
  105. package/dist/domain/index.d.ts.map +1 -0
  106. package/dist/domain/index.js +18 -0
  107. package/dist/domain/index.js.map +1 -0
  108. package/dist/domain/repositories/CodeGraphRepository.d.ts +58 -0
  109. package/dist/domain/repositories/CodeGraphRepository.d.ts.map +1 -0
  110. package/dist/domain/repositories/CodeGraphRepository.js +37 -0
  111. package/dist/domain/repositories/CodeGraphRepository.js.map +1 -0
  112. package/dist/domain/services/CodeGraphBuilder.d.ts +50 -0
  113. package/dist/domain/services/CodeGraphBuilder.d.ts.map +1 -0
  114. package/dist/domain/services/CodeGraphBuilder.js +121 -0
  115. package/dist/domain/services/CodeGraphBuilder.js.map +1 -0
  116. package/dist/infrastructure/parser/implementations/GoParser.d.ts +25 -0
  117. package/dist/infrastructure/parser/implementations/GoParser.d.ts.map +1 -0
  118. package/dist/infrastructure/parser/implementations/GoParser.js +158 -0
  119. package/dist/infrastructure/parser/implementations/GoParser.js.map +1 -0
  120. package/dist/infrastructure/parser/implementations/PythonParser.d.ts +30 -0
  121. package/dist/infrastructure/parser/implementations/PythonParser.d.ts.map +1 -0
  122. package/dist/infrastructure/parser/implementations/PythonParser.js +201 -0
  123. package/dist/infrastructure/parser/implementations/PythonParser.js.map +1 -0
  124. package/dist/infrastructure/parser/implementations/TypeScriptParser.d.ts +63 -0
  125. package/dist/infrastructure/parser/implementations/TypeScriptParser.d.ts.map +1 -0
  126. package/dist/infrastructure/parser/implementations/TypeScriptParser.js +420 -0
  127. package/dist/infrastructure/parser/implementations/TypeScriptParser.js.map +1 -0
  128. package/dist/infrastructure/parser/index.d.ts +13 -0
  129. package/dist/infrastructure/parser/index.d.ts.map +1 -0
  130. package/dist/infrastructure/parser/index.js +32 -0
  131. package/dist/infrastructure/parser/index.js.map +1 -0
  132. package/dist/infrastructure/parser/interfaces/ParserBase.d.ts +124 -0
  133. package/dist/infrastructure/parser/interfaces/ParserBase.d.ts.map +1 -0
  134. package/dist/infrastructure/parser/interfaces/ParserBase.js +200 -0
  135. package/dist/infrastructure/parser/interfaces/ParserBase.js.map +1 -0
  136. package/dist/infrastructure/parser/registry/ParserRegistry.d.ts +68 -0
  137. package/dist/infrastructure/parser/registry/ParserRegistry.d.ts.map +1 -0
  138. package/dist/infrastructure/parser/registry/ParserRegistry.js +116 -0
  139. package/dist/infrastructure/parser/registry/ParserRegistry.js.map +1 -0
  140. package/dist/infrastructure/repositories/CodeGraphRepositoryImpl.d.ts +44 -0
  141. package/dist/infrastructure/repositories/CodeGraphRepositoryImpl.d.ts.map +1 -0
  142. package/dist/infrastructure/repositories/CodeGraphRepositoryImpl.js +129 -0
  143. package/dist/infrastructure/repositories/CodeGraphRepositoryImpl.js.map +1 -0
  144. package/dist/infrastructure/repositories/index.d.ts +3 -0
  145. package/dist/infrastructure/repositories/index.d.ts.map +1 -0
  146. package/dist/infrastructure/repositories/index.js +7 -0
  147. package/dist/infrastructure/repositories/index.js.map +1 -0
  148. package/dist/infrastructure/storage/StorageFactory.d.ts +53 -0
  149. package/dist/infrastructure/storage/StorageFactory.d.ts.map +1 -0
  150. package/dist/infrastructure/storage/StorageFactory.js +150 -0
  151. package/dist/infrastructure/storage/StorageFactory.js.map +1 -0
  152. package/dist/infrastructure/storage/adapters/FileSystemStorage.d.ts +52 -0
  153. package/dist/infrastructure/storage/adapters/FileSystemStorage.d.ts.map +1 -0
  154. package/dist/infrastructure/storage/adapters/FileSystemStorage.js +315 -0
  155. package/dist/infrastructure/storage/adapters/FileSystemStorage.js.map +1 -0
  156. package/dist/infrastructure/storage/adapters/KuzuDBStorage.d.ts +52 -0
  157. package/dist/infrastructure/storage/adapters/KuzuDBStorage.d.ts.map +1 -0
  158. package/dist/infrastructure/storage/adapters/KuzuDBStorage.js +235 -0
  159. package/dist/infrastructure/storage/adapters/KuzuDBStorage.js.map +1 -0
  160. package/dist/infrastructure/storage/adapters/MemoryStorage.d.ts +37 -0
  161. package/dist/infrastructure/storage/adapters/MemoryStorage.d.ts.map +1 -0
  162. package/dist/infrastructure/storage/adapters/MemoryStorage.js +229 -0
  163. package/dist/infrastructure/storage/adapters/MemoryStorage.js.map +1 -0
  164. package/dist/infrastructure/storage/adapters/Neo4jStorage.d.ts +49 -0
  165. package/dist/infrastructure/storage/adapters/Neo4jStorage.d.ts.map +1 -0
  166. package/dist/infrastructure/storage/adapters/Neo4jStorage.js +222 -0
  167. package/dist/infrastructure/storage/adapters/Neo4jStorage.js.map +1 -0
  168. package/dist/infrastructure/storage/index.d.ts +6 -0
  169. package/dist/infrastructure/storage/index.d.ts.map +1 -0
  170. package/dist/infrastructure/storage/index.js +13 -0
  171. package/dist/infrastructure/storage/index.js.map +1 -0
  172. package/dist/infrastructure/storage/interfaces/StorageBase.d.ts +76 -0
  173. package/dist/infrastructure/storage/interfaces/StorageBase.d.ts.map +1 -0
  174. package/dist/infrastructure/storage/interfaces/StorageBase.js +116 -0
  175. package/dist/infrastructure/storage/interfaces/StorageBase.js.map +1 -0
  176. package/dist/interface/config/index.d.ts +102 -0
  177. package/dist/interface/config/index.d.ts.map +1 -0
  178. package/dist/interface/config/index.js +7 -0
  179. package/dist/interface/config/index.js.map +1 -0
  180. package/dist/interface/types/index.d.ts +425 -0
  181. package/dist/interface/types/index.d.ts.map +1 -0
  182. package/dist/interface/types/index.js +8 -0
  183. package/dist/interface/types/index.js.map +1 -0
  184. package/dist/interface/types/parser.d.ts +103 -0
  185. package/dist/interface/types/parser.d.ts.map +1 -0
  186. package/dist/interface/types/parser.js +7 -0
  187. package/dist/interface/types/parser.js.map +1 -0
  188. package/dist/interface/types/storage.d.ts +98 -0
  189. package/dist/interface/types/storage.d.ts.map +1 -0
  190. package/dist/interface/types/storage.js +7 -0
  191. package/dist/interface/types/storage.js.map +1 -0
  192. package/dist/orchestrator/test-linker.js +1 -1
  193. package/dist/orchestrator/test-linker.js.map +1 -1
  194. package/dist/server/CodeMapServer.d.ts +51 -0
  195. package/dist/server/CodeMapServer.d.ts.map +1 -0
  196. package/dist/server/CodeMapServer.js +146 -0
  197. package/dist/server/CodeMapServer.js.map +1 -0
  198. package/dist/server/handlers/AnalysisHandler.d.ts +82 -0
  199. package/dist/server/handlers/AnalysisHandler.d.ts.map +1 -0
  200. package/dist/server/handlers/AnalysisHandler.js +196 -0
  201. package/dist/server/handlers/AnalysisHandler.js.map +1 -0
  202. package/dist/server/handlers/QueryHandler.d.ts +57 -0
  203. package/dist/server/handlers/QueryHandler.d.ts.map +1 -0
  204. package/dist/server/handlers/QueryHandler.js +260 -0
  205. package/dist/server/handlers/QueryHandler.js.map +1 -0
  206. package/dist/server/index.d.ts +7 -0
  207. package/dist/server/index.d.ts.map +1 -0
  208. package/dist/server/index.js +13 -0
  209. package/dist/server/index.js.map +1 -0
  210. package/dist/server/routes/api.d.ts +8 -0
  211. package/dist/server/routes/api.d.ts.map +1 -0
  212. package/dist/server/routes/api.js +372 -0
  213. package/dist/server/routes/api.js.map +1 -0
  214. package/dist/server/types/index.d.ts +171 -0
  215. package/dist/server/types/index.d.ts.map +1 -0
  216. package/dist/server/types/index.js +7 -0
  217. package/dist/server/types/index.js.map +1 -0
  218. package/dist/types/index.d.ts +6 -372
  219. package/dist/types/index.d.ts.map +1 -1
  220. package/dist/types/index.js +9 -3
  221. package/dist/types/index.js.map +1 -1
  222. package/docs/AI_ASSISTANT_SETUP.md +68 -0
  223. package/docs/PUBLISHING.md +472 -0
  224. package/docs/README.md +37 -0
  225. package/docs/SETUP_GUIDE.md +91 -5
  226. package/docs/ai-guide/COMMANDS.md +403 -0
  227. package/docs/ai-guide/INTEGRATION.md +513 -0
  228. package/docs/ai-guide/OUTPUT.md +465 -0
  229. package/docs/ai-guide/PATTERNS.md +409 -0
  230. package/docs/ai-guide/PROMPTS.md +414 -0
  231. package/docs/ai-guide/QUICKSTART.md +114 -0
  232. package/docs/ai-guide/README.md +66 -0
  233. package/docs/archive/AI_INTEGRATION_GUIDE_ARCHIVED.md +7 -1
  234. package/docs/archive/ARCHIVE.md +39 -0
  235. package/docs/archive/MYCLAUDE_GUIDE.md +305 -0
  236. package/docs/archive/PUBLISH_NPM_DESIGN_V1.md +6 -0
  237. package/docs/archive/PUBLISH_NPM_DESIGN_V2.md +6 -0
  238. package/docs/archive/README.md +29 -0
  239. package/docs/archive/TASK_DESIGN_COVERAGE_REPORT.md +6 -0
  240. package/docs/archive/TEST_SUMMARY.md +140 -0
  241. package/docs/archive/comprehensive_test_report.md +337 -0
  242. package/docs/{CI_GATEWAY_DESIGN.md → archive/design-docs/CI_GATEWAY_DESIGN.md} +6 -0
  243. package/docs/{PUBLISH_NPM_DESIGN_FINAL.md → archive/design-docs/PUBLISH_NPM_DESIGN_FINAL.md} +7 -1
  244. package/docs/{REFACTOR_ARCHITECTURE_OVERVIEW.md → archive/design-docs/REFACTOR_ARCHITECTURE_OVERVIEW.md} +8 -2
  245. package/docs/{REFACTOR_CONFIDENCE_DESIGN.md → archive/design-docs/REFACTOR_CONFIDENCE_DESIGN.md} +6 -0
  246. package/docs/{REFACTOR_GIT_ANALYZER_DESIGN.md → archive/design-docs/REFACTOR_GIT_ANALYZER_DESIGN.md} +8 -2
  247. package/docs/{REFACTOR_ORCHESTRATOR_DESIGN.md → archive/design-docs/REFACTOR_ORCHESTRATOR_DESIGN.md} +6 -0
  248. package/docs/{REFACTOR_RESULT_FUSION_DESIGN.md → archive/design-docs/REFACTOR_RESULT_FUSION_DESIGN.md} +6 -0
  249. package/docs/{REFACTOR_TEST_LINKER_DESIGN.md → archive/design-docs/REFACTOR_TEST_LINKER_DESIGN.md} +6 -0
  250. package/docs/archive/myclaude.md +1084 -0
  251. package/docs/archive/plans/2026-03-14-go-language-support-design.md +92 -0
  252. package/docs/{REFACTOR_REQUIREMENTS.md → archive/product-specs/REFACTOR_REQUIREMENTS.md} +11 -5
  253. package/docs/archive/scenario-2-deps-analysis.md +353 -0
  254. package/docs/design-docs/README.md +26 -0
  255. package/docs/exec-plans/MVP3-IMPLEMENTATION-ROADMAP.md +524 -0
  256. package/docs/exec-plans/README.md +29 -0
  257. package/docs/exec-plans/active/.gitkeep +0 -0
  258. package/docs/exec-plans/completed/.gitkeep +0 -0
  259. package/docs/{plans/POST_TASK_PLAN.md → exec-plans/completed/2026-03-03-post-task-plan.md} +9 -3
  260. package/docs/exec-plans/completed/harness-engineering-rollout.md +184 -0
  261. package/docs/exec-plans/tech-debt/.gitkeep +0 -0
  262. package/docs/exec-plans/tech-debt/2026-03-15-lint-guardrail-gap.md +30 -0
  263. package/docs/generated/README.md +19 -0
  264. package/docs/product-specs/MVP3-ARCHITECTURE-COMPARISON.md +504 -0
  265. package/docs/product-specs/MVP3-ARCHITECTURE-REDESIGN-PRD.md +322 -0
  266. package/docs/product-specs/MVP3-ARCHITECTURE-REDESIGN-TECH-PRD.md +1374 -0
  267. package/docs/product-specs/README.md +22 -0
  268. package/docs/references/README.md +15 -0
  269. package/docs/references/tmp.md +527 -0
  270. package/docs/rules/README.md +16 -0
  271. package/docs/rules/architecture-guardrails.md +349 -0
  272. package/docs/rules/code-quality-redlines.md +321 -0
  273. package/docs/rules/deployment.md +23 -0
  274. package/docs/rules/engineering-with-codex-openai.md +202 -0
  275. package/docs/rules/pre-release-checklist.md +426 -0
  276. package/docs/rules/testing.md +73 -0
  277. package/docs/rules/validation.md +39 -0
  278. package/package.json +26 -7
  279. package/scripts/.githooks/commit-msg +31 -0
  280. package/scripts/.githooks/pre-commit +55 -0
  281. package/scripts/benchmark.ts +209 -0
  282. package/scripts/hooks/commit-msg +24 -0
  283. package/scripts/hooks/install-hooks.sh +29 -0
  284. package/scripts/hooks/pre-commit +60 -0
  285. package/scripts/pre-release-check.js +717 -0
  286. package/scripts/release.sh +142 -0
  287. package/scripts/run-benchmark.sh +29 -0
  288. package/scripts/validate-ai-docs.js +294 -0
  289. package/scripts/validate-docs.js +238 -0
  290. package/scripts/validate-pack.js +86 -0
  291. package/dist/ai/claude.d.ts +0 -38
  292. package/dist/ai/claude.d.ts.map +0 -1
  293. package/dist/ai/claude.js +0 -169
  294. package/dist/ai/claude.js.map +0 -1
  295. package/dist/ai/codex.d.ts +0 -38
  296. package/dist/ai/codex.d.ts.map +0 -1
  297. package/dist/ai/codex.js +0 -169
  298. package/dist/ai/codex.js.map +0 -1
  299. package/dist/ai/factory.d.ts +0 -48
  300. package/dist/ai/factory.d.ts.map +0 -1
  301. package/dist/ai/factory.js +0 -95
  302. package/dist/ai/factory.js.map +0 -1
  303. package/dist/ai/index.d.ts +0 -12
  304. package/dist/ai/index.d.ts.map +0 -1
  305. package/dist/ai/index.js +0 -29
  306. package/dist/ai/index.js.map +0 -1
  307. package/dist/ai/provider.d.ts +0 -70
  308. package/dist/ai/provider.d.ts.map +0 -1
  309. package/dist/ai/provider.js +0 -31
  310. package/dist/ai/provider.js.map +0 -1
  311. package/dist/ai/subagent-caller.d.ts +0 -90
  312. package/dist/ai/subagent-caller.d.ts.map +0 -1
  313. package/dist/ai/subagent-caller.js +0 -280
  314. package/dist/ai/subagent-caller.js.map +0 -1
  315. package/dist/ai/types.d.ts +0 -70
  316. package/dist/ai/types.d.ts.map +0 -1
  317. package/dist/ai/types.js +0 -5
  318. package/dist/ai/types.js.map +0 -1
  319. package/dist/generator/ai-overview.d.ts +0 -51
  320. package/dist/generator/ai-overview.d.ts.map +0 -1
  321. package/dist/generator/ai-overview.js +0 -160
  322. package/dist/generator/ai-overview.js.map +0 -1
  323. package/dist/orchestrator/ai-feed-generator.d.ts +0 -210
  324. package/dist/orchestrator/ai-feed-generator.d.ts.map +0 -1
  325. package/dist/orchestrator/ai-feed-generator.js +0 -377
  326. package/dist/orchestrator/ai-feed-generator.js.map +0 -1
  327. package/docs/OMC_TEAM_DEBUG_REPORT.md +0 -285
  328. /package/docs/{plans/archive → exec-plans/completed}/2026-03-03-deps-path-extension-fix.md +0 -0
@@ -0,0 +1,717 @@
1
+ // [META] since:2026-03-22 | owner:release-team | stable:true
2
+ // [WHY] 发布前全面检查 - 基于 AI_FRIENDLINESS_AUDIT.md 的强制护栏
3
+ // 确保每次发布都符合 AI 友好文档的行业标准
4
+
5
+ import { existsSync, readFileSync, statSync } from 'node:fs';
6
+ import { readdir } from 'node:fs/promises';
7
+ import path from 'node:path';
8
+ import { fileURLToPath } from 'node:url';
9
+
10
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
11
+ const rootDir = path.resolve(__dirname, '..');
12
+
13
+ // 颜色输出
14
+ const colors = {
15
+ red: (s) => `\x1b[31m${s}\x1b[0m`,
16
+ green: (s) => `\x1b[32m${s}\x1b[0m`,
17
+ yellow: (s) => `\x1b[33m${s}\x1b[0m`,
18
+ blue: (s) => `\x1b[34m${s}\x1b[0m`,
19
+ bold: (s) => `\x1b[1m${s}\x1b[0m`,
20
+ };
21
+
22
+ const { red, green, yellow, blue, bold } = colors;
23
+
24
+ // ============================================
25
+ // 检查配置
26
+ // ============================================
27
+
28
+ const MAX_FILE_SIZE_KB = 50; // 单个AI文档最大50KB
29
+ const MAX_TOTAL_AI_DOCS_KB = 500; // 所有AI文档总计最大500KB
30
+ const MAX_LLMSTXT_TOKEN_ESTIMATE = 5000; // llms.txt 估算token限制
31
+
32
+ const requiredAIDocs = [
33
+ { file: 'llms.txt', required: true, minSize: 100, maxSize: 10000 },
34
+ { file: 'AI_GUIDE.md', required: true, minSize: 1000, maxSize: 50000 },
35
+ { file: 'AI_DISCOVERY.md', required: true, minSize: 1000, maxSize: 50000 },
36
+ { file: 'ai-document-index.yaml', required: true, minSize: 500, maxSize: 50000 },
37
+ { file: 'docs/ai-guide/README.md', required: true, minSize: 500, maxSize: 30000 },
38
+ { file: 'docs/ai-guide/QUICKSTART.md', required: true, minSize: 1000, maxSize: 50000 },
39
+ { file: 'docs/ai-guide/COMMANDS.md', required: true, minSize: 2000, maxSize: 100000 },
40
+ { file: 'docs/ai-guide/OUTPUT.md', required: true, minSize: 2000, maxSize: 100000 },
41
+ { file: 'docs/ai-guide/PATTERNS.md', required: true, minSize: 2000, maxSize: 100000 },
42
+ { file: 'docs/ai-guide/PROMPTS.md', required: true, minSize: 2000, maxSize: 100000 },
43
+ { file: 'docs/ai-guide/INTEGRATION.md', required: true, minSize: 2000, maxSize: 150000 },
44
+ ];
45
+
46
+ // 版本必须一致的文件
47
+ const versionFiles = [
48
+ { file: 'package.json', extractor: (c) => JSON.parse(c).version },
49
+ { file: 'llms.txt', extractor: extractVersionFromText },
50
+ { file: 'ai-document-index.yaml', extractor: extractVersionFromYAML },
51
+ { file: 'AI_GUIDE.md', extractor: extractVersionFromText },
52
+ { file: 'AI_DISCOVERY.md', extractor: extractVersionFromText },
53
+ ];
54
+
55
+ // 必需的发布相关文件检查
56
+ const releaseRequirements = {
57
+ changelog: { file: 'CHANGELOG.md', required: true },
58
+ license: { file: 'LICENSE', required: true },
59
+ readme: { file: 'README.md', required: true },
60
+ };
61
+
62
+ // 必须存在的交叉引用
63
+ const requiredCrossRefs = [
64
+ { from: 'llms.txt', mustReference: ['AI_GUIDE.md', 'ai-document-index.yaml'] },
65
+ { from: 'AI_GUIDE.md', mustReference: ['AI_DISCOVERY.md', 'ai-document-index.yaml', 'docs/ai-guide/'] },
66
+ { from: 'README.md', mustReference: ['AI_GUIDE.md'] },
67
+ { from: 'AGENTS.md', mustReference: ['AI 友好'] },
68
+ { from: 'CLAUDE.md', mustReference: ['AI_GUIDE.md', 'docs/ai-guide/'] },
69
+ ];
70
+
71
+ // llms.txt 标准要求 (基于 llmstxt.org)
72
+ const llmsTxtStandards = {
73
+ mustHaveH1: /^#\s+\w+/m,
74
+ mustHaveSummary: /^>\s+/m,
75
+ mustHaveDocsSection: /##\s*(?:文档|Docs|快速开始|Quick Start)/i,
76
+ mustHaveLinks: /\[.+\]\(.+\)/,
77
+ recommendedSections: ['快速开始', '完整文档', 'Full Documentation', '可选', 'Optional'],
78
+ };
79
+
80
+ // ============================================
81
+ // 工具函数
82
+ // ============================================
83
+
84
+ function readText(filePath) {
85
+ const absolutePath = path.join(rootDir, filePath);
86
+ if (!existsSync(absolutePath)) return null;
87
+ return readFileSync(absolutePath, 'utf8');
88
+ }
89
+
90
+ function getFileSize(filePath) {
91
+ const absolutePath = path.join(rootDir, filePath);
92
+ if (!existsSync(absolutePath)) return 0;
93
+ return statSync(absolutePath).size;
94
+ }
95
+
96
+ function extractVersionFromText(content) {
97
+ // 匹配 "version: x.x.x" 或 "版本: x.x.x" 或 "Version x.x.x"
98
+ const match = content.match(/(?:version|版本)[:\s]+v?(\d+\.\d+\.\d+)/i);
99
+ return match ? match[1] : null;
100
+ }
101
+
102
+ function extractVersionFromYAML(content) {
103
+ // 匹配 YAML 中的 version: "x.x.x" 或 version: x.x.x
104
+ const match = content.match(/version[:\s]+["']?(\d+\.\d+\.\d+)["']?/i);
105
+ return match ? match[1] : null;
106
+ }
107
+
108
+ function estimateTokens(text) {
109
+ // 简化的token估算:英文单词 + 中文字符
110
+ const englishWords = (text.match(/\b\w+\b/g) || []).length;
111
+ const chineseChars = (text.match(/[\u4e00-\u9fa5]/g) || []).length;
112
+ return Math.ceil(englishWords * 1.3 + chineseChars * 2);
113
+ }
114
+
115
+ // ============================================
116
+ // 检查项
117
+ // ============================================
118
+
119
+ async function checkRequiredFiles(failures) {
120
+ console.log(blue('\n📁 1. AI文档完整性检查\n'));
121
+
122
+ let totalSize = 0;
123
+
124
+ for (const { file, required, minSize, maxSize } of requiredAIDocs) {
125
+ const content = readText(file);
126
+ const size = getFileSize(file);
127
+ totalSize += size;
128
+
129
+ if (!content) {
130
+ if (required) {
131
+ failures.push({
132
+ type: 'missing_required_file',
133
+ file,
134
+ message: `缺少必需的AI文档: ${file}`,
135
+ });
136
+ console.log(red(` ❌ ${file} - 文件不存在`));
137
+ } else {
138
+ console.log(yellow(` ⚠️ ${file} - 可选文件不存在`));
139
+ }
140
+ continue;
141
+ }
142
+
143
+ if (size < minSize) {
144
+ failures.push({
145
+ type: 'file_too_small',
146
+ file,
147
+ message: `${file} 太小 (${size} bytes, 最小要求 ${minSize})`,
148
+ });
149
+ console.log(red(` ❌ ${file} - 文件太小 (${size} bytes)`));
150
+ } else if (size > maxSize) {
151
+ failures.push({
152
+ type: 'file_too_large',
153
+ file,
154
+ message: `${file} 太大 (${Math.round(size/1024)}KB, 最大允许 ${Math.round(maxSize/1024)}KB)`,
155
+ });
156
+ console.log(red(` ❌ ${file} - 文件太大 (${Math.round(size/1024)}KB)`));
157
+ } else {
158
+ console.log(green(` ✅ ${file} (${Math.round(size/1024)}KB)`));
159
+ }
160
+ }
161
+
162
+ // 总大小检查
163
+ const totalSizeKB = Math.round(totalSize / 1024);
164
+ if (totalSizeKB > MAX_TOTAL_AI_DOCS_KB) {
165
+ failures.push({
166
+ type: 'total_size_exceeded',
167
+ message: `AI文档总大小 ${totalSizeKB}KB 超过限制 ${MAX_TOTAL_AI_DOCS_KB}KB`,
168
+ });
169
+ console.log(red(`\n ❌ 总大小: ${totalSizeKB}KB (限制: ${MAX_TOTAL_AI_DOCS_KB}KB)`));
170
+ } else {
171
+ console.log(green(`\n ✅ 总大小: ${totalSizeKB}KB (限制: ${MAX_TOTAL_AI_DOCS_KB}KB)`));
172
+ }
173
+ }
174
+
175
+ async function checkLlmsTxtStandards(failures) {
176
+ console.log(blue('\n📋 2. llms.txt 标准格式检查\n'));
177
+
178
+ const content = readText('llms.txt');
179
+ if (!content) {
180
+ failures.push({
181
+ type: 'missing_llms_txt',
182
+ message: '缺少 llms.txt 文件 (llmstxt.org 标准要求)',
183
+ });
184
+ console.log(red(' ❌ llms.txt 不存在'));
185
+ return;
186
+ }
187
+
188
+ const checks = [
189
+ { name: 'H1标题', test: llmsTxtStandards.mustHaveH1, required: true },
190
+ { name: '摘要引用', test: llmsTxtStandards.mustHaveSummary, required: true },
191
+ { name: '文档章节', test: llmsTxtStandards.mustHaveDocsSection, required: true },
192
+ { name: '链接格式', test: llmsTxtStandards.mustHaveLinks, required: true },
193
+ ];
194
+
195
+ for (const { name, test, required } of checks) {
196
+ if (test.test(content)) {
197
+ console.log(green(` ✅ ${name}`));
198
+ } else if (required) {
199
+ failures.push({
200
+ type: 'llms_txt_standard_violation',
201
+ file: 'llms.txt',
202
+ message: `llms.txt 缺少必需的 ${name}`,
203
+ });
204
+ console.log(red(` ❌ ${name} (必需)`));
205
+ } else {
206
+ console.log(yellow(` ⚠️ ${name} (建议)`));
207
+ }
208
+ }
209
+
210
+ // Token效率检查
211
+ const tokens = estimateTokens(content);
212
+ if (tokens > MAX_LLMSTXT_TOKEN_ESTIMATE) {
213
+ failures.push({
214
+ type: 'llms_txt_token_limit',
215
+ file: 'llms.txt',
216
+ message: `llms.txt 估算 token 数 ${tokens} 超过限制 ${MAX_LLMSTXT_TOKEN_ESTIMATE}`,
217
+ });
218
+ console.log(red(` ❌ Token估算: ${tokens} (限制: ${MAX_LLMSTXT_TOKEN_ESTIMATE})`));
219
+ } else {
220
+ console.log(green(` ✅ Token估算: ${tokens} (限制: ${MAX_LLMSTXT_TOKEN_ESTIMATE})`));
221
+ }
222
+ }
223
+
224
+ async function checkVersionConsistency(failures) {
225
+ console.log(blue('\n🔢 3. 版本一致性检查\n'));
226
+
227
+ const versions = {};
228
+
229
+ for (const { file, extractor } of versionFiles) {
230
+ const content = readText(file);
231
+ if (!content) {
232
+ console.log(yellow(` ⚠️ ${file} - 文件不存在`));
233
+ continue;
234
+ }
235
+
236
+ const version = extractor(content);
237
+ if (version) {
238
+ versions[file] = version;
239
+ console.log(` 📄 ${file}: v${version}`);
240
+ } else {
241
+ console.log(yellow(` ⚠️ ${file}: 未找到版本号`));
242
+ }
243
+ }
244
+
245
+ const uniqueVersions = [...new Set(Object.values(versions))];
246
+ if (uniqueVersions.length === 0) {
247
+ failures.push({
248
+ type: 'no_version_found',
249
+ message: '未在任何文件中找到版本号',
250
+ });
251
+ console.log(red('\n ❌ 未找到任何版本号'));
252
+ } else if (uniqueVersions.length > 1) {
253
+ failures.push({
254
+ type: 'version_mismatch',
255
+ message: `版本号不一致: ${uniqueVersions.join(', ')}`,
256
+ details: versions,
257
+ });
258
+ console.log(red(`\n ❌ 版本号不一致: ${uniqueVersions.join(', ')}`));
259
+ console.log(red(` 请确保所有文件版本号一致`));
260
+ } else {
261
+ console.log(green(`\n ✅ 所有文件版本一致: v${uniqueVersions[0]}`));
262
+ }
263
+
264
+ // 语义版本格式检查
265
+ const pkgVersion = versions['package.json'];
266
+ if (pkgVersion && !/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(pkgVersion)) {
267
+ failures.push({
268
+ type: 'invalid_semver',
269
+ message: `package.json 版本号 "${pkgVersion}" 不符合语义化版本规范`,
270
+ });
271
+ console.log(red(` ❌ 版本号格式无效: ${pkgVersion}`));
272
+ }
273
+ }
274
+
275
+ async function checkCrossReferences(failures) {
276
+ console.log(blue('\n🔗 4. 交叉引用有效性检查\n'));
277
+
278
+ for (const { from, mustReference } of requiredCrossRefs) {
279
+ const content = readText(from);
280
+ if (!content) {
281
+ console.log(yellow(` ⚠️ ${from} - 文件不存在,跳过引用检查`));
282
+ continue;
283
+ }
284
+
285
+ const missing = mustReference.filter(ref => !content.includes(ref));
286
+ if (missing.length > 0) {
287
+ failures.push({
288
+ type: 'missing_cross_reference',
289
+ file: from,
290
+ message: `${from} 缺少必需引用: ${missing.join(', ')}`,
291
+ });
292
+ console.log(red(` ❌ ${from} - 缺少: ${missing.join(', ')}`));
293
+ } else {
294
+ console.log(green(` ✅ ${from} - 所有必需引用存在`));
295
+ }
296
+ }
297
+
298
+ // 验证链接目标文件存在
299
+ console.log(blue('\n 验证链接目标文件存在性:\n'));
300
+
301
+ const allContent = requiredAIDocs.map(d => readText(d.file)).filter(Boolean).join('\n');
302
+ const linkPattern = /\[.*?\]\((.*?)\)/g;
303
+ const links = [];
304
+ let match;
305
+
306
+ while ((match = linkPattern.exec(allContent)) !== null) {
307
+ const link = match[1];
308
+ // 只检查相对路径的本地文件
309
+ if (!link.startsWith('http') && !link.startsWith('#')) {
310
+ links.push(link.replace(/^\.\//, '').split('#')[0]);
311
+ }
312
+ }
313
+
314
+ const uniqueLinks = [...new Set(links)];
315
+ let brokenLinks = 0;
316
+
317
+ for (const link of uniqueLinks.slice(0, 30)) { // 限制检查数量
318
+ // 跳过锚点链接和特殊路径
319
+ if (link.includes('#') || link === 'LICENSE' || link === 'CHANGELOG.md') {
320
+ continue;
321
+ }
322
+
323
+ const linkPath = path.join(rootDir, link);
324
+ if (!existsSync(linkPath)) {
325
+ // 可能是目录
326
+ if (!existsSync(path.join(linkPath, 'README.md'))) {
327
+ console.log(yellow(` ⚠️ 可能损坏的链接: ${link}`));
328
+ brokenLinks++;
329
+ }
330
+ }
331
+ }
332
+
333
+ if (brokenLinks === 0) {
334
+ console.log(green(` ✅ 所有检查的内部链接有效`));
335
+ } else {
336
+ console.log(yellow(` ⚠️ 发现 ${brokenLinks} 个可能损坏的链接`));
337
+ }
338
+ }
339
+
340
+ async function checkAIFriendliness(failures) {
341
+ console.log(blue('\n🤖 5. AI友好性检查\n'));
342
+
343
+ const aiGuide = readText('AI_GUIDE.md');
344
+ if (!aiGuide) {
345
+ console.log(red(' ❌ AI_GUIDE.md 不存在'));
346
+ return;
347
+ }
348
+
349
+ const checks = [
350
+ { name: '层级标题 (##)', pattern: /^##+\s+/m },
351
+ { name: '表格 (速查表)', pattern: /\|.*\|.*\|/ },
352
+ { name: '代码块', pattern: /```(?:bash|typescript|json)/ },
353
+ { name: 'TypeScript接口', pattern: /interface\s+\w+/ },
354
+ { name: '决策树/流程图', pattern: /决策树|流程图|```mermaid/ },
355
+ { name: '提示词模板', pattern: /提示词|模板|prompt/i },
356
+ ];
357
+
358
+ for (const { name, pattern } of checks) {
359
+ if (pattern.test(aiGuide)) {
360
+ console.log(green(` ✅ ${name}`));
361
+ } else {
362
+ console.log(yellow(` ⚠️ ${name} (建议添加)`));
363
+ }
364
+ }
365
+ }
366
+
367
+ async function checkChangelogSync(failures) {
368
+ console.log(blue('\n📝 6. CHANGELOG同步检查\n'));
369
+
370
+ const changelog = readText('CHANGELOG.md');
371
+ const pkg = readText('package.json');
372
+
373
+ if (!changelog) {
374
+ failures.push({
375
+ type: 'missing_changelog',
376
+ message: '缺少 CHANGELOG.md',
377
+ });
378
+ console.log(red(' ❌ CHANGELOG.md 不存在'));
379
+ return;
380
+ }
381
+
382
+ if (!pkg) {
383
+ console.log(red(' ❌ package.json 不存在'));
384
+ return;
385
+ }
386
+
387
+ const pkgVersion = JSON.parse(pkg).version;
388
+
389
+ // 检查CHANGELOG中是否有当前版本
390
+ const versionHeader = new RegExp(`##?\\s*\\[?${pkgVersion}\\]?`, 'i');
391
+ if (versionHeader.test(changelog)) {
392
+ console.log(green(` ✅ CHANGELOG 包含当前版本 v${pkgVersion}`));
393
+ } else {
394
+ failures.push({
395
+ type: 'changelog_not_synced',
396
+ message: `CHANGELOG.md 缺少当前版本 v${pkgVersion} 的条目`,
397
+ });
398
+ console.log(red(` ❌ CHANGELOG 缺少 v${pkgVersion} 条目`));
399
+ }
400
+
401
+ // 检查CHANGELOG是否包含AI文档更新记录
402
+ const hasAIDocsMention = /AI.*文档|llms\.txt|AI_GUIDE/i.test(changelog);
403
+ if (hasAIDocsMention) {
404
+ console.log(green(` ✅ CHANGELOG 包含AI文档相关记录`));
405
+ } else {
406
+ console.log(yellow(` ⚠️ CHANGELOG 未提及AI文档更新 (建议)`));
407
+ }
408
+ }
409
+
410
+ async function checkYamlIndex(failures) {
411
+ console.log(blue('\n📊 7. YAML索引有效性检查\n'));
412
+
413
+ const content = readText('ai-document-index.yaml');
414
+ if (!content) {
415
+ console.log(red(' ❌ ai-document-index.yaml 不存在'));
416
+ return;
417
+ }
418
+
419
+ const checks = [
420
+ { name: 'project 字段', pattern: /^project:/m },
421
+ { name: 'version 字段', pattern: /^\s+version:/m },
422
+ { name: 'documentation 字段', pattern: /^documentation:/m },
423
+ { name: 'ai_documents 列表', pattern: /ai_documents:/ },
424
+ { name: 'cli_commands 索引', pattern: /cli_commands:/ },
425
+ { name: 'navigation 配置', pattern: /navigation:/ },
426
+ ];
427
+
428
+ for (const { name, pattern } of checks) {
429
+ if (pattern.test(content)) {
430
+ console.log(green(` ✅ ${name}`));
431
+ } else {
432
+ failures.push({
433
+ type: 'yaml_structure_missing',
434
+ file: 'ai-document-index.yaml',
435
+ message: `缺少 ${name}`,
436
+ });
437
+ console.log(red(` ❌ ${name}`));
438
+ }
439
+ }
440
+
441
+ // 检查引用的文件是否都存在
442
+ console.log(blue('\n 验证YAML中引用的文件:\n'));
443
+ const docMatches = content.matchAll(/path:\s*["']?([^"'\n]+)["']?/g);
444
+ const paths = [...docMatches]
445
+ .map(m => m[1])
446
+ .filter(p => !p.startsWith('http'))
447
+ .map(p => p.split('#')[0]); // 移除锚点
448
+
449
+ let missingFiles = 0;
450
+ for (const p of paths) {
451
+ if (!existsSync(path.join(rootDir, p))) {
452
+ console.log(red(` ❌ 文件不存在: ${p}`));
453
+ missingFiles++;
454
+ }
455
+ }
456
+
457
+ if (missingFiles === 0) {
458
+ console.log(green(` ✅ 所有引用的文件存在 (${paths.length} 个)`));
459
+ } else {
460
+ failures.push({
461
+ type: 'yaml_missing_files',
462
+ message: `YAML索引引用了 ${missingFiles} 个不存在的文件`,
463
+ });
464
+ }
465
+ }
466
+
467
+ async function checkDocumentationStandards(failures) {
468
+ console.log(blue('\n📚 8. AGENTS.md 文档规范检查\n'));
469
+
470
+ const agents = readText('AGENTS.md');
471
+ if (!agents) {
472
+ console.log(red(' ❌ AGENTS.md 不存在'));
473
+ return;
474
+ }
475
+
476
+ const requiredSections = [
477
+ { name: 'AI友好文档规范', pattern: /AI.*友好.*文档|AI.*文档.*规范/i },
478
+ { name: '结构清晰要求', pattern: /结构清晰|层级标题/i },
479
+ { name: '决策树要求', pattern: /决策树|流程图/i },
480
+ { name: '速查表要求', pattern: /速查表|表格/i },
481
+ { name: '代码可复现要求', pattern: /代码.*复现|可执行.*代码/i },
482
+ { name: '类型定义要求', pattern: /类型定义|TypeScript.*接口/i },
483
+ { name: '提示词模板要求', pattern: /提示词|模板/i },
484
+ ];
485
+
486
+ for (const { name, pattern } of requiredSections) {
487
+ if (pattern.test(agents)) {
488
+ console.log(green(` ✅ ${name}`));
489
+ } else {
490
+ failures.push({
491
+ type: 'agents_requirement_missing',
492
+ message: `AGENTS.md 缺少 ${name}`,
493
+ });
494
+ console.log(red(` ❌ ${name}`));
495
+ }
496
+ }
497
+ }
498
+
499
+ async function checkReleaseFiles(failures) {
500
+ console.log(blue('\n📦 9. 发布必需文件检查\n'));
501
+
502
+ for (const [key, { file, required }] of Object.entries(releaseRequirements)) {
503
+ const content = readText(file);
504
+
505
+ if (!content) {
506
+ if (required) {
507
+ failures.push({
508
+ type: 'missing_release_file',
509
+ file,
510
+ message: `缺少发布必需文件: ${file}`,
511
+ });
512
+ console.log(red(` ❌ ${file} (必需)`));
513
+ } else {
514
+ console.log(yellow(` ⚠️ ${file} (建议)`));
515
+ }
516
+ } else {
517
+ const size = getFileSize(file);
518
+ console.log(green(` ✅ ${file} (${Math.round(size/1024)}KB)`));
519
+ }
520
+ }
521
+ }
522
+
523
+ async function checkGitTag(failures) {
524
+ console.log(blue('\n🏷️ 10. Git Tag 一致性检查\n'));
525
+
526
+ // 获取 package.json 版本
527
+ const pkg = readText('package.json');
528
+ if (!pkg) {
529
+ console.log(red(' ❌ package.json 不存在'));
530
+ return;
531
+ }
532
+
533
+ const pkgVersion = JSON.parse(pkg).version;
534
+ const expectedTag = `v${pkgVersion}`;
535
+
536
+ console.log(` 📦 package.json 版本: v${pkgVersion}`);
537
+ console.log(` 🏷️ 期望的 tag: ${expectedTag}`);
538
+
539
+ // 检查本地 tag 是否存在
540
+ try {
541
+ const { execSync } = await import('node:child_process');
542
+
543
+ // 检查本地 tag
544
+ try {
545
+ const localTag = execSync(`git tag -l "${expectedTag}"`, { encoding: 'utf8', cwd: rootDir }).trim();
546
+ if (localTag === expectedTag) {
547
+ console.log(green(` ✅ 本地 tag ${expectedTag} 已存在`));
548
+
549
+ // 检查 tag 是否指向当前 commit
550
+ const tagCommit = execSync(`git rev-list -n1 "${expectedTag}"`, { encoding: 'utf8', cwd: rootDir }).trim();
551
+ const currentCommit = execSync('git rev-parse HEAD', { encoding: 'utf8', cwd: rootDir }).trim();
552
+
553
+ if (tagCommit === currentCommit) {
554
+ console.log(green(` ✅ Tag 指向当前 commit`));
555
+ } else {
556
+ console.log(yellow(` ⚠️ Tag 指向不同 commit`));
557
+ console.log(yellow(` Tag commit: ${tagCommit.substring(0, 8)}`));
558
+ console.log(yellow(` Current: ${currentCommit.substring(0, 8)}`));
559
+ }
560
+ } else {
561
+ console.log(yellow(` ⚠️ 本地 tag ${expectedTag} 不存在`));
562
+ console.log(yellow(` 运行: git tag -a "${expectedTag}" -m "Release ${expectedTag}"`));
563
+ }
564
+ } catch (e) {
565
+ console.log(yellow(` ⚠️ 无法检查本地 tag`));
566
+ }
567
+
568
+ // 检查远程 tag
569
+ try {
570
+ const remoteTag = execSync(`git ls-remote --tags origin "refs/tags/${expectedTag}"`, { encoding: 'utf8', cwd: rootDir }).trim();
571
+ if (remoteTag.includes(expectedTag)) {
572
+ console.log(green(` ✅ 远程 tag ${expectedTag} 已存在`));
573
+ } else {
574
+ console.log(yellow(` ⚠️ 远程 tag ${expectedTag} 不存在`));
575
+ console.log(yellow(` 推送命令: git push origin "${expectedTag}"`));
576
+ }
577
+ } catch (e) {
578
+ console.log(yellow(` ⚠️ 无法检查远程 tag (可能没有远程仓库)`));
579
+ }
580
+
581
+ // 检查 GitHub Release (如果配置了 gh CLI)
582
+ try {
583
+ const ghCheck = execSync('which gh', { encoding: 'utf8', stdio: 'pipe' });
584
+ if (ghCheck) {
585
+ try {
586
+ const releaseInfo = execSync(`gh release view "${expectedTag}" 2>&1`, { encoding: 'utf8', cwd: rootDir, stdio: 'pipe' });
587
+ if (releaseInfo.includes(expectedTag)) {
588
+ console.log(green(` ✅ GitHub Release ${expectedTag} 已存在`));
589
+ }
590
+ } catch (e) {
591
+ console.log(yellow(` ⚠️ GitHub Release ${expectedTag} 不存在`));
592
+ console.log(yellow(` 将在 tag 推送后自动创建`));
593
+ }
594
+ }
595
+ } catch (e) {
596
+ // gh CLI 未安装,跳过
597
+ }
598
+
599
+ } catch (error) {
600
+ console.log(yellow(` ⚠️ Git 检查失败: ${error.message}`));
601
+ }
602
+
603
+ // 检查当前分支
604
+ try {
605
+ const { execSync } = await import('node:child_process');
606
+ const currentBranch = execSync('git branch --show-current', { encoding: 'utf8', cwd: rootDir }).trim();
607
+ console.log(` 🌿 当前分支: ${currentBranch}`);
608
+
609
+ if (currentBranch !== 'main' && currentBranch !== 'master') {
610
+ console.log(yellow(` ⚠️ 不在 main/master 分支,建议切换到 main 分支发布`));
611
+ } else {
612
+ console.log(green(` ✅ 在 ${currentBranch} 分支`));
613
+ }
614
+ } catch (e) {
615
+ // 忽略
616
+ }
617
+ }
618
+
619
+ // ============================================
620
+ // 主函数
621
+ // ============================================
622
+
623
+ async function runPreReleaseChecks() {
624
+ console.log(bold('╔════════════════════════════════════════════════════════════╗'));
625
+ console.log(bold('║ 发布前检查 - AI友好文档护栏 (基于审计报告) ║'));
626
+ console.log(bold('╚════════════════════════════════════════════════════════════╝'));
627
+
628
+ const failures = [];
629
+ const startTime = Date.now();
630
+
631
+ try {
632
+ await checkRequiredFiles(failures);
633
+ await checkLlmsTxtStandards(failures);
634
+ await checkVersionConsistency(failures);
635
+ await checkCrossReferences(failures);
636
+ await checkAIFriendliness(failures);
637
+ await checkChangelogSync(failures);
638
+ await checkYamlIndex(failures);
639
+ await checkDocumentationStandards(failures);
640
+ await checkReleaseFiles(failures);
641
+ await checkGitTag(failures);
642
+ } catch (error) {
643
+ console.error(red(`\n检查过程中发生错误: ${error.message}`));
644
+ process.exit(1);
645
+ }
646
+
647
+ const duration = Date.now() - startTime;
648
+
649
+ // 结果汇总
650
+ console.log(bold('\n╔════════════════════════════════════════════════════════════╗'));
651
+ console.log(bold('║ 检查结果汇总 ║'));
652
+ console.log(bold('╚════════════════════════════════════════════════════════════╝'));
653
+
654
+ const criticalFailures = failures.filter(f =>
655
+ f.type === 'missing_required_file' ||
656
+ f.type === 'missing_llms_txt' ||
657
+ f.type === 'version_mismatch' ||
658
+ f.type === 'llms_txt_standard_violation' ||
659
+ f.type === 'missing_release_file'
660
+ );
661
+
662
+ const warnings = failures.filter(f =>
663
+ !criticalFailures.includes(f)
664
+ );
665
+
666
+ console.log(`\n⏱️ 耗时: ${duration}ms`);
667
+ console.log(`📝 总检查项: 10`);
668
+ console.log(`❌ 关键错误: ${criticalFailures.length}`);
669
+ console.log(`⚠️ 警告: ${warnings.length}`);
670
+
671
+ if (criticalFailures.length > 0) {
672
+ console.log(red('\n🚫 关键错误 (阻止发布):\n'));
673
+ criticalFailures.forEach((f, i) => {
674
+ console.log(red(` ${i + 1}. [${f.type}] ${f.message}`));
675
+ });
676
+ }
677
+
678
+ if (warnings.length > 0) {
679
+ console.log(yellow('\n⚠️ 警告 (建议修复):\n'));
680
+ warnings.forEach((f, i) => {
681
+ console.log(yellow(` ${i + 1}. [${f.type}] ${f.message}`));
682
+ });
683
+ }
684
+
685
+ // 发布指南
686
+ console.log(bold('\n╔════════════════════════════════════════════════════════════╗'));
687
+ console.log(bold('║ 发布流程指南 ║'));
688
+ console.log(bold('╚════════════════════════════════════════════════════════════╝'));
689
+
690
+ const pkg = readText('package.json');
691
+ if (pkg) {
692
+ const pkgVersion = JSON.parse(pkg).version;
693
+ console.log(`\n当前版本: v${pkgVersion}`);
694
+ console.log('\n📋 发布步骤:');
695
+ console.log(' 1. npm run docs:check:pre-release # 运行此检查');
696
+ console.log(' 2. ./scripts/release.sh patch|minor|major # 或指定版本');
697
+ console.log(' 3. git push origin main --tags # 推送 tag');
698
+ console.log(' 4. GitHub Actions 自动: 构建 → 测试 → 发布 → 创建 Release');
699
+ console.log('\n🔗 相关链接:');
700
+ console.log(` - GitHub Actions: https://github.com/mycodemap/mycodemap/actions`);
701
+ console.log(` - NPM 包: https://www.npmjs.com/package/@mycodemap/mycodemap`);
702
+ }
703
+
704
+ console.log(bold('\n╔════════════════════════════════════════════════════════════╗'));
705
+
706
+ if (criticalFailures.length === 0) {
707
+ console.log(green('║ ✅ 所有关键检查通过 - 可以安全发布! ║'));
708
+ console.log(bold('╚════════════════════════════════════════════════════════════╝'));
709
+ process.exit(0);
710
+ } else {
711
+ console.log(red('║ ❌ 存在关键错误 - 请修复后再发布! ║'));
712
+ console.log(bold('╚════════════════════════════════════════════════════════════╝'));
713
+ process.exit(1);
714
+ }
715
+ }
716
+
717
+ runPreReleaseChecks();