freeharness 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 (375) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +108 -0
  3. package/README.md +134 -0
  4. package/canonical/HARVEST.yaml +858 -0
  5. package/canonical/PROVENANCE.yaml +740 -0
  6. package/canonical/agents/README.md +95 -0
  7. package/canonical/agents/agentic-architect.md +18 -0
  8. package/canonical/agents/database-reviewer.md +41 -0
  9. package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
  10. package/canonical/agents/pr-reviewer.md +96 -0
  11. package/canonical/agents/python-reviewer.md +55 -0
  12. package/canonical/agents/report-formatter.md +19 -0
  13. package/canonical/agents/security-reviewer.md +53 -0
  14. package/canonical/agents/test-writer.md +34 -0
  15. package/canonical/commands/fh-context.md +37 -0
  16. package/canonical/evals/promptfoo.redteam.yaml +108 -0
  17. package/canonical/hooks/cost-prices.json +14 -0
  18. package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
  19. package/canonical/hooks/freeharness-config-guard.mjs +162 -0
  20. package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
  21. package/canonical/hooks/freeharness-converge.mjs +227 -0
  22. package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
  23. package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
  24. package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
  25. package/canonical/hooks/freeharness-precompact.mjs +323 -0
  26. package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
  27. package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
  28. package/canonical/hooks/freeharness-session-start +583 -0
  29. package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
  30. package/canonical/hooks/hooks.claude-code.json +17 -0
  31. package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
  32. package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
  33. package/canonical/hooks/hooks.converge.claude-code.json +15 -0
  34. package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
  35. package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
  36. package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
  37. package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
  38. package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
  39. package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
  40. package/canonical/mcp/servers.json +20 -0
  41. package/canonical/openspec/config.base.yaml +89 -0
  42. package/canonical/openspec/schema.spec-driven.yaml +277 -0
  43. package/canonical/openspec/templates/data-contract.md +36 -0
  44. package/canonical/openspec/templates/design.md +84 -0
  45. package/canonical/openspec/templates/eval-plan.md +33 -0
  46. package/canonical/openspec/templates/follow-ups.md +2 -0
  47. package/canonical/openspec/templates/proposal.md +45 -0
  48. package/canonical/openspec/templates/spec.md +42 -0
  49. package/canonical/openspec/templates/tasks.md +38 -0
  50. package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
  51. package/canonical/profiles/local-llamacpp.json +27 -0
  52. package/canonical/profiles/local-ollama.json +20 -0
  53. package/canonical/profiles/mcp.json +91 -0
  54. package/canonical/rules/CLAUDE.md +78 -0
  55. package/canonical/rules/project-CLAUDE.template.md +62 -0
  56. package/canonical/rules/routing.md +20 -0
  57. package/canonical/rules/safety.md +41 -0
  58. package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
  59. package/canonical/skills/agent-evaluation/SKILL.md +102 -0
  60. package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
  61. package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
  62. package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
  63. package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
  64. package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
  65. package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
  66. package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
  67. package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
  68. package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
  69. package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
  70. package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
  71. package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
  72. package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
  73. package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
  74. package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
  75. package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
  76. package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
  77. package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
  78. package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
  79. package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
  80. package/canonical/skills/agentic-architecture/SKILL.md +41 -0
  81. package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
  82. package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
  83. package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
  84. package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
  85. package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
  86. package/canonical/skills/code-review/SKILL.md +52 -0
  87. package/canonical/skills/code-review/evals/cases.yaml +197 -0
  88. package/canonical/skills/git-workflow/SKILL.md +41 -0
  89. package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
  90. package/canonical/skills/local-code/SKILL.md +24 -0
  91. package/canonical/skills/local-code/evals/cases.yaml +85 -0
  92. package/canonical/skills/local-code/scripts/query_llama.py +68 -0
  93. package/canonical/skills/report-formatting/SKILL.md +62 -0
  94. package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
  95. package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
  96. package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
  97. package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
  98. package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
  99. package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
  100. package/canonical/skills/report-formatting/reference/authoring.md +66 -0
  101. package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
  102. package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
  103. package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
  104. package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
  105. package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
  106. package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
  107. package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
  108. package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
  109. package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
  110. package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
  111. package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
  112. package/canonical/skills/report-formatting/scripts/package.json +17 -0
  113. package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
  114. package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
  115. package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
  116. package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
  117. package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
  118. package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
  119. package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
  120. package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
  121. package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
  122. package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
  123. package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
  124. package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
  125. package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
  126. package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
  127. package/canonical/skills/systematic-debugging/SKILL.md +44 -0
  128. package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
  129. package/canonical/skills/test-driven-development/SKILL.md +42 -0
  130. package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
  131. package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
  132. package/canonical/skills/verification-before-completion/SKILL.md +53 -0
  133. package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
  134. package/dist/adapters/content/language-lint.d.ts +46 -0
  135. package/dist/adapters/content/language-lint.js +191 -0
  136. package/dist/adapters/harness/claude-code.d.ts +57 -0
  137. package/dist/adapters/harness/claude-code.js +385 -0
  138. package/dist/adapters/harness/index.d.ts +3 -0
  139. package/dist/adapters/harness/index.js +17 -0
  140. package/dist/adapters/harness/opencode.d.ts +7 -0
  141. package/dist/adapters/harness/opencode.js +166 -0
  142. package/dist/adapters/harness/plugin.d.ts +22 -0
  143. package/dist/adapters/harness/plugin.js +257 -0
  144. package/dist/adapters/memory/doctor.d.ts +480 -0
  145. package/dist/adapters/memory/doctor.js +1217 -0
  146. package/dist/adapters/memory/vendored.d.ts +150 -0
  147. package/dist/adapters/memory/vendored.js +487 -0
  148. package/dist/adapters/package/node.d.ts +9 -0
  149. package/dist/adapters/package/node.js +20 -0
  150. package/dist/adapters/prompt/readline.d.ts +19 -0
  151. package/dist/adapters/prompt/readline.js +53 -0
  152. package/dist/adapters/sync/diff.d.ts +43 -0
  153. package/dist/adapters/sync/diff.js +380 -0
  154. package/dist/cli/cleanup.d.ts +86 -0
  155. package/dist/cli/cleanup.js +382 -0
  156. package/dist/cli/cost.d.ts +304 -0
  157. package/dist/cli/cost.js +501 -0
  158. package/dist/cli/doctor.d.ts +205 -0
  159. package/dist/cli/doctor.js +654 -0
  160. package/dist/cli/executor.d.ts +5 -0
  161. package/dist/cli/executor.js +48 -0
  162. package/dist/cli/plugin-validate.d.ts +37 -0
  163. package/dist/cli/plugin-validate.js +256 -0
  164. package/dist/cli/prefix.d.ts +68 -0
  165. package/dist/cli/prefix.js +218 -0
  166. package/dist/cli/profile.d.ts +170 -0
  167. package/dist/cli/profile.js +285 -0
  168. package/dist/cli/runner.d.ts +10 -0
  169. package/dist/cli/runner.js +27 -0
  170. package/dist/cli/uninstall.d.ts +65 -0
  171. package/dist/cli/uninstall.js +147 -0
  172. package/dist/index.d.ts +8 -0
  173. package/dist/index.js +989 -0
  174. package/dist/infra/dogfood.d.ts +31 -0
  175. package/dist/infra/dogfood.js +51 -0
  176. package/dist/infra/fsutil.d.ts +40 -0
  177. package/dist/infra/fsutil.js +143 -0
  178. package/dist/infra/manifest.d.ts +76 -0
  179. package/dist/infra/manifest.js +92 -0
  180. package/dist/infra/paths.d.ts +19 -0
  181. package/dist/infra/paths.js +74 -0
  182. package/dist/infra/routing.d.ts +4 -0
  183. package/dist/infra/routing.js +7 -0
  184. package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
  185. package/node_modules/@freeharness/core/dist/context.js +1 -0
  186. package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
  187. package/node_modules/@freeharness/core/dist/index.js +6 -0
  188. package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
  189. package/node_modules/@freeharness/core/dist/planner.js +18 -0
  190. package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
  191. package/node_modules/@freeharness/core/dist/ports.js +1 -0
  192. package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
  193. package/node_modules/@freeharness/core/dist/registry.js +124 -0
  194. package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
  195. package/node_modules/@freeharness/core/dist/tiers.js +99 -0
  196. package/node_modules/@freeharness/core/package.json +34 -0
  197. package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
  198. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
  199. package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
  200. package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
  201. package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
  202. package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
  203. package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
  204. package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
  205. package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
  206. package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
  207. package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
  208. package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
  209. package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
  210. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
  211. package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
  212. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
  213. package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
  214. package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
  215. package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
  216. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
  217. package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
  218. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
  219. package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
  220. package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
  221. package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
  222. package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
  223. package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
  224. package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
  225. package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
  226. package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
  227. package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
  228. package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
  229. package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
  230. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
  231. package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
  232. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
  233. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
  234. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
  235. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
  236. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
  237. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
  238. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
  239. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
  240. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
  241. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
  242. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
  243. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
  244. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
  245. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
  246. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
  247. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
  248. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
  249. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
  250. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
  251. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
  252. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
  253. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
  254. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
  255. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
  256. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
  257. package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
  258. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
  259. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
  260. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
  261. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
  262. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
  263. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
  264. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
  265. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
  266. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
  267. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
  268. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
  269. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
  270. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
  271. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
  272. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
  273. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
  274. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
  275. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
  276. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
  277. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
  278. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
  279. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
  280. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
  281. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
  282. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
  283. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
  284. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
  285. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
  286. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
  287. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
  288. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
  289. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
  290. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
  291. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
  292. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
  293. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
  294. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
  295. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
  296. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
  297. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
  298. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
  299. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
  300. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
  301. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
  302. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
  303. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
  304. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
  305. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
  306. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
  307. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
  308. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
  309. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
  310. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
  311. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
  312. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
  313. package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
  314. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
  315. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
  316. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
  317. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
  318. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
  319. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
  320. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
  321. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
  322. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
  323. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
  324. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
  325. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
  326. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
  327. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
  328. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
  329. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
  330. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
  331. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
  332. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
  333. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
  334. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
  335. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
  336. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
  337. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
  338. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
  339. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
  340. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
  341. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
  342. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
  343. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
  344. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
  345. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
  346. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
  347. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
  348. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
  349. package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
  350. package/node_modules/@freeharness/sdd/package.json +57 -0
  351. package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
  352. package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
  353. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
  354. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
  355. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
  356. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
  357. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
  358. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
  359. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
  360. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
  361. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
  362. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
  363. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
  364. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
  365. package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
  366. package/package.json +70 -0
  367. package/provenance/canonical.PROVENANCE.yaml +740 -0
  368. package/provenance/claude-mem.LICENSE.upstream +202 -0
  369. package/provenance/memory.PROVENANCE.yaml +399 -0
  370. package/provenance/sdd.PROVENANCE.yaml +175 -0
  371. package/vendor-licenses/caveman.LICENSE +27 -0
  372. package/vendor-licenses/deepseek-harness.LICENSE +21 -0
  373. package/vendor-licenses/ecc.LICENSE +21 -0
  374. package/vendor-licenses/pi.LICENSE +21 -0
  375. package/vendor-licenses/superpowers.LICENSE +21 -0
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Command Invocation
3
+ *
4
+ * How a tool spells an OpenSpec command has two parts, and only one of them
5
+ * can be read off the file the adapter writes:
6
+ *
7
+ * - The *name* comes from the file. `.../commands/opsx/<id>.md` is namespaced
8
+ * by its directory, so the tool registers `opsx:<id>` (Claude Code, Gemini,
9
+ * Crush, ...). `.../commands/opsx-<id>.md` names the command with the
10
+ * filename, so the tool registers `opsx-<id>` (Cursor, GitHub Copilot,
11
+ * OpenCode, ...).
12
+ * - The *prefix* is the tool's own and cannot be derived. Almost every tool
13
+ * uses `/`; Amazon Q loads these files into its prompt library, which is
14
+ * invoked with `@` (`@opsx-propose`), so its adapter declares that prefix.
15
+ *
16
+ * Deriving the name from `getFilePath` keeps generated cross-references and
17
+ * onboarding hints in step with the files OpenSpec actually writes. A
18
+ * hand-maintained list drifted before: only OpenCode was rewritten when the
19
+ * hyphen form was introduced (#727), and Cursor still advertised `/opsx:`
20
+ * commands its palette never registered (#1307). Carrying the prefix as
21
+ * adapter metadata rather than inferring it keeps the one tool that does not
22
+ * use a slash from being advertised as if it did.
23
+ */
24
+ import type { ToolCommandAdapter } from './types.js';
25
+ export type CommandInvocationStyle = 'namespaced' | 'flat';
26
+ /**
27
+ * Everything needed to spell one of a tool's OpenSpec commands.
28
+ */
29
+ export interface CommandInvocation {
30
+ /** How the command file names the command. */
31
+ style: CommandInvocationStyle;
32
+ /** What the user types before the name, e.g. `/` or Amazon Q's `@`. */
33
+ prefix: string;
34
+ }
35
+ /** The form these docs, command bodies, and skill templates are authored in. */
36
+ export declare const CANONICAL_INVOCATION: CommandInvocation;
37
+ /**
38
+ * Classifies a generated command file by the name the tool will answer to.
39
+ *
40
+ * The test is the filename, not the directory: an `opsx-` prefix means the
41
+ * filename is the command. Every other shape is treated as namespaced, which
42
+ * is what all seven `opsx/<id>.*` adapters need. An adapter that neither
43
+ * prefixes the filename nor nests under `opsx/` would land here too — none
44
+ * does, and the registry-wide test in invocation.test.ts fails if one appears.
45
+ *
46
+ * @param commandFilePath - Path returned by an adapter's `getFilePath`
47
+ * @returns 'flat' when the filename carries the `opsx-` prefix, otherwise
48
+ * 'namespaced'
49
+ */
50
+ export declare function getInvocationStyleForPath(commandFilePath: string): CommandInvocationStyle;
51
+ /**
52
+ * Resolves how a tool's generated commands are invoked: the name from the
53
+ * files its adapter writes, the prefix from the adapter's own declaration.
54
+ *
55
+ * @param adapter - The tool-specific command adapter
56
+ * @returns The invocation shared by every command that adapter generates
57
+ */
58
+ export declare function getInvocationForAdapter(adapter: ToolCommandAdapter): CommandInvocation;
59
+ /**
60
+ * Spells one command the way the tool registers it.
61
+ *
62
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
63
+ * @param commandId - The command identifier (e.g. 'apply')
64
+ * @returns What the user types, e.g. `/opsx:apply`, `/opsx-apply`, `@opsx-apply`
65
+ */
66
+ export declare function formatCommandInvocation(invocation: CommandInvocation, commandId: string): string;
67
+ /**
68
+ * Whether a tool's invocation differs from the canonical `/opsx:<id>` that
69
+ * command bodies and skill templates are authored in — that is, whether
70
+ * generated text has to be rewritten for that tool at all.
71
+ */
72
+ export declare function needsInvocationRewrite(invocation: CommandInvocation): boolean;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Command Invocation
3
+ *
4
+ * How a tool spells an OpenSpec command has two parts, and only one of them
5
+ * can be read off the file the adapter writes:
6
+ *
7
+ * - The *name* comes from the file. `.../commands/opsx/<id>.md` is namespaced
8
+ * by its directory, so the tool registers `opsx:<id>` (Claude Code, Gemini,
9
+ * Crush, ...). `.../commands/opsx-<id>.md` names the command with the
10
+ * filename, so the tool registers `opsx-<id>` (Cursor, GitHub Copilot,
11
+ * OpenCode, ...).
12
+ * - The *prefix* is the tool's own and cannot be derived. Almost every tool
13
+ * uses `/`; Amazon Q loads these files into its prompt library, which is
14
+ * invoked with `@` (`@opsx-propose`), so its adapter declares that prefix.
15
+ *
16
+ * Deriving the name from `getFilePath` keeps generated cross-references and
17
+ * onboarding hints in step with the files OpenSpec actually writes. A
18
+ * hand-maintained list drifted before: only OpenCode was rewritten when the
19
+ * hyphen form was introduced (#727), and Cursor still advertised `/opsx:`
20
+ * commands its palette never registered (#1307). Carrying the prefix as
21
+ * adapter metadata rather than inferring it keeps the one tool that does not
22
+ * use a slash from being advertised as if it did.
23
+ */
24
+ import path from 'path';
25
+ /** The form these docs, command bodies, and skill templates are authored in. */
26
+ export const CANONICAL_INVOCATION = { style: 'namespaced', prefix: '/' };
27
+ /**
28
+ * Classifies a generated command file by the name the tool will answer to.
29
+ *
30
+ * The test is the filename, not the directory: an `opsx-` prefix means the
31
+ * filename is the command. Every other shape is treated as namespaced, which
32
+ * is what all seven `opsx/<id>.*` adapters need. An adapter that neither
33
+ * prefixes the filename nor nests under `opsx/` would land here too — none
34
+ * does, and the registry-wide test in invocation.test.ts fails if one appears.
35
+ *
36
+ * @param commandFilePath - Path returned by an adapter's `getFilePath`
37
+ * @returns 'flat' when the filename carries the `opsx-` prefix, otherwise
38
+ * 'namespaced'
39
+ */
40
+ export function getInvocationStyleForPath(commandFilePath) {
41
+ return path.basename(commandFilePath).startsWith('opsx-') ? 'flat' : 'namespaced';
42
+ }
43
+ /**
44
+ * Resolves how a tool's generated commands are invoked: the name from the
45
+ * files its adapter writes, the prefix from the adapter's own declaration.
46
+ *
47
+ * @param adapter - The tool-specific command adapter
48
+ * @returns The invocation shared by every command that adapter generates
49
+ */
50
+ export function getInvocationForAdapter(adapter) {
51
+ return {
52
+ // Any command id works: every adapter applies one naming rule to all of them.
53
+ style: getInvocationStyleForPath(adapter.getFilePath('explore')),
54
+ prefix: adapter.invocationPrefix ?? CANONICAL_INVOCATION.prefix,
55
+ };
56
+ }
57
+ /**
58
+ * Spells one command the way the tool registers it.
59
+ *
60
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
61
+ * @param commandId - The command identifier (e.g. 'apply')
62
+ * @returns What the user types, e.g. `/opsx:apply`, `/opsx-apply`, `@opsx-apply`
63
+ */
64
+ export function formatCommandInvocation(invocation, commandId) {
65
+ const separator = invocation.style === 'namespaced' ? ':' : '-';
66
+ return `${invocation.prefix}opsx${separator}${commandId}`;
67
+ }
68
+ /**
69
+ * Whether a tool's invocation differs from the canonical `/opsx:<id>` that
70
+ * command bodies and skill templates are authored in — that is, whether
71
+ * generated text has to be rewritten for that tool at all.
72
+ */
73
+ export function needsInvocationRewrite(invocation) {
74
+ return (invocation.style !== CANONICAL_INVOCATION.style ||
75
+ invocation.prefix !== CANONICAL_INVOCATION.prefix);
76
+ }
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Command Adapter Registry
3
+ *
4
+ * Centralized registry for tool command adapters.
5
+ *
6
+ * FreeHarness trim: vendored from OpenSpec with the adapter set reduced to the
7
+ * two harnesses FreeHarness targets (Claude Code + OpenCode). The upstream
8
+ * registry registered 29 adapters; the other 27 imports/registrations were
9
+ * removed. Registry API is otherwise unchanged.
10
+ */
11
+ import type { ToolCommandAdapter } from './types.js';
12
+ /**
13
+ * Registry for looking up tool command adapters.
14
+ */
15
+ export declare class CommandAdapterRegistry {
16
+ private static adapters;
17
+ /**
18
+ * Register a tool command adapter.
19
+ * @param adapter - The adapter to register
20
+ */
21
+ static register(adapter: ToolCommandAdapter): void;
22
+ /**
23
+ * Get an adapter by tool ID.
24
+ * @param toolId - The tool identifier (e.g., 'claude', 'opencode')
25
+ * @returns The adapter or undefined if not registered
26
+ */
27
+ static get(toolId: string): ToolCommandAdapter | undefined;
28
+ /**
29
+ * Get all registered adapters.
30
+ * @returns Array of all registered adapters
31
+ */
32
+ static getAll(): ToolCommandAdapter[];
33
+ /**
34
+ * Check if an adapter is registered for a tool.
35
+ * @param toolId - The tool identifier
36
+ * @returns True if an adapter exists
37
+ */
38
+ static has(toolId: string): boolean;
39
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Command Adapter Registry
3
+ *
4
+ * Centralized registry for tool command adapters.
5
+ *
6
+ * FreeHarness trim: vendored from OpenSpec with the adapter set reduced to the
7
+ * two harnesses FreeHarness targets (Claude Code + OpenCode). The upstream
8
+ * registry registered 29 adapters; the other 27 imports/registrations were
9
+ * removed. Registry API is otherwise unchanged.
10
+ */
11
+ import { claudeAdapter } from './adapters/claude.js';
12
+ import { opencodeAdapter } from './adapters/opencode.js';
13
+ /**
14
+ * Registry for looking up tool command adapters.
15
+ */
16
+ export class CommandAdapterRegistry {
17
+ static adapters = new Map();
18
+ // Static initializer - register built-in adapters (trimmed to claude + opencode)
19
+ static {
20
+ CommandAdapterRegistry.register(claudeAdapter);
21
+ CommandAdapterRegistry.register(opencodeAdapter);
22
+ }
23
+ /**
24
+ * Register a tool command adapter.
25
+ * @param adapter - The adapter to register
26
+ */
27
+ static register(adapter) {
28
+ CommandAdapterRegistry.adapters.set(adapter.toolId, adapter);
29
+ }
30
+ /**
31
+ * Get an adapter by tool ID.
32
+ * @param toolId - The tool identifier (e.g., 'claude', 'opencode')
33
+ * @returns The adapter or undefined if not registered
34
+ */
35
+ static get(toolId) {
36
+ return CommandAdapterRegistry.adapters.get(toolId);
37
+ }
38
+ /**
39
+ * Get all registered adapters.
40
+ * @returns Array of all registered adapters
41
+ */
42
+ static getAll() {
43
+ return Array.from(CommandAdapterRegistry.adapters.values());
44
+ }
45
+ /**
46
+ * Check if an adapter is registered for a tool.
47
+ * @param toolId - The tool identifier
48
+ * @returns True if an adapter exists
49
+ */
50
+ static has(toolId) {
51
+ return CommandAdapterRegistry.adapters.has(toolId);
52
+ }
53
+ }
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Command Generation Types
3
+ *
4
+ * Tool-agnostic interfaces for command generation.
5
+ * These types separate "what to generate" from "how to format it".
6
+ */
7
+ /**
8
+ * Tool-agnostic command data.
9
+ * Represents the content of a command without any tool-specific formatting.
10
+ */
11
+ export interface CommandContent {
12
+ /** Command identifier (e.g., 'explore', 'apply', 'new') */
13
+ id: string;
14
+ /** Human-readable name (e.g., 'OpenSpec Explore') */
15
+ name: string;
16
+ /** Brief description of command purpose */
17
+ description: string;
18
+ /** Grouping category (e.g., 'Workflow') */
19
+ category: string;
20
+ /** Array of tag strings */
21
+ tags: string[];
22
+ /** The command instruction content (body text) */
23
+ body: string;
24
+ }
25
+ /**
26
+ * Per-tool formatting strategy.
27
+ * Each AI tool implements this interface to handle its specific file path
28
+ * and frontmatter format requirements.
29
+ */
30
+ export interface ToolCommandAdapter {
31
+ /** Tool identifier matching AIToolOption.value (e.g., 'claude', 'cursor') */
32
+ toolId: string;
33
+ /**
34
+ * Returns the file path for a command.
35
+ * @param commandId - The command identifier (e.g., 'explore')
36
+ * @returns Path from project root (e.g., '.claude/commands/opsx/explore.md').
37
+ * May be absolute for tools with global-scoped command files.
38
+ */
39
+ getFilePath(commandId: string): string;
40
+ /**
41
+ * What the user types before the command name, when it is not the default
42
+ * `/`. Amazon Q loads these files into its prompt library, which is invoked
43
+ * with `@` (`@opsx-propose`), so its adapter sets '@'. The name itself is
44
+ * still derived from getFilePath — see invocation.ts.
45
+ */
46
+ invocationPrefix?: string;
47
+ /**
48
+ * Formats the complete file content including frontmatter.
49
+ * @param content - The tool-agnostic command content
50
+ * @returns Complete file content ready to write
51
+ */
52
+ formatFile(content: CommandContent): string;
53
+ }
54
+ /**
55
+ * Result of generating a command file.
56
+ */
57
+ export interface GeneratedCommand {
58
+ /** File path from project root, or absolute for global-scoped command files */
59
+ path: string;
60
+ /** Complete file content (frontmatter + body) */
61
+ fileContent: string;
62
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Command Generation Types
3
+ *
4
+ * Tool-agnostic interfaces for command generation.
5
+ * These types separate "what to generate" from "how to format it".
6
+ */
7
+ export {};
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Shared YAML frontmatter helpers for command adapters.
3
+ *
4
+ * Several tool adapters emit YAML frontmatter and need to escape
5
+ * user-facing strings (name, description, category, tags) so the
6
+ * generated file stays valid YAML. This module centralizes that logic
7
+ * so the behavior is identical across adapters and fixed in one place.
8
+ */
9
+ /**
10
+ * Escapes a string value for safe YAML output.
11
+ *
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
24
+ *
25
+ * @param value - The raw string to embed in YAML frontmatter.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
27
+ */
28
+ export declare function escapeYamlValue(value: string): string;
29
+ /**
30
+ * Formats a tags array as a YAML array with proper escaping.
31
+ *
32
+ * @param tags - Array of tag strings.
33
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
34
+ */
35
+ export declare function formatTagsArray(tags: string[]): string;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Shared YAML frontmatter helpers for command adapters.
3
+ *
4
+ * Several tool adapters emit YAML frontmatter and need to escape
5
+ * user-facing strings (name, description, category, tags) so the
6
+ * generated file stays valid YAML. This module centralizes that logic
7
+ * so the behavior is identical across adapters and fixed in one place.
8
+ */
9
+ /**
10
+ * Escapes a string value for safe YAML output.
11
+ *
12
+ * Always emits a double-quoted scalar. Quoting unconditionally keeps the
13
+ * value a string no matter what it holds: an unquoted `true`, `null` or
14
+ * `123` would round-trip as a boolean, null or number, and an unquoted
15
+ * value opening with a block indicator (`|`, `>`) or containing `: `
16
+ * is not valid YAML at all.
17
+ *
18
+ * Inside the quotes it escapes everything that cannot appear verbatim in a
19
+ * double-quoted scalar: backslash, double quote, line feed, carriage
20
+ * return, and the non-printable characters YAML's `c-printable` production
21
+ * excludes (C0 controls, DEL and C1 controls). Lenient parsers accept a raw
22
+ * control byte, but strict ones reject the document outright, so escaping
23
+ * them here keeps the generated file portable across every tool's parser.
24
+ *
25
+ * @param value - The raw string to embed in YAML frontmatter.
26
+ * @returns The value as an escaped, double-quoted YAML scalar.
27
+ */
28
+ export function escapeYamlValue(value) {
29
+ const escaped = value
30
+ .replace(/\\/g, '\\\\')
31
+ .replace(/"/g, '\\"')
32
+ .replace(/\n/g, '\\n')
33
+ .replace(/\r/g, '\\r')
34
+ // Remaining non-printables have no dedicated escape; emit them as \xHH.
35
+ .replace(/[\x00-\x08\x0b\x0c\x0e-\x1f\x7f-\x9f]/g, (char) => `\\x${char.charCodeAt(0).toString(16).padStart(2, '0')}`);
36
+ return `"${escaped}"`;
37
+ }
38
+ /**
39
+ * Formats a tags array as a YAML array with proper escaping.
40
+ *
41
+ * @param tags - Array of tag strings.
42
+ * @returns Formatted YAML array string, e.g. '[tag1, tag2]'.
43
+ */
44
+ export function formatTagsArray(tags) {
45
+ const escapedTags = tags.map((tag) => escapeYamlValue(tag));
46
+ return `[${escapedTags.join(', ')}]`;
47
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Command Reference Utilities
3
+ *
4
+ * Utilities for transforming command references to tool-specific formats.
5
+ *
6
+ * FreeHarness trim: reduced to the single transform the vendored generator and
7
+ * initProject need. Upstream also carried skill-reference transformers for
8
+ * Codex ($name), Kimi (/skill:name), Rovo Dev (natural language) and the
9
+ * capability-aware getTransformerForTool selector. FreeHarness targets only
10
+ * Claude Code and OpenCode, so those code paths (and the command-surface.ts
11
+ * dependency they pulled in) were dropped. The invocation for a claude/opencode
12
+ * target is derived directly from its adapter in init.ts.
13
+ */
14
+ import type { CommandInvocation } from './command-generation/invocation.js';
15
+ /**
16
+ * Rewrites the canonical `/opsx:<command>` references that command bodies and
17
+ * skill templates are authored with into the form the target tool actually
18
+ * registers — `/opsx-<command>` for tools that name the command by filename
19
+ * (e.g. OpenCode). Claude Code keeps the canonical `/opsx:<command>` form, so
20
+ * for it this is a no-op the caller skips via needsInvocationRewrite().
21
+ *
22
+ * Only known command ids are rewritten, so a mistyped or invented
23
+ * `/opsx:<something>` is left as written rather than silently reshaped into a
24
+ * command that does not exist either.
25
+ *
26
+ * @param text - The text containing command references
27
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
28
+ * @returns Text with command references spelled the tool's way
29
+ *
30
+ * @example
31
+ * transformCommandInvocations('/opsx:new', { style: 'flat', prefix: '/' }) // '/opsx-new'
32
+ */
33
+ export declare function transformCommandInvocations(text: string, invocation: CommandInvocation): string;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Command Reference Utilities
3
+ *
4
+ * Utilities for transforming command references to tool-specific formats.
5
+ *
6
+ * FreeHarness trim: reduced to the single transform the vendored generator and
7
+ * initProject need. Upstream also carried skill-reference transformers for
8
+ * Codex ($name), Kimi (/skill:name), Rovo Dev (natural language) and the
9
+ * capability-aware getTransformerForTool selector. FreeHarness targets only
10
+ * Claude Code and OpenCode, so those code paths (and the command-surface.ts
11
+ * dependency they pulled in) were dropped. The invocation for a claude/opencode
12
+ * target is derived directly from its adapter in init.ts.
13
+ */
14
+ import { formatCommandInvocation } from './command-generation/invocation.js';
15
+ /**
16
+ * Rewrites the canonical `/opsx:<command>` references that command bodies and
17
+ * skill templates are authored with into the form the target tool actually
18
+ * registers — `/opsx-<command>` for tools that name the command by filename
19
+ * (e.g. OpenCode). Claude Code keeps the canonical `/opsx:<command>` form, so
20
+ * for it this is a no-op the caller skips via needsInvocationRewrite().
21
+ *
22
+ * Only known command ids are rewritten, so a mistyped or invented
23
+ * `/opsx:<something>` is left as written rather than silently reshaped into a
24
+ * command that does not exist either.
25
+ *
26
+ * @param text - The text containing command references
27
+ * @param invocation - The tool's invocation, from getInvocationForAdapter()
28
+ * @returns Text with command references spelled the tool's way
29
+ *
30
+ * @example
31
+ * transformCommandInvocations('/opsx:new', { style: 'flat', prefix: '/' }) // '/opsx-new'
32
+ */
33
+ export function transformCommandInvocations(text, invocation) {
34
+ return text.replace(/\/opsx:([a-z-]+)/g, (match, commandId) => commandId in COMMAND_TO_SKILL_NAME
35
+ ? formatCommandInvocation(invocation, commandId)
36
+ : match);
37
+ }
38
+ /**
39
+ * Maps command short names to their skill names. Used to gate which
40
+ * `/opsx:<id>` references are rewritten (unknown ids are left untouched).
41
+ */
42
+ const COMMAND_TO_SKILL_NAME = {
43
+ 'explore': 'openspec-explore',
44
+ 'new': 'openspec-new-change',
45
+ 'continue': 'openspec-continue-change',
46
+ 'apply': 'openspec-apply-change',
47
+ 'update': 'openspec-update-change',
48
+ 'ff': 'openspec-ff-change',
49
+ 'sync': 'openspec-sync-specs',
50
+ 'archive': 'openspec-archive-change',
51
+ 'bulk-archive': 'openspec-bulk-archive-change',
52
+ 'verify': 'openspec-verify-change',
53
+ 'onboard': 'openspec-onboard',
54
+ 'propose': 'openspec-propose',
55
+ };
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Pre-approved tools for generated skills and slash commands, emitted as the
3
+ * `allowed-tools` frontmatter field (Agent Skills standard for SKILL.md;
4
+ * same field for Claude Code slash commands). Scoped to the OpenSpec CLI so
5
+ * agents that honor it stop prompting on each `openspec` call; the field
6
+ * only pre-approves — it does not restrict — so any other tool a skill or
7
+ * command needs (Read, Write, arbitrary Bash for builds/tests) stays
8
+ * available under the user's normal permission settings. Tools that don't
9
+ * recognize the field ignore it.
10
+ */
11
+ export declare const OPENSPEC_CLI_ALLOWED_TOOLS = "Bash(openspec:*)";
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Pre-approved tools for generated skills and slash commands, emitted as the
3
+ * `allowed-tools` frontmatter field (Agent Skills standard for SKILL.md;
4
+ * same field for Claude Code slash commands). Scoped to the OpenSpec CLI so
5
+ * agents that honor it stop prompting on each `openspec` call; the field
6
+ * only pre-approves — it does not restrict — so any other tool a skill or
7
+ * command needs (Read, Write, arbitrary Bash for builds/tests) stays
8
+ * available under the user's normal permission settings. Tools that don't
9
+ * recognize the field ignore it.
10
+ */
11
+ export const OPENSPEC_CLI_ALLOWED_TOOLS = 'Bash(openspec:*)';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Skill Generation Utilities
3
+ *
4
+ * Shared utilities for generating skill and command files.
5
+ */
6
+ import { getOpsxExploreCommandTemplate, type SkillTemplate } from '../templates/skill-templates.js';
7
+ import type { CommandContent } from '../command-generation/index.js';
8
+ /**
9
+ * Skill template with directory name and workflow ID mapping.
10
+ */
11
+ export interface SkillTemplateEntry {
12
+ template: SkillTemplate;
13
+ dirName: string;
14
+ workflowId: string;
15
+ }
16
+ /**
17
+ * Command template with ID mapping.
18
+ */
19
+ export interface CommandTemplateEntry {
20
+ template: ReturnType<typeof getOpsxExploreCommandTemplate>;
21
+ id: string;
22
+ }
23
+ /**
24
+ * Gets skill templates with their directory names, optionally filtered by workflow IDs.
25
+ *
26
+ * @param workflowFilter - If provided, only return templates whose workflowId is in this array
27
+ */
28
+ export declare function getSkillTemplates(workflowFilter?: readonly string[]): SkillTemplateEntry[];
29
+ /**
30
+ * Gets command templates with their IDs, optionally filtered by workflow IDs.
31
+ *
32
+ * @param workflowFilter - If provided, only return templates whose id is in this array
33
+ */
34
+ export declare function getCommandTemplates(workflowFilter?: readonly string[]): CommandTemplateEntry[];
35
+ /**
36
+ * Converts command templates to CommandContent array, optionally filtered by workflow IDs.
37
+ *
38
+ * @param workflowFilter - If provided, only return contents whose id is in this array
39
+ */
40
+ export declare function getCommandContents(workflowFilter?: readonly string[]): CommandContent[];
41
+ /**
42
+ * Generates skill file content with YAML frontmatter.
43
+ *
44
+ * @param template - The skill template
45
+ * @param generatedByVersion - The OpenSpec version to embed in the file
46
+ * @param transformInstructions - Optional callback to transform the instructions content
47
+ */
48
+ export declare function generateSkillContent(template: SkillTemplate, generatedByVersion: string, transformInstructions?: (instructions: string) => string): string;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Skill Generation Utilities
3
+ *
4
+ * Shared utilities for generating skill and command files.
5
+ */
6
+ import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getUpdateChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getArchiveChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOnboardSkillTemplate, getOpsxProposeSkillTemplate, getOpsxExploreCommandTemplate, getOpsxNewCommandTemplate, getOpsxContinueCommandTemplate, getOpsxApplyCommandTemplate, getOpsxUpdateCommandTemplate, getOpsxFfCommandTemplate, getOpsxSyncCommandTemplate, getOpsxArchiveCommandTemplate, getOpsxBulkArchiveCommandTemplate, getOpsxVerifyCommandTemplate, getOpsxOnboardCommandTemplate, getOpsxProposeCommandTemplate, } from '../templates/skill-templates.js';
7
+ import { OPENSPEC_CLI_ALLOWED_TOOLS } from './allowed-tools.js';
8
+ /**
9
+ * Gets skill templates with their directory names, optionally filtered by workflow IDs.
10
+ *
11
+ * @param workflowFilter - If provided, only return templates whose workflowId is in this array
12
+ */
13
+ export function getSkillTemplates(workflowFilter) {
14
+ const all = [
15
+ { template: getExploreSkillTemplate(), dirName: 'openspec-explore', workflowId: 'explore' },
16
+ { template: getNewChangeSkillTemplate(), dirName: 'openspec-new-change', workflowId: 'new' },
17
+ { template: getContinueChangeSkillTemplate(), dirName: 'openspec-continue-change', workflowId: 'continue' },
18
+ { template: getApplyChangeSkillTemplate(), dirName: 'openspec-apply-change', workflowId: 'apply' },
19
+ { template: getUpdateChangeSkillTemplate(), dirName: 'openspec-update-change', workflowId: 'update' },
20
+ { template: getFfChangeSkillTemplate(), dirName: 'openspec-ff-change', workflowId: 'ff' },
21
+ { template: getSyncSpecsSkillTemplate(), dirName: 'openspec-sync-specs', workflowId: 'sync' },
22
+ { template: getArchiveChangeSkillTemplate(), dirName: 'openspec-archive-change', workflowId: 'archive' },
23
+ { template: getBulkArchiveChangeSkillTemplate(), dirName: 'openspec-bulk-archive-change', workflowId: 'bulk-archive' },
24
+ { template: getVerifyChangeSkillTemplate(), dirName: 'openspec-verify-change', workflowId: 'verify' },
25
+ { template: getOnboardSkillTemplate(), dirName: 'openspec-onboard', workflowId: 'onboard' },
26
+ { template: getOpsxProposeSkillTemplate(), dirName: 'openspec-propose', workflowId: 'propose' },
27
+ ];
28
+ if (!workflowFilter)
29
+ return all;
30
+ const filterSet = new Set(workflowFilter);
31
+ return all.filter(entry => filterSet.has(entry.workflowId));
32
+ }
33
+ /**
34
+ * Gets command templates with their IDs, optionally filtered by workflow IDs.
35
+ *
36
+ * @param workflowFilter - If provided, only return templates whose id is in this array
37
+ */
38
+ export function getCommandTemplates(workflowFilter) {
39
+ const all = [
40
+ { template: getOpsxExploreCommandTemplate(), id: 'explore' },
41
+ { template: getOpsxNewCommandTemplate(), id: 'new' },
42
+ { template: getOpsxContinueCommandTemplate(), id: 'continue' },
43
+ { template: getOpsxApplyCommandTemplate(), id: 'apply' },
44
+ { template: getOpsxUpdateCommandTemplate(), id: 'update' },
45
+ { template: getOpsxFfCommandTemplate(), id: 'ff' },
46
+ { template: getOpsxSyncCommandTemplate(), id: 'sync' },
47
+ { template: getOpsxArchiveCommandTemplate(), id: 'archive' },
48
+ { template: getOpsxBulkArchiveCommandTemplate(), id: 'bulk-archive' },
49
+ { template: getOpsxVerifyCommandTemplate(), id: 'verify' },
50
+ { template: getOpsxOnboardCommandTemplate(), id: 'onboard' },
51
+ { template: getOpsxProposeCommandTemplate(), id: 'propose' },
52
+ ];
53
+ if (!workflowFilter)
54
+ return all;
55
+ const filterSet = new Set(workflowFilter);
56
+ return all.filter(entry => filterSet.has(entry.id));
57
+ }
58
+ /**
59
+ * Converts command templates to CommandContent array, optionally filtered by workflow IDs.
60
+ *
61
+ * @param workflowFilter - If provided, only return contents whose id is in this array
62
+ */
63
+ export function getCommandContents(workflowFilter) {
64
+ const commandTemplates = getCommandTemplates(workflowFilter);
65
+ return commandTemplates.map(({ template, id }) => ({
66
+ id,
67
+ name: template.name,
68
+ description: template.description,
69
+ category: template.category,
70
+ tags: template.tags,
71
+ body: template.content,
72
+ }));
73
+ }
74
+ /**
75
+ * Generates skill file content with YAML frontmatter.
76
+ *
77
+ * @param template - The skill template
78
+ * @param generatedByVersion - The OpenSpec version to embed in the file
79
+ * @param transformInstructions - Optional callback to transform the instructions content
80
+ */
81
+ export function generateSkillContent(template, generatedByVersion, transformInstructions) {
82
+ const instructions = transformInstructions
83
+ ? transformInstructions(template.instructions)
84
+ : template.instructions;
85
+ return `---
86
+ name: ${template.name}
87
+ description: ${template.description}
88
+ allowed-tools: ${OPENSPEC_CLI_ALLOWED_TOOLS}
89
+ license: ${template.license || 'MIT'}
90
+ compatibility: ${template.compatibility || 'Requires openspec CLI.'}
91
+ metadata:
92
+ author: ${template.metadata?.author || 'openspec'}
93
+ version: "${template.metadata?.version || '1.0'}"
94
+ generatedBy: "${generatedByVersion}"
95
+ ---
96
+
97
+ ${instructions}
98
+ `;
99
+ }