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.
- package/LICENSE +21 -0
- package/NOTICE +108 -0
- package/README.md +134 -0
- package/canonical/HARVEST.yaml +858 -0
- package/canonical/PROVENANCE.yaml +740 -0
- package/canonical/agents/README.md +95 -0
- package/canonical/agents/agentic-architect.md +18 -0
- package/canonical/agents/database-reviewer.md +41 -0
- package/canonical/agents/explorer-ai-engineer-analyst.md +65 -0
- package/canonical/agents/pr-reviewer.md +96 -0
- package/canonical/agents/python-reviewer.md +55 -0
- package/canonical/agents/report-formatter.md +19 -0
- package/canonical/agents/security-reviewer.md +53 -0
- package/canonical/agents/test-writer.md +34 -0
- package/canonical/commands/fh-context.md +37 -0
- package/canonical/evals/promptfoo.redteam.yaml +108 -0
- package/canonical/hooks/cost-prices.json +14 -0
- package/canonical/hooks/freeharness-auto-memory.mjs +158 -0
- package/canonical/hooks/freeharness-config-guard.mjs +162 -0
- package/canonical/hooks/freeharness-context-monitor.mjs +198 -0
- package/canonical/hooks/freeharness-converge.mjs +227 -0
- package/canonical/hooks/freeharness-cost-tracker.mjs +1027 -0
- package/canonical/hooks/freeharness-memory-guard.mjs +57 -0
- package/canonical/hooks/freeharness-output-pruner.mjs +333 -0
- package/canonical/hooks/freeharness-precompact.mjs +323 -0
- package/canonical/hooks/freeharness-repeat-tool.mjs +208 -0
- package/canonical/hooks/freeharness-security-guidance.mjs +164 -0
- package/canonical/hooks/freeharness-session-start +583 -0
- package/canonical/hooks/hooks.auto-memory.claude-code.json +16 -0
- package/canonical/hooks/hooks.claude-code.json +17 -0
- package/canonical/hooks/hooks.config-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.context-monitor.claude-code.json +15 -0
- package/canonical/hooks/hooks.converge.claude-code.json +15 -0
- package/canonical/hooks/hooks.cost-tracker.claude-code.json +37 -0
- package/canonical/hooks/hooks.memory-guard.claude-code.json +16 -0
- package/canonical/hooks/hooks.output-pruner.claude-code.json +16 -0
- package/canonical/hooks/hooks.precompact.claude-code.json +15 -0
- package/canonical/hooks/hooks.repeat-tool.claude-code.json +25 -0
- package/canonical/hooks/hooks.security-guidance.claude-code.json +16 -0
- package/canonical/mcp/servers.json +20 -0
- package/canonical/openspec/config.base.yaml +89 -0
- package/canonical/openspec/schema.spec-driven.yaml +277 -0
- package/canonical/openspec/templates/data-contract.md +36 -0
- package/canonical/openspec/templates/design.md +84 -0
- package/canonical/openspec/templates/eval-plan.md +33 -0
- package/canonical/openspec/templates/follow-ups.md +2 -0
- package/canonical/openspec/templates/proposal.md +45 -0
- package/canonical/openspec/templates/spec.md +42 -0
- package/canonical/openspec/templates/tasks.md +38 -0
- package/canonical/profiles/local-llamacpp.LOCAL-MODELS.md +47 -0
- package/canonical/profiles/local-llamacpp.json +27 -0
- package/canonical/profiles/local-ollama.json +20 -0
- package/canonical/profiles/mcp.json +91 -0
- package/canonical/rules/CLAUDE.md +78 -0
- package/canonical/rules/project-CLAUDE.template.md +62 -0
- package/canonical/rules/routing.md +20 -0
- package/canonical/rules/safety.md +41 -0
- package/canonical/settings/settings.cache-hygiene.claude-code.json +5 -0
- package/canonical/skills/agent-evaluation/SKILL.md +102 -0
- package/canonical/skills/agent-evaluation/assets/evaluation_report_template.md +206 -0
- package/canonical/skills/agent-evaluation/evals/cases.yaml +106 -0
- package/canonical/skills/agent-evaluation/references/dataset-preparation.md +351 -0
- package/canonical/skills/agent-evaluation/references/scorers-constraints.md +165 -0
- package/canonical/skills/agent-evaluation/references/scorers.md +431 -0
- package/canonical/skills/agent-evaluation/references/setup-guide.md +252 -0
- package/canonical/skills/agent-evaluation/references/tracing-integration.md +164 -0
- package/canonical/skills/agent-evaluation/references/troubleshooting.md +514 -0
- package/canonical/skills/agent-evaluation/scripts/analyze_results.py +462 -0
- package/canonical/skills/agent-evaluation/scripts/create_dataset_template.py +382 -0
- package/canonical/skills/agent-evaluation/scripts/list_datasets.py +273 -0
- package/canonical/skills/agent-evaluation/scripts/run_evaluation_template.py +309 -0
- package/canonical/skills/agent-evaluation/scripts/setup_mlflow.py +353 -0
- package/canonical/skills/agent-evaluation/scripts/utils/__init__.py +27 -0
- package/canonical/skills/agent-evaluation/scripts/utils/env_validation.py +123 -0
- package/canonical/skills/agent-evaluation/scripts/utils/tracing_utils.py +108 -0
- package/canonical/skills/agent-evaluation/scripts/validate_agent_tracing.py +148 -0
- package/canonical/skills/agent-evaluation/scripts/validate_auth.py +240 -0
- package/canonical/skills/agent-evaluation/scripts/validate_environment.py +185 -0
- package/canonical/skills/agent-evaluation/scripts/validate_tracing_runtime.py +318 -0
- package/canonical/skills/agentic-architecture/SKILL.md +41 -0
- package/canonical/skills/agentic-architecture/evals/cases.yaml +94 -0
- package/canonical/skills/agentic-architecture/reference/context-engineering.md +75 -0
- package/canonical/skills/agentic-architecture/reference/patterns.md +76 -0
- package/canonical/skills/agentic-architecture/reference/reliability-observability.md +94 -0
- package/canonical/skills/agentic-architecture/reference/review-framework.md +59 -0
- package/canonical/skills/code-review/SKILL.md +52 -0
- package/canonical/skills/code-review/evals/cases.yaml +197 -0
- package/canonical/skills/git-workflow/SKILL.md +41 -0
- package/canonical/skills/git-workflow/evals/cases.yaml +92 -0
- package/canonical/skills/local-code/SKILL.md +24 -0
- package/canonical/skills/local-code/evals/cases.yaml +85 -0
- package/canonical/skills/local-code/scripts/query_llama.py +68 -0
- package/canonical/skills/report-formatting/SKILL.md +62 -0
- package/canonical/skills/report-formatting/evals/cases.yaml +83 -0
- package/canonical/skills/report-formatting/reference/ARCHITECTURE.md +135 -0
- package/canonical/skills/report-formatting/reference/HELPERS.md +120 -0
- package/canonical/skills/report-formatting/reference/PPTX.md +136 -0
- package/canonical/skills/report-formatting/reference/RELEASE.md +99 -0
- package/canonical/skills/report-formatting/reference/TEMPLATES.md +48 -0
- package/canonical/skills/report-formatting/reference/authoring.md +66 -0
- package/canonical/skills/report-formatting/scripts/architecture-template.md +271 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-logo.png +0 -0
- package/canonical/skills/report-formatting/scripts/assets/claro-wordmark.svg +1 -0
- package/canonical/skills/report-formatting/scripts/build-architecture.js +57 -0
- package/canonical/skills/report-formatting/scripts/build-md-claro.js +224 -0
- package/canonical/skills/report-formatting/scripts/build-release.js +51 -0
- package/canonical/skills/report-formatting/scripts/check-env.js +58 -0
- package/canonical/skills/report-formatting/scripts/docmodel.js +283 -0
- package/canonical/skills/report-formatting/scripts/example-build.js +119 -0
- package/canonical/skills/report-formatting/scripts/example_build_ArchitectureReview_docx.js +195 -0
- package/canonical/skills/report-formatting/scripts/example_build_ExecutiveReport_docx.js +114 -0
- package/canonical/skills/report-formatting/scripts/package.json +17 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_StatusReport_pptx.py +223 -0
- package/canonical/skills/report-formatting/scripts/pptx/example_build_WeeklyStatus_pptx.py +245 -0
- package/canonical/skills/report-formatting/scripts/pptx/pptx_office.py +144 -0
- package/canonical/skills/report-formatting/scripts/pptx/requirements.txt +7 -0
- package/canonical/skills/report-formatting/scripts/pptx/status_report_blocks.py +193 -0
- package/canonical/skills/report-formatting/scripts/pptx/theme_claro_pptx.py +473 -0
- package/canonical/skills/report-formatting/scripts/release-template.md +80 -0
- package/canonical/skills/report-formatting/scripts/render-mermaid.js +105 -0
- package/canonical/skills/report-formatting/scripts/theme-claro.js +403 -0
- package/canonical/skills/subagent-driven-development/SKILL.md +60 -0
- package/canonical/skills/subagent-driven-development/evals/cases.yaml +208 -0
- package/canonical/skills/subagent-driven-development/reference/brief.md +91 -0
- package/canonical/skills/subagent-driven-development/reference/handoff.md +118 -0
- package/canonical/skills/subagent-driven-development/scripts/validate-handoff.mjs +850 -0
- package/canonical/skills/systematic-debugging/SKILL.md +44 -0
- package/canonical/skills/systematic-debugging/evals/cases.yaml +90 -0
- package/canonical/skills/test-driven-development/SKILL.md +42 -0
- package/canonical/skills/test-driven-development/evals/cases.yaml +86 -0
- package/canonical/skills/test-driven-development/reference/writing-good-tests.md +52 -0
- package/canonical/skills/verification-before-completion/SKILL.md +53 -0
- package/canonical/skills/verification-before-completion/evals/cases.yaml +107 -0
- package/dist/adapters/content/language-lint.d.ts +46 -0
- package/dist/adapters/content/language-lint.js +191 -0
- package/dist/adapters/harness/claude-code.d.ts +57 -0
- package/dist/adapters/harness/claude-code.js +385 -0
- package/dist/adapters/harness/index.d.ts +3 -0
- package/dist/adapters/harness/index.js +17 -0
- package/dist/adapters/harness/opencode.d.ts +7 -0
- package/dist/adapters/harness/opencode.js +166 -0
- package/dist/adapters/harness/plugin.d.ts +22 -0
- package/dist/adapters/harness/plugin.js +257 -0
- package/dist/adapters/memory/doctor.d.ts +480 -0
- package/dist/adapters/memory/doctor.js +1217 -0
- package/dist/adapters/memory/vendored.d.ts +150 -0
- package/dist/adapters/memory/vendored.js +487 -0
- package/dist/adapters/package/node.d.ts +9 -0
- package/dist/adapters/package/node.js +20 -0
- package/dist/adapters/prompt/readline.d.ts +19 -0
- package/dist/adapters/prompt/readline.js +53 -0
- package/dist/adapters/sync/diff.d.ts +43 -0
- package/dist/adapters/sync/diff.js +380 -0
- package/dist/cli/cleanup.d.ts +86 -0
- package/dist/cli/cleanup.js +382 -0
- package/dist/cli/cost.d.ts +304 -0
- package/dist/cli/cost.js +501 -0
- package/dist/cli/doctor.d.ts +205 -0
- package/dist/cli/doctor.js +654 -0
- package/dist/cli/executor.d.ts +5 -0
- package/dist/cli/executor.js +48 -0
- package/dist/cli/plugin-validate.d.ts +37 -0
- package/dist/cli/plugin-validate.js +256 -0
- package/dist/cli/prefix.d.ts +68 -0
- package/dist/cli/prefix.js +218 -0
- package/dist/cli/profile.d.ts +170 -0
- package/dist/cli/profile.js +285 -0
- package/dist/cli/runner.d.ts +10 -0
- package/dist/cli/runner.js +27 -0
- package/dist/cli/uninstall.d.ts +65 -0
- package/dist/cli/uninstall.js +147 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +989 -0
- package/dist/infra/dogfood.d.ts +31 -0
- package/dist/infra/dogfood.js +51 -0
- package/dist/infra/fsutil.d.ts +40 -0
- package/dist/infra/fsutil.js +143 -0
- package/dist/infra/manifest.d.ts +76 -0
- package/dist/infra/manifest.js +92 -0
- package/dist/infra/paths.d.ts +19 -0
- package/dist/infra/paths.js +74 -0
- package/dist/infra/routing.d.ts +4 -0
- package/dist/infra/routing.js +7 -0
- package/node_modules/@freeharness/core/dist/context.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/context.js +1 -0
- package/node_modules/@freeharness/core/dist/index.d.ts +5 -0
- package/node_modules/@freeharness/core/dist/index.js +6 -0
- package/node_modules/@freeharness/core/dist/planner.d.ts +13 -0
- package/node_modules/@freeharness/core/dist/planner.js +18 -0
- package/node_modules/@freeharness/core/dist/ports.d.ts +90 -0
- package/node_modules/@freeharness/core/dist/ports.js +1 -0
- package/node_modules/@freeharness/core/dist/registry.d.ts +41 -0
- package/node_modules/@freeharness/core/dist/registry.js +124 -0
- package/node_modules/@freeharness/core/dist/tiers.d.ts +30 -0
- package/node_modules/@freeharness/core/dist/tiers.js +99 -0
- package/node_modules/@freeharness/core/package.json +34 -0
- package/node_modules/@freeharness/sdd/PROVENANCE.yaml +175 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.d.ts +2 -0
- package/node_modules/@freeharness/sdd/dist/src/bin/openspec.js +166 -0
- package/node_modules/@freeharness/sdd/dist/src/index.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/src/index.js +11 -0
- package/node_modules/@freeharness/sdd/dist/src/init.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/src/init.js +190 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/root-resolver.js +32 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.d.ts +81 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/archive.js +483 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/context.js +48 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.d.ts +57 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/follow-up.js +279 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.d.ts +67 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/instructions.js +460 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.d.ts +5 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/list.js +95 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/new-change.js +150 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.d.ts +4 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/schemas.js +23 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.d.ts +56 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/shared.js +140 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/status.js +85 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.d.ts +6 -0
- package/node_modules/@freeharness/sdd/dist/src/shim/validate.js +229 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.d.ts +40 -0
- package/node_modules/@freeharness/sdd/dist/src/validate-change.js +114 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.d.ts +24 -0
- package/node_modules/@freeharness/sdd/dist/src/validate.js +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.d.ts +130 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/apply/specs-apply.js +981 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.d.ts +46 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-metadata.js +128 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.d.ts +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/change-status-policy.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.d.ts +50 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/file-system.js +394 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/global-config.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.d.ts +71 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/graph.js +164 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/index.js +21 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.d.ts +102 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/instruction-loader.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/outputs.js +138 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.d.ts +82 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/resolver.js +333 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/schema.js +110 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/state.js +32 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/task-progress.js +149 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/engine/types.js +49 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/claude.js +31 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.d.ts +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/index.js +10 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/adapters/opencode.js +26 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.d.ts +28 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/generator.js +41 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts +23 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js +25 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/invocation.js +76 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/registry.js +53 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.d.ts +62 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/types.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/yaml.js +47 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.d.ts +33 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-references.js +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.d.ts +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/allowed-tools.js +11 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.d.ts +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/shared/skill-generation.js +99 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/skill-templates.js +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.d.ts +18 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/types.js +4 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.d.ts +19 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/apply-change.js +207 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/archive-change.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/bulk-archive-change.js +673 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/continue-change.js +230 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/explore.js +550 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/feedback.js +107 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/ff-change.js +228 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/new-change.js +147 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/onboard.js +571 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/propose.js +322 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.d.ts +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/store-selection.js +7 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/sync-specs.js +518 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/update-change.js +176 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.d.ts +9 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/templates/workflows/verify-change.js +344 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/constants.js +54 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.d.ts +35 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/delta-resolution.js +171 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.d.ts +27 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/change-parser.js +210 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.d.ts +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/code-fence.js +48 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.d.ts +22 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/markdown-parser.js +186 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.d.ts +65 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-blocks.js +409 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.d.ts +55 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/requirement-text.js +98 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.d.ts +8 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js +77 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts +44 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.js +116 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts +12 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.js +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts +72 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js +30 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.d.ts +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/index.js +3 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.js +14 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.d.ts +39 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/spec-discovery.js +114 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.d.ts +45 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-lines.js +105 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.d.ts +15 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/task-numbering.js +56 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.d.ts +17 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/types.js +1 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.d.ts +94 -0
- package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/validator.js +756 -0
- package/node_modules/@freeharness/sdd/package.json +57 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/LICENSE.upstream +22 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/schema.upstream.yaml +232 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/README.md +19 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-apply-change/SKILL.md +187 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-archive-change/SKILL.md +181 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-bulk-archive-change/SKILL.md +338 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-continue-change/SKILL.md +117 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-explore/SKILL.md +342 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-ff-change/SKILL.md +116 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-new-change/SKILL.md +76 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-onboard/SKILL.md +560 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-propose/SKILL.md +162 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-sync-specs/SKILL.md +261 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-update-change/SKILL.md +90 -0
- package/node_modules/@freeharness/sdd/vendor/openspec/assets/skills/openspec-verify-change/SKILL.md +174 -0
- package/package.json +70 -0
- package/provenance/canonical.PROVENANCE.yaml +740 -0
- package/provenance/claude-mem.LICENSE.upstream +202 -0
- package/provenance/memory.PROVENANCE.yaml +399 -0
- package/provenance/sdd.PROVENANCE.yaml +175 -0
- package/vendor-licenses/caveman.LICENSE +27 -0
- package/vendor-licenses/deepseek-harness.LICENSE +21 -0
- package/vendor-licenses/ecc.LICENSE +21 -0
- package/vendor-licenses/pi.LICENSE +21 -0
- package/vendor-licenses/superpowers.LICENSE +21 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Store-free, PATH-free `openspec` CLI shim for FreeHarness.
|
|
3
|
+
//
|
|
4
|
+
// A commander-free argv parser dispatching the subcommands the /opsx skills
|
|
5
|
+
// shell out to, over the vendored engine + validation slices. It matches
|
|
6
|
+
// upstream's flags and single-document `--json` output contract so the skills
|
|
7
|
+
// parse it unchanged. Subcommands that were dropped with the store (feedback,
|
|
8
|
+
// store ...) are not registered; `archive` is present but deferred (see
|
|
9
|
+
// src/shim/archive.ts).
|
|
10
|
+
//
|
|
11
|
+
// Root resolution is store-free: walk up from the cwd to the nearest openspec/
|
|
12
|
+
// directory (src/root-resolver.ts). Its PARENT is the project root passed to the
|
|
13
|
+
// engine. `context` may run without a root (to report no_openspec_root); `new
|
|
14
|
+
// change` falls back to the cwd as an implicit root; every other command
|
|
15
|
+
// requires a root.
|
|
16
|
+
import * as path from 'node:path';
|
|
17
|
+
import { findOpenspecDir } from '../root-resolver.js';
|
|
18
|
+
import { statusHandler } from '../shim/status.js';
|
|
19
|
+
import { schemasHandler } from '../shim/schemas.js';
|
|
20
|
+
import { listHandler } from '../shim/list.js';
|
|
21
|
+
import { instructionsHandler } from '../shim/instructions.js';
|
|
22
|
+
import { contextHandler } from '../shim/context.js';
|
|
23
|
+
import { validateHandler } from '../shim/validate.js';
|
|
24
|
+
import { newChangeHandler } from '../shim/new-change.js';
|
|
25
|
+
import { archiveHandler } from '../shim/archive.js';
|
|
26
|
+
import { followUpAddHandler, followUpClaimHandler, followUpListHandler } from '../shim/follow-up.js';
|
|
27
|
+
/** Flags that consume the following token as their value. */
|
|
28
|
+
const VALUE_FLAGS = new Set(['--change', '--schema', '--description', '--sort', '--store', '--type', '--from', '--by']);
|
|
29
|
+
function parseArgs(argv) {
|
|
30
|
+
const positionals = [];
|
|
31
|
+
const flags = {};
|
|
32
|
+
for (let i = 0; i < argv.length; i++) {
|
|
33
|
+
const token = argv[i];
|
|
34
|
+
if (token.startsWith('--')) {
|
|
35
|
+
const eq = token.indexOf('=');
|
|
36
|
+
if (eq !== -1) {
|
|
37
|
+
flags[token.slice(0, eq)] = token.slice(eq + 1);
|
|
38
|
+
}
|
|
39
|
+
else if (VALUE_FLAGS.has(token)) {
|
|
40
|
+
flags[token] = argv[++i] ?? '';
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
flags[token] = true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
positionals.push(token);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return { positionals, flags };
|
|
51
|
+
}
|
|
52
|
+
function projectRootFrom(startDir) {
|
|
53
|
+
const openspecDir = findOpenspecDir(startDir);
|
|
54
|
+
return openspecDir ? path.dirname(openspecDir) : null;
|
|
55
|
+
}
|
|
56
|
+
function requireRoot(cwd) {
|
|
57
|
+
const root = projectRootFrom(cwd);
|
|
58
|
+
if (!root) {
|
|
59
|
+
throw new Error('No OpenSpec root found. Run this inside a project with an openspec/ directory.');
|
|
60
|
+
}
|
|
61
|
+
return root;
|
|
62
|
+
}
|
|
63
|
+
async function main() {
|
|
64
|
+
const [command, ...rest] = process.argv.slice(2);
|
|
65
|
+
const cwd = process.cwd();
|
|
66
|
+
if (!command || command === '--help' || command === '-h') {
|
|
67
|
+
printUsage();
|
|
68
|
+
return command ? 0 : 1;
|
|
69
|
+
}
|
|
70
|
+
if (command === '--version' || command === '-v') {
|
|
71
|
+
console.log('freeharness-sdd-shim');
|
|
72
|
+
return 0;
|
|
73
|
+
}
|
|
74
|
+
const { positionals, flags } = parseArgs(rest);
|
|
75
|
+
const json = flags['--json'] === true;
|
|
76
|
+
switch (command) {
|
|
77
|
+
case 'status':
|
|
78
|
+
return statusHandler(requireRoot(cwd), {
|
|
79
|
+
change: flags['--change'],
|
|
80
|
+
schema: flags['--schema'],
|
|
81
|
+
json,
|
|
82
|
+
});
|
|
83
|
+
case 'instructions':
|
|
84
|
+
return instructionsHandler(requireRoot(cwd), positionals[0], {
|
|
85
|
+
change: flags['--change'],
|
|
86
|
+
schema: flags['--schema'],
|
|
87
|
+
json,
|
|
88
|
+
});
|
|
89
|
+
case 'schemas':
|
|
90
|
+
return schemasHandler(projectRootFrom(cwd) ?? '', { json });
|
|
91
|
+
case 'list':
|
|
92
|
+
return await listHandler(requireRoot(cwd), {
|
|
93
|
+
json,
|
|
94
|
+
sort: flags['--sort'] ?? 'recent',
|
|
95
|
+
});
|
|
96
|
+
case 'context':
|
|
97
|
+
return contextHandler(projectRootFrom(cwd), { json });
|
|
98
|
+
case 'validate':
|
|
99
|
+
return await validateHandler(requireRoot(cwd), positionals[0], {
|
|
100
|
+
specs: flags['--specs'] === true,
|
|
101
|
+
strict: flags['--strict'] === true,
|
|
102
|
+
json,
|
|
103
|
+
});
|
|
104
|
+
case 'new': {
|
|
105
|
+
// `openspec new change <id>`
|
|
106
|
+
if (positionals[0] !== 'change') {
|
|
107
|
+
throw new Error(`Unknown subcommand 'new ${positionals[0] ?? ''}'. Did you mean 'new change <id>'?`);
|
|
108
|
+
}
|
|
109
|
+
const root = projectRootFrom(cwd) ?? cwd; // implicit root: scaffold under cwd
|
|
110
|
+
return newChangeHandler(root, positionals[1], {
|
|
111
|
+
schema: flags['--schema'],
|
|
112
|
+
description: flags['--description'],
|
|
113
|
+
json,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
case 'archive':
|
|
117
|
+
return await archiveHandler(requireRoot(cwd), positionals[0], {
|
|
118
|
+
json,
|
|
119
|
+
yes: flags['--yes'] === true,
|
|
120
|
+
force: flags['--force'] === true,
|
|
121
|
+
});
|
|
122
|
+
case 'follow-up': {
|
|
123
|
+
const root = requireRoot(cwd);
|
|
124
|
+
const sub = positionals[0];
|
|
125
|
+
const options = { json, from: flags['--from'], by: flags['--by'] };
|
|
126
|
+
if (sub === 'add')
|
|
127
|
+
return followUpAddHandler(root, positionals[1], positionals[2], options);
|
|
128
|
+
if (sub === 'list')
|
|
129
|
+
return followUpListHandler(root, options);
|
|
130
|
+
if (sub === 'claim')
|
|
131
|
+
return followUpClaimHandler(root, positionals[1], positionals[2], options);
|
|
132
|
+
throw new Error(`Unknown subcommand 'follow-up ${sub ?? ''}'. Did you mean 'follow-up add|list|claim'?`);
|
|
133
|
+
}
|
|
134
|
+
default:
|
|
135
|
+
console.error(`Unknown command '${command}'.`);
|
|
136
|
+
printUsage();
|
|
137
|
+
return 1;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function printUsage() {
|
|
141
|
+
console.error([
|
|
142
|
+
'Usage: openspec <command> [options]',
|
|
143
|
+
'',
|
|
144
|
+
'Commands:',
|
|
145
|
+
' status --change <id> [--schema <s>] [--json]',
|
|
146
|
+
' instructions <artifact|apply|archive> --change <id> [--schema <s>] [--json]',
|
|
147
|
+
' new change <id> [--schema <s>] [--description <d>] [--json]',
|
|
148
|
+
' list [--sort recent|name] [--json]',
|
|
149
|
+
' validate [<item>] [--specs] [--strict] [--json]',
|
|
150
|
+
' schemas [--json]',
|
|
151
|
+
' context [--json]',
|
|
152
|
+
' archive <id> [--yes] [--force] [--json]',
|
|
153
|
+
' follow-up add <change-id> "<text>" [--from <task>] [--json]',
|
|
154
|
+
' follow-up list [--json]',
|
|
155
|
+
' follow-up claim <change-id> <index> --by <change-id> [--json]',
|
|
156
|
+
].join('\n'));
|
|
157
|
+
}
|
|
158
|
+
main()
|
|
159
|
+
.then((code) => {
|
|
160
|
+
process.exitCode = code;
|
|
161
|
+
})
|
|
162
|
+
.catch((error) => {
|
|
163
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
164
|
+
console.error(message);
|
|
165
|
+
process.exitCode = 1;
|
|
166
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @freeharness/sdd public surface.
|
|
3
|
+
*
|
|
4
|
+
* Store-free, PATH-free vendored slice of OpenSpec: schema validation, project
|
|
5
|
+
* root resolution, and non-interactive project initialization (the `/opsx`
|
|
6
|
+
* commands + `openspec-*` skills + `openspec/` scaffold).
|
|
7
|
+
*/
|
|
8
|
+
export { findOpenspecDir } from './root-resolver.js';
|
|
9
|
+
export { validateSchema } from './validate.js';
|
|
10
|
+
export type { ValidateSchemaOptions, ValidateSchemaResult } from './validate.js';
|
|
11
|
+
export { initProject } from './init.js';
|
|
12
|
+
export type { InitProjectOptions, InitProjectResult, SddInitTarget, } from './init.js';
|
|
13
|
+
export { validateChange } from './validate-change.js';
|
|
14
|
+
export type { ValidateChangeOptions, ValidateChangeResult, } from './validate-change.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @freeharness/sdd public surface.
|
|
3
|
+
*
|
|
4
|
+
* Store-free, PATH-free vendored slice of OpenSpec: schema validation, project
|
|
5
|
+
* root resolution, and non-interactive project initialization (the `/opsx`
|
|
6
|
+
* commands + `openspec-*` skills + `openspec/` scaffold).
|
|
7
|
+
*/
|
|
8
|
+
export { findOpenspecDir } from './root-resolver.js';
|
|
9
|
+
export { validateSchema } from './validate.js';
|
|
10
|
+
export { initProject } from './init.js';
|
|
11
|
+
export { validateChange } from './validate-change.js';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store-free, non-interactive `openspec init` for FreeHarness.
|
|
3
|
+
*
|
|
4
|
+
* Reconstructs the minimal subset of OpenSpec's `InitCommand.execute` needed to
|
|
5
|
+
* produce, with NO global `openspec` on PATH, the same on-disk layout that
|
|
6
|
+
* `openspec init --tools <tool>` writes for Claude Code and OpenCode:
|
|
7
|
+
*
|
|
8
|
+
* - `/opsx` command files (via the vendored command-generation adapters)
|
|
9
|
+
* - `openspec-*` skill files (via the vendored skill-generation + templates)
|
|
10
|
+
* - the `openspec/` project (specs/, changes/, changes/archive/, config.yaml)
|
|
11
|
+
*
|
|
12
|
+
* What was deliberately dropped vs. upstream init.ts (all of it is interactive,
|
|
13
|
+
* store-, telemetry-, migration-, or multi-tool-selection machinery that has no
|
|
14
|
+
* place in a library call): tool selection prompts, legacy-artifact cleanup,
|
|
15
|
+
* store pointer guards, profile/delivery config resolution, GitHub Copilot cloud
|
|
16
|
+
* files, welcome animation, and success reporting. The generation logic itself
|
|
17
|
+
* is the vendored upstream code, used faithfully.
|
|
18
|
+
*/
|
|
19
|
+
export type SddInitTarget = 'claude' | 'opencode';
|
|
20
|
+
export interface InitProjectOptions {
|
|
21
|
+
/** Which harness to generate commands + skills for. */
|
|
22
|
+
target: SddInitTarget;
|
|
23
|
+
/** Project root the `openspec/` tree and tool dirs are written under. */
|
|
24
|
+
projectDir: string;
|
|
25
|
+
}
|
|
26
|
+
export interface InitProjectResult {
|
|
27
|
+
/** Absolute paths of every file created, in write order. */
|
|
28
|
+
written: string[];
|
|
29
|
+
/**
|
|
30
|
+
* Human-readable notes about files deliberately left untouched (an existing
|
|
31
|
+
* `openspec/config.yaml`). Callers surface them as `note:` lines.
|
|
32
|
+
*/
|
|
33
|
+
notes: string[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Generates the `/opsx` commands, `openspec-*` skills, and `openspec/` project
|
|
37
|
+
* structure for one harness under `projectDir`.
|
|
38
|
+
*/
|
|
39
|
+
export declare function initProject(opts: InitProjectOptions): Promise<InitProjectResult>;
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Store-free, non-interactive `openspec init` for FreeHarness.
|
|
3
|
+
*
|
|
4
|
+
* Reconstructs the minimal subset of OpenSpec's `InitCommand.execute` needed to
|
|
5
|
+
* produce, with NO global `openspec` on PATH, the same on-disk layout that
|
|
6
|
+
* `openspec init --tools <tool>` writes for Claude Code and OpenCode:
|
|
7
|
+
*
|
|
8
|
+
* - `/opsx` command files (via the vendored command-generation adapters)
|
|
9
|
+
* - `openspec-*` skill files (via the vendored skill-generation + templates)
|
|
10
|
+
* - the `openspec/` project (specs/, changes/, changes/archive/, config.yaml)
|
|
11
|
+
*
|
|
12
|
+
* What was deliberately dropped vs. upstream init.ts (all of it is interactive,
|
|
13
|
+
* store-, telemetry-, migration-, or multi-tool-selection machinery that has no
|
|
14
|
+
* place in a library call): tool selection prompts, legacy-artifact cleanup,
|
|
15
|
+
* store pointer guards, profile/delivery config resolution, GitHub Copilot cloud
|
|
16
|
+
* files, welcome animation, and success reporting. The generation logic itself
|
|
17
|
+
* is the vendored upstream code, used faithfully.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'node:fs/promises';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import { generateCommands, CommandAdapterRegistry, } from '../vendor/openspec/generation/command-generation/index.js';
|
|
22
|
+
import { getInvocationForAdapter, needsInvocationRewrite, } from '../vendor/openspec/generation/command-generation/invocation.js';
|
|
23
|
+
import { transformCommandInvocations } from '../vendor/openspec/generation/command-references.js';
|
|
24
|
+
import { getSkillTemplates, getCommandContents, generateSkillContent, } from '../vendor/openspec/generation/shared/skill-generation.js';
|
|
25
|
+
/**
|
|
26
|
+
* The "core" profile workflow set, mirrored from OpenSpec's
|
|
27
|
+
* `profiles.ts#CORE_WORKFLOWS`. This is the default set `openspec init` installs
|
|
28
|
+
* when no custom profile is configured. Inlined rather than vendoring the whole
|
|
29
|
+
* profile/global-config stack, which is pure interactive-config plumbing.
|
|
30
|
+
*/
|
|
31
|
+
const CORE_WORKFLOWS = [
|
|
32
|
+
'propose',
|
|
33
|
+
'explore',
|
|
34
|
+
'apply',
|
|
35
|
+
'update',
|
|
36
|
+
'sync',
|
|
37
|
+
'archive',
|
|
38
|
+
];
|
|
39
|
+
/**
|
|
40
|
+
* Project-local skills root per target. Mirrors OpenSpec's `AI_TOOLS[].skillsDir`
|
|
41
|
+
* for these two tools; skills live under `<skillsDir>/skills/` per the Agent
|
|
42
|
+
* Skills spec (see resolveToolSkillsDir upstream).
|
|
43
|
+
*/
|
|
44
|
+
const TOOL_SKILLS_DIR = {
|
|
45
|
+
claude: '.claude',
|
|
46
|
+
opencode: '.opencode',
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Version stamped into each SKILL.md `generatedBy` field. Upstream reads its own
|
|
50
|
+
* package.json; here it records the OpenSpec release this generation slice was
|
|
51
|
+
* vendored from, so the provenance stays honest.
|
|
52
|
+
*/
|
|
53
|
+
const OPENSPEC_VENDOR_VERSION = '1.8.0';
|
|
54
|
+
/**
|
|
55
|
+
* Minimal reconstruction of OpenSpec's `serializeConfig({ schema })` — the
|
|
56
|
+
* `openspec/config.yaml` current init writes. Pure string building, so it is
|
|
57
|
+
* reproduced here rather than vendoring config-prompts.ts and its dependencies.
|
|
58
|
+
*/
|
|
59
|
+
function serializeConfig(schema) {
|
|
60
|
+
return ([
|
|
61
|
+
`schema: ${schema}`,
|
|
62
|
+
'',
|
|
63
|
+
'# Project context (optional)',
|
|
64
|
+
'# This is shown to AI when creating artifacts.',
|
|
65
|
+
'# Add your tech stack, conventions, style guides, domain knowledge, etc.',
|
|
66
|
+
'# Example:',
|
|
67
|
+
'# context: |',
|
|
68
|
+
'# Tech stack: TypeScript, React, Node.js',
|
|
69
|
+
'# We use conventional commits',
|
|
70
|
+
'# Domain: e-commerce platform',
|
|
71
|
+
'',
|
|
72
|
+
'# Per-artifact rules (optional)',
|
|
73
|
+
'# Add custom rules for specific artifacts.',
|
|
74
|
+
'# Example:',
|
|
75
|
+
'# rules:',
|
|
76
|
+
'# proposal:',
|
|
77
|
+
'# - Keep proposals under 500 words',
|
|
78
|
+
'# - Always include a "Non-goals" section',
|
|
79
|
+
'# tasks:',
|
|
80
|
+
'# - Break tasks into chunks of max 2 hours',
|
|
81
|
+
'',
|
|
82
|
+
'# Per-operation guidance (optional)',
|
|
83
|
+
'# Add advisory guidance for how apply and archive work should be conducted.',
|
|
84
|
+
'# This is separate from artifact rules above.',
|
|
85
|
+
'# Example:',
|
|
86
|
+
'# operations:',
|
|
87
|
+
'# apply:',
|
|
88
|
+
'# guidance:',
|
|
89
|
+
'# - Keep test summaries concise',
|
|
90
|
+
'# archive:',
|
|
91
|
+
'# guidance:',
|
|
92
|
+
'# - Summarize the archive outcome before finishing',
|
|
93
|
+
].join('\n') + '\n');
|
|
94
|
+
}
|
|
95
|
+
/** True when `filePath` exists (any kind of entry). */
|
|
96
|
+
async function pathExists(filePath) {
|
|
97
|
+
try {
|
|
98
|
+
await fs.access(filePath);
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/** Writes `content` to `filePath`, creating parent directories as needed. */
|
|
106
|
+
async function writeFileEnsuringDir(filePath, content) {
|
|
107
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
108
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Hides a generated OpenSpec skill from Claude Code's "/" menu.
|
|
112
|
+
*
|
|
113
|
+
* The `openspec-*` skills are the bodies behind the `/opsx:*` commands; the commands
|
|
114
|
+
* invoke them through the model, so `user-invocable: false` (Claude Code docs, "Control
|
|
115
|
+
* who invokes a skill") removes the duplicate-looking `/openspec-*` entries from the menu
|
|
116
|
+
* without changing what the model can call. Other targets are left untouched.
|
|
117
|
+
*
|
|
118
|
+
* Args:
|
|
119
|
+
* content: The generated SKILL.md text (frontmatter first).
|
|
120
|
+
* target: The harness the skill is generated for.
|
|
121
|
+
*
|
|
122
|
+
* Returns:
|
|
123
|
+
* The content with the field inserted after the frontmatter's `name:` line.
|
|
124
|
+
*/
|
|
125
|
+
function hideFromSlashMenu(content, target) {
|
|
126
|
+
if (target !== 'claude' || !content.startsWith('---\n') || content.includes('user-invocable:'))
|
|
127
|
+
return content;
|
|
128
|
+
return content.replace(/^(---\nname:[^\n]*\n)/, '$1user-invocable: false\n');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Generates the `/opsx` commands, `openspec-*` skills, and `openspec/` project
|
|
132
|
+
* structure for one harness under `projectDir`.
|
|
133
|
+
*/
|
|
134
|
+
export async function initProject(opts) {
|
|
135
|
+
const { target, projectDir } = opts;
|
|
136
|
+
const adapter = CommandAdapterRegistry.get(target);
|
|
137
|
+
if (!adapter) {
|
|
138
|
+
throw new Error(`No command adapter registered for target '${target}'. Supported targets: claude, opencode.`);
|
|
139
|
+
}
|
|
140
|
+
const written = [];
|
|
141
|
+
const notes = [];
|
|
142
|
+
// --- openspec/ project structure -----------------------------------------
|
|
143
|
+
const openspecDir = path.join(projectDir, 'openspec');
|
|
144
|
+
for (const dir of [
|
|
145
|
+
openspecDir,
|
|
146
|
+
path.join(openspecDir, 'specs'),
|
|
147
|
+
path.join(openspecDir, 'changes'),
|
|
148
|
+
path.join(openspecDir, 'changes', 'archive'),
|
|
149
|
+
]) {
|
|
150
|
+
await fs.mkdir(dir, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
// config.yaml is user-owned once it exists: a project's `context:` and `rules:`
|
|
153
|
+
// live there, so a re-run (bootstrap, update, --fix) must never rewrite it.
|
|
154
|
+
const configPath = path.join(openspecDir, 'config.yaml');
|
|
155
|
+
if (await pathExists(configPath)) {
|
|
156
|
+
notes.push(`openspec/config.yaml already exists; kept as is (context/rules preserved): ${configPath}`);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
await writeFileEnsuringDir(configPath, serializeConfig('spec-driven'));
|
|
160
|
+
written.push(configPath);
|
|
161
|
+
}
|
|
162
|
+
// --- skills ---------------------------------------------------------------
|
|
163
|
+
// The command-reference form differs per target: Claude Code registers the
|
|
164
|
+
// canonical `/opsx:<id>` (no rewrite); OpenCode registers `/opsx-<id>`, so
|
|
165
|
+
// skill bodies are rewritten to match. This mirrors upstream
|
|
166
|
+
// getTransformerForTool for these two adapter-backed, slash-prefixed tools.
|
|
167
|
+
const invocation = getInvocationForAdapter(adapter);
|
|
168
|
+
const skillTransformer = needsInvocationRewrite(invocation)
|
|
169
|
+
? (text) => transformCommandInvocations(text, invocation)
|
|
170
|
+
: undefined;
|
|
171
|
+
const skillsRoot = path.join(projectDir, TOOL_SKILLS_DIR[target], 'skills');
|
|
172
|
+
for (const { template, dirName } of getSkillTemplates(CORE_WORKFLOWS)) {
|
|
173
|
+
const skillFile = path.join(skillsRoot, dirName, 'SKILL.md');
|
|
174
|
+
const content = hideFromSlashMenu(generateSkillContent(template, OPENSPEC_VENDOR_VERSION, skillTransformer), target);
|
|
175
|
+
await writeFileEnsuringDir(skillFile, content);
|
|
176
|
+
written.push(skillFile);
|
|
177
|
+
}
|
|
178
|
+
// --- commands -------------------------------------------------------------
|
|
179
|
+
// generateCommands applies the same invocation rewrite to command bodies and
|
|
180
|
+
// asks the adapter for the tool-specific path + frontmatter.
|
|
181
|
+
const commandContents = getCommandContents(CORE_WORKFLOWS);
|
|
182
|
+
for (const cmd of generateCommands(commandContents, adapter)) {
|
|
183
|
+
const commandFile = path.isAbsolute(cmd.path)
|
|
184
|
+
? cmd.path
|
|
185
|
+
: path.join(projectDir, cmd.path);
|
|
186
|
+
await writeFileEnsuringDir(commandFile, cmd.fileContent);
|
|
187
|
+
written.push(commandFile);
|
|
188
|
+
}
|
|
189
|
+
return { written, notes };
|
|
190
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Walks up from `startDir` looking for an `openspec/` directory.
|
|
3
|
+
*
|
|
4
|
+
* @param startDir - Directory to start searching from.
|
|
5
|
+
* @returns The absolute path to the nearest `openspec/` directory, or null if
|
|
6
|
+
* none is found before reaching the filesystem root.
|
|
7
|
+
*/
|
|
8
|
+
export declare function findOpenspecDir(startDir: string): string | null;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Store-free project-root resolution. Unlike the upstream fork's root resolver,
|
|
2
|
+
// this has no dependency on the ~/.openspec multi-repo store or worksets: it just
|
|
3
|
+
// walks up from a starting directory looking for an `openspec/` directory.
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
/**
|
|
7
|
+
* Walks up from `startDir` looking for an `openspec/` directory.
|
|
8
|
+
*
|
|
9
|
+
* @param startDir - Directory to start searching from.
|
|
10
|
+
* @returns The absolute path to the nearest `openspec/` directory, or null if
|
|
11
|
+
* none is found before reaching the filesystem root.
|
|
12
|
+
*/
|
|
13
|
+
export function findOpenspecDir(startDir) {
|
|
14
|
+
let current = path.resolve(startDir);
|
|
15
|
+
while (true) {
|
|
16
|
+
const candidate = path.join(current, 'openspec');
|
|
17
|
+
try {
|
|
18
|
+
if (fs.statSync(candidate).isDirectory()) {
|
|
19
|
+
return candidate;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Not present at this level — keep walking up.
|
|
24
|
+
}
|
|
25
|
+
const parent = path.dirname(current);
|
|
26
|
+
if (parent === current) {
|
|
27
|
+
// Reached the filesystem root without a match.
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
current = parent;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { ValidationIssue } from '../../vendor/openspec/validation/types.js';
|
|
2
|
+
import { type UnresolvedDeltaHeader } from '../../vendor/openspec/validation/delta-resolution.js';
|
|
3
|
+
import { type ChangeMetadata } from '../../vendor/openspec/engine/change-metadata.js';
|
|
4
|
+
import { type FollowUpItem } from './follow-up.js';
|
|
5
|
+
/** One `Supersedes:` link resolved against openspec/changes/archive/. */
|
|
6
|
+
export interface SupersessionLink {
|
|
7
|
+
/** The superseded (archived) change id. */
|
|
8
|
+
change: string;
|
|
9
|
+
/** Absolute path of the archived record. */
|
|
10
|
+
path: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Resolves the ids a change supersedes: the deduplicated union of design.md's
|
|
14
|
+
* `Supersedes:` lines and the metadata `supersedes` list, design.md first.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readSupersedes(designText: string, metadata: ChangeMetadata | null): string[];
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the change's `Supersedes:` lines and enforces the supersession
|
|
19
|
+
* rules: every id names an archived change, and no MODIFIED requirement of this
|
|
20
|
+
* change repeats a superseded requirement's text unchanged.
|
|
21
|
+
*/
|
|
22
|
+
export declare function checkSupersession(changeName: string, changeDir: string, changesDir: string, metadata: ChangeMetadata | null): Promise<SupersessionLink[]>;
|
|
23
|
+
/**
|
|
24
|
+
* Lines that describe what archive would refuse or what is still open. The
|
|
25
|
+
* unresolved headers are listed here as well so one refusal names everything.
|
|
26
|
+
*/
|
|
27
|
+
export declare function listArchiveBlockers(changeDir: string, issues: ValidationIssue[], unresolved?: UnresolvedDeltaHeader[]): string[];
|
|
28
|
+
/** One unchecked task resolved outside this change. */
|
|
29
|
+
export interface ArchivedDisposition {
|
|
30
|
+
kind: string;
|
|
31
|
+
task: string;
|
|
32
|
+
target: string;
|
|
33
|
+
}
|
|
34
|
+
export interface ArchiveChangeOptions {
|
|
35
|
+
/** Project root (the parent of the openspec/ directory). */
|
|
36
|
+
projectRoot: string;
|
|
37
|
+
/**
|
|
38
|
+
* Skips the blockers gate (unchecked tasks, deltas archive would refuse),
|
|
39
|
+
* as upstream `--yes` skips its confirmation prompt. Without it, a change
|
|
40
|
+
* with blockers is listed and refused with nothing written.
|
|
41
|
+
*/
|
|
42
|
+
yes?: boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Archives despite unresolved MODIFIED / REMOVED / RENAMED headers: the fold
|
|
45
|
+
* skips those deltas (each printed as a warning) and the rest is applied.
|
|
46
|
+
* Without it, any unresolved header refuses the archive with nothing written.
|
|
47
|
+
*/
|
|
48
|
+
force?: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface ArchiveChangeResult {
|
|
51
|
+
/** Capability ids whose main spec was updated by the fold. */
|
|
52
|
+
applied: string[];
|
|
53
|
+
/** Absolute path the change directory was moved to. */
|
|
54
|
+
archivedTo: string;
|
|
55
|
+
/** Archived changes this change supersedes (from design.md `Supersedes:`). */
|
|
56
|
+
supersedes: SupersessionLink[];
|
|
57
|
+
/** Delta headers skipped by the fold under `--force` (empty otherwise). */
|
|
58
|
+
skipped: UnresolvedDeltaHeader[];
|
|
59
|
+
/** Unchecked tasks resolved outside this change, grouped for display by kind. */
|
|
60
|
+
dispositions: ArchivedDisposition[];
|
|
61
|
+
/** The archived change's unclaimed follow-ups, printed as a notice (never a blocker). */
|
|
62
|
+
followUps: FollowUpItem[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Archive a change: validate it, fold its delta specs into openspec/specs/, then
|
|
66
|
+
* move openspec/changes/<name>/ to openspec/changes/archive/<name>/.
|
|
67
|
+
*
|
|
68
|
+
* Throws (with an actionable message) rather than partially archiving when the
|
|
69
|
+
* change is invalid, a fold fails, or the archive destination is already taken.
|
|
70
|
+
*/
|
|
71
|
+
export declare function archiveChange(changeName: string | undefined, { projectRoot, yes, force }: ArchiveChangeOptions): Promise<ArchiveChangeResult>;
|
|
72
|
+
export interface ArchiveOptions {
|
|
73
|
+
json?: boolean;
|
|
74
|
+
yes?: boolean;
|
|
75
|
+
force?: boolean;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* CLI wrapper for `openspec archive <id>`. Returns the process exit code and
|
|
79
|
+
* emits either the single-document `--json` result or human-readable lines.
|
|
80
|
+
*/
|
|
81
|
+
export declare function archiveHandler(projectRoot: string, changeName: string | undefined, options: ArchiveOptions): Promise<number>;
|