artifact-chain-assistant 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (328) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +20 -0
  3. package/.claude-plugin/plugin.json +11 -0
  4. package/.codex-plugin/plugin.json +27 -0
  5. package/.github/ISSUE_TEMPLATE/bug_report.yml +26 -0
  6. package/.github/ISSUE_TEMPLATE/feature_request.yml +19 -0
  7. package/.github/pull_request_template.md +14 -0
  8. package/.github/workflows/ci.yml +23 -0
  9. package/CHANGELOG.md +196 -0
  10. package/CODE_OF_CONDUCT.md +11 -0
  11. package/CONTRIBUTING.md +24 -0
  12. package/EXTENDED-ARTIFACT-CATALOG.md +312 -0
  13. package/EXTENDED-ARTIFACT-CATALOG.zh-CN.md +289 -0
  14. package/INSTALL.md +1340 -0
  15. package/LICENSE +186 -0
  16. package/NOTICE +18 -0
  17. package/README.md +426 -0
  18. package/README.zh-CN.md +409 -0
  19. package/SECURITY.md +19 -0
  20. package/adapters/claude/.claude-plugin/plugin.json +11 -0
  21. package/adapters/claude/EXTENDED-ARTIFACT-CATALOG.md +312 -0
  22. package/adapters/claude/EXTENDED-ARTIFACT-CATALOG.zh-CN.md +289 -0
  23. package/adapters/claude/INSTALL.md +1340 -0
  24. package/adapters/claude/agent-methods/catalog.yaml +260 -0
  25. package/adapters/claude/bin/version-lock-audit.sh +21 -0
  26. package/adapters/claude/bin/version-lock-refresh.sh +21 -0
  27. package/adapters/claude/commands/version-lock-audit.md +9 -0
  28. package/adapters/claude/commands/version-lock-refresh.md +9 -0
  29. package/adapters/claude/compatibility.json +9 -0
  30. package/adapters/claude/hooks/hooks.json +16 -0
  31. package/adapters/claude/hooks/version-lock-stop.mjs +77 -0
  32. package/adapters/claude/schemas/artifact-workflow-profile.schema.json +72 -0
  33. package/adapters/claude/scripts/batch-merge.mjs +276 -0
  34. package/adapters/claude/scripts/batch-split.mjs +184 -0
  35. package/adapters/claude/scripts/check-workflow-profile.mjs +64 -0
  36. package/adapters/claude/scripts/doctor.mjs +44 -0
  37. package/adapters/claude/scripts/lib/artifact-graph-runtime.mjs +189 -0
  38. package/adapters/claude/scripts/lib/compatibility-policy.mjs +435 -0
  39. package/adapters/claude/scripts/lib/inline-yaml-parser.mjs +216 -0
  40. package/adapters/claude/scripts/lib/method-registry-version.mjs +7 -0
  41. package/adapters/claude/scripts/lib/workflow-profile.mjs +645 -0
  42. package/adapters/claude/scripts/run-artifact-workflow.mjs +366 -0
  43. package/adapters/claude/skills/artifact-audit/SKILL.md +80 -0
  44. package/adapters/claude/skills/artifact-batch/SKILL.md +115 -0
  45. package/adapters/claude/skills/artifact-chain-bootstrap/SKILL.md +343 -0
  46. package/adapters/claude/skills/artifact-chain-maintainer/SKILL.md +167 -0
  47. package/adapters/claude/skills/artifact-generate/SKILL.md +89 -0
  48. package/adapters/claude/skills/artifact-repair/SKILL.md +124 -0
  49. package/adapters/claude/skills/artifact-review/SKILL.md +122 -0
  50. package/adapters/claude/skills/artifact-workflow-worker/SKILL.md +90 -0
  51. package/adapters/claude/skills/prd-feature/SKILL.md +68 -0
  52. package/adapters/claude/skills/prd-feature/author/SKILL.md +92 -0
  53. package/adapters/claude/skills/prd-feature/references/compose.md +43 -0
  54. package/adapters/claude/skills/prd-feature/references/inspect.md +94 -0
  55. package/adapters/claude/skills/prd-feature/references/validate.md +65 -0
  56. package/adapters/claude/skills/prd-feature/repair/SKILL.md +135 -0
  57. package/adapters/claude/skills/prd-feature/review/SKILL.md +134 -0
  58. package/adapters/claude/skills/scenario-script/SKILL.md +76 -0
  59. package/adapters/claude/skills/scenario-script/author/SKILL.md +111 -0
  60. package/adapters/claude/skills/scenario-script/references/compose.md +43 -0
  61. package/adapters/claude/skills/scenario-script/references/inspect.md +105 -0
  62. package/adapters/claude/skills/scenario-script/references/validate.md +72 -0
  63. package/adapters/claude/skills/scenario-script/repair/SKILL.md +135 -0
  64. package/adapters/claude/skills/scenario-script/review/SKILL.md +137 -0
  65. package/adapters/claude/skills/where-am-i/SKILL.md +233 -0
  66. package/adapters/claude/templates/README.md +159 -0
  67. package/adapters/claude/templates/core/decision/review-checklist.md +35 -0
  68. package/adapters/claude/templates/core/decision/starter.md +66 -0
  69. package/adapters/claude/templates/core/design/review-checklist.md +41 -0
  70. package/adapters/claude/templates/core/design/starter.md +84 -0
  71. package/adapters/claude/templates/core/e2e_test/review-checklist.md +43 -0
  72. package/adapters/claude/templates/core/e2e_test/starter.md +70 -0
  73. package/adapters/claude/templates/core/feature/review-checklist.md +29 -0
  74. package/adapters/claude/templates/core/feature/starter.md +43 -0
  75. package/adapters/claude/templates/core/scenario/review-checklist.md +29 -0
  76. package/adapters/claude/templates/core/scenario/starter.md +57 -0
  77. package/adapters/claude/templates/core/test/review-checklist.md +37 -0
  78. package/adapters/claude/templates/core/test/starter.md +70 -0
  79. package/adapters/claude/templates/extended/ADOPTION-GUIDE.md +263 -0
  80. package/adapters/claude/templates/extended/README.md +261 -0
  81. package/adapters/claude/templates/extended/agent/agent_skill/review-checklist.md +51 -0
  82. package/adapters/claude/templates/extended/agent/agent_skill/starter.md +133 -0
  83. package/adapters/claude/templates/extended/agent/hook_policy/review-checklist.md +58 -0
  84. package/adapters/claude/templates/extended/agent/hook_policy/starter.md +134 -0
  85. package/adapters/claude/templates/extended/agent/prompt_packet/review-checklist.md +54 -0
  86. package/adapters/claude/templates/extended/agent/prompt_packet/starter.md +106 -0
  87. package/adapters/claude/templates/extended/contracts/api_contract/review-checklist.md +43 -0
  88. package/adapters/claude/templates/extended/contracts/api_contract/starter.md +92 -0
  89. package/adapters/claude/templates/extended/contracts/batch_job_contract/review-checklist.md +82 -0
  90. package/adapters/claude/templates/extended/contracts/batch_job_contract/starter.md +158 -0
  91. package/adapters/claude/templates/extended/contracts/cli_contract/review-checklist.md +43 -0
  92. package/adapters/claude/templates/extended/contracts/cli_contract/starter.md +93 -0
  93. package/adapters/claude/templates/extended/contracts/data_contract/review-checklist.md +45 -0
  94. package/adapters/claude/templates/extended/contracts/data_contract/starter.md +88 -0
  95. package/adapters/claude/templates/extended/contracts/integration_contract/review-checklist.md +77 -0
  96. package/adapters/claude/templates/extended/contracts/integration_contract/starter.md +158 -0
  97. package/adapters/claude/templates/extended/contracts/ipc_contract/review-checklist.md +78 -0
  98. package/adapters/claude/templates/extended/contracts/ipc_contract/starter.md +214 -0
  99. package/adapters/claude/templates/extended/contracts/report_contract/review-checklist.md +61 -0
  100. package/adapters/claude/templates/extended/contracts/report_contract/starter.md +97 -0
  101. package/adapters/claude/templates/extended/contracts/ui_contract/review-checklist.md +70 -0
  102. package/adapters/claude/templates/extended/contracts/ui_contract/starter.md +150 -0
  103. package/adapters/claude/templates/extended/domain/database_migration/review-checklist.md +51 -0
  104. package/adapters/claude/templates/extended/domain/database_migration/starter.md +115 -0
  105. package/adapters/claude/templates/extended/domain/domain_model/review-checklist.md +43 -0
  106. package/adapters/claude/templates/extended/domain/domain_model/starter.md +83 -0
  107. package/adapters/claude/templates/extended/governance/oss_compliance/review-checklist.md +51 -0
  108. package/adapters/claude/templates/extended/governance/oss_compliance/starter.md +84 -0
  109. package/adapters/claude/templates/extended/governance/publish_skill/review-checklist.md +58 -0
  110. package/adapters/claude/templates/extended/governance/publish_skill/starter.md +172 -0
  111. package/adapters/claude/templates/extended/governance/release_policy/review-checklist.md +57 -0
  112. package/adapters/claude/templates/extended/governance/release_policy/starter.md +131 -0
  113. package/adapters/claude/templates/extended/ops/deployment_manifest/review-checklist.md +51 -0
  114. package/adapters/claude/templates/extended/ops/deployment_manifest/starter.md +117 -0
  115. package/adapters/claude/templates/extended/ops/migration_plan/review-checklist.md +63 -0
  116. package/adapters/claude/templates/extended/ops/migration_plan/starter.md +117 -0
  117. package/adapters/claude/templates/extended/ops/performance_budget/review-checklist.md +50 -0
  118. package/adapters/claude/templates/extended/ops/performance_budget/starter.md +117 -0
  119. package/adapters/claude/templates/extended/ops/runbook/review-checklist.md +51 -0
  120. package/adapters/claude/templates/extended/ops/runbook/starter.md +101 -0
  121. package/adapters/claude/templates/extended/ops/security_review/review-checklist.md +56 -0
  122. package/adapters/claude/templates/extended/ops/security_review/starter.md +125 -0
  123. package/adapters/codex/.codex-plugin/plugin.json +27 -0
  124. package/adapters/codex/EXTENDED-ARTIFACT-CATALOG.md +312 -0
  125. package/adapters/codex/EXTENDED-ARTIFACT-CATALOG.zh-CN.md +289 -0
  126. package/adapters/codex/INSTALL.md +1340 -0
  127. package/adapters/codex/agent-methods/catalog.yaml +260 -0
  128. package/adapters/codex/compatibility.json +9 -0
  129. package/adapters/codex/schemas/artifact-workflow-profile.schema.json +72 -0
  130. package/adapters/codex/scripts/batch-merge.mjs +276 -0
  131. package/adapters/codex/scripts/batch-split.mjs +184 -0
  132. package/adapters/codex/scripts/check-workflow-profile.mjs +64 -0
  133. package/adapters/codex/scripts/doctor.mjs +44 -0
  134. package/adapters/codex/scripts/lib/artifact-graph-runtime.mjs +189 -0
  135. package/adapters/codex/scripts/lib/compatibility-policy.mjs +435 -0
  136. package/adapters/codex/scripts/lib/inline-yaml-parser.mjs +216 -0
  137. package/adapters/codex/scripts/lib/method-registry-version.mjs +7 -0
  138. package/adapters/codex/scripts/lib/workflow-profile.mjs +645 -0
  139. package/adapters/codex/scripts/run-artifact-workflow.mjs +366 -0
  140. package/adapters/codex/skills/artifact-audit/SKILL.md +80 -0
  141. package/adapters/codex/skills/artifact-batch/SKILL.md +115 -0
  142. package/adapters/codex/skills/artifact-chain-bootstrap/SKILL.md +343 -0
  143. package/adapters/codex/skills/artifact-chain-maintainer/SKILL.md +167 -0
  144. package/adapters/codex/skills/artifact-generate/SKILL.md +89 -0
  145. package/adapters/codex/skills/artifact-repair/SKILL.md +124 -0
  146. package/adapters/codex/skills/artifact-review/SKILL.md +122 -0
  147. package/adapters/codex/skills/artifact-workflow-worker/SKILL.md +90 -0
  148. package/adapters/codex/skills/prd-feature/SKILL.md +68 -0
  149. package/adapters/codex/skills/prd-feature/author/SKILL.md +92 -0
  150. package/adapters/codex/skills/prd-feature/references/compose.md +43 -0
  151. package/adapters/codex/skills/prd-feature/references/inspect.md +94 -0
  152. package/adapters/codex/skills/prd-feature/references/validate.md +65 -0
  153. package/adapters/codex/skills/prd-feature/repair/SKILL.md +135 -0
  154. package/adapters/codex/skills/prd-feature/review/SKILL.md +134 -0
  155. package/adapters/codex/skills/scenario-script/SKILL.md +76 -0
  156. package/adapters/codex/skills/scenario-script/author/SKILL.md +111 -0
  157. package/adapters/codex/skills/scenario-script/references/compose.md +43 -0
  158. package/adapters/codex/skills/scenario-script/references/inspect.md +105 -0
  159. package/adapters/codex/skills/scenario-script/references/validate.md +72 -0
  160. package/adapters/codex/skills/scenario-script/repair/SKILL.md +135 -0
  161. package/adapters/codex/skills/scenario-script/review/SKILL.md +137 -0
  162. package/adapters/codex/skills/where-am-i/SKILL.md +233 -0
  163. package/adapters/codex/templates/README.md +159 -0
  164. package/adapters/codex/templates/core/decision/review-checklist.md +35 -0
  165. package/adapters/codex/templates/core/decision/starter.md +66 -0
  166. package/adapters/codex/templates/core/design/review-checklist.md +41 -0
  167. package/adapters/codex/templates/core/design/starter.md +84 -0
  168. package/adapters/codex/templates/core/e2e_test/review-checklist.md +43 -0
  169. package/adapters/codex/templates/core/e2e_test/starter.md +70 -0
  170. package/adapters/codex/templates/core/feature/review-checklist.md +29 -0
  171. package/adapters/codex/templates/core/feature/starter.md +43 -0
  172. package/adapters/codex/templates/core/scenario/review-checklist.md +29 -0
  173. package/adapters/codex/templates/core/scenario/starter.md +57 -0
  174. package/adapters/codex/templates/core/test/review-checklist.md +37 -0
  175. package/adapters/codex/templates/core/test/starter.md +70 -0
  176. package/adapters/codex/templates/extended/ADOPTION-GUIDE.md +263 -0
  177. package/adapters/codex/templates/extended/README.md +261 -0
  178. package/adapters/codex/templates/extended/agent/agent_skill/review-checklist.md +51 -0
  179. package/adapters/codex/templates/extended/agent/agent_skill/starter.md +133 -0
  180. package/adapters/codex/templates/extended/agent/hook_policy/review-checklist.md +58 -0
  181. package/adapters/codex/templates/extended/agent/hook_policy/starter.md +134 -0
  182. package/adapters/codex/templates/extended/agent/prompt_packet/review-checklist.md +54 -0
  183. package/adapters/codex/templates/extended/agent/prompt_packet/starter.md +106 -0
  184. package/adapters/codex/templates/extended/contracts/api_contract/review-checklist.md +43 -0
  185. package/adapters/codex/templates/extended/contracts/api_contract/starter.md +92 -0
  186. package/adapters/codex/templates/extended/contracts/batch_job_contract/review-checklist.md +82 -0
  187. package/adapters/codex/templates/extended/contracts/batch_job_contract/starter.md +158 -0
  188. package/adapters/codex/templates/extended/contracts/cli_contract/review-checklist.md +43 -0
  189. package/adapters/codex/templates/extended/contracts/cli_contract/starter.md +93 -0
  190. package/adapters/codex/templates/extended/contracts/data_contract/review-checklist.md +45 -0
  191. package/adapters/codex/templates/extended/contracts/data_contract/starter.md +88 -0
  192. package/adapters/codex/templates/extended/contracts/integration_contract/review-checklist.md +77 -0
  193. package/adapters/codex/templates/extended/contracts/integration_contract/starter.md +158 -0
  194. package/adapters/codex/templates/extended/contracts/ipc_contract/review-checklist.md +78 -0
  195. package/adapters/codex/templates/extended/contracts/ipc_contract/starter.md +214 -0
  196. package/adapters/codex/templates/extended/contracts/report_contract/review-checklist.md +61 -0
  197. package/adapters/codex/templates/extended/contracts/report_contract/starter.md +97 -0
  198. package/adapters/codex/templates/extended/contracts/ui_contract/review-checklist.md +70 -0
  199. package/adapters/codex/templates/extended/contracts/ui_contract/starter.md +150 -0
  200. package/adapters/codex/templates/extended/domain/database_migration/review-checklist.md +51 -0
  201. package/adapters/codex/templates/extended/domain/database_migration/starter.md +115 -0
  202. package/adapters/codex/templates/extended/domain/domain_model/review-checklist.md +43 -0
  203. package/adapters/codex/templates/extended/domain/domain_model/starter.md +83 -0
  204. package/adapters/codex/templates/extended/governance/oss_compliance/review-checklist.md +51 -0
  205. package/adapters/codex/templates/extended/governance/oss_compliance/starter.md +84 -0
  206. package/adapters/codex/templates/extended/governance/publish_skill/review-checklist.md +58 -0
  207. package/adapters/codex/templates/extended/governance/publish_skill/starter.md +172 -0
  208. package/adapters/codex/templates/extended/governance/release_policy/review-checklist.md +57 -0
  209. package/adapters/codex/templates/extended/governance/release_policy/starter.md +131 -0
  210. package/adapters/codex/templates/extended/ops/deployment_manifest/review-checklist.md +51 -0
  211. package/adapters/codex/templates/extended/ops/deployment_manifest/starter.md +117 -0
  212. package/adapters/codex/templates/extended/ops/migration_plan/review-checklist.md +63 -0
  213. package/adapters/codex/templates/extended/ops/migration_plan/starter.md +117 -0
  214. package/adapters/codex/templates/extended/ops/performance_budget/review-checklist.md +50 -0
  215. package/adapters/codex/templates/extended/ops/performance_budget/starter.md +117 -0
  216. package/adapters/codex/templates/extended/ops/runbook/review-checklist.md +51 -0
  217. package/adapters/codex/templates/extended/ops/runbook/starter.md +101 -0
  218. package/adapters/codex/templates/extended/ops/security_review/review-checklist.md +56 -0
  219. package/adapters/codex/templates/extended/ops/security_review/starter.md +125 -0
  220. package/agent-methods/catalog.yaml +260 -0
  221. package/compatibility.json +9 -0
  222. package/package.json +85 -0
  223. package/runtime/claude/version-lock-stop.mjs +77 -0
  224. package/schemas/artifact-workflow-profile.schema.json +72 -0
  225. package/scripts/batch-merge.mjs +276 -0
  226. package/scripts/batch-split.mjs +184 -0
  227. package/scripts/build-adapters.mjs +195 -0
  228. package/scripts/build-runtime-bundles.mjs +134 -0
  229. package/scripts/check-compatibility.mjs +19 -0
  230. package/scripts/check-method-registry.mjs +461 -0
  231. package/scripts/check-templates.mjs +348 -0
  232. package/scripts/check-workflow-profile.mjs +64 -0
  233. package/scripts/doctor.mjs +44 -0
  234. package/scripts/install-git-hooks.mjs +21 -0
  235. package/scripts/lib/artifact-graph-runtime.mjs +189 -0
  236. package/scripts/lib/compatibility-policy.mjs +435 -0
  237. package/scripts/lib/inline-yaml-parser.mjs +216 -0
  238. package/scripts/lib/method-registry-version.mjs +7 -0
  239. package/scripts/lib/workflow-profile.mjs +645 -0
  240. package/scripts/run-artifact-workflow.mjs +366 -0
  241. package/scripts/sync-skills.mjs +149 -0
  242. package/skills-src/artifact-audit/SKILL.md +80 -0
  243. package/skills-src/artifact-batch/SKILL.md +115 -0
  244. package/skills-src/artifact-chain-bootstrap/SKILL.md +343 -0
  245. package/skills-src/artifact-chain-maintainer/SKILL.md +167 -0
  246. package/skills-src/artifact-generate/SKILL.md +89 -0
  247. package/skills-src/artifact-repair/SKILL.md +124 -0
  248. package/skills-src/artifact-review/SKILL.md +122 -0
  249. package/skills-src/artifact-workflow-worker/SKILL.md +90 -0
  250. package/skills-src/prd-feature/SKILL.md +68 -0
  251. package/skills-src/prd-feature/author/SKILL.md +92 -0
  252. package/skills-src/prd-feature/references/compose.md +43 -0
  253. package/skills-src/prd-feature/references/inspect.md +94 -0
  254. package/skills-src/prd-feature/references/validate.md +65 -0
  255. package/skills-src/prd-feature/repair/SKILL.md +135 -0
  256. package/skills-src/prd-feature/review/SKILL.md +134 -0
  257. package/skills-src/scenario-script/SKILL.md +76 -0
  258. package/skills-src/scenario-script/author/SKILL.md +111 -0
  259. package/skills-src/scenario-script/references/compose.md +43 -0
  260. package/skills-src/scenario-script/references/inspect.md +105 -0
  261. package/skills-src/scenario-script/references/validate.md +72 -0
  262. package/skills-src/scenario-script/repair/SKILL.md +135 -0
  263. package/skills-src/scenario-script/review/SKILL.md +137 -0
  264. package/skills-src/where-am-i/SKILL.md.tpl +233 -0
  265. package/templates/README.md +159 -0
  266. package/templates/claude/marketplace.json.tpl +20 -0
  267. package/templates/claude/plugin.json.tpl +11 -0
  268. package/templates/claude/settings.json.tpl +16 -0
  269. package/templates/codex/marketplace.json.tpl +20 -0
  270. package/templates/codex/plugin.json.tpl +27 -0
  271. package/templates/core/decision/review-checklist.md +35 -0
  272. package/templates/core/decision/starter.md +66 -0
  273. package/templates/core/design/review-checklist.md +41 -0
  274. package/templates/core/design/starter.md +84 -0
  275. package/templates/core/e2e_test/review-checklist.md +43 -0
  276. package/templates/core/e2e_test/starter.md +70 -0
  277. package/templates/core/feature/review-checklist.md +29 -0
  278. package/templates/core/feature/starter.md +43 -0
  279. package/templates/core/scenario/review-checklist.md +29 -0
  280. package/templates/core/scenario/starter.md +57 -0
  281. package/templates/core/test/review-checklist.md +37 -0
  282. package/templates/core/test/starter.md +70 -0
  283. package/templates/extended/ADOPTION-GUIDE.md +263 -0
  284. package/templates/extended/README.md +261 -0
  285. package/templates/extended/agent/agent_skill/review-checklist.md +51 -0
  286. package/templates/extended/agent/agent_skill/starter.md +133 -0
  287. package/templates/extended/agent/hook_policy/review-checklist.md +58 -0
  288. package/templates/extended/agent/hook_policy/starter.md +134 -0
  289. package/templates/extended/agent/prompt_packet/review-checklist.md +54 -0
  290. package/templates/extended/agent/prompt_packet/starter.md +106 -0
  291. package/templates/extended/contracts/api_contract/review-checklist.md +43 -0
  292. package/templates/extended/contracts/api_contract/starter.md +92 -0
  293. package/templates/extended/contracts/batch_job_contract/review-checklist.md +82 -0
  294. package/templates/extended/contracts/batch_job_contract/starter.md +158 -0
  295. package/templates/extended/contracts/cli_contract/review-checklist.md +43 -0
  296. package/templates/extended/contracts/cli_contract/starter.md +93 -0
  297. package/templates/extended/contracts/data_contract/review-checklist.md +45 -0
  298. package/templates/extended/contracts/data_contract/starter.md +88 -0
  299. package/templates/extended/contracts/integration_contract/review-checklist.md +77 -0
  300. package/templates/extended/contracts/integration_contract/starter.md +158 -0
  301. package/templates/extended/contracts/ipc_contract/review-checklist.md +78 -0
  302. package/templates/extended/contracts/ipc_contract/starter.md +214 -0
  303. package/templates/extended/contracts/report_contract/review-checklist.md +61 -0
  304. package/templates/extended/contracts/report_contract/starter.md +97 -0
  305. package/templates/extended/contracts/ui_contract/review-checklist.md +70 -0
  306. package/templates/extended/contracts/ui_contract/starter.md +150 -0
  307. package/templates/extended/domain/database_migration/review-checklist.md +51 -0
  308. package/templates/extended/domain/database_migration/starter.md +115 -0
  309. package/templates/extended/domain/domain_model/review-checklist.md +43 -0
  310. package/templates/extended/domain/domain_model/starter.md +83 -0
  311. package/templates/extended/governance/oss_compliance/review-checklist.md +51 -0
  312. package/templates/extended/governance/oss_compliance/starter.md +84 -0
  313. package/templates/extended/governance/publish_skill/review-checklist.md +58 -0
  314. package/templates/extended/governance/publish_skill/starter.md +172 -0
  315. package/templates/extended/governance/release_policy/review-checklist.md +57 -0
  316. package/templates/extended/governance/release_policy/starter.md +131 -0
  317. package/templates/extended/ops/deployment_manifest/review-checklist.md +51 -0
  318. package/templates/extended/ops/deployment_manifest/starter.md +117 -0
  319. package/templates/extended/ops/migration_plan/review-checklist.md +63 -0
  320. package/templates/extended/ops/migration_plan/starter.md +117 -0
  321. package/templates/extended/ops/performance_budget/review-checklist.md +50 -0
  322. package/templates/extended/ops/performance_budget/starter.md +117 -0
  323. package/templates/extended/ops/runbook/review-checklist.md +51 -0
  324. package/templates/extended/ops/runbook/starter.md +101 -0
  325. package/templates/extended/ops/security_review/review-checklist.md +56 -0
  326. package/templates/extended/ops/security_review/starter.md +125 -0
  327. package/templates/git-hooks/pre-commit.sh +43 -0
  328. package/templates/git-hooks/pre-push.sh +22 -0
