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
@@ -4,7 +4,7 @@ description: Generate or update precise, reader-oriented README.md and AGENTS.md
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: Miya Daniel
7
- version: 0.3.4
7
+ version: 0.4.0
8
8
  ---
9
9
 
10
10
  # Repo Docs (Automated Project Documentation Generation & Smart Merging)
@@ -37,10 +37,6 @@ Merges codebase scan facts and bespoke notes into `README.md`/`AGENTS.md`.
37
37
  3. Pick a template below; else built-in structure.
38
38
  4. Draft: `README.md` = user journey; `AGENTS.md` = conventions, build/test commands.
39
39
  5. [Summarize] Verify commands run; mark doubts `// TODO: Pending confirmation`; ask (`grill-me`).
40
- 6. Write to root; if protected, `.github/AGENTS.md`/`docs/README.md`.
40
+ 6. Write to root; if protected, `<workspace>/.github/AGENTS.md`/`<workspace>/docs/README.md`.
41
41
 
42
- ## `repo-docs/templates/`
43
-
44
- readme-template.md · product-readme-template.md · multi-skills-readme-template.md · single-skill-readme-template.md · knowledge-readme-template.md · agents-template.md · product-agents-template.md · skills-agents-template.md · knowledge-agents-template.md · manual-recon.md
45
-
46
- Deep dive: references/process-guide.md
42
+ Deep dive: <this-skill-dir>/references/process-guide.md
@@ -4,7 +4,7 @@ description: "Rewrite past Git history to comply with Angular Style conventions.
4
4
  license: Apache-2.0
5
5
  metadata:
6
6
  author: Miya Daniel
7
- version: 0.3.4
7
+ version: 0.4.0
8
8
  ---
9
9
 
10
10
  # Rewrite Commits
@@ -34,4 +34,4 @@ metadata:
34
34
  2. `[Think] & [Try]` Create a temp branch. Never run bare interactive `git rebase -i`; prefer `git reset --soft HEAD~<N>` plus structured commits, or Node.js scripting (no hardcoded `sed -i`). Messages MUST follow Angular Style per the `git-commit` skill.
35
35
  3. `[Summarize]` Run `git log --oneline` for confirmation. On merge conflict, run `git rebase --abort`, STOP, and hand over to human decision or trigger `zoom-out`.
36
36
 
