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,110 @@
|
|
|
1
|
+
// Vendored faithfully from @fission-ai/openspec@1.8.0
|
|
2
|
+
// src/core/artifact-graph/schema.ts
|
|
3
|
+
// No behavioural changes. Part of the schema-validation slice.
|
|
4
|
+
import * as fs from 'node:fs';
|
|
5
|
+
import { parse as parseYaml } from 'yaml';
|
|
6
|
+
import { SchemaYamlSchema } from './types.js';
|
|
7
|
+
export class SchemaValidationError extends Error {
|
|
8
|
+
constructor(message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.name = 'SchemaValidationError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Loads and validates an artifact schema from a YAML file.
|
|
15
|
+
*/
|
|
16
|
+
export function loadSchema(filePath) {
|
|
17
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
18
|
+
return parseSchema(content);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Parses and validates an artifact schema from YAML content.
|
|
22
|
+
*/
|
|
23
|
+
export function parseSchema(yamlContent) {
|
|
24
|
+
const parsed = parseYaml(yamlContent);
|
|
25
|
+
// Validate with Zod
|
|
26
|
+
const result = SchemaYamlSchema.safeParse(parsed);
|
|
27
|
+
if (!result.success) {
|
|
28
|
+
const errors = result.error.issues.map(e => `${e.path.join('.')}: ${e.message}`).join(', ');
|
|
29
|
+
throw new SchemaValidationError(`Invalid schema: ${errors}`);
|
|
30
|
+
}
|
|
31
|
+
const schema = result.data;
|
|
32
|
+
// Check for duplicate artifact IDs
|
|
33
|
+
validateNoDuplicateIds(schema.artifacts);
|
|
34
|
+
// Check that all requires references are valid
|
|
35
|
+
validateRequiresReferences(schema.artifacts);
|
|
36
|
+
// Check for cycles
|
|
37
|
+
validateNoCycles(schema.artifacts);
|
|
38
|
+
return schema;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Validates that there are no duplicate artifact IDs.
|
|
42
|
+
*/
|
|
43
|
+
function validateNoDuplicateIds(artifacts) {
|
|
44
|
+
const seen = new Set();
|
|
45
|
+
for (const artifact of artifacts) {
|
|
46
|
+
if (seen.has(artifact.id)) {
|
|
47
|
+
throw new SchemaValidationError(`Duplicate artifact ID: ${artifact.id}`);
|
|
48
|
+
}
|
|
49
|
+
seen.add(artifact.id);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Validates that all `requires` references point to valid artifact IDs.
|
|
54
|
+
*/
|
|
55
|
+
function validateRequiresReferences(artifacts) {
|
|
56
|
+
const validIds = new Set(artifacts.map(a => a.id));
|
|
57
|
+
for (const artifact of artifacts) {
|
|
58
|
+
for (const req of artifact.requires) {
|
|
59
|
+
if (!validIds.has(req)) {
|
|
60
|
+
throw new SchemaValidationError(`Invalid dependency reference in artifact '${artifact.id}': '${req}' does not exist`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Validates that there are no cyclic dependencies.
|
|
67
|
+
* Uses DFS to detect cycles and reports the full cycle path.
|
|
68
|
+
*/
|
|
69
|
+
function validateNoCycles(artifacts) {
|
|
70
|
+
const artifactMap = new Map(artifacts.map(a => [a.id, a]));
|
|
71
|
+
const visited = new Set();
|
|
72
|
+
const inStack = new Set();
|
|
73
|
+
const parent = new Map();
|
|
74
|
+
function dfs(id) {
|
|
75
|
+
visited.add(id);
|
|
76
|
+
inStack.add(id);
|
|
77
|
+
const artifact = artifactMap.get(id);
|
|
78
|
+
if (!artifact)
|
|
79
|
+
return null;
|
|
80
|
+
for (const dep of artifact.requires) {
|
|
81
|
+
if (!visited.has(dep)) {
|
|
82
|
+
parent.set(dep, id);
|
|
83
|
+
const cycle = dfs(dep);
|
|
84
|
+
if (cycle)
|
|
85
|
+
return cycle;
|
|
86
|
+
}
|
|
87
|
+
else if (inStack.has(dep)) {
|
|
88
|
+
// Found a cycle - reconstruct the path
|
|
89
|
+
const cyclePath = [dep];
|
|
90
|
+
let current = id;
|
|
91
|
+
while (current !== dep) {
|
|
92
|
+
cyclePath.unshift(current);
|
|
93
|
+
current = parent.get(current);
|
|
94
|
+
}
|
|
95
|
+
cyclePath.unshift(dep);
|
|
96
|
+
return cyclePath.join(' → ');
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
inStack.delete(id);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
for (const artifact of artifacts) {
|
|
103
|
+
if (!visited.has(artifact.id)) {
|
|
104
|
+
const cycle = dfs(artifact.id);
|
|
105
|
+
if (cycle) {
|
|
106
|
+
throw new SchemaValidationError(`Cyclic dependency detected: ${cycle}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CompletedSet } from './types.js';
|
|
2
|
+
import type { ArtifactGraph } from './graph.js';
|
|
3
|
+
/**
|
|
4
|
+
* Detects which artifacts are completed by checking file existence in the change directory.
|
|
5
|
+
* Returns a Set of completed artifact IDs.
|
|
6
|
+
*
|
|
7
|
+
* @param graph - The artifact graph to check
|
|
8
|
+
* @param changeDir - The change directory to scan for files
|
|
9
|
+
* @returns Set of artifact IDs whose generated files exist
|
|
10
|
+
*/
|
|
11
|
+
export declare function detectCompleted(graph: ArtifactGraph, changeDir: string): CompletedSet;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Vendored VERBATIM from @fission-ai/openspec@1.8.0 src/core/artifact-graph/state.ts
|
|
2
|
+
// (import paths already resolve within this vendored engine directory).
|
|
3
|
+
import * as fs from 'node:fs';
|
|
4
|
+
import { artifactOutputExists } from './outputs.js';
|
|
5
|
+
/**
|
|
6
|
+
* Detects which artifacts are completed by checking file existence in the change directory.
|
|
7
|
+
* Returns a Set of completed artifact IDs.
|
|
8
|
+
*
|
|
9
|
+
* @param graph - The artifact graph to check
|
|
10
|
+
* @param changeDir - The change directory to scan for files
|
|
11
|
+
* @returns Set of artifact IDs whose generated files exist
|
|
12
|
+
*/
|
|
13
|
+
export function detectCompleted(graph, changeDir) {
|
|
14
|
+
const completed = new Set();
|
|
15
|
+
// Handle missing change directory gracefully
|
|
16
|
+
if (!fs.existsSync(changeDir)) {
|
|
17
|
+
return completed;
|
|
18
|
+
}
|
|
19
|
+
for (const artifact of graph.getAllArtifacts()) {
|
|
20
|
+
if (isArtifactComplete(artifact.generates, changeDir)) {
|
|
21
|
+
completed.add(artifact.id);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return completed;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Checks if an artifact is complete by checking if its generated file(s) exist.
|
|
28
|
+
* Supports both simple paths and glob patterns.
|
|
29
|
+
*/
|
|
30
|
+
function isArtifactComplete(generates, changeDir) {
|
|
31
|
+
return artifactOutputExists(changeDir, generates);
|
|
32
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface ParsedTask {
|
|
2
|
+
done: boolean;
|
|
3
|
+
description: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function parseTaskLines(content: string): ParsedTask[];
|
|
6
|
+
export interface TaskProgress {
|
|
7
|
+
total: number;
|
|
8
|
+
/** Upstream field name, an alias of `done`. */
|
|
9
|
+
completed: number;
|
|
10
|
+
/** Checked tasks. Same count as `completed`. */
|
|
11
|
+
done: number;
|
|
12
|
+
/** Unchecked tasks carrying no disposition. */
|
|
13
|
+
open: number;
|
|
14
|
+
/** Unchecked tasks carrying a `Disposition:` line. */
|
|
15
|
+
dispositioned: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function countTasksFromContent(content: string): TaskProgress;
|
|
18
|
+
/** Resolves the task files selected by the schema's apply tracking rule. */
|
|
19
|
+
export declare function resolveTaskFilesForChange(changeDir: string, projectRoot: string): string[];
|
|
20
|
+
/**
|
|
21
|
+
* Computes a change's task progress by resolving its tracked-tasks artifact and
|
|
22
|
+
* counting checkboxes across every matched file, falling back to a single
|
|
23
|
+
* top-level `tasks.md`.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getTaskProgressForChange(changesDir: string, changeName: string, projectRoot: string): Promise<TaskProgress>;
|
|
26
|
+
/**
|
|
27
|
+
* One-line task status. A caller that knows the disposition-aware counts passes them: a
|
|
28
|
+
* change with no open task is complete even while an unchecked, dispositioned task remains,
|
|
29
|
+
* and the dispositioned count is named so the gap between `completed` and `total` is
|
|
30
|
+
* accounted for. A caller passing only the two upstream fields reads every unchecked task
|
|
31
|
+
* as open.
|
|
32
|
+
*/
|
|
33
|
+
export declare function formatTaskStatus(progress: Pick<TaskProgress, 'total' | 'completed'> & Partial<Pick<TaskProgress, 'open' | 'dispositioned'>>): string;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
// Vendored (store-free) from @fission-ai/openspec@1.8.0 src/utils/task-progress.ts.
|
|
2
|
+
// The checkbox parsing (parseTaskLines / countTasksFromContent) and the
|
|
3
|
+
// tracked-tasks resolution (schema apply.tracks -> generates glob ->
|
|
4
|
+
// resolveArtifactOutputs, with a single top-level tasks.md fallback) are
|
|
5
|
+
// faithful. The only changes are import paths (rewritten to this engine
|
|
6
|
+
// directory) and dropping the run-scoped SchemaGlobCache / --archived plumbing,
|
|
7
|
+
// which the list shim does not need. Schema resolution goes through the
|
|
8
|
+
// store-free resolveSchemaForChange (explicit -> metadata -> spec-driven).
|
|
9
|
+
import { promises as fs } from 'node:fs';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import { resolveSchema } from './resolver.js';
|
|
12
|
+
import { resolveArtifactOutputs } from './outputs.js';
|
|
13
|
+
import { resolveSchemaForChange } from './change-metadata.js';
|
|
14
|
+
/**
|
|
15
|
+
* A Markdown task line: a `-`/`*` bullet carrying a `[ ]` or `[x]` checkbox.
|
|
16
|
+
* Leading whitespace is allowed so nested sub-tasks count like their parents.
|
|
17
|
+
*/
|
|
18
|
+
const TASK_LINE_PATTERN = /^\s*[-*]\s*\[([\sxX])\]\s*(.*)/;
|
|
19
|
+
export function parseTaskLines(content) {
|
|
20
|
+
const tasks = [];
|
|
21
|
+
for (const line of content.split('\n')) {
|
|
22
|
+
const match = line.match(TASK_LINE_PATTERN);
|
|
23
|
+
if (match) {
|
|
24
|
+
tasks.push({ done: match[1].toLowerCase() === 'x', description: match[2].trim() });
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return tasks;
|
|
28
|
+
}
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
// FreeHarness: disposition-aware counting. Not in upstream.
|
|
31
|
+
//
|
|
32
|
+
// This file keeps its own faithful-to-upstream `parseTaskLines` above (no
|
|
33
|
+
// annotation awareness) so task-numbering-style consumers are unaffected;
|
|
34
|
+
// `countTasksFromContent` needs to tell a plain open task from one resolved
|
|
35
|
+
// elsewhere, so it scans annotation lines locally rather than importing the
|
|
36
|
+
// validation-layer parser (this engine directory does not depend on
|
|
37
|
+
// ../validation).
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// The trailing `\s*` absorbs the `\r` of a CRLF file, which `.` never matches; without it no
|
|
40
|
+
// annotation of such a file parses and every disposition in it is dropped.
|
|
41
|
+
const TASK_ANNOTATION_PATTERN = /^\s*(?:Verify|Interfaces|Boundary|Depends|Disposition):\s*(.*)\s*$/;
|
|
42
|
+
const DISPOSITION_LINE_PATTERN = /^\s*Disposition:\s*(\S+)/;
|
|
43
|
+
/** Kinds that resolve a task. Any other kind leaves it open, and validate refuses it. */
|
|
44
|
+
const DISPOSITION_KINDS = new Set(['superseded', 'moved', 'external']);
|
|
45
|
+
/** Parses task lines, marking each unchecked task that carries a `Disposition:` line. */
|
|
46
|
+
function parseTasksWithDisposition(content) {
|
|
47
|
+
const tasks = [];
|
|
48
|
+
let current;
|
|
49
|
+
for (const line of content.split('\n')) {
|
|
50
|
+
const task = line.match(TASK_LINE_PATTERN);
|
|
51
|
+
if (task) {
|
|
52
|
+
current = { done: task[1].toLowerCase() === 'x', description: task[2].trim(), dispositioned: false };
|
|
53
|
+
tasks.push(current);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (current && TASK_ANNOTATION_PATTERN.test(line)) {
|
|
57
|
+
const disposition = DISPOSITION_LINE_PATTERN.exec(line);
|
|
58
|
+
if (disposition && DISPOSITION_KINDS.has(disposition[1]))
|
|
59
|
+
current.dispositioned = true;
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
current = undefined;
|
|
63
|
+
}
|
|
64
|
+
return tasks;
|
|
65
|
+
}
|
|
66
|
+
export function countTasksFromContent(content) {
|
|
67
|
+
const tasks = parseTasksWithDisposition(content);
|
|
68
|
+
const done = tasks.filter((task) => task.done).length;
|
|
69
|
+
const dispositioned = tasks.filter((task) => !task.done && task.dispositioned).length;
|
|
70
|
+
const open = tasks.length - done - dispositioned;
|
|
71
|
+
return { total: tasks.length, completed: done, done, open, dispositioned };
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Identifies the change's tracked-tasks artifact: the artifact whose `generates`
|
|
75
|
+
* equals the schema's `apply.tracks`, falling back to the artifact with id
|
|
76
|
+
* `tasks` when no `apply` block declares what it tracks.
|
|
77
|
+
*/
|
|
78
|
+
function findTrackedTasksArtifact(schema) {
|
|
79
|
+
const tracks = schema.apply?.tracks;
|
|
80
|
+
if (tracks != null) {
|
|
81
|
+
return schema.artifacts.find((a) => a.generates === tracks);
|
|
82
|
+
}
|
|
83
|
+
return schema.artifacts.find((a) => a.id === 'tasks');
|
|
84
|
+
}
|
|
85
|
+
function resolveTrackedTasksGlob(changeDir, projectRoot) {
|
|
86
|
+
try {
|
|
87
|
+
const schemaName = resolveSchemaForChange(changeDir, undefined, projectRoot);
|
|
88
|
+
const schema = resolveSchema(schemaName, projectRoot);
|
|
89
|
+
return findTrackedTasksArtifact(schema)?.generates;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/** Resolves the task files selected by the schema's apply tracking rule. */
|
|
96
|
+
export function resolveTaskFilesForChange(changeDir, projectRoot) {
|
|
97
|
+
const generates = resolveTrackedTasksGlob(changeDir, projectRoot);
|
|
98
|
+
return generates ? resolveArtifactOutputs(changeDir, generates) : [];
|
|
99
|
+
}
|
|
100
|
+
async function countTaskFile(file) {
|
|
101
|
+
try {
|
|
102
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
103
|
+
return countTasksFromContent(content);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return { total: 0, completed: 0, done: 0, open: 0, dispositioned: 0 };
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Computes a change's task progress by resolving its tracked-tasks artifact and
|
|
111
|
+
* counting checkboxes across every matched file, falling back to a single
|
|
112
|
+
* top-level `tasks.md`.
|
|
113
|
+
*/
|
|
114
|
+
export async function getTaskProgressForChange(changesDir, changeName, projectRoot) {
|
|
115
|
+
const changeDir = path.join(changesDir, changeName);
|
|
116
|
+
const files = resolveTaskFilesForChange(changeDir, projectRoot);
|
|
117
|
+
const targets = files.length > 0 ? files : [path.join(changeDir, 'tasks.md')];
|
|
118
|
+
let total = 0;
|
|
119
|
+
let completed = 0;
|
|
120
|
+
let done = 0;
|
|
121
|
+
let open = 0;
|
|
122
|
+
let dispositioned = 0;
|
|
123
|
+
for (const file of targets) {
|
|
124
|
+
const progress = await countTaskFile(file);
|
|
125
|
+
total += progress.total;
|
|
126
|
+
completed += progress.completed;
|
|
127
|
+
done += progress.done;
|
|
128
|
+
open += progress.open;
|
|
129
|
+
dispositioned += progress.dispositioned;
|
|
130
|
+
}
|
|
131
|
+
return { total, completed, done, open, dispositioned };
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* One-line task status. A caller that knows the disposition-aware counts passes them: a
|
|
135
|
+
* change with no open task is complete even while an unchecked, dispositioned task remains,
|
|
136
|
+
* and the dispositioned count is named so the gap between `completed` and `total` is
|
|
137
|
+
* accounted for. A caller passing only the two upstream fields reads every unchecked task
|
|
138
|
+
* as open.
|
|
139
|
+
*/
|
|
140
|
+
export function formatTaskStatus(progress) {
|
|
141
|
+
if (progress.total === 0)
|
|
142
|
+
return 'No tasks';
|
|
143
|
+
const open = progress.open ?? progress.total - progress.completed;
|
|
144
|
+
if (open === 0)
|
|
145
|
+
return '✓ Complete';
|
|
146
|
+
const dispositioned = progress.dispositioned ?? 0;
|
|
147
|
+
const aside = dispositioned > 0 ? ` (${dispositioned} dispositioned)` : '';
|
|
148
|
+
return `${progress.completed}/${progress.total} tasks${aside}`;
|
|
149
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ArtifactSchema: z.ZodObject<{
|
|
3
|
+
id: z.ZodString;
|
|
4
|
+
generates: z.ZodString;
|
|
5
|
+
description: z.ZodString;
|
|
6
|
+
template: z.ZodString;
|
|
7
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
8
|
+
requires: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
9
|
+
}, z.core.$strip>;
|
|
10
|
+
export declare const ApplyPhaseSchema: z.ZodObject<{
|
|
11
|
+
requires: z.ZodArray<z.ZodString>;
|
|
12
|
+
tracks: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
13
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
14
|
+
}, z.core.$strip>;
|
|
15
|
+
export declare const SchemaYamlSchema: z.ZodObject<{
|
|
16
|
+
name: z.ZodString;
|
|
17
|
+
version: z.ZodNumber;
|
|
18
|
+
description: z.ZodOptional<z.ZodString>;
|
|
19
|
+
artifacts: z.ZodArray<z.ZodObject<{
|
|
20
|
+
id: z.ZodString;
|
|
21
|
+
generates: z.ZodString;
|
|
22
|
+
description: z.ZodString;
|
|
23
|
+
template: z.ZodString;
|
|
24
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
25
|
+
requires: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
26
|
+
}, z.core.$strip>>;
|
|
27
|
+
apply: z.ZodOptional<z.ZodObject<{
|
|
28
|
+
requires: z.ZodArray<z.ZodString>;
|
|
29
|
+
tracks: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
30
|
+
instruction: z.ZodOptional<z.ZodString>;
|
|
31
|
+
}, z.core.$strip>>;
|
|
32
|
+
}, z.core.$strip>;
|
|
33
|
+
export type Artifact = z.infer<typeof ArtifactSchema>;
|
|
34
|
+
export type ApplyPhase = z.infer<typeof ApplyPhaseSchema>;
|
|
35
|
+
export type SchemaYaml = z.infer<typeof SchemaYamlSchema>;
|
|
36
|
+
export type CompletedSet = Set<string>;
|
|
37
|
+
export interface BlockedArtifacts {
|
|
38
|
+
[artifactId: string]: string[];
|
|
39
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// Vendored faithfully from @fission-ai/openspec@1.8.0
|
|
2
|
+
// src/core/artifact-graph/types.ts
|
|
3
|
+
// No behavioural changes. Part of the schema-validation slice.
|
|
4
|
+
import * as path from 'node:path';
|
|
5
|
+
import { z } from 'zod';
|
|
6
|
+
function relativePathSchema(fieldName) {
|
|
7
|
+
return z
|
|
8
|
+
.string()
|
|
9
|
+
.min(1, { error: `${fieldName} is required` })
|
|
10
|
+
.superRefine((value, ctx) => {
|
|
11
|
+
const segments = value.split(/[\\/]+/u);
|
|
12
|
+
const isDrivePath = /^[A-Za-z]:/u.test(value);
|
|
13
|
+
const isAbsolute = path.posix.isAbsolute(value) || path.win32.isAbsolute(value) || isDrivePath;
|
|
14
|
+
const escapes = segments.includes('..');
|
|
15
|
+
if (isAbsolute || escapes || value.includes('\0')) {
|
|
16
|
+
ctx.addIssue({
|
|
17
|
+
code: 'custom',
|
|
18
|
+
message: `${fieldName} must be a relative path inside its allowed directory`,
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// Artifact definition schema
|
|
24
|
+
export const ArtifactSchema = z.object({
|
|
25
|
+
id: z.string().min(1, { error: 'Artifact ID is required' }),
|
|
26
|
+
generates: relativePathSchema('generates field'),
|
|
27
|
+
description: z.string(),
|
|
28
|
+
template: relativePathSchema('template field'),
|
|
29
|
+
instruction: z.string().optional(),
|
|
30
|
+
requires: z.array(z.string()).default([]),
|
|
31
|
+
});
|
|
32
|
+
// Apply phase configuration for schema-aware apply instructions
|
|
33
|
+
export const ApplyPhaseSchema = z.object({
|
|
34
|
+
// Artifact IDs that must exist before apply is available
|
|
35
|
+
requires: z.array(z.string()).min(1, { error: 'At least one required artifact' }),
|
|
36
|
+
// Path to file with checkboxes for progress (relative to change dir), or null if no tracking
|
|
37
|
+
tracks: relativePathSchema('apply.tracks').nullable().optional(),
|
|
38
|
+
// Custom guidance for the apply phase
|
|
39
|
+
instruction: z.string().optional(),
|
|
40
|
+
});
|
|
41
|
+
// Full schema YAML structure
|
|
42
|
+
export const SchemaYamlSchema = z.object({
|
|
43
|
+
name: z.string().min(1, { error: 'Schema name is required' }),
|
|
44
|
+
version: z.number().int().positive({ error: 'Version must be a positive integer' }),
|
|
45
|
+
description: z.string().optional(),
|
|
46
|
+
artifacts: z.array(ArtifactSchema).min(1, { error: 'At least one artifact required' }),
|
|
47
|
+
// Optional apply phase configuration (for schema-aware apply instructions)
|
|
48
|
+
apply: ApplyPhaseSchema.optional(),
|
|
49
|
+
});
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Command Adapter
|
|
3
|
+
*
|
|
4
|
+
* Formats commands for Claude Code following its frontmatter specification.
|
|
5
|
+
*/
|
|
6
|
+
import type { ToolCommandAdapter } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Claude Code adapter for command generation.
|
|
9
|
+
* File path: .claude/commands/opsx/<id>.md
|
|
10
|
+
* Frontmatter: name, description, allowed-tools, category, tags
|
|
11
|
+
*/
|
|
12
|
+
export declare const claudeAdapter: ToolCommandAdapter;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude Code Command Adapter
|
|
3
|
+
*
|
|
4
|
+
* Formats commands for Claude Code following its frontmatter specification.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { escapeYamlValue, formatTagsArray } from '../yaml.js';
|
|
8
|
+
import { OPENSPEC_CLI_ALLOWED_TOOLS } from '../../shared/allowed-tools.js';
|
|
9
|
+
/**
|
|
10
|
+
* Claude Code adapter for command generation.
|
|
11
|
+
* File path: .claude/commands/opsx/<id>.md
|
|
12
|
+
* Frontmatter: name, description, allowed-tools, category, tags
|
|
13
|
+
*/
|
|
14
|
+
export const claudeAdapter = {
|
|
15
|
+
toolId: 'claude',
|
|
16
|
+
getFilePath(commandId) {
|
|
17
|
+
return path.join('.claude', 'commands', 'opsx', `${commandId}.md`);
|
|
18
|
+
},
|
|
19
|
+
formatFile(content) {
|
|
20
|
+
return `---
|
|
21
|
+
name: ${escapeYamlValue(content.name)}
|
|
22
|
+
description: ${escapeYamlValue(content.description)}
|
|
23
|
+
allowed-tools: ${OPENSPEC_CLI_ALLOWED_TOOLS}
|
|
24
|
+
category: ${escapeYamlValue(content.category)}
|
|
25
|
+
tags: ${formatTagsArray(content.tags)}
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
${content.body}
|
|
29
|
+
`;
|
|
30
|
+
},
|
|
31
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Adapters Index
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the tool command adapters.
|
|
5
|
+
*
|
|
6
|
+
* FreeHarness trim: reduced from the upstream 29-adapter re-export to the two
|
|
7
|
+
* harnesses FreeHarness targets (Claude Code + OpenCode).
|
|
8
|
+
*/
|
|
9
|
+
export { claudeAdapter } from './claude.js';
|
|
10
|
+
export { opencodeAdapter } from './opencode.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Adapters Index
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the tool command adapters.
|
|
5
|
+
*
|
|
6
|
+
* FreeHarness trim: reduced from the upstream 29-adapter re-export to the two
|
|
7
|
+
* harnesses FreeHarness targets (Claude Code + OpenCode).
|
|
8
|
+
*/
|
|
9
|
+
export { claudeAdapter } from './claude.js';
|
|
10
|
+
export { opencodeAdapter } from './opencode.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Command Adapter
|
|
3
|
+
*
|
|
4
|
+
* Formats commands for OpenCode following its frontmatter specification.
|
|
5
|
+
*/
|
|
6
|
+
import type { ToolCommandAdapter } from '../types.js';
|
|
7
|
+
/**
|
|
8
|
+
* OpenCode adapter for command generation.
|
|
9
|
+
* File path: .opencode/commands/opsx-<id>.md
|
|
10
|
+
* Frontmatter: description
|
|
11
|
+
*/
|
|
12
|
+
export declare const opencodeAdapter: ToolCommandAdapter;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode Command Adapter
|
|
3
|
+
*
|
|
4
|
+
* Formats commands for OpenCode following its frontmatter specification.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'path';
|
|
7
|
+
import { escapeYamlValue } from '../yaml.js';
|
|
8
|
+
/**
|
|
9
|
+
* OpenCode adapter for command generation.
|
|
10
|
+
* File path: .opencode/commands/opsx-<id>.md
|
|
11
|
+
* Frontmatter: description
|
|
12
|
+
*/
|
|
13
|
+
export const opencodeAdapter = {
|
|
14
|
+
toolId: 'opencode',
|
|
15
|
+
getFilePath(commandId) {
|
|
16
|
+
return path.join('.opencode', 'commands', `opsx-${commandId}.md`);
|
|
17
|
+
},
|
|
18
|
+
formatFile(content) {
|
|
19
|
+
return `---
|
|
20
|
+
description: ${escapeYamlValue(content.description)}
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
${content.body}
|
|
24
|
+
`;
|
|
25
|
+
},
|
|
26
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Generator
|
|
3
|
+
*
|
|
4
|
+
* Functions for generating command files using tool adapters.
|
|
5
|
+
*/
|
|
6
|
+
import type { CommandContent, ToolCommandAdapter, GeneratedCommand } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Generate a single command file using the provided adapter.
|
|
9
|
+
*
|
|
10
|
+
* Command bodies are authored with `/opsx:<id>` references. Tools whose command
|
|
11
|
+
* files are invoked by filename register `/opsx-<id>` instead, and Amazon Q
|
|
12
|
+
* surfaces them in its prompt library as `@opsx-<id>`, so the body is rewritten
|
|
13
|
+
* to the form that tool answers to before the adapter formats it. Doing it here
|
|
14
|
+
* rather than per adapter keeps every tool in step (#727, #1307); adapters stay
|
|
15
|
+
* pure formatters.
|
|
16
|
+
*
|
|
17
|
+
* @param content - The tool-agnostic command content
|
|
18
|
+
* @param adapter - The tool-specific adapter
|
|
19
|
+
* @returns Generated command with path and file content
|
|
20
|
+
*/
|
|
21
|
+
export declare function generateCommand(content: CommandContent, adapter: ToolCommandAdapter): GeneratedCommand;
|
|
22
|
+
/**
|
|
23
|
+
* Generate multiple command files using the provided adapter.
|
|
24
|
+
* @param contents - Array of tool-agnostic command contents
|
|
25
|
+
* @param adapter - The tool-specific adapter
|
|
26
|
+
* @returns Array of generated commands with paths and file contents
|
|
27
|
+
*/
|
|
28
|
+
export declare function generateCommands(contents: CommandContent[], adapter: ToolCommandAdapter): GeneratedCommand[];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Generator
|
|
3
|
+
*
|
|
4
|
+
* Functions for generating command files using tool adapters.
|
|
5
|
+
*/
|
|
6
|
+
import { getInvocationForAdapter, needsInvocationRewrite } from './invocation.js';
|
|
7
|
+
// FreeHarness: command-references vendored alongside generation/ (was ../../utils).
|
|
8
|
+
import { transformCommandInvocations } from '../command-references.js';
|
|
9
|
+
/**
|
|
10
|
+
* Generate a single command file using the provided adapter.
|
|
11
|
+
*
|
|
12
|
+
* Command bodies are authored with `/opsx:<id>` references. Tools whose command
|
|
13
|
+
* files are invoked by filename register `/opsx-<id>` instead, and Amazon Q
|
|
14
|
+
* surfaces them in its prompt library as `@opsx-<id>`, so the body is rewritten
|
|
15
|
+
* to the form that tool answers to before the adapter formats it. Doing it here
|
|
16
|
+
* rather than per adapter keeps every tool in step (#727, #1307); adapters stay
|
|
17
|
+
* pure formatters.
|
|
18
|
+
*
|
|
19
|
+
* @param content - The tool-agnostic command content
|
|
20
|
+
* @param adapter - The tool-specific adapter
|
|
21
|
+
* @returns Generated command with path and file content
|
|
22
|
+
*/
|
|
23
|
+
export function generateCommand(content, adapter) {
|
|
24
|
+
const invocation = getInvocationForAdapter(adapter);
|
|
25
|
+
const formatted = needsInvocationRewrite(invocation)
|
|
26
|
+
? { ...content, body: transformCommandInvocations(content.body, invocation) }
|
|
27
|
+
: content;
|
|
28
|
+
return {
|
|
29
|
+
path: adapter.getFilePath(content.id),
|
|
30
|
+
fileContent: adapter.formatFile(formatted),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Generate multiple command files using the provided adapter.
|
|
35
|
+
* @param contents - Array of tool-agnostic command contents
|
|
36
|
+
* @param adapter - The tool-specific adapter
|
|
37
|
+
* @returns Array of generated commands with paths and file contents
|
|
38
|
+
*/
|
|
39
|
+
export function generateCommands(contents, adapter) {
|
|
40
|
+
return contents.map((content) => generateCommand(content, adapter));
|
|
41
|
+
}
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Generation Module
|
|
3
|
+
*
|
|
4
|
+
* Generic command generation system with tool-specific adapters.
|
|
5
|
+
*
|
|
6
|
+
* FreeHarness trim: adapter re-export reduced to claude + opencode.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { generateCommands, CommandAdapterRegistry, type CommandContent } from './command-generation/index.js';
|
|
11
|
+
*
|
|
12
|
+
* const contents: CommandContent[] = [...];
|
|
13
|
+
* const adapter = CommandAdapterRegistry.get('claude');
|
|
14
|
+
* if (adapter) {
|
|
15
|
+
* const commands = generateCommands(contents, adapter);
|
|
16
|
+
* // Write commands to disk
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export type { CommandContent, ToolCommandAdapter, GeneratedCommand, } from './types.js';
|
|
21
|
+
export { CommandAdapterRegistry } from './registry.js';
|
|
22
|
+
export { generateCommand, generateCommands } from './generator.js';
|
|
23
|
+
export { claudeAdapter, opencodeAdapter } from './adapters/index.js';
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/generation/command-generation/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command Generation Module
|
|
3
|
+
*
|
|
4
|
+
* Generic command generation system with tool-specific adapters.
|
|
5
|
+
*
|
|
6
|
+
* FreeHarness trim: adapter re-export reduced to claude + opencode.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```typescript
|
|
10
|
+
* import { generateCommands, CommandAdapterRegistry, type CommandContent } from './command-generation/index.js';
|
|
11
|
+
*
|
|
12
|
+
* const contents: CommandContent[] = [...];
|
|
13
|
+
* const adapter = CommandAdapterRegistry.get('claude');
|
|
14
|
+
* if (adapter) {
|
|
15
|
+
* const commands = generateCommands(contents, adapter);
|
|
16
|
+
* // Write commands to disk
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
// Registry
|
|
21
|
+
export { CommandAdapterRegistry } from './registry.js';
|
|
22
|
+
// Generator functions
|
|
23
|
+
export { generateCommand, generateCommands } from './generator.js';
|
|
24
|
+
// Adapters (for direct access if needed)
|
|
25
|
+
export { claudeAdapter, opencodeAdapter } from './adapters/index.js';
|