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
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/parsers/spec-structure.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { buildCodeFenceMask } from './code-fence.js';
|
|
2
|
+
const REQUIREMENTS_SECTION_HEADER = /^##\s+Requirements\s*$/i;
|
|
3
|
+
const TOP_LEVEL_SECTION_HEADER = /^##\s+/;
|
|
4
|
+
const DELTA_HEADER = /^##\s+(ADDED|MODIFIED|REMOVED|RENAMED)\s+Requirements\s*$/i;
|
|
5
|
+
const REQUIREMENT_HEADER = /^###\s+Requirement:\s*(.+)\s*$/i;
|
|
6
|
+
export function findMainSpecStructureIssues(content) {
|
|
7
|
+
const normalized = content.replace(/\r\n?/g, '\n');
|
|
8
|
+
const stripped = stripFencedCodeBlocksPreservingLines(normalized);
|
|
9
|
+
const lines = stripped.split('\n');
|
|
10
|
+
const issues = [];
|
|
11
|
+
const requirementLines = new Map();
|
|
12
|
+
const requirementsHeaderIndex = lines.findIndex(line => REQUIREMENTS_SECTION_HEADER.test(line));
|
|
13
|
+
let requirementsEndIndex = lines.length;
|
|
14
|
+
if (requirementsHeaderIndex !== -1) {
|
|
15
|
+
for (let i = requirementsHeaderIndex + 1; i < lines.length; i++) {
|
|
16
|
+
if (TOP_LEVEL_SECTION_HEADER.test(lines[i])) {
|
|
17
|
+
requirementsEndIndex = i;
|
|
18
|
+
break;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
for (let i = 0; i < lines.length; i++) {
|
|
23
|
+
const line = lines[i];
|
|
24
|
+
const trimmed = line.trim();
|
|
25
|
+
if (!trimmed) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (DELTA_HEADER.test(line)) {
|
|
29
|
+
issues.push({
|
|
30
|
+
kind: 'delta-header',
|
|
31
|
+
line: i + 1,
|
|
32
|
+
header: trimmed,
|
|
33
|
+
message: `Main spec contains delta header "${trimmed}". ` +
|
|
34
|
+
'Delta headers are only valid inside openspec/changes/<name>/specs/<capability-path>/spec.md ' +
|
|
35
|
+
'and truncate the parsed ## Requirements section.',
|
|
36
|
+
});
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const requirementMatch = line.match(REQUIREMENT_HEADER);
|
|
40
|
+
if (!requirementMatch) {
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const insideRequirements = requirementsHeaderIndex !== -1 &&
|
|
44
|
+
i > requirementsHeaderIndex &&
|
|
45
|
+
i < requirementsEndIndex;
|
|
46
|
+
if (!insideRequirements) {
|
|
47
|
+
issues.push({
|
|
48
|
+
kind: 'requirement-outside-requirements',
|
|
49
|
+
line: i + 1,
|
|
50
|
+
header: trimmed,
|
|
51
|
+
message: `Requirement header "${trimmed}" appears outside the main ## Requirements section. ` +
|
|
52
|
+
'Main specs only parse requirements inside that section, so this requirement is currently invisible to validate, list, and archive.',
|
|
53
|
+
});
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
const requirementName = requirementMatch[1].trim();
|
|
57
|
+
const previousLine = requirementLines.get(requirementName);
|
|
58
|
+
if (previousLine !== undefined) {
|
|
59
|
+
issues.push({
|
|
60
|
+
kind: 'duplicate-requirement',
|
|
61
|
+
line: i + 1,
|
|
62
|
+
header: trimmed,
|
|
63
|
+
message: `Requirement header "${trimmed}" duplicates the requirement declared on line ${previousLine}. ` +
|
|
64
|
+
'Requirement names must be unique so spec updates cannot discard one block while updating another.',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
requirementLines.set(requirementName, i + 1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return issues;
|
|
72
|
+
}
|
|
73
|
+
export function stripFencedCodeBlocksPreservingLines(content) {
|
|
74
|
+
const lines = content.split('\n');
|
|
75
|
+
const mask = buildCodeFenceMask(lines);
|
|
76
|
+
return lines.map((line, i) => (mask[i] ? '' : line)).join('\n');
|
|
77
|
+
}
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/purpose-placeholder.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detects a `## Purpose` that is still a placeholder, rather than one somebody
|
|
3
|
+
* wrote.
|
|
4
|
+
*
|
|
5
|
+
* When a delta introduces a capability with no usable `## Purpose`, archive
|
|
6
|
+
* stamps the placeholder into the new main spec. That text is over
|
|
7
|
+
* `MIN_PURPOSE_LENGTH`, so the brevity check cannot reach it: the one rule that
|
|
8
|
+
* exists to catch a Purpose nobody wrote is satisfied by the exact string
|
|
9
|
+
* meaning nobody wrote one. Nothing else reads it afterwards, so the capability
|
|
10
|
+
* keeps a to-do in it while every command reports success.
|
|
11
|
+
*
|
|
12
|
+
* Two things count, and deliberately nothing else:
|
|
13
|
+
*
|
|
14
|
+
* - the placeholder this tool generates, recognised through the same constants
|
|
15
|
+
* the writer composes it from, wherever it sits in the Purpose - nobody types
|
|
16
|
+
* that sentence by accident;
|
|
17
|
+
* - a `TBD` or `TODO` **opening** the Purpose, which is the marker left behind
|
|
18
|
+
* when someone is told to leave "a brief TBD placeholder" and never comes
|
|
19
|
+
* back. Which of the two words got typed says nothing about whether the
|
|
20
|
+
* Purpose was written, so both are read the same way.
|
|
21
|
+
*
|
|
22
|
+
* A marker inside a sentence is left alone. "The retry budget is TBD pending
|
|
23
|
+
* benchmarks" is a real Purpose with an open question in it, and reporting it
|
|
24
|
+
* would teach people to ignore the warning - which costs more than the findings
|
|
25
|
+
* it would add.
|
|
26
|
+
*
|
|
27
|
+
* Fenced code inside the Purpose is quoted material rather than the Purpose
|
|
28
|
+
* speaking, so it is read out first. Without that, a Purpose documenting the
|
|
29
|
+
* sentence archive writes is reported as being that sentence: a document about
|
|
30
|
+
* the placeholder, failing for carrying one.
|
|
31
|
+
*/
|
|
32
|
+
export interface PurposePlaceholderIssue {
|
|
33
|
+
/** 1-based line of the placeholder text, when it can be located. */
|
|
34
|
+
line?: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Reports the Purpose of a main spec as an unwritten placeholder, or null when
|
|
38
|
+
* it reads as authored content.
|
|
39
|
+
*
|
|
40
|
+
* An empty Purpose is not reported here - `SPEC_PURPOSE_EMPTY` already covers
|
|
41
|
+
* it, and reporting both would put two findings on one line. That falls out of
|
|
42
|
+
* the two rules rather than needing a case of its own.
|
|
43
|
+
*/
|
|
44
|
+
export declare function findPurposePlaceholderIssue(overview: string, content?: string): PurposePlaceholderIssue | null;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { buildCodeFenceMask } from './parsers/code-fence.js';
|
|
2
|
+
import { PURPOSE_PLACEHOLDER_PREFIX, PURPOSE_PLACEHOLDER_SUFFIX } from './constants.js';
|
|
3
|
+
/**
|
|
4
|
+
* A `TBD` or `TODO` opening the Purpose. The lookahead keeps it off a longer
|
|
5
|
+
* word that merely begins with those letters, like "TBDs" or "TODOs", while
|
|
6
|
+
* still allowing the punctuation a marker is usually written with: `TODO:`,
|
|
7
|
+
* `TBD -`. It rejects any letter, digit or combining mark rather than only the
|
|
8
|
+
* ASCII ones `\b` knows about, because a Purpose is prose and prose is not
|
|
9
|
+
* always written in Latin script - `TBD` followed by an Arabic-Indic digit is
|
|
10
|
+
* as much a longer word as `TBDs` is.
|
|
11
|
+
*/
|
|
12
|
+
const LEADING_MARKER = /^(?:TBD|TODO)(?![\p{L}\p{N}\p{M}_])/iu;
|
|
13
|
+
const PURPOSE_HEADER = /^ {0,3}##(?!#)[ \t]+Purpose[ \t]*$/i;
|
|
14
|
+
const TOP_LEVEL_HEADER = /^ {0,3}#{1,2}(?!#)[ \t]+/;
|
|
15
|
+
/**
|
|
16
|
+
* The lines of `text` that sit outside a fenced code block, with line endings
|
|
17
|
+
* normalised first.
|
|
18
|
+
*
|
|
19
|
+
* `buildCodeFenceMask` is the masker the requirement and structure parsers
|
|
20
|
+
* already share, and its own reason for existing is that a second, private
|
|
21
|
+
* notion of what a fence is drifts from the first. This check reads Markdown
|
|
22
|
+
* for the same purpose they do, so it reads fences the same way they do.
|
|
23
|
+
*/
|
|
24
|
+
function unfencedLines(text) {
|
|
25
|
+
const lines = text.replace(/\r\n?/g, '\n').split('\n');
|
|
26
|
+
const fenced = buildCodeFenceMask(lines);
|
|
27
|
+
return lines.filter((_, index) => !fenced[index]);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* True when the text carries the sentence archive writes. Matched as its two
|
|
31
|
+
* fixed halves in order, because the change name between them varies - so the
|
|
32
|
+
* check follows the writer's own definition instead of a second copy of it.
|
|
33
|
+
*/
|
|
34
|
+
function generatedPlaceholderPrefixIndex(text) {
|
|
35
|
+
let suffixAt = text.indexOf(PURPOSE_PLACEHOLDER_SUFFIX);
|
|
36
|
+
while (suffixAt !== -1) {
|
|
37
|
+
// Use the closest prefix before this suffix. An authored explanation can
|
|
38
|
+
// mention the prefix above the real placeholder; choosing the first prefix
|
|
39
|
+
// would then point the diagnostic at the explanation instead of the text
|
|
40
|
+
// the user needs to replace.
|
|
41
|
+
const prefixAt = text.lastIndexOf(PURPOSE_PLACEHOLDER_PREFIX, suffixAt);
|
|
42
|
+
if (prefixAt !== -1)
|
|
43
|
+
return prefixAt;
|
|
44
|
+
suffixAt = text.indexOf(PURPOSE_PLACEHOLDER_SUFFIX, suffixAt + 1);
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Reports the Purpose of a main spec as an unwritten placeholder, or null when
|
|
50
|
+
* it reads as authored content.
|
|
51
|
+
*
|
|
52
|
+
* An empty Purpose is not reported here - `SPEC_PURPOSE_EMPTY` already covers
|
|
53
|
+
* it, and reporting both would put two findings on one line. That falls out of
|
|
54
|
+
* the two rules rather than needing a case of its own.
|
|
55
|
+
*/
|
|
56
|
+
export function findPurposePlaceholderIssue(overview, content) {
|
|
57
|
+
// An empty Purpose needs no branch of its own: neither rule matches empty
|
|
58
|
+
// text, so it falls through to null on the line below. An early return for it
|
|
59
|
+
// would be a guard no test could hold, which is worse than none. A Purpose
|
|
60
|
+
// that is nothing but a fenced block reduces to the same empty text here, and
|
|
61
|
+
// is left to the brevity and empty-Purpose rules for the same reason.
|
|
62
|
+
const prose = unfencedLines(overview).join('\n').trim();
|
|
63
|
+
const leading = LEADING_MARKER.test(prose);
|
|
64
|
+
if (!leading && generatedPlaceholderPrefixIndex(prose) === undefined)
|
|
65
|
+
return null;
|
|
66
|
+
// Which rule matched decides where the placeholder is, so the locator is told.
|
|
67
|
+
// When both match the leading marker wins: it sits at or above the generated
|
|
68
|
+
// sentence, and the earliest marker is the one a reader scanning down meets.
|
|
69
|
+
return { line: content === undefined ? undefined : findPlaceholderLine(content, leading) };
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* The line inside the `## Purpose` section carrying the placeholder, so the
|
|
73
|
+
* warning points at the text to replace rather than at the file.
|
|
74
|
+
*
|
|
75
|
+
* Which line that is depends on the rule that matched. A leading marker is the
|
|
76
|
+
* section's first non-blank line by definition. The generated sentence is not:
|
|
77
|
+
* it can follow prose somebody wrote, and naming the first non-blank line then
|
|
78
|
+
* points at that prose - a line the reader can see is fine, which reads as the
|
|
79
|
+
* check being wrong rather than the Purpose being unwritten.
|
|
80
|
+
*
|
|
81
|
+
* Fenced lines are skipped on the way, for the reason detection skips them, and
|
|
82
|
+
* so a `## Requirements` quoted inside a fence cannot end the section early.
|
|
83
|
+
*
|
|
84
|
+
* Undefined when the placeholder cannot be located - no section header, or a
|
|
85
|
+
* generated sentence no single line carries. The caller then reports the finding
|
|
86
|
+
* without a line rather than with a guessed one, since a wrong line number is
|
|
87
|
+
* worse than none.
|
|
88
|
+
*
|
|
89
|
+
* Line endings are normalised first, so the same spec reports the same line
|
|
90
|
+
* whether it was saved on Windows or on macOS/Linux.
|
|
91
|
+
*/
|
|
92
|
+
function findPlaceholderLine(content, leading) {
|
|
93
|
+
const lines = content.replace(/\r\n?/g, '\n').split('\n');
|
|
94
|
+
const fenced = buildCodeFenceMask(lines);
|
|
95
|
+
const headerIndex = lines.findIndex((line, index) => !fenced[index] && PURPOSE_HEADER.test(line));
|
|
96
|
+
if (headerIndex === -1)
|
|
97
|
+
return undefined;
|
|
98
|
+
const purposeLines = [];
|
|
99
|
+
for (let i = headerIndex + 1; i < lines.length; i++) {
|
|
100
|
+
if (fenced[i])
|
|
101
|
+
continue;
|
|
102
|
+
if (TOP_LEVEL_HEADER.test(lines[i]))
|
|
103
|
+
break;
|
|
104
|
+
if (leading && lines[i].trim())
|
|
105
|
+
return i + 1;
|
|
106
|
+
purposeLines.push({ line: i + 1, text: lines[i] });
|
|
107
|
+
}
|
|
108
|
+
if (leading)
|
|
109
|
+
return undefined;
|
|
110
|
+
const purpose = purposeLines.map(({ text }) => text).join('\n');
|
|
111
|
+
const prefixAt = generatedPlaceholderPrefixIndex(purpose);
|
|
112
|
+
if (prefixAt === undefined)
|
|
113
|
+
return undefined;
|
|
114
|
+
const lineOffset = purpose.slice(0, prefixAt).split('\n').length - 1;
|
|
115
|
+
return purposeLines[lineOffset]?.line;
|
|
116
|
+
}
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/base.schema.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const ScenarioSchema: z.ZodObject<{
|
|
3
|
+
rawText: z.ZodString;
|
|
4
|
+
}, z.core.$strip>;
|
|
5
|
+
export declare const RequirementSchema: z.ZodObject<{
|
|
6
|
+
text: z.ZodString;
|
|
7
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
8
|
+
rawText: z.ZodString;
|
|
9
|
+
}, z.core.$strip>>;
|
|
10
|
+
}, z.core.$strip>;
|
|
11
|
+
export type Scenario = z.infer<typeof ScenarioSchema>;
|
|
12
|
+
export type Requirement = z.infer<typeof RequirementSchema>;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { VALIDATION_MESSAGES } from '../constants.js';
|
|
3
|
+
export const ScenarioSchema = z.object({
|
|
4
|
+
rawText: z.string().min(1, VALIDATION_MESSAGES.SCENARIO_EMPTY),
|
|
5
|
+
});
|
|
6
|
+
export const RequirementSchema = z.object({
|
|
7
|
+
// SHALL/MUST body-keyword enforcement lives in the imperative validator
|
|
8
|
+
// (Validator.applySpecRules), not here: the parser collapses the requirement
|
|
9
|
+
// header into `text`, so a Zod refine on `text` cannot tell "keyword in header
|
|
10
|
+
// only" from "keyword in body" and emits a misleading generic error. The
|
|
11
|
+
// validator recovers the header and emits the targeted hint for both the
|
|
12
|
+
// main-spec and change-delta paths (#1156).
|
|
13
|
+
text: z.string()
|
|
14
|
+
.min(1, VALIDATION_MESSAGES.REQUIREMENT_EMPTY),
|
|
15
|
+
scenarios: z.array(ScenarioSchema)
|
|
16
|
+
.min(1, VALIDATION_MESSAGES.REQUIREMENT_NO_SCENARIOS),
|
|
17
|
+
});
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const DeltaOperationType: z.ZodEnum<{
|
|
3
|
+
ADDED: "ADDED";
|
|
4
|
+
MODIFIED: "MODIFIED";
|
|
5
|
+
REMOVED: "REMOVED";
|
|
6
|
+
RENAMED: "RENAMED";
|
|
7
|
+
}>;
|
|
8
|
+
export declare const DeltaSchema: z.ZodObject<{
|
|
9
|
+
spec: z.ZodString;
|
|
10
|
+
operation: z.ZodEnum<{
|
|
11
|
+
ADDED: "ADDED";
|
|
12
|
+
MODIFIED: "MODIFIED";
|
|
13
|
+
REMOVED: "REMOVED";
|
|
14
|
+
RENAMED: "RENAMED";
|
|
15
|
+
}>;
|
|
16
|
+
description: z.ZodString;
|
|
17
|
+
requirement: z.ZodOptional<z.ZodObject<{
|
|
18
|
+
text: z.ZodString;
|
|
19
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
20
|
+
rawText: z.ZodString;
|
|
21
|
+
}, z.core.$strip>>;
|
|
22
|
+
}, z.core.$strip>>;
|
|
23
|
+
requirements: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
24
|
+
text: z.ZodString;
|
|
25
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
26
|
+
rawText: z.ZodString;
|
|
27
|
+
}, z.core.$strip>>;
|
|
28
|
+
}, z.core.$strip>>>;
|
|
29
|
+
rename: z.ZodOptional<z.ZodObject<{
|
|
30
|
+
from: z.ZodString;
|
|
31
|
+
to: z.ZodString;
|
|
32
|
+
}, z.core.$strip>>;
|
|
33
|
+
}, z.core.$strip>;
|
|
34
|
+
export declare const ChangeSchema: z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
why: z.ZodString;
|
|
37
|
+
whatChanges: z.ZodString;
|
|
38
|
+
deltas: z.ZodArray<z.ZodObject<{
|
|
39
|
+
spec: z.ZodString;
|
|
40
|
+
operation: z.ZodEnum<{
|
|
41
|
+
ADDED: "ADDED";
|
|
42
|
+
MODIFIED: "MODIFIED";
|
|
43
|
+
REMOVED: "REMOVED";
|
|
44
|
+
RENAMED: "RENAMED";
|
|
45
|
+
}>;
|
|
46
|
+
description: z.ZodString;
|
|
47
|
+
requirement: z.ZodOptional<z.ZodObject<{
|
|
48
|
+
text: z.ZodString;
|
|
49
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
50
|
+
rawText: z.ZodString;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
requirements: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
54
|
+
text: z.ZodString;
|
|
55
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
56
|
+
rawText: z.ZodString;
|
|
57
|
+
}, z.core.$strip>>;
|
|
58
|
+
}, z.core.$strip>>>;
|
|
59
|
+
rename: z.ZodOptional<z.ZodObject<{
|
|
60
|
+
from: z.ZodString;
|
|
61
|
+
to: z.ZodString;
|
|
62
|
+
}, z.core.$strip>>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
65
|
+
version: z.ZodDefault<z.ZodString>;
|
|
66
|
+
format: z.ZodLiteral<"openspec-change">;
|
|
67
|
+
sourcePath: z.ZodOptional<z.ZodString>;
|
|
68
|
+
}, z.core.$strip>>;
|
|
69
|
+
}, z.core.$strip>;
|
|
70
|
+
export type DeltaOperation = z.infer<typeof DeltaOperationType>;
|
|
71
|
+
export type Delta = z.infer<typeof DeltaSchema>;
|
|
72
|
+
export type Change = z.infer<typeof ChangeSchema>;
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/change.schema.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { RequirementSchema } from './base.schema.js';
|
|
3
|
+
import { MIN_WHY_SECTION_LENGTH, MAX_WHY_SECTION_LENGTH, MAX_DELTAS_PER_CHANGE, VALIDATION_MESSAGES } from '../constants.js';
|
|
4
|
+
export const DeltaOperationType = z.enum(['ADDED', 'MODIFIED', 'REMOVED', 'RENAMED']);
|
|
5
|
+
export const DeltaSchema = z.object({
|
|
6
|
+
spec: z.string().min(1, VALIDATION_MESSAGES.DELTA_SPEC_EMPTY),
|
|
7
|
+
operation: DeltaOperationType,
|
|
8
|
+
description: z.string().min(1, VALIDATION_MESSAGES.DELTA_DESCRIPTION_EMPTY),
|
|
9
|
+
requirement: RequirementSchema.optional(),
|
|
10
|
+
requirements: z.array(RequirementSchema).optional(),
|
|
11
|
+
rename: z.object({
|
|
12
|
+
from: z.string(),
|
|
13
|
+
to: z.string(),
|
|
14
|
+
}).optional(),
|
|
15
|
+
});
|
|
16
|
+
export const ChangeSchema = z.object({
|
|
17
|
+
name: z.string().min(1, VALIDATION_MESSAGES.CHANGE_NAME_EMPTY),
|
|
18
|
+
why: z.string()
|
|
19
|
+
.min(MIN_WHY_SECTION_LENGTH, VALIDATION_MESSAGES.CHANGE_WHY_TOO_SHORT)
|
|
20
|
+
.max(MAX_WHY_SECTION_LENGTH, VALIDATION_MESSAGES.CHANGE_WHY_TOO_LONG),
|
|
21
|
+
whatChanges: z.string().min(1, VALIDATION_MESSAGES.CHANGE_WHAT_EMPTY),
|
|
22
|
+
deltas: z.array(DeltaSchema)
|
|
23
|
+
.min(1, VALIDATION_MESSAGES.CHANGE_NO_DELTAS)
|
|
24
|
+
.max(MAX_DELTAS_PER_CHANGE, VALIDATION_MESSAGES.CHANGE_TOO_MANY_DELTAS),
|
|
25
|
+
metadata: z.object({
|
|
26
|
+
version: z.string().default('1.0.0'),
|
|
27
|
+
format: z.literal('openspec-change'),
|
|
28
|
+
sourcePath: z.string().optional(),
|
|
29
|
+
}).optional(),
|
|
30
|
+
});
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export { ScenarioSchema, RequirementSchema, type Scenario, type Requirement, } from './base.schema.js';
|
|
2
|
+
export { SpecSchema, type Spec, } from './spec.schema.js';
|
|
3
|
+
export { DeltaOperationType, DeltaSchema, ChangeSchema, type DeltaOperation, type Delta, type Change, } from './change.schema.js';
|
package/node_modules/@freeharness/sdd/dist/vendor/openspec/validation/schemas/spec.schema.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const SpecSchema: z.ZodObject<{
|
|
3
|
+
name: z.ZodString;
|
|
4
|
+
overview: z.ZodString;
|
|
5
|
+
requirements: z.ZodArray<z.ZodObject<{
|
|
6
|
+
text: z.ZodString;
|
|
7
|
+
scenarios: z.ZodArray<z.ZodObject<{
|
|
8
|
+
rawText: z.ZodString;
|
|
9
|
+
}, z.core.$strip>>;
|
|
10
|
+
}, z.core.$strip>>;
|
|
11
|
+
metadata: z.ZodOptional<z.ZodObject<{
|
|
12
|
+
version: z.ZodDefault<z.ZodString>;
|
|
13
|
+
format: z.ZodLiteral<"openspec">;
|
|
14
|
+
sourcePath: z.ZodOptional<z.ZodString>;
|
|
15
|
+
}, z.core.$strip>>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export type Spec = z.infer<typeof SpecSchema>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { RequirementSchema } from './base.schema.js';
|
|
3
|
+
import { VALIDATION_MESSAGES } from '../constants.js';
|
|
4
|
+
export const SpecSchema = z.object({
|
|
5
|
+
name: z.string().min(1, VALIDATION_MESSAGES.SPEC_NAME_EMPTY),
|
|
6
|
+
overview: z.string().min(1, VALIDATION_MESSAGES.SPEC_PURPOSE_EMPTY),
|
|
7
|
+
requirements: z.array(RequirementSchema)
|
|
8
|
+
.min(1, VALIDATION_MESSAGES.SPEC_NO_REQUIREMENTS),
|
|
9
|
+
metadata: z.object({
|
|
10
|
+
version: z.string().default('1.0.0'),
|
|
11
|
+
format: z.literal('openspec'),
|
|
12
|
+
sourcePath: z.string().optional(),
|
|
13
|
+
}).optional(),
|
|
14
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface DiscoveredSpec {
|
|
2
|
+
/** Spec id relative to the specs root, forward-slash separated on every platform (e.g. "web" or "platform/session-layout"). */
|
|
3
|
+
id: string;
|
|
4
|
+
/** Path to the spec.md file (absolute if the specs root is absolute). */
|
|
5
|
+
specFile: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Recursively discover every `spec.md` under a specs root, so both the flat
|
|
9
|
+
* `specs/<id>/spec.md` layout and nested `specs/<area>/<id>/spec.md` layouts
|
|
10
|
+
* are found (#1353). A `spec.md` sitting directly in the root is ignored,
|
|
11
|
+
* matching the historical requirement that specs live in a capability folder.
|
|
12
|
+
* Dot-directories are skipped and symlinked directories are not followed.
|
|
13
|
+
* An in-capability symlinked `spec.md` IS resolved: `hasAnyFileUnder` and the
|
|
14
|
+
* artifact graph's globs both count it as content, so dropping it here would
|
|
15
|
+
* silently lose the delta on archive. A link outside its capability is
|
|
16
|
+
* rejected and a dangling link is skipped. Results are sorted by id.
|
|
17
|
+
*
|
|
18
|
+
* A missing root (ENOENT) yields an empty list, but any other read failure
|
|
19
|
+
* (EACCES, EIO, ...) is thrown rather than swallowed: since this feeds the
|
|
20
|
+
* archive/apply merge path, silently dropping an unreadable capability would
|
|
21
|
+
* recreate the exact data-loss class #1353 is closing.
|
|
22
|
+
*/
|
|
23
|
+
export declare function discoverSpecFiles(specsRoot: string): Promise<DiscoveredSpec[]>;
|
|
24
|
+
/**
|
|
25
|
+
* True when any regular non-dot file exists anywhere under the given
|
|
26
|
+
* directory. Used by validate/archive to detect content under a change's
|
|
27
|
+
* specs/ that contradicts a declared skip_specs marker - including files that
|
|
28
|
+
* discoverSpecFiles ignores (a root spec.md, stray non-spec.md notes), since
|
|
29
|
+
* anything there would be silently dropped or misread while the change claims
|
|
30
|
+
* to have nothing. Dot entries (.DS_Store, .gitkeep, dot-directories) are
|
|
31
|
+
* skipped to match discoverSpecFiles - they are invisible to every other
|
|
32
|
+
* code path, so they must not count as spec content. Symlinks DO count
|
|
33
|
+
* (without being followed): the artifact graph's globs follow them, so a
|
|
34
|
+
* symlinked spec would read as existing content while the change claims to
|
|
35
|
+
* have none - it contradicts the marker like any regular file. A missing
|
|
36
|
+
* directory returns false; other read failures are thrown for the caller to
|
|
37
|
+
* decide.
|
|
38
|
+
*/
|
|
39
|
+
export declare function hasAnyFileUnder(dirPath: string): Promise<boolean>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { FileSystemUtils } from '../engine/file-system.js';
|
|
4
|
+
function assertDiscoveredSpecPath(specsRoot, capabilityDir, specFile) {
|
|
5
|
+
try {
|
|
6
|
+
FileSystemUtils.assertPathWithin(specsRoot, specFile);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
// Direct capability directories may intentionally be external monorepo
|
|
10
|
+
// links. In that case, confine the file to the capability itself.
|
|
11
|
+
FileSystemUtils.assertPathWithin(capabilityDir, specFile);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Recursively discover every `spec.md` under a specs root, so both the flat
|
|
16
|
+
* `specs/<id>/spec.md` layout and nested `specs/<area>/<id>/spec.md` layouts
|
|
17
|
+
* are found (#1353). A `spec.md` sitting directly in the root is ignored,
|
|
18
|
+
* matching the historical requirement that specs live in a capability folder.
|
|
19
|
+
* Dot-directories are skipped and symlinked directories are not followed.
|
|
20
|
+
* An in-capability symlinked `spec.md` IS resolved: `hasAnyFileUnder` and the
|
|
21
|
+
* artifact graph's globs both count it as content, so dropping it here would
|
|
22
|
+
* silently lose the delta on archive. A link outside its capability is
|
|
23
|
+
* rejected and a dangling link is skipped. Results are sorted by id.
|
|
24
|
+
*
|
|
25
|
+
* A missing root (ENOENT) yields an empty list, but any other read failure
|
|
26
|
+
* (EACCES, EIO, ...) is thrown rather than swallowed: since this feeds the
|
|
27
|
+
* archive/apply merge path, silently dropping an unreadable capability would
|
|
28
|
+
* recreate the exact data-loss class #1353 is closing.
|
|
29
|
+
*/
|
|
30
|
+
export async function discoverSpecFiles(specsRoot) {
|
|
31
|
+
const results = [];
|
|
32
|
+
const walk = async (dir, segments) => {
|
|
33
|
+
let entries;
|
|
34
|
+
try {
|
|
35
|
+
entries = await fs.readdir(dir, { withFileTypes: true });
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
if (err?.code === 'ENOENT')
|
|
39
|
+
return;
|
|
40
|
+
throw err;
|
|
41
|
+
}
|
|
42
|
+
for (const entry of entries) {
|
|
43
|
+
if (entry.name.startsWith('.'))
|
|
44
|
+
continue;
|
|
45
|
+
if (entry.isDirectory()) {
|
|
46
|
+
await walk(path.join(dir, entry.name), [...segments, entry.name]);
|
|
47
|
+
}
|
|
48
|
+
else if (entry.name === 'spec.md' && segments.length > 0) {
|
|
49
|
+
const specFile = path.join(dir, entry.name);
|
|
50
|
+
if (entry.isFile()) {
|
|
51
|
+
assertDiscoveredSpecPath(specsRoot, dir, specFile);
|
|
52
|
+
results.push({ id: segments.join('/'), specFile });
|
|
53
|
+
}
|
|
54
|
+
else if (entry.isSymbolicLink()) {
|
|
55
|
+
try {
|
|
56
|
+
if ((await fs.stat(specFile)).isFile()) {
|
|
57
|
+
assertDiscoveredSpecPath(specsRoot, dir, specFile);
|
|
58
|
+
results.push({ id: segments.join('/'), specFile });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
// A dangling link is not content; anything else fails loudly.
|
|
63
|
+
if (err?.code !== 'ENOENT')
|
|
64
|
+
throw err;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
await walk(specsRoot, []);
|
|
71
|
+
// Plain code-point comparison, not localeCompare: the latter follows the
|
|
72
|
+
// process's ICU locale, so ordering could vary by OS/CI. Code-point ordering
|
|
73
|
+
// guarantees the deterministic output the docstring promises.
|
|
74
|
+
return results.sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* True when any regular non-dot file exists anywhere under the given
|
|
78
|
+
* directory. Used by validate/archive to detect content under a change's
|
|
79
|
+
* specs/ that contradicts a declared skip_specs marker - including files that
|
|
80
|
+
* discoverSpecFiles ignores (a root spec.md, stray non-spec.md notes), since
|
|
81
|
+
* anything there would be silently dropped or misread while the change claims
|
|
82
|
+
* to have nothing. Dot entries (.DS_Store, .gitkeep, dot-directories) are
|
|
83
|
+
* skipped to match discoverSpecFiles - they are invisible to every other
|
|
84
|
+
* code path, so they must not count as spec content. Symlinks DO count
|
|
85
|
+
* (without being followed): the artifact graph's globs follow them, so a
|
|
86
|
+
* symlinked spec would read as existing content while the change claims to
|
|
87
|
+
* have none - it contradicts the marker like any regular file. A missing
|
|
88
|
+
* directory returns false; other read failures are thrown for the caller to
|
|
89
|
+
* decide.
|
|
90
|
+
*/
|
|
91
|
+
export async function hasAnyFileUnder(dirPath) {
|
|
92
|
+
let entries;
|
|
93
|
+
try {
|
|
94
|
+
entries = await fs.readdir(dirPath, { withFileTypes: true });
|
|
95
|
+
}
|
|
96
|
+
catch (err) {
|
|
97
|
+
if (err?.code === 'ENOENT') {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
throw err;
|
|
101
|
+
}
|
|
102
|
+
for (const entry of entries) {
|
|
103
|
+
if (entry.name.startsWith('.')) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
if (entry.isFile() || entry.isSymbolicLink()) {
|
|
107
|
+
return true;
|
|
108
|
+
}
|
|
109
|
+
if (entry.isDirectory() && (await hasAnyFileUnder(path.join(dirPath, entry.name)))) {
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return false;
|
|
114
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
export interface ParsedTask {
|
|
2
|
+
/** Checkbox state: `[x]`/`[X]` is done, anything else is not. */
|
|
3
|
+
done: boolean;
|
|
4
|
+
/** Task text after the checkbox, trimmed (may be empty). */
|
|
5
|
+
description: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Parses every task line in a tasks file, in document order. Every line matching
|
|
9
|
+
* the pattern counts, wherever it sits (inside a code fence, HTML comment, or an
|
|
10
|
+
* indented block), matching upstream.
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseTaskLines(content: string): ParsedTask[];
|
|
13
|
+
/** The annotation keys the tasks template documents. */
|
|
14
|
+
export declare const TASK_ANNOTATION_KEYS: readonly ["Verify", "Interfaces", "Boundary", "Depends", "Disposition"];
|
|
15
|
+
export type TaskAnnotationKey = (typeof TASK_ANNOTATION_KEYS)[number];
|
|
16
|
+
/**
|
|
17
|
+
* A task resolved outside this change: `superseded`/`moved` name another
|
|
18
|
+
* change id, `external` carries free-form reference text. `kind` is the raw
|
|
19
|
+
* first token of the `Disposition:` value, so a value outside the three
|
|
20
|
+
* documented kinds still parses (a reader such as `validate --strict` reports
|
|
21
|
+
* it, rather than the parser silently dropping the line).
|
|
22
|
+
*/
|
|
23
|
+
export interface TaskDisposition {
|
|
24
|
+
kind: string;
|
|
25
|
+
target: string;
|
|
26
|
+
}
|
|
27
|
+
export interface AnnotatedTask extends ParsedTask {
|
|
28
|
+
/** 1-based line of the checkbox in the tasks file. */
|
|
29
|
+
line: number;
|
|
30
|
+
/** Annotation lines that followed the checkbox, keyed by their label. */
|
|
31
|
+
annotations: Partial<Record<TaskAnnotationKey, string>>;
|
|
32
|
+
/** Parsed `Disposition:` line, or null when the task carries none. */
|
|
33
|
+
disposition: TaskDisposition | null;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* True when the line is one of the documented annotation lines. Such a line is
|
|
37
|
+
* never a task, whatever precedes it.
|
|
38
|
+
*/
|
|
39
|
+
export declare function isTaskAnnotationLine(line: string): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Parses task lines and attaches the annotation lines that directly follow each
|
|
42
|
+
* task (blank lines and non-annotation prose end the run). The task count is
|
|
43
|
+
* exactly `parseTaskLines(content).length`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseAnnotatedTaskLines(content: string): AnnotatedTask[];
|