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
@@ -2,23 +2,6 @@
2
2
  // precisely those paths instead of sweeping shared directories that may also
3
3
  // hold content from other tools, the user's own manual additions, or
4
4
  // self-evolve's locally-generated skills.
5
- //
6
- // Deliberately does NOT track find-skills' third-party downloads the same
7
- // way: generated[] works because Harness owns the full lifecycle (authored,
8
- // quality-gated, and status-tracked by self-evolve/skill-creator). A skill
9
- // fetched via `npx skills add` is unaudited content Harness doesn't own or
10
- // control the lifecycle of - the `skills` CLI's own lock file is already the
11
- // live record of what's installed, so find-skills queries that directly
12
- // (`npx skills list`) instead of caching a second, driftable copy here.
13
- //
14
- // The manifest always lives at <platform-home>/harness-everything/manifest.json
15
- // - e.g. .claude/harness-everything/manifest.json, .cursor/harness-everything/
16
- // manifest.json, or (global scope) ~/.agents/harness-everything/manifest.json.
17
- // harness-everything/ is a subfolder this package exclusively owns inside a
18
- // directory that already belongs to that platform (or, for global scope, the
19
- // shared ~/.agents convention) - nothing else creates a directory literally
20
- // named "harness-everything" there, so nesting under it is what makes "the
21
- // manifest can only describe our own installs" actually true.
22
5
  const fs = require('fs');
23
6
  const path = require('path');
24
7
 
@@ -35,9 +18,7 @@ function getManifestPath(homeDir) {
35
18
  }
36
19
 