37
- Deep dive: references/workflow.md
37
+ Deep dive: <this-skill-dir>/references/workflow.md
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/env node
2
+ 'use strict';
3
+
4
+ const crypto = require('crypto');
5
+ const fs = require('fs');
6
+ const path = require('path');
7
+
8
+ const ROOT = path.resolve(__dirname, '..');
9
+ const SKILLS_ROOT = path.join(ROOT, 'plugins', 'harness-everything', 'skills');
10
+ const DEFAULT_OUTPUT = path.join(ROOT, 'dist', 'openai-submission', 'harness-everything-skills.zip');
11
+
12
+ function parseArgs(argv) {
13
+ let output = DEFAULT_OUTPUT;
14
+ for (let i = 0; i < argv.length; i += 1) {
15
+ if (argv[i] === '--output') {
16
+ if (!argv[i + 1]) throw new Error('--output requires a path');
17
+ output = path.resolve(argv[++i]);
18
+ } else {
19
+ throw new Error(`unknown argument: ${argv[i]}`);
20
+ }
21
+ }
22
+ return { output };
23
+ }
24
+
25
+ function filesUnder(root, base = root, out = []) {
26
+ for (const entry of fs.readdirSync(root, { withFileTypes: true })) {
27
+ const full = path.join(root, entry.name);
28
+ if (entry.isDirectory()) filesUnder(full, base, out);
29
+ else if (entry.isFile()) out.push(path.relative(base, full).replace(/\\/g, '/'));
30
+ }
31
+ return out.sort();
32
+ }
33
+
34
+ const CRC_TABLE = (() => {
35
+ const table = new Uint32Array(256);
36
+ for (let n = 0; n < 256; n += 1) {
37
+ let c = n;
38
+ for (let k = 0; k < 8; k += 1) c = (c & 1) ? (0xedb88320 ^ (c >>> 1)) : (c >>> 1);
39
+ table[n] = c >>> 0;
40
+ }
41
+ return table;
42
+ })();
43
+
44
+ function crc32(buffer) {
45
+ let c = 0xffffffff;
46
+ for (const byte of buffer) c = CRC_TABLE[(c ^ byte) & 0xff] ^ (c >>> 8);
47
+ return (c ^ 0xffffffff) >>> 0;
48
+ }
49
+
50
+ function zipStored(entries) {
51
+ const localParts = [];
52
+ const centralParts = [];
53
+ let offset = 0;
54
+
55
+ for (const entry of entries) {
56
+ const name = Buffer.from(entry.name, 'utf8');
57
+ const data = entry.data;
58
+ const crc = crc32(data);
59
+ const local = Buffer.alloc(30);
60
+ local.writeUInt32LE(0x04034b50, 0);
61
+ local.writeUInt16LE(20, 4);
62
+ local.writeUInt16LE(0x0800, 6);
63
+ local.writeUInt16LE(0, 8);
64
+ local.writeUInt16LE(0, 10);
65
+ local.writeUInt16LE(33, 12); // 1980-01-01, 00:00:00
66
+ local.writeUInt32LE(crc, 14);
67
+ local.writeUInt32LE(data.length, 18);
68
+ local.writeUInt32LE(data.length, 22);
69
+ local.writeUInt16LE(name.length, 26);
70
+ local.writeUInt16LE(0, 28);
71
+
72
+ const central = Buffer.alloc(46);
73
+ central.writeUInt32LE(0x02014b50, 0);
74
+ central.writeUInt16LE(0x0314, 4); // ZIP 2.0, Unix creator
75
+ central.writeUInt16LE(20, 6);
76
+ central.writeUInt16LE(0x0800, 8);
77
+ central.writeUInt16LE(0, 10);
78
+ central.writeUInt16LE(0, 12);
79
+ central.writeUInt16LE(33, 14);
80
+ central.writeUInt32LE(crc, 16);
81
+ central.writeUInt32LE(data.length, 20);
82
+ central.writeUInt32LE(data.length, 24);
83
+ central.writeUInt16LE(name.length, 28);
84
+ central.writeUInt16LE(0, 30);
85
+ central.writeUInt16LE(0, 32);
86
+ central.writeUInt16LE(0, 34);
87
+ central.writeUInt16LE(0, 36);
88
+ const mode = entry.name.endsWith('.sh') ? 0o100755 : 0o100644;
89
+ central.writeUInt32LE((mode << 16) >>> 0, 38);
90
+ central.writeUInt32LE(offset, 42);
91
+
92
+ localParts.push(local, name, data);
93
+ centralParts.push(central, name);
94
+ offset += local.length + name.length + data.length;
95
+ }
96
+
97
+ const centralDirectory = Buffer.concat(centralParts);
98
+ const end = Buffer.alloc(22);
99
+ end.writeUInt32LE(0x06054b50, 0);
100
+ end.writeUInt16LE(0, 4);
101
+ end.writeUInt16LE(0, 6);
102
+ end.writeUInt16LE(entries.length, 8);
103
+ end.writeUInt16LE(entries.length, 10);
104
+ end.writeUInt32LE(centralDirectory.length, 12);
105
+ end.writeUInt32LE(offset, 16);
106
+ end.writeUInt16LE(0, 20);
107
+
108
+ return Buffer.concat([...localParts, centralDirectory, end]);
109
+ }
110
+
111
+ function sha256(buffer) {
112
+ return crypto.createHash('sha256').update(buffer).digest('hex');
113
+ }
114
+
115
+ function build(output) {
116
+ if (!fs.existsSync(SKILLS_ROOT)) throw new Error(`packaged skills not found: ${SKILLS_ROOT}`);
117
+ const relativeFiles = filesUnder(SKILLS_ROOT);
118
+ if (relativeFiles.length === 0) throw new Error('no packaged skill files found');
119
+
120
+ const entries = relativeFiles.map(relative => {
121
+ const data = fs.readFileSync(path.join(SKILLS_ROOT, relative));
122
+ return { name: `skills/${relative}`, data };
123
+ });
124
+ const zip = zipStored(entries);
125
+ fs.mkdirSync(path.dirname(output), { recursive: true });
126
+ fs.writeFileSync(output, zip);
127
+
128
+ const manifest = {
129
+ format: 'harness-openai-skill-bundle-manifest-v1',
130
+ source: 'plugins/harness-everything/skills',
131
+ file_count: entries.length,
132
+ bundle_sha256: sha256(zip),
133
+ files: entries.map(entry => ({
134
+ path: entry.name,
135
+ bytes: entry.data.length,
136
+ sha256: sha256(entry.data)
137
+ }))
138
+ };
139
+ const manifestPath = output.replace(/\.zip$/i, '') + '.manifest.json';
140
+ fs.writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
141
+ console.log(`OpenAI skill bundle: ${output}`);
142
+ console.log(`Files: ${manifest.file_count}`);
143
+ console.log(`SHA256: ${manifest.bundle_sha256}`);
144
+ console.log(`Manifest: ${manifestPath}`);
145
+ return { output, manifestPath, manifest };
146
+ }
147
+
148
+ if (require.main === module) {
149
+ try {
150
+ const { output } = parseArgs(process.argv.slice(2));
151
+ build(output);
152
+ } catch (error) {
153
+ console.error(error.message);
154
+ process.exit(1);
155
+ }
156
+ }
157
+
158
+ module.exports = { build, crc32, filesUnder, zipStored };
@@ -26,7 +26,7 @@
26
26
  const fs = require('fs');
