bmad-module-skill-forge 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +0 -8
- package/docs/_data/pinned.yaml +1 -1
- package/docs/_internal/STABILITY.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/examples.md +1 -1
- package/docs/workflows.md +5 -5
- package/package.json +2 -2
- package/src/README.md +1 -1
- package/src/knowledge/ccc-bridge.md +12 -12
- package/src/knowledge/qmd-registry.md +5 -5
- package/src/shared/health-check.md +5 -5
- package/src/shared/references/description-guard-protocol.md +100 -0
- package/src/shared/references/output-contract-schema.md +1 -1
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
- package/src/shared/scripts/skf-build-change-manifest.py +420 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
- package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
- package/src/shared/scripts/skf-description-guard.py +359 -0
- package/src/shared/scripts/skf-detect-language.py +2 -2
- package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
- package/src/shared/scripts/skf-detect-tools.py +97 -8
- package/src/shared/scripts/skf-detect-workspaces.py +1 -1
- package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
- package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
- package/src/shared/scripts/skf-hash-content.py +284 -0
- package/src/shared/scripts/skf-load-provenance.py +295 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +45 -1
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
- package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
- package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
- package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
- package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
- package/src/skf-audit-skill/SKILL.md +66 -15
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
- package/src/skf-audit-skill/customize.toml +49 -0
- package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-audit-skill/references/init.md +305 -0
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -16
- package/src/skf-brief-skill/SKILL.md +48 -18
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
- package/src/skf-brief-skill/customize.toml +44 -0
- package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
- package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
- package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
- package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
- package/src/skf-brief-skill/references/headless-args.md +9 -9
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
- package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
- package/src/skf-brief-skill/references/version-resolution.md +2 -2
- package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
- package/src/skf-create-skill/SKILL.md +25 -19
- package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
- package/src/skf-create-skill/assets/skill-sections.md +5 -5
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
- package/src/skf-create-skill/customize.toml +35 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
- package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
- package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
- package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
- package/src/skf-create-skill/references/extraction-patterns.md +8 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +17 -9
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
- package/src/skf-create-stack-skill/SKILL.md +76 -17
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +46 -0
- package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
- package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
- package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
- package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
- package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
- package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
- package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
- package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
- package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
- package/src/skf-drop-skill/SKILL.md +84 -12
- package/src/skf-drop-skill/customize.toml +57 -0
- package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
- package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
- package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
- package/src/skf-export-skill/SKILL.md +85 -16
- package/src/skf-export-skill/assets/managed-section-format.md +3 -3
- package/src/skf-export-skill/assets/snippet-format.md +2 -2
- package/src/skf-export-skill/customize.toml +49 -0
- package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +18 -12
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +21 -51
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +30 -6
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +116 -91
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +14 -22
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
- package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
- package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
- package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
- package/src/skf-test-skill/references/health-check.md +14 -0
- package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
- package/src/skf-test-skill/references/migration-section-rules.md +4 -2
- package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
- package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
- package/src/skf-test-skill/references/scoring-rules.md +8 -6
- package/src/skf-test-skill/references/source-access-protocol.md +7 -5
- package/src/skf-test-skill/scripts/compute-score.py +88 -17
- package/src/skf-test-skill/templates/test-report-template.md +13 -13
- package/src/skf-update-skill/SKILL.md +23 -14
- package/src/skf-update-skill/customize.toml +44 -0
- package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
- package/src/skf-update-skill/references/health-check.md +32 -0
- package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
- package/src/skf-update-skill/references/manual-section-rules.md +4 -0
- package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
- package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
- package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
- package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
- package/src/skf-update-skill/references/report.md +214 -0
- package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
- package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
- package/src/skf-verify-stack/SKILL.md +89 -17
- package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
- package/src/skf-verify-stack/customize.toml +50 -0
- package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
- package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
- package/src/skf-verify-stack/references/init.md +166 -0
- package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
- package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
- package/tools/validate-docs-drift.js +1 -1
- package/src/skf-audit-skill/steps-c/step-01-init.md +0 -221
- package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
- package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
- package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
- package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
- package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
- package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
# {outputFile} resolves from the activation-stored {outputFolderPath}
|
|
3
|
+
# variable (set in SKILL.md On Activation §4 from output_folder config +
|
|
4
|
+
# customize override).
|
|
5
|
+
outputFile: '{outputFolderPath}/refined-architecture-{project_name}.md'
|
|
6
|
+
nextStepFile: 'health-check.md'
|
|
4
7
|
---
|
|
5
8
|
|
|
9
|
+
<!-- Config: communicate in {communication_language}. Render the user-facing summary in {document_output_language}. -->
|
|
10
|
+
|
|
6
11
|
# Step 6: Present Report
|
|
7
12
|
|
|
8
13
|
## STEP GOAL:
|
|
@@ -17,8 +22,6 @@ Present the complete refinement summary to the user. Display counts of gaps fill
|
|
|
17
22
|
|
|
18
23
|
## MANDATORY SEQUENCE
|
|
19
24
|
|
|
20
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
21
|
-
|
|
22
25
|
### 1. Load Refined Document
|
|
23
26
|
|
|
24
27
|
Read the `{outputFile}` to have all data available for presentation.
|
|
@@ -81,7 +84,13 @@ Re-run **[RA] Refine Architecture** anytime after updating your skills or archit
|
|
|
81
84
|
|
|
82
85
|
### Result Contract
|
|
83
86
|
|
|
84
|
-
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{
|
|
87
|
+
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{outputFolderPath}/refine-architecture-result-{timestamp}.json` (reuse the activation-stored `{timestamp}`, resolution to seconds) and a copy at `{outputFolderPath}/refine-architecture-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include the refined architecture doc path in `outputs`; include `gap_count`, `issue_count`, and `improvement_count` in `summary`. On any write failure: HALT (exit code 4, `halt_reason: "write-failed"`) and emit the error envelope.
|
|
88
|
+
|
|
89
|
+
When `{headless_mode}` is true, also emit the single-line envelope on **stdout** before chaining to step 7 (matches the SKILL.md "Result Contract (Headless)" shape):
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
SKF_REFINE_ARCHITECTURE_RESULT_JSON: {"status":"success","refined_path":"{outputFile}","gap_count":{gap_count},"issue_count":{issue_count},"improvement_count":{improvement_count},"exit_code":0,"halt_reason":null}
|
|
93
|
+
```
|
|
85
94
|
|
|
86
95
|
Then load, read the full file, and execute `{nextStepFile}` — the health-check step is the true terminal step of this workflow.
|
|
87
96
|
|
|
@@ -9,6 +9,16 @@ description: Rename a skill across all its versions — transactional copy-verif
|
|
|
9
9
|
|
|
10
10
|
Renames a skill across all its versions with transactional safety — copy to the new name, verify all references updated, delete the old name only after verification succeeds. Rebuilds platform context files to reference the new name. The agentskills.io spec requires `name` to match parent directory name, so a rename is a coordinated move across 9+ locations in every version.
|
|
11
11
|
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
15
|
+
- `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.
|
|
16
|
+
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
17
|
+
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
18
|
+
- `{skill-name}` resolves to the skill directory's basename.
|
|
19
|
+
- **Module-level path exception:** paths starting with `knowledge/` or `shared/` resolve from the SKF module root, not the skill root — install layout puts both at `{project-root}/_bmad/skf/`. The `versionPathsKnowledge: 'knowledge/version-paths.md'` frontmatter scalar in stage files uses this convention; same for `shared/health-check.md` chained from the terminal step.
|
|
20
|
+
- **Cross-skill data coupling:** `references/execute.md` reads `skf-export-skill/assets/managed-section-format.md` for the IDE→context-file mapping table and the skill-index rebuild rules when re-keying context files post-rename. Rename-skill assumes that asset is present at install time and that its semantics are stable across the two skills' versions.
|
|
21
|
+
|
|
12
22
|
## Role
|
|
13
23
|
|
|
14
24
|
You are Ferris in Management mode — a precision surgeon who operates on the entire skill group atomically. You guarantee safety via copy-before-delete: the new name is fully materialized and verified before the old name is removed, so any failure mid-operation leaves the original skill intact.
|
|
@@ -20,39 +30,99 @@ These rules apply to every step in this workflow:
|
|
|
20
30
|
- Never delete the old skill directories until the new name has been fully materialized and verified
|
|
21
31
|
- Never proceed past a verification failure — roll back (delete new directories) and halt
|
|
22
32
|
- Never allow a rename to collide with an existing skill name
|
|
23
|
-
- Read each step file completely before taking any action
|
|
24
|
-
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
25
33
|
- Only load one step file at a time — never preload future steps
|
|
26
34
|
- If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
|
|
27
35
|
- Always communicate in `{communication_language}`
|
|
36
|
+
- At any interactive prompt, the inputs `cancel`, `exit`, `[X]`, `q`, or `:q` exit cleanly with exit code 6 (`halt_reason: "user-cancelled"`)
|
|
28
37
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
29
38
|
|
|
30
39
|
## Stages
|
|
31
40
|
|
|
32
41
|
| # | Step | File | Auto-proceed |
|
|
33
42
|
|---|------|------|--------------|
|
|
34
|
-
| 1 | Select & Validate |
|
|
35
|
-
| 2 | Execute Rename |
|
|
36
|
-
| 3 | Report |
|
|
37
|
-
| 4 | Workflow Health Check |
|
|
43
|
+
| 1 | Select & Validate | references/select.md | No (confirm) |
|
|
44
|
+
| 2 | Execute Rename | references/execute.md | No (confirm) |
|
|
45
|
+
| 3 | Report | references/report.md | Yes |
|
|
46
|
+
| 4 | Workflow Health Check | references/health-check.md | Yes |
|
|
38
47
|
|
|
39
48
|
## Invocation Contract
|
|
40
49
|
|
|
41
50
|
| Aspect | Detail |
|
|
42
51
|
|--------|--------|
|
|
43
52
|
| **Inputs** | old_name [required], new_name [required] |
|
|
44
|
-
| **
|
|
45
|
-
| **
|
|
46
|
-
| **
|
|
53
|
+
| **Flags** | `--headless` / `-H` (auto-resolve all gates); `--dry-run` (run selection + validation + display the §8 confirmation block, then exit with `status="dry-run"` — no copy, no manifest re-key, no delete). Useful for verifying the rename plan before the irreversible §8 (delete old) section. |
|
|
54
|
+
| **Gates** | step 1: Input Gate [use args] x2, Confirm Gate [Y] |
|
|
55
|
+
| **Outputs** | Renamed skill directories, updated manifest, updated context files, `{new_name}/rename-skill-result-{timestamp}.json` and `{new_name}/rename-skill-result-latest.json` |
|
|
56
|
+
| **Concurrency** | Two simultaneous rename runs against the same `old_name` would corrupt state mid-copy. select.md §4b acquires a PID-file lock at `{forge_data_folder}/{old_name}/.skf-rename.lock` once `old_name` is resolved; live-PID collisions HALT with `halt_reason: "halted-for-concurrent-run"`. Stale locks (dead PID) are cleared silently with a warning. The lock is released by the terminal health-check step (step 4) and by every documented halt path. |
|
|
57
|
+
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true. The §6 source-authority warning HALTs by default in headless when `source_authority="official"`; set `force_source_authority_in_headless = "true"` in `customize.toml` to auto-acknowledge and proceed (the override is recorded in `headless_decisions[]`). |
|
|
58
|
+
| **Exit codes** | See "Exit Codes" below |
|
|
59
|
+
|
|
60
|
+
## Exit Codes
|
|
61
|
+
|
|
62
|
+
Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
|
|
63
|
+
|
|
64
|
+
| Code | Meaning | Raised by |
|
|
65
|
+
| ---- | -------------------- | -------------------------------------------------------------------------------------------- |
|
|
66
|
+
| 0 | success | step 4 (terminal) |
|
|
67
|
+
| 2 | input-missing / input-invalid | step 1 §4/§5 (headless missing `old_name`/`new_name` arg) → `input-missing`; new name fails kebab-case / length / same-as-old → `input-invalid` |
|
|
68
|
+
| 3 | resolution-failure | step 1 §2 (manifest is malformed JSON); step 1 §3 (no skills found anywhere) |
|
|
69
|
+
| 4 | write-failure | On-Activation §3 pre-flight write probe (skills_output_folder / forge_data_folder unwritable); step 2 §1 (copy); step 2 §3 (file content update); step 2 §6 (manifest write); step 2 §7 (context-file rewrite) |
|
|
70
|
+
| 5 | state-conflict | step 1 §5 (name-collision check fails: target name already in use); step 1 §6 (source-authority="official" headless without `force_source_authority_in_headless`); concurrency lock collision (`halted-for-concurrent-run`) |
|
|
71
|
+
| 6 | user-cancelled | step 1 §6 (source-authority warning [N]); step 1 §8 confirmation gate `[N]`; any prompt that accepted `cancel`/`exit`/`:q` |
|
|
72
|
+
|
|
73
|
+
## Result Contract (Headless)
|
|
74
|
+
|
|
75
|
+
When `{headless_mode}` is true, step 3 emits a single-line JSON envelope on **stdout** before chaining to step 4, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
SKF_RENAME_SKILL_RESULT_JSON: {"status":"success|error|dry-run","old_name":"…|null","new_name":"…|null","versions_renamed":[],"manifest_rekeyed":false,"context_files_updated":[],"exit_code":0,"halt_reason":null}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
`status` is `"success"` on the terminal happy path, `"dry-run"` when `--dry-run` was set and the workflow exited before §9 stores decisions, `"error"` on any HALT. `halt_reason` is one of: `null` (success), `"input-missing"`, `"input-invalid"`, `"manifest-corrupt"`, `"nothing-to-rename"`, `"name-collision"`, `"source-authority-blocked"`, `"halted-for-concurrent-run"`, `"copy-failed"`, `"verify-failed"`, `"manifest-write-failed"`, `"context-rebuild-failed"`, `"write-failed"`, `"user-cancelled"`. `exit_code` matches the table above.
|
|
47
82
|
|
|
48
83
|
## On Activation
|
|
49
84
|
|
|
50
85
|
1. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
|
|
51
86
|
- `project_name`, `output_folder`, `user_name`, `communication_language`, `document_output_language`
|
|
52
87
|
- `skills_output_folder`, `forge_data_folder`, `sidecar_path`
|
|
53
|
-
- `snippet_skill_root_override` (optional string) — when set, the context-file rebuild in step
|
|
88
|
+
- `snippet_skill_root_override` (optional string) — when set, the context-file rebuild in step 2 preserves any snippet `root:` prefix that matches the override instead of rewriting it to the target IDE's skill root. See `skf-export-skill/assets/managed-section-format.md` for full semantics.
|
|
54
89
|
- Generate and store `timestamp` as `YYYYMMDD-HHmmss` format. This value is fixed for the entire workflow run.
|
|
55
90
|
|
|
56
|
-
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml
|
|
91
|
+
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in `{sidecar_path}/preferences.yaml`. Default: false.
|
|
92
|
+
|
|
93
|
+
3. **Resolve workflow customization.** Run:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
|
97
|
+
--skill {skill-root} --key workflow
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
|
|
101
|
+
|
|
102
|
+
- `{skill-root}/customize.toml` — bundled defaults
|
|
103
|
+
- `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
|
|
104
|
+
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
105
|
+
|
|
106
|
+
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 scalar.
|
|
107
|
+
|
|
108
|
+
Apply the 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, the bundled default applies:
|
|
109
|
+
|
|
110
|
+
- `{forceSourceAuthorityInHeadless}` ← `workflow.force_source_authority_in_headless` (empty or non-`"true"` = HALT in headless on `"official"` source-authority)
|
|
111
|
+
- `{unknownIdeDefaultContextFile}` ← `workflow.unknown_ide_default_context_file` if non-empty, else `AGENTS.md`
|
|
112
|
+
- `{unknownIdeDefaultSkillRoot}` ← `workflow.unknown_ide_default_skill_root` if non-empty, else `.agents/skills/`
|
|
113
|
+
|
|
114
|
+
Stash all three as workflow-context variables. Stage files reference them directly — no conditional at the usage site.
|
|
115
|
+
|
|
116
|
+
4. **Pre-flight write probe.** Verify both `{skills_output_folder}` and `{forge_data_folder}` are writable. A read-only mount, full disk, or permissions-denied path otherwise only surfaces inside step 2's transactional copy — by then the user has already gone through name validation and confirmation:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
for dir in "{skills_output_folder}" "{forge_data_folder}"; do
|
|
120
|
+
mkdir -p "$dir" && \
|
|
121
|
+
printf 'probe' > "$dir/.skf-write-probe" && \
|
|
122
|
+
rm "$dir/.skf-write-probe"
|
|
123
|
+
done
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`). In headless mode, emit the error envelope per **Result Contract (Headless)** with `old_name: null` and `new_name: null` (neither is resolved yet at activation time).
|
|
57
127
|
|
|
58
|
-
|
|
128
|
+
5. Load, read the full file, and then execute `references/select.md` to begin the workflow.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-rename-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 (audit-log emit,
|
|
13
|
+
# ticket-reference enforcement) that must precede any rename 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
|
+
# (rename-policy reminders, public-name-stability rules, audit guardrails).
|
|
25
|
+
# Overrides append.
|
|
26
|
+
#
|
|
27
|
+
# Each entry is either:
|
|
28
|
+
# - a literal sentence, e.g. "Renames of skills tagged `published` require approval."
|
|
29
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
30
|
+
# "file:{project-root}/docs/rename-policy.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 safety + default scalars ---
|
|
38
|
+
#
|
|
39
|
+
# Auto-acknowledge the source-authority="official" warning in headless mode.
|
|
40
|
+
# Empty string = HALT in headless when source_authority is "official"
|
|
41
|
+
# (the safe default — local renames diverge from any registry-published
|
|
42
|
+
# name). Set to "true" to silently proceed and record the override in the
|
|
43
|
+
# headless decision trail.
|
|
44
|
+
|
|
45
|
+
force_source_authority_in_headless = ""
|
|
46
|
+
|
|
47
|
+
# Fallback IDE → context-file mapping for unknown IDEs in `config.yaml.ides`.
|
|
48
|
+
# Empty string = use bundled defaults (AGENTS.md / .agents/skills/).
|
|
49
|
+
# Used by execute.md §7 when rebuilding context files.
|
|
50
|
+
|
|
51
|
+
unknown_ide_default_context_file = ""
|
|
52
|
+
unknown_ide_default_skill_root = ""
|
|
@@ -1,19 +1,48 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'report.md'
|
|
3
3
|
versionPathsKnowledge: 'knowledge/version-paths.md'
|
|
4
4
|
managedSectionLogic: 'skf-export-skill/assets/managed-section-format.md'
|
|
5
|
+
# Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in
|
|
6
|
+
# order (installed SKF module path first, src/ dev-checkout fallback);
|
|
7
|
+
# first existing path wins. §3 + §6 use it for crash-safe file rewrites
|
|
8
|
+
# (stage to .skf-tmp, fsync, rename) — letting the LLM write directly
|
|
9
|
+
# risks half-written artifacts on process kill or disk-full mid-write.
|
|
10
|
+
# HALT if neither candidate exists.
|
|
11
|
+
atomicWriteProbeOrder:
|
|
12
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
13
|
+
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
14
|
+
# Resolve `{updateActiveSymlinkHelper}` similarly. §4 uses it to
|
|
15
|
+
# atomically repair the `active` symlink with `flock` and the Windows
|
|
16
|
+
# junction fallback — `rm + ln -s` would race against concurrent readers
|
|
17
|
+
# and silently break on Windows.
|
|
18
|
+
updateActiveSymlinkProbeOrder:
|
|
19
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-update-active-symlink.py'
|
|
20
|
+
- '{project-root}/src/shared/scripts/skf-update-active-symlink.py'
|
|
21
|
+
# Resolve `{manifestOpsHelper}` similarly. §6 uses the `rename` action
|
|
22
|
+
# for atomic re-key (preserves `active_version`, `versions` map, all
|
|
23
|
+
# fields, then writes via temp + rename).
|
|
24
|
+
manifestOpsProbeOrder:
|
|
25
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-manifest-ops.py'
|
|
26
|
+
- '{project-root}/src/shared/scripts/skf-manifest-ops.py'
|
|
27
|
+
# Resolve `{rebuildManagedSectionsHelper}` similarly. §7.7 uses the
|
|
28
|
+
# `replace` action for the surgical between-marker rewrite.
|
|
29
|
+
rebuildManagedSectionsProbeOrder:
|
|
30
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-rebuild-managed-sections.py'
|
|
31
|
+
- '{project-root}/src/shared/scripts/skf-rebuild-managed-sections.py'
|
|
5
32
|
---
|
|
6
33
|
|
|
34
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
35
|
+
|
|
7
36
|
# Step 2: Execute Rename (Transactional)
|
|
8
37
|
|
|
9
38
|
## STEP GOAL:
|
|
10
39
|
|
|
11
|
-
Execute the rename decisions recorded in step
|
|
40
|
+
Execute the rename decisions recorded in step 1 as a transaction. Copy the old `{skill_group}` and `{forge_group}` to the new name, rename inner directories, rewrite every in-file reference, verify no trace of the old name remains inside the new location, update the export manifest, rebuild platform context files, and only then delete the old directories. Any failure before the final delete rolls back by removing the new directories — the old skill remains intact.
|
|
12
41
|
|
|
13
42
|
## Rules
|
|
14
43
|
|
|
15
44
|
- Execute sections strictly in order — each section depends on the previous one
|
|
16
|
-
- Do not re-prompt the user — decisions were made in step
|
|
45
|
+
- Do not re-prompt the user — decisions were made in step 1
|
|
17
46
|
- Do not delete anything from old directories before section 8
|
|
18
47
|
- Do not proceed past a verification failure in section 5
|
|
19
48
|
- Report each section's outcome as it completes
|
|
@@ -22,15 +51,26 @@ Execute the rename decisions recorded in step-01 as a transaction. Copy the old
|
|
|
22
51
|
|
|
23
52
|
**CRITICAL:** This is transactional. After section 1 (copy), the old skill is untouched. If any section between 2 and 7 fails, delete `{new_skill_group}` and `{new_forge_group}`, report the failure, and halt — the old skill remains intact. Only section 8 (delete old) makes the operation irreversible. Do not skip, reorder, or improvise.
|
|
24
53
|
|
|
25
|
-
### 0. Re-read Version-Paths Knowledge
|
|
54
|
+
### 0. Re-read Version-Paths Knowledge + Resolve Helpers
|
|
26
55
|
|
|
27
56
|
Read `{versionPathsKnowledge}` again and confirm the templates (`{skill_package}`, `{skill_group}`, `{forge_version}`, `{forge_group}`) and the Rename section. Also read `{managedSectionLogic}` for the managed-section format template and the skill index rebuild rules that will be reused in section 7.
|
|
28
57
|
|
|
58
|
+
**Resolve helpers** in parallel — these are independent file-existence checks that batch into one tool-call message:
|
|
59
|
+
|
|
60
|
+
- `{atomicWriteHelper}` ← first existing path in `{atomicWriteProbeOrder}` (used in §3, §6 for crash-safe writes)
|
|
61
|
+
- `{updateActiveSymlinkHelper}` ← first existing path in `{updateActiveSymlinkProbeOrder}` (used in §4 for atomic symlink repair)
|
|
62
|
+
- `{manifestOpsHelper}` ← first existing path in `{manifestOpsProbeOrder}` (used in §6 for the manifest re-key)
|
|
63
|
+
- `{rebuildManagedSectionsHelper}` ← first existing path in `{rebuildManagedSectionsProbeOrder}` (used in §7.7 for between-marker swap)
|
|
64
|
+
|
|
65
|
+
If any helper has no existing candidate, release the lock and HALT (exit code 4, `halt_reason: "write-failed"`) — the rename's safety guarantees depend on these helpers and a fall-through to LLM-driven writes would silently regress atomicity.
|
|
66
|
+
|
|
67
|
+
**Lock release contract:** every halt path in this step ends with `rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"` before exiting. The terminal health-check (step 4) is the success-path release.
|
|
68
|
+
|
|
29
69
|
### 1. Copy skill_group and forge_group
|
|
30
70
|
|
|
31
|
-
**Precondition:** Both `{new_skill_group}` and `{new_forge_group}` must NOT exist (step
|
|
71
|
+
**Precondition:** Both `{new_skill_group}` and `{new_forge_group}` must NOT exist (step 1 validated this in the collision check, but verify again before copying).
|
|
32
72
|
|
|
33
|
-
1. If `{new_skill_group}` or `{new_forge_group}` exists on disk, halt with: "**Collision detected at execution time.** `{new_skill_group}` or `{new_forge_group}` now exists on disk — it did not exist during step
|
|
73
|
+
1. If `{new_skill_group}` or `{new_forge_group}` exists on disk, halt with: "**Collision detected at execution time.** `{new_skill_group}` or `{new_forge_group}` now exists on disk — it did not exist during step 1 selection. Aborting before any files are touched."
|
|
34
74
|
|
|
35
75
|
2. Copy `{old_skill_group}` to `{new_skill_group}` recursively:
|
|
36
76
|
- Preserve file permissions, timestamps, and symlinks
|
|
@@ -64,17 +104,24 @@ Report: "**Renamed {count} inner directories** to `{new_name}/`."
|
|
|
64
104
|
|
|
65
105
|
For each version `v` in `affected_versions`, operate on the files inside `{new_skill_group}/{v}/{new_name}/` (the freshly renamed inner directory) and `{new_forge_group}/{v}/`:
|
|
66
106
|
|
|
107
|
+
**Write semantics (apply to 3a / 3b / 3c / 3d):** Compute the new file content in memory (LLM judgment work), then pipe it to `{atomicWriteHelper} write <target>` so the rewrite is staged in `<target>.skf-tmp`, fsync'd, and atomically renamed into place. A process kill or disk-full event mid-rewrite leaves the original file intact — no half-written artifacts.
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
echo "{new_content}" | python3 {atomicWriteHelper} write "{target_path}"
|
|
111
|
+
```
|
|
112
|
+
|
|
67
113
|
**3a. SKILL.md frontmatter:**
|
|
68
114
|
|
|
69
115
|
- Path: `{new_skill_group}/{v}/{new_name}/SKILL.md`
|
|
70
116
|
- In the YAML frontmatter (between the leading `---` markers), replace the `name:` field value from `{old_name}` to `{new_name}`
|
|
71
117
|
- Only replace within the frontmatter block — do not substitute matches inside the body text
|
|
118
|
+
- Pipe via `{atomicWriteHelper} write` per the write semantics above
|
|
72
119
|
- If the file is missing, record it in `section3_warnings` and continue
|
|
73
120
|
|
|
74
121
|
**3b. metadata.json:**
|
|
75
122
|
|
|
76
123
|
- Path: `{new_skill_group}/{v}/{new_name}/metadata.json`
|
|
77
|
-
- Parse the JSON, set `name` = `{new_name}`, write back preserving formatting
|
|
124
|
+
- Parse the JSON, set `name` = `{new_name}`, write back preserving formatting via `{atomicWriteHelper} write`
|
|
78
125
|
- If the file is missing, record it in `section3_warnings` and continue
|
|
79
126
|
|
|
80
127
|
**3c. context-snippet.md:**
|
|
@@ -85,36 +132,43 @@ For each version `v` in `affected_versions`, operate on the files inside `{new_s
|
|
|
85
132
|
- Example: `root: .windsurf/skills/{old_name}/` → `root: .windsurf/skills/{new_name}/`
|
|
86
133
|
- Example: `root: skills/{old_name}/` → `root: skills/{new_name}/`
|
|
87
134
|
- Legacy pre-fix form `root: skills/{old_name}/active/{old_name}/` → `root: skills/{new_name}/` (normalize to flat form during rename)
|
|
135
|
+
- Pipe via `{atomicWriteHelper} write` per the write semantics above
|
|
88
136
|
- If the file is missing, record it in `section3_warnings` and continue
|
|
89
137
|
|
|
90
138
|
**3d. provenance-map.json:**
|
|
91
139
|
|
|
92
140
|
- Path: `{new_forge_group}/{v}/provenance-map.json`
|
|
93
|
-
- Parse JSON, set `skill_name` = `{new_name}`, write back
|
|
141
|
+
- Parse JSON, set `skill_name` = `{new_name}`, write back via `{atomicWriteHelper} write`
|
|
94
142
|
- If the file is missing (some versions may not have a provenance map), record it in `section3_warnings` and continue
|
|
95
143
|
|
|
96
144
|
**Rollback on any update failure (not just a missing file):**
|
|
97
145
|
|
|
98
146
|
- `rm -rf {new_skill_group}` and `rm -rf {new_forge_group}`
|
|
99
|
-
-
|
|
147
|
+
- Release the lock: `rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"`
|
|
148
|
+
- Halt with: "**File update failed** at `{path}`: {error}. Rolled back both new directories. Old skill is intact." HALT (exit code 4, `halt_reason: "write-failed"`). In headless, emit the error envelope.
|
|
100
149
|
|
|
101
150
|
Report: "**Updated file contents** across {affected_versions_count} version(s): SKILL.md, metadata.json, context-snippet.md, provenance-map.json."
|
|
102
151
|
|
|
103
152
|
### 4. Fix the `active` Symlink in the New Location
|
|
104
153
|
|
|
105
|
-
Recreate or repair the `active` symlink in `{new_skill_group}
|
|
154
|
+
Recreate or repair the `active` symlink in `{new_skill_group}` via `{updateActiveSymlinkHelper}` — the helper holds an `flock` on `{new_skill_group}/active.lock`, surfaces a clear error on Windows non-dev-mode (no silent fallback), and uses the `ln -sfn tmp && mv -Tf tmp link` pattern to make the flip atomic against concurrent readers.
|
|
106
155
|
|
|
107
|
-
1. Inspect `{old_skill_group}/active` to determine the target version (the value the symlink points to — typically just the version string, not an absolute path)
|
|
108
|
-
2.
|
|
109
|
-
- If the copy in section 1 preserved it correctly and it points to the same version string → leave it as-is
|
|
110
|
-
- If it exists but points somewhere invalid (e.g., an absolute path back into the old location) → remove and recreate it
|
|
111
|
-
- If it is missing (some copy tools do not preserve symlinks) → create it
|
|
112
|
-
3. The symlink target should be a relative path: the version string alone (e.g., `0.6.0`), so that `{new_skill_group}/active/{new_name}/` resolves correctly
|
|
156
|
+
1. Inspect `{old_skill_group}/active` to determine the target version (the value the symlink points to — typically just the version string, not an absolute path). If `{old_skill_group}/active` does not exist, skip this section — there is no symlink to repair.
|
|
157
|
+
2. Invoke:
|
|
113
158
|
|
|
114
|
-
|
|
159
|
+
```bash
|
|
160
|
+
python3 {updateActiveSymlinkHelper} flip-link \
|
|
161
|
+
--link {new_skill_group}/active \
|
|
162
|
+
--target {target_version}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
3. The helper handles all four cases (missing, present-and-correct, present-and-stale, present-and-invalid) uniformly via atomic replace.
|
|
166
|
+
|
|
167
|
+
**Rollback on helper non-zero exit:**
|
|
115
168
|
|
|
116
169
|
- `rm -rf {new_skill_group}` and `rm -rf {new_forge_group}`
|
|
117
|
-
-
|
|
170
|
+
- Release the lock: `rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"`
|
|
171
|
+
- Halt with: "**Failed to repair `active` symlink** in `{new_skill_group}`: {captured stderr}. Rolled back both new directories. Old skill is intact." HALT (exit code 4, `halt_reason: "write-failed"`). In headless, emit the error envelope.
|
|
118
172
|
|
|
119
173
|
### 5. Verify — No Trace of `{old_name}` Inside the New Location
|
|
120
174
|
|
|
@@ -136,13 +190,14 @@ Also check the directory listing itself:
|
|
|
136
190
|
**On hard failure (any structural reference to `{old_name}` remains):**
|
|
137
191
|
|
|
138
192
|
- `rm -rf {new_skill_group}` and `rm -rf {new_forge_group}`
|
|
139
|
-
-
|
|
193
|
+
- Release the lock: `rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"`
|
|
194
|
+
- Halt with: "**Verification failed.** `{old_name}` still appears in: {list of paths}. Rolled back both new directories. Old skill is intact." HALT (exit code 5, `halt_reason: "verify-failed"`). In headless, emit the error envelope.
|
|
140
195
|
|
|
141
196
|
Report: "**Verified** — no structural references to `{old_name}` remain inside the new location across {affected_versions_count} version(s). {if verification_warnings is non-empty: 'Informational body-text mentions retained in SKILL.md: {list}.'}"
|
|
142
197
|
|
|
143
198
|
### 6. Update Export Manifest
|
|
144
199
|
|
|
145
|
-
**If `manifest_exists = false` (step
|
|
200
|
+
**If `manifest_exists = false` (step 1 recorded no manifest on disk):**
|
|
146
201
|
|
|
147
202
|
Skip this section entirely. Set `manifest_updated = false` and `manifest_backup = null`. There is no manifest to re-key — the skill was never exported. Section 7 will find no platform context files to rebuild either (no manifest means no prior export, so no `<!-- SKF:BEGIN -->` markers exist), and any platform file that happens to be present will be left alone by the section 2 marker check.
|
|
148
203
|
|
|
@@ -150,19 +205,21 @@ Report: "**Manifest update skipped** — no `.export-manifest.json` on disk. The
|
|
|
150
205
|
|
|
151
206
|
**If `manifest_exists = true`:**
|
|
152
207
|
|
|
153
|
-
1.
|
|
154
|
-
2. **
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
5. Write the updated manifest back to `{skills_output_folder}/.export-manifest.json`
|
|
208
|
+
1. **Hold a deep copy in memory** as `manifest_backup` — required for rollback in this section and section 7 on failure. Read `{skills_output_folder}/.export-manifest.json` once and stash the parsed object.
|
|
209
|
+
2. **Re-key via the helper.** If the manifest contains `exports.{old_name}`, invoke:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
python3 {manifestOpsHelper} {skills_output_folder} rename {old_name} {new_name}
|
|
213
|
+
```
|
|
160
214
|
|
|
161
|
-
|
|
215
|
+
The helper preserves `active_version`, `versions` map, and all fields, then writes the manifest atomically via temp + rename. If the manifest does NOT contain `exports.{old_name}` (the skill was on disk but never exported), skip the invocation — the manifest has nothing to change.
|
|
162
216
|
|
|
163
|
-
|
|
217
|
+
**Rollback on helper non-zero exit:**
|
|
218
|
+
|
|
219
|
+
- Restore the manifest from `manifest_backup` via `{atomicWriteHelper} write {skills_output_folder}/.export-manifest.json` (re-pipe the JSON-serialized backup)
|
|
164
220
|
- `rm -rf {new_skill_group}` and `rm -rf {new_forge_group}`
|
|
165
|
-
-
|
|
221
|
+
- Release the lock: `rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"`
|
|
222
|
+
- Halt with: "**Manifest update failed:** {captured stderr}. Restored manifest from backup and rolled back new directories. Old skill is intact." HALT (exit code 4, `halt_reason: "manifest-write-failed"`). In headless, emit the error envelope.
|
|
166
223
|
|
|
167
224
|
Set context flag `manifest_updated = true`.
|
|
168
225
|
|
|
@@ -170,78 +227,16 @@ Report: "**Manifest updated** — re-keyed `exports.{old_name}` → `exports.{ne
|
|
|
170
227
|
|
|
171
228
|
### 7. Rebuild Context Files
|
|
172
229
|
|
|
173
|
-
Load
|
|
174
|
-
|
|
175
|
-
**Resolve `target_context_files`** using the canonical mapping table in `{managedSectionLogic}`:
|
|
176
|
-
|
|
177
|
-
1. For each entry in `config.yaml.ides`, look up its `context_file` and `skill_root` from the mapping table
|
|
178
|
-
2. For any entry not found in the table, default to AGENTS.md / `.agents/skills/` and emit a warning: "Unknown IDE '{value}' in config.yaml — defaulting to AGENTS.md"
|
|
179
|
-
3. Deduplicate by `context_file` — when multiple IDEs map to the same context file, use the first configured IDE's `skill_root`
|
|
180
|
-
4. If `config.yaml.ides` is absent or the mapping yields an empty list, fall back to `[{context_file: "AGENTS.md", skill_root: ".agents/skills/"}]` and emit a note: "No IDEs configured in config.yaml — defaulting to AGENTS.md"
|
|
181
|
-
|
|
182
|
-
Store the result as `target_context_files` for this section.
|
|
183
|
-
|
|
184
|
-
For each entry in `target_context_files`:
|
|
185
|
-
|
|
186
|
-
1. **Resolve target file** at `{context_file}`.
|
|
187
|
-
|
|
188
|
-
2. **Read the current file.**
|
|
189
|
-
- If the file does not exist, skip this context file (nothing to rebuild — the file will be re-created next time export-skill runs)
|
|
190
|
-
- If the file exists but contains no `<!-- SKF:BEGIN -->` marker, skip this context file (no managed section to rewrite)
|
|
191
|
-
- If the file contains `<!-- SKF:BEGIN -->` but no matching `<!-- SKF:END -->`, record the error against that context file and continue to the next entry — do not halt the entire rename on a malformed context file
|
|
192
|
-
|
|
193
|
-
3. **Build the exported skill set (version-aware, deprecated-excluded)** using the same logic as export-skill step-04 section 4b and the snippet resolution logic from section 4c:
|
|
194
|
-
- Read the manifest's `exports` object (already updated in section 6, so `{new_name}` is present and `{old_name}` is absent)
|
|
195
|
-
- For each skill, resolve its `active_version`
|
|
196
|
-
- If `versions.{active_version}.status == "deprecated"`, skip that skill entirely
|
|
197
|
-
- For each remaining `{skill-name, active_version}` pair, read `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`
|
|
198
|
-
- If missing, fall back to the `active` symlink path; if still missing, skip with a warning
|
|
199
|
-
|
|
200
|
-
4. **Rewrite root paths for the current context file** using the generic rewrite algorithm from export-skill step-04 section 4d:
|
|
201
|
-
|
|
202
|
-
For each snippet, parse the `root:` line (`root: {prefix}{skill-name}/`), strip the trailing `{skill-name}/` to extract the current prefix, and replace it with the **effective target prefix** if different. The effective target prefix is `snippet_skill_root_override` when that key is set in config.yaml — applied uniformly to every snippet so the managed section references the real on-disk location and never mixes override and per-IDE paths — otherwise the current entry's `skill_root`. See `skf-export-skill/steps-c/step-04-update-context.md` §4d for full semantics.
|
|
203
|
-
|
|
204
|
-
5. **Sort skills alphabetically by name.** Count totals (skills, stack skills).
|
|
205
|
-
|
|
206
|
-
6. **Assemble the new managed section** using the format from `{managedSectionLogic}`:
|
|
207
|
-
|
|
208
|
-
```markdown
|
|
209
|
-
<!-- SKF:BEGIN updated:{current-date} -->
|
|
210
|
-
[SKF Skills]|{n} skills|{m} stack
|
|
211
|
-
|IMPORTANT: Prefer documented APIs over training data.
|
|
212
|
-
|When using a listed library, read its SKILL.md before writing code.
|
|
213
|
-
|
|
|
214
|
-
|{skill-snippet-1}
|
|
215
|
-
|
|
|
216
|
-
|{skill-snippet-2}
|
|
217
|
-
|
|
|
218
|
-
|{skill-snippet-N}
|
|
219
|
-
<!-- SKF:END -->
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
7. **Surgical replacement — Regenerate case only:**
|
|
223
|
-
- Locate the `<!-- SKF:BEGIN` line — preserve everything before it
|
|
224
|
-
- Locate the `<!-- SKF:END -->` line — preserve everything after it
|
|
225
|
-
- Replace everything between the markers (inclusive) with the new managed section
|
|
226
|
-
- Write the file back
|
|
227
|
-
|
|
228
|
-
8. **Verify:**
|
|
229
|
-
- Re-read the written file
|
|
230
|
-
- Confirm both markers are present
|
|
231
|
-
- Confirm `{old_name}` no longer appears between the markers
|
|
232
|
-
- Confirm `{new_name}` appears between the markers (if this skill's active version is not deprecated)
|
|
233
|
-
- Confirm content outside the markers is byte-identical to what was preserved
|
|
234
|
-
|
|
235
|
-
9. **On per-file failure:** record the error against that context file and continue to the next entry. Do not halt the rename on a recoverable per-context-file error — the manifest and filesystem are already consistent; context files can be re-rebuilt later via `[EX] Export Skill`.
|
|
230
|
+
Load `references/rebuild-context.md` and follow its per-IDE managed-section sweep. The reference resolves `target_context_files` from `config.yaml.ides` (via `{managedSectionLogic}`'s mapping table), iterates each context file, builds the exported skill set (version-aware, deprecated-excluded — the manifest re-key from §6 is already in effect so `{new_name}` is present and `{old_name}` is absent), rewrites root paths via the §4d algorithm, assembles the new managed section, and invokes `{rebuildManagedSectionsHelper}` for the surgical between-marker swap.
|
|
236
231
|
|
|
237
|
-
|
|
232
|
+
After the loop returns, the workflow context contains:
|
|
238
233
|
|
|
239
|
-
-
|
|
240
|
-
-
|
|
234
|
+
- `context_files_updated` — list of files successfully rewritten
|
|
235
|
+
- `context_files_failed` — list of any that failed (per-file failures do not halt the rename — the manifest and filesystem are already canonical state, so context files can be re-rebuilt later via `[EX] Export Skill`)
|
|
241
236
|
|
|
242
|
-
Report
|
|
237
|
+
Report per the reference's after-loop block, then proceed to §8.
|
|
243
238
|
|
|
244
|
-
**Note:**
|
|
239
|
+
**Note:** §7 failures do not trigger a rollback. Platform context files are derived artifacts; the manifest and on-disk skill directories are the canonical state.
|
|
245
240
|
|
|
246
241
|
### 8. Delete Old Directories (Point of No Return)
|
|
247
242
|
|
|
@@ -272,7 +267,7 @@ Report: "**Deleted old directories:** `{old_skill_group}` and `{old_forge_group}
|
|
|
272
267
|
|
|
273
268
|
### 9. Store Results in Context
|
|
274
269
|
|
|
275
|
-
Store the following for step
|
|
270
|
+
Store the following for step 3:
|
|
276
271
|
|
|
277
272
|
- `old_name` — the previous skill name
|
|
278
273
|
- `new_name` — the new skill name
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Note: `shared/health-check.md` resolves relative to the SKF module root
|
|
3
|
+
# ({project-root}/_bmad/skf/ when installed, {project-root}/src/ during
|
|
4
|
+
# development), NOT relative to this step file.
|
|
5
|
+
nextStepFile: 'shared/health-check.md'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
9
|
+
|
|
10
|
+
# Step 4: Workflow Health Check
|
|
11
|
+
|
|
12
|
+
## STEP GOAL:
|
|
13
|
+
|
|
14
|
+
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of rename-skill — after the shared health check completes, the workflow is fully done.
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
- No user-facing reports, file writes, or result contracts in this step — those belong in step 3
|
|
19
|
+
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
20
|
+
- Do not attempt any other action between loading this step and executing `{nextStepFile}`
|
|
21
|
+
|
|
22
|
+
## MANDATORY SEQUENCE
|
|
23
|
+
|
|
24
|
+
1. **Release the rename lock.** Delete `{forge_data_folder}/{old_name}/.skf-rename.lock` if it still exists (the lock is acquired in select.md §4b and released here as the terminal cleanup). A no-op when `old_name` was never resolved or the lock was already removed by an earlier halt path.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
rm -f "{forge_data_folder}/{old_name}/.skf-rename.lock"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
2. Load `{nextStepFile}`, read it fully, then execute it.
|