bmad-module-skill-forge 1.9.0 → 2.0.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/.nvmrc +1 -1
- package/README.md +10 -5
- package/docs/_data/pinned.yaml +2 -2
- package/docs/agents.md +11 -2
- package/docs/architecture.md +5 -4
- package/docs/bmad-synergy.md +30 -7
- package/docs/campaign.md +172 -0
- package/docs/examples.md +7 -3
- package/docs/forge-auto.md +90 -0
- package/docs/getting-started.md +9 -0
- package/docs/how-it-works.md +6 -4
- package/docs/index.md +4 -3
- package/docs/skill-model.md +1 -1
- package/docs/troubleshooting.md +17 -1
- package/docs/verifying-a-skill.md +2 -2
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +64 -24
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +4 -3
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +6 -3
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- package/src/shared/scripts/skf-comention-pairs.py +350 -0
- package/src/shared/scripts/skf-count-tokens.py +222 -0
- package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +240 -4
- package/src/shared/scripts/skf-detect-language.py +82 -3
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- package/src/shared/scripts/skf-find-cycles.py +246 -0
- package/src/shared/scripts/skf-hash-content.py +487 -2
- package/src/shared/scripts/skf-language-corpora.py +100 -0
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
- package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
- package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
- package/src/shared/scripts/skf-shape-detect.py +576 -25
- package/src/shared/scripts/skf-shard-body.py +461 -0
- package/src/shared/scripts/skf-skill-inventory.py +139 -3
- package/src/shared/scripts/skf-structural-diff.py +307 -67
- package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
- package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
- package/src/shared/scripts/skf-validate-output.py +443 -10
- package/src/shared/scripts/skf-validate-pins.py +3 -3
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +2 -0
- package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
- package/src/skf-analyze-source/references/continue.md +8 -13
- package/src/skf-analyze-source/references/generate-briefs.md +28 -12
- package/src/skf-analyze-source/references/headless-contract.md +33 -0
- package/src/skf-analyze-source/references/health-check.md +1 -2
- package/src/skf-analyze-source/references/identify-units.md +25 -36
- package/src/skf-analyze-source/references/init.md +12 -25
- package/src/skf-analyze-source/references/map-and-detect.md +8 -20
- package/src/skf-analyze-source/references/recommend.md +4 -14
- package/src/skf-analyze-source/references/scan-project.md +3 -11
- package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
- package/src/skf-audit-skill/SKILL.md +9 -6
- package/src/skf-audit-skill/customize.toml +2 -0
- package/src/skf-audit-skill/references/init.md +58 -32
- package/src/skf-audit-skill/references/re-index.md +15 -34
- package/src/skf-audit-skill/references/report.md +11 -58
- package/src/skf-audit-skill/references/semantic-diff.md +4 -22
- package/src/skf-audit-skill/references/severity-classify.md +53 -87
- package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
- package/src/skf-audit-skill/references/structural-diff.md +43 -68
- package/src/skf-brief-skill/SKILL.md +7 -36
- package/src/skf-brief-skill/assets/scope-templates.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +13 -18
- package/src/skf-brief-skill/references/confirm-brief.md +2 -15
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +27 -24
- package/src/skf-brief-skill/references/headless-args.md +1 -1
- package/src/skf-brief-skill/references/health-check.md +1 -22
- package/src/skf-brief-skill/references/invocation-contract.md +37 -0
- package/src/skf-brief-skill/references/scope-definition.md +6 -15
- package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
- package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +19 -13
- package/src/skf-campaign/SKILL.md +121 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +75 -0
- package/src/skf-campaign/manifest.yaml +15 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +121 -0
- package/src/skf-campaign/references/step-02-strategy.md +102 -0
- package/src/skf-campaign/references/step-03-pins.md +56 -0
- package/src/skf-campaign/references/step-04-provenance.md +63 -0
- package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
- package/src/skf-campaign/references/step-06-batch.md +88 -0
- package/src/skf-campaign/references/step-07-capstone.md +63 -0
- package/src/skf-campaign/references/step-08-verify.md +75 -0
- package/src/skf-campaign/references/step-09-refine.md +83 -0
- package/src/skf-campaign/references/step-10-export.md +106 -0
- package/src/skf-campaign/references/step-11-maintenance.md +84 -0
- package/src/skf-campaign/references/step-resume.md +115 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +244 -0
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
- package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
- package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
- package/src/skf-campaign/templates/campaign-report-template.md +54 -0
- package/src/skf-campaign/templates/kickoff-template.md +48 -0
- package/src/skf-create-skill/SKILL.md +15 -4
- package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
- package/src/skf-create-skill/assets/skill-sections.md +9 -100
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
- package/src/skf-create-skill/customize.toml +13 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
- package/src/skf-create-skill/references/compile.md +37 -47
- package/src/skf-create-skill/references/component-extraction.md +8 -35
- package/src/skf-create-skill/references/ecosystem-check.md +9 -25
- package/src/skf-create-skill/references/enrich.md +4 -17
- package/src/skf-create-skill/references/extract.md +20 -27
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +10 -8
- package/src/skf-create-skill/references/generate-artifacts.md +20 -25
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +27 -14
- package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +33 -15
- package/src/skf-create-skill/references/step-doc-sources.md +13 -4
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
- package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
- package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
- package/src/skf-create-skill/references/validate.md +69 -29
- package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
- package/src/skf-create-stack-skill/SKILL.md +15 -9
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +10 -0
- package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
- package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
- package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
- package/src/skf-create-stack-skill/references/generate-output.md +24 -75
- package/src/skf-create-stack-skill/references/init.md +9 -81
- package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
- package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
- package/src/skf-create-stack-skill/references/report.md +27 -62
- package/src/skf-create-stack-skill/references/validate.md +35 -31
- package/src/skf-drop-skill/SKILL.md +20 -23
- package/src/skf-drop-skill/customize.toml +10 -0
- package/src/skf-drop-skill/references/execute.md +67 -36
- package/src/skf-drop-skill/references/headless-contract.md +18 -0
- package/src/skf-drop-skill/references/health-check.md +1 -13
- package/src/skf-drop-skill/references/report.md +44 -10
- package/src/skf-drop-skill/references/select.md +93 -48
- package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
- package/src/skf-export-skill/SKILL.md +17 -14
- package/src/skf-export-skill/assets/managed-section-format.md +2 -5
- package/src/skf-export-skill/customize.toml +10 -6
- package/src/skf-export-skill/references/generate-snippet.md +21 -35
- package/src/skf-export-skill/references/load-skill.md +44 -42
- package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
- package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
- package/src/skf-export-skill/references/package.md +27 -33
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
- package/src/skf-export-skill/references/result-envelope.md +28 -0
- package/src/skf-export-skill/references/summary.md +11 -5
- package/src/skf-export-skill/references/token-report.md +42 -24
- package/src/skf-export-skill/references/update-context.md +32 -33
- package/src/skf-forger/SKILL.md +32 -39
- package/src/skf-forger/references/pipeline-mode.md +34 -0
- package/src/skf-forger/scripts/parse-pipeline.py +270 -0
- package/src/skf-quick-skill/SKILL.md +10 -60
- package/src/skf-quick-skill/customize.toml +9 -0
- package/src/skf-quick-skill/references/batch-mode.md +6 -4
- package/src/skf-quick-skill/references/compile.md +15 -52
- package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
- package/src/skf-quick-skill/references/finalize.md +12 -6
- package/src/skf-quick-skill/references/halt-contract.md +54 -0
- package/src/skf-quick-skill/references/health-check.md +3 -4
- package/src/skf-quick-skill/references/quick-extract.md +7 -18
- package/src/skf-quick-skill/references/registry-resolution.md +1 -23
- package/src/skf-quick-skill/references/resolve-target.md +27 -34
- package/src/skf-quick-skill/references/write-and-validate.md +10 -25
- package/src/skf-refine-architecture/SKILL.md +16 -8
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +10 -8
- package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
- package/src/skf-refine-architecture/references/health-check.md +1 -1
- package/src/skf-refine-architecture/references/improvements.md +9 -25
- package/src/skf-refine-architecture/references/init.md +9 -16
- package/src/skf-refine-architecture/references/issue-detection.md +10 -25
- package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
- package/src/skf-refine-architecture/references/report.md +14 -11
- package/src/skf-rename-skill/SKILL.md +11 -21
- package/src/skf-rename-skill/customize.toml +10 -0
- package/src/skf-rename-skill/references/execute.md +112 -82
- package/src/skf-rename-skill/references/exit-codes.md +12 -0
- package/src/skf-rename-skill/references/report.md +16 -8
- package/src/skf-rename-skill/references/select.md +69 -42
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
- package/src/skf-setup/SKILL.md +21 -13
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +11 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +10 -8
- package/src/skf-setup/references/report.md +26 -32
- package/src/skf-setup/references/tier-rules.md +2 -32
- package/src/skf-setup/references/write-config.md +9 -10
- package/src/skf-test-skill/SKILL.md +10 -8
- package/src/skf-test-skill/customize.toml +2 -0
- package/src/skf-test-skill/references/coherence-check.md +19 -31
- package/src/skf-test-skill/references/coverage-check.md +111 -67
- package/src/skf-test-skill/references/detect-mode.md +10 -41
- package/src/skf-test-skill/references/external-validators.md +11 -19
- package/src/skf-test-skill/references/init.md +39 -21
- package/src/skf-test-skill/references/migration-section-rules.md +4 -4
- package/src/skf-test-skill/references/report.md +60 -40
- package/src/skf-test-skill/references/score.md +32 -64
- package/src/skf-test-skill/references/scoring-rules.md +6 -62
- package/src/skf-test-skill/references/source-access-protocol.md +15 -5
- package/src/skf-test-skill/references/step-hard-gate.md +1 -3
- package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
- package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
- package/src/skf-test-skill/scripts/compute-score.py +135 -4
- package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
- package/src/skf-update-skill/SKILL.md +17 -5
- package/src/skf-update-skill/customize.toml +11 -6
- package/src/skf-update-skill/references/detect-changes.md +48 -36
- package/src/skf-update-skill/references/health-check.md +5 -11
- package/src/skf-update-skill/references/init.md +40 -32
- package/src/skf-update-skill/references/manual-section-rules.md +1 -2
- package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
- package/src/skf-update-skill/references/merge.md +13 -57
- package/src/skf-update-skill/references/re-extract.md +27 -25
- package/src/skf-update-skill/references/report.md +14 -7
- package/src/skf-update-skill/references/validate.md +32 -30
- package/src/skf-update-skill/references/write.md +86 -51
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
- package/src/skf-verify-stack/SKILL.md +11 -21
- package/src/skf-verify-stack/customize.toml +12 -3
- package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
- package/src/skf-verify-stack/references/coverage.md +21 -10
- package/src/skf-verify-stack/references/exit-codes.md +14 -0
- package/src/skf-verify-stack/references/health-check.md +1 -1
- package/src/skf-verify-stack/references/init.md +20 -25
- package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
- package/src/skf-verify-stack/references/integrations.md +44 -49
- package/src/skf-verify-stack/references/report.md +28 -34
- package/src/skf-verify-stack/references/requirements.md +3 -3
- package/src/skf-verify-stack/references/synthesize.md +36 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
- package/tools/cli/lib/ui.js +3 -2
- package/docs/deepwiki.md +0 -89
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -122,7 +122,7 @@ Target file contains `<!-- SKF:BEGIN` but no matching `<!-- SKF:END -->` marker.
|
|
|
122
122
|
When regenerating (Case 3) or creating/appending (Cases 1-2), rebuild the skill index from the **exported skill set** only:
|
|
123
123
|
|
|
124
124
|
1. Read `{skills_output_folder}/.export-manifest.json` (v2 schema — see `knowledge/version-paths.md`) to determine which skills have been explicitly exported and their `active_version` (if no manifest exists, only the current export target qualifies)
|
|
125
|
-
2. For each skill in the exported set, resolve the snippet at `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md` (i.e., `{skill_package}/context-snippet.md`). Do NOT use glob patterns across version directories — always resolve via manifest `active_version` or `active` symlink
|
|
125
|
+
2. For each skill in the exported set, resolve the snippet at `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md` (i.e., `{skill_package}/context-snippet.md`). Do NOT use glob patterns across version directories — always resolve via manifest `active_version` or `active` symlink, falling back to the flat `{skills_output_folder}/{skill-name}/context-snippet.md` path for a skill not yet migrated to the versioned layout
|
|
126
126
|
3. Count total skills and stack skills (from filtered set only)
|
|
127
127
|
4. Assemble filtered snippets into managed section
|
|
128
128
|
5. Sort alphabetically by skill name
|
|
@@ -132,7 +132,4 @@ When regenerating (Case 3) or creating/appending (Cases 1-2), rebuild the skill
|
|
|
132
132
|
|
|
133
133
|
## Safety Rules
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
- ALWAYS preserve existing file content above and below markers
|
|
137
|
-
- ALWAYS verify file was written correctly after write
|
|
138
|
-
- If write fails, report error — do not attempt partial writes
|
|
135
|
+
Only the bytes between `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` are yours to rewrite; everything above and below is the user's own file (their CLAUDE.md/AGENTS.md/.cursorrules) and must survive byte-for-byte — rewriting outside the markers destroys their content. On write failure, report and stop — never leave a partial write. Route writes through the atomic-write / rebuild-managed-sections helpers: they verify byte-identity of the content outside the markers after each write, so no separate hand-check is needed.
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# DO NOT EDIT -- overwritten on every update.
|
|
2
2
|
#
|
|
3
3
|
# Workflow customization surface for skf-export-skill.
|
|
4
|
+
# Team overrides: _bmad/custom/skf-export-skill.toml (under {project-root})
|
|
5
|
+
# Personal overrides: _bmad/custom/skf-export-skill.user.toml (under {project-root})
|
|
4
6
|
|
|
5
7
|
[workflow]
|
|
6
8
|
|
|
@@ -34,6 +36,14 @@ persistent_facts = [
|
|
|
34
36
|
"file:{project-root}/**/project-context.md",
|
|
35
37
|
]
|
|
36
38
|
|
|
39
|
+
# Optional post-export hook. When non-empty, invoked with
|
|
40
|
+
# `--result-path=<path>` after step 6 finalizes the per-run result JSON
|
|
41
|
+
# (before the terminal health-check step). Useful for downstream
|
|
42
|
+
# distribution, notification, or pipeline chaining. Failures are logged to
|
|
43
|
+
# workflow_warnings[] but never fail the workflow. Empty = no-op (default).
|
|
44
|
+
|
|
45
|
+
on_complete = ""
|
|
46
|
+
|
|
37
47
|
# --- Optional asset overrides ---
|
|
38
48
|
#
|
|
39
49
|
# Lift the canonical asset paths so orgs can substitute house-style copies
|
|
@@ -41,9 +51,3 @@ persistent_facts = [
|
|
|
41
51
|
|
|
42
52
|
managed_section_format_path = ""
|
|
43
53
|
snippet_format_path = ""
|
|
44
|
-
|
|
45
|
-
# Override the manifest location. Empty = use
|
|
46
|
-
# {skills_output_folder}/.export-manifest.json. Useful for orgs that want
|
|
47
|
-
# a cross-project manifest at a stable path (e.g. ~/.skf/export-manifest.json).
|
|
48
|
-
|
|
49
|
-
export_manifest_path = ""
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'update-context.md'
|
|
3
3
|
snippetFormatData: '{snippetFormatPath}'
|
|
4
|
+
# Resolve `{countTokensHelper}` by probing `{countTokensProbeOrder}` in order
|
|
5
|
+
# (installed SKF module path first, src/ dev-checkout fallback); the first
|
|
6
|
+
# existing path wins. §5 uses it to report the written snippet's authoritative
|
|
7
|
+
# token count (char-over-four, matching step 5's token report) instead of the
|
|
8
|
+
# in-prompt `words * 1.3` heuristic.
|
|
9
|
+
countTokensProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-count-tokens.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-count-tokens.py'
|
|
4
12
|
---
|
|
5
13
|
|
|
6
14
|
<!-- Config: communicate in {communication_language}. Generate snippet content in {document_output_language}. -->
|
|
@@ -73,36 +81,17 @@ Store `{skill_root}` for use in snippet generation. The context-snippet.md writt
|
|
|
73
81
|
- **If NO new gotchas are derived AND `prior_gotchas` exists AND `prior_gotchas_already_carried == true`:** Expiry reached (re-export only — first-export branch above takes precedence) — drop the gotchas line entirely. Emit warning: "**Stale gotchas dropped** — the prior gotchas were already carried forward once and cannot be derived from the current evidence report. The snippet now has no gotchas line. If the prior gotchas are still relevant, re-add them to the evidence report's T2-future section and re-run export."
|
|
74
82
|
- **If NO new gotchas derived AND no `prior_gotchas`:** Omit the gotchas line.
|
|
75
83
|
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
[{skill-name} v{version}]|root: {skill_root}{skill-name}/
|
|
79
|
-
|IMPORTANT: {skill-name} v{version} — read SKILL.md before writing {skill-name} code. Do NOT rely on training data.
|
|
80
|
-
|quick-start:{SKILL.md#quick-start}
|
|
81
|
-
|api: {export-1}(), {export-2}(), {export-3}, {export-4}(), {export-5}
|
|
82
|
-
|key-types:{SKILL.md#key-types} — {inline summary ~10 words}
|
|
83
|
-
|gotchas: {pitfall-1}, {pitfall-2}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
**If fewer exports than limit:** List all available.
|
|
87
|
-
**If no exports:** Omit the api line.
|
|
88
|
-
**If no gotchas derivable AND no prior gotchas to carry forward:** Omit the gotchas line.
|
|
84
|
+
Emit the single-skill template from {snippetFormatData} (loaded in §2), filling `api` from the exports selected above (list all if fewer than the limit; omit the line if there are none), `key-types` from the inline summary extracted above, and `gotchas` per the carry-forward decision tree above (omit the line when it resolves to none).
|
|
89
85
|
|
|
90
86
|
**For stack skills (`skill_type: "stack"`):**
|
|
91
87
|
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
[{project}-stack v{version}]|root: {skill_root}{project}-stack/
|
|
95
|
-
|IMPORTANT: {project}-stack — read SKILL.md before writing integration code. Do NOT rely on training data.
|
|
96
|
-
|stack: {dep-1}@{v1}, {dep-2}@{v2}, {dep-3}@{v3}
|
|
97
|
-
|integrations: {pattern-1}, {pattern-2}
|
|
98
|
-
|gotchas: {pitfall-1}, {pitfall-2}
|
|
99
|
-
```
|
|
88
|
+
Emit the stack-skill template from {snippetFormatData}, filling `stack` from metadata.json `components` and `integrations` from metadata.json `integrations`.
|
|
100
89
|
|
|
101
90
|
**Stack skill gotchas carry-forward:** Same one-cycle expiry logic as single skills. If no new gotchas derived and `prior_gotchas_already_carried == false`, preserve with the `[CARRIED]` prefix. If already carried once (`prior_gotchas_already_carried == true`), drop the line and warn loudly. See the single-skill steps for the complete protocol.
|
|
102
91
|
|
|
103
92
|
### 4. Verify Token Count
|
|
104
93
|
|
|
105
|
-
Estimate token count
|
|
94
|
+
Estimate the generated snippet's token count with the **char-over-four** convention (`len(snippet)//4`) over the content held in context — the same convention `skf-count-tokens.py` uses for step 5's token report, so the two numbers agree. The freshly generated snippet is only in context here (not yet on disk), so this pre-write estimate stays in-prompt to drive the trim decision below; step 5 confirms it authoritatively against the written file via the helper.
|
|
106
95
|
|
|
107
96
|
- Target: ~80-120 tokens per skill (aspirational for Quick/Forge tiers)
|
|
108
97
|
- Warning threshold: >300 tokens (hard ceiling — Deep tier may legitimately exceed 120 when gotchas carry load-bearing breaking-change notices)
|
|
@@ -122,12 +111,20 @@ Estimate token count of generated snippet (approximate: words * 1.3).
|
|
|
122
111
|
|
|
123
112
|
**Estimated tokens:** {count}"
|
|
124
113
|
|
|
125
|
-
Hold content in context for step 4.
|
|
114
|
+
Use the §4 char-over-four estimate for `{count}` — nothing is written in dry-run, so the helper has no on-disk snippet to measure. Hold content in context for step 4.
|
|
126
115
|
|
|
127
116
|
**If NOT dry-run:**
|
|
128
117
|
|
|
129
118
|
Write the generated content to `{resolved_skill_package}/context-snippet.md`.
|
|
130
119
|
|
|
120
|
+
Then confirm the token count authoritatively: resolve `{countTokensHelper}` from `{countTokensProbeOrder}` (first existing path wins) and run it against the written package, reading the `context-snippet.md` row's `tokens` value:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python3 {countTokensHelper} {resolved_skill_package}
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Use that value as `{count}` — it matches step 5's token report exactly. If the helper cannot run (no Python/uv), fall back to the §4 char-over-four estimate.
|
|
127
|
+
|
|
131
128
|
"**context-snippet.md written.**
|
|
132
129
|
**Path:** `{resolved_skill_package}/context-snippet.md`
|
|
133
130
|
**Estimated tokens:** {count}"
|
|
@@ -136,16 +133,5 @@ Write the generated content to `{resolved_skill_package}/context-snippet.md`.
|
|
|
136
133
|
|
|
137
134
|
Display: "**Proceeding to context update...**"
|
|
138
135
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
- After snippet generation completes, immediately load, read entire file, then execute {nextStepFile}
|
|
142
|
-
|
|
143
|
-
#### EXECUTION RULES:
|
|
144
|
-
|
|
145
|
-
- This is an auto-proceed step with no user choices
|
|
146
|
-
- Proceed directly to next step after generation
|
|
147
|
-
|
|
148
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
149
|
-
|
|
150
|
-
ONLY WHEN snippet generation is complete (or skipped due to passive_context opt-out) will you load and read fully `{nextStepFile}` to execute context update.
|
|
136
|
+
Auto-proceed (no user choices): once snippet generation is complete (or skipped via the `passive_context` opt-out), load, read entirely, and execute `{nextStepFile}`.
|
|
151
137
|
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'package.md'
|
|
3
|
+
managedSectionData: '{managedSectionFormatPath}'
|
|
4
|
+
# Resolve `{validateOutputHelper}` by probing `{validateOutputProbeOrder}` in
|
|
5
|
+
# order (installed SKF module path first, src/ dev-checkout fallback); first
|
|
6
|
+
# existing path wins. §2 runs it with `--export-gate` to obtain the
|
|
7
|
+
# agentskills.io export verdict — required-field presence, enum membership,
|
|
8
|
+
# JSON validity, and the SKILL.md Section 7b <-> scripts/assets cross-reference
|
|
9
|
+
# — as one deterministic JSON result, instead of re-deriving those checks
|
|
10
|
+
# in-prompt each run. package.md §1-4 renders its status from the same verdict.
|
|
11
|
+
validateOutputProbeOrder:
|
|
12
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-output.py'
|
|
13
|
+
- '{project-root}/src/shared/scripts/skf-validate-output.py'
|
|
3
14
|
---
|
|
4
15
|
|
|
5
16
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -25,18 +36,20 @@ Determine the skill(s) to export and any flags:
|
|
|
25
36
|
|
|
26
37
|
**Skill Path Discovery (version-aware — see `knowledge/version-paths.md`):**
|
|
27
38
|
- If user provided one or more skill names or paths as arguments, use that list directly
|
|
28
|
-
- If `--all` was passed, build the list from every skill in `{skills_output_folder}/.export-manifest.json.exports` whose `active_version` entry is not `status: "deprecated"` (deprecated skills are excluded from all exports — see step 4 §4b)
|
|
29
|
-
- If no explicit skill and no `--all`,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
39
|
+
- If `--all` was passed, build the list from every skill in `{skills_output_folder}/.export-manifest.json.exports` whose `active_version` entry is not `status: "deprecated"` (deprecated skills are excluded from all exports — see step 4 §4b). **First-export fallback:** if the manifest is absent or its `exports` object is empty (a fresh repo with skills on disk but no prior export), do not resolve to an empty set — enumerate skills on disk instead, using the same discovery ladder as the no-argument branch below (`active` symlinks at `{skills_output_folder}/{skill-name}/active/{skill-name}/SKILL.md`, then flat `{skills_output_folder}/{skill-name}/SKILL.md`). Every disk-discovered skill is non-deprecated by definition — deprecation status lives only in the manifest.
|
|
40
|
+
- If no explicit skill and no `--all`, then:
|
|
41
|
+
- **Headless guard:** if `{headless_mode}` is true, HALT (exit code 2, `halt_reason: "input-missing"`) — a non-interactive run cannot answer the skill-selection menu; the operator must pass an explicit `skill_name` or `--all`. Emit the error envelope per `references/result-envelope.md` with `skills: []`, `context_files_updated: []`, `manifest_path: null`.
|
|
42
|
+
- **Interactive:** discover available skills using the export manifest:
|
|
43
|
+
1. Read `{skills_output_folder}/.export-manifest.json` — list skill names from `exports`
|
|
44
|
+
2. For each skill group directory in `{skills_output_folder}/`, check for `{skill_group}/active/{skill-name}/SKILL.md`
|
|
45
|
+
3. If neither manifest nor `active` symlink yields results, fall back to flat path: `{skills_output_folder}/{skill-name}/SKILL.md`
|
|
33
46
|
- If multiple skills are found, present the list and accept either a single selection or a comma-/space-separated multi-selection (e.g. `1, 2, 3` or `all`)
|
|
34
|
-
- If no skills found,
|
|
47
|
+
- If no skills found, HALT (exit code 3, `halt_reason: "resolution-failure"`): "No skills found in {skills_output_folder}/. Run create-skill first." In headless, emit the error envelope per `references/result-envelope.md` with `skills: []`, `context_files_updated: []`, `manifest_path: null`.
|
|
35
48
|
|
|
36
49
|
Store the resolved selection as `skill_batch` — a list of one or more skill names. `len(skill_batch) > 1` activates multi-skill mode (see §1c below).
|
|
37
50
|
|
|
38
51
|
**Flag Parsing:**
|
|
39
|
-
- `--all` flag: Check if provided. When true and no explicit skill list was given, `skill_batch` is the full non-deprecated manifest set (see above).
|
|
52
|
+
- `--all` flag: Check if provided. When true and no explicit skill list was given, `skill_batch` is the full non-deprecated manifest set — or, when no manifest exists yet, the full on-disk discovery set (see the first-export fallback above).
|
|
40
53
|
- `--context-file` flag: Check if explicitly provided (CLAUDE.md, .cursorrules, or AGENTS.md). Replaces the old `--platform` flag.
|
|
41
54
|
- `--dry-run` flag: Check if provided. Default: `false`
|
|
42
55
|
|
|
@@ -44,16 +57,9 @@ Store the resolved selection as `skill_batch` — a list of one or more skill na
|
|
|
44
57
|
|
|
45
58
|
If `--context-file` is explicitly provided, use that single context file as the sole target. Determine the skill root from the first configured IDE that maps to that context file (or `.agents/skills/` for AGENTS.md if no matching IDE is configured). If other IDEs are configured in config.yaml, emit a note: "**Note:** Exporting to {context-file} only. config.yaml also lists: {other-ides}. Run without `--context-file` to export to all configured IDEs."
|
|
46
59
|
|
|
47
|
-
If `--context-file` is NOT provided, read the `ides` list from config.yaml and map each
|
|
60
|
+
If `--context-file` is NOT provided, read the `ides` list from config.yaml and map each entry to its `context_file` and `skill_root` using the "IDE → Context File Mapping" table plus the "Resolution rules" in `{managedSectionData}` — that canonical file carries the deduplication (group by context file; first configured IDE's skill root wins), the unknown-IDE default-and-warn, and the missing-`ides`-key (treat as empty list) behavior, each with its exact warning/report string. Every IDE the installer offers has an explicit mapping — no silent skips.
|
|
48
61
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
1. Look up its `context_file` and `skill_root` from the canonical mapping table
|
|
52
|
-
2. If the IDE is not in the table, default to AGENTS.md / `.agents/skills/` and warn: "Unknown IDE '{value}' in config.yaml — defaulting to AGENTS.md with `.agents/skills/`"
|
|
53
|
-
|
|
54
|
-
**Deduplication:** Group by `context_file`. When multiple IDE entries map to the same context file (e.g. both `codex` and `cline` map to AGENTS.md), deduplicate so each context file appears in `target_context_files` only once. Use the **first configured IDE's** `skill_root` for that context file. Report the deduplication: "Multiple IDEs target AGENTS.md — using {first-ide}'s skill root (`{skill_root}`). Each IDE's skills are installed to its own directory."
|
|
55
|
-
|
|
56
|
-
**Missing-key handling:** If the `ides` key is absent from config.yaml (older installation or manually edited file), treat it as an empty list.
|
|
62
|
+
Apply those rules to `config.yaml.ides`, then:
|
|
57
63
|
|
|
58
64
|
- If mapping produces one or more context files (after dedup), store as `target_context_files` list — each entry has `{context_file, skill_root}`
|
|
59
65
|
- If mapping produces zero entries (empty ides list and no recognized entries), fall back to `[{context_file: "AGENTS.md", skill_root: ".agents/skills/"}]` with note: "No IDEs configured in config.yaml — defaulting to AGENTS.md with `.agents/skills/`."
|
|
@@ -64,13 +70,13 @@ For each IDE in `config.yaml.ides`:
|
|
|
64
70
|
|
|
65
71
|
### 1b. Detect Snippet Root Prefix Mismatch
|
|
66
72
|
|
|
67
|
-
**Skip entirely if `snippet_skill_root_override` is set in `config.yaml`** — the authoring-repo escape hatch is already configured and any on-disk prefix that matches it is ground truth (see `
|
|
73
|
+
**Skip entirely if `snippet_skill_root_override` is set in `config.yaml`** — the authoring-repo escape hatch is already configured and any on-disk prefix that matches it is ground truth (see `{managedSectionData}` override rules).
|
|
68
74
|
|
|
69
75
|
**Otherwise:** load `references/preflight-snippet-root-probe.md` and follow its probe + (a) Set override / (b) Proceed with IDE mapping / (c) Cancel gate protocol. The reference handles candidate snippet collection (manifest-driven), prefix observation, the mismatch warning, and headless default ((b) Proceed). Returns control to §1c on no-mismatch fast path or after a (b) choice.
|
|
70
76
|
|
|
71
77
|
### 1c. Multi-skill Mode (when `len(skill_batch) > 1`)
|
|
72
78
|
|
|
73
|
-
**If `len(skill_batch) == 1`:** single-skill mode
|
|
79
|
+
**If `len(skill_batch) == 1`:** single-skill mode — every section below operates on the one skill without iteration. Skip this subsection.
|
|
74
80
|
|
|
75
81
|
**If `len(skill_batch) > 1`:** load `references/multi-skill-mode.md` and apply its per-step behavior matrix. The reference partitions work so that step 1 §2–5 iterates per skill, step 1 §6 presents a single consolidated [C] gate, step 4 batches once across the whole run, and step 7 health check runs once. It also defines the all-or-nothing halt semantics if any single skill fails §2 validation.
|
|
76
82
|
|
|
@@ -95,15 +101,22 @@ Load all files from `{resolved_skill_package}`:
|
|
|
95
101
|
- `references/` — Progressive disclosure directory
|
|
96
102
|
- `context-snippet.md` — Existing snippet (will be regenerated)
|
|
97
103
|
|
|
98
|
-
**Validation
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
**Validation (deterministic — the export gate):**
|
|
105
|
+
|
|
106
|
+
Run the export gate against the resolved package. Resolve `{validateOutputHelper}` from `{validateOutputProbeOrder}` (first existing path wins):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
python3 {validateOutputHelper} {resolved_skill_package} --export-gate
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
The script emits one JSON verdict covering every check this step used to derive by hand: `SKILL.md` present and non-empty; `metadata.json` present and valid JSON; the required agentskills.io fields present (`name`, `version`, `skill_type`, `source_authority`, `exports`, `generation_date`, `confidence_tier`); enum membership (`skill_type` ∈ single/stack, `source_authority` ∈ official/internal/community, `confidence_tier` ∈ Quick/Forge/Forge+/Deep); a non-empty `exports` array (empty is a low warning, not a halt); and the SKILL.md Section 7b ↔ on-disk `scripts/`/`assets/` cross-reference (a §7b-named file absent on disk is a high issue; an unreferenced on-disk file is a low orphan warning). Read `result` (PASS/FAIL), `export_status` (READY/WARNINGS/NOT_READY), and the issue arrays under `validation.metadata.{issues,enum_issues}` and `validation.crossref_7b.{missing,orphans}`. **Retain this JSON as the export verdict** — step 2 (`package.md`) renders its status from it without re-deriving the checks.
|
|
103
113
|
|
|
104
|
-
**If
|
|
105
|
-
|
|
114
|
+
**If the script cannot run** (no `uv`/Python — e.g. claude.ai web): perform the equivalent checks by hand; `python3 {validateOutputHelper} --help` documents exactly what it verifies.
|
|
115
|
+
|
|
116
|
+
**If `result` is `FAIL` / `export_status` is `NOT_READY`** (any high-severity issue in `validation.*`):
|
|
117
|
+
"**Export cannot proceed.** Missing or invalid: {list the high-severity issue messages from the script's `validation.metadata.{issues,enum_issues}` and `validation.crossref_7b.missing`}
|
|
106
118
|
Run create-skill to generate a complete skill first."
|
|
119
|
+
Then HALT (exit code 3, `halt_reason: "resolution-failure"`). In headless, emit the error envelope per `references/result-envelope.md` with the resolved `skills`, `context_files_updated: []`, `manifest_path: null`.
|
|
107
120
|
|
|
108
121
|
### 3. Read Skill Metadata
|
|
109
122
|
|
|
@@ -196,23 +209,12 @@ Continue to step 5 regardless — this is advisory, not blocking.
|
|
|
196
209
|
|
|
197
210
|
**Are these the correct skills to export?**"
|
|
198
211
|
|
|
199
|
-
### 6.
|
|
200
|
-
|
|
201
|
-
Display: "**Select:** [C] Continue to packaging | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)" (multi-skill mode: the single [C] gate covers the whole batch)
|
|
202
|
-
|
|
203
|
-
#### Menu Handling Logic:
|
|
204
|
-
|
|
205
|
-
- IF C: Proceed with loaded skill data, then load, read entire file, then execute {nextStepFile}
|
|
206
|
-
- IF X (or `cancel` / `exit` / `:q`): Display "Cancelled — no packaging or context file writes were performed." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per SKILL.md "Result Contract (Headless)" with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
|
|
207
|
-
- IF Any other: help user respond, then [Redisplay Menu Options](#6-present-menu-options)
|
|
208
|
-
|
|
209
|
-
#### EXECUTION RULES:
|
|
210
|
-
|
|
211
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
212
|
-
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past skill confirmation"
|
|
213
|
-
- ONLY proceed to next step when user selects 'C'
|
|
212
|
+
### 6. Confirmation Gate
|
|
214
213
|
|
|
215
|
-
|
|
214
|
+
Display: "**Select:** [C] Continue to packaging | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)" (multi-skill mode: the single [C] gate covers the whole batch), then wait for the reply.
|
|
216
215
|
|
|
217
|
-
|
|
216
|
+
- **[C]** — proceed with the loaded skill data: load, read entirely, and execute `{nextStepFile}`.
|
|
217
|
+
- **[X]** / `cancel` / `exit` / `:q` — Display "Cancelled — no packaging or context file writes were performed." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per `references/result-envelope.md` with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
|
|
218
|
+
- **Any other input** — help the user respond, then redisplay this gate.
|
|
219
|
+
- **Headless** [default C]: auto-proceed with [C], log "headless: auto-continue past skill confirmation".
|
|
218
220
|
|
|
@@ -35,4 +35,4 @@ If any single skill fails validation in step 1 §2 (required-file or metadata-fi
|
|
|
35
35
|
|
|
36
36
|
## Single-skill mode (reference)
|
|
37
37
|
|
|
38
|
-
`len(skill_batch) == 1`
|
|
38
|
+
`len(skill_batch) == 1` runs the single-skill path: every section operates on the one skill without iteration, no gate consolidation, no per-step table consultation. This file does not need to be loaded.
|
|
@@ -43,10 +43,18 @@ Wait for user choice.
|
|
|
43
43
|
|
|
44
44
|
### (a) clear
|
|
45
45
|
|
|
46
|
+
The marker excision is deterministic surgery with one correct answer per input — a mis-parsed boundary silently corrupts the user's surrounding content. Delegate it to the tested `clear` action of `skf-rebuild-managed-sections.py`, the same helper `update-context.md` §9 uses for the between-marker swap; do not excise markers in-prompt. Resolve `{rebuildManagedSectionsHelper}` from `update-context.md`'s `{rebuildManagedSectionsProbeOrder}` frontmatter (first existing path wins). If no candidate exists, HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) per `update-context.md` §9 — falling through to an in-prompt excision would regress the atomic-write + post-clear verify guarantee.
|
|
47
|
+
|
|
46
48
|
For each file in `orphaned_context_files`:
|
|
47
49
|
|
|
48
|
-
1.
|
|
49
|
-
|
|
50
|
+
1. Run:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
python3 {rebuildManagedSectionsHelper} {file_path} clear
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
The `clear` action removes the entire `<!-- SKF:BEGIN -->`…`<!-- SKF:END -->` block (and its surrounding blank lines), leaves the rest of the file intact, and performs an atomic temp-file + rename write with a post-clear verify that the section is gone. Treat any non-zero exit (or a `status: "error"` envelope) as a clear failure — HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) reporting `{file_path}: {captured stderr}`. This branch is interactive-only (the headless default is (b) keep), so it emits no result envelope here.
|
|
57
|
+
2. On success (`status: "ok"`, `action: "cleared"`), append the file path to `orphans_cleared`. On a non-empty list, record it in the §6 result contract as a `deviations[]` entry (`kind: "clear_orphan_context"`, `files: [...]`) — the extensible deviations mechanism summary.md §6 documents for choices that diverge from the canonical export path.
|
|
50
58
|
|
|
51
59
|
### (b) keep
|
|
52
60
|
|
|
@@ -58,7 +66,7 @@ Add each entry in `orphaned_context_files` to a separate `rewrite_context_files`
|
|
|
58
66
|
|
|
59
67
|
Use `.agents/skills/` as the default skill root for rewritten orphans (the IDE-neutral path used when the original IDE mapping is no longer available).
|
|
60
68
|
|
|
61
|
-
Record each rewritten file in `orphans_rewritten
|
|
69
|
+
Record each rewritten file in `orphans_rewritten`. On a non-empty list, record it in the §6 result contract as a `deviations[]` entry (`kind: "rewrite_orphan_context"`, `files: [...]`) — the same extensible deviations mechanism summary.md §6 documents.
|
|
62
70
|
|
|
63
71
|
## Downstream contract
|
|
64
72
|
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'generate-snippet.md'
|
|
3
|
+
# `{validateOutputHelper}` resolves from `{validateOutputProbeOrder}` (first
|
|
4
|
+
# existing path wins). Step 1 §2 already ran `--export-gate` and retained the
|
|
5
|
+
# JSON verdict; this step renders its status from that verdict. Only re-run the
|
|
6
|
+
# command below if the step-1 JSON is not in context (e.g. package.md entered
|
|
7
|
+
# directly). The verdict is deterministic — same package → same result.
|
|
8
|
+
validateOutputProbeOrder:
|
|
9
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-output.py'
|
|
10
|
+
- '{project-root}/src/shared/scripts/skf-validate-output.py'
|
|
3
11
|
---
|
|
4
12
|
|
|
5
13
|
<!-- Config: communicate in {communication_language}. Validate package contents in {document_output_language}. -->
|
|
@@ -34,19 +42,16 @@ Verify the skill package at `{resolved_skill_package}` (resolved in step 1 via m
|
|
|
34
42
|
└── assets/ ← Optional: Templates, schemas, configs
|
|
35
43
|
```
|
|
36
44
|
|
|
37
|
-
**
|
|
38
|
-
|
|
39
|
-
2
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
3. `references/` — If exists, check at least one .md file present
|
|
48
|
-
4. `scripts/` — If exists, verify at least one file present and each file referenced in SKILL.md Section 7b exists. Warn for orphaned scripts (present but not referenced).
|
|
49
|
-
5. `assets/` — If exists, verify at least one file present and each file referenced in SKILL.md Section 7b exists. Warn for orphaned assets (present but not referenced).
|
|
45
|
+
**Component checks — from the export-gate verdict (do not re-derive):**
|
|
46
|
+
|
|
47
|
+
Step 1 §2 already ran the export gate (`python3 {validateOutputHelper} {resolved_skill_package} --export-gate`) and retained its JSON. Read that verdict rather than re-listing the required fields, enum values, or Section 7b rules here — it deterministically covers all of it:
|
|
48
|
+
|
|
49
|
+
- `SKILL.md` present and non-empty; `metadata.json` present and valid JSON — `validation.skill_md.issues` / `validation.metadata.issues`
|
|
50
|
+
- Required agentskills.io fields present (`name`, `version`, `skill_type`, `source_authority`, `exports`, `generation_date`, `confidence_tier`) — `validation.metadata.issues`
|
|
51
|
+
- Enum membership (`skill_type`, `source_authority`, `confidence_tier`) — `validation.metadata.enum_issues`
|
|
52
|
+
- SKILL.md Section 7b ↔ on-disk `scripts/`/`assets/` cross-reference — `validation.crossref_7b.missing` (high: §7b-named file absent on disk) and `validation.crossref_7b.orphans` (low: on-disk file not referenced in §7b)
|
|
53
|
+
|
|
54
|
+
If the step-1 JSON is not in context (e.g. this step was entered directly), re-run the command above to regenerate it — the verdict is deterministic. `references/` presence (at least one `.md`) remains a simple on-disk observation for the §4 report.
|
|
50
55
|
|
|
51
56
|
### 2. Validate Metadata Completeness
|
|
52
57
|
|
|
@@ -62,26 +67,26 @@ Check metadata.json for recommended (non-required) fields:
|
|
|
62
67
|
|
|
63
68
|
### 3. Assess Package Readiness
|
|
64
69
|
|
|
65
|
-
|
|
70
|
+
Read `export_status` directly from the export-gate verdict (step 1 §2) — do not re-compute the status by hand:
|
|
66
71
|
|
|
67
|
-
**READY
|
|
68
|
-
**WARNINGS
|
|
69
|
-
**NOT READY
|
|
72
|
+
- **READY** — the verdict has no issues (`export_status: "READY"`).
|
|
73
|
+
- **WARNINGS** — only medium/low issues remain (`export_status: "WARNINGS"`): §7b orphans, an empty `exports` array, or the recommended-field notes from §2 above.
|
|
74
|
+
- **NOT READY** — any high-severity issue (`export_status: "NOT_READY"`). Step 1 §2 halts on this, so a healthy run never reaches here; if it does, surface the high-severity messages and halt.
|
|
70
75
|
|
|
71
76
|
### 4. Report Package Status
|
|
72
77
|
|
|
73
78
|
"**Package structure validated.**
|
|
74
79
|
|
|
75
|
-
**Status:** {READY / WARNINGS}
|
|
80
|
+
**Status:** {export_status: READY / WARNINGS}
|
|
76
81
|
|
|
77
82
|
**Required Components:**
|
|
78
83
|
- SKILL.md: ✅
|
|
79
|
-
- metadata.json: ✅ (
|
|
84
|
+
- metadata.json: ✅ (required fields valid per export-gate verdict)
|
|
80
85
|
- references/: {✅ present ({count} files) / ⚠️ not present}
|
|
81
86
|
|
|
82
|
-
{If warnings:}
|
|
87
|
+
{If warnings (export_status: WARNINGS):}
|
|
83
88
|
**Warnings:**
|
|
84
|
-
- {list missing recommended fields}
|
|
89
|
+
- {list missing recommended fields from §2, plus any `validation.crossref_7b.orphans` and an empty `exports` warning from the verdict}
|
|
85
90
|
|
|
86
91
|
**Package is ready for snippet generation.**"
|
|
87
92
|
|
|
@@ -89,16 +94,5 @@ Determine package status:
|
|
|
89
94
|
|
|
90
95
|
Display: "**Proceeding to snippet generation...**"
|
|
91
96
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
- After package validation completes, immediately load, read entire file, then execute {nextStepFile}
|
|
95
|
-
|
|
96
|
-
#### EXECUTION RULES:
|
|
97
|
-
|
|
98
|
-
- This is an auto-proceed step with no user choices
|
|
99
|
-
- Proceed directly to next step after validation
|
|
100
|
-
|
|
101
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
102
|
-
|
|
103
|
-
ONLY WHEN package validation is complete will you load and read fully `{nextStepFile}` to execute snippet generation.
|
|
97
|
+
Auto-proceed (no user choices): once package validation is complete, load, read entirely, and execute `{nextStepFile}`.
|
|
104
98
|
|
|
@@ -5,6 +5,15 @@
|
|
|
5
5
|
# truth by contract — no probe needed and the entire authoring-repo
|
|
6
6
|
# escape hatch is already configured. Loaded once per export run, not
|
|
7
7
|
# per skill.
|
|
8
|
+
# Resolve `{rebuildManagedSectionsHelper}` by probing
|
|
9
|
+
# `{rebuildManagedSectionsProbeOrder}` in order (installed SKF module
|
|
10
|
+
# path first, src/ dev-checkout fallback); first existing path wins.
|
|
11
|
+
# The `root-probe` action reads each candidate snippet's first line,
|
|
12
|
+
# parses/strips the `root:` prefix, and returns `observed_prefixes` +
|
|
13
|
+
# `mismatch` — deterministic prefix comparison the LLM must not re-derive.
|
|
14
|
+
rebuildManagedSectionsProbeOrder:
|
|
15
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-rebuild-managed-sections.py'
|
|
16
|
+
- '{project-root}/src/shared/scripts/skf-rebuild-managed-sections.py'
|
|
8
17
|
---
|
|
9
18
|
|
|
10
19
|
<!-- Config: communicate in {communication_language}. Render the warning and gate prompt in {document_output_language}. -->
|
|
@@ -26,16 +35,26 @@ Loaded by `load-skill.md` §1b after `target_context_files` is resolved and `sni
|
|
|
26
35
|
|
|
27
36
|
## Probe Algorithm
|
|
28
37
|
|
|
29
|
-
1. Collect candidate snippet paths:
|
|
38
|
+
1. Collect candidate snippet paths (manifest-driven orchestration — stays in-prompt):
|
|
30
39
|
- Read `{skills_output_folder}/.export-manifest.json` if it exists. For each skill in `exports` with a resolvable `active_version`, add `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`.
|
|
31
40
|
- Also include the current skill's snippet if present.
|
|
32
|
-
2.
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
2. **Read the prefixes and compare via the helper** — reading each snippet's first line, parsing/stripping the `root:` prefix, collecting the unique set, and comparing against the reference is deterministic prefix arithmetic with one correct answer per input. Resolve `{rebuildManagedSectionsHelper}` from `{rebuildManagedSectionsProbeOrder}` (frontmatter — first existing path wins; if no candidate exists, skip the probe and continue to §2 without a warning rather than blocking export on a missing dev-only helper), then run:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
python3 {rebuildManagedSectionsHelper} root-probe {candidate-snippet-1} {candidate-snippet-2} … --reference-root {target_context_files[0].skill_root}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Pass every candidate snippet path from step 1 as a positional argument and the reference `skill_root` as `--reference-root`. The helper reads each snippet that exists, parses its first-line `root:` value, strips the trailing `{skill-name}/` (recovered from the row's own `[skill-name v...]` header) to extract the prefix, and returns:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{"status": "ok", "reference_root": "…", "observed_prefixes": ["…"], "mismatch": true}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Set `observed_prefixes = result["observed_prefixes"]` (already unique and sorted; missing or root-less snippets contribute nothing). `result["mismatch"]` is `true` when any observed prefix differs from the reference `skill_root` — the trigger for the Mismatch Gate below.
|
|
35
54
|
|
|
36
55
|
## Mismatch Gate
|
|
37
56
|
|
|
38
|
-
**If `
|
|
57
|
+
**If `result["mismatch"]` is `true`** (some value in `observed_prefixes` does not match the reference `skill_root`):
|
|
39
58
|
|
|
40
59
|
Emit a single warning (once, not per snippet) and present resolution options before continuing to §2:
|
|
41
60
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
<!-- Config: emit exactly as specified — this is a machine-parsed contract. Loaded standalone by any halting stage; it back-references no other file. -->
|
|
2
|
+
|
|
3
|
+
# Headless Result Envelope
|
|
4
|
+
|
|
5
|
+
The single-line JSON envelope export-skill emits on non-interactive (`{headless_mode}`) runs. Pipeline consumers parse it to branch on the run's outcome, so its shape must be reproduced exactly. This file stands alone — every HARD-HALT stage can load it without SKILL.md in context.
|
|
6
|
+
|
|
7
|
+
## Emission rule
|
|
8
|
+
|
|
9
|
+
- **Success / dry-run:** step 6 (`summary.md`) emits the envelope on **stdout**, once, before chaining to step 7.
|
|
10
|
+
- **Every HARD HALT:** emit the same envelope shape on **stderr** with `status: "error"`, then exit with the matching code.
|
|
11
|
+
|
|
12
|
+
## Shape
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
SKF_EXPORT_RESULT_JSON: {"status":"success|error|dry-run","skills":[],"context_files_updated":[],"manifest_path":"…|null","headless_decisions":[],"exit_code":0,"halt_reason":null}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Fields
|
|
19
|
+
|
|
20
|
+
- `status` — `"success"` on the terminal happy path, `"dry-run"` when `--dry-run` skipped the §4 context and manifest writes (the run still reaches the terminal step), `"error"` on any HALT.
|
|
21
|
+
- `skills` — resolved skill names in the batch (JSON array).
|
|
22
|
+
- `context_files_updated` — context files successfully written this run (JSON array; `[]` when a HALT preceded any write).
|
|
23
|
+
- `manifest_path` — the written manifest path, or `null` when no manifest write completed.
|
|
24
|
+
- `headless_decisions` — the `{gate, default_action, taken_action, reason}` entries logged as each gate auto-resolved (JSON array).
|
|
25
|
+
- `exit_code` — 0 success/dry-run · 2 input-missing · 3 resolution-failure · 4 write-failure · 5 state-conflict · 6 user-cancelled.
|
|
26
|
+
- `halt_reason` — `null` on success/dry-run, else one of: `"input-missing"`, `"resolution-failure"`, `"malformed-markers"`, `"manifest-write-failed"`, `"context-rebuild-failed"`, `"write-failed"`, `"user-cancelled"`. Each value is emitted by a real HALT site (see the SKILL.md Exit Codes table for the code↔reason map); the enum lists no value that no stage emits.
|
|
27
|
+
|
|
28
|
+
A halting stage sets the branch-specific fields inline (e.g. `manifest_path: null`, `context_files_updated: []`) and fills the rest from the shape above.
|
|
@@ -132,7 +132,7 @@ No files were written. To run the export for real:
|
|
|
132
132
|
|
|
133
133
|
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{timestamp}.json` (reuse the activation-stored `{timestamp}`, resolution to seconds) and a copy at `{skills_output_folder}/export-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all context files and target managed-section files in `outputs`; include total always-on and on-trigger token counts in `summary`.
|
|
134
134
|
|
|
135
|
-
When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (
|
|
135
|
+
When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (per `references/result-envelope.md`):
|
|
136
136
|
|
|
137
137
|
```
|
|
138
138
|
SKF_EXPORT_RESULT_JSON: {"status":"success","skills":{skill_batch_names},"context_files_updated":{context_files_updated},"manifest_path":"{skills_output_folder}/.export-manifest.json","headless_decisions":{headless_decisions},"exit_code":0,"halt_reason":null}
|
|
@@ -156,11 +156,17 @@ Substitute `{skill_batch_names}`, `{context_files_updated}`, and `{headless_deci
|
|
|
156
156
|
|
|
157
157
|
Other workflow choices that diverge from the strict spec path may add their own entries with a distinct `kind` value — auditors then have one place to look for "what did this run choose to do differently from the canonical flow." Omit the field when there are no deviations rather than writing an empty array, so the absence is readable as "ran the canonical path."
|
|
158
158
|
|
|
159
|
-
###
|
|
159
|
+
### 6b. Post-Export Hook (Optional)
|
|
160
|
+
|
|
161
|
+
If `{onCompleteCommand}` (resolved at SKILL.md On Activation §4 from `workflow.on_complete`) is non-empty, invoke it now — after both the per-run and `-latest` result JSON have been written:
|
|
160
162
|
|
|
161
|
-
|
|
163
|
+
```bash
|
|
164
|
+
{onCompleteCommand} --result-path={skills_output_folder}/export-skill-result-{timestamp}.json
|
|
165
|
+
```
|
|
162
166
|
|
|
163
|
-
|
|
167
|
+
Run it with a bounded timeout. On success, continue. On non-zero exit, timeout, or any failure, append the reason to `workflow_warnings[]` (e.g. `on_complete — failed (exit {N}): {stderr_first_line}`) and continue. **The hook must never fail the workflow** — it is integration glue (downstream distribution, notifier, pipeline chain) and any failure there is orthogonal to the export outcome. When `{onCompleteCommand}` is empty (bundled default), skip this section entirely.
|
|
168
|
+
|
|
169
|
+
### 7. Chain to Health Check
|
|
164
170
|
|
|
165
|
-
|
|
171
|
+
ONLY WHEN the export summary, distribution instructions, result contract, and on-complete hook (or its skip on an empty `{onCompleteCommand}`) are complete 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 summary reads as final.
|
|
166
172
|
|