@@ -0,0 +1,189 @@
1
+ #!/usr/bin/env node
2
+ // @scenario S-44 @feature ACA13 @feature ACA3
3
+ // @decision D-ACA-15
4
+ import { access, readFile, realpath } from 'node:fs/promises';
5
+ import { delimiter, join, dirname, resolve } from 'node:path';
6
+ import { loadCompatibilityPolicy } from './compatibility-policy.mjs';
7
+
8
+ /**
9
+ * Locate the artifact-graph CLI in a target project, resolve its package version,
10
+ * and compare against the plugin's compatibility policy.
11
+ *
12
+ * Resolution order:
13
+ * 1. <projectRoot>/node_modules/.bin/artifact-graph
14
+ * 2. PATH lookup for artifact-graph
15
+ * 3. ARTIFACT_GRAPH_LEGACY_CLI env var (explicit fallback)
16
+ *
17
+ * For the resolved CLI, look up its owning package.json (name === "artifact-graph")
18
+ * and compare the version field against policy.artifactGraph.verifiedVersion.
19
+ *
20
+ * @param {{ projectRoot: string, env?: Record<string,string> }} opts
21
+ * @returns {Promise<{ok: boolean, cliPath?: string, packagePath?: string, actualVersion?: string, expectedVersion?: string, reason?: string, remediation?: string}>}
22
+ */
23
+ export async function inspectArtifactGraphRuntime({ projectRoot, env }) {
24
+ const pluginRoot = resolve(import.meta.dirname, '..', '..');
25
+ let policy;
26
+ try {
27
+ policy = await loadCompatibilityPolicy(pluginRoot);
28
+ } catch (error) {
29
+ return {
30
+ ok: false,
31
+ reason: 'policy_load_failed',
32
+ remediation: `Failed to load compatibility policy: ${error.message}`,
33
+ expectedVersion: null,
34
+ };
35
+ }
36
+
37
+ const expectedVersion = policy.artifactGraph.verifiedVersion;
38
+ const installSpec = policy.artifactGraph.installSpec;
39
+
40
+ // 1. Try project-local CLI first
41
+ const localBin = join(projectRoot, 'node_modules', '.bin', 'artifact-graph');
42
+ let cliPath = await resolveIfExecutable(localBin);
43
+
44
+ // 2. Try PATH
45
+ if (!cliPath) {
46
+ cliPath = await findOnPath(env ?? process.env);
47
+ }
48
+
49
+ // 3. Try explicit legacy CLI override
50
+ if (!cliPath) {
51
+ const legacy = (env ?? process.env).ARTIFACT_GRAPH_LEGACY_CLI;
52
+ if (legacy) {
53
+ cliPath = await resolveIfExecutable(legacy);
54
+ }
55
+ }
56
+
57
+ if (!cliPath) {
58
+ return {
59
+ ok: false,
60
+ reason: 'cli_not_found',
61
+ expectedVersion,
62
+ remediation: `artifact-graph CLI not found. Run: pnpm add -D ${installSpec}`,
63
+ };
64
+ }
65
+
66
+ // 4. Resolve the owning package.json
67
+ const { packagePath, version } = await resolvePackageVersion(cliPath);
68
+
69
+ if (!version) {
70
+ return {
71
+ ok: false,
72
+ cliPath,
73
+ packagePath,
74
+ reason: 'version_unresolved',
75
+ expectedVersion,
76
+ remediation: `Could not determine artifact-graph version from ${packagePath || cliPath}. Run: pnpm add -D ${installSpec}`,
77
+ };
78
+ }
79
+
80
+ if (version !== expectedVersion) {
81
+ return {
82
+ ok: false,
83
+ cliPath,
84
+ packagePath,
85
+ actualVersion: version,
86
+ expectedVersion,
87
+ reason: 'version_mismatch',
88
+ remediation: `artifact-graph version is ${version}, expected ${expectedVersion}. Run: pnpm add -D ${installSpec}`,
89
+ };
90
+ }
91
+
92
+ return {
93
+ ok: true,
94
+ cliPath,
95
+ packagePath,
96
+ actualVersion: version,
97
+ expectedVersion,
98
+ };
99
+ }
100
+
101
+ /**
102
+ * Resolve a path to its realpath if it exists and is executable (X_OK).
103
+ */
104
+ async function resolveIfExecutable(path) {
105
+ try {
106
+ const real = await realpath(path);
107
+ await access(real, 1); // X_OK = 1
108
+ return real;
109
+ } catch {
110
+ return null;
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Search PATH for artifact-graph binary.
116
+ * Does NOT check ARTIFACT_GRAPH_LEGACY_CLI — that's the caller's fallback.
117
+ */
118
+ export async function findOnPath(env) {
119
+ const pathEnv = env.PATH || '';
120
+ const pathDirs = pathEnv.split(delimiter);
121
+
122
+ for (const dir of pathDirs) {
123
+ if (!dir) continue;
124
+ const candidate = join(dir, 'artifact-graph');
125
+ const resolved = await resolveIfExecutable(candidate);
126
+ if (resolved) return resolved;
127
+ }
128
+
129
+ return null;
130
+ }
131
+
132
+ /**
133
+ * Given a CLI path, find the owning artifact-graph package.json and its version.
134
+ *
135
+ * Strategy:
136
+ * 1. Walk up from the CLI directory looking for package.json with name === "artifact-graph".
137
+ * 2. If CLI is under .bin/, also try walking up from the sibling artifact-graph/ package directory.
138
+ *
139
+ * Returns { packagePath, version } or { packagePath: null, version: null }.
140
+ */
141
+ export async function resolvePackageVersion(cliPath) {
142
+ // Strategy 1: walk up from CLI location
143
+ const result = await walkUpForPackage(dirname(cliPath));
144
+ if (result.packagePath) return result;
145
+
146
+ // Strategy 2: if CLI is under a .bin/ directory, check sibling package directories
147
+ const dir = dirname(cliPath);
148
+ const parentDir = dirname(dir);
149
+ if (dir.endsWith('.bin') || dir.endsWith('.bin/')) {
150
+ // Check parentDir/artifact-graph/package.json directly
151
+ const siblingPkg = join(parentDir, 'artifact-graph', 'package.json');
152
+ try {
153
+ const raw = await readFile(siblingPkg, 'utf8');
154
+ const pkg = JSON.parse(raw);
155
+ if (pkg.name === 'artifact-graph') {
156
+ return { packagePath: siblingPkg, version: pkg.version || null };
157
+ }
158
+ } catch {
159
+ // No sibling package found
160
+ }
161
+ }
162
+
163
+ return { packagePath: null, version: null };
164
+ }
165
+
166
+ async function walkUpForPackage(startDir) {
167
+ let dir = startDir;
168
+ const seen = new Set();
169
+
170
+ while (dir && !seen.has(dir)) {
171
+ seen.add(dir);
172
+ const pkgPath = join(dir, 'package.json');
173
+ try {
174
+ const raw = await readFile(pkgPath, 'utf8');
175
+ const pkg = JSON.parse(raw);
176
+ if (pkg.name === 'artifact-graph') {
177
+ return { packagePath: pkgPath, version: pkg.version || null };
178
+ }
179
+ } catch {
180
+ // No package.json at this level, or not valid JSON
181
+ }
182
+
183
+ const parent = dirname(dir);
184
+ if (parent === dir) break;
185
+ dir = parent;
186
+ }
187
+
188
+ return { packagePath: null, version: null };
189
+ }
@@ -0,0 +1,435 @@
1
+ #!/usr/bin/env node
2
+ // @scenario S-44 @feature ACA13
3
+ // @decision D-ACA-15
4
+ import { readFile, readdir } from 'node:fs/promises';
5
+ import { join, relative } from 'node:path';
6
+
7
+ const REQUIRED_SCHEMA_VERSION = '1.0';
8
+
9
+ /**
10
+ * Load and validate the compatibility policy from pluginRoot.
11
+ * Returns a frozen policy object.
12
+ *
13
+ * @param {string} pluginRoot
14
+ * @returns {Promise<{schemaVersion: string, pluginVersion: string, artifactGraph: {verifiedVersion: string, installSpec: string, githubFallbackSpec: string}}>}
15
+ */
16
+ export async function loadCompatibilityPolicy(pluginRoot) {
17
+ const policyPath = join(pluginRoot, 'compatibility.json');
18
+ let raw;
19
+ try {
20
+ raw = await readFile(policyPath, 'utf8');
21
+ } catch (error) {
22
+ throw new Error(`compatibility.json not found at ${policyPath}: ${error.message}`);
23
+ }
24
+
25
+ let policy;
26
+ try {
27
+ policy = JSON.parse(raw);
28
+ } catch (error) {
29
+ throw new Error(`compatibility.json is not valid JSON: ${error.message}`);
30
+ }
31
+
32
+ if (policy.schemaVersion !== REQUIRED_SCHEMA_VERSION) {
33
+ throw new Error(
34
+ `compatibility.json schemaVersion must be "${REQUIRED_SCHEMA_VERSION}", got "${policy.schemaVersion}"`,
35
+ );
36
+ }
37
+
38
+ if (!policy.pluginVersion || typeof policy.pluginVersion !== 'string') {
39
+ throw new Error('compatibility.json must have a non-empty pluginVersion string');
40
+ }
41
+
42
+ if (!policy.artifactGraph || typeof policy.artifactGraph !== 'object') {
43
+ throw new Error('compatibility.json must have an artifactGraph object');
44
+ }
45
+
46
+ const { verifiedVersion, installSpec, githubFallbackSpec } = policy.artifactGraph;
47
+ if (!verifiedVersion || typeof verifiedVersion !== 'string') {
48
+ throw new Error('compatibility.json artifactGraph must have a non-empty verifiedVersion string');
49
+ }
50
+ if (!installSpec || typeof installSpec !== 'string') {
51
+ throw new Error('compatibility.json artifactGraph must have a non-empty installSpec string');
52
+ }
53
+ if (!githubFallbackSpec || typeof githubFallbackSpec !== 'string') {
54
+ throw new Error('compatibility.json artifactGraph must have a non-empty githubFallbackSpec string');
55
+ }
56
+
57
+ return deepFreeze(policy);
58
+ }
59
+
60
+ /**
61
+ * Validate plugin version consistency, install specs, and documentation against the policy.
62
+ * Returns an array of issue strings. Empty array means no issues.
63
+ *
64
+ * @param {string} pluginRoot
65
+ * @returns {Promise<string[]>}
66
+ */
67
+ export async function validateCompatibilityPolicy(pluginRoot) {
68
+ const issues = [];
69
+ let policy;
70
+ try {
71
+ policy = await loadCompatibilityPolicy(pluginRoot);
72
+ } catch (error) {
73
+ issues.push(`Policy load failed: ${error.message}`);
74
+ return issues;
75
+ }
76
+
77
+ const { pluginVersion, artifactGraph } = policy;
78
+ const { verifiedVersion, installSpec, githubFallbackSpec } = artifactGraph;
79
+
80
+ // Check installSpec is precise
81
+ const expectedInstallSpec = `artifact-graph@${verifiedVersion}`;
82
+ if (installSpec !== expectedInstallSpec) {
83
+ issues.push(
84
+ `installSpec must be "${expectedInstallSpec}", got "${installSpec}"`,
85
+ );
86
+ }
87
+
88
+ // Check githubFallbackSpec ends with correct tag
89
+ const expectedTag = `artifact-graph-v${verifiedVersion}`;
90
+ if (!githubFallbackSpec.endsWith(`#${expectedTag}`)) {
91
+ issues.push(
92
+ `githubFallbackSpec must end with "#${expectedTag}", got "${githubFallbackSpec}"`,
93
+ );
94
+ }
95
+
96
+ // Check package.json version
97
+ await checkJsonField(pluginRoot, 'package.json', 'version', pluginVersion, issues);
98
+
99
+ // Check Claude marketplace metadata.version (real schema)
100
+ await checkClaudeMarketplaceVersion(pluginRoot, pluginVersion, issues);
101
+
102
+ // Check Codex marketplace plugin source path (real schema has no version field)
103
+ await checkCodexMarketplaceSource(pluginRoot, issues);
104
+
105
+ // Check adapter manifest versions (real paths: .codex-plugin/plugin.json, .claude-plugin/plugin.json)
106
+ for (const [adapter, manifestRel] of [
107
+ ['codex', join('adapters', 'codex', '.codex-plugin', 'plugin.json')],
108
+ ['claude', join('adapters', 'claude', '.claude-plugin', 'plugin.json')],
109
+ ]) {
110
+ await checkAdapterManifest(pluginRoot, adapter, manifestRel, pluginVersion, issues);
111
+ }
112
+
113
+ // Check adapter compatibility.json deep match against root policy
114
+ for (const adapter of ['codex', 'claude']) {
115
+ await checkAdapterCompatibility(pluginRoot, adapter, policy, issues);
116
+ }
117
+
118
+ // Check adapter doctor and lib files exist
119
+ for (const adapter of ['codex', 'claude']) {
120
+ await checkAdapterDoctorFiles(pluginRoot, adapter, issues);
121
+ }
122
+
123
+ // Check docs for forbidden install patterns (real public snapshot at plugin root)
124
+ await checkDocsForForbiddenPatterns(pluginRoot, artifactGraph, issues);
125
+
126
+ return issues;
127
+ }
128
+
129
+ async function checkJsonField(pluginRoot, relativePath, field, expected, issues) {
130
+ const filePath = join(pluginRoot, relativePath);
131
+ try {
132
+ const raw = await readFile(filePath, 'utf8');
133
+ const json = JSON.parse(raw);
134
+ if (json[field] !== expected) {
135
+ issues.push(
136
+ `${relativePath} ${field} must be "${expected}", got "${json[field]}"`,
137
+ );
138
+ }
139
+ } catch (error) {
140
+ if (error.code === 'ENOENT') {
141
+ issues.push(`${relativePath} is missing (required)`);
142
+ } else if (error instanceof SyntaxError) {
143
+ issues.push(`${relativePath} is not valid JSON: ${error.message}`);
144
+ } else {
145
+ issues.push(`${relativePath} error: ${error.message}`);
146
+ }
147
+ }
148
+ }
149
+
150
+ /**
151
+ * Check Claude marketplace metadata.version matches plugin version.
152
+ * Real schema: { metadata: { version: "x.y.z" } }
153
+ */
154
+ async function checkClaudeMarketplaceVersion(pluginRoot, expectedVersion, issues) {
155
+ const relPath = join('.claude-plugin', 'marketplace.json');
156
+ const filePath = join(pluginRoot, relPath);
157
+ try {
158
+ const raw = await readFile(filePath, 'utf8');
159
+ const json = JSON.parse(raw);
160
+ const actual = json.metadata?.version;
161
+ if (actual === undefined) {
162
+ issues.push(`${relPath} metadata.version is missing (required)`);
163
+ } else if (actual !== expectedVersion) {
164
+ issues.push(`${relPath} metadata.version must be "${expectedVersion}", got "${actual}"`);
165
+ }
166
+ } catch (error) {
167
+ if (error.code === 'ENOENT') {
168
+ issues.push(`${relPath} is missing (required)`);
169
+ } else if (error instanceof SyntaxError) {
170
+ issues.push(`${relPath} is not valid JSON: ${error.message}`);
171
+ } else {
172
+ issues.push(`${relPath} error: ${error.message}`);
173
+ }
174
+ }
175
+ }
176
+
177
+ /**
178
+ * Check Codex marketplace plugin source path points to ./adapters/codex.
179
+ * Real schema has NO version field; validate source.path instead.
180
+ */
181
+ async function checkCodexMarketplaceSource(pluginRoot, issues) {
182
+ const relPath = join('.agents', 'plugins', 'marketplace.json');
183
+ const filePath = join(pluginRoot, relPath);
184
+ try {
185
+ const raw = await readFile(filePath, 'utf8');
186
+ const json = JSON.parse(raw);
187
+ const plugin = json.plugins?.[0];
188
+ if (!plugin) {
189
+ issues.push(`${relPath} has no plugins array entries`);
190
+ return;
191
+ }
192
+ const sourcePath = plugin.source?.path;
193
+ if (sourcePath !== './adapters/codex') {
194
+ issues.push(
195
+ `${relPath} plugins[0].source.path must be "./adapters/codex", got "${sourcePath}"`,
196
+ );
197
+ }
198
+ } catch (error) {
199
+ if (error.code === 'ENOENT') {
200
+ issues.push(`${relPath} is missing (required)`);
201
+ } else if (error instanceof SyntaxError) {
202
+ issues.push(`${relPath} is not valid JSON: ${error.message}`);
203
+ } else {
204
+ issues.push(`${relPath} error: ${error.message}`);
205
+ }
206
+ }
207
+ }
208
+
209
+ /**
210
+ * Check adapter plugin manifest version.
211
+ * Fail-closed: missing file or invalid JSON produces an issue, never silently skipped.
212
+ */
213
+ async function checkAdapterManifest(pluginRoot, adapter, manifestRel, expectedVersion, issues) {
214
+ const filePath = join(pluginRoot, manifestRel);
215
+ try {
216
+ const raw = await readFile(filePath, 'utf8');
217
+ const json = JSON.parse(raw);
218
+ if (json.version !== expectedVersion) {
219
+ issues.push(
220
+ `${adapter} adapter manifest version must be "${expectedVersion}", got "${json.version}"`,
221
+ );
222
+ }
223
+ } catch (error) {
224
+ if (error.code === 'ENOENT') {
225
+ issues.push(`${adapter} adapter manifest is missing at ${manifestRel}`);
226
+ } else if (error instanceof SyntaxError) {
227
+ issues.push(`${adapter} adapter manifest is not valid JSON: ${error.message}`);
228
+ } else {
229
+ issues.push(`${adapter} adapter manifest error: ${error.message}`);
230
+ }
231
+ }
232
+ }
233
+
234
+ /**
235
+ * Check adapter compatibility.json matches root policy (deep equality).
236
+ * Fail-closed: missing file produces an issue.
237
+ */
238
+ async function checkAdapterCompatibility(pluginRoot, adapter, rootPolicy, issues) {
239
+ const compatRel = join('adapters', adapter, 'compatibility.json');
240
+ const filePath = join(pluginRoot, compatRel);
241
+ try {
242
+ const raw = await readFile(filePath, 'utf8');
243
+ const json = JSON.parse(raw);
244
+ // Deep compare all fields that matter
245
+ if (json.schemaVersion !== rootPolicy.schemaVersion) {
246
+ issues.push(`${compatRel} schemaVersion must be "${rootPolicy.schemaVersion}", got "${json.schemaVersion}"`);
247
+ }
248
+ if (json.pluginVersion !== rootPolicy.pluginVersion) {
249
+ issues.push(`${compatRel} pluginVersion must be "${rootPolicy.pluginVersion}", got "${json.pluginVersion}"`);
250
+ }
251
+ const ag = json.artifactGraph;
252
+ const rag = rootPolicy.artifactGraph;
253
+ if (!ag) {
254
+ issues.push(`${compatRel} missing artifactGraph object`);
255
+ } else {
256
+ if (ag.verifiedVersion !== rag.verifiedVersion) {
257
+ issues.push(`${compatRel} artifactGraph.verifiedVersion must be "${rag.verifiedVersion}", got "${ag.verifiedVersion}"`);
258
+ }
259
+ if (ag.installSpec !== rag.installSpec) {
260
+ issues.push(`${compatRel} artifactGraph.installSpec must be "${rag.installSpec}", got "${ag.installSpec}"`);
261
+ }
262
+ if (ag.githubFallbackSpec !== rag.githubFallbackSpec) {
263
+ issues.push(`${compatRel} artifactGraph.githubFallbackSpec must be "${rag.githubFallbackSpec}", got "${ag.githubFallbackSpec}"`);
264
+ }
265
+ }
266
+ } catch (error) {
267
+ if (error.code === 'ENOENT') {
268
+ issues.push(`${compatRel} is missing (required for adapter ${adapter})`);
269
+ } else if (error instanceof SyntaxError) {
270
+ issues.push(`${compatRel} is not valid JSON: ${error.message}`);
271
+ } else {
272
+ issues.push(`${compatRel} error: ${error.message}`);
273
+ }
274
+ }
275
+ }
276
+
277
+ // ── Install spec classification (argument-order agnostic) ─────────────
278
+
279
+ // Recognized package-manager install command prefixes.
280
+ const INSTALL_CMD_PREFIXES = [
281
+ ['npm', 'install'],
282
+ ['npm', 'i'],
283
+ ['pnpm', 'add'],
284
+ ];
285
+
286
+ /**
287
+ * Classify a single code-block line for forbidden install specs.
288
+ * Returns a description string if the spec is forbidden, null otherwise.
289
+ *
290
+ * Strategy: split the line into tokens, match a known install command prefix,
291
+ * then scan ALL remaining tokens for an artifact-graph package spec — no
292
+ * enumeration of flag orderings.
293
+ *
294
+ * Only exact matches against expectedInstallSpec and expectedGithubSpec are allowed.
295
+ *
296
+ * @param {string} line
297
+ * @param {string} expectedInstallSpec - e.g. "artifact-graph@0.3.1"
298
+ * @param {string} expectedGithubSpec - e.g. "github:ifoohoo/artifact-graph#artifact-graph-v0.3.1"
299
+ */
300
+ function classifyInstallSpecViolation(line, expectedInstallSpec, expectedGithubSpec) {
301
+ const tokens = line.split(/\s+/);
302
+
303
+ // Standalone GitHub repo (no install command prefix needed)
304
+ // Match both the current ifoohoo slug and the pre-migration mzdbxqh slug so
305
+ // stale references are still flagged as mismatches.
306
+ if (tokens.length === 1 && /^github:(?:mzdbxqh|ifoohoo)\/artifact-graph/.test(tokens[0])) {
307
+ if (tokens[0] === expectedGithubSpec) return null;
308
+ return `GitHub spec mismatch: got "${tokens[0]}", expected "${expectedGithubSpec}"`;
309
+ }
310
+
311
+ if (tokens.length < 3) return null;
312
+
313
+ // Match command prefix (e.g. "npm install", "pnpm add")
314
+ let cmdLen = 0;
315
+ for (const [bin, sub] of INSTALL_CMD_PREFIXES) {
316
+ if (tokens[0] === bin && tokens[1] === sub) {
317
+ cmdLen = 2;
318
+ break;
319
+ }
320
+ }
321
+ if (cmdLen === 0) return null;
322
+
323
+ // Scan remaining tokens for a package spec containing artifact-graph
324
+ for (const tok of tokens.slice(cmdLen)) {
325
+ // Skip flags
326
+ if (tok.startsWith('-')) continue;
327
+
328
+ // GitHub spec: github:ifoohoo/artifact-graph or github:ifoohoo/artifact-graph#tag
329
+ if (/^github:(?:mzdbxqh|ifoohoo)\/artifact-graph/.test(tok)) {
330
+ if (tok === expectedGithubSpec) continue;
331
+ return `GitHub spec mismatch: got "${tok}", expected "${expectedGithubSpec}"`;
332
+ }
333
+
334
+ // npm/pnpm package spec
335
+ if (/^artifact-graph(@|$)/.test(tok)) {
336
+ if (tok === expectedInstallSpec) continue;
337
+ return `install spec mismatch: got "${tok}", expected "${expectedInstallSpec}"`;
338
+ }
339
+ }
340
+
341
+ return null;
342
+ }
343
+
344
+ /**
345
+ * Check public docs for forbidden install patterns.
346
+ * Scans real public snapshot files at plugin root:
347
+ * INSTALL.md, README.md, README.zh-CN.md, adapters/codex/INSTALL.md, adapters/claude/INSTALL.md
348
+ *
349
+ * For each fenced code block line, extracts the artifact-graph package spec
350
+ * from any argument position and classifies it — no enumeration of flag orderings.
351
+ *
352
+ * @param {string} pluginRoot
353
+ * @param {{installSpec: string, githubFallbackSpec: string}} artifactGraphPolicy
354
+ * @param {string[]} issues
355
+ */
356
+ async function checkDocsForForbiddenPatterns(pluginRoot, artifactGraphPolicy, issues) {
357
+ const { installSpec: expectedInstallSpec, githubFallbackSpec: expectedGithubSpec } = artifactGraphPolicy;
358
+ const docPaths = [
359
+ 'INSTALL.md',
360
+ 'README.md',
361
+ 'README.zh-CN.md',
362
+ join('adapters', 'codex', 'INSTALL.md'),
363
+ join('adapters', 'claude', 'INSTALL.md'),
364
+ ];
365
+
366
+ for (const relPath of docPaths) {
367
+ const filePath = join(pluginRoot, relPath);
368
+ let content;
369
+ try {
370
+ content = await readFile(filePath, 'utf8');
371
+ } catch (error) {
372
+ if (error.code === 'ENOENT') {
373
+ issues.push(`${relPath} is missing (required public doc)`);
374
+ }
375
+ continue;
376
+ }
377
+
378
+ const lines = extractCodeBlocks(content)
379
+ .split('\n')
380
+ .map((l) => l.trim())
381
+ .filter(Boolean);
382
+
383
+ for (const line of lines) {
384
+ const violation = classifyInstallSpecViolation(line, expectedInstallSpec, expectedGithubSpec);
385
+ if (violation) {
386
+ issues.push(`${relPath} code blocks contain forbidden install pattern: ${violation}`);
387
+ }
388
+ }
389
+ }
390
+ }
391
+
392
+ function extractCodeBlocks(markdown) {
393
+ const blocks = [];
394
+ const re = /```[\w-]*\n([\s\S]*?)```/g;
395
+ let m;
396
+ while ((m = re.exec(markdown)) !== null) {
397
+ blocks.push(m[1]);
398
+ }
399
+ return blocks.join('\n');
400
+ }
401
+
402
+ /**
403
+ * Check adapter doctor and lib files exist.
404
+ * Fail-closed: missing file produces an issue.
405
+ */
406
+ async function checkAdapterDoctorFiles(pluginRoot, adapter, issues) {
407
+ const requiredFiles = [
408
+ join('adapters', adapter, 'scripts', 'doctor.mjs'),
409
+ join('adapters', adapter, 'scripts', 'lib', 'compatibility-policy.mjs'),
410
+ join('adapters', adapter, 'scripts', 'lib', 'artifact-graph-runtime.mjs'),
411
+ ];
412
+
413
+ for (const relPath of requiredFiles) {
414
+ const filePath = join(pluginRoot, relPath);
415
+ try {
416
+ await readFile(filePath, 'utf8');
417
+ } catch (error) {
418
+ if (error.code === 'ENOENT') {
419
+ issues.push(`${relPath} is missing (required for adapter ${adapter})`);
420
+ } else {
421
+ issues.push(`${relPath} error: ${error.message}`);
422
+ }
423
+ }
424
+ }
425
+ }
426
+
427
+ function deepFreeze(obj) {
428
+ Object.freeze(obj);
429
+ for (const value of Object.values(obj)) {
430
+ if (value && typeof value === 'object' && !Object.isFrozen(value)) {
431
+ deepFreeze(value);
432
+ }
433
+ }
434
+ return obj;
435
+ }