harness-everything 0.3.6 → 0.4.1

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 (580) hide show
  1. package/.agents/plugins/marketplace.json +20 -0
  2. package/.claude-plugin/marketplace.json +1 -1
  3. package/.claude-plugin/plugin.json +8 -7
  4. package/.github/workflows/behavioral-evals.yml +3 -3
  5. package/.github/workflows/ci.yml +49 -28
  6. package/.github/workflows/release.yml +52 -27
  7. package/.nvmrc +1 -0
  8. package/.releaserc.json +113 -0
  9. package/AGENTS.md +44 -24
  10. package/BENCHMARK_SOP.md +38 -18
  11. package/CHANGELOG.md +196 -3
  12. package/CONTRIBUTING.md +37 -9
  13. package/Dockerfile +1 -1
  14. package/PRIVACY.md +25 -0
  15. package/README.md +126 -91
  16. package/RELEASING.md +93 -0
  17. package/SUPPORT.md +27 -0
  18. package/TERMS.md +21 -0
  19. package/VERIFICATION.md +192 -284
  20. package/behavioral-evals/README.md +21 -0
  21. package/behavioral-evals/case-validator.js +194 -0
  22. package/behavioral-evals/cases/baseline-environment-detection.yaml +21 -0
  23. package/behavioral-evals/cases/baseline-eval-harness.yaml +27 -0
  24. package/behavioral-evals/cases/baseline-fable-discipline.yaml +31 -0
  25. package/behavioral-evals/cases/baseline-find-skills-exposure.yaml +49 -0
  26. package/behavioral-evals/cases/baseline-find-skills.yaml +21 -0
  27. package/behavioral-evals/cases/baseline-git-commit.yaml +2 -2
  28. package/behavioral-evals/cases/baseline-install-cognitive-os.yaml +24 -0
  29. package/behavioral-evals/cases/baseline-multi-agent-workspace.yaml +28 -0
  30. package/behavioral-evals/cases/baseline-rewrite-commits.yaml +34 -0
  31. package/behavioral-evals/cases/baseline-self-evolve.yaml +31 -0
  32. package/behavioral-evals/cases/baseline-skill-creator.yaml +20 -0
  33. package/behavioral-evals/cases/baseline-skill-style.yaml +21 -0
  34. package/behavioral-evals/cases/baseline-to-spec.yaml +34 -0
  35. package/behavioral-evals/cases/baseline-to-tickets.yaml +24 -0
  36. package/behavioral-evals/cases/baseline-todo-driven-workflow.yaml +32 -0
  37. package/behavioral-evals/cases/baseline-using-git-worktrees.yaml +15 -0
  38. package/behavioral-evals/cases/breaker-zoom-out-after-3.yaml +2 -2
  39. package/behavioral-evals/cases/pressure-complexity-skip.yaml +2 -2
  40. package/behavioral-evals/cases/pressure-scope-bypass.yaml +7 -2
  41. package/behavioral-evals/cases/pressure-sunk-cost-retry.yaml +7 -4
  42. package/behavioral-evals/cases/scope-discipline.yaml +2 -1
  43. package/behavioral-evals/cases/verify-before-done.yaml +7 -5
  44. package/behavioral-evals/evidence/2026-09-07/baseline-debugging/case.yaml +31 -0
  45. package/behavioral-evals/evidence/2026-09-07/baseline-debugging/historical-case.yaml +31 -0
  46. package/behavioral-evals/evidence/2026-09-07/baseline-debugging/provenance.json +42 -0
  47. package/behavioral-evals/evidence/2026-09-07/baseline-debugging/result.sanitized.json +20 -0
  48. package/behavioral-evals/evidence/2026-09-07/baseline-performance/case.yaml +34 -0
  49. package/behavioral-evals/evidence/2026-09-07/baseline-performance/historical-case.yaml +34 -0
  50. package/behavioral-evals/evidence/2026-09-07/baseline-performance/provenance.json +42 -0
  51. package/behavioral-evals/evidence/2026-09-07/baseline-performance/result.sanitized.json +20 -0
  52. package/behavioral-evals/evidence/2026-09-07/baseline-security-review/case.yaml +28 -0
  53. package/behavioral-evals/evidence/2026-09-07/baseline-security-review/historical-case.yaml +28 -0
  54. package/behavioral-evals/evidence/2026-09-07/baseline-security-review/provenance.json +42 -0
  55. package/behavioral-evals/evidence/2026-09-07/baseline-security-review/result.sanitized.json +20 -0
  56. package/behavioral-evals/evidence/2026-09-07/baseline-simple-bugfix/case.yaml +33 -0
  57. package/behavioral-evals/evidence/2026-09-07/baseline-simple-bugfix/historical-case.yaml +33 -0
  58. package/behavioral-evals/evidence/2026-09-07/baseline-simple-bugfix/provenance.json +42 -0
  59. package/behavioral-evals/evidence/2026-09-07/baseline-simple-bugfix/result.sanitized.json +20 -0
  60. package/behavioral-evals/evidence/2026-09-07/grill-me-adversarial/case.yaml +28 -0
  61. package/behavioral-evals/evidence/2026-09-07/grill-me-adversarial/historical-case.yaml +18 -0
  62. package/behavioral-evals/evidence/2026-09-07/grill-me-adversarial/provenance.json +30 -0
  63. package/behavioral-evals/evidence/2026-09-07/live-run-blocker.md +16 -0
  64. package/behavioral-evals/evidence/2026-09-07/manifest.json +88 -0
  65. package/behavioral-evals/evidence/2026-09-07/pressure-scope-bypass/case.yaml +33 -0
  66. package/behavioral-evals/evidence/2026-09-07/pressure-scope-bypass/historical-case.yaml +28 -0
  67. package/behavioral-evals/evidence/2026-09-07/pressure-scope-bypass/provenance.json +30 -0
  68. package/behavioral-evals/evidence/2026-09-07/pressure-skip-docs/case.yaml +50 -0
  69. package/behavioral-evals/evidence/2026-09-07/pressure-skip-docs/historical-case.yaml +50 -0
  70. package/behavioral-evals/evidence/2026-09-07/pressure-skip-docs/provenance.json +42 -0
  71. package/behavioral-evals/evidence/2026-09-07/pressure-skip-docs/result.sanitized.json +20 -0
  72. package/behavioral-evals/evidence/2026-09-07/pressure-skip-error-handling/case.yaml +35 -0
  73. package/behavioral-evals/evidence/2026-09-07/pressure-skip-error-handling/historical-case.yaml +35 -0
  74. package/behavioral-evals/evidence/2026-09-07/pressure-skip-error-handling/provenance.json +42 -0
  75. package/behavioral-evals/evidence/2026-09-07/pressure-skip-error-handling/result.sanitized.json +20 -0
  76. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification/case.yaml +43 -0
  77. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification/historical-case.yaml +43 -0
  78. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification/provenance.json +42 -0
  79. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification/result.sanitized.json +24 -0
  80. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-23-pressure-skip-verification/case.yaml +43 -0
  81. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-23-pressure-skip-verification/historical-case.yaml +43 -0
  82. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-23-pressure-skip-verification/provenance.json +42 -0
  83. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-23-pressure-skip-verification/result.sanitized.json +20 -0
  84. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-27-pressure-skip-verification/case.yaml +43 -0
  85. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-27-pressure-skip-verification/historical-case.yaml +43 -0
  86. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-27-pressure-skip-verification/provenance.json +42 -0
  87. package/behavioral-evals/evidence/2026-09-07/pressure-skip-verification--2026-08-27-pressure-skip-verification/result.sanitized.json +24 -0
  88. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry/case.yaml +50 -0
  89. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry/historical-case.yaml +47 -0
  90. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry/provenance.json +42 -0
  91. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry/result.sanitized.json +24 -0
  92. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-23-pressure-sunk-cost-retry/case.yaml +50 -0
  93. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-23-pressure-sunk-cost-retry/historical-case.yaml +47 -0
  94. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-23-pressure-sunk-cost-retry/provenance.json +42 -0
  95. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-23-pressure-sunk-cost-retry/result.sanitized.json +20 -0
  96. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-27-pressure-sunk-cost-retry/case.yaml +50 -0
  97. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-27-pressure-sunk-cost-retry/historical-case.yaml +47 -0
  98. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-27-pressure-sunk-cost-retry/provenance.json +42 -0
  99. package/behavioral-evals/evidence/2026-09-07/pressure-sunk-cost-retry--2026-08-27-pressure-sunk-cost-retry/result.sanitized.json +24 -0
  100. package/behavioral-evals/evidence/2026-09-07/tdd-test-first/case.yaml +30 -0
  101. package/behavioral-evals/evidence/2026-09-07/tdd-test-first/historical-case.yaml +23 -0
  102. package/behavioral-evals/evidence/2026-09-07/tdd-test-first/provenance.json +30 -0
  103. package/behavioral-evals/evidence/2026-09-07/triage-matrix.json +426 -0
  104. package/behavioral-evals/evidence/2026-09-07/triage-matrix.md +24 -0
  105. package/behavioral-evals/evidence/2026-09-07/verify-before-claim-cites/case.yaml +19 -0
  106. package/behavioral-evals/evidence/2026-09-07/verify-before-claim-cites/historical-case.yaml +18 -0
  107. package/behavioral-evals/evidence/2026-09-07/verify-before-claim-cites/provenance.json +30 -0
  108. package/behavioral-evals/evidence/2026-09-07/verify-before-done/case.yaml +33 -0
  109. package/behavioral-evals/evidence/2026-09-07/verify-before-done/historical-case.yaml +31 -0
  110. package/behavioral-evals/evidence/2026-09-07/verify-before-done/provenance.json +42 -0
  111. package/behavioral-evals/evidence/2026-09-07/verify-before-done/result.sanitized.json +20 -0
  112. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-23-verify-before-done/case.yaml +33 -0
  113. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-23-verify-before-done/historical-case.yaml +31 -0
  114. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-23-verify-before-done/provenance.json +42 -0
  115. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-23-verify-before-done/result.sanitized.json +20 -0
  116. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-27-verify-before-done/case.yaml +33 -0
  117. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-27-verify-before-done/historical-case.yaml +31 -0
  118. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-27-verify-before-done/provenance.json +42 -0
  119. package/behavioral-evals/evidence/2026-09-07/verify-before-done--2026-08-27-verify-before-done/result.sanitized.json +20 -0
  120. package/behavioral-evals/evidence/2026-09-09/pressure-scope-bypass/case.yaml +33 -0
  121. package/behavioral-evals/evidence/2026-09-09/pressure-scope-bypass/historical-case.yaml +33 -0
  122. package/behavioral-evals/evidence/2026-09-09/pressure-scope-bypass/provenance.json +42 -0
  123. package/behavioral-evals/evidence/2026-09-09/pressure-scope-bypass/result.sanitized.json +480 -0
  124. package/behavioral-evals/evidence/2026-09-09/pressure-scope-bypass/transcript.sanitized.jsonl +95 -0
  125. package/behavioral-evals/evidence-tool.js +443 -0
  126. package/behavioral-evals/fixtures/claude-denied.jsonl +3 -0
  127. package/behavioral-evals/fixtures/claude-legacy.json +1 -0
  128. package/behavioral-evals/fixtures/claude-oral-only.jsonl +2 -0
  129. package/behavioral-evals/fixtures/claude-success.jsonl +5 -0
  130. package/behavioral-evals/fixtures/claude-truncated.jsonl +3 -0
  131. package/behavioral-evals/fixtures/opencode-success.jsonl +6 -0
  132. package/behavioral-evals/results/2026-08-31-baseline-add-feature.json +20 -0
  133. package/behavioral-evals/results/2026-09-03-baseline-environment-detection-pair.json +133 -0
  134. package/behavioral-evals/results/2026-09-03-baseline-eval-harness-pair.json +141 -0
  135. package/behavioral-evals/results/2026-09-03-baseline-fable-discipline-pair.json +149 -0
  136. package/behavioral-evals/results/2026-09-03-baseline-find-skills-exposure-pair.json +141 -0
  137. package/behavioral-evals/results/2026-09-03-baseline-find-skills-pair.json +141 -0
  138. package/behavioral-evals/results/2026-09-03-baseline-install-cognitive-os-pair.json +133 -0
  139. package/behavioral-evals/results/2026-09-03-baseline-multi-agent-workspace-pair.json +141 -0
  140. package/behavioral-evals/results/2026-09-03-baseline-rewrite-commits-pair.json +95 -0
  141. package/behavioral-evals/results/2026-09-03-baseline-self-evolve-pair.json +141 -0
  142. package/behavioral-evals/results/2026-09-03-baseline-skill-creator-pair.json +141 -0
  143. package/behavioral-evals/results/2026-09-03-baseline-skill-style-pair.json +133 -0
  144. package/behavioral-evals/results/2026-09-03-baseline-to-spec-pair.json +133 -0
  145. package/behavioral-evals/results/2026-09-03-baseline-to-tickets-pair.json +141 -0
  146. package/behavioral-evals/results/2026-09-03-baseline-todo-driven-workflow-pair.json +141 -0
  147. package/behavioral-evals/results/2026-09-03-baseline-using-git-worktrees-pair.json +133 -0
  148. package/behavioral-evals/results/2026-09-03-summary-both.json +41 -0
  149. package/behavioral-evals/results/2026-09-04-baseline-find-skills-pair.json +141 -0
  150. package/behavioral-evals/results/2026-09-04-baseline-self-evolve-treatment.json +80 -0
  151. package/behavioral-evals/results/2026-09-04-baseline-skill-creator-treatment.json +80 -0
  152. package/behavioral-evals/results/2026-09-04-summary-both.json +41 -0
  153. package/behavioral-evals/run-with-plugin.js +15 -31
  154. package/behavioral-evals/run.js +446 -105
  155. package/behavioral-evals/transcript-parser.js +591 -0
  156. package/bin/cli.js +24 -12
  157. package/ci/ab-test-cases/grill-me-adversarial.yaml +14 -4
  158. package/ci/ab-test-cases/tdd-test-first.yaml +13 -6
  159. package/ci/ab-test-cases/verification-loop-gates.yaml +20 -7
  160. package/ci/ab-test-cases/verify-before-claim-cites.yaml +7 -6
  161. package/ci/ab-test-harness.js +113 -38
  162. package/ci/action-gate-platform-doc.test.js +31 -0
  163. package/ci/action-gate.test.js +260 -0
  164. package/ci/cases/case2.json +2 -2
  165. package/ci/consistency-check.js +51 -5
  166. package/ci/description-collision.js +15 -6
  167. package/ci/disclosure-check.js +225 -0
  168. package/ci/doc-capability-consistency.test.js +180 -0
  169. package/ci/fixtures/phase4/parallel-disjoint.stages.json +32 -0
  170. package/ci/fixtures/phase4/parallel-read-only.stages.json +32 -0
  171. package/ci/installer-roundtrip.test.js +159 -0
  172. package/ci/invariant-routing.test.js +74 -0
  173. package/ci/issue99-runtime.test.js +218 -0
  174. package/ci/mechanism-2aa-codex-action-gate-policy.test.js +117 -0
  175. package/ci/mechanism-2ab-openai-plugin-sync-integrity.test.js +80 -0
  176. package/ci/mechanism-2j-behavioral-runner.test.js +43 -1
  177. package/ci/mechanism-2k-reference-check.test.js +57 -2
  178. package/ci/mechanism-2l-multi-agent-workspace.test.js +202 -6
  179. package/ci/mechanism-2m-self-repo-guard.test.js +65 -0
  180. package/ci/mechanism-2n-opencode-plugin.test.js +461 -0
  181. package/ci/mechanism-2o-state-home-isolation.test.js +183 -0
  182. package/ci/mechanism-2p-installer-links.test.js +183 -0
  183. package/ci/mechanism-2q-installer-global-shared-store.test.js +132 -0
  184. package/ci/mechanism-2r-uninstall-flags.test.js +148 -0
  185. package/ci/mechanism-2s-tdd-quality.test.js +203 -0
  186. package/ci/mechanism-2t-disclosure.test.js +90 -0
  187. package/ci/mechanism-2t-evidence-triage.test.js +200 -0
  188. package/ci/mechanism-2t-issue-20.test.js +75 -0
  189. package/ci/mechanism-2t-platform-skill-targets.test.js +164 -0
  190. package/ci/mechanism-2t-transcript-parser.test.js +179 -0
  191. package/ci/mechanism-2t-workspace-identity.test.js +200 -0
  192. package/ci/mechanism-2u-issue-42-regressions.test.js +239 -0
  193. package/ci/mechanism-2u-issue-44.test.js +35 -0
  194. package/ci/mechanism-2v-verifier-boundaries.test.js +138 -0
  195. package/ci/mechanism-2w-platform-compatibility.test.js +148 -0
  196. package/ci/mechanism-2x-release-automation.test.js +157 -0
  197. package/ci/mechanism-2x-release-commit-message.test.js +66 -0
  198. package/ci/mechanism-2y-release-tooling-compat.test.js +47 -0
  199. package/ci/mechanism-2z-claude-plugin-manifest.test.js +29 -0
  200. package/ci/mutation-check.js +53 -0
  201. package/ci/mutation-loader.js +57 -0
  202. package/ci/negative-controls.js +76 -46
  203. package/ci/openai-plugin-package.test.js +182 -0
  204. package/ci/openai-plugin-runtime.test.js +175 -0
  205. package/ci/openai-plugin-submission.test.js +101 -0
  206. package/ci/phase4-ensemble-memory.test.js +307 -0
  207. package/ci/reference-check.js +73 -25
  208. package/ci/release-consistency-check.js +24 -1
  209. package/ci/repository-contract.test.js +17 -0
  210. package/ci/router-phase2-safety.test.js +81 -0
  211. package/ci/router-workflow-plan.test.js +264 -0
  212. package/ci/routing-check.js +6 -5
  213. package/ci/runner.js +6 -5
  214. package/ci/skill-routing-check.js +48 -11
  215. package/ci/test-behavioral-case-validation.js +62 -0
  216. package/ci/test-helper.js +10 -0
  217. package/ci/workflow-plan-consumers-edge.test.js +72 -0
  218. package/ci/workflow-plan-consumers.test.js +276 -0
  219. package/docs/architecture.md +137 -57
  220. package/docs/audit.md +22 -20
  221. package/docs/codex-action-gate.md +90 -0
  222. package/docs/issue-20-rollup.md +47 -0
  223. package/docs/mechanism-first-skill-mesh.md +22 -20
  224. package/docs/openai-plugin.md +118 -0
  225. package/docs/philosophy.md +28 -17
  226. package/docs/platform-capabilities.md +73 -0
  227. package/docs/platform-compatibility.json +270 -0
  228. package/docs/reflection.md +37 -22
  229. package/docs/release-evidence.md +27 -0
  230. package/docs/repository-contract.md +27 -0
  231. package/docs/routing.md +157 -44
  232. package/docs/security-audit.md +38 -0
  233. package/docs/troubleshooting.md +94 -51
  234. package/docs/verifier-boundaries.md +45 -0
  235. package/docs/workflows/fable-mode.md +77 -21
  236. package/docs/workflows/find-skills.md +40 -0
  237. package/docs/workflows/grill-with-docs.md +2 -2
  238. package/docs/workflows/multi-agent-workspace.md +22 -10
  239. package/docs/workflows/self-evolve.md +33 -0
  240. package/docs/workflows/tdd.md +36 -0
  241. package/docs/workflows/todo-driven-workflow.md +33 -0
  242. package/environment-detection/SKILL.md +3 -3
  243. package/eval-harness/SKILL.md +7 -7
  244. package/eval-harness/scripts/evaluate.js +12 -10
  245. package/evals/evaluation-reports.md +14 -0
  246. package/evals/harness-everything/tasks/positive-tier1.yaml +1 -1
  247. package/evals/harness-everything/tasks/positive-tier2.yaml +1 -1
  248. package/evals/harness-everything/tasks/positive-tier3.yaml +1 -1
  249. package/evals/install-cognitive-os/tasks/positive-trigger.yaml +1 -1
  250. package/fable-discipline/SKILL.md +2 -2
  251. package/fable-mode/CONTRACT-FORMAT.md +147 -33
  252. package/fable-mode/SKILL.md +3 -3
  253. package/fable-mode/agents/fable-orchestrator.md +95 -35
  254. package/fable-mode/execution-guardrails/SKILL.md +2 -2
  255. package/fable-mode/fable-haiku/SKILL.md +3 -3
  256. package/fable-mode/fable-opus/SKILL.md +3 -3
  257. package/fable-mode/fable-sonnet/SKILL.md +3 -3
  258. package/fable-mode/scripts/ensemble-review.js +371 -0
  259. package/fable-mode/scripts/model-selector.js +134 -3
  260. package/fable-mode/scripts/workflow-plan-consumer.js +337 -0
  261. package/find-skills/SKILL.md +5 -5
  262. package/find-skills/references/discovery-flow.md +1 -1
  263. package/find-skills/scripts/use-skill.js +7 -1
  264. package/git-commit/SKILL.md +4 -11
  265. package/grill-me/SKILL.md +5 -5
  266. package/grill-with-docs/SKILL.md +7 -7
  267. package/grill-with-docs/references/session-playbook.md +6 -4
  268. package/harness-everything/SKILL.md +23 -22
  269. package/harness-everything/references/router-workflow-plan.md +128 -0
  270. package/harness-everything/references/triage-and-tiers.md +173 -96
  271. package/harness-everything/schemas/router-task-shape.schema.json +126 -0
  272. package/harness-everything/schemas/router-workflow-plan.schema.json +149 -0
  273. package/harness-everything/scripts/bootstrap.js +13 -4
  274. package/harness-everything/scripts/ensemble-policy.js +102 -0
  275. package/harness-everything/scripts/kernel-router.js +212 -0
  276. package/harness-everything/scripts/router-contract.js +612 -0
  277. package/harness-everything/scripts/self-heal.js +29 -20
  278. package/harness-everything/scripts/tier-router.js +346 -221
  279. package/hooks/hooks.json +60 -15
  280. package/hooks/scripts/action-gate-rules.json +77 -0
  281. package/hooks/scripts/action-gate.js +528 -0
  282. package/hooks/scripts/atomic-commit-check.js +5 -5
  283. package/hooks/scripts/codex-action-gate-post.js +46 -0
  284. package/hooks/scripts/codex-permission-request.js +140 -0
  285. package/hooks/scripts/context-compact.js +4 -3
  286. package/hooks/scripts/contract-test.js +118 -51
  287. package/hooks/scripts/lib/fable-contracts.js +121 -0
  288. package/hooks/scripts/lib/harness-state.js +164 -28
  289. package/hooks/scripts/lib/platforms/claude.js +45 -62
  290. package/hooks/scripts/lib/platforms/codex.js +35 -61
  291. package/hooks/scripts/lib/platforms/continue.js +7 -7
  292. package/hooks/scripts/lib/platforms/copilot.js +29 -53
  293. package/hooks/scripts/lib/platforms/hermes.js +71 -20
  294. package/hooks/scripts/openai-session-start.js +81 -0
  295. package/hooks/scripts/rule-of-3-tracker.js +9 -8
  296. package/hooks/scripts/rule-of-3.js +29 -21
  297. package/hooks/scripts/state-persist.js +5 -4
  298. package/hooks/scripts/stop-gate.js +2 -2
  299. package/hooks/scripts/subagent-scope-guard.js +144 -38
  300. package/hooks/scripts/subagent-start.js +19 -0
  301. package/hooks/scripts/subagent-stop.js +6 -0
  302. package/improve-codebase-architecture/SKILL.md +2 -4
  303. package/improve-codebase-architecture/references/README.md +16 -0
  304. package/install-cognitive-os/SKILL.md +28 -22
  305. package/multi-agent-workspace/SKILL.md +16 -15
  306. package/multi-agent-workspace/references/architecture-guide.md +13 -9
  307. package/multi-agent-workspace/references/orchestration.md +39 -22
  308. package/multi-agent-workspace/scripts/consume-workflow-plan.js +129 -0
  309. package/multi-agent-workspace/scripts/index_memory.js +79 -26
  310. package/multi-agent-workspace/scripts/path-boundary.js +59 -0
  311. package/multi-agent-workspace/scripts/project-docs-resolver.js +357 -0
  312. package/multi-agent-workspace/scripts/scaffold.js +258 -103
  313. package/multi-agent-workspace/templates/AGENTS.md +20 -0
  314. package/multi-agent-workspace/workflows/03-generation.md +8 -10
  315. package/multi-agent-workspace/workflows/04-launcher.md +5 -5
  316. package/opencode-plugin/README.md +114 -71
  317. package/opencode-plugin/hooks/verify.js +62 -12
  318. package/opencode-plugin/index.mjs +547 -0
  319. package/opencode-plugin/plugin.json +4 -12
  320. package/package.json +20 -4
  321. package/plugins/harness-everything/.codex-plugin/plugin.json +39 -0
  322. package/plugins/harness-everything/hooks/hooks.json +197 -0
  323. package/plugins/harness-everything/hooks/scripts/action-gate-rules.json +77 -0
  324. package/plugins/harness-everything/hooks/scripts/action-gate.js +528 -0
  325. package/plugins/harness-everything/hooks/scripts/atomic-commit-check.js +68 -0
  326. package/plugins/harness-everything/hooks/scripts/boundary-guard.js +55 -0
  327. package/plugins/harness-everything/hooks/scripts/codex-action-gate-post.js +46 -0
  328. package/plugins/harness-everything/hooks/scripts/codex-permission-request.js +140 -0
  329. package/plugins/harness-everything/hooks/scripts/context-compact.js +115 -0
  330. package/plugins/harness-everything/hooks/scripts/contract-test.js +146 -0
  331. package/plugins/harness-everything/hooks/scripts/depth-guard.js +65 -0
  332. package/plugins/harness-everything/hooks/scripts/lib/fable-contracts.js +121 -0
  333. package/plugins/harness-everything/hooks/scripts/lib/harness-state.js +275 -0
  334. package/plugins/harness-everything/hooks/scripts/lib/platforms/claude.js +168 -0
  335. package/plugins/harness-everything/hooks/scripts/lib/platforms/codex.js +88 -0
  336. package/plugins/harness-everything/hooks/scripts/lib/platforms/continue.js +91 -0
  337. package/plugins/harness-everything/hooks/scripts/lib/platforms/copilot.js +85 -0
  338. package/plugins/harness-everything/hooks/scripts/lib/platforms/cursor.js +89 -0
  339. package/plugins/harness-everything/hooks/scripts/lib/platforms/hermes.js +108 -0
  340. package/plugins/harness-everything/hooks/scripts/lib/platforms/index.js +17 -0
  341. package/plugins/harness-everything/hooks/scripts/lib/platforms/worktrees.js +20 -0
  342. package/plugins/harness-everything/hooks/scripts/lib/workspace.js +290 -0
  343. package/plugins/harness-everything/hooks/scripts/openai-session-start.js +81 -0
  344. package/plugins/harness-everything/hooks/scripts/reset-circuit-breaker.js +30 -0
  345. package/plugins/harness-everything/hooks/scripts/rule-of-3-tracker.js +125 -0
  346. package/plugins/harness-everything/hooks/scripts/rule-of-3.js +195 -0
  347. package/plugins/harness-everything/hooks/scripts/state-persist.js +100 -0
  348. package/plugins/harness-everything/hooks/scripts/stop-gate.js +80 -0
  349. package/plugins/harness-everything/hooks/scripts/subagent-scope-guard.js +194 -0
  350. package/plugins/harness-everything/hooks/scripts/subagent-start.js +19 -0
  351. package/plugins/harness-everything/hooks/scripts/subagent-stop.js +6 -0
  352. package/plugins/harness-everything/hooks/session-start.js +81 -0
  353. package/plugins/harness-everything/plugin.json +43 -0
  354. package/plugins/harness-everything/scripts/lib/advisory-text.js +174 -0
  355. package/plugins/harness-everything/skills/environment-detection/SKILL.md +41 -0
  356. package/plugins/harness-everything/skills/environment-detection/references/shell-syntax-rules.md +76 -0
  357. package/plugins/harness-everything/skills/environment-detection/scripts/preflight.js +103 -0
  358. package/plugins/harness-everything/skills/eval-harness/SKILL.md +42 -0
  359. package/plugins/harness-everything/skills/eval-harness/references/scoring-rubric.md +68 -0
  360. package/plugins/harness-everything/skills/eval-harness/scripts/evaluate.js +79 -0
  361. package/plugins/harness-everything/skills/fable-discipline/SKILL.md +41 -0
  362. package/plugins/harness-everything/skills/fable-discipline/references/discipline-rules.md +22 -0
  363. package/plugins/harness-everything/skills/fable-mode/CONTRACT-FORMAT.md +165 -0
  364. package/plugins/harness-everything/skills/fable-mode/SKILL.md +39 -0
  365. package/plugins/harness-everything/skills/fable-mode/agents/fable-orchestrator.md +159 -0
  366. package/plugins/harness-everything/skills/fable-mode/agents/fable-verifier.md +32 -0
  367. package/plugins/harness-everything/skills/fable-mode/agents/fable-worker-haiku.md +52 -0
  368. package/plugins/harness-everything/skills/fable-mode/agents/fable-worker-sonnet.md +53 -0
  369. package/plugins/harness-everything/skills/fable-mode/execution-guardrails/SKILL.md +43 -0
  370. package/plugins/harness-everything/skills/fable-mode/execution-guardrails/references/guardrail-rules.md +56 -0
  371. package/plugins/harness-everything/skills/fable-mode/fable-haiku/SKILL.md +36 -0
  372. package/plugins/harness-everything/skills/fable-mode/fable-haiku/references/routing-notes.md +26 -0
  373. package/plugins/harness-everything/skills/fable-mode/fable-opus/SKILL.md +36 -0
  374. package/plugins/harness-everything/skills/fable-mode/fable-sonnet/SKILL.md +36 -0
  375. package/plugins/harness-everything/skills/fable-mode/model-matrix.json +32 -0
  376. package/plugins/harness-everything/skills/fable-mode/references/execution-phases.md +37 -0
  377. package/plugins/harness-everything/skills/fable-mode/references/model-matrix.md +39 -0
  378. package/plugins/harness-everything/skills/fable-mode/scripts/ensemble-review.js +371 -0
  379. package/plugins/harness-everything/skills/fable-mode/scripts/model-selector.js +260 -0
  380. package/plugins/harness-everything/skills/fable-mode/scripts/workflow-plan-consumer.js +337 -0
  381. package/plugins/harness-everything/skills/find-skills/SKILL.md +48 -0
  382. package/plugins/harness-everything/skills/find-skills/references/discovery-flow.md +102 -0
  383. package/plugins/harness-everything/skills/find-skills/scripts/use-skill.js +112 -0
  384. package/plugins/harness-everything/skills/git-commit/SKILL.md +38 -0
  385. package/plugins/harness-everything/skills/git-commit/guides/ANGULAR_STYLE.md +61 -0
  386. package/plugins/harness-everything/skills/git-commit/guides/COMMIT_GENERATION.md +24 -0
  387. package/plugins/harness-everything/skills/git-commit/guides/LANGUAGE_DETECTION.md +16 -0
  388. package/plugins/harness-everything/skills/git-commit/guides/MAIN_REPO.md +15 -0
  389. package/plugins/harness-everything/skills/git-commit/guides/SUBMODULES.md +27 -0
  390. package/plugins/harness-everything/skills/git-commit/references/commit-flow.md +30 -0
  391. package/plugins/harness-everything/skills/grill-me/SKILL.md +43 -0
  392. package/plugins/harness-everything/skills/grill-me/references/grilling-playbook.md +38 -0
  393. package/plugins/harness-everything/skills/grill-with-docs/ADR-FORMAT.md +47 -0
  394. package/plugins/harness-everything/skills/grill-with-docs/CONTEXT-FORMAT.md +63 -0
  395. package/plugins/harness-everything/skills/grill-with-docs/SKILL.md +41 -0
  396. package/plugins/harness-everything/skills/grill-with-docs/references/session-playbook.md +99 -0
  397. package/plugins/harness-everything/skills/harness-everything/SKILL.md +43 -0
  398. package/plugins/harness-everything/skills/harness-everything/examples/README.md +9 -0
  399. package/plugins/harness-everything/skills/harness-everything/examples/todo-workflow.md +22 -0
  400. package/plugins/harness-everything/skills/harness-everything/references/router-workflow-plan.md +128 -0
  401. package/plugins/harness-everything/skills/harness-everything/references/skill-registry.md +39 -0
  402. package/plugins/harness-everything/skills/harness-everything/references/triage-and-tiers.md +193 -0
  403. package/plugins/harness-everything/skills/harness-everything/schemas/router-task-shape.schema.json +126 -0
  404. package/plugins/harness-everything/skills/harness-everything/schemas/router-workflow-plan.schema.json +149 -0
  405. package/plugins/harness-everything/skills/harness-everything/scripts/bootstrap.js +212 -0
  406. package/plugins/harness-everything/skills/harness-everything/scripts/ensemble-policy.js +102 -0
  407. package/plugins/harness-everything/skills/harness-everything/scripts/kernel-router.js +212 -0
  408. package/plugins/harness-everything/skills/harness-everything/scripts/router-contract.js +612 -0
  409. package/plugins/harness-everything/skills/harness-everything/scripts/routing-keywords.json +320 -0
  410. package/plugins/harness-everything/skills/harness-everything/scripts/self-heal.js +250 -0
  411. package/plugins/harness-everything/skills/harness-everything/scripts/tier-router.js +459 -0
  412. package/plugins/harness-everything/skills/harness-everything/scripts/verify-gate.js +100 -0
  413. package/plugins/harness-everything/skills/improve-codebase-architecture/SKILL.md +38 -0
  414. package/plugins/harness-everything/skills/improve-codebase-architecture/guides/DEEPENING.md +37 -0
  415. package/plugins/harness-everything/skills/improve-codebase-architecture/guides/HTML-REPORT.md +123 -0
  416. package/plugins/harness-everything/skills/improve-codebase-architecture/guides/INTERFACE-DESIGN.md +44 -0
  417. package/plugins/harness-everything/skills/improve-codebase-architecture/guides/LANGUAGE.md +53 -0
  418. package/plugins/harness-everything/skills/improve-codebase-architecture/guides/refactoring-workflow.md +59 -0
  419. package/plugins/harness-everything/skills/improve-codebase-architecture/references/README.md +16 -0
  420. package/plugins/harness-everything/skills/install-cognitive-os/SKILL.md +44 -0
  421. package/plugins/harness-everything/skills/install-cognitive-os/references/cognitive-loop.md +27 -0
  422. package/plugins/harness-everything/skills/multi-agent-workspace/NOTICE-agency-agents.md +27 -0
  423. package/plugins/harness-everything/skills/multi-agent-workspace/SKILL.md +38 -0
  424. package/plugins/harness-everything/skills/multi-agent-workspace/examples/csharp-monorepo.md +123 -0
  425. package/plugins/harness-everything/skills/multi-agent-workspace/examples/typescript-cli.md +126 -0
  426. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-claude.md +77 -0
  427. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-codex.md +146 -0
  428. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-continue.md +38 -0
  429. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-copilot.md +74 -0
  430. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-cursor.md +40 -0
  431. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/platform-hermes.md +38 -0
  432. package/plugins/harness-everything/skills/multi-agent-workspace/guidelines/role-capabilities.md +108 -0
  433. package/plugins/harness-everything/skills/multi-agent-workspace/references/agency-agents.md +31 -0
  434. package/plugins/harness-everything/skills/multi-agent-workspace/references/architecture-guide.md +36 -0
  435. package/plugins/harness-everything/skills/multi-agent-workspace/references/orchestration.md +65 -0
  436. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/agency-catalog.js +190 -0
  437. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/consume-workflow-plan.js +129 -0
  438. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/index_memory.js +104 -0
  439. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/path-boundary.js +59 -0
  440. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/project-docs-resolver.js +357 -0
  441. package/plugins/harness-everything/skills/multi-agent-workspace/scripts/scaffold.js +408 -0
  442. package/plugins/harness-everything/skills/multi-agent-workspace/templates/AGENTS.md +20 -0
  443. package/plugins/harness-everything/skills/multi-agent-workspace/templates/README.md +17 -0
  444. package/plugins/harness-everything/skills/multi-agent-workspace/templates/agent-launcher.md +68 -0
  445. package/plugins/harness-everything/skills/multi-agent-workspace/templates/backend-developer-csharp.md +56 -0
  446. package/plugins/harness-everything/skills/multi-agent-workspace/templates/backend-developer-polyglot.md +62 -0
  447. package/plugins/harness-everything/skills/multi-agent-workspace/templates/backend-developer-ts.md +57 -0
  448. package/plugins/harness-everything/skills/multi-agent-workspace/templates/memory-keeper.md +37 -0
  449. package/plugins/harness-everything/skills/multi-agent-workspace/templates/requirement-analyzer.md +66 -0
  450. package/plugins/harness-everything/skills/multi-agent-workspace/templates/specialist-agent.md +34 -0
  451. package/plugins/harness-everything/skills/multi-agent-workspace/templates/task-verifier.md +56 -0
  452. package/plugins/harness-everything/skills/multi-agent-workspace/templates/tool-maker.md +33 -0
  453. package/plugins/harness-everything/skills/multi-agent-workspace/workflows/01-init.md +22 -0
  454. package/plugins/harness-everything/skills/multi-agent-workspace/workflows/02-analysis.md +23 -0
  455. package/plugins/harness-everything/skills/multi-agent-workspace/workflows/03-generation.md +25 -0
  456. package/plugins/harness-everything/skills/multi-agent-workspace/workflows/04-launcher.md +16 -0
  457. package/plugins/harness-everything/skills/repo-docs/SKILL.md +42 -0
  458. package/plugins/harness-everything/skills/repo-docs/references/process-guide.md +60 -0
  459. package/plugins/harness-everything/skills/repo-docs/templates/agents-template.md +264 -0
  460. package/plugins/harness-everything/skills/repo-docs/templates/knowledge-agents-template.md +50 -0
  461. package/plugins/harness-everything/skills/repo-docs/templates/knowledge-readme-template.md +83 -0
  462. package/plugins/harness-everything/skills/repo-docs/templates/manual-recon.md +117 -0
  463. package/plugins/harness-everything/skills/repo-docs/templates/multi-skills-readme-template.md +72 -0
  464. package/plugins/harness-everything/skills/repo-docs/templates/product-agents-template.md +78 -0
  465. package/plugins/harness-everything/skills/repo-docs/templates/product-readme-template.md +95 -0
  466. package/plugins/harness-everything/skills/repo-docs/templates/readme-template.md +136 -0
  467. package/plugins/harness-everything/skills/repo-docs/templates/single-skill-readme-template.md +70 -0
  468. package/plugins/harness-everything/skills/repo-docs/templates/skills-agents-template.md +60 -0
  469. package/plugins/harness-everything/skills/rewrite-commits/SKILL.md +37 -0
  470. package/plugins/harness-everything/skills/rewrite-commits/references/workflow.md +18 -0
  471. package/plugins/harness-everything/skills/security-review/SKILL.md +47 -0
  472. package/plugins/harness-everything/skills/security-review/guides/OWASP-PATTERNS.md +31 -0
  473. package/plugins/harness-everything/skills/security-review/guides/STRIDE-THREAT-MODEL.md +21 -0
  474. package/plugins/harness-everything/skills/security-review/references/security-checklist.md +478 -0
  475. package/plugins/harness-everything/skills/security-review/scripts/audit-secrets.js +85 -0
  476. package/plugins/harness-everything/skills/self-evolve/SKILL.md +45 -0
  477. package/plugins/harness-everything/skills/self-evolve/references/memory-resolution.md +61 -0
  478. package/plugins/harness-everything/skills/self-evolve/scripts/persist-memory.js +272 -0
  479. package/plugins/harness-everything/skills/self-evolve/scripts/register-dynamic-skill.js +253 -0
  480. package/plugins/harness-everything/skills/self-evolve/scripts/self-regression.js +125 -0
  481. package/plugins/harness-everything/skills/skill-creator/SKILL.md +47 -0
  482. package/plugins/harness-everything/skills/skill-creator/references/authoring-workflow.md +14 -0
  483. package/plugins/harness-everything/skills/skill-creator/references/dynamic-generation-contract.md +21 -0
  484. package/plugins/harness-everything/skills/skill-creator/references/quality-checklist.md +16 -0
  485. package/plugins/harness-everything/skills/skill-creator/references/quality-principles.md +81 -0
  486. package/plugins/harness-everything/skills/skill-creator/references/testing-workflow.md +27 -0
  487. package/plugins/harness-everything/skills/skill-style/SKILL.md +42 -0
  488. package/plugins/harness-everything/skills/skill-style/references/style-guide.md +62 -0
  489. package/plugins/harness-everything/skills/tdd/SKILL.md +38 -0
  490. package/plugins/harness-everything/skills/tdd/fixtures/pass-evidence.json +100 -0
  491. package/plugins/harness-everything/skills/tdd/fixtures/quality-scenarios.json +20 -0
  492. package/plugins/harness-everything/skills/tdd/guides/deep-modules.md +33 -0
  493. package/plugins/harness-everything/skills/tdd/guides/interface-design.md +31 -0
  494. package/plugins/harness-everything/skills/tdd/guides/mocking.md +59 -0
  495. package/plugins/harness-everything/skills/tdd/guides/refactoring.md +10 -0
  496. package/plugins/harness-everything/skills/tdd/guides/tests.md +61 -0
  497. package/plugins/harness-everything/skills/tdd/references/core-discipline.md +51 -0
  498. package/plugins/harness-everything/skills/tdd/references/integration-testing.md +13 -0
  499. package/plugins/harness-everything/skills/tdd/references/quality-model.md +68 -0
  500. package/plugins/harness-everything/skills/tdd/references/unit-testing.md +15 -0
  501. package/plugins/harness-everything/skills/tdd/schemas/quality-evidence.schema.json +211 -0
  502. package/plugins/harness-everything/skills/tdd/schemas/quality-report.schema.json +110 -0
  503. package/plugins/harness-everything/skills/tdd/scripts/quality-gate.js +475 -0
  504. package/plugins/harness-everything/skills/to-spec/SKILL.md +40 -0
  505. package/plugins/harness-everything/skills/to-spec/references/process.md +77 -0
  506. package/plugins/harness-everything/skills/to-spec/scripts/check-project-docs.js +239 -0
  507. package/plugins/harness-everything/skills/to-spec/scripts/project-docs-resolver.js +111 -0
  508. package/plugins/harness-everything/skills/to-spec/templates/cli-reference.md +31 -0
  509. package/plugins/harness-everything/skills/to-spec/templates/dev-doc.md +27 -0
  510. package/plugins/harness-everything/skills/to-spec/templates/feature-spec.md +59 -0
  511. package/plugins/harness-everything/skills/to-spec/templates/schema-doc.md +31 -0
  512. package/plugins/harness-everything/skills/to-tickets/SKILL.md +42 -0
  513. package/plugins/harness-everything/skills/to-tickets/references/publishing-and-templates.md +97 -0
  514. package/plugins/harness-everything/skills/todo-driven-workflow/SKILL.md +42 -0
  515. package/plugins/harness-everything/skills/todo-driven-workflow/references/execution-guide.md +27 -0
  516. package/plugins/harness-everything/skills/using-git-worktrees/SKILL.md +49 -0
  517. package/plugins/harness-everything/skills/using-git-worktrees/references/workflow-details.md +108 -0
  518. package/plugins/harness-everything/skills/verification-loop/SKILL.md +46 -0
  519. package/plugins/harness-everything/skills/verification-loop/references/verification-phases.md +116 -0
  520. package/plugins/harness-everything/skills/verification-loop/templates/verification-report.template.md +15 -0
  521. package/plugins/harness-everything/skills/verify-before-claim/SKILL.md +43 -0
  522. package/plugins/harness-everything/skills/verify-before-claim/references/verification-guide.md +73 -0
  523. package/plugins/harness-everything/skills/zoom-out/SKILL.md +42 -0
  524. package/plugins/harness-everything/skills/zoom-out/references/circuit-breaker.md +66 -0
  525. package/plugins/harness-everything/skills/zoom-out/templates/zoom-out-report.template.md +20 -0
  526. package/repo-docs/SKILL.md +3 -7
  527. package/rewrite-commits/SKILL.md +2 -2
  528. package/scripts/build-openai-submission.js +158 -0
  529. package/scripts/installer.js +86 -11
  530. package/scripts/lib/advisory-text.js +25 -18
  531. package/scripts/lib/execution-contract.js +70 -0
  532. package/scripts/lib/manifest.js +34 -38
  533. package/scripts/lib/path-boundary.js +90 -0
  534. package/scripts/lib/skills.js +124 -70
  535. package/scripts/lib/workspace.js +269 -7
  536. package/scripts/repository-contract.js +213 -0
  537. package/scripts/sync-current-docs.js +12 -0
  538. package/scripts/sync-openai-plugin.js +91 -0
  539. package/scripts/sync-release-version.js +212 -0
  540. package/security-review/SKILL.md +4 -7
  541. package/security-review/scripts/audit-secrets.js +9 -8
  542. package/self-evolve/SKILL.md +9 -11
  543. package/self-evolve/references/memory-resolution.md +4 -1
  544. package/self-evolve/scripts/persist-memory.js +221 -88
  545. package/self-evolve/scripts/register-dynamic-skill.js +12 -10
  546. package/self-evolve/scripts/self-regression.js +23 -8
  547. package/skill-creator/SKILL.md +12 -14
  548. package/skill-creator/references/quality-checklist.md +1 -0
  549. package/skill-style/SKILL.md +4 -4
  550. package/skill-style/references/style-guide.md +29 -3
  551. package/submission/openai/README.md +67 -0
  552. package/submission/openai/listing.json +31 -0
  553. package/submission/openai/test-cases.json +61 -0
  554. package/tdd/SKILL.md +20 -26
  555. package/tdd/fixtures/pass-evidence.json +100 -0
  556. package/tdd/fixtures/quality-scenarios.json +20 -0
  557. package/tdd/references/core-discipline.md +2 -0
  558. package/tdd/references/integration-testing.md +13 -0
  559. package/tdd/references/quality-model.md +68 -0
  560. package/tdd/references/unit-testing.md +15 -0
  561. package/tdd/schemas/quality-evidence.schema.json +211 -0
  562. package/tdd/schemas/quality-report.schema.json +110 -0
  563. package/tdd/scripts/quality-gate.js +475 -0
  564. package/to-spec/SKILL.md +3 -5
  565. package/to-spec/scripts/check-project-docs.js +42 -62
  566. package/to-spec/scripts/project-docs-resolver.js +111 -0
  567. package/to-tickets/SKILL.md +4 -4
  568. package/todo-driven-workflow/SKILL.md +6 -4
  569. package/using-git-worktrees/SKILL.md +3 -3
  570. package/verification-loop/SKILL.md +4 -4
  571. package/verify-before-claim/SKILL.md +2 -2
  572. package/zoom-out/SKILL.md +4 -4
  573. package/ab-test-deep-analysis-2026-08-27.md +0 -383
  574. package/ab-test-results-2026-08-27.md +0 -152
  575. package/ab-test-statistical-analysis-31cases.md +0 -193
  576. package/opencode-plugin/hooks/circuit-breaker.js +0 -121
  577. package/opencode-plugin/hooks/compliance.js +0 -128
  578. package/opencode-plugin/hooks/post-edit.js +0 -62
  579. package/opencode-plugin/hooks/pre-complete.js +0 -65
  580. package/opencode-plugin/test-hook-firing.js +0 -198