27
27
  const path = require('path');
28
28
 
29
- const { getWorkspaceRoot, getUserPromptsDir } = require('./lib/workspace');
29
+ const { getWorkspaceRoot, getWorkspaceStateDir, getUserPromptsDir } = require('./lib/workspace');
30
30
  const { interactiveSelect, interactiveSingleSelect, askQuestion } = require('./lib/prompts');
31
31
  const advisory = require('./lib/advisory-text');
32
32
  const claudeHooks = require('./lib/claude-hooks');
@@ -35,7 +35,12 @@ const skills = require('./lib/skills');
35
35
  const { ensureWorkspaceGitignorePatterns, removeWorkspaceExcludePatterns, cleanEmptyDirs } = require('./lib/gitignore');
36
36
 
37
37
  const userHome = require('os').homedir();
38
- const workspaceRoot = getWorkspaceRoot();
38
+ const detectedWorkspaceRoot = getWorkspaceRoot();
39
+ // Global installs are valid outside a repository, but the module still needs
40
+ // a non-null path while it evaluates local-detection helpers. Keep this
41
+ // fallback private to global mode; main() rejects non-global work from a
42
+ // directory whose workspace identity cannot be resolved.
43
+ const workspaceRoot = detectedWorkspaceRoot || path.resolve(process.cwd());
39
44
  const harnessSourceDir = path.resolve(__dirname, '..');
40
45
  const packageVersion = require(path.join(harnessSourceDir, 'package.json')).version;
41
46
 
@@ -65,7 +70,16 @@ async function main() {
65
70
  // workspace - skill installation is an explicit user choice, never a
66
71
  // side effect of a background repair.
67
72
  const hasNoSkillsFlag = args.includes('--no-skills');
73
+ if (!detectedWorkspaceRoot && !hasGlobalFlag) {
74
+ throw new Error('cannot install locally outside a git workspace; pass --global for a user-wide install');
75
+ }
68
76
  const hasAnyPlatformFlag = hasClaudeFlag || hasCursorFlag || hasCopilotFlag || hasCodexFlag || hasContinueFlag || hasHermesFlag || hasAllFlag;
77
+ // #49: default 'auto' tries a junction (Windows) / symlink (elsewhere) into
78
+ // one canonical per-scope copy and silently falls back to an independent
79
+ // physical copy per target if that fails. --copy/--symlink override the
80
+ // auto-detection explicitly - --symlink surfaces a link failure as an
81
+ // error instead of silently falling back, since the user asked for it.
82
+ const linkMode = args.includes('--copy') ? 'copy' : args.includes('--symlink') ? 'symlink' : 'auto';
69
83
 
70
84
  let requestedSkills = ['add', 'skill', 'skills'].includes(command)
71
85
  ? args.slice(3).filter(arg => !arg.startsWith('-'))
@@ -263,7 +277,8 @@ async function main() {
263
277
  }
264
278
 
265
279
  console.log(`\nInstalling Harness skills:`);
266
- skills.installSkillsToTargets({ chosenSkills, targetDirs, harnessSourceDir, packageVersion });
280
+ const canonicalDir = skills.getCanonicalSkillsDir({ isGlobal, workspaceRoot, userHome });
281
+ skills.installSkillsToTargets({ chosenSkills, targetDirs, harnessSourceDir, packageVersion, canonicalDir, linkMode });
267
282
 
268
283
  // Claude Code discovers named agents from .claude/agents/, not from a
269
284
  // nested skill directory. Keep the source copies in fable-mode for plugin
@@ -297,6 +312,16 @@ async function main() {
297
312
  if (targets.continue) patternsToIgnore.push('.continue/harness-everything/', '.continue/skills/');
298
313
  }
299
314
 
315
+ // The local canonical skills store (#49) is new territory - .agents/
316
+ // wasn't previously a Harness-owned local directory - so it needs its
317
+ // own ignore pattern rather than relying on any platform's own list.
318
+ if (chosenSkills.length > 0 && linkMode !== 'copy') {
319
+ const canonicalDir = skills.getCanonicalSkillsDir({ isGlobal: false, workspaceRoot, userHome });
320
+ if (fs.existsSync(canonicalDir)) {
321
+ patternsToIgnore.push('.agents/skills/');
322
+ }
323
+ }
324
+
300
325
  ensureWorkspaceGitignorePatterns(workspaceRoot, patternsToIgnore);
301
326
  }
