bmad-module-skill-forge 2.2.0 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +49 -49
- package/docs/404.md +10 -8
- package/docs/_data/pinned.yaml +22 -13
- package/docs/_internal/STABILITY.md +58 -35
- package/docs/agents.md +39 -53
- package/docs/architecture.md +65 -51
- package/docs/bmad-synergy.md +53 -51
- package/docs/campaign.md +127 -75
- package/docs/concepts.md +34 -28
- package/docs/examples.md +70 -68
- package/docs/forge-auto.md +34 -31
- package/docs/getting-started.md +118 -57
- package/docs/how-it-works.md +25 -21
- package/docs/index.md +15 -15
- package/docs/skill-model.md +70 -59
- package/docs/troubleshooting.md +143 -18
- package/docs/verifying-a-skill.md +87 -57
- package/docs/why-skf.md +24 -22
- package/docs/workflows.md +274 -110
- package/package.json +18 -10
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/agentskills-spec.md +2 -0
- package/src/knowledge/ccc-bridge.md +40 -24
- package/src/knowledge/confidence-tiers.md +9 -5
- package/src/knowledge/overview.md +3 -3
- package/src/knowledge/progressive-capability.md +8 -8
- package/src/knowledge/provenance-tracking.md +9 -5
- package/src/knowledge/qmd-registry.md +3 -3
- package/src/knowledge/skf-knowledge-index.csv +2 -2
- package/src/knowledge/skill-lifecycle.md +18 -11
- package/src/knowledge/split-body-strategy.md +0 -3
- package/src/knowledge/tool-resolution.md +4 -2
- package/src/knowledge/version-paths.md +101 -15
- package/src/module-help.csv +3 -3
- package/src/module.yaml +10 -0
- package/src/shared/data/ast-grep-recipes.yaml +608 -0
- package/src/shared/data/ide-context-files.json +30 -0
- package/src/shared/health-check.md +31 -59
- package/src/shared/references/description-guard-protocol.md +12 -9
- package/src/shared/references/feasibility-report-schema.md +19 -13
- package/src/shared/references/headless-gate-convention.md +55 -3
- package/src/shared/references/output-contract-schema.md +19 -8
- package/src/shared/references/pipeline-contracts.md +94 -29
- package/src/shared/references/tessl-review.md +77 -0
- package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
- package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
- package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
- package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
- package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
- package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
- package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
- package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
- package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
- package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
- package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
- package/src/shared/scripts/skf-atomic-write.py +233 -64
- package/src/shared/scripts/skf-build-change-manifest.py +2753 -28
- package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
- package/src/shared/scripts/skf-check-unit-records.py +184 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
- package/src/shared/scripts/skf-classify-changed-files.py +772 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +267 -105
- package/src/shared/scripts/skf-count-imports.py +1867 -0
- package/src/shared/scripts/skf-count-tokens.py +1 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +21 -3
- package/src/shared/scripts/skf-description-guard.py +99 -11
- package/src/shared/scripts/skf-detect-docs.py +694 -2
- package/src/shared/scripts/skf-detect-language.py +486 -107
- package/src/shared/scripts/skf-detect-registry.py +887 -0
- package/src/shared/scripts/skf-detect-scripts-assets.py +197 -55
- package/src/shared/scripts/skf-detect-tools.py +209 -27
- package/src/shared/scripts/skf-detect-workspaces.py +506 -30
- package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
- package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
- package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
- package/src/shared/scripts/skf-extract-public-api.py +5247 -96
- package/src/shared/scripts/skf-extraction-inventory.py +1280 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +664 -0
- package/src/shared/scripts/skf-fetch-temporal.py +674 -0
- package/src/shared/scripts/skf-find-cycles.py +97 -29
- package/src/shared/scripts/skf-find-test-report.py +476 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +469 -205
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +700 -0
- package/src/shared/scripts/skf-hash-content.py +180 -20
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +161 -27
- package/src/shared/scripts/skf-manifest-ops.py +1 -1
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
- package/src/shared/scripts/skf-merge-doc-urls.py +143 -20
- package/src/shared/scripts/skf-names-present.py +221 -0
- package/src/shared/scripts/skf-pair-intersect.py +119 -28
- package/src/shared/scripts/skf-parse-gaps.py +1384 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-preflight.py +176 -28
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +64 -8
- package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
- package/src/shared/scripts/skf-quick-batch.py +774 -0
- package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
- package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
- package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
- package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
- package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
- package/src/shared/scripts/skf-resolve-authoritative-files.py +155 -14
- package/src/shared/scripts/skf-resolve-package.py +523 -106
- package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
- package/src/shared/scripts/skf-run-lock.py +577 -0
- package/src/shared/scripts/skf-scan-manifests.py +998 -57
- package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
- package/src/shared/scripts/skf-severity-classify.py +712 -108
- package/src/shared/scripts/skf-shape-detect.py +298 -204
- package/src/shared/scripts/skf-shard-body.py +9 -8
- package/src/shared/scripts/skf-skill-inventory.py +2412 -89
- package/src/shared/scripts/skf-skills-module.py +472 -0
- package/src/shared/scripts/skf-source-tree.py +1796 -0
- package/src/shared/scripts/skf-structural-diff.py +787 -121
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +120 -67
- package/src/shared/scripts/skf-update-run-state.py +624 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
- package/src/shared/scripts/skf-validate-brief-schema.py +23 -2
- package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
- package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
- package/src/shared/scripts/skf-validate-output.py +712 -64
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +116 -10
- package/src/shared/scripts/skf-verify-provenance-completeness.py +3945 -152
- package/src/shared/scripts/skf-write-skill-brief.py +406 -25
- package/src/shared/tool-requirements.yaml +201 -0
- package/src/skf-analyze-source/SKILL.md +41 -36
- package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
- package/src/skf-analyze-source/customize.toml +36 -24
- package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
- package/src/skf-analyze-source/references/continue.md +2 -13
- package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
- package/src/skf-analyze-source/references/generate-briefs.md +121 -55
- package/src/skf-analyze-source/references/headless-contract.md +42 -15
- package/src/skf-analyze-source/references/identify-units.md +96 -110
- package/src/skf-analyze-source/references/init.md +73 -71
- package/src/skf-analyze-source/references/map-and-detect.md +123 -105
- package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
- package/src/skf-analyze-source/references/recommend.md +51 -70
- package/src/skf-analyze-source/references/scan-project.md +60 -84
- package/src/skf-analyze-source/references/scan-root.md +39 -0
- package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
- package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
- package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
- package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
- package/src/skf-audit-skill/SKILL.md +43 -51
- package/src/skf-audit-skill/assets/drift-report-template.md +28 -3
- package/src/skf-audit-skill/customize.toml +41 -20
- package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
- package/src/skf-audit-skill/references/doc-drift.md +141 -0
- package/src/skf-audit-skill/references/headless-contract.md +29 -0
- package/src/skf-audit-skill/references/health-check.md +2 -0
- package/src/skf-audit-skill/references/init.md +149 -210
- package/src/skf-audit-skill/references/re-index.md +103 -110
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +34 -25
- package/src/skf-audit-skill/references/severity-classify.md +79 -65
- package/src/skf-audit-skill/references/severity-rules.md +15 -6
- package/src/skf-audit-skill/references/structural-diff.md +80 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +712 -0
- package/src/skf-brief-skill/SKILL.md +37 -26
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +18 -25
- package/src/skf-brief-skill/assets/skill-brief-schema.md +30 -23
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +144 -127
- package/src/skf-brief-skill/references/confirm-brief.md +11 -9
- package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
- package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
- package/src/skf-brief-skill/references/gather-intent.md +87 -182
- package/src/skf-brief-skill/references/headless-args.md +84 -16
- package/src/skf-brief-skill/references/health-check.md +1 -1
- package/src/skf-brief-skill/references/invocation-contract.md +18 -13
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
- package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
- package/src/skf-brief-skill/references/scope-definition.md +123 -47
- package/src/skf-brief-skill/references/step-auto-brief.md +26 -100
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +7 -10
- package/src/skf-brief-skill/references/write-brief.md +66 -57
- package/src/skf-campaign/SKILL.md +31 -34
- package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
- package/src/skf-campaign/customize.toml +47 -16
- package/src/skf-campaign/references/campaign-contracts.md +39 -29
- package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
- package/src/skf-campaign/references/health-check.md +7 -16
- package/src/skf-campaign/references/step-01-setup.md +46 -84
- package/src/skf-campaign/references/step-02-strategy.md +31 -30
- package/src/skf-campaign/references/step-03-pins.md +26 -18
- package/src/skf-campaign/references/step-04-provenance.md +24 -23
- package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
- package/src/skf-campaign/references/step-06-batch.md +41 -34
- package/src/skf-campaign/references/step-07-capstone.md +40 -25
- package/src/skf-campaign/references/step-08-verify.md +28 -29
- package/src/skf-campaign/references/step-09-refine.md +29 -30
- package/src/skf-campaign/references/step-10-export.md +48 -36
- package/src/skf-campaign/references/step-11-maintenance.md +31 -34
- package/src/skf-campaign/references/step-resume.md +37 -68
- package/src/skf-campaign/scripts/campaign-deps.py +57 -18
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
- package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
- package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
- package/src/skf-campaign/scripts/campaign-report.py +204 -37
- package/src/skf-campaign/scripts/campaign-state.py +1128 -0
- package/src/skf-campaign/scripts/campaign-status.py +10 -74
- package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
- package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
- package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
- package/src/skf-campaign/templates/campaign-report-template.md +5 -1
- package/src/skf-campaign/templates/kickoff-template.md +0 -14
- package/src/skf-create-skill/SKILL.md +27 -20
- package/src/skf-create-skill/assets/compile-assembly-rules.md +11 -8
- package/src/skf-create-skill/assets/skill-sections.md +21 -11
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +36 -58
- package/src/skf-create-skill/references/batch-mode.md +81 -0
- package/src/skf-create-skill/references/ccc-index-check.md +27 -0
- package/src/skf-create-skill/references/compile.md +119 -70
- package/src/skf-create-skill/references/component-extraction.md +113 -91
- package/src/skf-create-skill/references/enrich.md +41 -23
- package/src/skf-create-skill/references/entry-points-by-hand.md +37 -0
- package/src/skf-create-skill/references/extract.md +204 -162
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +11 -11
- package/src/skf-create-skill/references/extraction-patterns.md +588 -201
- package/src/skf-create-skill/references/generate-artifacts.md +145 -93
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +53 -36
- package/src/skf-create-skill/references/relabel-rule.md +12 -0
- package/src/skf-create-skill/references/report.md +37 -57
- package/src/skf-create-skill/references/source-resolution-protocols.md +58 -169
- package/src/skf-create-skill/references/step-auto-shard.md +20 -93
- package/src/skf-create-skill/references/step-doc-rot.md +44 -60
- package/src/skf-create-skill/references/step-doc-sources.md +28 -19
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
- package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
- package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
- package/src/skf-create-skill/references/validate.md +173 -99
- package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
- package/src/skf-create-stack-skill/SKILL.md +29 -56
- package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
- package/src/skf-create-stack-skill/customize.toml +23 -12
- package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
- package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
- package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
- package/src/skf-create-stack-skill/references/generate-output.md +138 -128
- package/src/skf-create-stack-skill/references/init.md +90 -32
- package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
- package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
- package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
- package/src/skf-create-stack-skill/references/report.md +39 -33
- package/src/skf-create-stack-skill/references/validate.md +20 -39
- package/src/skf-drop-skill/SKILL.md +28 -51
- package/src/skf-drop-skill/customize.toml +44 -30
- package/src/skf-drop-skill/references/execute.md +83 -146
- package/src/skf-drop-skill/references/health-check.md +2 -0
- package/src/skf-drop-skill/references/invocation-contract.md +64 -0
- package/src/skf-drop-skill/references/report.md +46 -30
- package/src/skf-drop-skill/references/select.md +122 -124
- package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
- package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
- package/src/skf-export-skill/SKILL.md +40 -62
- package/src/skf-export-skill/assets/managed-section-format.md +14 -50
- package/src/skf-export-skill/assets/snippet-format.md +3 -1
- package/src/skf-export-skill/customize.toml +42 -13
- package/src/skf-export-skill/references/generate-snippet.md +54 -46
- package/src/skf-export-skill/references/health-check.md +2 -0
- package/src/skf-export-skill/references/invocation-contract.md +15 -0
- package/src/skf-export-skill/references/load-skill.md +88 -62
- package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
- package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
- package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
- package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
- package/src/skf-export-skill/references/package.md +15 -73
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
- package/src/skf-export-skill/references/result-envelope.md +31 -16
- package/src/skf-export-skill/references/summary.md +41 -17
- package/src/skf-export-skill/references/token-report.md +4 -12
- package/src/skf-export-skill/references/update-context.md +118 -237
- package/src/skf-forger/SKILL.md +61 -37
- package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
- package/src/skf-forger/customize.toml +43 -0
- package/src/skf-forger/references/pipeline-mode.md +73 -18
- package/src/skf-forger/scripts/forge-status.py +299 -0
- package/src/skf-forger/scripts/parse-pipeline.py +322 -54
- package/src/skf-forger/scripts/pipeline-gate.py +428 -0
- package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
- package/src/skf-quick-skill/SKILL.md +54 -53
- package/src/skf-quick-skill/assets/skill-template.md +4 -2
- package/src/skf-quick-skill/customize.toml +51 -20
- package/src/skf-quick-skill/references/batch-mode.md +74 -21
- package/src/skf-quick-skill/references/compile.md +30 -31
- package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
- package/src/skf-quick-skill/references/finalize.md +69 -18
- package/src/skf-quick-skill/references/halt-contract.md +41 -29
- package/src/skf-quick-skill/references/health-check.md +5 -3
- package/src/skf-quick-skill/references/quick-extract.md +114 -45
- package/src/skf-quick-skill/references/registry-resolution.md +9 -64
- package/src/skf-quick-skill/references/resolve-target.md +116 -66
- package/src/skf-quick-skill/references/write-and-validate.md +79 -40
- package/src/skf-refine-architecture/SKILL.md +43 -53
- package/src/skf-refine-architecture/customize.toml +49 -20
- package/src/skf-refine-architecture/references/compile.md +97 -54
- package/src/skf-refine-architecture/references/exit-codes.md +30 -0
- package/src/skf-refine-architecture/references/finding-storage.md +21 -0
- package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
- package/src/skf-refine-architecture/references/improvements.md +14 -20
- package/src/skf-refine-architecture/references/init.md +98 -57
- package/src/skf-refine-architecture/references/issue-detection.md +32 -39
- package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
- package/src/skf-refine-architecture/references/report.md +65 -54
- package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
- package/src/skf-rename-skill/SKILL.md +19 -54
- package/src/skf-rename-skill/customize.toml +32 -26
- package/src/skf-rename-skill/references/execute.md +230 -184
- package/src/skf-rename-skill/references/exit-codes.md +7 -7
- package/src/skf-rename-skill/references/health-check.md +1 -7
- package/src/skf-rename-skill/references/invocation-contract.md +25 -0
- package/src/skf-rename-skill/references/report.md +63 -52
- package/src/skf-rename-skill/references/select.md +197 -115
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
- package/src/skf-setup/SKILL.md +26 -26
- package/src/skf-setup/customize.toml +14 -10
- package/src/skf-setup/references/auto-index.md +50 -63
- package/src/skf-setup/references/ccc-index.md +29 -90
- package/src/skf-setup/references/detect-and-tier.md +58 -67
- package/src/skf-setup/references/health-check.md +2 -0
- package/src/skf-setup/references/invocation-contract.md +14 -0
- package/src/skf-setup/references/report.md +43 -166
- package/src/skf-setup/references/tier-rules.md +5 -5
- package/src/skf-setup/references/write-config.md +34 -57
- package/src/skf-test-skill/SKILL.md +17 -57
- package/src/skf-test-skill/assets/output-section-formats.md +33 -34
- package/src/skf-test-skill/customize.toml +27 -13
- package/src/skf-test-skill/references/coherence-check.md +134 -62
- package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
- package/src/skf-test-skill/references/coverage-check.md +209 -264
- package/src/skf-test-skill/references/detect-mode.md +5 -5
- package/src/skf-test-skill/references/external-validators.md +94 -82
- package/src/skf-test-skill/references/health-check.md +6 -7
- package/src/skf-test-skill/references/init.md +164 -91
- package/src/skf-test-skill/references/invocation-contract.md +66 -0
- package/src/skf-test-skill/references/migration-section-rules.md +5 -2
- package/src/skf-test-skill/references/report.md +164 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +42 -155
- package/src/skf-test-skill/references/source-access-protocol.md +18 -94
- package/src/skf-test-skill/references/step-hard-gate.md +51 -33
- package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
- package/src/skf-test-skill/scripts/build-result-context.py +380 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
- package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
- package/src/skf-test-skill/scripts/compute-score.py +223 -45
- package/src/skf-test-skill/scripts/gap-ledger.py +1666 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +1198 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +547 -79
- package/src/skf-test-skill/scripts/score-signatures.py +479 -0
- package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +133 -56
- package/src/skf-test-skill/templates/test-report-template.md +21 -15
- package/src/skf-update-skill/SKILL.md +38 -25
- package/src/skf-update-skill/customize.toml +27 -12
- package/src/skf-update-skill/references/detect-changes.md +253 -223
- package/src/skf-update-skill/references/gap-driven.md +336 -0
- package/src/skf-update-skill/references/health-check.md +31 -5
- package/src/skf-update-skill/references/init.md +254 -84
- package/src/skf-update-skill/references/invocation-contract.md +12 -0
- package/src/skf-update-skill/references/manual-section-rules.md +6 -23
- package/src/skf-update-skill/references/merge.md +182 -49
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +102 -35
- package/src/skf-update-skill/references/write.md +357 -155
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +183 -46
- package/src/skf-verify-stack/SKILL.md +23 -42
- package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
- package/src/skf-verify-stack/customize.toml +55 -22
- package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
- package/src/skf-verify-stack/references/coverage.md +67 -64
- package/src/skf-verify-stack/references/exit-codes.md +21 -8
- package/src/skf-verify-stack/references/init.md +107 -62
- package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
- package/src/skf-verify-stack/references/integrations.md +106 -65
- package/src/skf-verify-stack/references/report.md +59 -42
- package/src/skf-verify-stack/references/requirements.md +32 -9
- package/src/skf-verify-stack/references/synthesize.md +53 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
- package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
- package/tools/cli/commands/install.js +11 -4
- package/tools/cli/commands/status.js +15 -3
- package/tools/cli/commands/update.js +11 -4
- package/tools/cli/lib/tool-check.js +320 -0
- package/tools/cli/lib/version-check.js +22 -9
- package/tools/cli/skf-cli.js +4 -1
- package/.gitattributes +0 -16
- package/.nvmrc +0 -1
- package/docs/_internal/RELEASING.md +0 -679
- package/release-audits/v1.0.0-launch-audit.md +0 -728
- package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
- package/src/skf-campaign/manifest.yaml +0 -15
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
- package/src/skf-create-skill/references/ecosystem-check.md +0 -74
- package/src/skf-drop-skill/references/headless-contract.md +0 -18
- package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
- package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
- package/src/skf-update-skill/references/validate.md +0 -124
- package/tools/validate-docs-drift.js +0 -233
- package/tools/validate-docs-links.js +0 -665
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'execute.md'
|
|
3
|
-
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# path wins. §7 uses its `affected-versions` action to enumerate the versions a
|
|
7
|
-
# rename must touch — the union of manifest version keys and on-disk version
|
|
8
|
-
# dirs, deduped and semver-sorted (numeric, so 0.10.0 precedes 0.9.0). Unlike
|
|
9
|
-
# execute.md's write helpers this one is not atomicity-critical: if neither path
|
|
10
|
-
# resolves, §7 falls back to computing the union in the prompt.
|
|
3
|
+
# §1 resolves each probe order below (installed SKF module path first,
|
|
4
|
+
# src/ dev-checkout fallback; the first existing path wins).
|
|
5
|
+
# {manifestOpsHelper}: the §2 `read` and the §7 `affected-versions`.
|
|
11
6
|
manifestOpsProbeOrder:
|
|
12
7
|
- '{project-root}/_bmad/skf/shared/scripts/skf-manifest-ops.py'
|
|
13
8
|
- '{project-root}/src/shared/scripts/skf-manifest-ops.py'
|
|
14
|
-
#
|
|
15
|
-
# (installed SKF module path first, src/ dev-checkout fallback). §3 uses it to
|
|
16
|
-
# enumerate the rename candidates: the union of manifest `exports` and on-disk
|
|
17
|
-
# skill directories, each with its version list and active version — computing
|
|
18
|
-
# that union/count in the prompt has one correct answer per input. §3 falls
|
|
19
|
-
# back to an in-prompt scan if neither path resolves.
|
|
9
|
+
# {skillInventoryHelper}: the §3 listing, §4a `--rename-check`, §6 `resolve`.
|
|
20
10
|
skillInventoryProbeOrder:
|
|
21
11
|
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
22
12
|
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
23
|
-
#
|
|
24
|
-
# uses it for the format / length / identity / collision checks (one correct
|
|
25
|
-
# answer per (name, filesystem, manifest) state) and the interrupted-rename
|
|
26
|
-
# recovery fingerprint; §5 falls back to the same checks in-prompt if Python is
|
|
27
|
-
# unavailable.
|
|
13
|
+
# {renameNameValidator}: this skill's own new-name gate, run in §5.
|
|
28
14
|
renameNameValidator: 'scripts/skf-validate-rename-name.py'
|
|
15
|
+
# {runLockHelper} and {emitEnvelopeHelper}: §4b and the halt procedure.
|
|
16
|
+
runLockProbeOrder:
|
|
17
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-run-lock.py'
|
|
18
|
+
- '{project-root}/src/shared/scripts/skf-run-lock.py'
|
|
19
|
+
emitEnvelopeProbeOrder:
|
|
20
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
|
|
21
|
+
- '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
|
|
29
22
|
---
|
|
30
23
|
|
|
31
24
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -38,58 +31,85 @@ Identify the skill the user wants to rename, validate the new name against the a
|
|
|
38
31
|
|
|
39
32
|
## Rules
|
|
40
33
|
|
|
41
|
-
- Focus only on selection, validation, and confirmation
|
|
34
|
+
- Focus only on selection, validation, and confirmation: this step writes only the run's own files (its run folder and run lock), never the manifest or a skill's files
|
|
42
35
|
- Do not proceed without explicit user confirmation at the final gate
|
|
43
36
|
- Do not accept a new name that fails validation (kebab-case, length, uniqueness)
|
|
44
37
|
- Present the list of affected versions clearly so the user understands the scope
|
|
45
38
|
|
|
46
|
-
**
|
|
39
|
+
**Halt procedure.** Every HALT below names, in parentheses, its exit code, its `halt_reason` and the phase its `emit-halt` reports (see `references/exit-codes.md`), and runs these, in order, before it stops:
|
|
47
40
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
```
|
|
41
|
+
1. Once §4b has bound `{lock_owner}`, release the run lock (a release never removes a lock another run holds). From `{project-root}`:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
uv run {runLockHelper} release --lock "{forge_data_folder}/.skf-rename-{old_name}.lock" --owner "{lock_owner}"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
When it exits non-zero or prints no JSON, tell the user in one line that the lock file stays, and add `"warnings": ["run-lock-not-released: {forge_data_folder}/.skf-rename-{old_name}.lock"]` to the payload below.
|
|
48
|
+
|
|
49
|
+
2. In `{headless_mode}`, pass the halt to the shared emitter, which prints its envelope on **stderr**. Write each string as JSON (escape `"`, `\` and control characters, and write every path with `/`), and pass `--run-dir "{run_dir}"` once §1 has bound it, even when the folder could not be created:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-rename-skill --run-dir "{run_dir}" --target stderr <<'SKF_HALT'
|
|
53
|
+
{"phase": "<phase>", "halt_reason": "<halt_reason>", "reason": "<the message the halt displays>", "path": "<the path the halt names; leave the key out when it names none>", "old_name": <"{old_name}", or null before §4 binds it>, "new_name": <"{new_name}", or null before §5 binds it>}
|
|
54
|
+
SKF_HALT
|
|
55
|
+
```
|
|
51
56
|
|
|
52
|
-
|
|
57
|
+
Display the `SKF_RENAME_SKILL_RESULT_JSON:` line it prints verbatim. When it exits non-zero and its `message` names the payload, fix the payload once and run it again. Only when `{emitEnvelopeHelper}` is missing, or the emitter still fails or prints no line, display the halt's message alone.
|
|
58
|
+
|
|
59
|
+
The halt leaves `{run_dir}` in place.
|
|
53
60
|
|
|
54
61
|
## MANDATORY SEQUENCE
|
|
55
62
|
|
|
56
|
-
### 1.
|
|
63
|
+
### 1. Start the Run
|
|
57
64
|
|
|
58
|
-
|
|
65
|
+
Resolve, as one batch of file-existence checks, `{runLockHelper}` ← first existing path in `{runLockProbeOrder}`, `{emitEnvelopeHelper}` ← first existing path in `{emitEnvelopeProbeOrder}`, `{manifestOpsHelper}` ← first existing path in `{manifestOpsProbeOrder}` and `{skillInventoryHelper}` ← first existing path in `{skillInventoryProbeOrder}`; all four stay bound for the rest of the run. From `{project-root}`, take the run id:
|
|
59
66
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
```bash
|
|
68
|
+
uv run {runLockHelper} run-id
|
|
69
|
+
```
|
|
63
70
|
|
|
64
|
-
|
|
71
|
+
Bind `{run_id}` ← its `run_id` and `{run_dir}` ← `{project-root}/_bmad-output/.skf-run/skf-rename-skill-{run_id}`. Then create the run folder and probe the folders the run writes, so a read-only mount or a full disk stops the run here rather than at step 2's copy:
|
|
65
72
|
|
|
66
|
-
|
|
73
|
+
```bash
|
|
74
|
+
for dir in "{run_dir}" "{skills_output_folder}" "{forge_data_folder}"; do
|
|
75
|
+
{ mkdir -p "$dir" && printf 'probe' > "$dir/.skf-write-probe" && rm "$dir/.skf-write-probe"; } \
|
|
76
|
+
|| { echo "not writable: $dir" >&2; exit 1; }
|
|
77
|
+
done
|
|
78
|
+
```
|
|
67
79
|
|
|
68
|
-
|
|
80
|
+
- When a helper has no existing candidate, or `run-id` exits non-zero or prints no JSON: HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:start-run`) with "**Rename Skill cannot start:** {the missing helper (`skf-run-lock.py`, `skf-emit-result-envelope.py`, `skf-manifest-ops.py` or `skf-skill-inventory.py`), or the helper's error}. Nothing was changed. Re-install SKF, then re-run." With no run id yet, its `emit-halt` leaves out `--run-dir "{run_dir}"`.
|
|
81
|
+
- When the loop exits non-zero: HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:write-probe`, with the folder its stderr names as `path`) with "**Cannot write to `{that folder}`.** Nothing was changed. Check that the path exists as a folder you can write to and that the disk has free space, then re-run."
|
|
69
82
|
|
|
70
|
-
|
|
83
|
+
Once the loop passes and `{customization_resolver_unavailable}` is set (SKILL.md On Activation step 3), record the reason in the run sink: write `customization_resolver_unavailable: {customization_resolver_unavailable}` to `{run_dir}/resolver-warning.txt` with a file write, never `echo` (the reason can hold quotes or `$( )`), then run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "$(cat "{run_dir}/resolver-warning.txt")"`, and delete that file (`rm -f "{run_dir}/resolver-warning.txt"`), so the report step's `rmdir` still finds the folder empty.
|
|
71
84
|
|
|
72
|
-
|
|
85
|
+
### 2. Read Export Manifest
|
|
86
|
+
|
|
87
|
+
Read the manifest through `{manifestOpsHelper}`, never by eye: it migrates v1 to v2, normalizes `platforms` to `ides`, and reports a file that does not parse:
|
|
73
88
|
|
|
74
|
-
|
|
89
|
+
```bash
|
|
90
|
+
uv run {manifestOpsHelper} {skills_output_folder} read
|
|
91
|
+
```
|
|
75
92
|
|
|
76
|
-
|
|
93
|
+
- **`status == "error"`** (the file exists but does not parse): halt with "**Export manifest is corrupt** at `{skills_output_folder}/.export-manifest.json`: {error}. Fix or remove the file before renaming." HALT (exit code 3, `halt_reason: "manifest-corrupt"`, `emit-halt` phase `select:read-manifest`, with the manifest as `path`).
|
|
94
|
+
- **`status == "ok"`**: use `result.manifest` (already in the v2 shape) as `manifest` for the rest of this step. Set `manifest_exists = true` when `manifest.exports` has at least one entry, else `false` (a missing file reads back as an empty `exports`). With no entry, §3's on-disk scan is the whole roster: drafted or never-exported skills can still be renamed, and step 2 §6 has no manifest entry to re-key.
|
|
95
|
+
- **No JSON on stdout** (the helper could not run): HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:read-manifest`) with "**Rename Skill cannot read the export manifest:** {the helper's stderr}. Nothing was changed. Re-install SKF, then re-run."
|
|
77
96
|
|
|
78
97
|
### 3. List Available Skills
|
|
79
98
|
|
|
80
|
-
Enumerate every skill available for rename deterministically
|
|
99
|
+
Enumerate every skill available for rename deterministically:
|
|
81
100
|
|
|
82
101
|
```bash
|
|
83
|
-
|
|
102
|
+
uv run {skillInventoryHelper} {skills_output_folder} --forge-data-folder {forge_data_folder}
|
|
84
103
|
```
|
|
85
104
|
|
|
86
|
-
Read the JSON. Each entry in `skills[]` carries `name`, its `versions` array, and `active_version` (the helper unions the manifest `exports` with the on-disk directories and dedupes, so manifest-tracked and orphaned skills both appear). A skill whose `name` is absent from `manifest.exports` is a draft/orphan the rename workflow can still handle
|
|
105
|
+
Read the JSON. Each entry in `skills[]` carries `name`, its `versions` array, and `active_version` (the helper unions the manifest `exports` with the on-disk directories and dedupes, so manifest-tracked and orphaned skills both appear), plus `skf_skill`. List only the entries whose `skf_skill` is true: rename copies and then deletes the whole folder, so a folder SKF did not generate is never offered. A listed skill whose `name` is absent from `manifest.exports` is a draft/orphan the rename workflow can still handle: annotate it "(not in manifest)". The §4a rename check decides whether the skill the user picks can move. Bind `{not_skf_output}` ← `not_skf_output` (folders holding a skill SKF did not generate); when it is non-empty, show one line under the list: "Not offered (not SKF output): {not_skf_output}". When the call prints no JSON, HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:list-skills`) with "**Rename Skill cannot list the skills:** {the helper's stderr}. Nothing was changed. Re-install SKF, then re-run."
|
|
87
106
|
|
|
88
|
-
**If
|
|
107
|
+
**If the list to display is empty** (no `skills[]` entry whose `skf_skill` is true):
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
- When `{old_name_arg}` is set and it is in `{not_skf_output}`, take the §4a refusal for a folder SKF did not generate first, in either mode (exit code 5, `halt_reason: "not-skf-output"`, `emit-halt` phase `select:ownership-check`, with `old_name: "{old_name}"` in its payload).
|
|
110
|
+
- Otherwise halt with "**Rename Skill: nothing to rename.** No skill SKF generated was found in `{skills_output_folder}/`. Run `[CS] Create Skill` first." When `{not_skf_output}` is non-empty, append: "Left untouched (not SKF output): {not_skf_output}." HALT (exit code 3, `halt_reason: "nothing-to-rename"`, `emit-halt` phase `select:list-skills`).
|
|
91
111
|
|
|
92
|
-
Display the list, one line per skill as `{name} ({n} versions, active: {active_version})` (append "(not in manifest)" for orphans):
|
|
112
|
+
Display the list only when §4 asks for the skill, one line per skill as `{name} ({n} versions, active: {active_version})` (append "(not in manifest)" for orphans):
|
|
93
113
|
|
|
94
114
|
```
|
|
95
115
|
**Rename Skill — select target**
|
|
@@ -98,88 +118,118 @@ Available skills:
|
|
|
98
118
|
1. cognee (3 versions, active: 0.6.0)
|
|
99
119
|
2. express (1 version, active: 4.18.0)
|
|
100
120
|
3. legacy-helper (not in manifest)
|
|
121
|
+
|
|
122
|
+
Not offered (not SKF output): my-module-skill
|
|
101
123
|
```
|
|
102
124
|
|
|
103
125
|
### 4. Ask Which Skill
|
|
104
126
|
|
|
127
|
+
**GATE [default: use args]**: When `{old_name_arg}` is set, it is the input below in either mode, and the question is not shown. Otherwise, in `{headless_mode}`, HALT (exit code 2, `halt_reason: "input-missing"`, `emit-halt` phase `select:ask-old-name`): "headless mode requires old_name argument." Otherwise display the §3 list and ask:
|
|
128
|
+
|
|
105
129
|
"**Which skill would you like to rename?**
|
|
106
130
|
Enter the skill name or its number from the list above, or `cancel` / `exit` / `:q` to abort."
|
|
107
131
|
|
|
108
|
-
Wait for user input. Accept either the numeric index or the skill name (exact match)
|
|
132
|
+
Wait for user input. Accept either the numeric index or the skill name (exact match); `{old_name_arg}` must be a name.
|
|
109
133
|
|
|
110
|
-
- If the user enters `cancel`, `exit`, `[X]`, `q`, or `:q`: Display "Cancelled
|
|
111
|
-
- **If the
|
|
134
|
+
- If the user enters `cancel`, `exit`, `[X]`, `q`, or `:q`: Display "Cancelled: no changes were made." and HALT (exit code 6, `halt_reason: "user-cancelled"`, `emit-halt` phase `select:ask-old-name`).
|
|
135
|
+
- **If the input names a folder in `{not_skf_output}`:** take the §4a refusal for a folder SKF did not generate.
|
|
136
|
+
- **If the user's input does not match any listed skill:**
|
|
137
|
+
- **Interactive:** say that it matches no listed skill, display the §3 list and ask again.
|
|
138
|
+
- **Headless (`{headless_mode}` is true):** the supplied `old_name` argument matches no listed skill and there is no further input to re-prompt for. HALT (exit code 2, `halt_reason: "input-invalid"`, `emit-halt` phase `select:ask-old-name`): "headless mode: old_name argument `{supplied value}` does not match any listed skill."
|
|
112
139
|
|
|
113
140
|
Store the selection as `old_name`.
|
|
114
141
|
|
|
142
|
+
### 4a. Ownership Check
|
|
143
|
+
|
|
144
|
+
Rename copies the whole `{skills_output_folder}/{old_name}/` folder and its forge folder, then deletes the old ones, so it only renames a skill SKF generated in the versioned layout. The inventory helper decides that; never decide by hand whether SKF generated a folder. Run:
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
uv run {skillInventoryHelper} "{skills_output_folder}" --skill {old_name} --rename-check --forge-data-folder "{forge_data_folder}"
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
From its `rename_check`, bind `{rename_verdict}` ← `verdict`, `{rename_reason}` ← `reason`, `{rename_detail}` ← `detail`, `{rename_entries}` ← `offending_entries`, `{target_errors}` ← `errors`, `{forge_move}` ← `forge_move`, `{forge_left_in_place}` ← `forge_left_in_place` and `{same_folder}` ← `same_folder`. The helper applies the rules below in order, to the skill folder and, unless both settings name one folder, to its forge folder, and returns the first that refuses. When the call exits non-zero, or its result has no `rename_check` (an installed `skf-skill-inventory.py` older than the flag), refuse with rule 1.
|
|
151
|
+
|
|
152
|
+
When `{rename_verdict}` is not `"ok"`, display the message of the rule that applies and HALT (exit code 5, `halt_reason: "{rename_verdict}"`, `emit-halt` phase `select:ownership-check`, with `old_name: "{old_name}"` in its payload): `not-skf-output`, or `flat-layout` for rule 4. No lock is held yet (§4b takes it), so the halt releases none.
|
|
153
|
+
|
|
154
|
+
1. No verdict (a failed call, or no `rename_check`) → `not-skf-output`: "**SKF cannot check that it generated `{old_name}`:** the rename check of `skf-skill-inventory.py` failed, or the installed one has none. Nothing was changed. Re-install SKF and re-run the rename."
|
|
155
|
+
2. `{rename_reason}` is `foreign`, `reserved-name` or `absent` (no skill SKF generated at `{skills_output_folder}/{old_name}`) → `not-skf-output`: "**`{old_name}` is not SKF output: nothing was changed.** `{skills_output_folder}/{old_name}/` has no SKF marker in its `metadata.json`, so SKF will not rename it. A shared `{skills_output_folder}` is supported: SKF leaves the skills it did not generate alone, so manage `{old_name}` yourself. Only if `{skills_output_folder}` holds a module's own source rather than skills, set `skills_output_folder` in `{project-root}/_bmad/skf/config.yaml` to a folder of its own, move your SKF skills there and re-run `/skf-setup`." When `{target_errors}` is non-empty (for example, the folder is a link), or the reason is `reserved-name` or `absent`, show `{rename_detail}` in place of the marker sentence.
|
|
156
|
+
3. `mixed` → `not-skf-output`: "**`{skills_output_folder}/{old_name}/` also holds entries SKF did not generate:** {rename_entries}. Nothing was changed. Rename moves and then deletes the whole folder, so SKF will not rename it. Move those entries out of the folder and re-run. A version folder with no `metadata.json` can also be one that an interrupted update-skill run left behind; delete it yourself in that case."
|
|
157
|
+
4. `flat-layout` → `flat-layout`: "**`{old_name}` still uses the flat layout.** Nothing was changed. Rename works on the versioned layout only: run `@Ferris TS {old_name}` (or US, AS or EX) once to move it into that layout, then re-run the rename."
|
|
158
|
+
5. `forge-link`, `forge-not-a-folder` or `forge-unreadable` (the forge folder is a link, is not a folder, or cannot be listed) → `not-skf-output`: "**SKF will not move `{forge_data_folder}/{old_name}`:** {rename_detail}. Nothing was changed." For `forge-link`, add: "SKF never moves or deletes through a link: the copy would take the files from where the link points, and removing the old name or rolling back would empty that folder. Replace the link with the folder it points to, then re-run." Otherwise (the path is not a folder, or SKF cannot list it), add: "Rename moves a forge folder only when it is a folder SKF can read. Move that path out of the way or fix its permissions, then re-run."
|
|
159
|
+
6. `forge-mixed` → `not-skf-output`: "**`{forge_data_folder}/{old_name}/` also holds entries SKF did not generate:** {rename_entries}. Nothing was changed. Rename moves and then deletes the whole forge folder, so SKF will not rename it. Move those entries out of the folder and re-run."
|
|
160
|
+
|
|
161
|
+
When no rule applies, `{forge_move}` and `{forge_left_in_place}` come from the helper. Then continue to §4b.
|
|
162
|
+
|
|
115
163
|
### 4b. Concurrency Guard
|
|
116
164
|
|
|
117
|
-
|
|
165
|
+
**Skip this section when `--dry-run` is set:** a dry run writes nothing to the skill, so it takes no lock and never blocks a rename.
|
|
118
166
|
|
|
119
|
-
|
|
167
|
+
Two concurrent rename runs against the same `old_name` would corrupt state mid-copy: one would `rm -rf` the other's freshly-staged new directories, or both would race on the manifest re-key. Take the run lock, a file that names the run holding it. From `{project-root}`, run:
|
|
120
168
|
|
|
121
169
|
```bash
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
HELD_PID=$(head -n1 "$LOCK" 2>/dev/null | awk '{print $1}')
|
|
127
|
-
if [ -n "$HELD_PID" ] && kill -0 "$HELD_PID" 2>/dev/null; then
|
|
128
|
-
echo "skf-rename-skill: another rename is in progress (pid=$HELD_PID, started $(awk 'NR==2' "$LOCK" 2>/dev/null))"
|
|
129
|
-
exit 1
|
|
130
|
-
fi
|
|
131
|
-
echo "skf-rename-skill: clearing stale lock from pid=$HELD_PID"
|
|
132
|
-
fi
|
|
133
|
-
|
|
134
|
-
printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
|
|
170
|
+
uv run {runLockHelper} acquire \
|
|
171
|
+
--lock "{forge_data_folder}/.skf-rename-{old_name}.lock" \
|
|
172
|
+
--owner "rename-skill:{old_name}:{run_id}" \
|
|
173
|
+
--stale-after 60
|
|
135
174
|
```
|
|
136
175
|
|
|
137
|
-
|
|
176
|
+
The lock sits beside the forge folders, never inside one: a skill can have no forge folder, or one SKF did not generate, and a lock inside it would be copied into the new one. The helper creates `{forge_data_folder}` when it is missing.
|
|
177
|
+
|
|
178
|
+
It prints one JSON line. Dispatch on its exit code:
|
|
179
|
+
|
|
180
|
+
- **0** (`acquired` true): bind `{lock_owner}` ← `owner`; every renewal and release passes that value. When `stale_replaced` is not null, a run that stopped without releasing its lock left it: display the helper's `message` and record the warning in the run sink, with `an unnamed owner` for a null `held_by` (a lock file an older SKF version wrote):
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "run-lock-replaced: {stale_replaced.held_by} since {stale_replaced.held_since}"
|
|
184
|
+
```
|
|
138
185
|
|
|
139
|
-
|
|
140
|
-
- HALT (exit code 5, `halt_reason: "halted-for-concurrent-run"`). In `{headless_mode}`, emit the error envelope per SKILL.md "Result Contract (Headless)" with `old_name: "{old_name}"`, `new_name: null`. **No `headless_decisions[]` entry** — this is a hard halt before any gate fires.
|
|
186
|
+
When `record` exits non-zero, show its message and go on: the warning is advisory.
|
|
141
187
|
|
|
142
|
-
**
|
|
188
|
+
- **3** (`acquired` false): another rename of `{old_name}` holds a lock that has not gone stale. Display "**Another rename of `{old_name}` is in progress.** {message}", with the helper's `message`, and HALT (exit code 5, `halt_reason: "halted-for-concurrent-run"`, `emit-halt` phase `select:concurrency-guard`, with the lock file as `path`). This run took no lock, so the halt releases none.
|
|
189
|
+
- **Any other exit, or no JSON:** HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:concurrency-guard`, with the lock file as `path`): "**The run lock could not be taken:** {the `message` the helper printed on stderr}. Nothing was changed." No lock was taken, so none is released.
|
|
143
190
|
|
|
144
|
-
|
|
145
|
-
- The terminal health-check step (step 4) deletes the lock as its final action on the success path.
|
|
146
|
-
- **Every halt from §5 onward — after this run has acquired the lock — must delete it before exiting** (`rm -f "$LOCK"` per halt site): the §5 input/format/collision halts, the §6 source-authority and cancel halts, the §8 cancel and dry-run exits, and execute.md's copy/verify/manifest/write rollbacks. Otherwise the next attempt would see a stale lock from this run.
|
|
191
|
+
A crashed run's lock goes stale 60 minutes after it was taken or last renewed, so step 2 §1 renews it before the copy.
|
|
147
192
|
|
|
148
193
|
### 5. Ask for New Name
|
|
149
194
|
|
|
195
|
+
**GATE [default: use args]**: When `{new_name_arg}` is set, it is the candidate in either mode, and the question is not shown. Otherwise, in `{headless_mode}`, HALT (exit code 2, `halt_reason: "input-missing"`, `emit-halt` phase `select:ask-new-name`): "headless mode requires new_name argument." Otherwise ask:
|
|
196
|
+
|
|
150
197
|
"**What is the new name for this skill?**
|
|
151
198
|
The new name must be kebab-case: lowercase alphanumeric with hyphens, 1-64 characters, matching the regex `^[a-z0-9]([a-z0-9-]*[a-z0-9])?$` (starts and ends with a lowercase letter or digit; a single letter or digit is valid). Or type `cancel` / `exit` / `:q` to abort."
|
|
152
199
|
|
|
153
|
-
Wait for user input. Trim whitespace.
|
|
200
|
+
Wait for user input. Trim whitespace.
|
|
154
201
|
|
|
155
|
-
- If the user enters `cancel`, `exit`, `[X]`, `q`, or `:q`:
|
|
202
|
+
- If the user enters `cancel`, `exit`, `[X]`, `q`, or `:q`: display "Cancelled: no changes were made." and HALT (exit code 6, `halt_reason: "user-cancelled"`, `emit-halt` phase `select:ask-new-name`).
|
|
156
203
|
|
|
157
|
-
**Validate the candidate deterministically
|
|
204
|
+
**Validate the candidate deterministically** with `{renameNameValidator}`, which applies format, length, identity and collision in that order and returns the verdict as JSON:
|
|
158
205
|
|
|
159
206
|
```bash
|
|
160
|
-
|
|
207
|
+
uv run {renameNameValidator} \
|
|
161
208
|
--old-name {old_name} --new-name {candidate} \
|
|
162
209
|
--skills-output-folder {skills_output_folder} \
|
|
163
210
|
--forge-data-folder {forge_data_folder}
|
|
164
211
|
```
|
|
165
212
|
|
|
166
|
-
|
|
213
|
+
When it prints no JSON, HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:validate-new-name`) with "**Rename Skill cannot check the new name:** {the validator's stderr}. Nothing was changed. Re-install SKF, then re-run."
|
|
167
214
|
|
|
168
|
-
Read `valid`, `first_failure`, `checks`, and `
|
|
215
|
+
Read `valid`, `first_failure`, `checks`, `interrupted_rename`, `interrupted_after_rekey` and `leftover_folders`. If `valid` is true, store the input as `new_name` and proceed to §6. When `interrupted_after_rekey` is true, take the recovery halt below the list, in both modes. Otherwise branch on `first_failure`. Interactive: display the message and ask the question above again, also when the candidate came from `{new_name_arg}`. Headless: HALT with the mapped code:
|
|
169
216
|
|
|
170
|
-
- **`format`** → "**Invalid name format.** The new name must be lowercase alphanumeric with hyphens, starting and ending with a lowercase letter or digit. Try again." (headless HALT: exit code 2, `halt_reason: "input-invalid"`)
|
|
171
|
-
- **`length`** → "**Invalid name length.** The new name must be 1-64 characters. Try again." (headless HALT: exit code 2, `halt_reason: "input-invalid"`)
|
|
172
|
-
- **`identity`** → "**The new name is identical to the current name.** Nothing to rename. Try again or abort the workflow." (headless HALT: exit code 2, `halt_reason: "input-invalid"`)
|
|
173
|
-
- **`collision`** → "**Name collision.** `{new-name}` already exists at: {the `path` of each entry in `checks.collision.locations`}. Pick a different name." When `interrupted_rename` is true, append: "This may be a stranded partial rename from an earlier interrupted run
|
|
217
|
+
- **`format`** → "**Invalid name format.** The new name must be lowercase alphanumeric with hyphens, starting and ending with a lowercase letter or digit. Try again." (headless HALT: exit code 2, `halt_reason: "input-invalid"`, `emit-halt` phase `select:validate-new-name`)
|
|
218
|
+
- **`length`** → "**Invalid name length.** The new name must be 1-64 characters. Try again." (headless HALT: exit code 2, `halt_reason: "input-invalid"`, `emit-halt` phase `select:validate-new-name`)
|
|
219
|
+
- **`identity`** → "**The new name is identical to the current name.** Nothing to rename. Try again or abort the workflow." (headless HALT: exit code 2, `halt_reason: "input-invalid"`, `emit-halt` phase `select:validate-new-name`)
|
|
220
|
+
- **`collision`** → "**Name collision.** `{new-name}` already exists at: {the `path` of each entry in `checks.collision.locations`}. Pick a different name." When `checks.collision.locations` has a `reserved` entry, say instead: "**Reserved name.** `improvement-queue` is SKF's own folder in `{forge_data_folder}`. Pick a different name." When `interrupted_rename` is true, append: "This may be a stranded partial rename from an earlier interrupted run: `{new_name}` was staged but `{old_name}` was never removed. Confirm the `{new_name}` directories are not a skill you want to keep, then remove `{skills_output_folder}/{new_name}`, and `{forge_data_folder}/{new_name}` only when it holds a copy of `{old_name}`'s forge folder, and re-run this rename." This gives headless pipelines a named recovery path instead of a dead-end collision halt. (headless HALT: exit code 5, `halt_reason: "name-collision"`, `emit-halt` phase `select:validate-new-name`)
|
|
174
221
|
|
|
175
|
-
**
|
|
222
|
+
**Recovery after the manifest re-key.** When `interrupted_after_rekey` is true, an earlier rename of `{old_name}` to `{new_name}` stopped between its manifest re-key and its delete, and `leftover_folders` lists the old folders it left. Re-asking would invite a third name and a second copy of the skill, so in both modes display "**An earlier rename of `{old_name}` to `{new_name}` stopped after it moved the export manifest to `{new_name}`.** `{new_name}` is the renamed skill, and these old folders are still on disk: {leftover_folders}. Nothing was changed. If `{old_name}` is not a skill you want to keep, finish that rename: delete them with SKF's checked delete, `uv run {skillInventoryHelper} guarded-delete --root "{skills_output_folder}" --root "{forge_data_folder}" {each path in leftover_folders, quoted}`, then run `[EX] Export Skill` to rebuild the context files that may still name `{old_name}`." and HALT (exit code 5, `halt_reason: "name-collision"`, `emit-halt` phase `select:validate-new-name`).
|
|
176
223
|
|
|
177
224
|
### 6. Source Authority Check
|
|
178
225
|
|
|
179
|
-
|
|
180
|
-
|
|
226
|
+
Read `source_authority` from the `metadata.json` of the version `resolve` picks (the manifest's `active_version`, or the `active` link's when the manifest lags it):
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
uv run {skillInventoryHelper} resolve "{skills_output_folder}" --skill {old_name} --forge-data-folder "{forge_data_folder}"
|
|
230
|
+
```
|
|
181
231
|
|
|
182
|
-
|
|
232
|
+
From its `resolve` object bind `{source_metadata}` ← `paths.metadata.path` and read the `source_authority` field of that file (if present). When the call fails or `{source_metadata}` is null, there is no `metadata.json` to read: treat `source_authority` as absent.
|
|
183
233
|
|
|
184
234
|
**If `source_authority == "official"`:**
|
|
185
235
|
|
|
@@ -193,34 +243,41 @@ registry will still get the original name. Rename is a LOCAL operation only —
|
|
|
193
243
|
does not rename anything at the registry.
|
|
194
244
|
```
|
|
195
245
|
|
|
196
|
-
|
|
246
|
+
**GATE [default: HALT in headless]**: When `{acknowledge_official}` is true, `--acknowledge-official` answers this warning for this run in either mode: set `source_authority_override = true` and proceed without asking. Otherwise, in `{headless_mode}`, proceed only when `{forceSourceAuthorityInHeadless}` is true (set `source_authority_override = true`); when it is not, HALT (exit code 5, `halt_reason: "source-authority-blocked"`, `emit-halt` phase `select:source-authority`) with "**`{old_name}` is an official skill** (its `source_authority` is `official`). Nothing was changed. To rename it in a headless run, pass `--acknowledge-official` with the invocation, or set `force_source_authority_in_headless` to `true` in your team or personal customization of skf-rename-skill to approve every headless rename of an official skill." Otherwise ask: "**Continue anyway?** [Y/N] (or `cancel` / `exit` / `:q` to abort)"
|
|
197
247
|
|
|
198
248
|
Wait for response.
|
|
199
|
-
- **If `N`** (or `cancel` / `exit` / `[X]` / `:q`) →
|
|
249
|
+
- **If `N`** (or `cancel` / `exit` / `[X]` / `:q`) → display "**Cancelled.** No changes were made." and HALT (exit code 6, `halt_reason: "user-cancelled"`, `emit-halt` phase `select:source-authority`).
|
|
200
250
|
- **If `Y`** → proceed. Set `source_authority_override = true`.
|
|
201
251
|
|
|
202
|
-
**
|
|
252
|
+
**Record a headless pass.** When `{headless_mode}` is true and the run proceeded past the warning, record the decision in the run sink, with `{source_authority_reason}` ← `--acknowledge-official flag` when `{acknowledge_official}` is true, else `force_source_authority_in_headless override`. From `{project-root}`:
|
|
253
|
+
|
|
254
|
+
```bash
|
|
255
|
+
cat > "{run_dir}/decision.json" <<'SKF_DECISION'
|
|
256
|
+
{"gate": "source-authority", "default_action": "halt", "taken_action": "proceed", "reason": "{source_authority_reason}"}
|
|
257
|
+
SKF_DECISION
|
|
258
|
+
uv run {emitEnvelopeHelper} record --workflow skf-rename-skill --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
When `record` exits non-zero, the decision cannot reach the audit trail: HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:source-authority`) with its message.
|
|
203
262
|
|
|
204
263
|
**If `source_authority` is absent, or any value other than `"official"`:** skip the warning and proceed.
|
|
205
264
|
|
|
206
265
|
### 7. Enumerate Affected Versions
|
|
207
266
|
|
|
208
|
-
|
|
267
|
+
Enumerate every version the rename must touch, the manifest's and the ones on disk, through the `affected-versions` action of `{manifestOpsHelper}`:
|
|
209
268
|
|
|
210
269
|
```bash
|
|
211
|
-
|
|
270
|
+
uv run {manifestOpsHelper} {skills_output_folder} affected-versions {old_name}
|
|
212
271
|
```
|
|
213
272
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
**If `{manifestOpsHelper}` has no existing candidate** (neither probe path resolves — e.g. Python/`uv` unavailable): compute `affected_versions` in the prompt instead — read every key under `exports.{old_name}.versions` in the manifest, list every directory under `{skills_output_folder}/{old_name}/` that is not `active`, union the two sets, and sort descending (newest first, comparing version components numerically). Store the list as `affected_versions` and its length as `affected_versions_count`.
|
|
273
|
+
Store `affected_versions` = `result.affected_versions` (newest first) and `affected_versions_count` = `result.count`. When it prints no JSON, or its `status` is not `"ok"`, HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:affected-versions`) with "**Rename Skill cannot list the versions of `{old_name}`:** {its `error`, or the helper's stderr}. Nothing was changed."
|
|
217
274
|
|
|
218
|
-
Also
|
|
275
|
+
Also bind the four outer paths, each without a trailing `/`:
|
|
219
276
|
|
|
220
|
-
- `old_skill_group` = `{skills_output_folder}/{old_name}
|
|
221
|
-
- `new_skill_group` = `{skills_output_folder}/{new_name}
|
|
222
|
-
- `old_forge_group` = `{forge_data_folder}/{old_name}
|
|
223
|
-
- `new_forge_group` = `{forge_data_folder}/{new_name}
|
|
277
|
+
- `old_skill_group` = `{skills_output_folder}/{old_name}`
|
|
278
|
+
- `new_skill_group` = `{skills_output_folder}/{new_name}`
|
|
279
|
+
- `old_forge_group` = `{forge_data_folder}/{old_name}`
|
|
280
|
+
- `new_forge_group` = `{forge_data_folder}/{new_name}`
|
|
224
281
|
|
|
225
282
|
### 8. Confirmation Gate
|
|
226
283
|
|
|
@@ -235,50 +292,75 @@ Display the full operation summary:
|
|
|
235
292
|
|
|
236
293
|
Directories that will be copied then removed:
|
|
237
294
|
{old_skill_group} → {new_skill_group}
|
|
238
|
-
{old_forge_group} → {new_forge_group}
|
|
295
|
+
{if forge_move:}{old_forge_group} → {new_forge_group}
|
|
296
|
+
{if forge_left_in_place:}Left in place (not SKF output): {forge_left_in_place} — SKF did not generate it, so it keeps its name.
|
|
239
297
|
|
|
240
298
|
Inside each version, the inner `{old_name}/` directory will be renamed to `{new_name}/`,
|
|
241
299
|
and the following files will be updated:
|
|
242
300
|
- SKILL.md (frontmatter `name` field)
|
|
243
|
-
- metadata.json (`name` field)
|
|
244
|
-
- context-snippet.md (
|
|
245
|
-
- provenance-map.json (`skill_name` field, under {old_forge_group})
|
|
301
|
+
- metadata.json (`name` field, and paths into the moved folders)
|
|
302
|
+
- context-snippet.md (the name in its header, its IMPORTANT line and its root paths)
|
|
303
|
+
{if forge_move or same_folder:}- provenance-map.json (`skill_name` field and paths into the moved folders, under {old_forge_group})
|
|
246
304
|
|
|
247
305
|
Manifest `exports.{old_name}` will be re-keyed to `exports.{new_name}`.
|
|
248
306
|
Platform context files (CLAUDE.md, .cursorrules, AGENTS.md) will be rebuilt so
|
|
249
307
|
the managed section references `{new_name}` instead of `{old_name}`.
|
|
308
|
+
Copies installed in your IDE skill folders (`npx skills add`) are not renamed;
|
|
309
|
+
unless `snippet_skill_root_override` is set, the report names any it finds.
|
|
250
310
|
|
|
251
|
-
Operation is **transactional
|
|
252
|
-
before the old name is removed. If
|
|
253
|
-
directories are removed and the old skill remains intact.
|
|
311
|
+
Operation is **transactional**: the new name will be fully materialized and verified
|
|
312
|
+
before the old name is removed. If a step fails up to the manifest re-key, the new
|
|
313
|
+
directories are removed and the old skill remains intact. A context file that fails
|
|
314
|
+
to rebuild afterwards is reported and never undoes the rename.
|
|
254
315
|
|
|
255
316
|
Proceed? [Y/N]
|
|
256
317
|
```
|
|
257
318
|
|
|
258
|
-
**GATE [default: Y]
|
|
319
|
+
**GATE [default: Y]**: If `{headless_mode}`: auto-proceed with [Y] (log line: "headless: auto-confirmed rename {old_name} → {new_name}") and record `{"gate": "confirm-rename", "default_action": "proceed", "taken_action": "proceed", "reason": "headless auto-confirm"}` in the run sink with §6's two commands, staged as `{run_dir}/decision.json`; when `record` exits non-zero, HALT (exit code 4, `halt_reason: "write-failed"`, `emit-halt` phase `select:confirm`) with its message. Skip the record when `--dry-run` is set: a dry run does not execute the rename, so there is no confirmation to record.
|
|
259
320
|
|
|
260
321
|
Wait for explicit user response.
|
|
261
322
|
|
|
262
|
-
**If `--dry-run` was passed**: skip the Y/N prompt entirely
|
|
323
|
+
**If `--dry-run` was passed**: skip the Y/N prompt entirely and display "**[DRY RUN] No changes were made: the preview above shows what would be renamed.**" The dry run took no lock (§4b), so it releases none. In `{headless_mode}`, emit the dry-run envelope on **stdout**. From `{project-root}`:
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
cat > "{run_dir}/result-context.json" <<'SKF_RESULT'
|
|
327
|
+
{"status": "dry-run", "old_name": "{old_name}", "new_name": "{new_name}", "versions_renamed": <affected_versions as a JSON array>, "manifest_rekeyed": false, "context_files_updated": [], "halt_reason": null}
|
|
328
|
+
SKF_RESULT
|
|
329
|
+
uv run {emitEnvelopeHelper} emit --workflow skf-rename-skill --run-dir "{run_dir}" < "{run_dir}/result-context.json"
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
Without `--result-dir` it writes no result file. It prints the complete line, `SKF_RENAME_SKILL_RESULT_JSON: {"status":"dry-run","old_name":"{old_name}","new_name":"{new_name}","versions_renamed":[<affected_versions>],"manifest_rekeyed":false,"context_files_updated":[],"exit_code":0,"halt_reason":null,"headless_decisions":[<the §6 source-authority decision, when it fired>],"run_id":"{run_id}","result_path":null}` (with `warnings` after `headless_decisions` when the run recorded one): display it verbatim. When it exits non-zero or prints no line, display its error, keep `{run_dir}` and say in one line that it holds the run's decisions, its warnings and the payload the emitter refused. Otherwise, in both modes, delete the run folder:
|
|
333
|
+
|
|
334
|
+
```bash
|
|
335
|
+
rm -f "{run_dir}/result-context.json" "{run_dir}/decision.json" "{run_dir}/headless-decisions.jsonl" "{run_dir}/warnings.jsonl" && rmdir "{run_dir}"
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
Then end the run with exit code 0: no copy, no manifest re-key, no delete.
|
|
263
339
|
|
|
264
340
|
- **If `Y`** → proceed to section 9
|
|
265
|
-
- **If `N`** (or `cancel` / `exit` / `[X]` / `:q`) →
|
|
341
|
+
- **If `N`** (or `cancel` / `exit` / `[X]` / `:q`) → display "**Cancelled.** No changes were made." and HALT (exit code 6, `halt_reason: "user-cancelled"`, `emit-halt` phase `select:confirm`).
|
|
266
342
|
- **Any other input** → re-display the confirmation and ask again
|
|
267
343
|
|
|
268
344
|
### 9. Store Decisions in Context
|
|
269
345
|
|
|
270
346
|
Store the following decisions in workflow context for step 2:
|
|
271
347
|
|
|
272
|
-
- `old_name
|
|
273
|
-
- `new_name
|
|
274
|
-
- `affected_versions
|
|
275
|
-
- `
|
|
276
|
-
- `
|
|
277
|
-
- `
|
|
278
|
-
- `
|
|
279
|
-
- `
|
|
280
|
-
- `
|
|
281
|
-
- `
|
|
348
|
+
- `old_name`: the current skill name
|
|
349
|
+
- `new_name`: the validated new name
|
|
350
|
+
- `affected_versions`: every version §7 listed, the version folders step 2 copies; step 2 §2 renames the package of each one that holds it
|
|
351
|
+
- `old_skill_group`: absolute path `{skills_output_folder}/{old_name}` (no trailing `/`, like the three below)
|
|
352
|
+
- `new_skill_group`: absolute path `{skills_output_folder}/{new_name}`
|
|
353
|
+
- `old_forge_group`: absolute path `{forge_data_folder}/{old_name}`
|
|
354
|
+
- `new_forge_group`: absolute path `{forge_data_folder}/{new_name}`
|
|
355
|
+
- `forge_move`: boolean from §4a (true when this rename moves the forge folder)
|
|
356
|
+
- `forge_left_in_place`: the forge folder §4a leaves under the old name because SKF did not generate it, or null
|
|
357
|
+
- `same_folder`: boolean from §4a (true when `skills_output_folder` and `forge_data_folder` name one folder)
|
|
358
|
+
- `manifest_exists`: boolean from §2 (step 2 §6 re-keys the manifest only when it is true)
|
|
359
|
+
- `source_authority_override`: boolean (true if the user acknowledged the `"official"` warning, false/absent otherwise)
|
|
360
|
+
- `run_id` and `run_dir`: the run id and the run folder from §1
|
|
361
|
+
- `lock_owner`: the run lock's owner from §4b
|
|
362
|
+
|
|
363
|
+
The run's auto-decisions stay in `{run_dir}`, where each gate recorded them for the emitter.
|
|
282
364
|
|
|
283
365
|
### 10. Load Next Step
|
|
284
366
|
|