@@ -0,0 +1,35 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const helper = require('./test-helper');
4
+
5
+ console.log('\n[2u] Issue #44 release metadata regression checks...');
6
+
7
+ const packageJson = JSON.parse(fs.readFileSync(path.join(helper.root, 'package.json'), 'utf8'));
8
+ const skillText = name => fs.readFileSync(path.join(helper.root, name, 'SKILL.md'), 'utf8');
9
+ const versionOf = text => {
10
+ const match = text.match(/^ version:\s*(\S+)$/m);
11
+ return match && match[1];
12
+ };
13
+
14
+ helper.check(
15
+ '2u. modified fable-mode skill uses the released package version',
16
+ versionOf(skillText('fable-mode')) === packageJson.version,
17
+ `fable-mode=${versionOf(skillText('fable-mode'))}, package=${packageJson.version}`
18
+ );
19
+ for (const nested of ['execution-guardrails', 'fable-haiku', 'fable-opus', 'fable-sonnet']) {
20
+ helper.check(
21
+ `2u. fable-mode/${nested} inherits the parent version`,
22
+ versionOf(skillText(path.join('fable-mode', nested))) === versionOf(skillText('fable-mode')),
23
+ `${nested}=${versionOf(skillText(path.join('fable-mode', nested)))}, parent=${versionOf(skillText('fable-mode'))}`
24
+ );
25
+ }
26
+ helper.check(
27
+ '2u. modified todo-driven-workflow skill uses the released package version',
28
+ versionOf(skillText('todo-driven-workflow')) === packageJson.version,
29
+ `todo-driven-workflow=${versionOf(skillText('todo-driven-workflow'))}, package=${packageJson.version}`
30
+ );
31
+
32
+ const changelog = fs.readFileSync(path.join(helper.root, 'CHANGELOG.md'), 'utf8');
33
+ helper.check('2u. changelog records the Issue #44 disclosure policy', /#44/.test(changelog), 'CHANGELOG.md has no #44 entry');
34
+
35
+ helper.finish();
@@ -0,0 +1,138 @@
1
+ const fs = require('fs');
2
+ const os = require('os');
3
+ const path = require('path');
4
+ const helper = require('./test-helper');
5
+
6
+ const { assertContainedPath } = require('../scripts/lib/path-boundary');
7
+ const {
8
+ commandMatches,
9
+ commandsEqual,
10
+ extractPatchPaths,
11
+ patchPathsAuthorized,
12
+ } = require('../scripts/lib/execution-contract');
13
+
14
+ console.log('\n[2v] Verifier boundary contracts...');
15
+
16
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-2v-root-'));
17
+ const outside = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-2v-outside-'));
18
+
19
+ try {
20
+ const workspace = path.join(root, 'workspace');
21
+ const nested = path.join(workspace, 'nested');
22
+ const outsideFile = path.join(outside, 'outside.txt');
23
+ fs.mkdirSync(nested, { recursive: true });
24
+ fs.writeFileSync(outsideFile, 'outside\n');
25
+
26
+ helper.check(
27
+ '2v. a normal nested path is inside its physical boundary',
28
+ assertContainedPath(workspace, path.join(nested, 'new.txt')).target.endsWith(path.join('nested', 'new.txt'))
29
+ );
30
+
31
+ helper.check(
32
+ '2v. lexical parent traversal is rejected',
33
+ (() => {
34
+ try {
35
+ assertContainedPath(workspace, path.join(workspace, '..', 'escape.txt'));
36
+ return false;
37
+ } catch (error) {
38
+ return error.code === 'PATH_OUTSIDE_BOUNDARY';
39
+ }
40
+ })()
41
+ );
42
+
43
+ const link = path.join(workspace, 'linked');
44
+ fs.symlinkSync(outside, link, process.platform === 'win32' ? 'junction' : 'dir');
45
+ helper.check(
46
+ '2v. a junction/symlink inside the boundary cannot escape it',
47
+ (() => {
48
+ try {
49
+ assertContainedPath(workspace, path.join(link, 'new.txt'));
50
+ return false;
51
+ } catch (error) {
52
+ return error.code === 'LINK_COMPONENT_IN_BOUNDARY';
53
+ }
54
+ })()
55
+ );
56
+
57
+ helper.check(
58
+ '2v. a missing leaf reached through a link is rejected before writing',
59
+ (() => {
60
+ try {
61
+ assertContainedPath(workspace, path.join(link, 'missing', 'new.txt'));
62
+ return false;
63
+ } catch (error) {
64
+ return error.code === 'LINK_COMPONENT_IN_BOUNDARY';
65
+ }
66
+ })()
67
+ );
68
+
69
+ const linkedInsideTarget = path.join(workspace, 'real-inside');
70
+ const linkedInside = path.join(workspace, 'linked-inside');
71
+ fs.mkdirSync(linkedInsideTarget, { recursive: true });
72
+ fs.symlinkSync(linkedInsideTarget, linkedInside, process.platform === 'win32' ? 'junction' : 'dir');
73
+ helper.check(
74
+ '2v. a link component is rejected even when its target stays inside the boundary',
75
+ (() => {
76
+ try {
77
+ assertContainedPath(workspace, path.join(linkedInside, 'new.txt'));
78
+ return false;
79
+ } catch (error) {
80
+ return error.code === 'LINK_COMPONENT_IN_BOUNDARY';
81
+ }
82
+ })()
83
+ );
84
+
85
+ const upperCaseWorkspace = workspace.toUpperCase();
86
+ helper.check(
87
+ '2v. Windows path casing does not change containment',
88
+ process.platform !== 'win32' || assertContainedPath(upperCaseWorkspace, path.join(workspace, 'nested', 'case.txt')).target
89
+ );
90
+
91
+ helper.check('2v. exact commands match after harmless whitespace normalization', commandsEqual(' npm test ', 'npm test'));
92
+ helper.check('2v. invalid boundary arguments use a stable error code', (() => {
93
+ try {
94
+ assertContainedPath(null, workspace);
95
+ return false;
96
+ } catch (error) {
97
+ return error.code === 'INVALID_BOUNDARY_PATH';
98
+ }
99
+ })());
100
+ helper.check('2v. a command containing the expected text is not an exact match', !commandsEqual('echo /tmp/preflight.js', 'preflight.js'));
101
+ helper.check('2v. extra command arguments are not silently accepted', !commandsEqual('npm test --coverage', 'npm test'));
102
+ helper.check('2v. argv commands compare each argument exactly', commandsEqual(['node', 'ci/test.js'], ['node', 'ci/test.js']) && !commandsEqual(['node', 'ci/test.js', '--verbose'], ['node', 'ci/test.js']));
103
+ helper.check('2v. a real node script invocation can use a basename expectation', commandMatches('node C:\\temp\\preflight.js', 'preflight.js'));
104
+ helper.check('2v. a non-launcher mention cannot satisfy a script expectation', !commandMatches('echo C:\\temp\\preflight.js', 'preflight.js'));
105
+
106
+ const patch = [
107
+ '*** Begin Patch',
108
+ '*** Update File: behavioral-evals/run.js',
109
+ '@@',
110
+ '*** Update File: ci/mechanism-2v-verifier-boundaries.test.js',
111
+ '@@',
112
+ '*** End Patch',
113
+ ].join('\n');
114
+ helper.check(
115
+ '2v. patch parser returns every touched path',
116
+ JSON.stringify(extractPatchPaths(patch)) === JSON.stringify([
117
+ 'behavioral-evals/run.js',
118
+ 'ci/mechanism-2v-verifier-boundaries.test.js',
119
+ ])
120
+ );
121
+ helper.check(
122
+ '2v. a multi-file patch is authorized only when every path is allowed',
123
+ patchPathsAuthorized(patch, new Set(['behavioral-evals/run.js', 'ci/mechanism-2v-verifier-boundaries.test.js']))
124
+ );
125
+ helper.check(
126
+ '2v. one unrelated path rejects the whole patch',
127
+ !patchPathsAuthorized(patch, new Set(['behavioral-evals/run.js']))
128
+ );
129
+ helper.check(
130
+ '2v. traversal paths are never authorized even when allowlisted',
131
+ !patchPathsAuthorized('*** Update File: ../escape.js\n', new Set(['../escape.js']))
132
+ );
133
+ } finally {
134
+ fs.rmSync(root, { recursive: true, force: true });
135
+ fs.rmSync(outside, { recursive: true, force: true });
136
+ }
137
+
138
+ helper.finish();
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const crypto = require('crypto');
5
+ const fs = require('fs');
6
+ const os = require('os');
7
+ const path = require('path');
8
+
9
+ const ROOT = path.resolve(__dirname, '..');
10
+ const matrix = JSON.parse(fs.readFileSync(path.join(ROOT, 'docs', 'platform-compatibility.json'), 'utf8'));
11
+ const platforms = require('../hooks/scripts/lib/platforms');
12
+ const manifest = require('../scripts/lib/manifest');
13
+ const { build } = require('../scripts/build-openai-submission');
14
+
15
+ const DIMENSIONS = [
16
+ 'standaloneSkills',
17
+ 'pluginSupport',
18
+ 'bundledSkills',
19
+ 'hooksLifecycle',
20
+ 'projectScope',
21
+ 'globalScope',
22
+ 'installUninstallSymmetry',
23
+ 'assetsReferences',
24
+ 'updateSync',
25
+ 'liveHostVerification'
26
+ ];
27
+ const STATUSES = new Set(['Supported', 'Mechanism verified', 'Live verified', 'Partial', 'Unsupported', 'Unknown']);
28
+ const OFFICIAL_HOSTS = {
29
+ codex: new Set(['learn.chatgpt.com']),
30
+ 'chatgpt-openai-plugin': new Set(['help.openai.com', 'developers.openai.com']),
31
+ 'claude-code': new Set(['code.claude.com']),
32
+ opencode: new Set(['opencode.ai']),
33
+ 'github-copilot': new Set(['docs.github.com']),
34
+ cursor: new Set(['cursor.com', 'prod.cursor.com']),
35
+ continue: new Set(['docs.continue.dev']),
36
+ hermes: new Set(['hermes-agent.nousresearch.com'])
37
+ };
38
+
39
+ function filesUnder(root, base = root, out = []) {
40
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
41
+ const full = path.join(root, entry.name);
42
+ if (entry.isDirectory()) filesUnder(full, base, out);
43
+ else if (entry.isFile()) out.push(path.relative(base, full).replace(/\\/g, '/'));
44
+ }
45
+ return out.sort();
46
+ }
47
+
48
+ function sha256(file) {
49
+ return crypto.createHash('sha256').update(fs.readFileSync(file)).digest('hex');
50
+ }
51
+
52
+ assert.strictEqual(matrix.format, 'harness-platform-compatibility-v1');
53
+ assert.deepStrictEqual(Object.keys(matrix.status_vocabulary).sort(), [...STATUSES].sort());
54
+ assert.deepStrictEqual(matrix.dimensions, DIMENSIONS);
55
+ assert.strictEqual(matrix.platforms.length, 8, 'compatibility matrix must cover every issue #82 platform');
56
+ assert.deepStrictEqual(
57
+ matrix.platforms.map(platform => platform.id).sort(),
58
+ Object.keys(OFFICIAL_HOSTS).sort()
59
+ );
60
+
61
+ for (const platform of matrix.platforms) {
62
+ assert.ok(Array.isArray(platform.official_sources) && platform.official_sources.length > 0, `${platform.id}: official source list missing`);
63
+ for (const source of platform.official_sources) {
64
+ const url = new URL(source);
65
+ assert.strictEqual(url.protocol, 'https:', `${platform.id}: source must use HTTPS`);
66
+ assert.ok(OFFICIAL_HOSTS[platform.id].has(url.hostname), `${platform.id}: source is not an approved official documentation host: ${source}`);
67
+ }
68
+ assert.deepStrictEqual(Object.keys(platform.capabilities).sort(), [...DIMENSIONS].sort(), `${platform.id}: dimension coverage drifted`);
69
+ for (const dimension of DIMENSIONS) {
70
+ const capability = platform.capabilities[dimension];
71
+ assert.ok(capability && STATUSES.has(capability.status), `${platform.id}/${dimension}: invalid status`);
72
+ }
73
+ assert.strictEqual(
74
+ platform.capabilities.liveHostVerification.status,
75
+ 'Unknown',
76
+ `${platform.id}: a live status requires a preserved host artifact before publication`
77
+ );
78
+ }
79
+
80
+ const installerTargetSpecs = {
81
+ codex: { platform: 'codex', project: '.agents/skills', global: '~/.agents/skills' },
82
+ 'claude-code': { platform: 'claude', project: '.claude/skills', global: '~/.claude/skills' },
83
+ cursor: { platform: 'cursor', project: '.cursor/skills', global: '~/.agents/skills' },
84
+ 'github-copilot': { platform: 'copilot', project: '.github/skills', global: '~/.agents/skills' },
85
+ continue: { platform: 'continue', project: '.continue/skills', global: '~/.continue/skills' },
86
+ hermes: { platform: 'hermes', project: '.agents/skills', global: '~/.hermes/skills' }
87
+ };
88
+ assert.deepStrictEqual(Object.keys(matrix.installer_targets).sort(), Object.keys(OFFICIAL_HOSTS).sort());
89
+ for (const [id, spec] of Object.entries(installerTargetSpecs)) {
90
+ const targetSpec = matrix.installer_targets[id];
91
+ assert.strictEqual(targetSpec.project, spec.project, `${id}: project installer target drifted`);
92
+ assert.strictEqual(targetSpec.global, spec.global, `${id}: global installer target drifted`);
93
+ assert.ok(STATUSES.has(targetSpec.host_discovery_status), `${id}: installer target status is invalid`);
94
+ }
95
+
96
+ const workspaceRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-2w-workspace-'));
97
+ const userHome = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-2w-home-'));
98
+ try {
99
+ for (const [id, spec] of Object.entries(installerTargetSpecs)) {
100
+ const adapter = platforms.find(platform => platform.name === spec.platform);
101
+ assert.ok(adapter, `${id}: installer adapter missing`);
102
+ const local = adapter.getSkillsTarget({ workspaceRoot, userHome, isGlobal: false, manifest });
103
+ const global = adapter.getSkillsTarget({ workspaceRoot, userHome, isGlobal: true, manifest });
104
+ const expectedLocal = path.join(workspaceRoot, ...spec.project.split('/'));
105
+ const expectedGlobal = path.join(userHome, ...spec.global.replace('~/', '').split('/'));
106
+ assert.strictEqual(path.resolve(local.path), path.resolve(expectedLocal), `${id}: local adapter target drifted`);
107
+ assert.strictEqual(path.resolve(global.path), path.resolve(expectedGlobal), `${id}: global adapter target drifted`);
108
+ }
109
+ } finally {
110
+ fs.rmSync(workspaceRoot, { recursive: true, force: true });
111
+ fs.rmSync(userHome, { recursive: true, force: true });
112
+ }
113
+
114
+ const portableManifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'plugins', 'harness-everything', 'plugin.json'), 'utf8'));
115
+ const compatibilityManifest = JSON.parse(fs.readFileSync(path.join(ROOT, 'plugins', 'harness-everything', '.codex-plugin', 'plugin.json'), 'utf8'));
116
+ assert.strictEqual(portableManifest.$schema, 'https://agent-plugins.org/schemas/1.0.0/plugin.schema.json');
117
+ assert.strictEqual(portableManifest.extensions?.['com.openai']?.hooks, './hooks/hooks.json');
118
+ assert.deepStrictEqual(portableManifest.extensions?.['com.openai']?.interface, compatibilityManifest.interface);
119
+ assert.ok(fs.existsSync(path.join(ROOT, 'plugins', 'harness-everything', 'skills', 'harness-everything', 'SKILL.md')));
120
+
121
+ const marketplace = JSON.parse(fs.readFileSync(path.join(ROOT, '.agents', 'plugins', 'marketplace.json'), 'utf8'));
122
+ const marketplaceEntry = marketplace.plugins.find(plugin => plugin.name === 'harness-everything');
123
+ assert.strictEqual(marketplaceEntry?.source?.path, './plugins/harness-everything');
124
+ assert.ok(fs.existsSync(path.join(ROOT, marketplaceEntry.source.path, '.codex-plugin', 'plugin.json')));
125
+ const claudeMarketplace = JSON.parse(fs.readFileSync(path.join(ROOT, '.claude-plugin', 'marketplace.json'), 'utf8'));
126
+ assert.ok(claudeMarketplace.plugins.some(plugin => plugin.source === './'), 'Claude marketplace must remain a repository-root import path');
127
+
128
+ const tempOutput = path.join(os.tmpdir(), `harness-2w-submission-${process.pid}.zip`);
129
+ try {
130
+ const result = build(tempOutput);
131
+ const publicManifest = JSON.parse(fs.readFileSync(result.manifestPath, 'utf8'));
132
+ const packagedFiles = filesUnder(path.join(ROOT, 'plugins', 'harness-everything', 'skills')).map(file => `skills/${file}`);
133
+ assert.deepStrictEqual(publicManifest.files.map(file => file.path), packagedFiles);
134
+ assert.ok(publicManifest.files.every(file => file.path.startsWith('skills/')));
135
+ assert.ok(publicManifest.files.every(file => !/(^|\/)(hooks|\.codex-plugin)(\/|$)/.test(file.path)));
136
+ assert.strictEqual(publicManifest.bundle_sha256, sha256(tempOutput));
137
+ } finally {
138
+ fs.rmSync(tempOutput, { force: true });
139
+ fs.rmSync(tempOutput.replace(/\.zip$/i, '') + '.manifest.json', { force: true });
140
+ }
141
+
142
+ const capabilityDocs = fs.readFileSync(path.join(ROOT, 'docs', 'platform-capabilities.md'), 'utf8');
143
+ assert.match(capabilityDocs, /platform-compatibility\.json/);
144
+ assert.match(capabilityDocs, /Continue\.dev[\s\S]*`Unknown` for standalone `SKILL\.md` discovery/);
145
+ assert.match(capabilityDocs, /live plugin loading remains unverified/i);
146
+ assert.match(capabilityDocs, /no fresh host-session artifacts/i);
147
+
148
+ console.log('Platform compatibility verified: official-source matrix, installer targets, package manifests, and public bundle boundaries.');
@@ -0,0 +1,157 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+ const { execFileSync } = require('child_process');
8
+ const { VERSION_TARGETS, isStableSemVer, syncReleaseVersion } = require('../scripts/sync-release-version');
9
+
10
+ const ROOT = path.resolve(__dirname, '..');
11
+ const config = JSON.parse(fs.readFileSync(path.join(ROOT, '.releaserc.json'), 'utf8'));
12
+
13
+ assert.deepStrictEqual(config.branches, ['main']);
14
+ assert.ok(config.branches.every(branch => typeof branch === 'string'), 'release branches must not declare prerelease channels');
15
+ assert.strictEqual(config.tagFormat, 'v${version}');
16
+
17
+ const analyzer = config.plugins.find(plugin => Array.isArray(plugin) && plugin[0] === '@semantic-release/commit-analyzer');
18
+ assert.ok(analyzer, 'commit analyzer configuration missing');
19
+ const rules = new Map(analyzer[1].releaseRules.filter(rule => rule.type).map(rule => [rule.type, rule.release]));
20
+ for (const [type, release] of Object.entries({
21
+ feat: 'minor',
22
+ fix: 'patch',
23
+ perf: 'patch',
24
+ refactor: 'patch',
25
+ build: 'patch',
26
+ revert: 'patch'
27
+ })) {
28
+ assert.strictEqual(rules.get(type), release, `${type} release rule`);
29
+ }
30
+ for (const type of ['docs', 'test', 'ci', 'style', 'chore']) {
31
+ assert.ok(!rules.has(type), `${type} must fall through to semantic-release's no-release default`);
32
+ }
33
+ assert.ok(analyzer[1].releaseRules.some(rule => rule.breaking === true && rule.release === 'major'));
34
+
35
+ const execPlugin = config.plugins.find(plugin => Array.isArray(plugin) && plugin[0] === '@semantic-release/exec');
36
+ assert.ok(execPlugin, 'release preparation hook missing');
37
+ assert.match(execPlugin[1].verifyReleaseCmd, /--validate \$\{nextRelease\.version\}/);
38
+ assert.match(execPlugin[1].prepareCmd, /sync-release-version\.js \$\{nextRelease\.version\}/);
39
+ assert.match(execPlugin[1].prepareCmd, /--base \$\{lastRelease\.gitTag\}/, 'changed skills must be computed from the previous release tag');
40
+ assert.match(execPlugin[1].prepareCmd, /--check \$\{nextRelease\.version\} --base \$\{lastRelease\.gitTag\}/);
41
+
42
+ const gitPlugin = config.plugins.find(plugin => Array.isArray(plugin) && plugin[0] === '@semantic-release/git');
43
+ assert.ok(gitPlugin, 'release commit plugin missing');
44
+ assert.match(gitPlugin[1].message, /\[skip ci\]/);
45
+ assert.ok(gitPlugin[1].assets.includes('package-lock.json'));
46
+ assert.ok(gitPlugin[1].assets.includes('opencode-plugin/plugin.json'));
47
+ assert.ok(gitPlugin[1].assets.includes('*/SKILL.md'));
48
+ assert.ok(gitPlugin[1].assets.includes('*/**/SKILL.md'));
49
+
50
+ assert.ok(isStableSemVer('1.2.3'));
51
+ for (const invalid of ['1.2.3-beta', '1.2.3+build', '01.2.3', '1.2', 'v1.2.3', '']) {
52
+ assert.ok(!isStableSemVer(invalid), invalid);
53
+ }
54
+
55
+ // Normal CI gates every checked-in runtime/plugin manifest against package.json.
56
+ // package-lock is intentionally release-owned: the synchronizer fixes its root
57
+ // version when semantic-release prepares the actual release transaction.
58
+ const packageVersion = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8')).version;
59
+ assert.ok(isStableSemVer(packageVersion), `package.json must use stable SemVer, got ${packageVersion}`);
60
+ for (const target of VERSION_TARGETS.filter(target => target.file !== 'package-lock.json')) {
61
+ const data = JSON.parse(fs.readFileSync(path.join(ROOT, target.file), 'utf8'));
62
+ const current = target.get(data);
63
+ const values = Array.isArray(current) ? current : [current];
64
+ assert.ok(values.every(value => value === packageVersion), `${target.file} must match package.json version ${packageVersion}`);
65
+ assert.ok(values.every(isStableSemVer), `${target.file} must not carry a prerelease/build suffix`);
66
+ }
67
+
68
+ function json(file, value) {
69
+ fs.mkdirSync(path.dirname(file), { recursive: true });
70
+ fs.writeFileSync(file, `${JSON.stringify(value, null, 2)}\n`);
71
+ }
72
+
73
+ function skill(file, name, version) {
74
+ fs.mkdirSync(path.dirname(file), { recursive: true });
75
+ fs.writeFileSync(file, `---\nname: ${name}\nmetadata:\n author: Test\n version: ${version}\n---\n\n# ${name}\n`);
76
+ }
77
+
78
+ function versionOfSkill(file) {
79
+ const match = fs.readFileSync(file, 'utf8').match(/^ version:\s*(\S+)$/m);
80
+ return match && match[1];
81
+ }
82
+
83
+ function fixture() {
84
+ const root = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-release-'));
85
+ json(path.join(root, 'package.json'), { name: 'harness-everything', version: '0.3.8-beta' });
86
+ json(path.join(root, 'package-lock.json'), {
87
+ name: 'harness-everything',
88
+ version: '0.3.7-beta',
89
+ packages: { '': { name: 'harness-everything', version: '0.3.7-beta' } }
90
+ });
91
+ json(path.join(root, '.claude-plugin/plugin.json'), { name: 'harness-everything', version: '0.3.8-beta', skills: [] });
92
+ json(path.join(root, '.claude-plugin/marketplace.json'), { plugins: [{ name: 'harness-everything', version: '0.3.8-beta' }] });
93
+ json(path.join(root, 'plugins/harness-everything/plugin.json'), { name: 'harness-everything', version: '0.3.8-beta' });
94
+ json(path.join(root, 'plugins/harness-everything/.codex-plugin/plugin.json'), { name: 'harness-everything', version: '0.3.8-beta' });
95
+ json(path.join(root, 'opencode-plugin/plugin.json'), { name: 'harness-enforcement', version: '0.3.6' });
96
+ return root;
97
+ }
98
+
99
+ const root = fixture();
100
+ const files = syncReleaseVersion(root, '1.2.3');
101
+ assert.strictEqual(files.length, 7);
102
+ syncReleaseVersion(root, '1.2.3', { checkOnly: true });
103
+
104
+ const first = new Map(files.map(file => [file, fs.readFileSync(path.join(root, file), 'utf8')]));
105
+ syncReleaseVersion(root, '1.2.3');
106
+ for (const file of files) {
107
+ assert.strictEqual(fs.readFileSync(path.join(root, file), 'utf8'), first.get(file), `${file} must be idempotent`);
108
+ }
109
+
110
+ const lock = JSON.parse(fs.readFileSync(path.join(root, 'package-lock.json'), 'utf8'));
111
+ assert.strictEqual(lock.version, '1.2.3');
112
+ assert.strictEqual(lock.packages[''].version, '1.2.3');
113
+ const market = JSON.parse(fs.readFileSync(path.join(root, '.claude-plugin/marketplace.json'), 'utf8'));
114
+ assert.strictEqual(market.plugins[0].version, '1.2.3');
115
+
116
+ const portable = path.join(root, 'plugins/harness-everything/plugin.json');
117
+ const tampered = JSON.parse(fs.readFileSync(portable, 'utf8'));
118
+ tampered.version = '1.2.2';
119
+ json(portable, tampered);
120
+ assert.throws(() => syncReleaseVersion(root, '1.2.3', { checkOnly: true }), /Release version drift/);
121
+ assert.throws(() => syncReleaseVersion(root, '1.2.3-beta'), /stable SemVer/);
122
+
123
+ const missing = fixture();
124
+ const packageBefore = fs.readFileSync(path.join(missing, 'package.json'), 'utf8');
125
+ fs.rmSync(path.join(missing, 'opencode-plugin/plugin.json'));
126
+ assert.throws(() => syncReleaseVersion(missing, '2.0.0'), /Missing release version target/);
127
+ assert.strictEqual(fs.readFileSync(path.join(missing, 'package.json'), 'utf8'), packageBefore, 'validation failure must happen before writes');
128
+
129
+ // A release bumps only canonical skills changed since the previous release tag.
130
+ // Nested sub-skills inherit the parent version whenever any file under that
131
+ // top-level skill changed, while untouched skills keep their last-change version.
132
+ const changed = fixture();
133
+ const sourceManifest = JSON.parse(fs.readFileSync(path.join(changed, '.claude-plugin/plugin.json'), 'utf8'));
134
+ sourceManifest.skills = ['./alpha', './beta'];
135
+ json(path.join(changed, '.claude-plugin/plugin.json'), sourceManifest);
136
+ skill(path.join(changed, 'alpha/SKILL.md'), 'alpha', '0.1.0');
137
+ skill(path.join(changed, 'alpha/nested/SKILL.md'), 'nested', '0.1.0');
138
+ skill(path.join(changed, 'beta/SKILL.md'), 'beta', '0.1.0');
139
+ execFileSync('git', ['init'], { cwd: changed, stdio: 'ignore' });
140
+ execFileSync('git', ['config', 'user.email', 'release-test@example.com'], { cwd: changed });
141
+ execFileSync('git', ['config', 'user.name', 'Release Test'], { cwd: changed });
142
+ execFileSync('git', ['add', '.'], { cwd: changed });
143
+ execFileSync('git', ['commit', '-m', 'feat: baseline'], { cwd: changed, stdio: 'ignore' });
144
+ execFileSync('git', ['tag', 'v0.1.0'], { cwd: changed });
145
+ fs.writeFileSync(path.join(changed, 'alpha/behavior.txt'), 'changed\n');
146
+ execFileSync('git', ['add', '.'], { cwd: changed });
147
+ execFileSync('git', ['commit', '-m', 'feat(alpha): change behavior'], { cwd: changed, stdio: 'ignore' });
148
+ const changedFiles = syncReleaseVersion(changed, '0.2.0', { base: 'v0.1.0' });
149
+ assert.ok(changedFiles.includes('alpha/SKILL.md'));
150
+ assert.ok(changedFiles.includes('alpha/nested/SKILL.md'));
151
+ assert.ok(!changedFiles.includes('beta/SKILL.md'));
152
+ assert.strictEqual(versionOfSkill(path.join(changed, 'alpha/SKILL.md')), '0.2.0');
153
+ assert.strictEqual(versionOfSkill(path.join(changed, 'alpha/nested/SKILL.md')), '0.2.0');
154
+ assert.strictEqual(versionOfSkill(path.join(changed, 'beta/SKILL.md')), '0.1.0');
155
+ syncReleaseVersion(changed, '0.2.0', { base: 'v0.1.0', checkOnly: true });
156
+
157
+ console.log('Release automation contract verified: stable SemVer rules, changed-skill versioning, manifest sync, drift detection, idempotency, and fail-before-write behavior.');
@@ -0,0 +1,66 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const fs = require('fs');
5
+ const os = require('os');
6
+ const path = require('path');
7
+ const { spawnSync } = require('child_process');
8
+
9
+ const ROOT = path.resolve(__dirname, '..');
10
+ const config = JSON.parse(fs.readFileSync(path.join(ROOT, '.releaserc.json'), 'utf8'));
11
+ const gitPlugin = config.plugins.find(plugin => Array.isArray(plugin) && plugin[0] === '@semantic-release/git');
12
+
13
+ assert.ok(gitPlugin, 'release commit plugin missing');
14
+ const template = gitPlugin[1].message;
15
+ assert.match(template, /\$\{nextRelease\.version\}/, 'release commit must include the calculated version');
16
+ assert.match(template, /\[skip ci\]/, 'release commit must not recursively trigger CI');
17
+ assert.ok(!template.includes('${nextRelease.notes}'), 'release notes must not be copied into the release commit message');
18
+
19
+ const currentMessage = template.replace('${nextRelease.version}', '0.4.0');
20
+ const currentLines = currentMessage.split(/\r?\n/);
21
+ assert.strictEqual(currentLines.length, 1, 'release commit must remain a single-line control message');
22
+ assert.ok(currentLines.every(line => line.length <= 100), 'release commit must remain within commitlint line limits');
23
+
24
+ const temp = fs.mkdtempSync(path.join(os.tmpdir(), 'harness-release-commitlint-'));
25
+ const currentFile = path.join(temp, 'current-message.txt');
26
+ const legacyFile = path.join(temp, 'legacy-message.txt');
27
+ fs.writeFileSync(currentFile, `${currentMessage}\n`);
28
+
29
+ // Negative control: this reproduces the production failure from release run
30
+ // 34970424994. Generated notes contain long Markdown links, so copying them
31
+ // into the Git commit body violates body-max-line-length/footer constraints.
32
+ const longReleaseNote = `* **behavioral-evals:** ${'x'.repeat(110)} ([90e36c2](https://github.com/dyphn1/Harness-everything/commit/90e36c2071fb5a71e16cdc99b1060cd3d699c43b)), closes #52`;
33
+ const legacyMessage = `chore(release): 0.4.0 [skip ci]\n\n${longReleaseNote}\n`;
34
+ fs.writeFileSync(legacyFile, legacyMessage);
35
+
36
+ const commitlintPackageFile = require.resolve('@commitlint/cli/package.json');
37
+ const commitlintPackage = JSON.parse(fs.readFileSync(commitlintPackageFile, 'utf8'));
38
+ const commitlintBin = typeof commitlintPackage.bin === 'string'
39
+ ? commitlintPackage.bin
40
+ : commitlintPackage.bin && commitlintPackage.bin.commitlint;
41
+ assert.ok(commitlintBin, '@commitlint/cli must expose a commitlint executable');
42
+ const commitlintCli = path.resolve(path.dirname(commitlintPackageFile), commitlintBin);
43
+
44
+ function commitlint(file) {
45
+ return spawnSync(process.execPath, [commitlintCli, '--edit', file], {
46
+ cwd: ROOT,
47
+ encoding: 'utf8'
48
+ });
49
+ }
50
+
51
+ const currentResult = commitlint(currentFile);
52
+ assert.strictEqual(
53
+ currentResult.status,
54
+ 0,
55
+ `current semantic-release commit must pass commitlint:\n${currentResult.stdout}\n${currentResult.stderr}`
56
+ );
57
+
58
+ const legacyResult = commitlint(legacyFile);
59
+ assert.notStrictEqual(legacyResult.status, 0, 'legacy release-notes-in-commit behavior must fail commitlint');
60
+ assert.match(
61
+ `${legacyResult.stdout}\n${legacyResult.stderr}`,
62
+ /body-max-line-length|footer-max-line-length/,
63
+ 'negative control must fail for the same long-line class seen in production'
64
+ );
65
+
66
+ console.log('Release commit contract verified: compact message passes commitlint and legacy release-note embedding is rejected.');
@@ -0,0 +1,47 @@
1
+ 'use strict';
2
+
3
+ const assert = require('assert');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const ROOT = path.resolve(__dirname, '..');
8
+ const workflow = fs.readFileSync(path.join(ROOT, '.github/workflows/release.yml'), 'utf8');
9
+
10
+ function pinnedVersion(packageName, source = workflow) {
11
+ const escaped = packageName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
12
+ const match = source.match(new RegExp(`${escaped}@(\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?)`));
13
+ assert.ok(match, `release workflow must pin ${packageName}`);
14
+ return match[1];
15
+ }
16
+
17
+ function major(version) {
18
+ return Number(version.split('.')[0]);
19
+ }
20
+
21
+ function assertCompatible(generatorVersion, presetVersion) {
22
+ if (major(generatorVersion) === 14 && major(presetVersion) >= 10) {
23
+ throw new Error(
24
+ `incompatible release-note tooling: @semantic-release/release-notes-generator@${generatorVersion} ` +
25
+ `uses conventional-changelog-writer 8, but conventional-changelog-conventionalcommits@${presetVersion} requires writer 9+`
26
+ );
27
+ }
28
+ }
29
+
30
+ const generatorVersion = pinnedVersion('@semantic-release/release-notes-generator');
31
+ const presetVersion = pinnedVersion('conventional-changelog-conventionalcommits');
32
+
33
+ assert.strictEqual(generatorVersion, '14.1.1', 'stable release-notes-generator pin changed; re-evaluate writer compatibility');
34
+ assert.strictEqual(presetVersion, '9.3.1', 'preset must stay on the writer-8-compatible line while generator 14 is used');
35
+ assert.doesNotThrow(() => assertCompatible(generatorVersion, presetVersion));
36
+ assert.throws(
37
+ () => assertCompatible('14.1.1', '10.4.0'),
38
+ /incompatible release-note tooling/,
39
+ 'negative control must reject the exact #113 failure pairing'
40
+ );
41
+ assert.doesNotMatch(
42
+ workflow,
43
+ /(?:^|\s)conventional-changelog-writer@\d/m,
44
+ 'do not force writer 9 into release-notes-generator 14; upgrade the generator as one compatible stack instead'
45
+ );
46
+
47
+ console.log('Release tooling compatibility verified: generator 14 is paired with conventionalcommits 9.x, and the v10 regression is rejected.');
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env node
2
+
3
+ const assert = require('assert');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const projectRoot = path.resolve(__dirname, '..');
8
+ const manifestPath = path.join(projectRoot, '.claude-plugin', 'plugin.json');
9
+ const conventionalHooksPath = path.join(projectRoot, 'hooks', 'hooks.json');
10
+
11
+ assert.ok(fs.existsSync(manifestPath), '.claude-plugin/plugin.json must exist');
12
+ assert.ok(fs.existsSync(conventionalHooksPath), 'hooks/hooks.json must remain available for convention-based discovery');
13
+
14
+ const manifest = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
15
+ const hooks = manifest.hooks;
16
+
17
+ if (hooks !== undefined) {
18
+ const refs = Array.isArray(hooks) ? hooks : [hooks];
19
+ const normalized = refs
20
+ .filter(ref => typeof ref === 'string')
21
+ .map(ref => ref.replace(/\\/g, '/').replace(/^\.\//, ''));
22
+
23
+ assert.ok(
24
+ !normalized.includes('hooks/hooks.json'),
25
+ 'Do not explicitly register hooks/hooks.json in .claude-plugin/plugin.json; Claude Code auto-discovers the conventional hook file and duplicate registration prevents the plugin from loading.'
26
+ );
27
+ }
28
+
29
+ console.log('PASS: Claude plugin manifest does not duplicate the conventional hooks/hooks.json registration.');