302
327
 
@@ -339,7 +364,29 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
339
364
  let removeGlobal = false;
340
365
  let removeSkills = false;
341
366
 
342
- const runInteractively = isInteractive && !hasYesFlag;
367
+ const hasLocalFlag = args.includes('--local');
368
+ const hasGlobalUninstallFlag = args.includes('--global') || args.includes('-g');
369
+ const hasSkillsUninstallFlag = args.includes('--skills');
370
+ // #48: any explicit scope flag wins over the interactive menu, even with a
371
+ // TTY attached - so `uninstall --local --global --skills` actually does
372
+ // what it says instead of being silently swapped for the checkbox menu
373
+ // (where only -y previously had that effect). Only a truly bare `uninstall`
374
+ // (no flags at all) still goes interactive when a TTY is available.
375
+ const hasAnyScopeFlag = hasYesFlag || hasLocalFlag || hasGlobalUninstallFlag || hasSkillsUninstallFlag;
376
+ const runInteractively = isInteractive && !hasAnyScopeFlag;
377
+
378
+ if (!runInteractively && !hasAnyScopeFlag) {
379
+ // #48: no flags AND no interactive terminal to fall back on - this used
380
+ // to silently do nothing while still printing "UNINSTALL COMPLETE!".
381
+ // Fail loudly instead so a non-TTY invocation (npx in some shells/CI/
382
+ // piped input) never looks like a successful no-op.
383
+ console.error("\n❌ No scope specified and no interactive terminal detected.");
384
+ console.error(" Pass flags to say what to remove, e.g.:");
385
+ console.error(" uninstall --local --skills");
386
+ console.error(" uninstall --local --global --skills -y");
387
+ console.error(" ...or run this command in an interactive terminal to use the menu.");
388
+ process.exit(1);
389
+ }
343
390
 
344
391
  if (runInteractively) {
345
392
  const choices = [];
@@ -385,7 +432,7 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
385
432
  const chosenSkillsToRemove = await interactiveSelect(selectSkillItems);
386
433
  for (const item of chosenSkillsToRemove) {
387
434
  if (item.checked) {
388
- skills.removeSkill(item._entry);
435
+ skills.removeSkill(item._entry, { workspaceRoot, userHome });
389
436
  console.log(` ✅ Removed skill: ${item.name}`);
390
437
  cleanEmptyDirs(item._entry.parentPath, [workspaceRoot, userHome]);
391
438
  }
@@ -393,10 +440,6 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
393
440
  }
394
441
  }
