bmad-module-skill-forge 1.4.0 → 1.5.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 +0 -8
- package/docs/_data/pinned.yaml +1 -1
- package/docs/_internal/STABILITY.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/examples.md +1 -1
- package/docs/workflows.md +5 -5
- package/package.json +2 -2
- package/src/README.md +1 -1
- package/src/knowledge/ccc-bridge.md +12 -12
- package/src/knowledge/qmd-registry.md +5 -5
- package/src/shared/health-check.md +5 -5
- package/src/shared/references/description-guard-protocol.md +100 -0
- package/src/shared/references/output-contract-schema.md +1 -1
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
- package/src/shared/scripts/skf-build-change-manifest.py +420 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
- package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
- package/src/shared/scripts/skf-description-guard.py +359 -0
- package/src/shared/scripts/skf-detect-language.py +2 -2
- package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
- package/src/shared/scripts/skf-detect-tools.py +97 -8
- package/src/shared/scripts/skf-detect-workspaces.py +1 -1
- package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
- package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
- package/src/shared/scripts/skf-hash-content.py +284 -0
- package/src/shared/scripts/skf-load-provenance.py +295 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +45 -1
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
- package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
- package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
- package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
- package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
- package/src/skf-audit-skill/SKILL.md +66 -15
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
- package/src/skf-audit-skill/customize.toml +49 -0
- package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-audit-skill/references/init.md +305 -0
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -16
- package/src/skf-brief-skill/SKILL.md +48 -18
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
- package/src/skf-brief-skill/customize.toml +44 -0
- package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
- package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
- package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
- package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
- package/src/skf-brief-skill/references/headless-args.md +9 -9
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
- package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
- package/src/skf-brief-skill/references/version-resolution.md +2 -2
- package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
- package/src/skf-create-skill/SKILL.md +25 -19
- package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
- package/src/skf-create-skill/assets/skill-sections.md +5 -5
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
- package/src/skf-create-skill/customize.toml +35 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
- package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
- package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
- package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
- package/src/skf-create-skill/references/extraction-patterns.md +8 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +17 -9
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
- package/src/skf-create-stack-skill/SKILL.md +76 -17
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +46 -0
- package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
- package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
- package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
- package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
- package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
- package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
- package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
- package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
- package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
- package/src/skf-drop-skill/SKILL.md +84 -12
- package/src/skf-drop-skill/customize.toml +57 -0
- package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
- package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
- package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
- package/src/skf-export-skill/SKILL.md +85 -16
- package/src/skf-export-skill/assets/managed-section-format.md +3 -3
- package/src/skf-export-skill/assets/snippet-format.md +2 -2
- package/src/skf-export-skill/customize.toml +49 -0
- package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +18 -12
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +21 -51
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +30 -6
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +116 -91
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +14 -22
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
- package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
- package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
- package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
- package/src/skf-test-skill/references/health-check.md +14 -0
- package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
- package/src/skf-test-skill/references/migration-section-rules.md +4 -2
- package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
- package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
- package/src/skf-test-skill/references/scoring-rules.md +8 -6
- package/src/skf-test-skill/references/source-access-protocol.md +7 -5
- package/src/skf-test-skill/scripts/compute-score.py +88 -17
- package/src/skf-test-skill/templates/test-report-template.md +13 -13
- package/src/skf-update-skill/SKILL.md +23 -14
- package/src/skf-update-skill/customize.toml +44 -0
- package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
- package/src/skf-update-skill/references/health-check.md +32 -0
- package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
- package/src/skf-update-skill/references/manual-section-rules.md +4 -0
- package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
- package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
- package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
- package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
- package/src/skf-update-skill/references/report.md +214 -0
- package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
- package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
- package/src/skf-verify-stack/SKILL.md +89 -17
- package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
- package/src/skf-verify-stack/customize.toml +50 -0
- package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
- package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
- package/src/skf-verify-stack/references/init.md +166 -0
- package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
- package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
- package/tools/validate-docs-drift.js +1 -1
- package/src/skf-audit-skill/steps-c/step-01-init.md +0 -221
- package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
- package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
- package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
- package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
- package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
- package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
package/README.md
CHANGED
|
@@ -181,14 +181,6 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
|
|
|
181
181
|
|
|
182
182
|
Past releases are documented in [CHANGELOG.md](CHANGELOG.md).
|
|
183
183
|
|
|
184
|
-
## Versioning & Stability
|
|
185
|
-
|
|
186
|
-
The v1.0.0 public API contract is documented in [docs/_internal/STABILITY.md](docs/_internal/STABILITY.md).
|
|
187
|
-
|
|
188
|
-
## Release Process
|
|
189
|
-
|
|
190
|
-
Maintainers: see [docs/_internal/RELEASING.md](docs/_internal/RELEASING.md) for branch-protection rules, required status checks, the [`release` environment with required-reviewer gate](docs/_internal/RELEASING.md#release-environment), the [npm Trusted Publisher registration](docs/_internal/RELEASING.md#npm-trusted-publisher) (OIDC-backed publish, auto-provenance), and the [rollback playbook](docs/_internal/RELEASING.md#rollback-playbook) covering seven failure scenarios.
|
|
191
|
-
|
|
192
184
|
## License
|
|
193
185
|
|
|
194
186
|
MIT License — see [LICENSE](LICENSE) for details.
|
package/docs/_data/pinned.yaml
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
# Enforced two ways: (1) release.yaml bumps this line in the same commit
|
|
27
27
|
# as package.json + marketplace.json on every release; (2) validate-docs-drift.js
|
|
28
28
|
# cross-checks this value against package.json.version and fails on mismatch.
|
|
29
|
-
skf_version: "1.
|
|
29
|
+
skf_version: "1.5.0"
|
|
30
30
|
|
|
31
31
|
# Path to the oh-my-skills repo, resolved relative to this repo's root.
|
|
32
32
|
# Override at runtime with the OMS environment variable if oh-my-skills
|
|
@@ -86,7 +86,7 @@ SKF supports the Node.js major versions declared in `package.json` `engines.node
|
|
|
86
86
|
The following surfaces are explicitly excluded from the v1.0.0 contract. Changes to any of these may land in any release — patch, minor, or major — without constituting a "breaking change" from a SemVer perspective. Downstream consumers SHOULD NOT pin against these surfaces.
|
|
87
87
|
|
|
88
88
|
- **`tools/cli/lib/*` internal helper modules** — implementation detail of the CLI; not a library. Any refactor that preserves the observable CLI surface and install layout above is allowed.
|
|
89
|
-
- **Internal structure of workflow step files under `src/skf-*/
|
|
89
|
+
- **Internal structure of workflow step files under `src/skf-*/references/`** — the workflow authoring format is an SKF-internal authoring surface; step numbering, file names, and prose can change.
|
|
90
90
|
- **`_bmad/_memory/forger-sidecar/*.yaml` file schemas** — Ferris sidecar state. Stable as a runtime contract between SKF versions during one install's lifetime (so `skf update` works), but not a downstream-consumable schema.
|
|
91
91
|
- **Ferris agent persona prose and menu wording** — the in-product agent persona can be rephrased or restructured at any time.
|
|
92
92
|
- **Exact chalk styling / ANSI color choices in command output** — stylistic; see the output-format bucket above for what IS committed.
|
package/docs/architecture.md
CHANGED
|
@@ -22,7 +22,7 @@ Each workflow directory contains these files, and each has a specific job:
|
|
|
22
22
|
| File | What it does | When it loads |
|
|
23
23
|
|---------------------------|---------------------------------------------------------------------------------------------------------------------|---------------------------------------------------|
|
|
24
24
|
| `SKILL.md` | Human-readable entry point — goals, role definition, initialization sequence, invocation contract, routes to first step | Entry point per workflow |
|
|
25
|
-
| `
|
|
25
|
+
| `references/*.md` | **Create** steps — primary execution, 4–10 sequential files per workflow (the last one always chains to the shared health check) | One at a time (just-in-time) |
|
|
26
26
|
| `references/*.md` | Workflow-specific reference data — rules, patterns, protocols | Read by steps on demand |
|
|
27
27
|
| `assets/*.md` | Workflow-specific output formats — schemas, templates, heuristics | Read by steps on demand |
|
|
28
28
|
| `templates/*.md` | Output skeletons with placeholder vars — steps fill these in to produce the final artifact | Read by steps when generating output |
|
|
@@ -41,7 +41,7 @@ Each workflow directory contains these files, and each has a specific job:
|
|
|
41
41
|
flowchart LR
|
|
42
42
|
U[User] --> A[Agent Persona]
|
|
43
43
|
A --> W[Workflow Entry: SKILL.md]
|
|
44
|
-
W --> S[Step Files:
|
|
44
|
+
W --> S[Step Files: references/]
|
|
45
45
|
S --> K[Knowledge Fragments<br/>skf-knowledge-index.csv → knowledge/*.md]
|
|
46
46
|
S --> D[References & Assets<br/>references/*.md, assets/*.md, templates/*.md]
|
|
47
47
|
S --> P[Scripts<br/>scripts/*.py, shared/scripts/*.py]
|
package/docs/examples.md
CHANGED
|
@@ -210,7 +210,7 @@ No source code to clone — only API documentation. Example: you're integrating
|
|
|
210
210
|
# When asked for target version, specify: 2025-04-30.basil
|
|
211
211
|
# Ferris confirms your doc URLs match that API version
|
|
212
212
|
@Ferris CS
|
|
213
|
-
# step
|
|
213
|
+
# step 3 skips (no source to clone), step 3c fetches docs via doc_fetcher
|
|
214
214
|
# All content is T3 [EXT:url] confidence. source_authority: community
|
|
215
215
|
```
|
|
216
216
|
|
package/docs/workflows.md
CHANGED
|
@@ -361,7 +361,7 @@ You can also set `headless_mode: true` in your forge preferences (`_bmad/_memory
|
|
|
361
361
|
SKF_SETUP_RESULT_JSON: {"skf_setup":{"tier":"Deep","previous_tier":"Forge","tier_changed":true,"tools":{...},"tools_added":[...],"tools_removed":[],"config_path":"...","ccc_index":{...},"files_written":[...],"tier_override_active":false,"tier_override_invalid":false,"require_tier_satisfied":null,"warnings":[],"error":null}}
|
|
362
362
|
```
|
|
363
363
|
|
|
364
|
-
Parent skills and CI pipelines `grep` one line out of the workflow log to learn the outcome — no ASCII-art parsing, no race against the [`forge-tier.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-setup/
|
|
364
|
+
Parent skills and CI pipelines `grep` one line out of the workflow log to learn the outcome — no ASCII-art parsing, no race against the [`forge-tier.yaml`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-setup/references/write-config.md) writer. The envelope schema is versioned at [`src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json) and asserted against on every emit.
|
|
365
365
|
|
|
366
366
|
**Exception — `/skf-quick-skill` headless emits structured progress + result envelopes.** Headless `/skf-quick-skill` runs are first-class building blocks for batch automators. Three operational contracts beyond per-gate auto-proceed:
|
|
367
367
|
|
|
@@ -386,13 +386,13 @@ Parent skills and CI pipelines `grep` one line out of the workflow log to learn
|
|
|
386
386
|
| 6 | compile-cancelled |
|
|
387
387
|
| 7 | finalize-blocked |
|
|
388
388
|
|
|
389
|
-
3. **Error-variant result contract on every HARD HALT.** A `SKF_QUICK_SKILL_RESULT_JSON: {…}` envelope is emitted on `stderr` (always) and copied to `{skill_package}/quick-skill-result-latest.json` when the skill package is known (HALTs at step
|
|
389
|
+
3. **Error-variant result contract on every HARD HALT.** A `SKF_QUICK_SKILL_RESULT_JSON: {…}` envelope is emitted on `stderr` (always) and copied to `{skill_package}/quick-skill-result-latest.json` when the skill package is known (HALTs at step 5 §1 onward). The schema and full population rules live in [`src/skf-quick-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/SKILL.md) § "Result Contract on HARD HALT".
|
|
390
390
|
|
|
391
391
|
**Batch mode (`--batch <file>`).** Drives N targets through the full pipeline (steps 1–7 each) in sequence. Input format: one target per line, `#` comments and blank lines ignored, optional per-line modifiers `language=<lang>` and `scope=<path>`. Per-target output lands in `{skill_package}/` as today; an aggregated summary writes to `{skills_output_folder}/_batch/quick-skill-batch-{ts}.json` (with `quick-skill-batch-latest.json` copy). Per-target boundary events (`{"batch":N,"target":"…","status":"start|done|fail",…}`) and a final `{"batch_summary":true,…}` event extend the per-step event stream above. Full input grammar, summary schema, and exit-code semantics in [`src/skf-quick-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-quick-skill/SKILL.md) § "Batch Mode".
|
|
392
392
|
|
|
393
393
|
**Exception — `/skf-brief-skill` headless emits a final result envelope and supports presets.** Headless `/skf-brief-skill` is a first-class building block for scripted brief generation (e.g. seeding briefs for N SaaS SDKs that share scope/authority defaults). Three operational contracts beyond per-gate auto-proceed:
|
|
394
394
|
|
|
395
|
-
1. **Pre-supplied inputs replace prompts.** Headless args are consumed at step
|
|
395
|
+
1. **Pre-supplied inputs replace prompts.** Headless args are consumed at step 1's GATE in place of the interactive menus: `target_repo`, `skill_name`, `target_version`, `language`, `source_type`, `source_authority`, `doc_urls`, `scope_type`, `scripts_intent`, `force`, `preset`. Required-arg shape depends on `source_type` (`target_repo` + `skill_name` for source-backed; `doc_urls` + `skill_name` for `docs-only`). Absent `source_authority` and `scope_type` are NOT guessed — they're resolved by signal-driven detection (`gh api user` vs. repo owner for authority; the 5-rule heuristic ladder for scope). Full grammar in [`src/skf-brief-skill/references/headless-args.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/references/headless-args.md).
|
|
396
396
|
|
|
397
397
|
2. **Structured exit-code map.** Every HARD HALT exits with a stable code so pipelines branch on the failure class without grepping message text:
|
|
398
398
|
|
|
@@ -405,9 +405,9 @@ Parent skills and CI pipelines `grep` one line out of the workflow log to learn
|
|
|
405
405
|
| 5 | overwrite-cancelled |
|
|
406
406
|
| 6 | user-cancelled |
|
|
407
407
|
|
|
408
|
-
3. **Final result envelope on every terminal exit.** Step-05 emits a single-line `SKF_BRIEF_RESULT_JSON: {…}` envelope on **stdout** before chaining to step
|
|
408
|
+
3. **Final result envelope on every terminal exit.** Step-05 emits a single-line `SKF_BRIEF_RESULT_JSON: {…}` envelope on **stdout** before chaining to step 6 on success; every HARD HALT emits the same envelope shape on **stderr** with `status: "error"` and a typed `halt_reason` (`input-missing`, `input-invalid`, `forge-tier-missing`, `target-inaccessible`, `gh-auth-failed`, `write-failed`, `overwrite-cancelled`, `user-cancelled`). Full envelope schema and population rules in [`src/skf-brief-skill/SKILL.md`](https://github.com/armelhbobdad/bmad-module-skill-forge/blob/main/src/skf-brief-skill/SKILL.md) § "Result Contract (Headless)".
|
|
409
409
|
|
|
410
|
-
**Presets (`--preset <name>`).** Loads `{sidecar_path}/brief-presets/{name}.yaml` and merges its keys as defaults at step
|
|
410
|
+
**Presets (`--preset <name>`).** Loads `{sidecar_path}/brief-presets/{name}.yaml` and merges its keys as defaults at step 1 §8; explicit headless args override preset values. The preset file is YAML containing any subset of the headless args above; unknown fields are ignored with a warning. Useful for repeated patterns — e.g. briefing 5 SaaS SDKs that all share `source_authority=community`, `scope_type=full-library`, `scripts_intent=skip`.
|
|
411
411
|
|
|
412
412
|
---
|
|
413
413
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "bmad-module-skill-forge",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"description": "BMAD module — Turn code and docs into instructions AI agents can actually follow. Progressive capability tiers (Quick/Forge/Forge+/Deep).",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"bmad",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"test:cli": "node test/test-cli-integration.js",
|
|
54
54
|
"test:install": "node test/test-installation-components.js",
|
|
55
55
|
"test:knowledge": "node test/test-knowledge-base.js",
|
|
56
|
-
"test:python": "uv run --with pytest --with pyyaml pytest test/test-compute-score-contract.py test/test-skf-preflight.py test/test-skf-skill-inventory.py test/test-skf-validate-output.py test/test-skf-validate-frontmatter.py test/test-skf-manifest-ops.py test/test-skf-rebuild-managed-sections.py test/test-skf-severity-classify.py test/test-skf-structural-diff.py test/test-skf-detect-tools.py test/test-skf-forge-tier-rw.py test/test-skf-emit-result-envelope.py test/test-skf-qmd-classify-collections.py test/test-skf-merge-ccc-exclusions.py test/test-skf-resolve-package.py test/test-skf-extract-public-api.py test/test-skf-render-quick-metadata.py test/test-skf-validate-brief-inputs.py test/test-skf-emit-brief-result-envelope.py test/test-skf-write-skill-brief.py test/test-skf-detect-workspaces.py test/test-skf-recommend-scope-type.py test/test-skf-detect-language.py -v",
|
|
56
|
+
"test:python": "uv run --with pytest --with pyyaml --with jsonschema pytest test/test-compute-score-contract.py test/test-skf-preflight.py test/test-skf-skill-inventory.py test/test-skf-validate-output.py test/test-skf-validate-frontmatter.py test/test-skf-manifest-ops.py test/test-skf-rebuild-managed-sections.py test/test-skf-severity-classify.py test/test-skf-structural-diff.py test/test-skf-detect-tools.py test/test-skf-forge-tier-rw.py test/test-skf-emit-result-envelope.py test/test-skf-qmd-classify-collections.py test/test-skf-merge-ccc-exclusions.py test/test-skf-resolve-package.py test/test-skf-extract-public-api.py test/test-skf-render-quick-metadata.py test/test-skf-validate-brief-inputs.py test/test-skf-emit-brief-result-envelope.py test/test-skf-write-skill-brief.py test/test-skf-detect-workspaces.py test/test-skf-recommend-scope-type.py test/test-skf-detect-language.py test/test-skf-description-guard.py test/test-skf-detect-scripts-assets.py test/test-skf-hash-content.py test/test-skf-validate-brief-schema.py test/test-skf-check-workspace-drift.py test/test-skf-update-active-symlink.py test/test-skf-build-change-manifest.py test/test-skf-provenance-gap-dispatch.py test/test-skf-resolve-authoritative-files.py test/test-skf-scan-manifests.py test/test-skf-pair-intersect.py test/test-skf-enumerate-stack-skills.py test/test-skf-compare-file-hashes.py test/test-skf-load-provenance.py test/test-skf-scan-skill-md-structure.py test/test-skf-disqualify-candidates.py test/test-skf-chain-reachability.py -v",
|
|
57
57
|
"test:schemas": "node test/test-agent-schema.js",
|
|
58
58
|
"test:workflow": "node test/test-workflow-state.js",
|
|
59
59
|
"validate:refs": "node tools/validate-file-refs.js --strict",
|
package/src/README.md
CHANGED
|
@@ -16,7 +16,7 @@ src/
|
|
|
16
16
|
│ └── ...
|
|
17
17
|
├── skf-{name}/ # 13 workflow skills (one directory each)
|
|
18
18
|
│ ├── SKILL.md # Skill entry point (overview, stages, invocation contract)
|
|
19
|
-
│ ├──
|
|
19
|
+
│ ├── references/ # Sequential step files
|
|
20
20
|
│ ├── references/ # Rules, patterns, protocols (decision-making)
|
|
21
21
|
│ ├── assets/ # Schemas, output formats
|
|
22
22
|
│ └── templates/ # Output skeletons (used by some skills)
|
|
@@ -43,7 +43,7 @@ Returns: list of `{file, score, snippet}` entries ranked by semantic relevance t
|
|
|
43
43
|
|
|
44
44
|
**Resolves to:** Check `ccc_index.status` in forge-tier.yaml. If `"none"` or the indexed_path does not match, run `cd {path} && ccc init` then `ccc index` and update forge-tier.yaml. Note: `ccc init` takes no positional arguments — it initializes the index for the current working directory.
|
|
45
45
|
|
|
46
|
-
**Usage context:** Called by setup step
|
|
46
|
+
**Usage context:** Called by setup step 1b to ensure the project root is indexed. Called lazily by extraction steps when `ccc_index.status` is `"none"` but ccc is available.
|
|
47
47
|
|
|
48
48
|
### `ccc_bridge.status()`
|
|
49
49
|
|
|
@@ -51,7 +51,7 @@ Returns: list of `{file, score, snippet}` entries ranked by semantic relevance t
|
|
|
51
51
|
1. `ccc --help` — confirms binary exists (exit 0) AND output contains the `CocoIndex Code` identity marker (rejects unrelated `ccc`-named binaries shadowing PATH)
|
|
52
52
|
2. `ccc doctor` — confirms daemon is running, extracts version string, validates embedding model
|
|
53
53
|
|
|
54
|
-
**Usage context:** Called exclusively by setup step
|
|
54
|
+
**Usage context:** Called exclusively by setup step 1 during tool detection. Downstream workflows read the result from forge-tier.yaml — they do not re-verify.
|
|
55
55
|
|
|
56
56
|
## Confidence
|
|
57
57
|
|
|
@@ -67,7 +67,7 @@ The ccc search is invisible in the output artifact. A Forge+ skill's citations a
|
|
|
67
67
|
|
|
68
68
|
### When Indexing Happens
|
|
69
69
|
|
|
70
|
-
1. **setup step
|
|
70
|
+
1. **setup step 1b:** Indexes the project root when setup runs. This is the primary indexing point.
|
|
71
71
|
2. **Workflow discovery steps:** If `ccc_index.status` is `"stale"` or `"none"`, discovery steps trigger a re-index and warn the user. They do not block.
|
|
72
72
|
3. **ccc daemon:** Incremental indexing means re-indexing unchanged files is a near-no-op.
|
|
73
73
|
|
|
@@ -81,7 +81,7 @@ The ccc search is invisible in the output artifact. A Forge+ skill's citations a
|
|
|
81
81
|
|
|
82
82
|
CCC stores its configuration at `{project-root}/.cocoindex_code/settings.yml`. This file contains `exclude_patterns` and `include_patterns` arrays in glob format. `ccc init` creates the file with sensible defaults (excludes `node_modules`, `__pycache__`, hidden dirs, etc.).
|
|
83
83
|
|
|
84
|
-
**SKF infrastructure exclusions:** setup step
|
|
84
|
+
**SKF infrastructure exclusions:** setup step 1b appends SKF-specific exclusion patterns after `ccc init` creates the default config. These patterns prevent indexing of framework and output directories that have zero value for source extraction:
|
|
85
85
|
|
|
86
86
|
| Pattern | Purpose |
|
|
87
87
|
|---------|---------|
|
|
@@ -98,13 +98,13 @@ The configured exclusion patterns are stored in `ccc_index.exclude_patterns` in
|
|
|
98
98
|
|
|
99
99
|
### Deferred Discovery (Remote Sources)
|
|
100
100
|
|
|
101
|
-
For remote repository sources (GitHub URLs), CCC cannot operate during step
|
|
101
|
+
For remote repository sources (GitHub URLs), CCC cannot operate during step 2b because no local code exists yet. The workspace clone or ephemeral clone happens in step 3. To provide CCC pre-ranking for remote sources:
|
|
102
102
|
|
|
103
|
-
1. **step
|
|
104
|
-
2. **step
|
|
105
|
-
3. **step
|
|
106
|
-
4. **step
|
|
107
|
-
5. **step
|
|
103
|
+
1. **step 2b:** Detects remote source, sets `{ccc_discovery: []}`, displays deferred message
|
|
104
|
+
2. **step 3:** After source resolution succeeds, detects the deferred scenario (`tools.ccc == true AND {ccc_discovery} is empty AND remote_clone_path is set AND tier is Forge+/Deep`)
|
|
105
|
+
3. **step 3 (workspace fast path):** If `{remote_clone_path}/.cocoindex_code/` already exists (persisted workspace index), skips init/index and uses `ccc search --refresh` — CCC daemon re-indexes only if files changed since last index. This is near-instant for unchanged repos.
|
|
106
|
+
4. **step 3 (first-time path):** If no existing CCC index, runs `cd {remote_clone_path} && ccc init`, applies standard build/dependency exclusions (node_modules, dist, .git, vendor, etc.) to `settings.yml`, then runs `ccc index`. Brief-specific `include_patterns`/`exclude_patterns` are NOT written to `settings.yml` — the CCC index is general-purpose. Filtering happens at search result time.
|
|
107
|
+
5. **step 3:** Executes CCC search and populates `{ccc_discovery}` before AST extraction begins
|
|
108
108
|
|
|
109
109
|
For workspace repos, the CCC index persists at `{workspace_repo_path}/.cocoindex_code/` and is reused across forges, projects, and sessions. For ephemeral fallback clones, the index is not registered in `ccc_index_registry` — the clone is deleted after extraction.
|
|
110
110
|
|
|
@@ -114,7 +114,7 @@ ccc_index and qmd_collections are **orthogonal**:
|
|
|
114
114
|
- `ccc_index` in forge-tier.yaml tracks the persistent source code index (one per project)
|
|
115
115
|
- `qmd_collections[]` in forge-tier.yaml tracks per-skill workflow artifact collections
|
|
116
116
|
- ccc indexes source code for semantic search; QMD indexes curated artifacts for temporal/knowledge search
|
|
117
|
-
- The janitor role for QMD (setup step
|
|
117
|
+
- The janitor role for QMD (setup step 3) operates independently of ccc_index
|
|
118
118
|
|
|
119
119
|
## Query Volume Bounds
|
|
120
120
|
|
|
@@ -133,7 +133,7 @@ To prevent excessive daemon calls, workflow steps cap ccc queries:
|
|
|
133
133
|
- Listing ccc as "unavailable" in reports for Quick/Forge tiers — ccc is a Forge+ capability, not something Quick/Forge tiers are missing
|
|
134
134
|
- Indexing without configuring exclusions — for project root indexes, apply SKF exclusions (framework/output directories); for workspace repo indexes, apply standard build artifact exclusions (node_modules, dist, .git, etc.)
|
|
135
135
|
- Writing brief-specific `exclude_patterns` to a workspace repo's `settings.yml` — workspace indexes are general-purpose and serve multiple briefs. Apply brief patterns at search result time, not index time. (Exception: ephemeral fallback clones are single-use, so brief exclusions may be applied to their `settings.yml` to reduce indexing time.)
|
|
136
|
-
- Skipping CCC discovery for remote sources without deferring to step
|
|
136
|
+
- Skipping CCC discovery for remote sources without deferring to step 3 — remote repos deserve the same pre-ranking as local sources
|
|
137
137
|
|
|
138
138
|
## Related Fragments
|
|
139
139
|
|
|
@@ -51,10 +51,10 @@ The `status` field is only present when QMD embed verification fails during coll
|
|
|
51
51
|
|
|
52
52
|
| Type | Producer | Content | Primary Consumers |
|
|
53
53
|
| --- | --- | --- | --- |
|
|
54
|
-
| `extraction` | create-skill step
|
|
55
|
-
| `brief` | brief-skill step
|
|
56
|
-
| `temporal` | create-skill step
|
|
57
|
-
| `docs` | create-skill step
|
|
54
|
+
| `extraction` | create-skill step 7 | Compiled SKILL.md, references, context-snippet — structured, confidence-rated exports | audit-skill (drift detection), update-skill (T2 enrichment) |
|
|
55
|
+
| `brief` | brief-skill step 5 | skill-brief.yaml — intent, scope, target repository metadata | Portfolio-level search (cross-skill deduplication) |
|
|
56
|
+
| `temporal` | create-skill step 3b | GitHub issues, PRs, releases, changelogs — historical and planned context at T2 confidence | step 4 enrichment (temporal annotations per exported function) |
|
|
57
|
+
| `docs` | create-skill step 3c | Fetched external documentation — API references, guides, usage examples (T3 confidence) | step 4 enrichment (cross-reference doc context with source-extracted functions) |
|
|
58
58
|
|
|
59
59
|
### Lifecycle
|
|
60
60
|
|
|
@@ -112,7 +112,7 @@ The `ccc_index_registry` array in forge-tier.yaml is a **parallel but separate**
|
|
|
112
112
|
| **What is indexed** | Curated workflow artifacts (SKILL.md, briefs, temporal data) | Source code (the actual codebase) |
|
|
113
113
|
| **Index engine** | QMD (BM25 + optional vector search) | cocoindex-code (AST + vector embeddings) |
|
|
114
114
|
| **Lifecycle** | Per-skill: created by create-skill, consumed by audit/update-skill | Per-project: created by setup, verified by create-skill |
|
|
115
|
-
| **Janitor** | setup step
|
|
115
|
+
| **Janitor** | setup step 3 (orphan/stale QMD collection cleanup) | setup step 3 section 5b (stale path cleanup) |
|
|
116
116
|
| **Availability** | Deep tier only | Forge+ and Deep tiers |
|
|
117
117
|
|
|
118
118
|
These registries are orthogonal — they never reference each other, and their janitor sections operate independently.
|
|
@@ -90,7 +90,7 @@ For each genuine finding, present it in this format:
|
|
|
90
90
|
|-------|-------|
|
|
91
91
|
| **Severity** | `bug` / `friction` / `gap` |
|
|
92
92
|
| **Workflow** | {workflow name} |
|
|
93
|
-
| **Step File** | `src/skf-{workflow}/
|
|
93
|
+
| **Step File** | `src/skf-{workflow}/references/{step-file-path}` |
|
|
94
94
|
| **Section** | {the specific section or instruction number — use a stable section heading slug, not line numbers} |
|
|
95
95
|
| **Fingerprint** | `fp-{7-hex}` — first 7 hex chars of `sha1("{severity}|{workflow}|{step_file}|{section-slug}")` |
|
|
96
96
|
|
|
@@ -223,7 +223,7 @@ After the issue is created, write the fingerprint → issue-url mapping to the s
|
|
|
223
223
|
{workflow name, e.g. `skf-create-skill`}
|
|
224
224
|
|
|
225
225
|
## Step File
|
|
226
|
-
`src/skf-{workflow}/
|
|
226
|
+
`src/skf-{workflow}/references/step-NN-name.md`
|
|
227
227
|
|
|
228
228
|
## Severity
|
|
229
229
|
`{bug | friction | gap}`
|
|
@@ -246,7 +246,7 @@ After the issue is created, write the fingerprint → issue-url mapping to the s
|
|
|
246
246
|
|
|
247
247
|
## Actual
|
|
248
248
|
<!-- ONE sentence. What did you observe instead? -->
|
|
249
|
-
{e.g. No staging path specified, so artifacts were written to `skills/{name}/` and step
|
|
249
|
+
{e.g. No staging path specified, so artifacts were written to `skills/{name}/` and step 7 had to reorganize them.}
|
|
250
250
|
|
|
251
251
|
## Evidence
|
|
252
252
|
<!-- Bulleted `file:line` citations. 2-5 bullets. No narrative prose. -->
|
|
@@ -255,11 +255,11 @@ After the issue is created, write the fingerprint → issue-url mapping to the s
|
|
|
255
255
|
|
|
256
256
|
## Impact
|
|
257
257
|
<!-- ONE sentence. What did this cost in THIS session? -->
|
|
258
|
-
{e.g. 50KB of artifacts written to the wrong path; step
|
|
258
|
+
{e.g. 50KB of artifacts written to the wrong path; step 7 required a file-move pass.}
|
|
259
259
|
|
|
260
260
|
## Suggested Fix
|
|
261
261
|
<!-- ONE recommended change. 1-3 sentences. Do NOT list multiple options here. -->
|
|
262
|
-
{e.g. Add a rule to step
|
|
262
|
+
{e.g. Add a rule to step 5 naming `_bmad-output/{skill-name}/` as the staging directory used by step 6 validation.}
|
|
263
263
|
|
|
264
264
|
<details>
|
|
265
265
|
<summary>Alternatives considered (optional)</summary>
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Description Guard Protocol
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
External validators (`skill-check check --fix`, `skill-check split-body`, and any future tool that may rewrite SKILL.md frontmatter) occasionally replace, truncate, or otherwise mutate the `description` field — sometimes substituting a generic version, sometimes re-introducing angle-bracket tokens that earlier sanitization removed.
|
|
6
|
+
|
|
7
|
+
The on-disk description is **authoritative**: it has been compiled (in `skf-create-skill`) or merged (in `skf-update-skill`) with deliberate trigger-optimization. Losing it to a tool's well-meaning rewrite breaks agent discovery quality and can re-introduce the angle-bracket failure mode that breaks tessl on the next run.
|
|
8
|
+
|
|
9
|
+
Any tool invocation that may touch SKILL.md must run inside the four-phase guard below. Workflows invoke the deterministic phases (1, 3, 4) via `src/shared/scripts/skf-description-guard.py`; the LLM only performs phase 2 (the tool call itself).
|
|
10
|
+
|
|
11
|
+
## The Four-Phase Guard
|
|
12
|
+
|
|
13
|
+
### 1. Capture
|
|
14
|
+
|
|
15
|
+
Before invoking the tool, snapshot the on-disk `description` value:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
uv run {project-root}/src/shared/scripts/skf-description-guard.py \
|
|
19
|
+
capture <skill-md-path>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Output JSON:
|
|
23
|
+
|
|
24
|
+
```json
|
|
25
|
+
{
|
|
26
|
+
"description": "the snapshotted value",
|
|
27
|
+
"schema_hash": "sha256:..."
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Stash the `description` value in workflow context as `guarded_description`. Also keep the in-context copy synced with the on-disk pre-call state.
|
|
32
|
+
|
|
33
|
+
### 2. Execute
|
|
34
|
+
|
|
35
|
+
Run the tool as specified in its section. The LLM performs this step normally — `skill-check check --fix`, `skill-check split-body`, or whatever is documented in the calling stage.
|
|
36
|
+
|
|
37
|
+
### 3 + 4. Verify and Restore
|
|
38
|
+
|
|
39
|
+
After the tool completes, run:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv run {project-root}/src/shared/scripts/skf-description-guard.py \
|
|
43
|
+
verify-restore <skill-md-path> \
|
|
44
|
+
--captured-description "{guarded_description}"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The script:
|
|
48
|
+
|
|
49
|
+
1. Re-reads on-disk `description`
|
|
50
|
+
2. Compares against `guarded_description` using **token-stream equality** — split each string on whitespace, compare resulting token lists element-by-element
|
|
51
|
+
3. If diverged: atomically rewrites the frontmatter `description` field with `guarded_description`
|
|
52
|
+
|
|
53
|
+
Output JSON:
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"diverged": true|false,
|
|
58
|
+
"restored": true|false,
|
|
59
|
+
"diff_kind": "none|whitespace-only|replaced|truncated|deleted",
|
|
60
|
+
"current_description": "what was on disk before any restore"
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
If `restored == true`, also update the in-context copy of `description` to match `guarded_description` so subsequent stages do not work from a stale tool-mutated version. Record `description_guard_restored: true` (with the tool name) in workflow context for the evidence report.
|
|
65
|
+
|
|
66
|
+
## Why Token-Stream Comparison
|
|
67
|
+
|
|
68
|
+
Token-stream comparison is the documented sweet spot between two failure modes:
|
|
69
|
+
|
|
70
|
+
- **Looser fuzzy matching** would let a tool swap one word past the guard (e.g., replace "compile" with "build").
|
|
71
|
+
- **Naive whitespace-normalized equality** would trip on a tool that collapses `"foo bar"` → `"foo bar"` (cosmetic whitespace fix), forcing unnecessary restore writes.
|
|
72
|
+
|
|
73
|
+
Splitting on whitespace and comparing token lists catches replaced words, truncation, deletion, and angle-bracket re-introduction while ignoring trailing newlines, re-wrapped quoted strings, and collapsed inner runs.
|
|
74
|
+
|
|
75
|
+
## What Counts as Divergence
|
|
76
|
+
|
|
77
|
+
- **`replaced`** — different content (any word changed)
|
|
78
|
+
- **`truncated`** — current tokens are a strict prefix of captured
|
|
79
|
+
- **`deleted`** — the field is empty or whitespace-only on disk
|
|
80
|
+
- **`whitespace-only`** — token streams match but raw strings differ (**not** divergence; do not restore)
|
|
81
|
+
- **`none`** — byte-identical (**not** divergence)
|
|
82
|
+
|
|
83
|
+
## Post-Restore Re-Validation (Optional)
|
|
84
|
+
|
|
85
|
+
Skills that run frontmatter compliance checks (e.g. `skf-create-skill validate.md`) should additionally re-validate the restored description against the frontmatter contract after restore — a restored value must still satisfy length limits, forbidden-token rules, and required-field shape. Run:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
uv run {project-root}/src/shared/scripts/skf-validate-frontmatter.py <skill-md-path>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
If the validator reports failure for the `description` field, flip the Schema row in the evidence report back to `FAIL` and record `description_guard_revalidation: FAIL` with the validator diagnostic. Do not halt — let the failure surface through the normal artifact path so step health-check and the result contract record it.
|
|
92
|
+
|
|
93
|
+
## Why This Protocol Is Centralized
|
|
94
|
+
|
|
95
|
+
Previously, each tool invocation in each calling stage carried its own copy of the capture/verify/restore prose. Duplicated defensive logic drifts: a fix in one section did not propagate to the other, and adding a new tool invocation required remembering to copy the pattern. Centralizing the protocol gives every calling stage one place to update when external validator behavior changes.
|
|
96
|
+
|
|
97
|
+
## Calling Workflows
|
|
98
|
+
|
|
99
|
+
- `src/skf-create-skill/references/validate.md` — wraps `skill-check check --fix` (§2) and `split-body` (§4). Runs the optional post-restore re-validation.
|
|
100
|
+
- `src/skf-update-skill/references/write.md` — wraps `skill-check check --fix` and `skill-check split-body --write` in §7. Does not run post-restore re-validation today; the post-write checks in §1 catch downstream issues.
|
|
@@ -42,4 +42,4 @@ There is no generic helper that writes the schema above; each skill assembles th
|
|
|
42
42
|
|
|
43
43
|
A generalised emitter (matching this document's schema) is a reasonable future helper when a second consumer materialises with the same shape. For now, skills that write this contract assemble the JSON in their terminal step — the work is small (5–8 fields) and skill-specific summary content benefits from being expressed inline alongside the rest of the step's logic.
|
|
44
44
|
|
|
45
|
-
skf-quick-skill writes both the success-variant contract (`
|
|
45
|
+
skf-quick-skill writes both the success-variant contract (`finalize.md` §3) and the error-variant contract on every HARD HALT (per `SKILL.md` § "Result Contract on HARD HALT") in this hand-assembled style.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/armelhbobdad/bmad-module-skill-forge/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json",
|
|
4
4
|
"title": "SKF_BRIEF_RESULT_JSON envelope (v1)",
|
|
5
|
-
"description": "Single-line JSON document emitted by skf-brief-skill step
|
|
5
|
+
"description": "Single-line JSON document emitted by skf-brief-skill step 5 §4b when {headless_mode} is true, prefixed with the literal 'SKF_BRIEF_RESULT_JSON: '. Pipelines grep one line out of the workflow log to branch on the brief outcome without parsing prose. Schema mirrors the contract in src/skf-brief-skill/SKILL.md Result Contract section.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": ["status", "brief_path", "skill_name", "version", "language", "scope_type", "exit_code", "halt_reason"],
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"status": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"enum": ["success", "error"],
|
|
13
|
-
"description": "'success' on the terminal happy path (after step
|
|
13
|
+
"description": "'success' on the terminal happy path (after step 5 wrote the brief and step 6 returned). 'error' on any HARD HALT."
|
|
14
14
|
},
|
|
15
15
|
"brief_path": {
|
|
16
16
|
"type": ["string", "null"],
|
|
@@ -19,20 +19,20 @@
|
|
|
19
19
|
"skill_name": {
|
|
20
20
|
"type": "string",
|
|
21
21
|
"minLength": 1,
|
|
22
|
-
"description": "Brief's skill_name field — present in every envelope (success and error) since it is captured at step
|
|
22
|
+
"description": "Brief's skill_name field — present in every envelope (success and error) since it is captured at step 1 §6 before any of the other failure branches."
|
|
23
23
|
},
|
|
24
24
|
"version": {
|
|
25
25
|
"type": ["string", "null"],
|
|
26
|
-
"description": "Resolved brief version (target_version if set, else auto-detected, else '1.0.0'). Null when the run errored before step
|
|
26
|
+
"description": "Resolved brief version (target_version if set, else auto-detected, else '1.0.0'). Null when the run errored before step 5's version-resolution ran."
|
|
27
27
|
},
|
|
28
28
|
"language": {
|
|
29
29
|
"type": ["string", "null"],
|
|
30
|
-
"description": "Detected or user-confirmed primary language. Null when the run errored before step
|
|
30
|
+
"description": "Detected or user-confirmed primary language. Null when the run errored before step 2's language-detection ran."
|
|
31
31
|
},
|
|
32
32
|
"scope_type": {
|
|
33
33
|
"type": ["string", "null"],
|
|
34
34
|
"enum": ["full-library", "specific-modules", "public-api", "component-library", "reference-app", "docs-only", null],
|
|
35
|
-
"description": "Confirmed scope.type from step
|
|
35
|
+
"description": "Confirmed scope.type from step 3. Null when the run errored before scope was confirmed."
|
|
36
36
|
},
|
|
37
37
|
"exit_code": {
|
|
38
38
|
"type": "integer",
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
3
|
"$id": "https://github.com/armelhbobdad/bmad-module-skill-forge/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json",
|
|
4
4
|
"title": "SKF_SETUP_RESULT_JSON envelope (v1)",
|
|
5
|
-
"description": "Single-line JSON document emitted by skf-setup step
|
|
5
|
+
"description": "Single-line JSON document emitted by skf-setup step 4 §4 when {headless_mode} is true, prefixed with the literal 'SKF_SETUP_RESULT_JSON: '. Pipelines grep one line out of the workflow log without parsing ASCII-art and without racing the forge-tier.yaml writer. Schema added in PR #247, extended in PR #248 (header / outputs / failure modes), extended again in this PR with previous_tier / tier_changed / tools_added / tools_removed / error.",
|
|
6
6
|
"type": "object",
|
|
7
7
|
"additionalProperties": false,
|
|
8
8
|
"required": ["skf_setup"],
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
"type": "object",
|
|
12
12
|
"additionalProperties": false,
|
|
13
13
|
"required": [
|
|
14
|
+
"status",
|
|
14
15
|
"tier",
|
|
15
16
|
"previous_tier",
|
|
16
17
|
"tier_changed",
|
|
@@ -27,6 +28,11 @@
|
|
|
27
28
|
"error"
|
|
28
29
|
],
|
|
29
30
|
"properties": {
|
|
31
|
+
"status": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"enum": ["success", "tier_failure", "write_failure", "blocked"],
|
|
34
|
+
"description": "Single-field outcome for pipeline branching. 'success' when no error and tier requirement (if any) is satisfied. 'tier_failure' when require_tier was set and is not satisfied. 'write_failure' when forge-tier.yaml or preferences.yaml could not be written. 'blocked' for any other halt that still produced an envelope (e.g. foreign ccc binary rejected pre-index)."
|
|
35
|
+
},
|
|
30
36
|
"tier": {
|
|
31
37
|
"type": "string",
|
|
32
38
|
"enum": ["Quick", "Forge", "Forge+", "Deep"],
|
|
@@ -76,7 +82,7 @@
|
|
|
76
82
|
"properties": {
|
|
77
83
|
"status": {
|
|
78
84
|
"type": "string",
|
|
79
|
-
"enum": ["fresh", "created", "failed", "none"]
|
|
85
|
+
"enum": ["fresh", "created", "failed", "none", "skipped"]
|
|
80
86
|
},
|
|
81
87
|
"indexed_path": { "type": ["string", "null"] },
|
|
82
88
|
"file_count": { "type": ["integer", "null"], "minimum": 0 }
|
|
@@ -119,7 +125,7 @@
|
|
|
119
125
|
"phase": {
|
|
120
126
|
"type": "string",
|
|
121
127
|
"minLength": 1,
|
|
122
|
-
"description": "Step or operation that failed (e.g. '
|
|
128
|
+
"description": "Step or operation that failed (e.g. 'write-config:forge-tier.yaml')."
|
|
123
129
|
},
|
|
124
130
|
"path": { "type": "string", "minLength": 1, "description": "Absolute path of the file the failed operation targeted." },
|
|
125
131
|
"reason": { "type": "string", "minLength": 1, "description": "Human-readable error message." }
|