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
@@ -1,128 +1,307 @@
1
1
  #!/usr/bin/env node
2
- const { execSync } = require('child_process');
3
-
4
- // Keyword/guide tables live in the sibling routing-keywords.json, not inline
5
- // here, so the Human Partner (or the LLM itself) can retune routing by
6
- // editing data - no code changes, no re-install. It travels with this script
7
- // on every install/update since it lives in the same skill folder. Fail open
8
- // (empty tables) if it's missing or hand-edited into invalid JSON, so a bad
9
- // edit degrades routing instead of breaking the hook.
2
+ const fs = require('fs');
3
+ const path = require('path');
4
+ const {
5
+ buildRouterContract,
6
+ writeRouterContract,
7
+ } = require('./router-contract');
8
+
9
+ const DEFAULT_ROUTING_CONFIG = {
10
+ tiers: { tier3: [], tier2: [] },
11
+ guideGroups: [],
12
+ factAudit: { externalClaim: [], estimate: [] },
13
+ };
14
+
10
15
  function loadRoutingConfig() {
11
- const fallback = { tiers: { tier3: [], tier2: [] }, guideGroups: [], factAudit: { externalClaim: [], estimate: [] } };
16
+ const configPath = process.env.HARNESS_ROUTING_CONFIG_PATH || path.join(__dirname, 'routing-keywords.json');
12
17
  try {
13
- const raw = require('fs').readFileSync(require('path').join(__dirname, 'routing-keywords.json'), 'utf8');
18
+ const raw = fs.readFileSync(configPath, 'utf8');
14
19
  const parsed = JSON.parse(raw);
15
20
  return {
16
- tiers: parsed.tiers || fallback.tiers,
17
- guideGroups: Array.isArray(parsed.guideGroups) ? parsed.guideGroups : fallback.guideGroups,
18
- factAudit: parsed.factAudit || fallback.factAudit
21
+ config: {
22
+ tiers: parsed.tiers || DEFAULT_ROUTING_CONFIG.tiers,
23
+ guideGroups: Array.isArray(parsed.guideGroups) ? parsed.guideGroups : DEFAULT_ROUTING_CONFIG.guideGroups,
24
+ factAudit: parsed.factAudit || DEFAULT_ROUTING_CONFIG.factAudit,
25
+ },
26
+ routingStatus: 'ok',
27
+ reasonCodes: [],
19
28
  };
20
29
  } catch (err) {
21
- console.log(`[Tier Routing Pre-check] routing-keywords.json missing/invalid - falling back to Tier 1 default, no guides. (${err.message})`);
22
- return fallback;
30
+ console.log(`[Tier Routing Pre-check] routing-keywords.json missing/invalid - routing is degraded; no silent Tier 1 fallback. (${err.message})`);
31
+ return {
32
+ config: DEFAULT_ROUTING_CONFIG,
33
+ routingStatus: 'degraded',
34
+ reasonCodes: ['routing-config-invalid'],
35
+ };
23
36
  }
24
37
  }
25
38
 
