bmad-module-skill-forge 1.4.1 → 1.5.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.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 +147 -16
- 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-manifest-ops.py +22 -6
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +34 -4
- 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} +48 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +32 -9
- 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} +16 -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/{steps-c/step-01-init.md → references/init.md} +63 -19
- 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} +35 -17
- package/src/skf-brief-skill/SKILL.md +49 -19
- 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} +27 -15
- 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} +35 -29
- 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 +2 -2
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +27 -20
- 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} +29 -16
- 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 +10 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +11 -11
- 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} +48 -28
- 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} +37 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +32 -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} +44 -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} +11 -11
- 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} +11 -49
- 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 +79 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +23 -11
- 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} +109 -113
- 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} +16 -31
- 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} +37 -73
- 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} +13 -9
- 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 +170 -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} +18 -14
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +27 -42
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +13 -9
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +14 -10
- package/tools/validate-docs-drift.js +1 -1
- 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
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
2
|
outputFile: '{forge_version}/drift-report-{timestamp}.md'
|
|
3
|
-
nextStepFile: '
|
|
3
|
+
nextStepFile: 'health-check.md'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
<!-- Config: communicate in {communication_language}. Drift report prose in {document_output_language}. -->
|
|
7
|
+
|
|
6
8
|
# Step 6: Generate Report
|
|
7
9
|
|
|
8
10
|
## STEP GOAL:
|
|
@@ -18,8 +20,6 @@ Finalize the drift report by completing the Audit Summary with calculated metric
|
|
|
18
20
|
|
|
19
21
|
## MANDATORY SEQUENCE
|
|
20
22
|
|
|
21
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
22
|
-
|
|
23
23
|
### 1. Complete Audit Summary
|
|
24
24
|
|
|
25
25
|
Update the ## Audit Summary section at the top of {outputFile} with final calculated values:
|
|
@@ -77,10 +77,10 @@ Append to {outputFile}:
|
|
|
77
77
|
{IF any CRITICAL or HIGH findings:}
|
|
78
78
|
**Recommended:** Run `[US] Update Skill` workflow to apply priority remediations automatically.
|
|
79
79
|
|
|
80
|
-
{IF `audit_ref != baseline_ref` (source version bump detected in step
|
|
81
|
-
**Version preservation (non-destructive).** `update-skill` preserves the prior version at `{skill_group}/{baseline_version}/` unchanged and writes the new skill to `{skill_group}/{audit_version}/` (see `skf-update-skill/
|
|
80
|
+
{IF `audit_ref != baseline_ref` (source version bump detected in step 1 §5b):}
|
|
81
|
+
**Version preservation (non-destructive).** `update-skill` preserves the prior version at `{skill_group}/{baseline_version}/` unchanged and writes the new skill to `{skill_group}/{audit_version}/` (see `skf-update-skill/references/merge.md` §6b, which creates the new version directory and leaves the previous one on disk). The `active` symlink at `{skill_group}/active` repoints to the new version (see `skf-update-skill/references/write.md` §5b). On the next export, the prior version's export-manifest entry transitions to `status: archived` — files retained for rollback (see `skf-export-skill/references/update-context.md`). Do **not** recommend `skf-drop-skill` + `skf-create-skill` for a version bump — that destroys the prior version's artifacts.
|
|
82
82
|
|
|
83
|
-
**Surface new entry points for the brief gate.** If the audit observed new top-level modules, renamed package trees, or new public entry points (new `__init__.py`, `index.ts`, `lib.rs`, or equivalent) that were not in the brief's original scope, call them out here. `update-skill` step
|
|
83
|
+
**Surface new entry points for the brief gate.** If the audit observed new top-level modules, renamed package trees, or new public entry points (new `__init__.py`, `index.ts`, `lib.rs`, or equivalent) that were not in the brief's original scope, call them out here. `update-skill` step 2 §1b detects new candidate files via heuristic and prompts `[P]romote` / `[S]kip` / `[U]pdate-brief`; surfacing them in advance makes that gate faster to resolve, or lets the user refine scope via `skf-brief-skill` before running update-skill.
|
|
84
84
|
|
|
85
85
|
{IF only MEDIUM or LOW findings:}
|
|
86
86
|
**Optional:** Minor drift detected. Manual updates sufficient, or run `[US] Update Skill` for automated remediation.
|
|
@@ -120,7 +120,7 @@ Append to {outputFile}:
|
|
|
120
120
|
### 4. Update Report Frontmatter
|
|
121
121
|
|
|
122
122
|
Update {outputFile} frontmatter:
|
|
123
|
-
- Append `'
|
|
123
|
+
- Append `'report'` to `stepsCompleted`
|
|
124
124
|
- Set `drift_score` to final calculated score
|
|
125
125
|
- Set `nextWorkflow` to `'update-skill'` if CRITICAL or HIGH findings, otherwise leave empty
|
|
126
126
|
|
|
@@ -170,6 +170,24 @@ Update {outputFile} frontmatter:
|
|
|
170
170
|
|
|
171
171
|
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{forge_version}/audit-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/audit-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the drift report path in `outputs`; include `drift_count` and `severity` (CLEAN/MINOR/SIGNIFICANT/CRITICAL) in `summary`.
|
|
172
172
|
|
|
173
|
+
**Stdout envelope (headless only).** When `{headless_mode}` is true, emit a single-line JSON envelope to **stdout** immediately after the on-disk result contract is written, so chaining workflows can consume `drift_score`, `report_path`, and `next_workflow` from a captured stdout line without polling the filesystem. The shape matches the "Result Contract (Headless)" section in SKILL.md verbatim:
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
SKF_AUDIT_RESULT_JSON: {"status":"success","skill_name":"{skill_name}","drift_score":"{CLEAN|MINOR|SIGNIFICANT|CRITICAL}","report_path":"{outputFile}","next_workflow":"{update-skill|null}","audit_ref":"{audit_ref}","exit_code":0,"halt_reason":null}
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Field rules: `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist (matches the frontmatter `nextWorkflow` set in §4), otherwise `null`. `audit_ref` carries the resolved value from step 1 §5b (`baseline_ref` when no upstream drift was detected, `latest_tag` or `remote_head` when the operator chose `[C] Checkout-and-audit-against-latest`).
|
|
180
|
+
|
|
181
|
+
**HALT envelope mirror (headless only).** For every HARD HALT raised in this workflow (skill-not-found at init.md §1, forge-tier missing at §2, source-dir missing at §5, write-failed at §6, user-cancelled at any `[X]` selection), emit the same envelope shape on **stderr** with `status: "error"`, `drift_score: null` (or last known value if classification ran), `report_path: null` if the report write failed, `exit_code` matching the Exit Codes table, and `halt_reason` set to the failure class from the table (`"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`). This is the only signal a wrapping pipeline receives on failure — log it before exiting.
|
|
182
|
+
|
|
183
|
+
**Post-audit hook (optional).** If `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it as:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
{onCompleteCommand} --result-path={result_json_path}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
where `{result_json_path}` is the per-run record path written above (`{forge_version}/audit-skill-result-{YYYYMMDD-HHmmss}.json`). Log success/failure to `workflow_warnings[]` — never fail the workflow on a hook error. The hook runs after the result contract is finalized so notifiers, ticket-tracker integrations, or downstream pipelines see a complete record. When `{onCompleteCommand}` is empty (bundled default), skip the invocation entirely.
|
|
190
|
+
|
|
173
191
|
### 6. Chain to Health Check
|
|
174
192
|
|
|
175
193
|
ONLY WHEN the report has been written, presented, and the result contract saved will you 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 user-facing summary reads as final.
|
package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md}
RENAMED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'severity-classify.md'
|
|
3
3
|
outputFile: '{forge_version}/drift-report-{timestamp}.md'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
7
|
+
|
|
6
8
|
# Step 4: Semantic Diff
|
|
7
9
|
|
|
8
10
|
## STEP GOAL:
|
|
@@ -18,8 +20,6 @@ Compare QMD knowledge context between the original skill creation and current st
|
|
|
18
20
|
|
|
19
21
|
## MANDATORY SEQUENCE
|
|
20
22
|
|
|
21
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
22
|
-
|
|
23
23
|
### 1. Check Forge Tier
|
|
24
24
|
|
|
25
25
|
**IF forge tier is Quick, Forge, or Forge+:**
|
|
@@ -34,7 +34,7 @@ Append to {outputFile}:
|
|
|
34
34
|
Semantic analysis compares QMD knowledge context for meaning-level changes that structural diff cannot detect. To enable semantic diff, run setup with QMD available to unlock Deep tier.
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
Update frontmatter: append `'
|
|
37
|
+
Update frontmatter: append `'semantic-diff'` to `stepsCompleted`
|
|
38
38
|
|
|
39
39
|
"**Semantic diff skipped (requires Deep tier). Proceeding to severity classification...**"
|
|
40
40
|
|
|
@@ -55,7 +55,7 @@ Launch a subprocess (Pattern 3 — data operations) that:
|
|
|
55
55
|
- Fall through to the **direct-content fallback** below instead of skipping outright.
|
|
56
56
|
- **Registry entry present and populated.** Use the `name` field from the registry entry as the collection to query. Proceed to bullet 2.
|
|
57
57
|
|
|
58
|
-
**Direct-content fallback** (used when the collection is registered but empty): load `SKILL.md` and `references/*.md` from the audited skill, then spot-check each documented export against the current source tree under `{source_root}` using the Deep-tier AST tooling this step already requires (ast_bridge; see step
|
|
58
|
+
**Direct-content fallback** (used when the collection is registered but empty): load `SKILL.md` and `references/*.md` from the audited skill, then spot-check each documented export against the current source tree under `{source_root}` using the Deep-tier AST tooling this step already requires (ast_bridge; see step 2 §1 "Deep tier"). This fallback is reachable only from Deep tier — §1 short-circuits Quick/Forge/Forge+ before §2 runs, so AST tooling is guaranteed available here. Record findings with confidence label `T1-low-fallback` rather than T2 — this is direct content inspection, not QMD-backed semantic analysis. The step's output schema is otherwise unchanged; set `qmd_collection = null` in the Semantic Drift header and annotate: "Semantic diff ran in direct-content fallback mode — QMD collection was registered but empty."
|
|
59
59
|
|
|
60
60
|
2. Queries for knowledge context around each export documented in the skill
|
|
61
61
|
3. Retrieves: usage patterns, conventions, architectural context, dependency relationships
|
|
@@ -128,7 +128,7 @@ Append to {outputFile}:
|
|
|
128
128
|
### 5. Update Report and Auto-Proceed
|
|
129
129
|
|
|
130
130
|
Update {outputFile} frontmatter:
|
|
131
|
-
- Append `'
|
|
131
|
+
- Append `'semantic-diff'` to `stepsCompleted`
|
|
132
132
|
|
|
133
133
|
### 6. Present MENU OPTIONS
|
|
134
134
|
|
package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md}
RENAMED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'report.md'
|
|
3
3
|
outputFile: '{forge_version}/drift-report-{timestamp}.md'
|
|
4
4
|
severityRulesFile: 'references/severity-rules.md'
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
8
|
+
|
|
7
9
|
# Step 5: Severity Classification
|
|
8
10
|
|
|
9
11
|
## STEP GOAL:
|
|
@@ -18,8 +20,6 @@ Grade every drift finding from Steps 03 and 04 by severity level (CRITICAL/HIGH/
|
|
|
18
20
|
|
|
19
21
|
## MANDATORY SEQUENCE
|
|
20
22
|
|
|
21
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
22
|
-
|
|
23
23
|
### 1. Load Severity Rules
|
|
24
24
|
|
|
25
25
|
Launch a subprocess (Pattern 3 — data operations) that:
|
|
@@ -85,7 +85,7 @@ Apply scoring rules from {severityRulesFile}:
|
|
|
85
85
|
|
|
86
86
|
### 5. Compile Severity Classification Section
|
|
87
87
|
|
|
88
|
-
**Rollup inherits from step
|
|
88
|
+
**Rollup inherits from step 3.** If step 3 §5 collapsed ≥ 10 same-kind findings into a single rollup row (deleted source file, renamed module, entire package tree removed), carry that rollup through to the matching severity table as one row — do not re-expand it here. Keep the existing 6-column severity table shape; the rollup encodes root cause, count, and representative symbols **inline in the `Finding` cell** rather than adding new columns, so rollup and per-item rows render cleanly in one table. Changed-signature and cross-file findings remain per-row; they were not eligible for rollup in step 3 and are not eligible here.
|
|
89
89
|
|
|
90
90
|
**Rollup row form (any severity table):**
|
|
91
91
|
|
|
@@ -138,7 +138,7 @@ Append to {outputFile}:
|
|
|
138
138
|
### 6. Update Report and Auto-Proceed
|
|
139
139
|
|
|
140
140
|
Update {outputFile} frontmatter:
|
|
141
|
-
- Append `'
|
|
141
|
+
- Append `'severity-classify'` to `stepsCompleted`
|
|
142
142
|
- Set `drift_score` to calculated overall score
|
|
143
143
|
|
|
144
144
|
### 7. Present MENU OPTIONS
|
package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md}
RENAMED
|
@@ -1,8 +1,16 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'semantic-diff.md'
|
|
3
3
|
outputFile: '{forge_version}/drift-report-{timestamp}.md'
|
|
4
|
+
loadProvenanceProbeOrder:
|
|
5
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-load-provenance.py'
|
|
6
|
+
- '{project-root}/src/shared/scripts/skf-load-provenance.py'
|
|
7
|
+
compareFileHashesProbeOrder:
|
|
8
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-compare-file-hashes.py'
|
|
9
|
+
- '{project-root}/src/shared/scripts/skf-compare-file-hashes.py'
|
|
4
10
|
---
|
|
5
11
|
|
|
12
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
13
|
+
|
|
6
14
|
# Step 3: Structural Diff
|
|
7
15
|
|
|
8
16
|
## STEP GOAL:
|
|
@@ -17,8 +25,6 @@ Compare the original provenance map extractions from create-skill against the cu
|
|
|
17
25
|
|
|
18
26
|
## MANDATORY SEQUENCE
|
|
19
27
|
|
|
20
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
21
|
-
|
|
22
28
|
### 1. Prepare Comparison Sets
|
|
23
29
|
|
|
24
30
|
Load both datasets:
|
|
@@ -29,19 +35,19 @@ Load both datasets:
|
|
|
29
35
|
**Current (from Step 02 extraction):**
|
|
30
36
|
- Export list with names, types, signatures, file paths, line numbers
|
|
31
37
|
|
|
32
|
-
**Canonicalize extractor methodology differences before matching.** The extractor used by `skf-create-skill` at baseline time and the re-extractor used by step
|
|
38
|
+
**Canonicalize extractor methodology differences before matching.** The extractor used by `skf-create-skill` at baseline time and the re-extractor used by step 2 can differ in cosmetic detail (quote style, module qualification, re-export resolution). Without normalization, those cosmetic differences surface as false-positive "Changed" and "Removed" entries even when the source commit has not moved. Apply these transforms to both sets symmetrically:
|
|
33
39
|
|
|
34
40
|
- **Quote style on string defaults.** Normalize string-literal defaults in signatures to a single style — e.g., `kind: str = "Hnsw"` ↔ `kind: str = 'Hnsw'`. Pick one canonical form and apply to both sides.
|
|
35
41
|
- **Module qualification of stdlib helpers.** Strip module prefixes on well-known stdlib helpers when the unqualified form is importable at the call site: `dataclasses.field(...)` → `field(...)`, `typing.Optional[...]` → `Optional[...]`, `typing.List[...]` → `List[...]`. Do not collapse user-defined namespaces.
|
|
36
|
-
- **Public-API re-export resolution.** When `{source_root}/**/__init__.py` re-exports an internal symbol under a different public name (`from .internal import _Impl as Public`, or via `__all__`), resolve both sides to the public name before key-matching — otherwise a renamed re-export in the current scan shows up as "Removed `_Impl`" + "Added `Public`" instead of matching the baseline entry.
|
|
42
|
+
- **Public-API re-export resolution.** When `{source_root}/**/__init__.py` re-exports an internal symbol under a different public name (`from .internal import _Impl as Public`, or via `__all__`), resolve both sides to the public name before key-matching — otherwise a renamed re-export in the current scan shows up as "Removed `_Impl`" + "Added `Public`" instead of matching the baseline entry. The re-export map is already in workflow context as `{reexport_map}` (produced by `skf-load-provenance.py normalize` in step 1 §4). Apply it directly without re-walking `__init__.py` files.
|
|
37
43
|
|
|
38
|
-
Record the set of transforms actually applied in workflow context — step
|
|
44
|
+
Record the set of transforms actually applied in workflow context — step 6 surfaces them in the Provenance section so a reviewer can tell which differences the diff collapsed and which were real.
|
|
39
45
|
|
|
40
46
|
Normalize both sets for comparison:
|
|
41
47
|
- Match by canonicalized export name (primary key)
|
|
42
48
|
- Group by file for location-aware comparison
|
|
43
49
|
|
|
44
|
-
> **Longer-term fix.** The principled remedy is to persist `skf-create-skill`'s ast-grep ruleset to `{forge_version}/extraction-rules.yaml` at create time and have step
|
|
50
|
+
> **Longer-term fix.** The principled remedy is to persist `skf-create-skill`'s ast-grep ruleset to `{forge_version}/extraction-rules.yaml` at create time and have step 2 replay that exact ruleset. When the file is present, step 2 extraction becomes reproducible against the baseline and the canonicalization pass above becomes a no-op. Until then, normalization is the salvage remediation for provenance maps that predate extractor pinning.
|
|
45
51
|
|
|
46
52
|
### 2. Detect Added Exports
|
|
47
53
|
|
|
@@ -87,16 +93,28 @@ For each changed export, record:
|
|
|
87
93
|
|
|
88
94
|
**Only execute if provenance-map.json contains `file_entries`.**
|
|
89
95
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
**Resolve `{compareFileHashesHelper}`** from `{compareFileHashesProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
97
|
+
|
|
98
|
+
Run one deterministic comparison subprocess — it walks tracked file_entries[] AND the inverse direction (source-tree → candidate set in standard script/asset/doc directories) so the LLM does not orchestrate per-file hashing:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run {compareFileHashesHelper} compare {provenanceMap} {sourceRoot}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Parse the emitted JSON:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
{
|
|
108
|
+
"added": ["<rel-path>", ...], // present on disk in tracked dirs, NOT in file_entries
|
|
109
|
+
"removed": ["<rel-path>", ...], // in file_entries, missing on disk
|
|
110
|
+
"changed": [{"path": "...", "stored_hash": "sha256:...", "current_hash": "sha256:..."}],
|
|
111
|
+
"stats": {"added": N, "removed": N, "changed": N, "unchanged": N}
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Hash-prefix normalization (writer-vs-reader compatibility — `skf-create-skill` writes `content_hash` with a `"sha256:"` prefix, a bare-hex hash from `hashlib` would otherwise never match) is handled inside the script. Downstream consumers read `added`/`removed`/`changed` directly with no further normalization.
|
|
98
116
|
|
|
99
|
-
Append
|
|
117
|
+
Append the three lists into the Structural Drift section as "### Script/Asset Drift ({stats.added + stats.removed + stats.changed})".
|
|
100
118
|
|
|
101
119
|
### Stack-Specific Structural Diff
|
|
102
120
|
|
|
@@ -164,7 +182,7 @@ Append to {outputFile}:
|
|
|
164
182
|
### 6. Update Report and Auto-Proceed
|
|
165
183
|
|
|
166
184
|
Update {outputFile} frontmatter:
|
|
167
|
-
- Append `'
|
|
185
|
+
- Append `'structural-diff'` to `stepsCompleted`
|
|
168
186
|
|
|
169
187
|
### 7. Present MENU OPTIONS
|
|
170
188
|
|
|
@@ -13,6 +13,14 @@ A good skill brief sets a tight, cohesive boundary: one capability with 3-8 prim
|
|
|
13
13
|
|
|
14
14
|
Brief-skill is split from create-skill so the scoping conversation runs *once*, on cheap signals (manifests, top-level exports, intent), without paying for AST extraction. Compilation is expensive; scoping decisions are cheap to revise. Keeping them in separate workflows lets a user iterate on the brief, share it for review, and re-run create-skill against the same brief whenever the upstream version moves.
|
|
15
15
|
|
|
16
|
+
## Conventions
|
|
17
|
+
|
|
18
|
+
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
19
|
+
- `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
|
|
20
|
+
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
21
|
+
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
22
|
+
- `{skill-name}` resolves to the skill directory's basename.
|
|
23
|
+
|
|
16
24
|
## Role
|
|
17
25
|
|
|
18
26
|
You are a skill scoping architect collaborating with a developer who wants to create an agent skill. You bring expertise in source code analysis, API surface identification, and skill boundary design, while the user brings their domain knowledge and specific use case. Work together as equals.
|
|
@@ -21,11 +29,9 @@ You are a skill scoping architect collaborating with a developer who wants to cr
|
|
|
21
29
|
|
|
22
30
|
These rules apply to every step in this workflow:
|
|
23
31
|
|
|
24
|
-
- Read each step file completely before taking any action
|
|
25
|
-
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
26
32
|
- Only load one step file at a time — never preload future steps
|
|
27
|
-
- **Lazy-load references and assets:** `references/*.md` and `assets/*.md` files are loaded inside the section that needs them, not at step entry. If a section is skipped (e.g. `version-resolution.md` when `{
|
|
28
|
-
- Always communicate in `{communication_language}` (the language for user-facing prose). Written artifact text — the `description`, `notes`, and other free-form fields persisted into `skill-brief.yaml` — is in `{document_output_language}`; per-step rules call this out where it applies (see step
|
|
33
|
+
- **Lazy-load references and assets:** `references/*.md` and `assets/*.md` files are loaded inside the section that needs them, not at step entry. If a section is skipped (e.g. `version-resolution.md` when `{extractPublicApiHelper}` already returned a version, `scope-templates.md` for the `docs-only` branch that bypasses §2c), do not load that file. Each unnecessary load costs context (~5-10 KB per reference) and biases the LLM toward consulting material the current path does not need.
|
|
34
|
+
- Always communicate in `{communication_language}` (the language for user-facing prose). Written artifact text — the `description`, `notes`, and other free-form fields persisted into `skill-brief.yaml` — is in `{document_output_language}`; per-step rules call this out where it applies (see step 5). The two values may be the same.
|
|
29
35
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
30
36
|
|
|
31
37
|
## On Activation
|
|
@@ -35,27 +41,51 @@ These rules apply to every step in this workflow:
|
|
|
35
41
|
|
|
36
42
|
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
|
|
37
43
|
|
|
38
|
-
3.
|
|
44
|
+
3. **Resolve workflow customization.** Run:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
|
48
|
+
--skill {skill-root} --key workflow
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
|
|
52
|
+
|
|
53
|
+
- `{skill-root}/customize.toml` — bundled defaults
|
|
54
|
+
- `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
|
|
55
|
+
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
56
|
+
|
|
57
|
+
If the script fails or is missing, fall back to reading `{skill-root}/customize.toml` directly — the bundled defaults are an empty string for each path scalar.
|
|
58
|
+
|
|
59
|
+
Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the three scalars, if the merged value is empty or absent, use the bundled default:
|
|
60
|
+
|
|
61
|
+
- `{descriptionVoiceExamplesPath}` ← `workflow.description_voice_examples_path` if non-empty, else `assets/description-voice-examples.md`
|
|
62
|
+
- `{scopeTemplatesPath}` ← `workflow.scope_templates_path` if non-empty, else `assets/scope-templates.md`
|
|
63
|
+
- `{briefSchemaPath}` ← `workflow.brief_schema_path` if non-empty, else `assets/skill-brief-schema.md`
|
|
64
|
+
|
|
65
|
+
Stash all three as workflow-context variables. Stage files reference `{descriptionVoiceExamplesPath}` / `{scopeTemplatesPath}` / `{briefSchemaPath}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies without forking the skill.
|
|
66
|
+
|
|
67
|
+
4. Load, read the full file, and execute `references/gather-intent.md`.
|
|
39
68
|
|
|
40
69
|
## Stages
|
|
41
70
|
|
|
42
71
|
| # | Step | File | Auto-proceed |
|
|
43
72
|
|---|------|------|--------------|
|
|
44
|
-
| 1 | Gather Intent |
|
|
45
|
-
| 2 | Analyze Target |
|
|
46
|
-
| 3 | Scope Definition |
|
|
47
|
-
| 4 | Confirm Brief |
|
|
48
|
-
| 5 | Write Brief |
|
|
49
|
-
| 6 | Workflow Health Check (terminal) |
|
|
73
|
+
| 1 | Gather Intent | references/gather-intent.md | No (interactive) |
|
|
74
|
+
| 2 | Analyze Target | references/analyze-target.md | Yes |
|
|
75
|
+
| 3 | Scope Definition | references/scope-definition.md | No (interactive) |
|
|
76
|
+
| 4 | Confirm Brief | references/confirm-brief.md | No (confirm) |
|
|
77
|
+
| 5 | Write Brief | references/write-brief.md | Yes |
|
|
78
|
+
| 6 | Workflow Health Check (terminal) | references/health-check.md | Yes |
|
|
50
79
|
|
|
51
80
|
## Invocation Contract
|
|
52
81
|
|
|
53
82
|
| Aspect | Detail |
|
|
54
83
|
|--------|--------|
|
|
55
84
|
| **Inputs** | `target_repo` [required], `skill_name` [required], `scope_hint` [optional], `language_hint` [optional], `target_version` [optional], `source_authority` [optional: official/community/internal, default community], `source_type` [optional: source/docs-only, default source], `doc_urls` [optional: list of `url[,label]` for source_type=docs-only or supplemental], `scope_type` [optional: full-library/specific-modules/public-api/component-library/reference-app/docs-only], `include` [optional: comma-separated globs], `exclude` [optional: comma-separated globs], `scripts_intent` [optional: detect/none/free-text, default detect], `assets_intent` [optional: detect/none/free-text, default detect], `intent` [optional: free-text used to derive description], `force` [optional: overwrite existing brief without prompting] |
|
|
56
|
-
| **Gates** | step
|
|
85
|
+
| **Gates** | step 1: Input Gate [use args] | step 3: Confirm Gate [C] | step 4: Confirm Gate [C] |
|
|
57
86
|
| **Outputs** | `skill-brief.yaml` at `{forge_data_folder}/{skill-name}/skill-brief.yaml`; final `SKF_BRIEF_RESULT_JSON` line on stdout when `{headless_mode}` is true |
|
|
58
87
|
| **Headless** | All gates auto-resolve with heuristic-driven or default action when `{headless_mode}` is true; pre-supplied inputs consumed at the gates that would otherwise prompt; absent `source_authority` and `scope_type` are resolved by signal-driven detection (see `references/headless-args.md`); existing briefs are preserved unless `--force` was supplied (HALT with `overwrite-cancelled` otherwise) |
|
|
88
|
+
| **Transient-failure retry** | This workflow does **not** auto-retry network or subprocess failures. A failed `gh` fetch (analyze-target.md §1, portfolio-similarity-check.md), QMD probe, or extraction script is logged and surfaced in the final result envelope as a warning, but the workflow continues with whatever signal it has. Headless pipelines that want retry semantics should wrap the invocation at their orchestrator level (e.g. CI re-runner on non-zero exit). Rationale: brief-skill is read-mostly with one terminal write (the YAML at step 5); a partial-signal retry has more failure modes than just re-running the whole workflow, which is cheap. |
|
|
59
89
|
| **Exit codes** | See "Exit Codes" below |
|
|
60
90
|
|
|
61
91
|
## Exit Codes
|
|
@@ -64,16 +94,16 @@ Every HARD HALT in this workflow exits with a stable code so headless automators
|
|
|
64
94
|
|
|
65
95
|
| Code | Meaning | Raised by |
|
|
66
96
|
| ---- | -------------------- | ------------------------------------------------------------------------------------------ |
|
|
67
|
-
| 0 | success | step
|
|
68
|
-
| 2 | input-missing / input-invalid | step
|
|
69
|
-
| 3 | resolution-failure | step
|
|
70
|
-
| 4 | write-failure | step
|
|
71
|
-
| 5 | overwrite-cancelled | step
|
|
72
|
-
| 6 | user-cancelled | any interactive menu in step
|
|
97
|
+
| 0 | success | step 6 (terminal) |
|
|
98
|
+
| 2 | input-missing / input-invalid | step 1 GATE — required headless arg absent (`target_repo`, `skill_name`, or `doc_urls` when `source_type=docs-only`) → `input-missing`; enum violation, malformed semver, non-kebab `skill_name`, or step 5 brief-context schema validation failure → `input-invalid` |
|
|
99
|
+
| 3 | resolution-failure | step 1 §1 (`forge-tier.yaml` missing); step 2 §1 (target inaccessible / `gh auth` fails) |
|
|
100
|
+
| 4 | write-failure | step 1 §1 pre-flight write probe (data folder unwritable: read-only mount, disk full, permissions denied); step 5 §4 (write to `{forge_data_folder}/{skill-name}/skill-brief.yaml` failed) |
|
|
101
|
+
| 5 | overwrite-cancelled | step 5 §2 (existing brief, `force` not supplied) |
|
|
102
|
+
| 6 | user-cancelled | any interactive menu in step 1/03/04 (user selected `[X]` Cancel and exit) |
|
|
73
103
|
|
|
74
104
|
## Result Contract (Headless)
|
|
75
105
|
|
|
76
|
-
When `{headless_mode}` is true, step
|
|
106
|
+
When `{headless_mode}` is true, step 5 emits a single-line JSON envelope on **stdout** before chaining to step 6, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
|
|
77
107
|
|
|
78
108
|
```
|
|
79
109
|
SKF_BRIEF_RESULT_JSON: {"status":"success|error","brief_path":"…|null","skill_name":"…","version":"…|null","language":"…|null","scope_type":"…|null","exit_code":0,"halt_reason":null}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Description Voice Examples
|
|
2
2
|
|
|
3
|
-
Loaded by step
|
|
3
|
+
Loaded by step 1 §7b only. The five examples below show the *range* of acceptable voices for the `description` field — they vary in lead, structure, and trigger phrasing on purpose. The point is to anchor the LLM to "two facts must come through (what the skill is, when to use it); everything else is voice — do not template-stamp."
|
|
4
4
|
|
|
5
5
|
## Examples
|
|
6
6
|
|
|
@@ -46,7 +46,7 @@ If the source is a remote GitHub repo, use `gh api repos/{owner}/{repo}/contents
|
|
|
46
46
|
|
|
47
47
|
If detection succeeds, use the detected version. If it fails or returns a non-semver value, fall back to `"1.0.0"`.
|
|
48
48
|
|
|
49
|
-
The create-skill workflow (
|
|
49
|
+
The create-skill workflow (extract) also performs version reconciliation at extraction time — if the source version has changed since the brief was created, the extraction step warns and uses the source version.
|
|
50
50
|
|
|
51
51
|
**Target version override:** When `target_version` is present in the brief, it takes precedence over auto-detection. Auto-detection still runs for informational purposes (displayed as "Detected version" alongside the user-specified "Target version"), but the `target_version` value is used as the brief's `version` field. This is particularly useful for docs-only skills (where no package manifest exists) and when the user wants to compile a skill for a specific older version.
|
|
52
52
|
|
|
@@ -67,6 +67,14 @@ scope:
|
|
|
67
67
|
# - "code/core/src/manager-api/**"
|
|
68
68
|
# - "code/core/src/preview-api/**"
|
|
69
69
|
notes: "Optional notes about scope decisions"
|
|
70
|
+
# Optional: authoring-time scope-type rationale (written once by brief-skill 2c)
|
|
71
|
+
# rationale:
|
|
72
|
+
# recommended: full-library
|
|
73
|
+
# chosen: public-api
|
|
74
|
+
# accepted_recommendation: false
|
|
75
|
+
# heuristic: narrow-public-api
|
|
76
|
+
# reason: "user overrode full-library->public-api: only documented API ships"
|
|
77
|
+
# recorded: "2026-05-18"
|
|
70
78
|
# Optional: amendment log for scope decisions made during create-skill §2a,
|
|
71
79
|
# update-skill §1b (auth-doc), and update-skill §1c (scope-expansion).
|
|
72
80
|
# amendments:
|
|
@@ -94,6 +102,28 @@ scope:
|
|
|
94
102
|
# - "**/*.stories.*"
|
|
95
103
|
```
|
|
96
104
|
|
|
105
|
+
### Scope Rationale (Optional)
|
|
106
|
+
|
|
107
|
+
`scope.rationale` is a single optional object recording **why the scope type was chosen at authoring time**. Unlike `scope.amendments[]` (an additive log that accumulates post-authoring decisions across workflow runs), `scope.rationale` is one decision, written once by `skf-brief-skill` step 03 §2c and revised in place on a step-4 `[R]` re-entry. It sits structurally beside `scope.amendments`, reusing the same structured / script-readable / human-auditable ethos rather than a prose decision log.
|
|
108
|
+
|
|
109
|
+
**Fields:**
|
|
110
|
+
|
|
111
|
+
| Field | Type | Required | Source |
|
|
112
|
+
|---|---|---|---|
|
|
113
|
+
| `recommended` | string (one of the six `scope.type` values) | yes | `skf-recommend-scope-type.py` → `scope_type` |
|
|
114
|
+
| `chosen` | string (one of the six) | yes | final `scope.type` |
|
|
115
|
+
| `accepted_recommendation` | bool | yes | `chosen == recommended` |
|
|
116
|
+
| `heuristic` | string | yes | script `matched_heuristic` |
|
|
117
|
+
| `reason` | string | yes | accepted → script `rationale` verbatim; overridden → user's stated reason, or `"user overrode {recommended}->{chosen}; reason not stated"` |
|
|
118
|
+
| `recorded` | string (ISO date `YYYY-MM-DD`) | yes | current date — mirrors `amendments[].date` |
|
|
119
|
+
|
|
120
|
+
**Who reads `scope.rationale`:**
|
|
121
|
+
|
|
122
|
+
- Humans reviewing the brief — it records why the boundary was drawn the way it was.
|
|
123
|
+
- `skf-update-skill` Update intent MAY later surface conflicts against it (e.g., a scope change that contradicts the original authoring decision). **Not implemented now — deferred.** The field is forward-compatible; the reader is wired later.
|
|
124
|
+
|
|
125
|
+
**Backward compatibility:** `scope.rationale` is optional. Briefs without this field validate unchanged — treat missing as absent (null). Mirrors the `scope.amendments` backward-compat rule.
|
|
126
|
+
|
|
97
127
|
### Scope Amendments (Optional)
|
|
98
128
|
|
|
99
129
|
`scope.amendments[]` is an additive, optional audit log of scope decisions made by workflows after the brief was first authored. Two writer paths exist today:
|
|
@@ -171,7 +201,7 @@ scope:
|
|
|
171
201
|
|
|
172
202
|
## Human-Readable Presentation Format
|
|
173
203
|
|
|
174
|
-
The runtime template lives in `
|
|
204
|
+
The runtime template lives in `references/confirm-brief.md` §2 — that is the single source of truth for how the brief is rendered for user confirmation (brief-skill step 4 only; analyze-source batch generation does not render). If the rendering format needs to change, edit the step file. This asset documents the data contract; the step owns the presentation.
|
|
175
205
|
|
|
176
206
|
## Validation Rules
|
|
177
207
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-brief-skill.
|
|
4
|
+
|
|
5
|
+
[workflow]
|
|
6
|
+
|
|
7
|
+
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
|
8
|
+
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
9
|
+
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
10
|
+
|
|
11
|
+
# Steps to run before the standard activation (uv probe, config load).
|
|
12
|
+
# Overrides append. Use for org-wide pre-flight checks (auth, network,
|
|
13
|
+
# compliance) that must precede any brief authoring work.
|
|
14
|
+
|
|
15
|
+
activation_steps_prepend = []
|
|
16
|
+
|
|
17
|
+
# Steps to run after activation but before the first stage executes.
|
|
18
|
+
# Overrides append. Use for context loads or banner customization that
|
|
19
|
+
# should run once activation completes successfully.
|
|
20
|
+
|
|
21
|
+
activation_steps_append = []
|
|
22
|
+
|
|
23
|
+
# Persistent facts the workflow keeps in mind for the whole run
|
|
24
|
+
# (house style, naming conventions, description-voice guardrails).
|
|
25
|
+
# Overrides append.
|
|
26
|
+
#
|
|
27
|
+
# Each entry is either:
|
|
28
|
+
# - a literal sentence, e.g. "Skill briefs must cite an authoritative source."
|
|
29
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
30
|
+
# "file:{project-root}/docs/brief-style.md" (globs supported; file
|
|
31
|
+
# contents are loaded and treated as facts).
|
|
32
|
+
|
|
33
|
+
persistent_facts = [
|
|
34
|
+
"file:{project-root}/**/project-context.md",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
# --- Optional asset overrides ---
|
|
38
|
+
#
|
|
39
|
+
# Lift the canonical asset paths so orgs can substitute house-style copies
|
|
40
|
+
# without forking the skill. Empty string = use the bundled default.
|
|
41
|
+
|
|
42
|
+
description_voice_examples_path = ""
|
|
43
|
+
scope_templates_path = ""
|
|
44
|
+
brief_schema_path = ""
|
package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md}
RENAMED
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'scope-definition.md'
|
|
3
3
|
versionResolutionFile: 'references/version-resolution.md'
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
extractPublicApiProbeOrder:
|
|
5
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-extract-public-api.py'
|
|
6
|
+
- '{project-root}/src/shared/scripts/skf-extract-public-api.py'
|
|
7
|
+
detectWorkspacesProbeOrder:
|
|
8
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-workspaces.py'
|
|
9
|
+
- '{project-root}/src/shared/scripts/skf-detect-workspaces.py'
|
|
10
|
+
detectLanguageProbeOrder:
|
|
11
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
|
|
12
|
+
- '{project-root}/src/shared/scripts/skf-detect-language.py'
|
|
7
13
|
---
|
|
8
14
|
|
|
15
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
16
|
+
|
|
9
17
|
# Step 2: Analyze Target
|
|
10
18
|
|
|
11
19
|
## STEP GOAL:
|
|
@@ -21,8 +29,6 @@ To analyze the target repository by resolving its location, reading its structur
|
|
|
21
29
|
|
|
22
30
|
## MANDATORY SEQUENCE
|
|
23
31
|
|
|
24
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
25
|
-
|
|
26
32
|
### 1. Resolve Target Location
|
|
27
33
|
|
|
28
34
|
**For GitHub URLs:**
|
|
@@ -58,11 +64,13 @@ Display: "**Resolving target...**"
|
|
|
58
64
|
|
|
59
65
|
### 1b. Detect Monorepo / Workspace Layout
|
|
60
66
|
|
|
61
|
-
|
|
67
|
+
**Resolve `{detectWorkspacesHelper}`** from `{detectWorkspacesProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
68
|
+
|
|
69
|
+
Delegate workspace detection to `{detectWorkspacesHelper}` instead of reasoning through manifest rules in prose. Build a payload from the tree fetched in §1 plus the small set of root manifests the detector needs, then invoke the script:
|
|
62
70
|
|
|
63
71
|
```bash
|
|
64
72
|
echo '{"tree": [<flat list of repo-relative file paths>], "manifests": {"package.json": "<raw text>", "Cargo.toml": "<raw text>", "pnpm-workspace.yaml": "<raw text>", "lerna.json": "<raw text>"}}' | \
|
|
65
|
-
uv run {
|
|
73
|
+
uv run {detectWorkspacesHelper}
|
|
66
74
|
```
|
|
67
75
|
|
|
68
76
|
- **`tree`** — pass the flat list of repo-relative file paths already fetched in §1 (for GitHub: the `path` values from the `gh api .../git/trees/HEAD?recursive=1` response; for local: the equivalent listing).
|
|
@@ -79,7 +87,7 @@ This looks like a monorepo ({manifest_kind}) with these workspaces:
|
|
|
79
87
|
1. {workspaces[0].name} ({workspaces[0].path})
|
|
80
88
|
2. {workspaces[1].name} ({workspaces[1].path})
|
|
81
89
|
...
|
|
82
|
-
Which one should the skill cover? Pick a number, type 'all' to scope at the repo root
|
|
90
|
+
Which one should the skill cover? Pick a number, or type 'all' to scope at the repo root.
|
|
83
91
|
```
|
|
84
92
|
|
|
85
93
|
Interactive: wait for the user choice. On a numbered choice, store `monorepo_workspace: {path}` and rebase §2-§4b against that path. On `'all'`, leave `monorepo_workspace` unset and proceed at the repo root with a note in the analysis summary that scope is unfiltered.
|
|
@@ -104,10 +112,12 @@ List the top-level directory structure:
|
|
|
104
112
|
|
|
105
113
|
### 3. Detect Primary Language
|
|
106
114
|
|
|
107
|
-
|
|
115
|
+
**Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
116
|
+
|
|
117
|
+
Delegate the rule walk to `{detectLanguageHelper}` instead of evaluating manifest presence and extension frequency in prose:
|
|
108
118
|
|
|
109
119
|
```bash
|
|
110
|
-
echo '{"tree": [<flat list of repo-relative file paths from §1>]}' | uv run {
|
|
120
|
+
echo '{"tree": [<flat list of repo-relative file paths from §1>]}' | uv run {detectLanguageHelper}
|
|
111
121
|
```
|
|
112
122
|
|
|
113
123
|
The script returns `{language, confidence, detection_source, fallback_to_extension_frequency}` after walking the documented rule table (manifest presence first — package.json with tsconfig.json disambiguation, Cargo.toml, pyproject.toml/setup.py/setup.cfg, go.mod, pom.xml, build.gradle.kts, build.gradle Groovy with Java/Kotlin disambiguation, *.csproj/*.sln, Gemfile — then extension-frequency fallback over recognized source extensions). Use the returned values directly:
|
|
@@ -120,7 +130,9 @@ If `confidence` is `low` (or `unknown` is returned for `language`): flag for use
|
|
|
120
130
|
|
|
121
131
|
### 4. List Top-Level Modules and Exports
|
|
122
132
|
|
|
123
|
-
|
|
133
|
+
**Resolve `{extractPublicApiHelper}`** from `{extractPublicApiProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
134
|
+
|
|
135
|
+
Identify the public API surface. **Delegate the parsing to `{extractPublicApiHelper}` whenever the detected language is supported** — the script is the single source of truth for manifest parsing, export discovery, and version detection across the whole SKF pipeline. Hand-rolling these in prose creates drift seams the LLM cannot fully close.
|
|
124
136
|
|
|
125
137
|
**Script-supported languages** (use the script): `js`, `ts`, `javascript`, `typescript`, `python`, `rust`, `go`, `java`, `kotlin`.
|
|
126
138
|
|
|
@@ -153,7 +165,7 @@ This section runs exactly one of §4.1 (script path) or §4.2 (fallback path) ba
|
|
|
153
165
|
3. Invoke the script and parse its JSON stdout:
|
|
154
166
|
|
|
155
167
|
```bash
|
|
156
|
-
echo '<payload-json>' | uv run {
|
|
168
|
+
echo '<payload-json>' | uv run {extractPublicApiHelper} --mode quick
|
|
157
169
|
```
|
|
158
170
|
|
|
159
171
|
On a non-zero exit (codes 1 or 2 per the script's docstring), capture stderr, log it, and fall through to §4.2 (the prose-fallback path) — never HALT just because the script choked on an unusual manifest.
|
|
@@ -200,7 +212,7 @@ If CCC is unavailable or returns no results: skip this subsection silently.
|
|
|
200
212
|
|
|
201
213
|
### 4b. Detect Source Version
|
|
202
214
|
|
|
203
|
-
**When the language was script-supported (§4 took the script path):** the `version` field returned by `{
|
|
215
|
+
**When the language was script-supported (§4 took the script path):** the `version` field returned by `{extractPublicApiHelper}` IS the detected version — do not re-derive it and do not load `{versionResolutionFile}`. The script already implements the language-specific lookups documented in that reference, so loading the reference here only burns context.
|
|
204
216
|
|
|
205
217
|
**When the language was not script-supported:** load `{versionResolutionFile}` and follow the prose Detection Algorithm directly (Ruby / C# / Swift / etc. fall outside the script's coverage).
|
|
206
218
|
|
|
@@ -268,5 +280,5 @@ Pause briefly for user input. If the user provides corrections or asks questions
|
|
|
268
280
|
|
|
269
281
|
## CRITICAL STEP COMPLETION NOTE
|
|
270
282
|
|
|
271
|
-
ONLY WHEN the analysis is complete and the summary has been presented to the user will you load and read fully
|
|
283
|
+
ONLY WHEN the analysis is complete and the summary has been presented to the user will you load and read fully `scope-definition.md` to begin scope definition.
|
|
272
284
|
|