coding-agent-skills 0.2.8

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 (357) hide show
  1. package/AGENTS.md +44 -0
  2. package/CHANGELOG.md +205 -0
  3. package/CONTRIBUTING.md +54 -0
  4. package/LICENSE +21 -0
  5. package/README.md +85 -0
  6. package/ROADMAP.md +87 -0
  7. package/RUNBOOK.md +47 -0
  8. package/bin/coding-agent-skills +75 -0
  9. package/contracts/evidence-pack/README.md +22 -0
  10. package/contracts/evidence-pack/evidence-pack.example.json +60 -0
  11. package/contracts/evidence-pack/evidence-pack.example.md +49 -0
  12. package/contracts/evidence-pack/evidence-pack.schema.json +156 -0
  13. package/docs/adapters/README.md +82 -0
  14. package/docs/adapters/discovery.md +50 -0
  15. package/docs/adapters/external-adapters.md +42 -0
  16. package/docs/adapters/project-installation.md +135 -0
  17. package/docs/adapters/real-project-adoption.md +193 -0
  18. package/docs/adapters/upgrade-evidence.md +67 -0
  19. package/docs/adapters/upgrades.md +83 -0
  20. package/docs/architecture/README.md +23 -0
  21. package/docs/authoring/README.md +54 -0
  22. package/docs/evidence-bundles/README.md +94 -0
  23. package/docs/privacy/README.md +26 -0
  24. package/docs/release/README.md +42 -0
  25. package/docs/release/npm-package.md +85 -0
  26. package/docs/safety/README.md +94 -0
  27. package/docs/testing/README.md +100 -0
  28. package/docs/usage/README.md +89 -0
  29. package/docs/versioning/README.md +30 -0
  30. package/docs/versioning/adapter-compatibility.md +54 -0
  31. package/examples/README.md +12 -0
  32. package/examples/adapters/README.md +9 -0
  33. package/examples/adapters/documentation-precedence.json +62 -0
  34. package/examples/adapters/narrow-repo-map.json +64 -0
  35. package/examples/adapters/runtime-status-hints.json +76 -0
  36. package/examples/command-policies/README.md +3 -0
  37. package/examples/command-policies/build-verify.json +57 -0
  38. package/examples/command-policies/git-preflight.json +44 -0
  39. package/examples/command-policies/llm-drift-control.json +45 -0
  40. package/examples/command-policies/repo-map.json +59 -0
  41. package/examples/command-policies/runtime-truth.json +59 -0
  42. package/examples/evidence-packs/README.md +3 -0
  43. package/examples/evidence-packs/build-verify.json +68 -0
  44. package/examples/evidence-packs/git-preflight.json +55 -0
  45. package/examples/evidence-packs/llm-drift-control.json +55 -0
  46. package/examples/evidence-packs/repo-map.json +55 -0
  47. package/examples/evidence-packs/runtime-truth.json +55 -0
  48. package/examples/manifests/README.md +3 -0
  49. package/examples/manifests/build-verify.json +14 -0
  50. package/examples/manifests/git-preflight.json +14 -0
  51. package/examples/manifests/llm-drift-control.json +14 -0
  52. package/examples/manifests/repo-map.json +14 -0
  53. package/examples/manifests/runtime-truth.json +14 -0
  54. package/examples/upgrade-evidence/README.md +14 -0
  55. package/examples/upgrade-evidence/chain-fail.evidence.json +155 -0
  56. package/examples/upgrade-evidence/chain-fail.evidence.md +14 -0
  57. package/examples/upgrade-evidence/chain-pass.evidence.json +156 -0
  58. package/examples/upgrade-evidence/stale-pin.evidence.json +117 -0
  59. package/examples/upgrade-evidence/unsafe-upgrade.evidence.json +128 -0
  60. package/examples/upgrade-evidence/valid-upgrade.evidence.json +105 -0
  61. package/examples/upgrade-evidence/valid-upgrade.evidence.md +13 -0
  62. package/examples/workflows/README.md +3 -0
  63. package/examples/workflows/build-verify.md +20 -0
  64. package/examples/workflows/git-preflight.md +18 -0
  65. package/examples/workflows/llm-drift-control.md +16 -0
  66. package/examples/workflows/repo-map.md +20 -0
  67. package/examples/workflows/runtime-truth.md +17 -0
  68. package/package.json +58 -0
  69. package/runs/skill-runs.md +162 -0
  70. package/schemas/adapter-upgrade-evidence.schema.json +443 -0
  71. package/schemas/archive-index.schema.json +174 -0
  72. package/schemas/archive-report.schema.json +322 -0
  73. package/schemas/command-policy.schema.json +125 -0
  74. package/schemas/evidence-bundle.schema.json +394 -0
  75. package/schemas/project-adapter-installation.schema.json +127 -0
  76. package/schemas/project-adapter.schema.json +328 -0
  77. package/schemas/skill-manifest.schema.json +40 -0
  78. package/scripts/check-adapter-upgrade-chain.mjs +32 -0
  79. package/scripts/check-adapter-upgrade.mjs +31 -0
  80. package/scripts/lib/adapter-discovery.mjs +441 -0
  81. package/scripts/lib/adapter-repo-map.mjs +358 -0
  82. package/scripts/lib/adapter-upgrade-chain.mjs +261 -0
  83. package/scripts/lib/adapter-upgrade.mjs +434 -0
  84. package/scripts/lib/evidence-bundle.mjs +831 -0
  85. package/scripts/lib/pack-rules.mjs +704 -0
  86. package/scripts/lib/project-adapter-installation.mjs +327 -0
  87. package/scripts/lib/safe-evidence-output.mjs +92 -0
  88. package/scripts/lib/schema-validator.mjs +146 -0
  89. package/scripts/lib/semver.mjs +54 -0
  90. package/scripts/lib/upgrade-evidence.mjs +276 -0
  91. package/scripts/render-adapter-repo-map.mjs +8 -0
  92. package/scripts/render-evidence-archive-report.mjs +18 -0
  93. package/scripts/run-next +220 -0
  94. package/scripts/test-pack.mjs +2232 -0
  95. package/scripts/validate-adapters.mjs +10 -0
  96. package/scripts/validate-maintainer-loop.mjs +146 -0
  97. package/scripts/validate-pack.mjs +950 -0
  98. package/scripts/validate-project-adapters.mjs +8 -0
  99. package/scripts/verify-evidence-bundle.mjs +18 -0
  100. package/skills/build-verify/SKILL.md +62 -0
  101. package/skills/build-verify/adapter-interface.md +7 -0
  102. package/skills/build-verify/agents/openai.yaml +4 -0
  103. package/skills/build-verify/checklist.md +12 -0
  104. package/skills/build-verify/evidence-template.md +11 -0
  105. package/skills/build-verify/examples.md +16 -0
  106. package/skills/build-verify/failure-modes.md +14 -0
  107. package/skills/git-preflight/SKILL.md +65 -0
  108. package/skills/git-preflight/adapter-interface.md +7 -0
  109. package/skills/git-preflight/agents/openai.yaml +4 -0
  110. package/skills/git-preflight/checklist.md +11 -0
  111. package/skills/git-preflight/evidence-template.md +10 -0
  112. package/skills/git-preflight/examples.md +18 -0
  113. package/skills/git-preflight/failure-modes.md +13 -0
  114. package/skills/llm-drift-control/SKILL.md +67 -0
  115. package/skills/llm-drift-control/adapter-interface.md +7 -0
  116. package/skills/llm-drift-control/agents/openai.yaml +4 -0
  117. package/skills/llm-drift-control/checklist.md +11 -0
  118. package/skills/llm-drift-control/evidence-template.md +13 -0
  119. package/skills/llm-drift-control/examples.md +15 -0
  120. package/skills/llm-drift-control/failure-modes.md +13 -0
  121. package/skills/repo-map/SKILL.md +71 -0
  122. package/skills/repo-map/adapter-interface.md +18 -0
  123. package/skills/repo-map/agents/openai.yaml +4 -0
  124. package/skills/repo-map/checklist.md +15 -0
  125. package/skills/repo-map/evidence-template.md +29 -0
  126. package/skills/repo-map/examples.md +19 -0
  127. package/skills/repo-map/failure-modes.md +16 -0
  128. package/skills/runtime-truth/SKILL.md +62 -0
  129. package/skills/runtime-truth/adapter-interface.md +7 -0
  130. package/skills/runtime-truth/agents/openai.yaml +4 -0
  131. package/skills/runtime-truth/checklist.md +11 -0
  132. package/skills/runtime-truth/evidence-template.md +12 -0
  133. package/skills/runtime-truth/examples.md +20 -0
  134. package/skills/runtime-truth/failure-modes.md +13 -0
  135. package/tests/README.md +44 -0
  136. package/tests/adapters/README.md +15 -0
  137. package/tests/completion/README.md +15 -0
  138. package/tests/evidence/README.md +15 -0
  139. package/tests/fixtures/README.md +23 -0
  140. package/tests/fixtures/adapters/allow-deploy.json +60 -0
  141. package/tests/fixtures/adapters/allow-git-push.json +60 -0
  142. package/tests/fixtures/adapters/expand-scope.json +53 -0
  143. package/tests/fixtures/adapters/expose-secrets.json +53 -0
  144. package/tests/fixtures/adapters/incompatible-version.json +53 -0
  145. package/tests/fixtures/adapters/override-audit-only.json +53 -0
  146. package/tests/fixtures/adapters/redefine-completion.json +53 -0
  147. package/tests/fixtures/adapters/remove-required-evidence.json +53 -0
  148. package/tests/fixtures/adapters/suppress-failures.json +53 -0
  149. package/tests/fixtures/adapters/valid-narrowing.json +53 -0
  150. package/tests/fixtures/adapters/valid-repo-map.json +53 -0
  151. package/tests/fixtures/adapters/weakening-repo-map.json +42 -0
  152. package/tests/fixtures/completion/cases.json +143 -0
  153. package/tests/fixtures/completion/false-complete.json +51 -0
  154. package/tests/fixtures/evidence-bundles/advisory-review-soon/archive/evidence-archive-index.json +52 -0
  155. package/tests/fixtures/evidence-bundles/advisory-review-soon/evidence/repo-map.evidence.json +68 -0
  156. package/tests/fixtures/evidence-bundles/advisory-review-soon/evidence/valid-upgrade.evidence.json +105 -0
  157. package/tests/fixtures/evidence-bundles/advisory-review-soon/evidence-bundle.json +109 -0
  158. package/tests/fixtures/evidence-bundles/invalid-archive/archive/evidence-archive-index.json +52 -0
  159. package/tests/fixtures/evidence-bundles/invalid-archive/evidence/repo-map.evidence.json +68 -0
  160. package/tests/fixtures/evidence-bundles/invalid-archive/evidence/valid-upgrade.evidence.json +105 -0
  161. package/tests/fixtures/evidence-bundles/invalid-archive/evidence-bundle.json +109 -0
  162. package/tests/fixtures/evidence-bundles/invalid-archive-index/archive/evidence-archive-index.json +52 -0
  163. package/tests/fixtures/evidence-bundles/invalid-archive-index/evidence/repo-map.evidence.json +68 -0
  164. package/tests/fixtures/evidence-bundles/invalid-archive-index/evidence/valid-upgrade.evidence.json +105 -0
  165. package/tests/fixtures/evidence-bundles/invalid-archive-index/evidence-bundle.json +109 -0
  166. package/tests/fixtures/evidence-bundles/invalid-hash/archive/evidence-archive-index.json +52 -0
  167. package/tests/fixtures/evidence-bundles/invalid-hash/evidence/repo-map.evidence.json +68 -0
  168. package/tests/fixtures/evidence-bundles/invalid-hash/evidence/valid-upgrade.evidence.json +105 -0
  169. package/tests/fixtures/evidence-bundles/invalid-hash/evidence-bundle.json +109 -0
  170. package/tests/fixtures/evidence-bundles/invalid-missing-entry/archive/evidence-archive-index.json +52 -0
  171. package/tests/fixtures/evidence-bundles/invalid-missing-entry/evidence/repo-map.evidence.json +68 -0
  172. package/tests/fixtures/evidence-bundles/invalid-missing-entry/evidence/valid-upgrade.evidence.json +105 -0
  173. package/tests/fixtures/evidence-bundles/invalid-missing-entry/evidence-bundle.json +109 -0
  174. package/tests/fixtures/evidence-bundles/invalid-path/archive/evidence-archive-index.json +52 -0
  175. package/tests/fixtures/evidence-bundles/invalid-path/evidence/repo-map.evidence.json +68 -0
  176. package/tests/fixtures/evidence-bundles/invalid-path/evidence/valid-upgrade.evidence.json +105 -0
  177. package/tests/fixtures/evidence-bundles/invalid-path/evidence-bundle.json +109 -0
  178. package/tests/fixtures/evidence-bundles/invalid-provenance/archive/evidence-archive-index.json +52 -0
  179. package/tests/fixtures/evidence-bundles/invalid-provenance/evidence/repo-map.evidence.json +68 -0
  180. package/tests/fixtures/evidence-bundles/invalid-provenance/evidence/valid-upgrade.evidence.json +105 -0
  181. package/tests/fixtures/evidence-bundles/invalid-provenance/evidence-bundle.json +109 -0
  182. package/tests/fixtures/evidence-bundles/invalid-regression/archive/evidence-archive-index.json +52 -0
  183. package/tests/fixtures/evidence-bundles/invalid-regression/evidence/repo-map.evidence.json +68 -0
  184. package/tests/fixtures/evidence-bundles/invalid-regression/evidence/valid-upgrade.evidence.json +105 -0
  185. package/tests/fixtures/evidence-bundles/invalid-regression/evidence-bundle.json +113 -0
  186. package/tests/fixtures/evidence-bundles/invalid-retention/archive/evidence-archive-index.json +52 -0
  187. package/tests/fixtures/evidence-bundles/invalid-retention/evidence/repo-map.evidence.json +68 -0
  188. package/tests/fixtures/evidence-bundles/invalid-retention/evidence/valid-upgrade.evidence.json +105 -0
  189. package/tests/fixtures/evidence-bundles/invalid-retention/evidence-bundle.json +109 -0
  190. package/tests/fixtures/evidence-bundles/invalid-signature-plan/archive/evidence-archive-index.json +52 -0
  191. package/tests/fixtures/evidence-bundles/invalid-signature-plan/evidence/repo-map.evidence.json +68 -0
  192. package/tests/fixtures/evidence-bundles/invalid-signature-plan/evidence/valid-upgrade.evidence.json +105 -0
  193. package/tests/fixtures/evidence-bundles/invalid-signature-plan/evidence-bundle.json +109 -0
  194. package/tests/fixtures/evidence-bundles/valid-bundle/archive/evidence-archive-index.json +52 -0
  195. package/tests/fixtures/evidence-bundles/valid-bundle/evidence/repo-map.evidence.json +68 -0
  196. package/tests/fixtures/evidence-bundles/valid-bundle/evidence/valid-upgrade.evidence.json +105 -0
  197. package/tests/fixtures/evidence-bundles/valid-bundle/evidence-bundle.json +109 -0
  198. package/tests/fixtures/external-adapters/empty/README.md +3 -0
  199. package/tests/fixtures/external-adapters/invalid-completion-override/.coding-agent/adapters/completion/adapter.json +53 -0
  200. package/tests/fixtures/external-adapters/invalid-deploy/.coding-agent/adapters/deploy/adapter.json +60 -0
  201. package/tests/fixtures/external-adapters/invalid-evidence-suppression/.coding-agent/adapters/evidence/adapter.json +53 -0
  202. package/tests/fixtures/external-adapters/invalid-failure-suppression/.coding-agent/adapters/failures/adapter.json +53 -0
  203. package/tests/fixtures/external-adapters/invalid-git-push/.coding-agent/adapters/publish/adapter.json +60 -0
  204. package/tests/fixtures/external-adapters/invalid-malformed/.coding-agent/adapters/malformed/adapter.json +1 -0
  205. package/tests/fixtures/external-adapters/invalid-malformed/malformed-adapter.txt +1 -0
  206. package/tests/fixtures/external-adapters/invalid-mode-escalation/.coding-agent/adapters/mode/adapter.json +53 -0
  207. package/tests/fixtures/external-adapters/invalid-path-traversal/.coding-agent/adapters/path/adapter.json +53 -0
  208. package/tests/fixtures/external-adapters/invalid-restriction-removal/.coding-agent/adapters/restrictions/adapter.json +52 -0
  209. package/tests/fixtures/external-adapters/invalid-scope-expansion/.coding-agent/adapters/scope/adapter.json +53 -0
  210. package/tests/fixtures/external-adapters/invalid-secret-exposure/.coding-agent/adapters/secrets/adapter.json +53 -0
  211. package/tests/fixtures/external-adapters/invalid-skill-id/.coding-agent/adapters/skill/adapter.json +53 -0
  212. package/tests/fixtures/external-adapters/invalid-skill-version/.coding-agent/adapters/skill-version/adapter.json +53 -0
  213. package/tests/fixtures/external-adapters/invalid-unknown-manifest/.coding-agent/adapters/unknown/manifest.json +1 -0
  214. package/tests/fixtures/external-adapters/invalid-version/.coding-agent/adapters/version/adapter.json +53 -0
  215. package/tests/fixtures/external-adapters/mixed/.coding-agent/adapters/invalid/adapter.json +60 -0
  216. package/tests/fixtures/external-adapters/mixed/.coding-agent/adapters/valid/adapter.json +53 -0
  217. package/tests/fixtures/external-adapters/valid-basic/.coding-agent/adapters/basic/adapter.json +53 -0
  218. package/tests/fixtures/external-adapters/valid-doc-precedence/coding-agent/adapters/docs/adapter.json +53 -0
  219. package/tests/fixtures/external-adapters/valid-runtime-status/adapters/coding-agent/runtime/adapter.json +65 -0
  220. package/tests/fixtures/mutation/cases.json +87 -0
  221. package/tests/fixtures/mutation/snapshot-target/README.md +3 -0
  222. package/tests/fixtures/mutation/snapshot-target/state.json +4 -0
  223. package/tests/fixtures/policy/commands.json +164 -0
  224. package/tests/fixtures/policy/properties.json +126 -0
  225. package/tests/fixtures/privacy/cases.json +47 -0
  226. package/tests/fixtures/project-adapter-installation/invalid-adapter-location/.agents/adapters/basic/adapter.json +53 -0
  227. package/tests/fixtures/project-adapter-installation/invalid-adapter-location/.coding-agent/skills.json +23 -0
  228. package/tests/fixtures/project-adapter-installation/invalid-adapter-schema-version/.coding-agent/adapters/basic/adapter.json +53 -0
  229. package/tests/fixtures/project-adapter-installation/invalid-adapter-schema-version/.coding-agent/skills.json +23 -0
  230. package/tests/fixtures/project-adapter-installation/invalid-adapter-version-mismatch/.coding-agent/adapters/basic/adapter.json +53 -0
  231. package/tests/fixtures/project-adapter-installation/invalid-adapter-version-mismatch/.coding-agent/skills.json +23 -0
  232. package/tests/fixtures/project-adapter-installation/invalid-bad-semver/.coding-agent/adapters/basic/adapter.json +53 -0
  233. package/tests/fixtures/project-adapter-installation/invalid-bad-semver/.coding-agent/skills.json +23 -0
  234. package/tests/fixtures/project-adapter-installation/invalid-completion-override/.coding-agent/adapters/basic/adapter.json +53 -0
  235. package/tests/fixtures/project-adapter-installation/invalid-completion-override/.coding-agent/skills.json +23 -0
  236. package/tests/fixtures/project-adapter-installation/invalid-failure-suppression/.coding-agent/adapters/basic/adapter.json +53 -0
  237. package/tests/fixtures/project-adapter-installation/invalid-failure-suppression/.coding-agent/skills.json +23 -0
  238. package/tests/fixtures/project-adapter-installation/invalid-missing-declaration/.coding-agent/adapters/basic/adapter.json +53 -0
  239. package/tests/fixtures/project-adapter-installation/invalid-mode-escalation/.coding-agent/adapters/basic/adapter.json +53 -0
  240. package/tests/fixtures/project-adapter-installation/invalid-mode-escalation/.coding-agent/skills.json +23 -0
  241. package/tests/fixtures/project-adapter-installation/invalid-path-traversal/.coding-agent/adapters/basic/adapter.json +53 -0
  242. package/tests/fixtures/project-adapter-installation/invalid-path-traversal/.coding-agent/skills.json +23 -0
  243. package/tests/fixtures/project-adapter-installation/invalid-scope-expansion/.coding-agent/adapters/basic/adapter.json +53 -0
  244. package/tests/fixtures/project-adapter-installation/invalid-scope-expansion/.coding-agent/skills.json +23 -0
  245. package/tests/fixtures/project-adapter-installation/invalid-secret-exposure/.coding-agent/adapters/basic/adapter.json +53 -0
  246. package/tests/fixtures/project-adapter-installation/invalid-secret-exposure/.coding-agent/skills.json +23 -0
  247. package/tests/fixtures/project-adapter-installation/invalid-skill-mismatch/.coding-agent/adapters/basic/adapter.json +53 -0
  248. package/tests/fixtures/project-adapter-installation/invalid-skill-mismatch/.coding-agent/skills.json +23 -0
  249. package/tests/fixtures/project-adapter-installation/invalid-unknown-skill/.coding-agent/adapters/basic/adapter.json +53 -0
  250. package/tests/fixtures/project-adapter-installation/invalid-unknown-skill/.coding-agent/skills.json +23 -0
  251. package/tests/fixtures/project-adapter-installation/invalid-unsupported-core-version/.coding-agent/adapters/basic/adapter.json +53 -0
  252. package/tests/fixtures/project-adapter-installation/invalid-unsupported-core-version/.coding-agent/skills.json +23 -0
  253. package/tests/fixtures/project-adapter-installation/invalid-weakens-restrictions/.coding-agent/adapters/basic/adapter.json +52 -0
  254. package/tests/fixtures/project-adapter-installation/invalid-weakens-restrictions/.coding-agent/skills.json +23 -0
  255. package/tests/fixtures/project-adapter-installation/valid-compatible-range/coding-agent/adapters/docs/adapter.json +53 -0
  256. package/tests/fixtures/project-adapter-installation/valid-compatible-range/coding-agent.skills.json +23 -0
  257. package/tests/fixtures/project-adapter-installation/valid-exact-pin/.coding-agent/adapters/basic/adapter.json +53 -0
  258. package/tests/fixtures/project-adapter-installation/valid-exact-pin/.coding-agent/skills.json +23 -0
  259. package/tests/fixtures/project-adapter-installation/valid-multiple-adapters/.coding-agent/skills.json +28 -0
  260. package/tests/fixtures/project-adapter-installation/valid-multiple-adapters/adapters/coding-agent/repo/adapter.json +53 -0
  261. package/tests/fixtures/project-adapter-installation/valid-multiple-adapters/adapters/coding-agent/runtime/adapter.json +58 -0
  262. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  263. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/01-current/.coding-agent/skills.json +27 -0
  264. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/02-incompatible/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  265. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/02-incompatible/.coding-agent/skills.json +27 -0
  266. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/03-target/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  267. package/tests/fixtures/project-adapter-upgrade-chains/broken-compatibility-chain/03-target/.coding-agent/skills.json +27 -0
  268. package/tests/fixtures/project-adapter-upgrade-chains/schema-drift-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  269. package/tests/fixtures/project-adapter-upgrade-chains/schema-drift-chain/01-current/.coding-agent/skills.json +27 -0
  270. package/tests/fixtures/project-adapter-upgrade-chains/schema-drift-chain/02-schema-drift/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  271. package/tests/fixtures/project-adapter-upgrade-chains/schema-drift-chain/02-schema-drift/.coding-agent/skills.json +27 -0
  272. package/tests/fixtures/project-adapter-upgrade-chains/skill-drift-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  273. package/tests/fixtures/project-adapter-upgrade-chains/skill-drift-chain/01-current/.coding-agent/skills.json +27 -0
  274. package/tests/fixtures/project-adapter-upgrade-chains/skill-drift-chain/02-skill-drift/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  275. package/tests/fixtures/project-adapter-upgrade-chains/skill-drift-chain/02-skill-drift/.coding-agent/skills.json +27 -0
  276. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  277. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/01-current/.coding-agent/skills.json +27 -0
  278. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/02-stale/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  279. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/02-stale/.coding-agent/skills.json +27 -0
  280. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/03-target/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  281. package/tests/fixtures/project-adapter-upgrade-chains/stale-pin-chain/03-target/.coding-agent/skills.json +27 -0
  282. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  283. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/01-current/.coding-agent/skills.json +27 -0
  284. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/02-safe/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  285. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/02-safe/.coding-agent/skills.json +27 -0
  286. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/03-weakens-restrictions/.coding-agent/adapters/fixture-chain-adapter/adapter.json +69 -0
  287. package/tests/fixtures/project-adapter-upgrade-chains/unsafe-weakening-chain/03-weakens-restrictions/.coding-agent/skills.json +27 -0
  288. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/01-current/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  289. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/01-current/.coding-agent/skills.json +27 -0
  290. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/02-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  291. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/02-upgrade/.coding-agent/skills.json +27 -0
  292. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/03-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  293. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/03-upgrade/.coding-agent/skills.json +27 -0
  294. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/04-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  295. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/04-upgrade/.coding-agent/skills.json +27 -0
  296. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/05-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  297. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/05-upgrade/.coding-agent/skills.json +27 -0
  298. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/06-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  299. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/06-upgrade/.coding-agent/skills.json +27 -0
  300. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/07-upgrade/.coding-agent/adapters/fixture-chain-adapter/adapter.json +70 -0
  301. package/tests/fixtures/project-adapter-upgrade-chains/valid-chain/07-upgrade/.coding-agent/skills.json +27 -0
  302. package/tests/fixtures/project-adapter-upgrades/adapter-schema-drift/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  303. package/tests/fixtures/project-adapter-upgrades/adapter-schema-drift/after/.coding-agent/skills.json +27 -0
  304. package/tests/fixtures/project-adapter-upgrades/adapter-schema-drift/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  305. package/tests/fixtures/project-adapter-upgrades/adapter-schema-drift/before/.coding-agent/skills.json +27 -0
  306. package/tests/fixtures/project-adapter-upgrades/safe-upgrade-preserves-restrictions/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +71 -0
  307. package/tests/fixtures/project-adapter-upgrades/safe-upgrade-preserves-restrictions/after/.coding-agent/skills.json +27 -0
  308. package/tests/fixtures/project-adapter-upgrades/safe-upgrade-preserves-restrictions/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  309. package/tests/fixtures/project-adapter-upgrades/safe-upgrade-preserves-restrictions/before/.coding-agent/skills.json +27 -0
  310. package/tests/fixtures/project-adapter-upgrades/skill-compatibility-drift/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  311. package/tests/fixtures/project-adapter-upgrades/skill-compatibility-drift/after/.coding-agent/skills.json +27 -0
  312. package/tests/fixtures/project-adapter-upgrades/skill-compatibility-drift/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  313. package/tests/fixtures/project-adapter-upgrades/skill-compatibility-drift/before/.coding-agent/skills.json +27 -0
  314. package/tests/fixtures/project-adapter-upgrades/stale-compatible-range/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  315. package/tests/fixtures/project-adapter-upgrades/stale-compatible-range/after/.coding-agent/skills.json +27 -0
  316. package/tests/fixtures/project-adapter-upgrades/stale-compatible-range/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  317. package/tests/fixtures/project-adapter-upgrades/stale-compatible-range/before/.coding-agent/skills.json +27 -0
  318. package/tests/fixtures/project-adapter-upgrades/stale-exact-pin/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  319. package/tests/fixtures/project-adapter-upgrades/stale-exact-pin/after/.coding-agent/skills.json +27 -0
  320. package/tests/fixtures/project-adapter-upgrades/stale-exact-pin/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  321. package/tests/fixtures/project-adapter-upgrades/stale-exact-pin/before/.coding-agent/skills.json +27 -0
  322. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-mode-escalation/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  323. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-mode-escalation/after/.coding-agent/skills.json +27 -0
  324. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-mode-escalation/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  325. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-mode-escalation/before/.coding-agent/skills.json +27 -0
  326. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-removes-evidence/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +69 -0
  327. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-removes-evidence/after/.coding-agent/skills.json +27 -0
  328. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-removes-evidence/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  329. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-removes-evidence/before/.coding-agent/skills.json +27 -0
  330. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-weakens-restrictions/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +69 -0
  331. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-weakens-restrictions/after/.coding-agent/skills.json +27 -0
  332. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-weakens-restrictions/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  333. package/tests/fixtures/project-adapter-upgrades/unsafe-upgrade-weakens-restrictions/before/.coding-agent/skills.json +27 -0
  334. package/tests/fixtures/project-adapter-upgrades/unsupported-future-core/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  335. package/tests/fixtures/project-adapter-upgrades/unsupported-future-core/after/.coding-agent/skills.json +27 -0
  336. package/tests/fixtures/project-adapter-upgrades/unsupported-future-core/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  337. package/tests/fixtures/project-adapter-upgrades/unsupported-future-core/before/.coding-agent/skills.json +27 -0
  338. package/tests/fixtures/project-adapter-upgrades/unsupported-old-core/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  339. package/tests/fixtures/project-adapter-upgrades/unsupported-old-core/after/.coding-agent/skills.json +27 -0
  340. package/tests/fixtures/project-adapter-upgrades/unsupported-old-core/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  341. package/tests/fixtures/project-adapter-upgrades/unsupported-old-core/before/.coding-agent/skills.json +27 -0
  342. package/tests/fixtures/project-adapter-upgrades/valid-upgrade/after/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  343. package/tests/fixtures/project-adapter-upgrades/valid-upgrade/after/.coding-agent/skills.json +27 -0
  344. package/tests/fixtures/project-adapter-upgrades/valid-upgrade/before/.coding-agent/adapters/fixture-upgrade-adapter/adapter.json +70 -0
  345. package/tests/fixtures/project-adapter-upgrades/valid-upgrade/before/.coding-agent/skills.json +27 -0
  346. package/tests/fixtures/sample-repo/.env.example +1 -0
  347. package/tests/fixtures/sample-repo/README.md +4 -0
  348. package/tests/fixtures/sample-repo/docs/architecture.md +3 -0
  349. package/tests/fixtures/sample-repo/package.json +11 -0
  350. package/tests/fixtures/sample-repo/src/index.js +3 -0
  351. package/tests/fixtures/sample-repo/test/index.test.js +8 -0
  352. package/tests/fixtures/triggers/cases.json +101 -0
  353. package/tests/policy/README.md +16 -0
  354. package/tests/privacy/README.md +14 -0
  355. package/tests/safety/README.md +17 -0
  356. package/tests/trigger/README.md +11 -0
  357. package/work-ledger.md +159 -0