395
442
  } else {
396
- const hasLocalFlag = args.includes('--local');
397
- const hasGlobalUninstallFlag = args.includes('--global') || args.includes('-g');
398
- const hasSkillsUninstallFlag = args.includes('--skills');
399
-
400
443
  if (hasYesFlag) {
401
444
  // -y auto-confirms local (cwd-scoped, obviously "this project") but
402
445
  // must NEVER auto-confirm global (~/.agents, ~/.claude, etc.) just
@@ -432,6 +475,11 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
432
475
  }
433
476
 
434
477
  if (typeof platform.getStateDir === 'function') {
478
+ // Legacy per-workspace state dir (pre-#42) - almost always already
479
+ // gone by the time uninstall runs, since the first hook invocation
480
+ // after the fix migrates it into the global home below. Kept as a
481
+ // no-op-in-the-common-case safety net for a workspace that was
482
+ // never actually used since upgrading.
435
483
  const stateDir = platform.getStateDir(workspaceRoot);
436
484
  if (fs.existsSync(stateDir)) {
437
485
  fs.rmSync(stateDir, { recursive: true, force: true });
@@ -440,6 +488,16 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
440
488
  }
441
489
  }
442
490
 
491
+ // Runtime state for this workspace now lives outside it entirely, under
492
+ // ~/.agents/harness-everything/workspaces/<key>/ (issue #42) - remove
493
+ // this workspace's slice of it too, so uninstalling doesn't leave an
494
+ // orphaned global state dir behind.
495
+ const globalWorkspaceStateDir = getWorkspaceStateDir(workspaceRoot);
496
+ if (fs.existsSync(globalWorkspaceStateDir)) {
497
+ fs.rmSync(globalWorkspaceStateDir, { recursive: true, force: true });
498
+ console.log(` ✅ Removed global runtime state for this workspace (${globalWorkspaceStateDir})`);
499
+ }
500
+
443
501
  // One-time migration cleanup: earlier versions used a self-invented
444
502
  // top-level .harness/ directory for Claude's manifest + skill copies.
445
503
  const legacyHarnessDir = path.join(workspaceRoot, '.harness');
@@ -513,8 +571,11 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
513
571
  console.log("Uninstalling all detected skills...");
514
572
  console.log("-------------------------------------------------");
515
573
  for (const skill of skillsToRemove) {
516
- if (fs.existsSync(skill.dirPath)) {
517
- skills.removeSkill(skill);
574
+ // pathPresent (not bare existsSync) so a dangling link - its canonical
575
+ // target already gone - still gets its manifest row cleaned up instead
576
+ // of being silently skipped forever.
577
+ if (skills.pathPresent(skill.dirPath)) {
578
+ skills.removeSkill(skill, { workspaceRoot, userHome });
518
579
  console.log(` ✅ Removed skill: ${skill.id} (${skill.scope})`);
519
580
  cleanEmptyDirs(skill.parentPath, [workspaceRoot, userHome]);
520
581
  }
@@ -536,6 +597,20 @@ async function runUninstall({ hasYesFlag, args, isInteractive }) {
536
597
  }
537
598
  cleanEmptyDirs(path.join(workspaceRoot, '.claude'), [workspaceRoot, userHome]);
538
599
 
600
+ // Canonical skills store (#49) - removeSkill() above already deletes each
601
+ // now-unreferenced canonical copy as its last link goes; this just tidies
602
+ // up the now-empty .agents/skills/ (and .agents/ itself, if nothing else
603
+ // put anything there). Runs here rather than inside the removeLocal/
604
+ // removeGlobal blocks above because skill removal itself happens later,
605
+ // in the removeSkills block below those - running any earlier would find
606
+ // the directory still populated.
607
+ if (removeLocal) {
608
+ cleanEmptyDirs(skills.getCanonicalSkillsDir({ isGlobal: false, workspaceRoot, userHome }), [workspaceRoot, userHome]);
609
+ }
610
+ if (removeGlobal) {
611
+ cleanEmptyDirs(skills.getCanonicalSkillsDir({ isGlobal: true, workspaceRoot, userHome }), [userHome]);
612
+ }
613
+
539
614
  console.log("\n🎉 UNINSTALL COMPLETE! Harness OS has been removed.");
540
615
  console.log("=================================================");
541
616
  }
@@ -1,7 +1,6 @@
1
1
  // Prompt-injection-only guidance for platforms with no hook/execution
2
2
  // mechanism (Cursor, Copilot, Codex, Continue, Hermes). Single source of
3
- // truth for the advisory block - it used to be duplicated verbatim inside
4
- // installer.js's top level and again inside main().
3
+ // truth for the advisory block.
5
4
  const fs = require('fs');
6
5
  const path = require('path');
7
6
 
@@ -37,13 +36,25 @@ const advisoryInstructions = [
37
36
  ``
38
37
  ].join('\n');
39
38
 
39
+ function hasHarnessMarker(content) {
40
+ return typeof content === 'string' && content.includes(MARKER);
41
+ }
42
+
43
+ function assertHarnessOwnedOrAbsent(targetFile, label) {
44
+ if (!fs.existsSync(targetFile)) return;
45
+ const content = fs.readFileSync(targetFile, 'utf8');
46
+ if (!hasHarnessMarker(content)) {
47
+ throw new Error(`Refusing to overwrite pre-existing non-Harness ${label}: ${targetFile}`);
48
+ }
49
+ }
50
+
40
51
  function injectAdvisoryText(targetFile, header, label) {
41
52
  const dir = path.dirname(targetFile);
42
53
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
43
54
 
44
55
  if (fs.existsSync(targetFile)) {
45
56
  const content = fs.readFileSync(targetFile, 'utf8');
46
- if (!content.includes(MARKER)) {
57
+ if (!hasHarnessMarker(content)) {
47
58
  fs.appendFileSync(targetFile, advisoryInstructions, 'utf8');
48
59
  console.log(` ✅ Augmented existing ${label} with Harness guidance (advisory-only)`);
49
60
  }
@@ -61,11 +72,8 @@ function removeAdvisoryText(targetFile) {
61
72
  if (markerIndex !== -1) {
62
73
  let cleanContent = content;
63
74
  const hashMarkerIndex = content.lastIndexOf('#', markerIndex);
64
- if (hashMarkerIndex !== -1) {
65
- cleanContent = content.substring(0, hashMarkerIndex).trim() + '\n';
66
- } else {
67
- cleanContent = content.substring(0, markerIndex).trim() + '\n';
68
- }
75
+ if (hashMarkerIndex !== -1) cleanContent = content.substring(0, hashMarkerIndex).trim() + '\n';
76
+ else cleanContent = content.substring(0, markerIndex).trim() + '\n';
69
77
 
70
78
  const lines = cleanContent.trim().split('\n').map(l => l.trim()).filter(l => l !== '');
71
79
  if (lines.length === 0 || (lines.length === 1 && (lines[0] === '# Cursor Project Rules' || lines[0] === '# AGENTS.md' || lines[0] === '# Copilot Instructions' || lines[0] === '# .hermes.md'))) {
@@ -81,17 +89,13 @@ function removeAdvisoryText(targetFile) {
81
89
  }
82
90
  }
83
91
 
84
- // Continue.dev reads project rules as individual Markdown files (with YAML
85
- // frontmatter) from a `.continue/rules/` folder rather than one shared file,
86
- // so - unlike the shared-file platforms above - Harness gets its own
87
- // dedicated `harness.md` rule file instead of appending into an arbitrary
88
- // pre-existing one.
92
+ // Continue gets a dedicated rule file. If a user already owns that exact
93
+ // path, do not replace it just because Harness chose the same filename.
89
94
  function installContinueRule(targetFile, label) {
90
95
  const dir = path.dirname(targetFile);
91
96
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
92
- if (fs.existsSync(targetFile) && fs.readFileSync(targetFile, 'utf8').includes(MARKER)) {
93
- return;
94
- }
97
+ assertHarnessOwnedOrAbsent(targetFile, label);
98
+ if (fs.existsSync(targetFile) && hasHarnessMarker(fs.readFileSync(targetFile, 'utf8'))) return;
95
99
  const content = [
96
100
  `---`,
97
101
  `name: Harness OS Guidance`,
@@ -108,7 +112,7 @@ function removeContinueRule(targetFile) {
108
112
  if (!fs.existsSync(targetFile)) return;
109
113
  try {
110
114
  const content = fs.readFileSync(targetFile, 'utf8');
111
- if (content.includes(MARKER)) {
115
+ if (hasHarnessMarker(content)) {
112
116
  fs.unlinkSync(targetFile);
113
117
  console.log(` ✅ Removed Harness rule file: ${targetFile}`);
114
118
  }
@@ -138,6 +142,7 @@ function buildCodexGlobalContent() {
138
142
  `---`,
139
143
  `# AGENTS.md`,
140
144
  ``,
145
+ `# ${MARKER}`,
141
146
  `This file is advisory only - this platform has no hook/execution mechanism to`,
142
147
  `enforce it mechanically (unlike Claude Code's hook-based circuit breaker). Treat`,
143
148
  `these as strong defaults, not guarantees.`,
@@ -158,10 +163,12 @@ function buildCodexGlobalContent() {
158
163
  module.exports = {
159
164
  MARKER,
160
165
  advisoryInstructions,
166
+ hasHarnessMarker,
167
+ assertHarnessOwnedOrAbsent,
161
168
  injectAdvisoryText,
162
169
  removeAdvisoryText,
163
170
  installContinueRule,
164
171
  removeContinueRule,
165
172
  buildCopilotGlobalContent,
166
173
  buildCodexGlobalContent,
167
- };
174
+ };
@@ -0,0 +1,70 @@
1
+ const path = require('path');
2
+
3
+ function normalizeCommand(command) {
4
+ if (Array.isArray(command)) {
5
+ return command.map((part) => String(part));
6
+ }
7
+ if (typeof command !== 'string') return null;
8
+ return command.trim().replace(/\s+/g, ' ');
9
+ }
10
+
11
+ function commandsEqual(actual, expected) {
12
+ const left = normalizeCommand(actual);
13
+ const right = normalizeCommand(expected);
14
+ if (Array.isArray(left) || Array.isArray(right)) {
15
+ return Array.isArray(left) && Array.isArray(right) &&
16
+ left.length === right.length && left.every((part, index) => part === right[index]);
17
+ }
18
+ return left !== null && left === right;
19
+ }
20
+
21
+ function commandTokens(command) {
22
+ if (typeof command !== 'string') return [];
23
+ return command.match(/"[^"]*"|'[^']*'|\S+/g) || [];
24
+ }
25
+
26
+ function commandMatches(actual, expected) {
27
+ if (commandsEqual(actual, expected)) return true;
28
+ if (typeof actual !== 'string' || typeof expected !== 'string') return false;
29
+ const target = expected.trim();
30
+ if (!target || /\s/.test(target) || !/\.(?:c?js|mjs|py|sh|ps1|bat|cmd)$/i.test(target)) return false;
31
+ const expectedName = path.basename(target.replace(/\\/g, '/')).toLowerCase();
32
+ const tokens = commandTokens(actual).map((token) => token.replace(/^['"]|['"]$/g, ''));
33
+ if (tokens.length < 2) return false;
34
+ const launcher = path.basename(tokens[0].replace(/\\/g, '/')).toLowerCase();
35
+ if (!new Set(['node', 'node.exe', 'bun', 'bun.exe', 'deno', 'deno.exe', 'python', 'python.exe', 'python3', 'python3.exe', 'ruby', 'ruby.exe']).has(launcher)) return false;
36
+ return tokens.slice(1).some((token) => path.basename(token.replace(/\\/g, '/')).toLowerCase() === expectedName);
37
+ }
38
+
39
+ function normalizeRepoPath(value) {
40
+ if (typeof value !== 'string') return null;
41
+ const normalized = value.replace(/\\/g, '/').replace(/^\.\//, '');
42
+ const segments = normalized.split('/');
43
+ if (!normalized || normalized === '.' || path.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized) || segments.includes('..')) return null;
44
+ return normalized;
45
+ }
46
+
47
+ function extractPatchPaths(patchText) {
48
+ if (typeof patchText !== 'string') return [];
49
+ const paths = [];
50
+ const marker = /^\*\*\* (?:Update File|Add File|Delete File|Move to):\s*(.+?)\s*$/gm;
51
+ for (const match of patchText.matchAll(marker)) {
52
+ if (!paths.includes(match[1])) paths.push(match[1]);
53
+ }
54
+ return paths;
55
+ }
56
+
57
+ function patchPathsAuthorized(patchText, allowedPaths) {
58
+ const paths = extractPatchPaths(patchText).map(normalizeRepoPath);
59
+ const allowed = new Set(Array.from(allowedPaths || []).map(normalizeRepoPath));
60
+ return paths.length > 0 && paths.every((candidate) => candidate && allowed.has(candidate));
61
+ }
62
+
63
+ module.exports = {
64
+ commandMatches,
65
+ commandsEqual,
66
+ extractPatchPaths,
67
+ normalizeCommand,
68
+ normalizeRepoPath,
69
+ patchPathsAuthorized,
70
+ };