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,348 @@
1
+ #!/usr/bin/env node
2
+ // @scenario S-01 @feature ACA1
3
+ // 模板目录完整性检查:校验 core 和 extended 下每个类型目录至少包含 starter.md 和 review-checklist.md
4
+ import { readFile, readdir, stat } from 'node:fs/promises';
5
+ import { dirname, join, relative } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+
8
+ const root = dirname(dirname(fileURLToPath(import.meta.url)));
9
+ const templatesDir = join(root, 'templates');
10
+ const REQUIRED_FILES = ['starter.md', 'review-checklist.md'];
11
+ const CATALOG_FILES = [
12
+ join(root, 'templates/extended/README.md'),
13
+ join(root, 'EXTENDED-ARTIFACT-CATALOG.md'),
14
+ join(root, 'EXTENDED-ARTIFACT-CATALOG.zh-CN.md'),
15
+ ];
16
+
17
+ /** 判断路径是否为目录 */
18
+ async function isDir(path) {
19
+ try {
20
+ return (await stat(path)).isDirectory();
21
+ } catch {
22
+ return false;
23
+ }
24
+ }
25
+
26
+ /** 获取目录下的子目录名列表 */
27
+ async function subdirs(path) {
28
+ if (!(await isDir(path))) return [];
29
+ const entries = await readdir(path, { withFileTypes: true });
30
+ return entries.filter((e) => e.isDirectory()).map((e) => e.name);
31
+ }
32
+
33
+ /** 检查单个类型目录,返回缺失文件列表 */
34
+ async function checkTypeDir(dirPath) {
35
+ const missing = [];
36
+ for (const file of REQUIRED_FILES) {
37
+ try {
38
+ await stat(join(dirPath, file));
39
+ } catch {
40
+ missing.push(file);
41
+ }
42
+ }
43
+ return missing;
44
+ }
45
+
46
+ // ── Professional skill family contract checks ──────────────────────────────
47
+
48
+ const PROFESSIONAL_ENTRY_FILES = ['SKILL.md', 'author/SKILL.md', 'review/SKILL.md', 'repair/SKILL.md'];
49
+ const PROFESSIONAL_REFERENCE_FILES = ['references/inspect.md', 'references/compose.md', 'references/validate.md'];
50
+
51
+ /**
52
+ * Prohibited literal patterns (case-insensitive for first group).
53
+ * Absolute path patterns are checked separately.
54
+ */
55
+ const PROHIBITED_LITERALS = [
56
+ /\bheimdall\b/i,
57
+ /\btauri\b/i,
58
+ /\bquick\s+check\b/i,
59
+ /\bopen\s+core\b/i,
60
+ /\bsqlite\b/i,
61
+ ];
62
+ const ABSOLUTE_PATH_RE = /(?:^|\s)\/(?:Users|home|opt|var|tmp|etc)\b/;
63
+
64
+ /**
65
+ * Detect professional families under skills-src: a directory is a professional
66
+ * family if it contains an `author/` subdirectory.
67
+ */
68
+ async function discoverProfessionalFamilies(skillsSrcDir) {
69
+ const families = [];
70
+ const entries = await readdir(skillsSrcDir, { withFileTypes: true });
71
+ for (const entry of entries) {
72
+ if (!entry.isDirectory()) continue;
73
+ const familyDir = join(skillsSrcDir, entry.name);
74
+ try {
75
+ await stat(join(familyDir, 'author'));
76
+ families.push({ name: entry.name, dir: familyDir });
77
+ } catch {
78
+ // not a professional family
79
+ }
80
+ }
81
+ return families;
82
+ }
83
+
84
+ /**
85
+ * Recursively collect all .md files under a directory.
86
+ */
87
+ async function collectMarkdownFiles(dir) {
88
+ const files = [];
89
+ const entries = await readdir(dir, { withFileTypes: true });
90
+ for (const entry of entries) {
91
+ const full = join(dir, entry.name);
92
+ if (entry.isDirectory()) {
93
+ files.push(...await collectMarkdownFiles(full));
94
+ } else if (entry.name.endsWith('.md')) {
95
+ files.push(full);
96
+ }
97
+ }
98
+ return files;
99
+ }
100
+
101
+ /**
102
+ * Parse YAML frontmatter fields from a markdown file.
103
+ * Returns the raw frontmatter block and parsed { name, description, extra }.
104
+ */
105
+ function parseFrontmatter(content) {
106
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
107
+ if (!match) return { raw: null, fields: {} };
108
+ const raw = match[1];
109
+ const fields = {};
110
+ for (const line of raw.split('\n')) {
111
+ const m = line.match(/^(\w[\w-]*):\s*(.*)$/);
112
+ if (m) fields[m[1]] = m[2].trim();
113
+ }
114
+ return { raw, fields };
115
+ }
116
+
117
+ /**
118
+ * Check professional family contract compliance.
119
+ * Returns array of error strings.
120
+ */
121
+ async function checkProfessionalFamilies(skillsSrcDir) {
122
+ const errors = [];
123
+ const families = await discoverProfessionalFamilies(skillsSrcDir);
124
+
125
+ for (const family of families) {
126
+ // 1. Entry completeness
127
+ for (const entry of PROFESSIONAL_ENTRY_FILES) {
128
+ const entryPath = join(family.dir, entry);
129
+ try {
130
+ await stat(entryPath);
131
+ } catch {
132
+ errors.push(`family ${family.name}: missing required entry ${entry}`);
133
+ }
134
+ }
135
+
136
+ // 1b. Internal reference completeness
137
+ for (const ref of PROFESSIONAL_REFERENCE_FILES) {
138
+ const refPath = join(family.dir, ref);
139
+ try {
140
+ await stat(refPath);
141
+ } catch {
142
+ errors.push(`family ${family.name}: missing required internal reference ${ref}`);
143
+ }
144
+ }
145
+
146
+ // 2. Closed-loop keywords
147
+ const readSafe = async (rel) => {
148
+ try { return await readFile(join(family.dir, rel), 'utf8'); } catch { return ''; }
149
+ };
150
+
151
+ const authorContent = await readSafe('author/SKILL.md');
152
+ const reviewContent = await readSafe('review/SKILL.md');
153
+ const repairContent = await readSafe('repair/SKILL.md');
154
+
155
+ // Default SKILL.md must contain routing keywords: author, review, repair
156
+ const defaultContent = await readSafe('SKILL.md');
157
+ if (defaultContent) {
158
+ for (const kw of ['author', 'review', 'repair']) {
159
+ if (!defaultContent.includes(kw)) {
160
+ errors.push(`family ${family.name}/SKILL.md: missing routing keyword "${kw}"`);
161
+ }
162
+ }
163
+ }
164
+
165
+ // Author must contain: inspect, compose, validate, review (as steps)
166
+ if (authorContent) {
167
+ for (const kw of ['inspect', 'compose', 'validate', 'review']) {
168
+ if (!authorContent.includes(kw)) {
169
+ errors.push(`family ${family.name}/author: missing closed-loop keyword "${kw}"`);
170
+ }
171
+ }
172
+ }
173
+
174
+ // Review must contain: inspect, review, findings
175
+ if (reviewContent) {
176
+ for (const kw of ['inspect', 'review', 'findings']) {
177
+ if (!reviewContent.includes(kw)) {
178
+ errors.push(`family ${family.name}/review: missing closed-loop keyword "${kw}"`);
179
+ }
180
+ }
181
+ }
182
+
183
+ // Repair must contain: findings, repair, re-review
184
+ if (repairContent) {
185
+ for (const kw of ['findings', 'repair', 're-review']) {
186
+ if (!repairContent.includes(kw)) {
187
+ errors.push(`family ${family.name}/repair: missing closed-loop keyword "${kw}"`);
188
+ }
189
+ }
190
+ }
191
+
192
+ // Internal references: inspect.md must contain "inspect" and "config"
193
+ // compose.md must contain "compose" and "frontmatter"
194
+ // validate.md must contain "validate"
195
+ const inspectRef = await readSafe('references/inspect.md');
196
+ if (inspectRef) {
197
+ for (const kw of ['inspect', 'config']) {
198
+ if (!inspectRef.includes(kw)) {
199
+ errors.push(`family ${family.name}/references/inspect.md: missing keyword "${kw}"`);
200
+ }
201
+ }
202
+ }
203
+ const composeRef = await readSafe('references/compose.md');
204
+ if (composeRef) {
205
+ for (const kw of ['compose', 'frontmatter']) {
206
+ if (!composeRef.includes(kw)) {
207
+ errors.push(`family ${family.name}/references/compose.md: missing keyword "${kw}"`);
208
+ }
209
+ }
210
+ }
211
+ const validateRef = await readSafe('references/validate.md');
212
+ if (validateRef) {
213
+ for (const kw of ['validate']) {
214
+ if (!validateRef.includes(kw)) {
215
+ errors.push(`family ${family.name}/references/validate.md: missing keyword "${kw}"`);
216
+ }
217
+ }
218
+ }
219
+
220
+ // 3. Prohibited literals in all family .md files
221
+ const allFiles = await collectMarkdownFiles(family.dir);
222
+ for (const filePath of allFiles) {
223
+ const relPath = relative(root, filePath);
224
+ const content = await readFile(filePath, 'utf8');
225
+ for (const pattern of PROHIBITED_LITERALS) {
226
+ if (pattern.test(content)) {
227
+ errors.push(`${relPath}: contains prohibited literal matching ${pattern}`);
228
+ }
229
+ }
230
+ if (ABSOLUTE_PATH_RE.test(content)) {
231
+ errors.push(`${relPath}: contains absolute path`);
232
+ }
233
+ }
234
+
235
+ // 4. References as non-entry: reference .md files must not have frontmatter
236
+ const refsDir = join(family.dir, 'references');
237
+ try {
238
+ const refEntries = await readdir(refsDir, { withFileTypes: true });
239
+ for (const ref of refEntries) {
240
+ if (!ref.isFile() || !ref.name.endsWith('.md')) continue;
241
+ const refContent = await readFile(join(refsDir, ref.name), 'utf8');
242
+ if (refContent.startsWith('---')) {
243
+ errors.push(
244
+ `family ${family.name}/references/${ref.name}: reference file must not have frontmatter`
245
+ );
246
+ }
247
+ }
248
+ } catch {
249
+ // no references dir — that's OK
250
+ }
251
+
252
+ // 5. Frontmatter shape: SKILL.md files must only have name + description
253
+ for (const entry of PROFESSIONAL_ENTRY_FILES) {
254
+ const entryPath = join(family.dir, entry);
255
+ let content;
256
+ try {
257
+ content = await readFile(entryPath, 'utf8');
258
+ } catch {
259
+ continue; // already reported as missing
260
+ }
261
+ const { fields } = parseFrontmatter(content);
262
+ const allowed = new Set(['name', 'description']);
263
+ for (const key of Object.keys(fields)) {
264
+ if (!allowed.has(key)) {
265
+ errors.push(
266
+ `family ${family.name}/${entry}: unexpected frontmatter field "${key}"`
267
+ );
268
+ }
269
+ }
270
+ // description must be third-person (should not start with first-person)
271
+ if (fields.description && /^(I|We)\s/i.test(fields.description)) {
272
+ errors.push(
273
+ `family ${family.name}/${entry}: description must be third-person`
274
+ );
275
+ }
276
+ }
277
+ }
278
+
279
+ return errors;
280
+ }
281
+
282
+ async function main() {
283
+ const errors = [];
284
+ const extendedTypes = [];
285
+
286
+ for (const requiredRoot of ['core', 'extended']) {
287
+ const path = join(templatesDir, requiredRoot);
288
+ if (!(await isDir(path)) || (await subdirs(path)).length === 0) {
289
+ errors.push({ type: `templates/${requiredRoot}`, missing: ['non-empty directory'] });
290
+ }
291
+ }
292
+
293
+ // 1. core 目录:每个子目录即一个类型
294
+ const coreDir = join(templatesDir, 'core');
295
+ for (const typeName of await subdirs(coreDir)) {
296
+ const missing = await checkTypeDir(join(coreDir, typeName));
297
+ if (missing.length > 0) {
298
+ errors.push({ type: `core/${typeName}`, missing });
299
+ }
300
+ }
301
+
302
+ // 2. extended 目录:每类(contracts, domain, ops, governance, agent)下各有类型子目录
303
+ const extendedDir = join(templatesDir, 'extended');
304
+ for (const category of await subdirs(extendedDir)) {
305
+ for (const typeName of await subdirs(join(extendedDir, category))) {
306
+ extendedTypes.push(typeName);
307
+ const missing = await checkTypeDir(join(extendedDir, category, typeName));
308
+ if (missing.length > 0) {
309
+ errors.push({ type: `extended/${category}/${typeName}`, missing });
310
+ }
311
+ }
312
+ }
313
+
314
+ for (const catalogFile of CATALOG_FILES) {
315
+ let text = '';
316
+ try {
317
+ text = await readFile(catalogFile, 'utf8');
318
+ } catch {
319
+ errors.push({ type: catalogFile, missing: ['catalog file'] });
320
+ continue;
321
+ }
322
+ for (const typeName of extendedTypes) {
323
+ if (!text.includes(typeName)) {
324
+ errors.push({ type: catalogFile, missing: [`catalog entry for ${typeName}`] });
325
+ }
326
+ }
327
+ }
328
+
329
+ if (errors.length > 0) {
330
+ for (const err of errors) {
331
+ console.error(
332
+ `Template integrity violation: ${err.type} is missing ${err.missing.join(', ')}`
333
+ );
334
+ }
335
+ console.error(
336
+ `\n${errors.length} type(s) have incomplete templates. ` +
337
+ `Each type directory must contain: ${REQUIRED_FILES.join(', ')}`
338
+ );
339
+ process.exitCode = 1;
340
+ } else {
341
+ console.log(
342
+ `Template integrity check passed: ${extendedTypes.length} extended type(s) have ` +
343
+ 'required files and catalog coverage.'
344
+ );
345
+ }
346
+ }
347
+
348
+ main();
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ // @feature ACA17
3
+ // @scenario S-51
4
+ // @scenario S-53
5
+ // @scenario S-54
6
+ // @decision D-ACA-17
7
+ // Thin CLI wrapper. scripts/lib/workflow-profile.mjs is the single resolver.
8
+ import { resolve } from 'node:path';
9
+ import { buildCheckerOutput } from './lib/workflow-profile.mjs';
10
+
11
+ export async function checkWorkflowProfile({ root = process.cwd(), action = 'review', domain, profilePath, target } = {}) {
12
+ const projectRoot = resolve(root);
13
+ const checker = await buildCheckerOutput({ root: projectRoot, profilePath, intent: action, domain, target });
14
+ return {
15
+ ...checker,
16
+ root: projectRoot,
17
+ action,
18
+ domain,
19
+ profile: checker.profile_path,
20
+ worker: checker.worker_path ? checker.worker_path.split('/').slice(-2, -1)[0] : null,
21
+ dry_run: true,
22
+ };
23
+ }
24
+
25
+ const isMain = import.meta.url === `file://${process.argv[1]}`;
26
+ if (isMain) {
27
+ const args = process.argv.slice(2);
28
+ const value = flag => {
29
+ const index = args.indexOf(flag);
30
+ return index >= 0 ? args[index + 1] : undefined;
31
+ };
32
+ if (args.includes('--help')) {
33
+ console.log('Usage: node check-workflow-profile.mjs --root <path> --action <generate|review|repair|audit|batch> --domain <type> [--profile <json|yaml>] [--target <path>] [--format json|text]');
34
+ process.exit(0);
35
+ }
36
+ let result;
37
+ try {
38
+ result = await checkWorkflowProfile({
39
+ root: value('--root') ?? process.cwd(),
40
+ action: value('--action') ?? 'review',
41
+ domain: value('--domain'),
42
+ profilePath: value('--profile'),
43
+ target: value('--target'),
44
+ });
45
+ } catch (error) {
46
+ result = {
47
+ status: 'BLOCKED', schema: null, profile_path: null, execution_mode: null,
48
+ worker_path: null, checklist_paths: [], validators: [], template_paths: [],
49
+ diagnostics: [`Checker failed closed: ${error.message}`],
50
+ next: 'Fix the malformed or unsafe profile and run this check again.',
51
+ root: resolve(value('--root') ?? process.cwd()),
52
+ action: value('--action') ?? 'review', domain: value('--domain'), profile: null,
53
+ worker: null, dry_run: true,
54
+ };
55
+ }
56
+ if ((value('--format') ?? 'json') === 'text') {
57
+ console.log(`${result.status}: ${result.action}/${result.domain ?? '(missing)'}`);
58
+ for (const item of result.diagnostics) console.log(`- ${item}`);
59
+ console.log(`Next: ${result.next}`);
60
+ } else {
61
+ console.log(JSON.stringify(result, null, 2));
62
+ }
63
+ process.exit(result.status === 'OK' ? 0 : 2);
64
+ }
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ // @scenario S-06 @feature ACA3
3
+ // @scenario S-44 @feature ACA13
4
+ // @decision D-ACA-15
5
+ import { spawnSync } from 'node:child_process';
6
+ import { resolve } from 'node:path';
7
+ import { inspectArtifactGraphRuntime } from './lib/artifact-graph-runtime.mjs';
8
+
9
+ // Parse --root from args (same as artifact-graph CLI convention)
10
+ const args = process.argv.slice(2);
11
+ let projectRoot = process.cwd();
12
+ const rootIdx = args.indexOf('--root');
13
+ if (rootIdx !== -1 && args[rootIdx + 1]) {
14
+ projectRoot = resolve(args[rootIdx + 1]);
15
+ }
16
+
17
+ const runtime = await inspectArtifactGraphRuntime({ projectRoot });
18
+
19
+ if (!runtime.ok) {
20
+ const lines = [
21
+ `artifact-chain-assistant: doctor pre-check failed`,
22
+ ` reason: ${runtime.reason}`,
23
+ ];
24
+ if (runtime.cliPath) lines.push(` cli: ${runtime.cliPath}`);
25
+ if (runtime.packagePath) lines.push(` package: ${runtime.packagePath}`);
26
+ if (runtime.actualVersion != null) lines.push(` actual version: ${runtime.actualVersion}`);
27
+ if (runtime.expectedVersion != null) lines.push(` expected version: ${runtime.expectedVersion}`);
28
+ if (runtime.remediation) lines.push(` fix: ${runtime.remediation}`);
29
+ process.stderr.write(lines.join('\n') + '\n');
30
+ process.exitCode = 1;
31
+ } else {
32
+ // Forward all args to the real artifact-graph doctor
33
+ const result = spawnSync(runtime.cliPath, ['doctor', ...args], {
34
+ cwd: process.cwd(),
35
+ stdio: 'inherit',
36
+ });
37
+
38
+ if (result.error) {
39
+ process.stderr.write(`artifact-chain-assistant: failed to run artifact-graph doctor: ${result.error.message}\n`);
40
+ process.exitCode = 127;
41
+ } else {
42
+ process.exitCode = result.status ?? 1;
43
+ }
44
+ }
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env node
2
+ // @scenario S-04 @feature ACA4
3
+ import { spawnSync } from 'node:child_process';
4
+ import { existsSync } from 'node:fs';
5
+ import { join } from 'node:path';
6
+
7
+ const args = process.argv.slice(2);
8
+ const cli = existsSync(join(process.cwd(), 'node_modules/.bin/artifact-graph'))
9
+ ? join(process.cwd(), 'node_modules/.bin/artifact-graph')
10
+ : 'artifact-graph';
11
+ const result = spawnSync(cli, ['hooks', 'install-git', ...args], {
12
+ cwd: process.cwd(),
13
+ stdio: 'inherit',
14
+ });
15
+
16
+ if (result.error) {
17
+ process.stderr.write(`artifact-chain-assistant: failed to run artifact-graph hooks install-git: ${result.error.message}\n`);
18
+ process.exitCode = 127;
19
+ } else {
20
+ process.exitCode = result.status ?? 1;
21
+ }
@@ -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
+ }