bmad-module-skill-forge 2.2.0 → 3.0.0
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/.claude-plugin/marketplace.json +1 -1
- package/README.md +49 -49
- package/docs/404.md +10 -8
- package/docs/_data/pinned.yaml +22 -13
- package/docs/_internal/STABILITY.md +58 -35
- package/docs/agents.md +39 -53
- package/docs/architecture.md +65 -51
- package/docs/bmad-synergy.md +53 -51
- package/docs/campaign.md +127 -75
- package/docs/concepts.md +34 -28
- package/docs/examples.md +70 -68
- package/docs/forge-auto.md +34 -31
- package/docs/getting-started.md +118 -57
- package/docs/how-it-works.md +25 -21
- package/docs/index.md +15 -15
- package/docs/skill-model.md +70 -59
- package/docs/troubleshooting.md +135 -18
- package/docs/verifying-a-skill.md +83 -57
- package/docs/why-skf.md +24 -22
- package/docs/workflows.md +274 -110
- package/package.json +18 -10
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/agentskills-spec.md +2 -0
- package/src/knowledge/ccc-bridge.md +40 -24
- package/src/knowledge/confidence-tiers.md +9 -5
- package/src/knowledge/overview.md +3 -3
- package/src/knowledge/progressive-capability.md +8 -8
- package/src/knowledge/provenance-tracking.md +9 -5
- package/src/knowledge/qmd-registry.md +2 -2
- package/src/knowledge/skf-knowledge-index.csv +2 -2
- package/src/knowledge/skill-lifecycle.md +18 -11
- package/src/knowledge/split-body-strategy.md +0 -3
- package/src/knowledge/tool-resolution.md +4 -2
- package/src/knowledge/version-paths.md +101 -15
- package/src/module-help.csv +3 -3
- package/src/module.yaml +10 -0
- package/src/shared/data/ast-grep-recipes.yaml +608 -0
- package/src/shared/data/ide-context-files.json +30 -0
- package/src/shared/health-check.md +32 -12
- package/src/shared/references/description-guard-protocol.md +12 -9
- package/src/shared/references/feasibility-report-schema.md +19 -13
- package/src/shared/references/headless-gate-convention.md +55 -3
- package/src/shared/references/output-contract-schema.md +19 -8
- package/src/shared/references/pipeline-contracts.md +94 -29
- package/src/shared/references/tessl-review.md +77 -0
- package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
- package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
- package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
- package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
- package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
- package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
- package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
- package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
- package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
- package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
- package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
- package/src/shared/scripts/skf-atomic-write.py +30 -14
- package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
- package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
- package/src/shared/scripts/skf-check-unit-records.py +184 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
- package/src/shared/scripts/skf-classify-changed-files.py +694 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
- package/src/shared/scripts/skf-count-imports.py +1867 -0
- package/src/shared/scripts/skf-count-tokens.py +1 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
- package/src/shared/scripts/skf-description-guard.py +99 -11
- package/src/shared/scripts/skf-detect-docs.py +694 -2
- package/src/shared/scripts/skf-detect-language.py +486 -107
- package/src/shared/scripts/skf-detect-registry.py +887 -0
- package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
- package/src/shared/scripts/skf-detect-tools.py +209 -27
- package/src/shared/scripts/skf-detect-workspaces.py +506 -30
- package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
- package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
- package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
- package/src/shared/scripts/skf-extract-public-api.py +4084 -85
- package/src/shared/scripts/skf-extraction-inventory.py +746 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
- package/src/shared/scripts/skf-fetch-temporal.py +674 -0
- package/src/shared/scripts/skf-find-cycles.py +97 -29
- package/src/shared/scripts/skf-find-test-report.py +476 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +661 -0
- package/src/shared/scripts/skf-hash-content.py +166 -12
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +159 -27
- package/src/shared/scripts/skf-manifest-ops.py +1 -1
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
- package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
- package/src/shared/scripts/skf-names-present.py +221 -0
- package/src/shared/scripts/skf-pair-intersect.py +119 -28
- package/src/shared/scripts/skf-parse-gaps.py +1384 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-preflight.py +161 -27
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
- package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
- package/src/shared/scripts/skf-quick-batch.py +774 -0
- package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
- package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
- package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
- package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
- package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
- package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
- package/src/shared/scripts/skf-resolve-package.py +523 -106
- package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
- package/src/shared/scripts/skf-run-lock.py +577 -0
- package/src/shared/scripts/skf-scan-manifests.py +998 -57
- package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
- package/src/shared/scripts/skf-severity-classify.py +712 -108
- package/src/shared/scripts/skf-shape-detect.py +298 -204
- package/src/shared/scripts/skf-shard-body.py +9 -8
- package/src/shared/scripts/skf-skill-inventory.py +2412 -89
- package/src/shared/scripts/skf-skills-module.py +472 -0
- package/src/shared/scripts/skf-source-tree.py +1796 -0
- package/src/shared/scripts/skf-structural-diff.py +670 -119
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +5 -5
- package/src/shared/scripts/skf-update-run-state.py +624 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
- package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
- package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
- package/src/shared/scripts/skf-validate-output.py +712 -64
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +116 -10
- package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
- package/src/shared/scripts/skf-write-skill-brief.py +367 -19
- package/src/shared/tool-requirements.yaml +201 -0
- package/src/skf-analyze-source/SKILL.md +41 -36
- package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
- package/src/skf-analyze-source/customize.toml +36 -24
- package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
- package/src/skf-analyze-source/references/continue.md +2 -13
- package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
- package/src/skf-analyze-source/references/generate-briefs.md +121 -55
- package/src/skf-analyze-source/references/headless-contract.md +42 -15
- package/src/skf-analyze-source/references/identify-units.md +96 -110
- package/src/skf-analyze-source/references/init.md +73 -71
- package/src/skf-analyze-source/references/map-and-detect.md +123 -105
- package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
- package/src/skf-analyze-source/references/recommend.md +51 -70
- package/src/skf-analyze-source/references/scan-project.md +60 -84
- package/src/skf-analyze-source/references/scan-root.md +39 -0
- package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
- package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
- package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
- package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
- package/src/skf-audit-skill/SKILL.md +43 -51
- package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
- package/src/skf-audit-skill/customize.toml +41 -20
- package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
- package/src/skf-audit-skill/references/doc-drift.md +141 -0
- package/src/skf-audit-skill/references/headless-contract.md +29 -0
- package/src/skf-audit-skill/references/init.md +148 -210
- package/src/skf-audit-skill/references/re-index.md +96 -108
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +27 -18
- package/src/skf-audit-skill/references/severity-classify.md +79 -65
- package/src/skf-audit-skill/references/severity-rules.md +15 -6
- package/src/skf-audit-skill/references/structural-diff.md +75 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
- package/src/skf-brief-skill/SKILL.md +36 -25
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +17 -24
- package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +142 -125
- package/src/skf-brief-skill/references/confirm-brief.md +10 -8
- package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
- package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
- package/src/skf-brief-skill/references/gather-intent.md +87 -182
- package/src/skf-brief-skill/references/headless-args.md +84 -16
- package/src/skf-brief-skill/references/health-check.md +1 -1
- package/src/skf-brief-skill/references/invocation-contract.md +18 -13
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
- package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
- package/src/skf-brief-skill/references/scope-definition.md +123 -47
- package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +3 -2
- package/src/skf-brief-skill/references/write-brief.md +66 -57
- package/src/skf-campaign/SKILL.md +31 -34
- package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
- package/src/skf-campaign/customize.toml +47 -16
- package/src/skf-campaign/references/campaign-contracts.md +39 -29
- package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
- package/src/skf-campaign/references/health-check.md +7 -16
- package/src/skf-campaign/references/step-01-setup.md +46 -84
- package/src/skf-campaign/references/step-02-strategy.md +31 -30
- package/src/skf-campaign/references/step-03-pins.md +26 -18
- package/src/skf-campaign/references/step-04-provenance.md +24 -23
- package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
- package/src/skf-campaign/references/step-06-batch.md +41 -34
- package/src/skf-campaign/references/step-07-capstone.md +40 -25
- package/src/skf-campaign/references/step-08-verify.md +28 -29
- package/src/skf-campaign/references/step-09-refine.md +29 -30
- package/src/skf-campaign/references/step-10-export.md +48 -36
- package/src/skf-campaign/references/step-11-maintenance.md +31 -34
- package/src/skf-campaign/references/step-resume.md +37 -68
- package/src/skf-campaign/scripts/campaign-deps.py +57 -18
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
- package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
- package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
- package/src/skf-campaign/scripts/campaign-report.py +204 -37
- package/src/skf-campaign/scripts/campaign-state.py +1128 -0
- package/src/skf-campaign/scripts/campaign-status.py +10 -74
- package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
- package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
- package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
- package/src/skf-campaign/templates/campaign-report-template.md +5 -1
- package/src/skf-campaign/templates/kickoff-template.md +0 -14
- package/src/skf-create-skill/SKILL.md +27 -20
- package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
- package/src/skf-create-skill/assets/skill-sections.md +15 -5
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
- package/src/skf-create-skill/references/batch-mode.md +81 -0
- package/src/skf-create-skill/references/ccc-index-check.md +27 -0
- package/src/skf-create-skill/references/compile.md +107 -29
- package/src/skf-create-skill/references/component-extraction.md +113 -91
- package/src/skf-create-skill/references/enrich.md +41 -23
- package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
- package/src/skf-create-skill/references/extract.md +200 -161
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
- package/src/skf-create-skill/references/extraction-patterns.md +584 -196
- package/src/skf-create-skill/references/generate-artifacts.md +145 -93
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +53 -36
- package/src/skf-create-skill/references/relabel-rule.md +12 -0
- package/src/skf-create-skill/references/report.md +28 -59
- package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
- package/src/skf-create-skill/references/step-auto-shard.md +20 -93
- package/src/skf-create-skill/references/step-doc-rot.md +44 -60
- package/src/skf-create-skill/references/step-doc-sources.md +28 -19
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
- package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
- package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
- package/src/skf-create-skill/references/validate.md +173 -99
- package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
- package/src/skf-create-stack-skill/SKILL.md +29 -56
- package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
- package/src/skf-create-stack-skill/customize.toml +23 -12
- package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
- package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
- package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
- package/src/skf-create-stack-skill/references/generate-output.md +138 -128
- package/src/skf-create-stack-skill/references/init.md +90 -32
- package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
- package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
- package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
- package/src/skf-create-stack-skill/references/report.md +39 -33
- package/src/skf-create-stack-skill/references/validate.md +20 -39
- package/src/skf-drop-skill/SKILL.md +28 -51
- package/src/skf-drop-skill/customize.toml +44 -30
- package/src/skf-drop-skill/references/execute.md +79 -146
- package/src/skf-drop-skill/references/invocation-contract.md +64 -0
- package/src/skf-drop-skill/references/report.md +46 -30
- package/src/skf-drop-skill/references/select.md +118 -124
- package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
- package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
- package/src/skf-export-skill/SKILL.md +40 -62
- package/src/skf-export-skill/assets/managed-section-format.md +14 -50
- package/src/skf-export-skill/assets/snippet-format.md +3 -1
- package/src/skf-export-skill/customize.toml +42 -13
- package/src/skf-export-skill/references/generate-snippet.md +54 -46
- package/src/skf-export-skill/references/health-check.md +2 -0
- package/src/skf-export-skill/references/invocation-contract.md +15 -0
- package/src/skf-export-skill/references/load-skill.md +88 -62
- package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
- package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
- package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
- package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
- package/src/skf-export-skill/references/package.md +15 -73
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
- package/src/skf-export-skill/references/result-envelope.md +31 -16
- package/src/skf-export-skill/references/summary.md +41 -17
- package/src/skf-export-skill/references/token-report.md +4 -12
- package/src/skf-export-skill/references/update-context.md +118 -237
- package/src/skf-forger/SKILL.md +61 -37
- package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
- package/src/skf-forger/customize.toml +43 -0
- package/src/skf-forger/references/pipeline-mode.md +73 -18
- package/src/skf-forger/scripts/forge-status.py +299 -0
- package/src/skf-forger/scripts/parse-pipeline.py +322 -54
- package/src/skf-forger/scripts/pipeline-gate.py +428 -0
- package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
- package/src/skf-quick-skill/SKILL.md +54 -53
- package/src/skf-quick-skill/assets/skill-template.md +4 -2
- package/src/skf-quick-skill/customize.toml +51 -20
- package/src/skf-quick-skill/references/batch-mode.md +74 -21
- package/src/skf-quick-skill/references/compile.md +30 -31
- package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
- package/src/skf-quick-skill/references/finalize.md +69 -18
- package/src/skf-quick-skill/references/halt-contract.md +41 -29
- package/src/skf-quick-skill/references/health-check.md +5 -3
- package/src/skf-quick-skill/references/quick-extract.md +114 -45
- package/src/skf-quick-skill/references/registry-resolution.md +9 -64
- package/src/skf-quick-skill/references/resolve-target.md +116 -66
- package/src/skf-quick-skill/references/write-and-validate.md +79 -40
- package/src/skf-refine-architecture/SKILL.md +43 -53
- package/src/skf-refine-architecture/customize.toml +49 -20
- package/src/skf-refine-architecture/references/compile.md +97 -54
- package/src/skf-refine-architecture/references/exit-codes.md +30 -0
- package/src/skf-refine-architecture/references/finding-storage.md +21 -0
- package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
- package/src/skf-refine-architecture/references/improvements.md +14 -20
- package/src/skf-refine-architecture/references/init.md +98 -57
- package/src/skf-refine-architecture/references/issue-detection.md +32 -39
- package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
- package/src/skf-refine-architecture/references/report.md +65 -54
- package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
- package/src/skf-rename-skill/SKILL.md +19 -54
- package/src/skf-rename-skill/customize.toml +32 -26
- package/src/skf-rename-skill/references/execute.md +230 -184
- package/src/skf-rename-skill/references/exit-codes.md +7 -7
- package/src/skf-rename-skill/references/health-check.md +1 -7
- package/src/skf-rename-skill/references/invocation-contract.md +25 -0
- package/src/skf-rename-skill/references/report.md +63 -52
- package/src/skf-rename-skill/references/select.md +197 -115
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
- package/src/skf-setup/SKILL.md +26 -26
- package/src/skf-setup/customize.toml +14 -10
- package/src/skf-setup/references/auto-index.md +50 -63
- package/src/skf-setup/references/ccc-index.md +29 -90
- package/src/skf-setup/references/detect-and-tier.md +58 -67
- package/src/skf-setup/references/health-check.md +2 -0
- package/src/skf-setup/references/invocation-contract.md +14 -0
- package/src/skf-setup/references/report.md +43 -166
- package/src/skf-setup/references/tier-rules.md +5 -5
- package/src/skf-setup/references/write-config.md +34 -57
- package/src/skf-test-skill/SKILL.md +17 -57
- package/src/skf-test-skill/assets/output-section-formats.md +33 -34
- package/src/skf-test-skill/customize.toml +27 -13
- package/src/skf-test-skill/references/coherence-check.md +134 -62
- package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
- package/src/skf-test-skill/references/coverage-check.md +217 -254
- package/src/skf-test-skill/references/detect-mode.md +5 -5
- package/src/skf-test-skill/references/external-validators.md +94 -82
- package/src/skf-test-skill/references/health-check.md +6 -7
- package/src/skf-test-skill/references/init.md +163 -88
- package/src/skf-test-skill/references/invocation-contract.md +66 -0
- package/src/skf-test-skill/references/migration-section-rules.md +5 -2
- package/src/skf-test-skill/references/report.md +162 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +41 -155
- package/src/skf-test-skill/references/source-access-protocol.md +19 -92
- package/src/skf-test-skill/references/step-hard-gate.md +51 -33
- package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
- package/src/skf-test-skill/scripts/build-result-context.py +287 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
- package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
- package/src/skf-test-skill/scripts/compute-score.py +223 -45
- package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
- package/src/skf-test-skill/scripts/score-signatures.py +459 -0
- package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
- package/src/skf-test-skill/templates/test-report-template.md +21 -15
- package/src/skf-update-skill/SKILL.md +38 -25
- package/src/skf-update-skill/customize.toml +27 -12
- package/src/skf-update-skill/references/detect-changes.md +233 -222
- package/src/skf-update-skill/references/gap-driven.md +336 -0
- package/src/skf-update-skill/references/health-check.md +31 -5
- package/src/skf-update-skill/references/init.md +250 -84
- package/src/skf-update-skill/references/invocation-contract.md +12 -0
- package/src/skf-update-skill/references/manual-section-rules.md +6 -23
- package/src/skf-update-skill/references/merge.md +180 -47
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +100 -35
- package/src/skf-update-skill/references/write.md +331 -149
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
- package/src/skf-verify-stack/SKILL.md +23 -42
- package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
- package/src/skf-verify-stack/customize.toml +55 -22
- package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
- package/src/skf-verify-stack/references/coverage.md +67 -64
- package/src/skf-verify-stack/references/exit-codes.md +21 -8
- package/src/skf-verify-stack/references/init.md +107 -62
- package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
- package/src/skf-verify-stack/references/integrations.md +106 -65
- package/src/skf-verify-stack/references/report.md +59 -42
- package/src/skf-verify-stack/references/requirements.md +32 -9
- package/src/skf-verify-stack/references/synthesize.md +53 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
- package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
- package/tools/cli/commands/install.js +11 -4
- package/tools/cli/commands/status.js +15 -3
- package/tools/cli/commands/update.js +11 -4
- package/tools/cli/lib/tool-check.js +320 -0
- package/tools/cli/lib/version-check.js +22 -9
- package/tools/cli/skf-cli.js +4 -1
- package/.gitattributes +0 -16
- package/.nvmrc +0 -1
- package/docs/_internal/RELEASING.md +0 -679
- package/release-audits/v1.0.0-launch-audit.md +0 -728
- package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
- package/src/skf-campaign/manifest.yaml +0 -15
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
- package/src/skf-create-skill/references/ecosystem-check.md +0 -74
- package/src/skf-drop-skill/references/headless-contract.md +0 -18
- package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
- package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
- package/src/skf-update-skill/references/validate.md +0 -124
- package/tools/validate-docs-drift.js +0 -233
- package/tools/validate-docs-links.js +0 -665
|
@@ -5,9 +5,6 @@ nextStepFile: 'health-check.md'
|
|
|
5
5
|
writeSkillBriefProbeOrder:
|
|
6
6
|
- '{project-root}/_bmad/skf/shared/scripts/skf-write-skill-brief.py'
|
|
7
7
|
- '{project-root}/src/shared/scripts/skf-write-skill-brief.py'
|
|
8
|
-
emitBriefEnvelopeProbeOrder:
|
|
9
|
-
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
10
|
-
- '{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
11
8
|
forgeTierRwProbeOrder:
|
|
12
9
|
- '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
|
|
13
10
|
- '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
|
|
@@ -32,7 +29,7 @@ forgeTierFile: '{sidecar_path}/forge-tier.yaml'
|
|
|
32
29
|
|
|
33
30
|
**Resolve `{writeSkillBriefHelper}`** from `{writeSkillBriefProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
34
31
|
|
|
35
|
-
`
|
|
32
|
+
`assets/skill-brief-schema.md` and `{versionResolutionFile}` document the brief contract for human readers. The deterministic enforcement of that contract lives in `{writeSkillBriefHelper}` and its JSON Schema artifact at `src/shared/scripts/schemas/skill-brief.v1.json`. Load `assets/skill-brief-schema.md` only if you need to explain a specific field to the user during inline adjustments; otherwise skip the read: the script is the source of truth.
|
|
36
33
|
|
|
37
34
|
### 2. Resolve Output Path
|
|
38
35
|
|
|
@@ -46,11 +43,19 @@ The script's atomic-write helper creates parent directories as needed (`mkdir -p
|
|
|
46
43
|
|
|
47
44
|
Before writing, check whether the resolved target path already exists.
|
|
48
45
|
|
|
49
|
-
**Ratify path (`ratify_mode: true` in workflow context):**
|
|
46
|
+
**Ratify path (`ratify_mode: true` in workflow context):** step 1 (`references/gather-intent-ratify.md`) authorized overwriting only the brief it read, `ratify_source_path`: interactively by `[R] Ratify`, then reviewed and approved at step 4, or headlessly by a `from_brief` argument. Check whether the target is that file (the same file through any path or link), each path written as it is on its line between the markers:
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
```bash
|
|
49
|
+
uv run python -c 'import os, sys; a, b = sys.stdin.read().splitlines()[:2]; print("same" if os.path.exists(a) and os.path.exists(b) and os.path.samefile(a, b) else "different")' <<'SKF_PATHS'
|
|
50
|
+
{resolved-target-path}
|
|
51
|
+
{ratify_source_path}
|
|
52
|
+
SKF_PATHS
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
- **`same`:** skip both gates below, with no `force` needed: log a single-line `brief-skill: ratify-mode auto-overwriting existing brief at {path}` and proceed to §3.
|
|
56
|
+
- **`different`** (the brief lives outside `{forge_data_folder}/<name>/`, or step 4 renamed it): an existing file at the target is another brief, so the gates below apply as on the derive route.
|
|
52
57
|
|
|
53
|
-
**Interactive (`{headless_mode}` is false,
|
|
58
|
+
**Interactive (`{headless_mode}` is false), unless the ratify check printed `same`:**
|
|
54
59
|
|
|
55
60
|
If the file exists, present:
|
|
56
61
|
|
|
@@ -60,18 +65,18 @@ Overwrite it with the brief you just approved? [Y/N]"
|
|
|
60
65
|
- **[Y]** Overwrite — proceed to §3.
|
|
61
66
|
- **[N]** Cancel — emit a single-line stderr log `brief-skill: overwrite-cancelled at {path}` and HALT with exit code 5 (do not chain to step 6; the run produced no new artifact).
|
|
62
67
|
|
|
63
|
-
**
|
|
68
|
+
**GATE [default: HALT unless `force` was supplied]**: headless (`{headless_mode}` is true), unless the ratify check printed `same`:
|
|
64
69
|
|
|
65
70
|
If the file exists:
|
|
66
71
|
|
|
67
72
|
- If `force` was supplied as a headless argument: log `"headless: force-overwriting existing brief at {path}"` and proceed to §3.
|
|
68
|
-
- Otherwise: emit the
|
|
73
|
+
- Otherwise: emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "overwrite-cancelled"` (SKILL.md Halt Contract), then HALT with exit code 5.
|
|
69
74
|
|
|
70
75
|
If the file does not exist, proceed normally.
|
|
71
76
|
|
|
72
77
|
### 3. Write the Brief
|
|
73
78
|
|
|
74
|
-
|
|
79
|
+
**Derive run** (any run but a ratify run): assemble the brief context as a **flat** JSON object: every approved value is a top-level key, scope is split across the `scope_*` keys instead of nested, and every optional field is passed as `null` when not set rather than conditionally omitted:
|
|
75
80
|
|
|
76
81
|
```json
|
|
77
82
|
{
|
|
@@ -90,28 +95,41 @@ Assemble the brief context as a **flat** JSON object — every approved value is
|
|
|
90
95
|
"scope_exclude": ["{approved exclude patterns}"],
|
|
91
96
|
"scope_notes": "{approved scope notes or empty string}",
|
|
92
97
|
"scope_rationale": null | {"recommended":"...","chosen":"...","accepted_recommendation":true|false,"heuristic":"...","reason":"...","recorded":"YYYY-MM-DD"},
|
|
93
|
-
"scope_tier_a_include": null | ["{tier-A authoring-surface patterns
|
|
94
|
-
"
|
|
98
|
+
"scope_tier_a_include": null | ["{tier-A authoring-surface patterns, from step 3 §3c}"],
|
|
99
|
+
"scope_registry_path": null | "{a component library's registry file; this key and the next two from step 3's component-library flow or its headless default}",
|
|
100
|
+
"scope_ui_variants": null | [{"name": "...", "package": "..."}],
|
|
101
|
+
"scope_demo_patterns": null | ["{demo globs}"],
|
|
95
102
|
"doc_urls": null | [{"url": "...", "label": "...", "source": "{optional: language-registry|readme-detection|homepage|pages-api|docs-folder}"}],
|
|
96
103
|
"scripts_intent": null | "{detect|none|free-text}",
|
|
97
104
|
"assets_intent": null | "{detect|none|free-text}",
|
|
98
105
|
"source_authority": null | "{official|community|internal}",
|
|
99
|
-
"target_ref": null | "{explicit git ref
|
|
100
|
-
"source_ref": null | "{resolved git ref — ratify only}"
|
|
106
|
+
"target_ref": null | "{the explicit git ref of step 1's /tree/<ref>/ URL}"
|
|
101
107
|
}
|
|
102
108
|
```
|
|
103
109
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
Pipe it into the writer script with the `--from-flat` flag:
|
|
110
|
+
Stage it in the run folder, then run the writer on the file with the `--from-flat` flag:
|
|
107
111
|
|
|
108
112
|
```bash
|
|
109
|
-
|
|
113
|
+
cat > "{run_dir}/brief-context.json" <<'SKF_JSON'
|
|
114
|
+
<the brief context above, as one JSON object>
|
|
115
|
+
SKF_JSON
|
|
116
|
+
uv run {writeSkillBriefHelper} write --target {resolved-target-path} --from-flat < "{run_dir}/brief-context.json"
|
|
110
117
|
```
|
|
111
118
|
|
|
112
119
|
The script translates flat → nested internally, drops the null optional fields, and runs the same schema validation and atomic write as before — pass every key always, the writer decides what reaches the YAML.
|
|
113
120
|
|
|
114
|
-
The
|
|
121
|
+
**Ratify run (`ratify_mode: true`):** write from the brief step 1 ratified, `{ratify_source_path}`, so nothing it holds is retyped. The writer keeps every field of that brief that it renders and the patch below does not name, such as its version, which step 2 never re-derives on a ratify run (an [R] pass analyzes the brief's ref but keeps the hydrated version), its git refs and its `scope.amendments` log. The patch holds the fields step 4 or a step 3 `[R]` pass can change: write each `<field>` as its current value in JSON, `null` when it is unset, which removes the key (an `[R]` pass that moved `scope.type` off `component-library` unsets the three component-library fields). Add any other field the user changed at step 4 under its brief key; a changed `version` sets `target_version` too when the brief holds one, because the writer keeps the two equal:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
cat > "{run_dir}/ratify-patch.json" <<'SKF_JSON'
|
|
125
|
+
{"name": <name>, "description": <description>, "language": <language>,
|
|
126
|
+
"scope": {"type": <scope.type>, "include": <scope.include>, "exclude": <scope.exclude>, "notes": <scope.notes>, "rationale": <scope.rationale>, "tier_a_include": <scope.tier_a_include>, "registry_path": <scope.registry_path>, "ui_variants": <scope.ui_variants>, "demo_patterns": <scope.demo_patterns>},
|
|
127
|
+
"scripts_intent": <scripts_intent>, "assets_intent": <assets_intent>, "doc_urls": <doc_urls>}
|
|
128
|
+
SKF_JSON
|
|
129
|
+
uv run {writeSkillBriefHelper} write --target {resolved-target-path} --base-brief "{ratify_source_path}" --patch-file "{run_dir}/ratify-patch.json"
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
Either way, the script:
|
|
115
133
|
- Validates the context against `src/shared/scripts/schemas/skill-brief.v1.json`
|
|
116
134
|
- Applies the version-precedence rule from `{versionResolutionFile}`
|
|
117
135
|
- Enforces the `target_version == version` invariant (refuses to write a brief that violates it)
|
|
@@ -122,55 +140,41 @@ The script:
|
|
|
122
140
|
**On script failure (non-zero exit):**
|
|
123
141
|
- Exit 1 (validation/invariant): The error JSON on stderr names the offending field. This indicates a context-assembly bug, not a user error — surface the message to the user, log it, then HALT.
|
|
124
142
|
- Interactive: **HALT** — display the error JSON's `message` field.
|
|
125
|
-
- Headless: emit the
|
|
126
|
-
- Exit 2 (I/O failure): The atomic write failed (target unwritable, disk full, etc.).
|
|
143
|
+
- Headless: emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "input-invalid"` (SKILL.md Halt Contract), then HALT (exit code 2).
|
|
144
|
+
- Exit 2 (I/O failure): The atomic write failed (target unwritable, disk full, etc.). On a ratify run it can also mean the brief at `{ratify_source_path}` could not be read: show the error JSON's `message` field.
|
|
127
145
|
- Interactive: **HALT** — "**Error:** Failed to write skill-brief.yaml. Check that the directory is writable and try again."
|
|
128
|
-
- Headless: emit the
|
|
129
|
-
|
|
130
|
-
**On success:** capture `brief_path` and `version` from the response envelope — both are needed for §4b and §6.
|
|
146
|
+
- Headless: emit the halt envelope first, `uv run {emitBriefEnvelopeHelper} emit --target stderr` with `halt_reason: "write-failed"` (SKILL.md Halt Contract), then HALT (exit code 4).
|
|
131
147
|
|
|
132
|
-
**
|
|
148
|
+
**On success:** capture `brief_path` and `version` from the response envelope (§4b, §6 and §6b need them), and add each entry of its `warnings[]` to `workflow_warnings[]`.
|
|
133
149
|
|
|
134
|
-
|
|
150
|
+
**Draft cleanup.** After a successful write, remove `{forge_data_folder}/{skill-name}/.brief-draft.json` if it exists (`rm -f`, silent on absent). The draft was the checkpoint step 1 §8 and step 3 §5c wrote for the in-flight workflow window; once the brief is written it is no longer meaningful. In headless mode this rm is a no-op (drafts are only written interactively).
|
|
135
151
|
|
|
136
|
-
|
|
152
|
+
### 3b. QMD Collection Registration (Deep Tier Only)
|
|
137
153
|
|
|
138
|
-
|
|
154
|
+
**IF forge tier is Deep AND QMD tool is available:** resolve `{forgeTierRwHelper}` from `{forgeTierRwProbeOrder}` (first existing path wins), then load `{qmdRegistrationFile}` and follow the procedure there to index the brief into a QMD collection and update the forge-tier registry. If neither path exists, do not HALT: the brief is already written, and a QMD problem never fails the run. Index the brief all the same, skip the procedure's registry update, and add `QMD registry not updated: skf-forge-tier-rw.py not found` to `workflow_warnings[]`. A warning the procedure logs goes on `workflow_warnings[]` too, which is why this runs before §4b builds the envelope.
|
|
139
155
|
|
|
140
|
-
**
|
|
156
|
+
**IF forge tier is NOT Deep OR QMD is not available:** skip this section silently: do not load `{qmdRegistrationFile}`. No messaging.
|
|
141
157
|
|
|
142
|
-
|
|
143
|
-
echo '{"status":"success","brief_path":"<from §3 response>","skill_name":"<name>","version":"<from §3 response>","language":"<language>","scope_type":"<scope.type>","halt_reason":null}' | \
|
|
144
|
-
uv run {emitBriefEnvelopeHelper} emit
|
|
145
|
-
```
|
|
158
|
+
### 4b. Result Envelope (Headless)
|
|
146
159
|
|
|
147
|
-
|
|
160
|
+
When `{headless_mode}` is true, build the run's `SKF_BRIEF_RESULT_JSON` line now, after the write (§3) and the QMD registration (§3b), so `workflow_warnings[]` holds every warning the run raised. `{emitBriefEnvelopeHelper}` was resolved at SKILL.md On Activation step 4, and `references/invocation-contract.md` defines each field. Bind `{result_envelope_line}` to the line it prints, and do not display it here: the shared health check displays it verbatim as the run's last line, the final message a `claude -p` caller reads:
|
|
148
161
|
|
|
149
162
|
```bash
|
|
150
|
-
|
|
151
|
-
|
|
163
|
+
uv run {emitBriefEnvelopeHelper} emit <<'SKF_BRIEF_RESULT'
|
|
164
|
+
{"status":"success","brief_path":"<brief_path from §3>","skill_name":"<name>","version":"<version from §3>","language":"<language>","scope_type":"<scope.type>","halt_reason":null,"mode":null,"warnings":[<workflow_warnings[] as JSON strings>]}
|
|
165
|
+
SKF_BRIEF_RESULT
|
|
152
166
|
```
|
|
153
167
|
|
|
154
|
-
|
|
168
|
+
The helper derives `exit_code`, checks the line against the envelope schema and prints it on stdout. If `{emitBriefEnvelopeHelper}` has no path, or the helper exits non-zero or prints no line, leave `{result_envelope_line}` empty and display its error: the brief is already written, so the run goes on.
|
|
155
169
|
|
|
156
|
-
|
|
170
|
+
A HALT in this step, or in steps 1 and 2, does not use this section: it emits the error envelope through the SKILL.md Halt Contract, which also gives the `unknown` placeholder for a halt before the skill name is resolved.
|
|
157
171
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
Invocation sites (each pointed at this block, not duplicated): step 1 §1 (write-failed pre-resolution; forge-tier-missing), step 1 §8 (input-missing/input-invalid GATE), step 2 §1 (target-inaccessible/gh-auth-failed), step 5 §2b (overwrite-cancelled), step 5 §3 (input-invalid/write-failed from script). The step 1 §1 forge-tier-missing and step 2 §1 target-inaccessible/gh-auth-failed sites emit through this block too, so every headless HALT class surfaces a `SKF_BRIEF_RESULT_JSON` envelope — there are no envelope-silent failure classes.
|
|
161
|
-
|
|
162
|
-
When `{headless_mode}` is false, skip this section silently — no envelope is emitted.
|
|
163
|
-
|
|
164
|
-
### 5. QMD Collection Registration (Deep Tier Only)
|
|
165
|
-
|
|
166
|
-
**Resolve `{forgeTierRwHelper}`** from `{forgeTierRwProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
167
|
-
|
|
168
|
-
**IF forge tier is Deep AND QMD tool is available:** load `{qmdRegistrationFile}` and follow the procedure there to index the brief into a QMD collection and update the forge-tier registry.
|
|
169
|
-
|
|
170
|
-
**IF forge tier is NOT Deep OR QMD is not available:** skip this section silently — do not load `{qmdRegistrationFile}`. No messaging.
|
|
172
|
+
When `{headless_mode}` is false, skip this section silently: no envelope is emitted.
|
|
171
173
|
|
|
172
174
|
### 6. Display Success Summary
|
|
173
175
|
|
|
176
|
+
When `{headless_mode}` is true, skip this section: the envelope §4b bound is the run's result.
|
|
177
|
+
|
|
174
178
|
"**Skill brief written successfully.**
|
|
175
179
|
|
|
176
180
|
---
|
|
@@ -199,7 +203,7 @@ After compilation, you can:
|
|
|
199
203
|
|
|
200
204
|
### 6b. On-Complete Hook (pipeline integration)
|
|
201
205
|
|
|
202
|
-
If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it now
|
|
206
|
+
If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it now, after the brief has been written (§3) and, in a headless run, the result envelope built and bound to `{result_envelope_line}` (§4b):
|
|
203
207
|
|
|
204
208
|
```bash
|
|
205
209
|
{onCompleteCommand} --result-path={brief_path}
|
|
@@ -207,12 +211,17 @@ If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 fr
|
|
|
207
211
|
|
|
208
212
|
where `{brief_path}` is the absolute path captured from the §3 response envelope (the freshly written `skill-brief.yaml`, the stable artifact a downstream consumer chains from).
|
|
209
213
|
|
|
210
|
-
-
|
|
211
|
-
- On
|
|
212
|
-
- **Never fail the workflow on hook errors** — the hook is for pipeline integration (chaining into create-skill, Slack, dashboards, CI), not for gating brief production.
|
|
214
|
+
- **Never fail the workflow on hook errors:** the hook is for pipeline integration (chaining into create-skill, Slack, dashboards, CI), not for gating brief production. On a non-zero exit or a process error, display one line, `on_complete hook failed (exit {code}): {first line of its stderr}`, and continue. A headless run bound its envelope at §4b, so the envelope does not carry this line.
|
|
215
|
+
- On success, add nothing: the hook's own output is its report.
|
|
213
216
|
|
|
214
|
-
When `{onCompleteCommand}` is empty (bundled default), skip this section entirely
|
|
217
|
+
When `{onCompleteCommand}` is empty (bundled default), skip this section entirely: no hook is invoked. An `[auto]` run runs only §3b of this file: step-auto-validate.md §3 runs the same hook right after its envelope.
|
|
215
218
|
|
|
216
219
|
### 7. Chain to Health Check
|
|
217
220
|
|
|
218
|
-
Once the brief file has been written and the success summary displayed,
|
|
221
|
+
Once the brief file has been written (and, outside headless mode, the success summary displayed), remove the run folder step 1 §1 created, with what the run staged in it (the guard keeps the command to that folder):
|
|
222
|
+
|
|
223
|
+
```bash
|
|
224
|
+
case "{run_dir}" in "{project-root}/_bmad-output/.skf-run/skf-brief-skill-"*) rm -rf "{run_dir}" ;; esac
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step: do not stop here even though the summary reads as final.
|
|
@@ -7,7 +7,7 @@ description: Campaign orchestration — multi-library skill production with depe
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
Orchestrates the production of 15+ skills across multiple sessions by driving them through the full SKF pipeline (brief, generate, compile, test, export) in dependency order.
|
|
10
|
+
Orchestrates the production of 15+ skills across multiple sessions by driving them through the full SKF pipeline (brief, generate, compile, test, export) in dependency order. File-based state (`_campaign-state.yaml`) survives context death, enabling resume from any point.
|
|
11
11
|
|
|
12
12
|
## Conventions
|
|
13
13
|
|
|
@@ -16,41 +16,40 @@ Orchestrates the production of 15+ skills across multiple sessions by driving th
|
|
|
16
16
|
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives).
|
|
17
17
|
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
18
18
|
- `{skill-name}` resolves to the skill directory's basename.
|
|
19
|
+
- **Module-level path exception:** bare paths beginning with `knowledge/` or `shared/` resolve from the SKF module root (`{project-root}/_bmad/skf/` installed, `src/` in dev), not the skill root; e.g. `shared/health-check.md` and the envelope schemas under `shared/scripts/schemas/`.
|
|
20
|
+
- **Sibling skills:** a path that names another SKF skill's folder (`skf-<name>/...`) resolves from the SKF module root, and that skill must be installed with this one.
|
|
19
21
|
|
|
20
22
|
## Role
|
|
21
23
|
|
|
22
|
-
You are a campaign orchestrator operating in Ferris's Management mode. You sequence workflows, track per-skill state, enforce quality gates, and ensure every skill reaches its target tier
|
|
24
|
+
You are a campaign orchestrator operating in Ferris's Management mode. You sequence workflows, track per-skill state, enforce quality gates, and ensure every skill reaches its target tier, while the individual pipeline workflows handle the actual artifact production.
|
|
23
25
|
|
|
24
26
|
## On Activation
|
|
25
27
|
|
|
26
28
|
Run these steps once, in order, before dispatching to Mode Routing.
|
|
27
29
|
|
|
28
|
-
1. **Load config.** Read `{project-root}/_bmad/skf/config.yaml` and `{sidecar_path}/preferences.yaml` in one batched message (independent files). From config resolve `project_name`, `user_name`, `communication_language`, `document_output_language`, `skills_output_folder`, `forge_data_folder`, `sidecar_path`.
|
|
30
|
+
1. **Load config.** Read `{project-root}/_bmad/skf/config.yaml` and `{sidecar_path}/preferences.yaml` in one batched message (independent files). From config resolve `project_name`, `user_name`, `communication_language`, `document_output_language`, `skills_output_folder`, `forge_data_folder`, `sidecar_path`. If the config file is missing, fall back to `forge_data_folder = forge-data`.
|
|
29
31
|
|
|
30
|
-
2. **Resolve `{headless_mode}
|
|
32
|
+
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in `{sidecar_path}/preferences.yaml`. Default: false.
|
|
31
33
|
|
|
32
34
|
3. **Resolve workflow customization.** Run:
|
|
33
35
|
|
|
34
36
|
```bash
|
|
35
|
-
|
|
37
|
+
uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow
|
|
36
38
|
```
|
|
37
39
|
|
|
38
|
-
|
|
40
|
+
It merges the bundled `{skill-root}/customize.toml` with `{project-root}/_bmad/custom/skf-campaign.toml` (team overrides, committed) and `.user.toml` (personal overrides, gitignored). When it exits non-zero, prints no JSON or is missing, print one line, `[activation/warn] customization_resolver_unavailable: <reason>` (`<reason>`: its first stderr line, `not found` when the script is missing, `no JSON` when it printed none). If the resolver cannot run, read `{skill-root}/customize.toml` alone and use its bundled defaults: the `{project-root}/_bmad/custom/` overrides do not apply to this run. In that case, unless the invocation is `campaign status` (which writes nothing), log `customization_resolver_unavailable: <reason>` as an `event` in the decision log once `{campaignWorkspacePath}` is bound below (`references/campaign-contracts.md`, Decision Log).
|
|
39
41
|
|
|
40
|
-
|
|
41
|
-
- `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
|
|
42
|
-
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
43
|
-
|
|
44
|
-
If it fails or is missing, fall back to `{skill-root}/customize.toml` directly. Resolve each scalar now (so step files never repeat the conditional) and stash as workflow-context variables:
|
|
42
|
+
Resolve each scalar now (so step files never repeat the conditional) and stash as workflow-context variables:
|
|
45
43
|
|
|
46
44
|
- `{campaignWorkspacePath}` ← `workflow.campaign_workspace_path` if non-empty, else `{forge_data_folder}/_campaign`
|
|
47
|
-
- `{qualityGateHard}` / `{qualityGateSoftTarget}` / `{qualityGateSoftFallback}` ← the `quality_gate_*` scalars (defaults `zero-critical-high` / `90` / `80`)
|
|
45
|
+
- `{qualityGateHard}` / `{qualityGateSoftTarget}` / `{qualityGateSoftFallback}` ← the `quality_gate_*` scalars (defaults `zero-critical-high` / `90` / `80`): the base gate, which step-01 §2 and `scripts/campaign-quality-gate.py` adjust with the brief and the directive
|
|
48
46
|
- `{reportTemplatePath}` ← `workflow.report_template_path` if non-empty, else `templates/campaign-report-template.md`
|
|
49
47
|
- `{kickoffTemplatePath}` ← `workflow.kickoff_template_path` if non-empty, else `templates/kickoff-template.md`
|
|
50
48
|
- `{briefTemplatePath}` ← `workflow.brief_template_path` if non-empty, else `templates/campaign-brief-template.yaml`
|
|
51
49
|
- `{onComplete}` ← `workflow.on_complete` (empty = no-op)
|
|
50
|
+
- `{emitEnvelopeHelper}` ← `{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py`, else `{project-root}/src/shared/scripts/skf-emit-result-envelope.py` (the first that exists)
|
|
52
51
|
|
|
53
|
-
Load `workflow.persistent_facts` (literal sentences and `file:` references, globs expanded) and keep them in mind for the whole campaign
|
|
52
|
+
Load `workflow.persistent_facts` (literal sentences and `file:` references, globs expanded: the bundled default loads every `project-context.md` under `{project-root}`; an entry prefixed `!` drops each earlier entry it names and loads nothing itself, so an override's `"!file:{project-root}/**/project-context.md"` turns that default off) and keep them in mind for the whole campaign: they are injected into every per-skill kickoff, whose loader drops a `!` entry the same way. Run any `activation_steps_prepend` now, right after the resolve: the config and preferences of steps 1 and 2 are already loaded, so a prepend step can read them but cannot run before them. `activation_steps_append` runs at step 5, once the CLI overrides are parsed.
|
|
54
53
|
|
|
55
54
|
4. **Parse CLI overrides** into the workflow context:
|
|
56
55
|
|
|
@@ -61,36 +60,34 @@ Run these steps once, in order, before dispatching to Mode Routing.
|
|
|
61
60
|
| `--manifest <file>` | Seed step-01 targets from a plain-text `name,repo_url,tier,pin` manifest. Implies `--headless`. |
|
|
62
61
|
| `--from <skill>` | Resume override — see Mode Routing. |
|
|
63
62
|
|
|
64
|
-
If `--brief` or `--manifest` is set, force `{headless_mode} = true` (log "headless: coerced by --brief/--manifest" if it was false).
|
|
65
|
-
|
|
66
|
-
**`--manifest` format:** one `name,repo_url,tier,pin` target per line (empty `pin` = latest); a trailing `;dep1,dep2` segment sets `depends_on`; blank and `#` lines are skipped. A malformed line HALTs step-01 with the offending line numbers — never a partial target set.
|
|
63
|
+
If `--brief` or `--manifest` is set, force `{headless_mode} = true` (log "headless: coerced by --brief/--manifest" if it was false). This is deliberate: a seeded run is an unattended run (CI), so it takes the default at every gate. To review the plan and the export, give the same file at the Setup question instead, which stays interactive. step-01 §1 documents the manifest format and validates every target.
|
|
67
64
|
|
|
68
|
-
5. **
|
|
65
|
+
5. Run any `activation_steps_append`, then **dispatch** per Mode Routing below.
|
|
69
66
|
|
|
70
67
|
## Workflow Rules
|
|
71
68
|
|
|
72
69
|
These rules apply to every step in this workflow:
|
|
73
70
|
|
|
74
|
-
- State-first
|
|
75
|
-
-
|
|
76
|
-
- Validate `_campaign-state.yaml` on every load by running `uv run scripts/campaign-validate-state.py --state-file {stateFile}` and HALT (exit code 3, `invalid-state`) on non-zero
|
|
77
|
-
- Zero memory dependency
|
|
78
|
-
-
|
|
79
|
-
-
|
|
80
|
-
- **Universal cancel affordance
|
|
71
|
+
- State-first: write state to disk before chaining to the next step or workflow
|
|
72
|
+
- Every state write goes through `scripts/campaign-state.py` (State Contract in `references/campaign-contracts.md`); never edit the state or its `.bak` by hand
|
|
73
|
+
- Validate `_campaign-state.yaml` on every load by running `uv run scripts/campaign-validate-state.py --state-file {stateFile}` and HALT (exit code 3, `invalid-state`) on non-zero; never hand-validate the schema
|
|
74
|
+
- Zero memory dependency: campaign state is 100% recoverable from disk; never rely on conversation context for progress tracking
|
|
75
|
+
- A sub-skill's result is what the step that runs it reads (an `SKF_*_RESULT_JSON` envelope or a verdict): a missing, unparseable or error result is a sub-skill failure, and never write partial state from an unparsed envelope
|
|
76
|
+
- Log every operator decision, headless default and event (skip/force, overwrite, export cancel/proceed, `.bak` recovery, user-cancel, a failed skill) as one typed entry in the append-only `{campaignWorkspacePath}/_campaign-decision-log.md` through `campaign-state.py log` (`references/campaign-contracts.md`), so rationale survives compaction and resume
|
|
77
|
+
- **Universal cancel affordance:** at any interactive gate between Setup and the Export gate, `cancel`/`exit`/`:q` triggers a HARD HALT with **exit code 12 (`user-cancelled`)**: log it and leave state intact and resumable. Exception: the Export gate's own `[C]ancel` stays exit code 11 (`export-cancelled`); never also emit 12 there, so an automator's exit-code branch stays deterministic.
|
|
81
78
|
- Always communicate in `{communication_language}`
|
|
82
79
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
83
|
-
- If `{headless_mode}` is true, emit a single-line JSON progress event to **stderr** at each step's entry, exit, and HARD HALT
|
|
80
|
+
- If `{headless_mode}` is true, emit a single-line JSON progress event to **stderr** at each step's entry, exit, and HARD HALT, and at every HARD HALT the error envelope (`references/campaign-contracts.md`: Headless Progress Events, Result Contract on HARD HALT)
|
|
84
81
|
|
|
85
82
|
## Stages
|
|
86
83
|
|
|
87
84
|
| # | Step | File | Auto-proceed |
|
|
88
85
|
|---|------|------|--------------|
|
|
89
86
|
| 0 | Setup | references/step-01-setup.md | Yes |
|
|
90
|
-
| 1 | Strategy | references/step-02-strategy.md |
|
|
87
|
+
| 1 | Strategy | references/step-02-strategy.md | No (plan confirmation; headless takes [P]) |
|
|
91
88
|
| 2 | Pin Validation | references/step-03-pins.md | Yes |
|
|
92
89
|
| 3 | Provenance | references/step-04-provenance.md | Yes |
|
|
93
|
-
| 4 | Skill Loop | references/step-05-skill-loop.md |
|
|
90
|
+
| 4 | Skill Loop | references/step-05-skill-loop.md | Conditional (a blocked dependency) |
|
|
94
91
|
| 5 | Tier B Batch | references/step-06-batch.md | Yes |
|
|
95
92
|
| 6 | Capstone | references/step-07-capstone.md | Yes |
|
|
96
93
|
| 7 | Verification | references/step-08-verify.md | Yes |
|
|
@@ -98,24 +95,24 @@ These rules apply to every step in this workflow:
|
|
|
98
95
|
| 9 | Export | references/step-10-export.md | No (write-gate HALT) |
|
|
99
96
|
| 10 | Maintenance | references/step-11-maintenance.md | Yes |
|
|
100
97
|
|
|
101
|
-
**Stage numbering:**
|
|
98
|
+
**Stage numbering:** `campaign.current_stage` is 0-indexed, so step-`NN` runs stage `NN - 1`; `campaign-state.py resume` maps a resumed campaign to its step file.
|
|
102
99
|
|
|
103
100
|
## Invocation Contract
|
|
104
101
|
|
|
105
102
|
| Aspect | Detail |
|
|
106
103
|
|--------|--------|
|
|
107
104
|
| **Inputs** | `campaign` to start a new campaign; `campaign resume [--from=<skill>]` to resume from last active or specified skill; `campaign status` for a read-only progress summary |
|
|
108
|
-
| **Outputs** | `_campaign-state.yaml` (state), `campaign-brief.yaml` (machine-generated brief), `campaign-report.md` (post-campaign summary), `_campaign-decision-log.md` (append-only rationale), `SKF_CAMPAIGN_RESULT_JSON` (headless envelope)
|
|
105
|
+
| **Outputs** | `_campaign-state.yaml` (state), `campaign-brief.yaml` (machine-generated brief), `campaign-report.md` (post-campaign summary), `_campaign-decision-log.md` (append-only rationale), all under `{campaignWorkspacePath}`; `SKF_CAMPAIGN_RESULT_JSON` (headless envelope) |
|
|
109
106
|
|
|
110
107
|
## Contracts
|
|
111
108
|
|
|
112
|
-
Exit codes, the HARD-HALT error envelope, the
|
|
109
|
+
Exit codes, the HARD-HALT error envelope, the **State Contract** (`scripts/campaign-state.py`), the decision log and per-step progress events live in `references/campaign-contracts.md`: consult it when you HALT, write state, or log. The envelope's one definition is `shared/scripts/schemas/skf-campaign-result-envelope.v1.json`; step-11 emits its success line.
|
|
113
110
|
|
|
114
111
|
## Mode Routing
|
|
115
112
|
|
|
116
113
|
On invocation:
|
|
117
114
|
|
|
118
|
-
1. **`campaign resume [--from=<skill>]
|
|
119
|
-
2. **`campaign`** (new, no existing state)
|
|
120
|
-
3. **`campaign`** (state exists)
|
|
121
|
-
4. **`campaign status`** (read-only)
|
|
115
|
+
1. **`campaign resume [--from=<skill>]`**: load `references/step-resume.md` (validates state, recovers from backup, chains to the stage `campaign-state.py resume` computes). `--from=<skill>` overrides the resume point to the named skill.
|
|
116
|
+
2. **`campaign`** (new, no existing state) to run from stage 0 (Setup).
|
|
117
|
+
3. **`campaign`** (state exists): when `{campaignWorkspacePath}/_campaign-state.yaml` or its `.bak` exists, prompt **resume** (via `references/step-resume.md`) or **overwrite**. On overwrite, first run `uv run scripts/campaign-state.py archive --state-file {campaignWorkspacePath}/_campaign-state.yaml --brief-file {campaignWorkspacePath}/campaign-brief.yaml`, which moves the state, its `.bak` and the brief into a new folder under `{campaignWorkspacePath}/archive/`, and log the `archive_dir` it returns (type `decision`) before chaining to step-01 (its `init` refuses to overwrite a state or backup). A `--brief` that named the workspace's `campaign-brief.yaml` is then read from `archive_dir`. **GATE [default: resume]**: in headless mode, default to **resume** (never silently clobber); archive-and-overwrite only when `--brief`/`--manifest` explicitly seeds a new campaign.
|
|
118
|
+
4. **`campaign status`** (read-only): load `{campaignWorkspacePath}/_campaign-state.yaml`, validate it via `campaign-validate-state.py`, then run `uv run scripts/campaign-status.py --state-file {campaignWorkspacePath}/_campaign-state.yaml` and display its summary (campaign name, current stage, completed-vs-total, per-status counts) followed by the last ~15 lines of `{campaignWorkspacePath}/_campaign-decision-log.md` for the recent decision trail, then stop. No backup, no mutation, no chaining. Exit 0 (or 9 if the state is unrecoverable).
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"properties": {
|
|
9
9
|
"campaign": {
|
|
10
10
|
"type": "object",
|
|
11
|
-
"required": ["name", "started_at", "last_updated", "current_stage", "quality_gate"
|
|
11
|
+
"required": ["name", "started_at", "last_updated", "current_stage", "quality_gate"],
|
|
12
12
|
"additionalProperties": false,
|
|
13
13
|
"properties": {
|
|
14
14
|
"name": {
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
},
|
|
49
49
|
"health_findings_queue": {
|
|
50
50
|
"type": "string",
|
|
51
|
-
"enum": ["local", "improvement"]
|
|
51
|
+
"enum": ["local", "improvement"],
|
|
52
|
+
"description": "Ignored. Setup asked for it before v3.0.0; the end-of-run health check now decides where findings go. Kept optional so state files that hold it still validate."
|
|
52
53
|
},
|
|
53
54
|
"architecture_doc_path": {
|
|
54
55
|
"type": ["string", "null"],
|
|
@@ -80,11 +81,13 @@
|
|
|
80
81
|
"description": "Stage 7 verify-stack summary. Detailed findings live in the external report at report_path.",
|
|
81
82
|
"properties": {
|
|
82
83
|
"report_path": {
|
|
83
|
-
"type": ["string", "null"]
|
|
84
|
+
"type": ["string", "null"],
|
|
85
|
+
"description": "report_path of the skf-verify-stack result envelope: the timestamped report, which no later run rewrites (not the -latest copy)."
|
|
84
86
|
},
|
|
85
87
|
"overall_verdict": {
|
|
86
88
|
"type": ["string", "null"],
|
|
87
|
-
"enum": ["
|
|
89
|
+
"enum": ["FEASIBLE", "CONDITIONALLY_FEASIBLE", "NOT_FEASIBLE", null],
|
|
90
|
+
"description": "overall_verdict of the skf-verify-stack result envelope."
|
|
88
91
|
},
|
|
89
92
|
"coverage_percentage": {
|
|
90
93
|
"type": ["number", "null"]
|
|
@@ -167,6 +170,24 @@
|
|
|
167
170
|
},
|
|
168
171
|
"commit_sha": {
|
|
169
172
|
"type": ["string", "null"]
|
|
173
|
+
},
|
|
174
|
+
"export": {
|
|
175
|
+
"type": ["object", "null"],
|
|
176
|
+
"additionalProperties": false,
|
|
177
|
+
"required": ["status"],
|
|
178
|
+
"description": "The Export stage's outcome for this skill, recorded by campaign-state.py set-skill --export after its skf-export-skill call: exported, or failed with that call's halt_reason and exit code (null when it gave none). Absent until Export runs the skill; a reset to pending removes it.",
|
|
179
|
+
"properties": {
|
|
180
|
+
"status": {
|
|
181
|
+
"type": "string",
|
|
182
|
+
"enum": ["exported", "failed"]
|
|
183
|
+
},
|
|
184
|
+
"halt_reason": {
|
|
185
|
+
"type": ["string", "null"]
|
|
186
|
+
},
|
|
187
|
+
"exit_code": {
|
|
188
|
+
"type": ["integer", "null"]
|
|
189
|
+
}
|
|
190
|
+
}
|
|
170
191
|
}
|
|
171
192
|
}
|
|
172
193
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# DO NOT EDIT -- overwritten on every update.
|
|
2
2
|
#
|
|
3
3
|
# Workflow customization surface for skf-campaign.
|
|
4
|
-
# Team overrides: _bmad/custom/skf-campaign.toml
|
|
5
|
-
# Personal overrides: _bmad/custom/skf-campaign.user.toml
|
|
4
|
+
# Team overrides: {project-root}/_bmad/custom/skf-campaign.toml
|
|
5
|
+
# Personal overrides: {project-root}/_bmad/custom/skf-campaign.user.toml
|
|
6
6
|
|
|
7
7
|
[workflow]
|
|
8
8
|
|
|
@@ -10,15 +10,18 @@
|
|
|
10
10
|
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
11
11
|
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
12
12
|
|
|
13
|
-
# Steps to run
|
|
14
|
-
#
|
|
15
|
-
#
|
|
13
|
+
# Steps to run right after the customization resolve (On Activation step 3).
|
|
14
|
+
# Config and preferences are already loaded by then, so a step here can read
|
|
15
|
+
# them but cannot run before them. Overrides append. Use for org-wide
|
|
16
|
+
# pre-flight checks (auth, network, compliance) that must precede any
|
|
17
|
+
# orchestration work.
|
|
16
18
|
|
|
17
19
|
activation_steps_prepend = []
|
|
18
20
|
|
|
19
|
-
# Steps to run
|
|
20
|
-
#
|
|
21
|
-
#
|
|
21
|
+
# Steps to run once activation is complete, the CLI overrides included (so
|
|
22
|
+
# headless mode already reflects --brief and --manifest), just before the
|
|
23
|
+
# first stage executes. Overrides append. Use for context loads or banner
|
|
24
|
+
# customization.
|
|
22
25
|
|
|
23
26
|
activation_steps_append = []
|
|
24
27
|
|
|
@@ -27,11 +30,21 @@ activation_steps_append = []
|
|
|
27
30
|
# into every per-skill kickoff, so project-scoped house facts propagate to
|
|
28
31
|
# the whole campaign. Overrides append.
|
|
29
32
|
#
|
|
30
|
-
# Each entry is
|
|
33
|
+
# Each entry is one of:
|
|
31
34
|
# - a literal sentence, e.g. "All skills must cite their upstream source."
|
|
32
35
|
# - a file reference prefixed with `file:`, e.g.
|
|
33
36
|
# "file:{project-root}/docs/skill-style.md" (globs supported; file
|
|
34
37
|
# contents are loaded and treated as facts).
|
|
38
|
+
# - an entry prefixed with `!`, which loads nothing and drops each earlier
|
|
39
|
+
# entry it names.
|
|
40
|
+
#
|
|
41
|
+
# The kickoff script expands each `file:` entry when it renders a Tier A
|
|
42
|
+
# kickoff (a `**` glob recursively, so the default below takes every
|
|
43
|
+
# project-context.md under {project-root}) and inlines each matching file in
|
|
44
|
+
# full into every kickoff. Overrides append, and the script drops a `!`
|
|
45
|
+
# entry and each earlier entry it names, so to keep those files out of every
|
|
46
|
+
# Tier A kickoff, set in {project-root}/_bmad/custom/skf-campaign.toml:
|
|
47
|
+
# persistent_facts = ["!file:{project-root}/**/project-context.md"]
|
|
35
48
|
|
|
36
49
|
persistent_facts = [
|
|
37
50
|
"file:{project-root}/**/project-context.md",
|
|
@@ -49,10 +62,25 @@ campaign_workspace_path = ""
|
|
|
49
62
|
|
|
50
63
|
# --- Quality gate ---
|
|
51
64
|
#
|
|
52
|
-
# Campaign-wide quality bar
|
|
53
|
-
#
|
|
54
|
-
#
|
|
55
|
-
#
|
|
65
|
+
# Campaign-wide quality bar, enforced on every skill. Precedence, highest
|
|
66
|
+
# first: the directive's `## Quality Overrides` (while the campaign runs),
|
|
67
|
+
# then the `quality_gate` of the campaign-brief.yaml Setup reads (from
|
|
68
|
+
# --brief or its opening question, field by field), then these values.
|
|
69
|
+
# Override here to change the org-wide default without forking the skill.
|
|
70
|
+
#
|
|
71
|
+
# quality_gate_hard: `zero-critical-high` is the only accepted value (Setup
|
|
72
|
+
# halts on any other). It passes a skill only when its test-skill run finds
|
|
73
|
+
# no Critical or High gap. A missing export is a Medium gap: it lowers the
|
|
74
|
+
# coverage score and no longer counts against this gate.
|
|
75
|
+
#
|
|
76
|
+
# quality_gate_soft_target: every Tier A test run gets it as `--threshold`,
|
|
77
|
+
# and a completed skill scoring at or above it exports as `pass`.
|
|
78
|
+
# quality_gate_soft_fallback: a completed skill scoring below the target but
|
|
79
|
+
# at or above this exports as `fallback`; one below it, or with no score, is
|
|
80
|
+
# listed at Export and not exported. test-skill fails a Tier A skill below
|
|
81
|
+
# its threshold unless it scores at least 80 (its threshold fallback), so a
|
|
82
|
+
# soft_fallback below 80 only matters for Tier B skills, checked by their
|
|
83
|
+
# quick-skill (skill-check) score, or for a soft_target below 80.
|
|
56
84
|
|
|
57
85
|
quality_gate_hard = "zero-critical-high"
|
|
58
86
|
quality_gate_soft_target = 90
|
|
@@ -68,8 +96,11 @@ report_template_path = ""
|
|
|
68
96
|
kickoff_template_path = ""
|
|
69
97
|
brief_template_path = ""
|
|
70
98
|
|
|
71
|
-
# Optional post-completion hook. When non-empty,
|
|
99
|
+
# Optional post-completion hook. When non-empty, step-11 invokes it once
|
|
100
|
+
# the campaign is finished: after the report and the final state write
|
|
101
|
+
# (current_stage 10), before the headless result envelope:
|
|
72
102
|
# <on_complete> --report-path=<path-to-campaign-report.md>
|
|
73
|
-
#
|
|
74
|
-
#
|
|
103
|
+
# --report-path is passed only when the report was written; a report that
|
|
104
|
+
# could not be generated leaves the hook called without it. Failures are
|
|
105
|
+
# logged to the decision log but never fail the campaign. Empty = no-op.
|
|
75
106
|
on_complete = ""
|