@@ -0,0 +1,441 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { fileURLToPath } from "node:url";
4
+
5
+ import {
6
+ adapterIssues,
7
+ detectSensitiveValues,
8
+ PILOT_SKILLS,
9
+ PILOT_VERSION,
10
+ } from "./pack-rules.mjs";
11
+ import { validateValue } from "./schema-validator.mjs";
12
+
13
+ export const ADAPTER_MANIFEST_FILENAME = "adapter.json";
14
+ export const ADAPTER_SCHEMA_VERSION = "1.0.0";
15
+ export const EXTERNAL_ADAPTER_LOCATIONS = [
16
+ ".coding-agent/adapters",
17
+ "coding-agent/adapters",
18
+ "adapters/coding-agent",
19
+ ];
20
+
21
+ const DEFAULT_CORE_ROOT = path.resolve(
22
+ path.dirname(fileURLToPath(import.meta.url)),
23
+ "..",
24
+ "..",
25
+ );
26
+ const MAX_MANIFEST_BYTES = 256 * 1024;
27
+
28
+ function inside(root, candidate) {
29
+ const relative = path.relative(root, candidate);
30
+ return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
31
+ }
32
+
33
+ function publicIssueCode(issue) {
34
+ if (/unsupported adapterVersion/i.test(issue)) return "unsupported-adapter-version";
35
+ if (/unknown pilot skill/i.test(issue)) return "unsupported-skill-id";
36
+ if (/override .* mode/i.test(issue)) return "mode-override";
37
+ if (/incompatible with/i.test(issue)) return "incompatible-skill-version";
38
+ if (/unsafe adapter path/i.test(issue)) return "unsafe-path";
39
+ if (/weakens required restriction/i.test(issue)) return "restriction-weakening";
40
+ if (/inherit shared restrictions/i.test(issue)) return "missing-shared-inheritance";
41
+ if (/remove shared restrictions/i.test(issue)) return "restriction-removal";
42
+ if (/suppress failures/i.test(issue)) return "failure-suppression";
43
+ if (/redefine completion/i.test(issue)) return "completion-override";
44
+ if (/expose secrets/i.test(issue)) return "secret-exposure";
45
+ if (/remove required evidence/i.test(issue)) return "required-evidence-removal";
46
+ if (/expand scope/i.test(issue)) return "scope-expansion";
47
+ if (/unsafe command alias/i.test(issue)) return "unsafe-command-alias";
48
+ if (/command alias .* declares/i.test(issue)) return "command-family-mismatch";
49
+ if (/unsafe status command|not status-only/i.test(issue)) {
50
+ return "unsafe-status-command";
51
+ }
52
+ if (/status commands require runtime-truth/i.test(issue)) {
53
+ return "runtime-status-incompatible";
54
+ }
55
+ if (/required evidence/i.test(issue)) return "required-evidence";
56
+ return "semantic-validation";
57
+ }
58
+
59
+ function schemaIssueCodes(errors) {
60
+ const codes = new Set();
61
+ for (const error of errors) {
62
+ codes.add("schema-validation");
63
+ if (/adapterVersion/.test(error)) codes.add("unsupported-adapter-version");
64
+ if (/supportedSkills.*id/.test(error)) codes.add("unsupported-skill-id");
65
+ if (/declaredMode/.test(error)) codes.add("mode-override");
66
+ if (/safeReadPaths|ignoredPaths|documentationPrecedence|rootMarkers/.test(error)) {
67
+ codes.add("unsafe-path");
68
+ }
69
+ if (/deniedOperationCategories/.test(error)) codes.add("restriction-weakening");
70
+ if (/allowRestrictionRemoval/.test(error)) codes.add("restriction-removal");
71
+ if (/allowFailureSuppression/.test(error)) codes.add("failure-suppression");
72
+ if (/allowCompletionOverride/.test(error)) codes.add("completion-override");
73
+ if (/allowSecretExposure/.test(error)) codes.add("secret-exposure");
74
+ if (/allowRequiredEvidenceRemoval|requiredEvidence/.test(error)) {
75
+ codes.add("required-evidence-removal");
76
+ }
77
+ if (/allowScopeExpansionWithoutApproval|requireApprovalOutsideScope/.test(error)) {
78
+ codes.add("scope-expansion");
79
+ }
80
+ }
81
+ return [...codes];
82
+ }
83
+
84
+ export function readSafeJsonFile(file, options = {}) {
85
+ const stat = fs.statSync(file);
86
+ if (stat.size > MAX_MANIFEST_BYTES) {
87
+ return { value: null, codes: ["manifest-too-large"] };
88
+ }
89
+
90
+ const raw = fs.readFileSync(file, "utf8");
91
+ if (options.scanSensitive !== false && detectSensitiveValues(raw).length > 0) {
92
+ return { value: null, codes: ["secret-like-content"] };
93
+ }
94
+
95
+ try {
96
+ return { value: JSON.parse(raw), codes: [] };
97
+ } catch {
98
+ return { value: null, codes: ["malformed-json"] };
99
+ }
100
+ }
101
+
102
+ function loadCore(coreRoot) {
103
+ if (!fs.existsSync(coreRoot) || !fs.lstatSync(coreRoot).isDirectory()) {
104
+ return { error: ["core-root-unavailable"] };
105
+ }
106
+
107
+ for (const relative of [
108
+ "schemas/project-adapter.schema.json",
109
+ ...PILOT_SKILLS.flatMap((skill) => [
110
+ `examples/manifests/${skill}.json`,
111
+ `examples/command-policies/${skill}.json`,
112
+ ]),
113
+ ]) {
114
+ if (!fs.existsSync(path.join(coreRoot, relative))) {
115
+ return { error: ["core-skill-metadata-unavailable"] };
116
+ }
117
+ }
118
+
119
+ const schemaRecord = readSafeJsonFile(
120
+ path.join(coreRoot, "schemas", "project-adapter.schema.json"),
121
+ { scanSensitive: false },
122
+ );
123
+ if (!schemaRecord.value) {
124
+ return { error: ["core-schema-unavailable"] };
125
+ }
126
+
127
+ const manifests = {};
128
+ const policies = {};
129
+ for (const skill of PILOT_SKILLS) {
130
+ const manifestRecord = readSafeJsonFile(
131
+ path.join(coreRoot, "examples", "manifests", `${skill}.json`),
132
+ { scanSensitive: false },
133
+ );
134
+ const policyRecord = readSafeJsonFile(
135
+ path.join(coreRoot, "examples", "command-policies", `${skill}.json`),
136
+ { scanSensitive: false },
137
+ );
138
+ if (!manifestRecord.value || !policyRecord.value) {
139
+ return { error: ["core-skill-metadata-unavailable"] };
140
+ }
141
+ manifests[skill] = manifestRecord.value;
142
+ policies[skill] = policyRecord.value;
143
+ }
144
+
145
+ return {
146
+ schema: schemaRecord.value,
147
+ manifests,
148
+ policies,
149
+ error: [],
150
+ };
151
+ }
152
+
153
+ function inspectPath(root, candidate) {
154
+ if (!inside(root, candidate)) return ["path-escape"];
155
+
156
+ const relative = path.relative(root, candidate);
157
+ let current = root;
158
+ for (const segment of relative.split(path.sep).filter(Boolean)) {
159
+ current = path.join(current, segment);
160
+ if (!fs.existsSync(current)) break;
161
+ if (fs.lstatSync(current).isSymbolicLink()) return ["symlink-escape"];
162
+ }
163
+ return [];
164
+ }
165
+
166
+ function discover(adapterRoot) {
167
+ const failures = [];
168
+ const manifests = [];
169
+
170
+ for (const location of EXTERNAL_ADAPTER_LOCATIONS) {
171
+ const container = path.resolve(adapterRoot, location);
172
+ const pathIssues = inspectPath(adapterRoot, container);
173
+ if (pathIssues.length) {
174
+ failures.push({ location, codes: pathIssues });
175
+ continue;
176
+ }
177
+ if (!fs.existsSync(container)) continue;
178
+
179
+ const containerStat = fs.lstatSync(container);
180
+ if (!containerStat.isDirectory()) {
181
+ failures.push({ location, codes: ["adapter-container-not-directory"] });
182
+ continue;
183
+ }
184
+
185
+ for (const entry of fs.readdirSync(container, { withFileTypes: true })) {
186
+ const adapterDirectory = path.join(container, entry.name);
187
+ const publicLocation = `${location}/<adapter>/${ADAPTER_MANIFEST_FILENAME}`;
188
+ if (entry.isSymbolicLink()) {
189
+ failures.push({ location: publicLocation, codes: ["symlink-escape"] });
190
+ continue;
191
+ }
192
+ if (!entry.isDirectory()) {
193
+ failures.push({
194
+ location: `${location}/<entry>`,
195
+ codes: ["unexpected-adapter-entry"],
196
+ });
197
+ continue;
198
+ }
199
+
200
+ const manifest = path.join(adapterDirectory, ADAPTER_MANIFEST_FILENAME);
201
+ const manifestIssues = inspectPath(adapterRoot, manifest);
202
+ if (manifestIssues.length) {
203
+ failures.push({ location: publicLocation, codes: manifestIssues });
204
+ continue;
205
+ }
206
+ if (!fs.existsSync(manifest)) {
207
+ failures.push({ location: publicLocation, codes: ["missing-adapter-manifest"] });
208
+ continue;
209
+ }
210
+
211
+ const manifestStat = fs.lstatSync(manifest);
212
+ if (manifestStat.isSymbolicLink()) {
213
+ failures.push({ location: publicLocation, codes: ["symlink-escape"] });
214
+ continue;
215
+ }
216
+ if (!manifestStat.isFile()) {
217
+ failures.push({ location: publicLocation, codes: ["manifest-not-regular-file"] });
218
+ continue;
219
+ }
220
+
221
+ const realManifest = fs.realpathSync(manifest);
222
+ if (!inside(adapterRoot, realManifest)) {
223
+ failures.push({ location: publicLocation, codes: ["symlink-escape"] });
224
+ continue;
225
+ }
226
+ manifests.push({ file: manifest, location: publicLocation, rootLocation: location });
227
+ }
228
+ }
229
+
230
+ return { manifests, failures };
231
+ }
232
+
233
+ function validateCompatibility(adapter, manifests, coreVersion) {
234
+ const codes = [];
235
+ if (adapter.adapterVersion !== ADAPTER_SCHEMA_VERSION) {
236
+ codes.push("unsupported-adapter-version");
237
+ }
238
+ for (const skill of adapter.supportedSkills ?? []) {
239
+ const manifest = manifests[skill.id];
240
+ if (!manifest) {
241
+ codes.push("unsupported-skill-id");
242
+ continue;
243
+ }
244
+ if (manifest.mode !== skill.declaredMode) codes.push("mode-override");
245
+ if (
246
+ !manifest.adapterCompatibility?.compatibleAdapterVersions?.includes(
247
+ adapter.adapterVersion,
248
+ )
249
+ ) {
250
+ codes.push("unsupported-adapter-version");
251
+ }
252
+ }
253
+ return codes;
254
+ }
255
+
256
+ export function validateExternalAdapters(adapterRootInput, options = {}) {
257
+ const input = String(adapterRootInput ?? "");
258
+ if (!input.trim()) {
259
+ return {
260
+ ok: false,
261
+ status: "failed",
262
+ discovered: 0,
263
+ accepted: [],
264
+ rejected: [],
265
+ failures: [{ location: "<root>", codes: ["missing-adapter-root"] }],
266
+ };
267
+ }
268
+ if (input.split(/[\\/]+/).includes("..")) {
269
+ return {
270
+ ok: false,
271
+ status: "failed",
272
+ discovered: 0,
273
+ accepted: [],
274
+ rejected: [],
275
+ failures: [{ location: "<root>", codes: ["root-path-traversal"] }],
276
+ };
277
+ }
278
+
279
+ const adapterRoot = path.resolve(input);
280
+ if (!fs.existsSync(adapterRoot)) {
281
+ return {
282
+ ok: false,
283
+ status: "failed",
284
+ discovered: 0,
285
+ accepted: [],
286
+ rejected: [],
287
+ failures: [{ location: "<root>", codes: ["adapter-root-not-found"] }],
288
+ };
289
+ }
290
+ if (fs.lstatSync(adapterRoot).isSymbolicLink()) {
291
+ return {
292
+ ok: false,
293
+ status: "failed",
294
+ discovered: 0,
295
+ accepted: [],
296
+ rejected: [],
297
+ failures: [{ location: "<root>", codes: ["symlink-escape"] }],
298
+ };
299
+ }
300
+ if (!fs.lstatSync(adapterRoot).isDirectory()) {
301
+ return {
302
+ ok: false,
303
+ status: "failed",
304
+ discovered: 0,
305
+ accepted: [],
306
+ rejected: [],
307
+ failures: [{ location: "<root>", codes: ["adapter-root-not-directory"] }],
308
+ };
309
+ }
310
+
311
+ const realRoot = fs.realpathSync(adapterRoot);
312
+ const core = loadCore(path.resolve(options.coreRoot ?? DEFAULT_CORE_ROOT));
313
+ const coreVersion = options.coreVersion ?? PILOT_VERSION;
314
+ if (core.error.length) {
315
+ return {
316
+ ok: false,
317
+ status: "failed",
318
+ discovered: 0,
319
+ accepted: [],
320
+ rejected: [],
321
+ failures: [{ location: "<core>", codes: core.error }],
322
+ };
323
+ }
324
+
325
+ const discovery = discover(realRoot);
326
+ const accepted = [];
327
+ const rejected = [];
328
+
329
+ for (const candidate of discovery.manifests) {
330
+ const record = readSafeJsonFile(candidate.file);
331
+ if (!record.value) {
332
+ rejected.push({ location: candidate.location, codes: record.codes });
333
+ continue;
334
+ }
335
+
336
+ const schemaErrors = validateValue(core.schema, record.value);
337
+ const semanticErrors = adapterIssues(record.value, {
338
+ policies: core.policies,
339
+ skillVersion: coreVersion,
340
+ });
341
+ const codes = new Set([
342
+ ...schemaIssueCodes(schemaErrors),
343
+ ...semanticErrors.map(publicIssueCode),
344
+ ...validateCompatibility(record.value, core.manifests, coreVersion),
345
+ ]);
346
+
347
+ if (codes.size > 0) {
348
+ rejected.push({ location: candidate.location, codes: [...codes].sort() });
349
+ continue;
350
+ }
351
+
352
+ accepted.push({
353
+ location: candidate.location,
354
+ rootLocation: candidate.rootLocation,
355
+ adapterId: record.value.adapterId,
356
+ adapterVersion: record.value.adapterVersion,
357
+ projectId: record.value.project.id,
358
+ skills: record.value.supportedSkills.map((skill) => skill.id).sort(),
359
+ skillCompatibility: record.value.supportedSkills
360
+ .map((skill) => ({
361
+ id: skill.id,
362
+ compatibleVersions: [...skill.compatibleVersions].sort(),
363
+ declaredMode: skill.declaredMode,
364
+ }))
365
+ .sort((left, right) => left.id.localeCompare(right.id)),
366
+ requiredEvidence: [...record.value.extensions.requiredEvidence].sort(),
367
+ approvalRequirements: record.value.approvalRequirements
368
+ .map((requirement) => requirement.operation)
369
+ .sort(),
370
+ deniedOperationCategories: [
371
+ ...record.value.inheritance.deniedOperationCategories,
372
+ ].sort(),
373
+ inheritance: {
374
+ sharedRestrictions: record.value.inheritance.sharedRestrictions,
375
+ allowRestrictionRemoval: record.value.inheritance.allowRestrictionRemoval,
376
+ allowModeOverride: record.value.inheritance.allowModeOverride,
377
+ allowFailureSuppression: record.value.inheritance.allowFailureSuppression,
378
+ allowCompletionOverride: record.value.inheritance.allowCompletionOverride,
379
+ allowSecretExposure: record.value.inheritance.allowSecretExposure,
380
+ allowRequiredEvidenceRemoval:
381
+ record.value.inheritance.allowRequiredEvidenceRemoval,
382
+ allowScopeExpansionWithoutApproval:
383
+ record.value.inheritance.allowScopeExpansionWithoutApproval,
384
+ },
385
+ });
386
+ }
387
+
388
+ const failures = discovery.failures;
389
+ const discovered = discovery.manifests.length + failures.length;
390
+ const ok = rejected.length === 0 && failures.length === 0;
391
+ return {
392
+ ok,
393
+ status: ok ? (discovered === 0 ? "empty" : "complete") : "failed",
394
+ discovered,
395
+ accepted,
396
+ rejected,
397
+ failures,
398
+ };
399
+ }
400
+
401
+ export function formatExternalAdapterSummary(result) {
402
+ if (result.status === "empty") {
403
+ return ["external adapter validation complete: 0 adapters discovered"];
404
+ }
405
+
406
+ const rejectedCount = result.rejected.length + result.failures.length;
407
+ const lines = [
408
+ `external adapter validation ${result.ok ? "complete" : "failed"}: ` +
409
+ `${result.accepted.length} accepted, ${rejectedCount} rejected`,
410
+ ];
411
+
412
+ for (const [index, accepted] of result.accepted.entries()) {
413
+ lines.push(`accepted adapter ${index + 1}: skills=${accepted.skills.join(",")}`);
414
+ }
415
+ for (const [index, rejected] of [
416
+ ...result.rejected,
417
+ ...result.failures,
418
+ ].entries()) {
419
+ lines.push(`rejected adapter ${index + 1}: ${[...new Set(rejected.codes)].join(",")}`);
420
+ }
421
+
422
+ return lines;
423
+ }
424
+
425
+ export function externalAdapterCliResult(adapterRoot, options = {}) {
426
+ if (!adapterRoot) {
427
+ return {
428
+ exitCode: 2,
429
+ stream: "stderr",
430
+ lines: ["usage: node scripts/validate-adapters.mjs <adapter-root>"],
431
+ };
432
+ }
433
+
434
+ const result = validateExternalAdapters(adapterRoot, options);
435
+ return {
436
+ exitCode: result.ok ? 0 : 1,
437
+ stream: result.ok ? "stdout" : "stderr",
438
+ lines: formatExternalAdapterSummary(result),
439
+ result,
440
+ };
441
+ }