37
20
  function readManifest(manifestPath) {
38
- if (!fs.existsSync(manifestPath)) {
39
- return { package: PACKAGE_NAME, skills: [], agents: [] };
40
- }
21
+ if (!fs.existsSync(manifestPath)) return { package: PACKAGE_NAME, skills: [], agents: [] };
41
22
  try {
42
23
  const data = JSON.parse(fs.readFileSync(manifestPath, 'utf8'));
43
24
  if (!Array.isArray(data.skills)) data.skills = [];
@@ -53,13 +34,41 @@ function writeManifest(manifestPath, data) {
53
34
  fs.writeFileSync(manifestPath, JSON.stringify(data, null, 2), 'utf8');
54
35
  }
55
36
 
56
- function recordSkillInstall(manifestPath, packageVersion, skillId, dirPath) {
37
+ function isManifestEmpty(data) {
38
+ return (data.skills || []).length === 0 &&
39
+ (data.generated || []).length === 0 &&
40
+ (data.agents || []).length === 0;
41
+ }
42
+
43
+ // `references/` is copied by the installer into the same Harness-owned
44
+ // bookkeeping directory as manifest.json. Once the manifest contains no
45
+ // owned artifacts, both are package-owned leftovers and can be removed as a
46
+ // unit without touching the platform home around them.
47
+ function removeManifestArtifactsIfEmpty(manifestPath, data) {
48
+ if (!isManifestEmpty(data)) return false;
49
+ if (fs.existsSync(manifestPath)) fs.unlinkSync(manifestPath);
50
+ const harnessDir = path.dirname(manifestPath);
51
+ const referencesDir = path.join(harnessDir, 'references');
52
+ if (fs.existsSync(referencesDir)) fs.rmSync(referencesDir, { recursive: true, force: true });
53
+ try {
54
+ if (fs.existsSync(harnessDir) && fs.readdirSync(harnessDir).length === 0) fs.rmdirSync(harnessDir);
55
+ } catch (e) {
56
+ // Another owned runtime artifact may still live here; leave it intact.
57
+ }
58
+ return true;
59
+ }
60
+
61
+ function recordSkillInstall(manifestPath, packageVersion, skillId, dirPath, linkInfo = {}) {
57
62
  const data = readManifest(manifestPath);
58
63
  data.package = PACKAGE_NAME;
59
64
  data.version = packageVersion;
60
65
  data.updatedAt = new Date().toISOString();
61
66
  const idx = data.skills.findIndex(s => s.dirPath === dirPath);
62
67
  const entry = { id: skillId, dirPath, installedAt: new Date().toISOString() };
68
+ if (linkInfo.kind && linkInfo.kind !== 'copy') {
69
+ entry.kind = linkInfo.kind;
70
+ entry.canonicalPath = linkInfo.canonicalPath;
71
+ }
63
72
  if (idx !== -1) data.skills[idx] = entry;
64
73
  else data.skills.push(entry);
65
74
  writeManifest(manifestPath, data);
@@ -80,7 +89,6 @@ function recordAgentInstall(manifestPath, packageVersion, agentId, filePath) {
80
89
  function recordGeneratedSkill(manifestPath, skillId, dirPath, description, triggers = []) {
81
90
  const data = readManifest(manifestPath);
82
91
  if (!Array.isArray(data.generated)) data.generated = [];
83
-
84
92
  data.updatedAt = new Date().toISOString();
85
93
  const idx = data.generated.findIndex(s => s.dirPath === dirPath || s.id === skillId);
86
94
  const entry = {
@@ -90,10 +98,8 @@ function recordGeneratedSkill(manifestPath, skillId, dirPath, description, trigg
90
98
  triggers: Array.isArray(triggers) ? triggers : [],
91
99
  generatedAt: new Date().toISOString()
92
100
  };
93
-
94
101
  if (idx !== -1) data.generated[idx] = { ...data.generated[idx], ...entry };
95
102
  else data.generated.push(entry);
96
-
97
103
  writeManifest(manifestPath, data);
98
104
  }
99
105
 
@@ -102,31 +108,21 @@ function removeGeneratedSkill(manifestPath, dirPath) {
102
108
  const data = readManifest(manifestPath);
103
109
  if (!Array.isArray(data.generated)) return;
104
110
  data.generated = data.generated.filter(s => s.dirPath !== dirPath);
105
- writeManifest(manifestPath, data);
111
+ if (!removeManifestArtifactsIfEmpty(manifestPath, data)) writeManifest(manifestPath, data);
106
112
  }
107
113
 
108
- // Removes one skill entry, and - once no skills remain in it - deletes the
109
- // manifest file itself rather than leaving an empty bookkeeping file behind.
110
114
  function removeSkillFromManifest(manifestPath, dirPath) {
111
115
  if (!fs.existsSync(manifestPath)) return;
112
116
  const data = readManifest(manifestPath);
113
117
  data.skills = data.skills.filter(s => s.dirPath !== dirPath);
114
- if (data.skills.length === 0 && (!data.generated || data.generated.length === 0) && (!data.agents || data.agents.length === 0)) {
115
- fs.unlinkSync(manifestPath);
116
- } else {
117
- writeManifest(manifestPath, data);
118
- }
118
+ if (!removeManifestArtifactsIfEmpty(manifestPath, data)) writeManifest(manifestPath, data);
119
119
  }
120
120
 
121
121
  function removeAgentFromManifest(manifestPath, filePath) {
122
122
  if (!fs.existsSync(manifestPath)) return;
123
123
  const data = readManifest(manifestPath);
124
124
  data.agents = data.agents.filter(agent => agent.filePath !== filePath);
125
- if (data.skills.length === 0 && (!data.generated || data.generated.length === 0) && data.agents.length === 0) {
126
- fs.unlinkSync(manifestPath);
127
- } else {
128
- writeManifest(manifestPath, data);
129
- }
125
+ if (!removeManifestArtifactsIfEmpty(manifestPath, data)) writeManifest(manifestPath, data);
130
126
  }
131
127
 
132
128
  module.exports = {
@@ -143,4 +139,4 @@ module.exports = {
143
139
  removeGeneratedSkill,
144
140
  removeSkillFromManifest,
145
141
  removeAgentFromManifest,
146
- };
142
+ };
@@ -0,0 +1,90 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function boundaryError(code, message) {
5
+ const error = new Error(message);
6
+ error.code = code;
7
+ return error;
8
+ }
9
+
10
+ function realpath(p) {
11
+ const resolver = fs.realpathSync.native || fs.realpathSync;
12
+ return resolver(p);
13
+ }
14
+
15
+ // Resolve the deepest existing ancestor first, then append missing segments.
16
+ // This preserves the physical location of an existing junction/symlink even
17
+ // when the final file has not been created yet.
18
+ function canonicalizePath(candidate) {
19
+ const absolute = path.resolve(candidate);
20
+ const missing = [];
21
+ let cursor = absolute;
22
+
23
+ while (true) {
24
+ try {
25
+ fs.lstatSync(cursor);
26
+ return path.join(realpath(cursor), ...missing);
27
+ } catch (error) {
28
+ if (!['ENOENT', 'ENOTDIR'].includes(error.code)) throw error;
29
+ const parent = path.dirname(cursor);
30
+ if (parent === cursor) return path.join(cursor, ...missing);
31
+ missing.unshift(path.basename(cursor));
32
+ cursor = parent;
33
+ }
34
+ }
35
+ }
36
+
37
+ function isWithin(root, candidate) {
38
+ const relative = path.relative(root, candidate);
39
+ return relative === '' || (
40
+ relative !== '..' &&
41
+ !relative.startsWith(`..${path.sep}`) &&
42
+ !path.isAbsolute(relative)
43
+ );
44
+ }
45
+
46
+ // A caller may intentionally choose a symlink as the boundary root. Links
47
+ // below that root are rejected so a later write/delete cannot follow an alias
48
+ // whose target was changed after the initial lexical path check.
49
+ function assertNoLinkComponents(root, candidate) {
50
+ const lexicalRoot = path.resolve(root);
51
+ const lexicalCandidate = path.resolve(candidate);
52
+ const relative = path.relative(lexicalRoot, lexicalCandidate);
53
+ if (relative === '..' || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) return;
54
+
55
+ let cursor = lexicalRoot;
56
+ for (const segment of relative ? relative.split(path.sep) : []) {
57
+ cursor = path.join(cursor, segment);
58
+ try {
59
+ if (fs.lstatSync(cursor).isSymbolicLink()) {
60
+ throw boundaryError('LINK_COMPONENT_IN_BOUNDARY', `Link component is not allowed below boundary: ${cursor}`);
61
+ }
62
+ } catch (error) {
63
+ if (error.code === 'ENOENT' || error.code === 'ENOTDIR') break;
64
+ throw error;
65
+ }
66
+ }
67
+ }
68
+
69
+ function assertContainedPath(root, candidate) {
70
+ if (typeof root !== 'string' || typeof candidate !== 'string') {
71
+ throw boundaryError('INVALID_BOUNDARY_PATH', 'Boundary root and candidate must be strings');
72
+ }
73
+
74
+ assertNoLinkComponents(root, candidate);
75
+ const physicalRoot = canonicalizePath(root);
76
+ const physicalCandidate = canonicalizePath(candidate);
77
+ if (!isWithin(physicalRoot, physicalCandidate)) {
78
+ throw boundaryError(
79
+ 'PATH_OUTSIDE_BOUNDARY',
80
+ `Path escapes boundary: ${candidate} is outside ${root}`
81
+ );
82
+ }
83
+ return { root: physicalRoot, target: physicalCandidate };
84
+ }
85
+
86
+ module.exports = {
87
+ assertContainedPath,
88
+ canonicalizePath,
89
+ isWithin,
90
+ };
@@ -9,23 +9,37 @@ function copyDir(src, dest) {
9
9
  for (const entry of entries) {
10
10
  const srcPath = path.join(src, entry.name);
11
11
  const destPath = path.join(dest, entry.name);
12
- if (entry.isDirectory()) {
13
- copyDir(srcPath, destPath);
14
- } else {
15
- fs.copyFileSync(srcPath, destPath);
16
- }
12
+ if (entry.isDirectory()) copyDir(srcPath, destPath);
13
+ else fs.copyFileSync(srcPath, destPath);
17
14
  }
18
15
  }
19
16
 
17
+ function isLinkPath(p) {
18
+ try { return fs.lstatSync(p).isSymbolicLink(); } catch (e) { return false; }
19
+ }
20
+
21
+ function pathPresent(p) {
22
+ return isLinkPath(p) || fs.existsSync(p);
23
+ }
24
+
25
+ function removePathSafely(p) {
26
+ if (pathPresent(p)) fs.rmSync(p, { recursive: true, force: true });
27
+ }
28
+
29
+ // `.agents/skills/` is the canonical per-scope store used for deduplication.
30
+ // Some hosts consume that path natively (for example Codex project skills),
31
+ // while others link from their own native directories (Continue/Hermes).
32
+ function getCanonicalSkillsDir({ isGlobal, workspaceRoot, userHome }) {
33
+ return path.join(isGlobal ? userHome : workspaceRoot, '.agents', 'skills');
34
+ }
35
+
20
36
  function getAvailableSkills(harnessSourceDir) {
21
37
  const dirs = fs.readdirSync(harnessSourceDir, { withFileTypes: true });
22
38
  const skills = [];
23
39
  for (const dir of dirs) {
24
40
  if (dir.isDirectory() && !dir.name.startsWith('.') && !['bin', 'docs', 'hooks', 'scripts', 'node_modules'].includes(dir.name)) {
25
41
  const skillPath = path.join(harnessSourceDir, dir.name, 'SKILL.md');
26
- if (fs.existsSync(skillPath)) {
27
- skills.push(dir.name);
28
- }
42
+ if (fs.existsSync(skillPath)) skills.push(dir.name);
29
43
  }
30
44
  }
31
45
  return skills.sort();
@@ -42,12 +56,7 @@ function parseFrontmatter(skillMdPath) {
42
56
  const m = yaml.match(new RegExp(`^${key}:\\s*(.*)$`, 'm'));
43
57
  return m ? m[1].trim().replace(/^['"]|['"]$/g, '') : '';
44
58
  };
45
- // Spec-compliant skills carry author/version under `metadata:`; older
46
- // installs (pre-0.3.4 copies already sitting in user workspaces) keep
47
- // them at the top level, so read both and prefer the nested form.
48
59
  const getMeta = (key) => {
49
- // Only keys nested under `metadata:` are indented in frontmatter,
50
- // so matching the indented key directly is unambiguous.
51
60
  const m = yaml.match(new RegExp(`^[ \\t]+${key}:\\s*(.*)$`, 'm'));
52
61
  return m ? m[1].trim().replace(/^['"]|['"]$/g, '') : '';
53
62
  };
@@ -68,24 +77,49 @@ function getSkillInfo(harnessSourceDir, skillDirName) {
68
77
  return { id: skillDirName, name: fm.name || skillDirName, description: fm.description || '' };
69
78
  }
70
79
 
71
- // The one signal that lets uninstall tell "a skill this package shipped"
72
- // apart from anything else living in the same shared skills folder (Cursor/
73
- // Copilot/Codex/Continue skills keep their platform-native location, so it's
74
- // still a shared folder) - including a user's own manually-installed skills
75
- // and self-evolve's locally-generated `skills/generated/*` skills, neither
76
- // of which carry this author string.
77
80
  function isHarnessSkillDir(dirPath) {
78
81
  const fm = parseFrontmatter(path.join(dirPath, 'SKILL.md'));
79
82
  return !!fm && fm.author === manifest.HARNESS_AUTHOR;
80
83
  }
81
84
 
82
- // targetDirs entries: { path, label, manifestPath } - manifestPath is that
83
- // target's own <platform-home>/harness-everything/manifest.json.
84
- function installSkillsToTargets({ chosenSkills, targetDirs, harnessSourceDir, packageVersion }) {
85
+ function ensureCanonicalSkill({ canonicalDir, skillName, harnessSourceDir }) {
86
+ const dest = path.join(canonicalDir, skillName);
87
+ removePathSafely(dest);
88
+ copyDir(path.join(harnessSourceDir, skillName), dest);
89
+ return dest;
90
+ }
91
+
92
+ function linkOrCopySkill({ dest, canonicalSkillDir, harnessSourceDir, skillName, linkMode }) {
93
+ removePathSafely(dest);
94
+ fs.mkdirSync(path.dirname(dest), { recursive: true });
95
+
96
+ if (linkMode === 'copy') {
97
+ copyDir(path.join(harnessSourceDir, skillName), dest);
98
+ return { kind: 'copy' };
99
+ }
100
+
101
+ const symlinkType = process.platform === 'win32' ? 'junction' : 'dir';
102
+ try {
103
+ fs.symlinkSync(canonicalSkillDir, dest, symlinkType);
104
+ return { kind: symlinkType === 'junction' ? 'junction' : 'symlink', canonicalPath: canonicalSkillDir };
105
+ } catch (e) {
106
+ if (linkMode === 'symlink') throw new Error(`Failed to create symlink at ${dest}: ${e.message}`);
107
+ copyDir(path.join(harnessSourceDir, skillName), dest);
108
+ return { kind: 'copy' };
109
+ }
110
+ }
111
+
112
+ function installSkillsToTargets({ chosenSkills, targetDirs, harnessSourceDir, packageVersion, canonicalDir, linkMode = 'auto' }) {
113
+ const useCanonical = !!canonicalDir && linkMode !== 'copy';
114
+ const canonicalSkillDirs = {};
115
+ if (useCanonical) {
116
+ for (const skillName of chosenSkills) {
117
+ canonicalSkillDirs[skillName] = ensureCanonicalSkill({ canonicalDir, skillName, harnessSourceDir });
118
+ }
119
+ }
120
+
85
121
  for (const target of targetDirs) {
86
122
  fs.mkdirSync(target.path, { recursive: true });
87
-
88
- // Copy references directory
89
123
  const refSrc = path.join(harnessSourceDir, 'references');
90
124
  if (fs.existsSync(refSrc)) {
91
125
  const refDest = path.join(path.dirname(target.manifestPath), 'references');
@@ -93,15 +127,22 @@ function installSkillsToTargets({ chosenSkills, targetDirs, harnessSourceDir, pa
93
127
  copyDir(refSrc, refDest);
94
128
  }
95
129
 
130
+ const targetIsCanonical = useCanonical && path.resolve(target.path) === path.resolve(canonicalDir);
96
131
  for (const skillName of chosenSkills) {
97
- const src = path.join(harnessSourceDir, skillName);
98
132
  const dest = path.join(target.path, skillName);
99
- if (fs.existsSync(dest)) {
100
- fs.rmSync(dest, { recursive: true, force: true });
133
+ let result;
134
+ if (!useCanonical) {
135
+ removePathSafely(dest);
136
+ copyDir(path.join(harnessSourceDir, skillName), dest);
137
+ result = { kind: 'copy' };
138
+ } else if (targetIsCanonical) {
139
+ result = { kind: 'copy' };
140
+ } else {
141
+ result = linkOrCopySkill({ dest, canonicalSkillDir: canonicalSkillDirs[skillName], harnessSourceDir, skillName, linkMode });
101
142
  }
102
- copyDir(src, dest);
103
- manifest.recordSkillInstall(target.manifestPath, packageVersion, skillName, dest);
104
- console.log(` ✅ Installed skill: ${target.label}${skillName}/`);
143
+ manifest.recordSkillInstall(target.manifestPath, packageVersion, skillName, dest, result);
144
+ const suffix = result.kind === 'copy' ? '' : ` (${result.kind} -> ${path.relative(path.dirname(dest), result.canonicalPath)})`;
145
+ console.log(` ✅ Installed skill: ${target.label}${skillName}/${suffix}`);
105
146
  }
106
147
  }
107
148
  }
@@ -111,9 +152,7 @@ function installAgentsToTarget({ target, harnessSourceDir, packageVersion }) {
111
152
  if (!fs.existsSync(sourceDir) || !target || !target.path || !target.manifestPath) return;
112
153
 
113
154
  fs.mkdirSync(target.path, { recursive: true });
114
- const trackedPaths = new Set(
115
- (manifest.readManifest(target.manifestPath).agents || []).map(agent => agent.filePath)
116
- );
155
+ const trackedPaths = new Set((manifest.readManifest(target.manifestPath).agents || []).map(agent => agent.filePath));
117
156
  for (const entry of fs.readdirSync(sourceDir, { withFileTypes: true })) {
118
157
  if (!entry.isFile() || !entry.name.endsWith('.md')) continue;
119
158
  const sourcePath = path.join(sourceDir, entry.name);
@@ -143,20 +182,22 @@ function manifestTrackedSkills(manifestPath, scopeLabel) {
143
182
  const data = manifest.readManifest(manifestPath);
144
183
  const results = [];
145
184
  for (const entry of data.skills || []) {
146
- if (fs.existsSync(entry.dirPath) && isHarnessSkillDir(entry.dirPath)) {
147
- results.push({ id: entry.id, scope: scopeLabel, dirPath: entry.dirPath, parentPath: path.dirname(entry.dirPath), manifestPath });
148
- }
185
+ const linked = isLinkPath(entry.dirPath);
186
+ if (!linked && (!fs.existsSync(entry.dirPath) || !isHarnessSkillDir(entry.dirPath))) continue;
187
+ results.push({
188
+ id: entry.id,
189
+ scope: scopeLabel,
190
+ dirPath: entry.dirPath,
191
+ parentPath: path.dirname(entry.dirPath),
192
+ manifestPath,
193
+ canonicalPath: entry.canonicalPath || null,
194
+ });
149
195
  }
150
196
  return results;
151
197
  }
152
198
 
153
- // Returns every skill this package can currently account for, scoped local +
154
- // global. Never lists a directory just because it happens to live under a
155
- // known skills folder - only manifest-recorded installs (or, as a fallback
156
- // for pre-manifest / pre-reorg installs, directories that still self-identify
157
- // via the author marker) qualify. This is what keeps "uninstall skills" from
158
- // ever touching a skill this package didn't put there.
159
- function getInstalledSkills(workspaceRoot, userHome) {
199
+ function getInstalledSkills(workspaceRoot, userHome, opts = {}) {
200
+ const includeLegacy = opts.includeLegacy !== false;
160
201
  const results = [];
161
202
  const globalAgentsDir = path.join(userHome, '.agents');
162
203
 
@@ -166,30 +207,32 @@ function getInstalledSkills(workspaceRoot, userHome) {
166
207
  { home: path.join(workspaceRoot, '.github'), scope: 'local (Copilot)' },
167
208
  { home: path.join(workspaceRoot, '.codex'), scope: 'local (Codex)' },
168
209
  { home: path.join(workspaceRoot, '.continue'), scope: 'local (Continue)' },
169
- { home: path.join(userHome, '.claude'), scope: 'global (Claude)' },
210
+ { home: path.join(workspaceRoot, '.hermes'), scope: 'local (Hermes)' },
211
+ { home: path.join(userHome, '.claude'), scope: 'global' },
170
212
  { home: globalAgentsDir, scope: 'global' },
213
+ { home: path.join(userHome, '.continue'), scope: 'global' },
214
+ { home: path.join(userHome, '.hermes'), scope: 'global' },
171
215
  ];
172
216
  for (const { home, scope } of manifestHomes) {
173
217
  results.push(...manifestTrackedSkills(manifest.getManifestPath(home), scope));
174
218
  }
175
219
 
176
- // Legacy fallback for installs that predate per-platform manifests (or the
177
- // old self-invented .harness/ local root, or - for Codex specifically - an
178
- // earlier version's mistaken `.agents/skills` target; Codex's real project
179
- // skills directory is `.codex/skills/`): scan the raw directories
180
- // directly, but only ever list an entry that still self-identifies via the
181
- // author marker - never a blind directory listing.
220
+ if (!includeLegacy) return results;
221
+
182
222
  const legacyDirs = [
183
223
  { path: path.join(workspaceRoot, '.harness', 'skills'), scope: 'local (legacy .harness)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.claude')) },
184
224
  { path: path.join(workspaceRoot, '.claude', 'harness-everything', 'skills'), scope: 'local (Claude legacy erroneous path)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.claude')) },
185
225
  { path: path.join(workspaceRoot, '.cursor', 'skills'), scope: 'local (Cursor)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.cursor')) },
186
226
  { path: path.join(workspaceRoot, '.github', 'skills'), scope: 'local (Copilot)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.github')) },
187
- { path: path.join(workspaceRoot, '.codex', 'skills'), scope: 'local (Codex)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.codex')) },
188
- { path: path.join(workspaceRoot, '.agents', 'skills'), scope: 'local (Codex, legacy .agents path)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.codex')) },
227
+ { path: path.join(workspaceRoot, '.codex', 'skills'), scope: 'local (Codex legacy .codex path)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.codex')) },
228
+ { path: path.join(workspaceRoot, '.agents', 'skills'), scope: 'local (shared Agent Skills)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.codex')) },
189
229
  { path: path.join(workspaceRoot, '.continue', 'skills'), scope: 'local (Continue)', manifestPath: manifest.getManifestPath(path.join(workspaceRoot, '.continue')) },
190
230
  { path: path.join(globalAgentsDir, 'skills'), scope: 'global', manifestPath: manifest.getManifestPath(globalAgentsDir) },
231
+ { path: path.join(userHome, '.continue', 'skills'), scope: 'global', manifestPath: manifest.getManifestPath(path.join(userHome, '.continue')) },
232
+ { path: path.join(userHome, '.hermes', 'skills'), scope: 'global', manifestPath: manifest.getManifestPath(path.join(userHome, '.hermes')) },
191
233
  ];
192
- const known = new Set(results.map(r => r.dirPath));
234
+
235
+ const known = new Set(results.flatMap(r => r.canonicalPath ? [r.dirPath, r.canonicalPath] : [r.dirPath]));
193
236
  for (const item of legacyDirs) {
194
237
  if (!fs.existsSync(item.path)) continue;
195
238
  try {
@@ -204,7 +247,7 @@ function getInstalledSkills(workspaceRoot, userHome) {
204
247
  }
205
248
  }
206
249
  } catch (e) {
207
- // ignore unreadable dirs
250
+ // Ignore unreadable fallback directories.
208
251
  }
209
252
  }
210
253
  return results;
@@ -220,30 +263,38 @@ function getInstalledAgents(workspaceRoot, userHome) {
220
263
  const manifestPath = manifest.getManifestPath(home);
221
264
  const data = manifest.readManifest(manifestPath);
222
265
  for (const entry of data.agents || []) {
223
- if (entry.filePath && fs.existsSync(entry.filePath)) {
224
- results.push({ ...entry, scope, manifestPath });
225
- }
266
+ if (entry.filePath && fs.existsSync(entry.filePath)) results.push({ ...entry, scope, manifestPath });
226
267
  }
227
268
  }
228
269
  return results;
229
270
  }
230
271
 
231
- function removeSkill(entry) {
232
- if (fs.existsSync(entry.dirPath)) {
233
- fs.rmSync(entry.dirPath, { recursive: true, force: true });
234
- }
235
- if (entry.manifestPath) {
236
- manifest.removeSkillFromManifest(entry.manifestPath, entry.dirPath);
272
+ function removeSkill(entry, ctx = {}) {
273
+ const wasLink = isLinkPath(entry.dirPath);
274
+ removePathSafely(entry.dirPath);
275
+ if (entry.manifestPath) manifest.removeSkillFromManifest(entry.manifestPath, entry.dirPath);
276
+
277
+ if (!ctx.workspaceRoot || !ctx.userHome) return;
278
+
279
+ if (wasLink && entry.canonicalPath) {
280
+ const stillInUse = getInstalledSkills(ctx.workspaceRoot, ctx.userHome, { includeLegacy: false }).some(
281
+ s => s.dirPath === entry.canonicalPath || s.canonicalPath === entry.canonicalPath
282
+ );
283
+ if (!stillInUse) removePathSafely(entry.canonicalPath);
284
+ } else if (!wasLink) {
285
+ const dependents = getInstalledSkills(ctx.workspaceRoot, ctx.userHome, { includeLegacy: false }).filter(
286
+ s => s.canonicalPath === entry.dirPath
287
+ );
288
+ for (const dep of dependents) {
289
+ removePathSafely(dep.dirPath);
290
+ if (dep.manifestPath) manifest.removeSkillFromManifest(dep.manifestPath, dep.dirPath);
291
+ }
237
292
  }
238
293
  }
239
294
 
240
295
  function removeAgent(entry) {
241
- if (entry.filePath && fs.existsSync(entry.filePath)) {
242
- fs.unlinkSync(entry.filePath);
243
- }
244
- if (entry.manifestPath) {
245
- manifest.removeAgentFromManifest(entry.manifestPath, entry.filePath);
246
- }
296
+ if (entry.filePath && fs.existsSync(entry.filePath)) fs.unlinkSync(entry.filePath);
297
+ if (entry.manifestPath) manifest.removeAgentFromManifest(entry.manifestPath, entry.filePath);
247
298
  }
248
299
 
249
300
  module.exports = {
@@ -251,10 +302,13 @@ module.exports = {
251
302
  getAvailableSkills,
252
303
  getSkillInfo,
253
304
  isHarnessSkillDir,
305
+ isLinkPath,
306
+ pathPresent,
307
+ getCanonicalSkillsDir,
254
308
  installSkillsToTargets,
255
309
  installAgentsToTarget,
256
310
  getInstalledSkills,
257
311
  getInstalledAgents,
258
312
  removeSkill,
259
313
  removeAgent,
260
- };
314
+ };