26
- function run(userPrompt) {
27
- console.log(`[Tier Routing Pre-check]`);
39
+ function matchKeyword(prompt, keyword) {
40
+ const k = keyword.toLowerCase().trim();
41
+ if (!k) return false;
42
+ const isChineseOrMultiword = /[\u4e00-\u9fa5]/.test(k) || k.includes(' ') || k.includes('-');
43
+ if (isChineseOrMultiword) return prompt.includes(k);
44
+ const escaped = k.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
45
+ return new RegExp(`\\b${escaped}\\b`, 'i').test(prompt);
46
+ }
28
47
 
29
- const promptLower = userPrompt.toLowerCase();
30
- const routingConfig = loadRoutingConfig();
48
+ function detectFableModel(prompt) {
49
+ const match = prompt.match(/\bfable(?:[- ]mode)?\s+(?:on|with)\s+(haiku|sonnet|sonnect|opus)\b|\bfable-(haiku|sonnet|opus)\b/i);
50
+ if (!match) return null;
51
+ const requested = (match[1] || match[2]).toLowerCase();
52
+ return requested === 'sonnect' ? 'sonnet' : requested;
53
+ }
31
54
 
32
- // Basic keyword heuristic (bilingual - the Human Partner often prompts in
33
- // Chinese, and an English-only net silently degrades to Tier 1 for them).
34
- // Deliberately NOT driven by the diff stats above: those measure what is
35
- // already sitting uncommitted in the tree - usually the PREVIOUS task's
36
- // leftovers - not the complexity of the task being asked for now.
37
- const TIER3_KEYWORDS = routingConfig.tiers.tier3 || [];
38
- const TIER2_KEYWORDS = routingConfig.tiers.tier2 || [];
55
+ function detectExplicitStrategy(prompt, requestedFableModel) {
56
+ if (/\bdirect[- ]single\b/i.test(prompt)) return 'direct-single';
57
+ if (/\biterative[- ]single\b/i.test(prompt)) return 'iterative-single';
58
+ if (/\bfable[- ]multi[- ]agent[- ]workspace\b|\bmulti[- ]agent workspace\b/i.test(prompt)) return 'fable-multi-agent-workspace';
59
+ if (/\bfable[- ]parallel\b|\bparallel fable\b/i.test(prompt)) return 'fable-parallel';
60
+ if (/\bfable[- ]staged\b|\bstaged fable\b/i.test(prompt)) return 'fable-staged';
61
+ if (requestedFableModel || /\b(?:use|run|enter)\s+fable(?:[- ]mode)?\b/i.test(prompt)) return 'fable-staged';
62
+ return null;
63
+ }
39
64
 
40
- function matchKeyword(prompt, keyword) {
41
- const k = keyword.toLowerCase().trim();
42
- if (!k) return false;
43
- const isChineseOrMultiword = /[\u4e00-\u9fa5]/.test(k) || k.includes(' ') || k.includes('-');
44
- if (isChineseOrMultiword) {
45
- return prompt.includes(k);
46
- }
47
- const escaped = k.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
48
- return new RegExp(`\\b${escaped}\\b`, 'i').test(prompt);
65
+ function detectProhibitions(prompt) {
66
+ const rules = [
67
+ ['fable', /\b(?:no|without|do not|don't)\s+(?:use\s+)?fable\b/i],
68
+ ['subagents', /\b(?:no|without|do not|don't)\s+(?:use\s+)?subagents?\b|\bsingle[- ]agent only\b/i],
69
+ ['parallel', /\b(?:no|without|do not|don't)\s+(?:use\s+)?parallel(?:ism| execution)?\b|\bdo not parallelize\b|\bserial only\b/i],
70
+ ['workspace', /\b(?:no|without|do not|don't)\s+(?:use\s+)?(?:multi[- ]agent )?workspace\b/i],
71
+ ['memory', /\b(?:no|without|do not|don't)\s+(?:use\s+)?memory\b/i],
72
+ ['ensemble', /\b(?:no|without|do not|don't)\s+(?:use\s+)?ensemble\b/i],
73
+ ];
74
+ return rules.filter(([, regex]) => regex.test(prompt)).map(([name]) => name);
75
+ }
76
+
77
+ function detectActionGateReasons(prompt) {
78
+ const reasons = [];
79
+ const irreversible = [
80
+ /\b(?:drop|truncate|wipe|purge|destroy)\b.*\b(?:database|db|table|production|prod|data)\b/i,
81
+ /\b(?:force[- ]push|push\s+--force(?:-with-lease)?|git\s+push\b[^\n]*--force(?:-with-lease)?)\b/i,
82
+ /\bgit\s+reset\s+--hard\b/i,
83
+ /\bdelete\b.*\b(?:production|prod|database|db|table|branch|release|data)\b/i,
84
+ ];
85
+ const external = [
86
+ /\bdeploy(?:ment|ing|ed)?\b.*\b(?:prod|production|live)\b|\bdeploy\s+to\s+(?:prod|production|live)\b/i,
87
+ /\b(?:npm|pnpm|yarn|cargo|pip|twine)\s+publish\b|\bpublish\s+(?:the\s+)?(?:package|release|artifact)\b/i,
88
+ /\b(?:send|email|message)\b.*\b(?:customer|client|user|users|external|production)\b/i,
89
+ /\b(?:charge|pay|payment|refund|transfer)\b.*\b(?:customer|account|money|funds|invoice)?\b/i,
90
+ /\bcreate\b.*\b(?:release|deployment)\b/i,
91
+ ];
92
+ if (irreversible.some(regex => regex.test(prompt))) reasons.push('irreversible-action');
93
+ if (external.some(regex => regex.test(prompt))) reasons.push('external-side-effect');
94
+ return reasons;
95
+ }
96
+
97
+ function addReason(reasonCodes, code) {
98
+ if (code && !reasonCodes.includes(code)) reasonCodes.push(code);
99
+ }
100
+
101
+ function deduplicateGuidesByPath(guides) {
102
+ const byPath = new Map();
103
+ for (const guide of guides) {
104
+ const match = String(guide).match(/^\s*-\s+([^\s]+)/);
105
+ const key = match ? match[1].replace(/\\/g, '/') : String(guide).trim();
106
+ if (!byPath.has(key)) byPath.set(key, guide);
49
107
  }
108
+ return Array.from(byPath.values());
109
+ }
110
+
111
+ function countDomainSignals(promptLower) {
112
+ const domains = [
113
+ /\bsecurity\b|安全|資安/i,
114
+ /\barchitecture\b|架構/i,
115
+ /\bdocumentation\b|\bdocs?\b|文件/i,
116
+ /\btests?\b|測試/i,
117
+ /\bfrontend\b|前端/i,
118
+ /\bbackend\b|後端/i,
119
+ /\bdatabase\b|資料庫/i,
120
+ /\binfrastructure\b|\bdevops\b|基礎設施/i,
121
+ ];
122
+ return domains.reduce((count, regex) => count + (regex.test(promptLower) ? 1 : 0), 0);
123
+ }
124
+
125
+ function plannerInputsFromContext(context, promptLower) {
126
+ const harness = context && typeof context.harness === 'object' ? context.harness : {};
127
+ const rawHost = (context && context.hostCapabilities) || harness.hostCapabilities || {};
128
+ const rawConstraints = (context && context.constraints) || harness.constraints || {};
129
+ const hostCapabilities = { ...rawHost };
130
+ const constraints = { ...rawConstraints };
50
131
 
51
- function detectFableModel(prompt) {
52
- const match = prompt.match(/\bfable(?:[- ]mode)?\s+(?:on|with)\s+(haiku|sonnet|sonnect|opus)\b|\bfable-(haiku|sonnet|opus)\b/i);
53
- if (!match) return null;
54
- const requested = (match[1] || match[2]).toLowerCase();
55
- return requested === 'sonnect' ? 'sonnet' : requested;
132
+ const envCapabilityMap = {
133
+ subagents: process.env.HARNESS_HOST_SUBAGENTS,
134
+ parallelCalls: process.env.HARNESS_HOST_PARALLEL_CALLS,
135
+ hooks: process.env.HARNESS_HOST_HOOKS,
136
+ state: process.env.HARNESS_HOST_STATE,
137
+ modelAvailability: process.env.HARNESS_HOST_MODEL_AVAILABILITY,
138
+ };
139
+ for (const [key, value] of Object.entries(envCapabilityMap)) {
140
+ if (value) hostCapabilities[key] = value;
56
141
  }
57
142
 
58
- let recommendedTier = "Tier 1 (Trivial)";
59
- let rationale = "No structural/testing signals in the prompt.";
143
+ if (process.env.HARNESS_BUDGET_CONCURRENCY !== undefined) constraints.concurrency = process.env.HARNESS_BUDGET_CONCURRENCY;
144
+ if (process.env.HARNESS_BUDGET_COST !== undefined) constraints.cost = process.env.HARNESS_BUDGET_COST;
145
+ if (process.env.HARNESS_BUDGET_LATENCY !== undefined) constraints.latency = process.env.HARNESS_BUDGET_LATENCY;
146
+ if (process.env.HARNESS_BUDGET_TOKENS !== undefined) constraints.tokens = process.env.HARNESS_BUDGET_TOKENS;
147
+
148
+ const concurrencyMatch = promptLower.match(/\b(?:max(?:imum)?\s+)?(?:concurrency|workers?|agents?)\s*(?:=|:|of)?\s*(\d+)\b/i);
149
+ if (concurrencyMatch) constraints.concurrency = Number(concurrencyMatch[1]);
150
+ if (/\b(?:single worker|one worker|serial only)\b/i.test(promptLower)) constraints.concurrency = 1;
151
+
152
+ return { hostCapabilities, constraints };
153
+ }
154
+
155
+ function emitDynamicSkills(promptLower, context, recommendedGuides) {
156
+ try {
157
+ const userHome = process.env.HOME || process.env.USERPROFILE || '';
158
+ const { getWorkspaceRoot } = require('../../scripts/lib/workspace');
159
+ const workspaceRoot = getWorkspaceRoot(context);
160
+
161
+ const manifestPaths = [
162
+ path.join(workspaceRoot, '.claude', 'harness-everything', 'manifest.json'),
163
+ path.join(workspaceRoot, '.cursor', 'harness-everything', 'manifest.json'),
164
+ path.join(workspaceRoot, '.github', 'harness-everything', 'manifest.json'),
165
+ path.join(workspaceRoot, '.codex', 'harness-everything', 'manifest.json'),
166
+ path.join(workspaceRoot, '.continue', 'harness-everything', 'manifest.json'),
167
+ path.join(userHome, '.agents', 'harness-everything', 'manifest.json'),
168
+ path.join(userHome, '.claude', 'harness-everything', 'manifest.json'),
169
+ ];
170
+
171
+ const generatedSkills = new Map();
172
+ for (const manifestPath of manifestPaths) {
173
+ if (!fs.existsSync(manifestPath)) continue;
174
+ try {
175
+ const manifestData = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
176
+ if (Array.isArray(manifestData.generated)) {
177
+ for (const skill of manifestData.generated) generatedSkills.set(skill.id, skill);
178
+ }
179
+ } catch (err) {
180
+ // Ignore malformed generated-skill manifests; they are advisory only.
181
+ }
182
+ }
183
+
184
+ const allDynamicSkills = Array.from(generatedSkills.values());
185
+ const matchedDynamicSkills = [];
186
+
187
+ for (const skill of allDynamicSkills) {
188
+ let score = 0;
189
+ for (const rawTrigger of skill.triggers || []) {
190
+ const trigger = rawTrigger.toLowerCase().trim();
191
+ if (!trigger || trigger.length < 2) continue;
192
+ if (['the', 'and', 'for', 'with', 'your', 'this', 'that', 'some', 'from', 'prevent', 'resolved'].includes(trigger)) continue;
193
+
194
+ if (/[\u4e00-\u9fa5]/.test(trigger)) {
195
+ if (promptLower.includes(trigger)) score += trigger.length * 2;
196
+ } else {
197
+ const escapedTrigger = trigger.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
198
+ const regex = new RegExp(`\\b${escapedTrigger}\\b`, 'i');
199
+ if (regex.test(promptLower)) score += trigger.length >= 4 ? 3 : 1.5;
200
+ }
201
+ }
202
+ if (score >= 3) matchedDynamicSkills.push({ skill, score });
203
+ }
204
+
205
+ if (matchedDynamicSkills.length > 0) {
206
+ matchedDynamicSkills.sort((a, b) => b.score - a.score);
207
+ console.log(`\n=> 🎯 HIGH-RELEVANCE SELF-EVOLVED SKILL(S) DETECTED:`);
208
+ matchedDynamicSkills.forEach(({ skill }) => {
209
+ let displayPath = skill.dirPath;
210
+ if (displayPath.startsWith(workspaceRoot)) displayPath = path.relative(workspaceRoot, displayPath);
211
+ console.log(`- ${displayPath}/SKILL.md (${skill.description} [DYNAMIC SKILL])`);
212
+ });
213
+ } else if (recommendedGuides.length === 0 && allDynamicSkills.length > 0) {
214
+ console.log(`\n=> ℹ️ UNMATCHED PROMPT HINT:`);
215
+ console.log(`No standard or dynamic skills matched your prompt directly.`);
216
+ console.log(`However, you have ${allDynamicSkills.length} self-evolved dynamic skill(s) registered in your manifest.json.`);
217
+ console.log(`To ensure you don't miss past lessons, you should inspect the "generated" section of your manifest.json or check .claude/harness-everything/skills/generated/ to see if any apply to your current task.`);
218
+ console.log(`If genuinely nothing covers this - including nothing already fetched via find-skills - load find-skills/SKILL.md: it checks "npx skills list" for anything already installed, then searches skills.sh/npx skills if not, and always requires explicit approval before installing anything.`);
219
+ }
220
+ } catch (err) {
221
+ // Dynamic-skill discovery is advisory and must never break core routing.
222
+ }
223
+ }
224
+
225
+ function run(userPrompt, context) {
226
+ console.log(`[Tier Routing Pre-check]`);
227
+
228
+ const promptLower = userPrompt.toLowerCase();
229
+ const loadedConfig = loadRoutingConfig();
230
+ const routingConfig = loadedConfig.config;
231
+ const TIER3_KEYWORDS = routingConfig.tiers.tier3 || [];
232
+ const TIER2_KEYWORDS = routingConfig.tiers.tier2 || [];
60
233
 
61
- // Task-shape signals catch one-sentence audits and benchmarks that a flat
62
- // keyword list cannot see. They are intentionally kept here, rather than
63
- // mixed into the editable technology keyword table.
64
234
  const macroSignals = [
65
235
  /\b(?:every|each|all|entire|whole|full|complete)\s+(?:skill|skills|repo|repository|codebase|project|file|files|module|modules)/i,
66
236
  /\b(?:evaluate|audit|benchmark|stress[- ]test|ab test|a\/b test|compare)\b/i,
67
237
  /\b(?:repository[- ]wide|codebase[- ]wide|end[- ]to[- ]end)\b/i,
68
238
  /\b(?:multiple|several|four|fourteen|dozens)\s+(?:issues|skills|files|modules)/i,
69
239
  /(?:每個|每一個|所有|全部|整個|全套|逐一|多個|四個).*(?:skill|技能|檔案|問題|版本|基準|測試|評估|稽核|比較|壓力)/i,
70
- /(?:評估|稽核|基準|壓力測試|比較).*(?:每個|所有|全部|整個|全套|技能|skill|檔案|版本)/i
240
+ /(?:評估|稽核|基準|壓力測試|比較).*(?:每個|所有|全部|整個|全套|技能|skill|檔案|版本)/i,
71
241
  ];
72
242
  const hasMacroSignal = macroSignals.some(signal => signal.test(userPrompt));
73
- const isTrivialDocsEdit = /^(?:(?:please|help me)\s+)?(?:fix|update|correct|change)\b.*\b(?:readme|documentation|docs?)\b.*\b(?:typo|spelling|wording|one line|single line)\b/i.test(userPrompt.trim());
243
+ const hasTrivialEditVerb = /^(?:(?:please|help me)\s+)?(?:fix|update|correct|change)\b/i.test(userPrompt.trim());
244
+ const hasDocsTarget = /\b(?:readme|documentation|docs?)\b/i.test(userPrompt);
245
+ const hasTinyEditSignal = /\b(?:typo|spelling|wording|one line|single line)\b/i.test(userPrompt);
246
+ const isTrivialDocsEdit = !hasMacroSignal && hasTrivialEditVerb && hasDocsTarget && hasTinyEditSignal;
247
+ const hasTier3Keyword = TIER3_KEYWORDS.some(keyword => matchKeyword(promptLower, keyword));
248
+ const hasTier2Keyword = TIER2_KEYWORDS.some(keyword => matchKeyword(promptLower, keyword));
249
+
250
+ let recommendedTier = 'Unclassified';
251
+ let rationale = 'No structural/testing signals matched; unclassified is not equivalent to trivial.';
252
+ const reasonCodes = [...loadedConfig.reasonCodes, 'no-classification-signal'];
74
253
 
75
254
  if (isTrivialDocsEdit) {
76
- // "update" is a common Tier 2 verb, but a one-line documentation typo
77
- // is still Tier 1. This override prevents a broad keyword from winning.
78
- recommendedTier = "Tier 1 (Trivial)";
79
- rationale = "Single documentation typo detected - direct edit, no checklist required.";
80
- } else if (hasMacroSignal || TIER3_KEYWORDS.some(k => matchKeyword(promptLower, k))) {
81
- recommendedTier = "Tier 3 (Macro Task)";
82
- rationale = "Prompt implies repository-wide scope, audit/benchmark work, architectural refactoring, or multi-agent collaboration.";
83
- } else if (TIER2_KEYWORDS.some(k => matchKeyword(promptLower, k))) {
84
- recommendedTier = "Tier 2 (Standard Task)";
85
- rationale = "Prompt implies development work needing TDD validation or multi-file coordination.";
255
+ recommendedTier = 'Tier 1 (Trivial)';
256
+ rationale = 'Single documentation typo detected - direct edit, no checklist required.';
257
+ reasonCodes.splice(loadedConfig.reasonCodes.length);
258
+ addReason(reasonCodes, 'trivial-docs-edit');
259
+ } else if (hasMacroSignal || hasTier3Keyword) {
260
+ recommendedTier = 'Tier 3 (Macro Task)';
261
+ rationale = 'Prompt implies repository-wide scope, audit/benchmark work, architectural refactoring, or multi-agent collaboration.';
262
+ reasonCodes.splice(loadedConfig.reasonCodes.length);
263
+ addReason(reasonCodes, hasMacroSignal ? 'macro-scope-signal' : 'tier3-keyword');
264
+ } else if (hasTier2Keyword) {
265
+ recommendedTier = 'Tier 2 (Standard Task)';
266
+ rationale = 'Prompt implies development work needing TDD validation or multi-file coordination.';
267
+ reasonCodes.splice(loadedConfig.reasonCodes.length);
268
+ addReason(reasonCodes, 'tier2-keyword');
86
269
  }
87
270
 
88
- // Structural complexity signals (not just keywords)
89
- // These help differentiate between simple and complex tasks within the same keyword tier
90
- const sentenceCount = userPrompt.split(/[.!?。!?]+/).filter(s => s.trim()).length;
271
+ const sentenceCount = userPrompt.split(/[.!?。!?]+/).filter(sentence => sentence.trim()).length;
91
272
  const hasMultipleTasks = /\b(and|also|then|additionally|plus|而且|還有|然後|另外|以及)\b/i.test(userPrompt);
92
273
  const mentionsSpecificFile = /\b(file|script|module|class|function|component)\b.*\.\w+/i.test(userPrompt);
93
274
  const hasQuestionMarks = /\?|?/.test(userPrompt);
94
275
  const hasMultipleSentences = sentenceCount > 2;
95
276
 
96
- // Adjust tier based on structural signals
97
277
  if (!hasMacroSignal && !isTrivialDocsEdit && hasMultipleTasks && hasMultipleSentences) {
98
- // Multiple tasks with multiple sentences suggests complexity
99
- if (recommendedTier.startsWith("Tier 1")) {
100
- recommendedTier = "Tier 2 (Standard Task)";
101
- rationale = "Multiple tasks detected with structural complexity - upgraded to Tier 2 for TDD validation.";
102
- } else if (recommendedTier.startsWith("Tier 2")) {
103
- // Keep at Tier 2 but note the complexity
104
- rationale += " Multiple task structure detected.";
278
+ if (recommendedTier === 'Unclassified' || recommendedTier.startsWith('Tier 1')) {
279
+ recommendedTier = 'Tier 2 (Standard Task)';
280
+ rationale = 'Multiple tasks detected with structural complexity - upgraded to Tier 2 for TDD validation.';
281
+ reasonCodes.splice(loadedConfig.reasonCodes.length);
282
+ addReason(reasonCodes, 'multi-task-structure');
283
+ } else if (recommendedTier.startsWith('Tier 2')) {
284
+ rationale += ' Multiple task structure detected.';
285
+ addReason(reasonCodes, 'multi-task-structure');
105
286
  }
106
287
  } else if (!hasMacroSignal && mentionsSpecificFile && !hasMultipleTasks) {
107
- // Single file mention with no multiple tasks suggests simpler work
108
- if (recommendedTier.startsWith("Tier 3")) {
109
- recommendedTier = "Tier 2 (Standard Task)";
110
- rationale = "Single file focus detected - downgraded from Tier 3 to Tier 2.";
288
+ if (recommendedTier.startsWith('Tier 3')) {
289
+ recommendedTier = 'Tier 2 (Standard Task)';
290
+ rationale = 'Single file focus detected - downgraded from Tier 3 to Tier 2.';
291
+ addReason(reasonCodes, 'single-file-focus');
111
292
  }
112
293
  } else if (!hasMacroSignal && hasQuestionMarks && !hasMultipleTasks) {
113
- // Questions without multiple tasks are often advisory, not execution
114
- if (recommendedTier.startsWith("Tier 3")) {
115
- recommendedTier = "Tier 2 (Standard Task)";
116
- rationale = "Question format detected - likely advisory rather than macro execution.";
294
+ if (recommendedTier.startsWith('Tier 3')) {
295
+ recommendedTier = 'Tier 2 (Standard Task)';
296
+ rationale = 'Question format detected - likely advisory rather than macro execution.';
297
+ addReason(reasonCodes, 'question-format');
117
298
  }
118
299
  }
119
300
 
120
301
  console.log(`\n=> RECOMMENDED TIER: ${recommendedTier}`);
121
302
  console.log(`=> RATIONALE: ${rationale}`);
122
303
 
123
- // Base execution loop: Tier 2/3 must run on the todo-driven-workflow
124
- // checklist (Tier 1 is exempt to avoid checklist bloat on trivial edits).
125
- if (!recommendedTier.startsWith("Tier 1")) {
304
+ if (recommendedTier.startsWith('Tier 2') || recommendedTier.startsWith('Tier 3')) {
126
305
  console.log(`\n=> BASE EXECUTION LOOP: Load 'todo-driven-workflow' and initialize its checklist (3-7 verifiable sub-tasks) BEFORE editing any file.`);
127
306
  console.log(` Track exactly ONE item in-progress at a time; verify with real evidence before marking completed.`);
128
307
  }
@@ -134,30 +313,25 @@ function run(userPrompt) {
134
313
  console.log(` Resolve availability and record fallback status with fable-mode/scripts/model-selector.js.`);
135
314
  }
136
315
 
137
- // Analyze and output relevant Knowledge Guides / Templates based on user prompt keywords.
138
- // Each group comes from routing-keywords.json - matches via plain-substring
139
- // 'keywords' OR a 'regex' source string (tested case-insensitively).
140
- const recommendedGuides = [];
141
-
316
+ const allRecommendedGuides = [];
142
317
  for (const group of routingConfig.guideGroups) {
143
318
  let matched = false;
144
- if (typeof group.regex === "string") {
145
- matched = new RegExp(group.regex, "i").test(promptLower);
319
+ if (typeof group.regex === 'string') {
320
+ matched = new RegExp(group.regex, 'i').test(promptLower);
146
321
  } else if (Array.isArray(group.keywords)) {
147
- matched = group.keywords.some(k => promptLower.includes(k));
148
- }
149
- if (matched && Array.isArray(group.guides)) {
150
- recommendedGuides.push(...group.guides);
322
+ matched = group.keywords.some(keyword => promptLower.includes(keyword));
151
323
  }
324
+ if (matched && Array.isArray(group.guides)) allRecommendedGuides.push(...group.guides);
152
325
  }
326
+ const recommendedGuides = deduplicateGuidesByPath(allRecommendedGuides);
153
327
 
154
328
  if (recommendedGuides.length > 0) {
155
329
  console.log(`\n=> RECOMMENDED KNOWLEDGE GUIDES (Auto-loaded based on keywords):`);
156
330
  recommendedGuides.forEach(guide => {
157
331
  const match = guide.match(/^- ([^\s]+)/);
158
332
  if (match) {
159
- const guidePath = require('path').join(__dirname, '..', '..', match[1]);
160
- if (!require('fs').existsSync(guidePath)) {
333
+ const guidePath = path.join(__dirname, '..', '..', match[1]);
334
+ if (!fs.existsSync(guidePath)) {
161
335
  console.log(`${guide} [NOT INSTALLED - Ignore this recommendation]`);
162
336
  return;
163
337
  }
@@ -166,130 +340,12 @@ function run(userPrompt) {
166
340
  });
167
341
  }
168
342
 
169
- // ---------------------------------------------------------
170
- // SELF-EVOLVED DYNAMIC SKILLS AUTO-DISCOVERY & PRECISE MATCHING
171
- //
172
- // Deliberately generated[] only, not find-skills' downloaded skills:
173
- // generated[] is safe to cache-and-match here because Harness owns its
174
- // whole lifecycle (self-evolve authors it, skill-creator quality-gates it,
175
- // status is tracked draft/active/deprecated). A skill fetched via
176
- // `npx skills add` has none of that - caching its triggers/description at
177
- // download time would silently go stale the moment the upstream skill (or
178
- // a later `npx skills update`/`remove`) changes it. find-skills queries
179
- // `npx skills list` live instead of being folded into this cache.
180
- // ---------------------------------------------------------
181
- try {
182
- const fs = require('fs');
183
- const path = require('path');
184
- const userHome = process.env.HOME || process.env.USERPROFILE || '';
185
-
186
- // Skill installs land at varying depth per platform/scope (e.g.
187
- // <root>/.claude/skills/harness-everything/scripts/, <root>/.cursor/skills/...,
188
- // ~/.claude/skills/...), so a fixed __dirname offset can't reach the real
189
- // workspace root. Walk up from the invoking cwd to the nearest .git instead
190
- // - the same approach register-dynamic-skill.js already uses.
191
- function getWorkspaceRoot() {
192
- let dir = path.resolve(process.cwd());
193
- while (dir !== path.parse(dir).root) {
194
- if (fs.existsSync(path.join(dir, '.git'))) return dir;
195
- dir = path.dirname(dir);
196
- }
197
- return process.cwd();
198
- }
199
- const workspaceRoot = getWorkspaceRoot();
200
-
201
- const manifestPaths = [
202
- path.join(workspaceRoot, '.claude', 'harness-everything', 'manifest.json'),
203
- path.join(workspaceRoot, '.cursor', 'harness-everything', 'manifest.json'),
204
- path.join(workspaceRoot, '.github', 'harness-everything', 'manifest.json'),
205
- path.join(workspaceRoot, '.codex', 'harness-everything', 'manifest.json'),
206
- path.join(workspaceRoot, '.continue', 'harness-everything', 'manifest.json'),
207
- path.join(userHome, '.agents', 'harness-everything', 'manifest.json'),
208
- path.join(userHome, '.claude', 'harness-everything', 'manifest.json')
209
- ];
210
-
211
- const generatedSkills = new Map();
212
- for (const mPath of manifestPaths) {
213
- if (fs.existsSync(mPath)) {
214
- try {
215
- const manifestData = JSON.parse(fs.readFileSync(mPath, 'utf8'));
216
- if (Array.isArray(manifestData.generated)) {
217
- for (const s of manifestData.generated) {
218
- generatedSkills.set(s.id, s);
219
- }
220
- }
221
- } catch (err) {
222
- // ignore malformed manifests
223
- }
224
- }
225
- }
226
-
227
- const allDynamicSkills = Array.from(generatedSkills.values());
228
- const matchedDynamicSkills = [];
343
+ emitDynamicSkills(promptLower, context, recommendedGuides);
229
344
 
230
- for (const skill of allDynamicSkills) {
231
- let score = 0;
232
- const triggers = skill.triggers || [];
233
-
234
- for (const rawTrigger of triggers) {
235
- const trigger = rawTrigger.toLowerCase().trim();
236
- if (!trigger || trigger.length < 2) continue;
237
-
238
- // Ignore generic words to prevent false positives
239
- if (['the', 'and', 'for', 'with', 'your', 'this', 'that', 'some', 'from', 'prevent', 'resolved'].includes(trigger)) continue;
240
-
241
- const isChinese = /[\u4e00-\u9fa5]/.test(trigger);
242
- if (isChinese) {
243
- if (promptLower.includes(trigger)) {
244
- score += trigger.length * 2;
245
- }
246
- } else {
247
- // English word-boundary matching to prevent substrings inside larger words
248
- const escapedTrigger = trigger.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
249
- const regex = new RegExp(`\\b${escapedTrigger}\\b`, 'i');
250
- if (regex.test(promptLower)) {
251
- score += trigger.length >= 4 ? 3 : 1.5;
252
- }
253
- }
254
- }
255
-
256
- if (score >= 3) {
257
- matchedDynamicSkills.push({ skill, score });
258
- }
259
- }
260
-
261
- if (matchedDynamicSkills.length > 0) {
262
- matchedDynamicSkills.sort((a, b) => b.score - a.score);
263
- console.log(`\n=> 🎯 HIGH-RELEVANCE SELF-EVOLVED SKILL(S) DETECTED:`);
264
- matchedDynamicSkills.forEach(({ skill }) => {
265
- // Compute path relative to workspace or keep absolute
266
- let displayPath = skill.dirPath;
267
- if (displayPath.startsWith(workspaceRoot)) {
268
- displayPath = path.relative(workspaceRoot, displayPath);
269
- }
270
- console.log(`- ${displayPath}/SKILL.md (${skill.description} [DYNAMIC SKILL])`);
271
- });
272
- } else if (recommendedGuides.length === 0 && allDynamicSkills.length > 0) {
273
- // Prompt has no match in standard skills, and no direct match in dynamic skills,
274
- // but there are indeed dynamic skills in manifest.json. Suggest the LLM to inspect them!
275
- console.log(`\n=> ℹ️ UNMATCHED PROMPT HINT:`);
276
- console.log(`No standard or dynamic skills matched your prompt directly.`);
277
- console.log(`However, you have ${allDynamicSkills.length} self-evolved dynamic skill(s) registered in your manifest.json.`);
278
- console.log(`To ensure you don't miss past lessons, you should inspect the "generated" section of your manifest.json or check .claude/harness-everything/skills/generated/ to see if any apply to your current task.`);
279
- console.log(`If genuinely nothing covers this - including nothing already fetched via find-skills - load find-skills/SKILL.md: it checks "npx skills list" for anything already installed, then searches skills.sh/npx skills if not, and always requires explicit approval before installing anything.`);
280
- }
281
- } catch (err) {
282
- // Fail silently in router to prevent breaking the core execution loop
283
- }
284
-
285
- // Fact-audit nudge: broad, cheap keyword net for claims that risk being
286
- // asserted from stale/wrong training memory instead of verified. False
287
- // positives cost nothing here (it's a reminder, not a block) so recall
288
- // matters more than precision.
289
345
  const externalClaimTriggers = routingConfig.factAudit.externalClaim || [];
290
346
  const estimateTriggers = routingConfig.factAudit.estimate || [];
291
- const hitExternalClaim = externalClaimTriggers.some(kw => promptLower.includes(kw));
292
- const hitEstimate = estimateTriggers.some(kw => promptLower.includes(kw));
347
+ const hitExternalClaim = externalClaimTriggers.some(keyword => promptLower.includes(keyword));
348
+ const hitEstimate = estimateTriggers.some(keyword => promptLower.includes(keyword));
293
349
 
294
350
  if (hitExternalClaim || hitEstimate) {
295
351
  console.log(`\n=> FACT-AUDIT REMINDER:`);
@@ -303,32 +359,101 @@ function run(userPrompt) {
303
359
  }
304
360
  }
305
361
 
306
- // Constraint strength must match judgment reliability: this routing is a
307
- // keyword heuristic, so it is a default, not an order.
308
- console.log(`\nTreat the tier above as the default route. If your own read of the task clearly disagrees, follow your read and say why in one line. An explicit instruction from the Human Partner always wins.`);
362
+ const independentWorkstreams = /\bindependent(?:ly)?\b|\bparallel(?:ize|ise|ized|ised|ism)?\b/i.test(userPrompt);
363
+ const readOnly = /\bread[- ]only\b|\bno edits?\b|\bwithout (?:editing|edits|changes|modifications)\b/i.test(userPrompt);
364
+ const disjointWrites = /\bdisjoint\b|\bnon[- ]overlapping\b|\bseparate files?\b|\bdistinct files?\b/i.test(userPrompt);
365
+ const sharedWrite = /\bsame files?\b|\bshared mutable state\b|\boverlapping writes?\b|\bshared write[- ]set\b/i.test(userPrompt);
366
+ const dependentStages = /\bdependent\b|\bsequential\b|\bstaged?\b|\bafter\b.*\bthen\b/i.test(userPrompt);
367
+ const multiSession = /\bmulti[- ]session\b|\bmultiple sessions\b|\bacross sessions\b|\bdurable\b|\blong[- ]running\b|\bpersistent handoff\b/i.test(userPrompt);
368
+ const reusableSpecialists = /\breusable specialists?\b|\bpersistent roles?\b|\bspecialist catalog\b|\breusable roles?\b/i.test(userPrompt);
369
+ const crossDomain = countDomainSignals(promptLower) >= 2;
370
+ const highUncertainty = /\bhigh uncertainty\b|\bcompeting approaches\b|\bdesign comparison\b|\bcompare alternatives\b|\btrade[- ]offs?\b/i.test(userPrompt);
371
+ const actionGateReasonCodes = detectActionGateReasons(userPrompt);
372
+ const irreversibleAction = actionGateReasonCodes.includes('irreversible-action');
373
+ const externalSideEffect = actionGateReasonCodes.includes('external-side-effect');
374
+ const requestedStrategy = detectExplicitStrategy(userPrompt, requestedFableModel);
375
+ const prohibitions = detectProhibitions(userPrompt);
376
+ const plannerInputs = plannerInputsFromContext(context, promptLower);
377
+
378
+ const contract = buildRouterContract({
379
+ routingStatus: loadedConfig.routingStatus,
380
+ recommendedTier,
381
+ rationale,
382
+ reasonCodes,
383
+ requestedFableModel,
384
+ explicitRequest: {
385
+ fableModel: requestedFableModel,
386
+ strategy: requestedStrategy,
387
+ prohibitions,
388
+ },
389
+ hostCapabilities: plannerInputs.hostCapabilities,
390
+ constraints: plannerInputs.constraints,
391
+ actionGateReasonCodes,
392
+ signals: {
393
+ macroScope: hasMacroSignal,
394
+ trivialDocsEdit: isTrivialDocsEdit,
395
+ tier3Keyword: hasTier3Keyword,
396
+ tier2Keyword: hasTier2Keyword,
397
+ multipleTasks: hasMultipleTasks,
398
+ multipleSentences: hasMultipleSentences,
399
+ specificFile: mentionsSpecificFile,
400
+ question: hasQuestionMarks,
401
+ independentWorkstreams,
402
+ readOnly,
403
+ disjointWrites,
404
+ sharedWrite,
405
+ dependentStages,
406
+ multiSession,
407
+ reusableSpecialists,
408
+ crossDomain,
409
+ highUncertainty,
410
+ irreversibleAction,
411
+ externalSideEffect,
412
+ highRisk: irreversibleAction || externalSideEffect,
413
+ },
414
+ });
415
+
416
+ console.log(`\n=> WORKFLOW STRATEGY: ${contract.workflowPlan.strategy || 'deferred'}`);
417
+ if (contract.workflowPlan.actionGate.required) {
418
+ console.log(`=> ACTION GATE: required (${contract.workflowPlan.actionGate.reasonCodes.join(', ')}); disposition=pending-approval`);
419
+ }
420
+ if (contract.workflowPlan.fallback.disposition !== 'none') {
421
+ console.log(`=> ROUTING FALLBACK: ${contract.workflowPlan.fallback.disposition}/${contract.workflowPlan.fallback.mode} (${contract.workflowPlan.fallback.reasonCodes.join(', ')})`);
422
+ }
423
+
424
+ if (process.env.HARNESS_ROUTER_CONTRACT_PATH) {
425
+ try {
426
+ writeRouterContract(process.env.HARNESS_ROUTER_CONTRACT_PATH, contract);
427
+ } catch (err) {
428
+ console.error(`[Tier Routing Pre-check] failed to write structured router contract: ${err.message}`);
429
+ }
430
+ }
431
+
432
+ console.log(`\nTreat the tier and strategy above as the default route. Explicit Human Partner choices/prohibitions win and are recorded in the plan; unavailable capabilities must remain visible rather than being silently downgraded.`);
433
+ return contract;
309
434
  }
310
435
 
311
436
  let userPrompt = process.argv[2] || '';
437
+ let hookContext = null;
312
438
 
313
439
  if (process.argv[2]) {
314
- // If a command-line argument is passed, use it and execute immediately.
315
440
  run(userPrompt);
316
441
  } else if (process.stdin.isTTY) {
317
- // Running interactively in a terminal without piped input, execute immediately.
318
442
  run('');
319
443
  } else {
320
- // Piped input or non-TTY, read from standard input.
321
444
  let inputData = '';
445
+ process.stdin.setEncoding('utf8');
322
446
  process.stdin.on('data', chunk => { inputData += chunk; });
323
447
  process.stdin.on('end', () => {
324
448
  try {
325
449
  if (inputData.trim()) {
326
450
  const payload = JSON.parse(inputData);
327
451
  if (typeof payload.prompt === 'string') userPrompt = payload.prompt;
452
+ hookContext = payload;
328
453
  }
329
454
  } catch (err) {
330
- // Not valid JSON on stdin - fall back to argv (useful for direct/manual testing).
455
+ // Not valid JSON on stdin - fall back to argv/manual behavior.
331
456
  }
332
- run(userPrompt);
457
+ run(userPrompt, hookContext);
333
458
  });
334
459
  }