bmad-module-skill-forge 1.4.1 → 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 +34 -4
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +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/{steps-c/step-01-init.md → references/init.md} +57 -19
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -17
- 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} +11 -11
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +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} +11 -11
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +11 -49
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +20 -8
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +109 -113
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +16 -31
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +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-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
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Static reference loaded by load-skill.md §1b only when
|
|
3
|
+
# `snippet_skill_root_override` is UNSET in config.yaml. When the
|
|
4
|
+
# override is set, every existing snippet's on-disk prefix is ground
|
|
5
|
+
# truth by contract — no probe needed and the entire authoring-repo
|
|
6
|
+
# escape hatch is already configured. Loaded once per export run, not
|
|
7
|
+
# per skill.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<!-- Config: communicate in {communication_language}. Render the warning and gate prompt in {document_output_language}. -->
|
|
11
|
+
|
|
12
|
+
# Snippet Root Prefix Mismatch — Pre-flight Probe
|
|
13
|
+
|
|
14
|
+
## Purpose
|
|
15
|
+
|
|
16
|
+
Catch the authoring-repo case before step 4 silently rewrites root paths. In an authoring repo, skills typically live under a single shared directory (`skills/`) that does not match any per-IDE `skill_root` (`.claude/skills/`, `.cursor/skills/`, etc.). Without this probe, step 4's root-rewrite algorithm would replace the on-disk prefix with an IDE-mapped one that the snippet files do not actually reside under.
|
|
17
|
+
|
|
18
|
+
Loaded by `load-skill.md` §1b after `target_context_files` is resolved and `snippet_skill_root_override` is confirmed unset.
|
|
19
|
+
|
|
20
|
+
## Inputs
|
|
21
|
+
|
|
22
|
+
- `target_context_files[0].skill_root` — the reference IDE-mapped skill root (used because step 3 §2.7 picks this same entry for snippet generation when no override is set)
|
|
23
|
+
- `{skills_output_folder}` — for manifest-driven candidate enumeration
|
|
24
|
+
- Current skill's snippet path (resolved via manifest / `active` symlink / flat path per `knowledge/version-paths.md`)
|
|
25
|
+
- `{headless_mode}` — boolean flag from workflow context
|
|
26
|
+
|
|
27
|
+
## Probe Algorithm
|
|
28
|
+
|
|
29
|
+
1. Collect candidate snippet paths:
|
|
30
|
+
- Read `{skills_output_folder}/.export-manifest.json` if it exists. For each skill in `exports` with a resolvable `active_version`, add `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/context-snippet.md`.
|
|
31
|
+
- Also include the current skill's snippet if present.
|
|
32
|
+
2. For each snippet that exists on disk, read the first line and parse the `root:` value. Strip the trailing `{skill-name}/` to extract the prefix (e.g. `skills/`, `.claude/skills/`).
|
|
33
|
+
3. Collect unique prefixes into `observed_prefixes`.
|
|
34
|
+
4. Compare against `target_context_files[0].skill_root` (the reference).
|
|
35
|
+
|
|
36
|
+
## Mismatch Gate
|
|
37
|
+
|
|
38
|
+
**If `observed_prefixes` contains any value that does not match the reference `skill_root`:**
|
|
39
|
+
|
|
40
|
+
Emit a single warning (once, not per snippet) and present resolution options before continuing to §2:
|
|
41
|
+
|
|
42
|
+
> **Snippet root prefix mismatch detected.**
|
|
43
|
+
> Existing snippets use: `{observed_prefixes}`
|
|
44
|
+
> IDE-mapped skill_root: `{target_context_files[0].skill_root}`
|
|
45
|
+
>
|
|
46
|
+
> This usually means you are in an authoring repo where skills live under a single shared directory. Options:
|
|
47
|
+
>
|
|
48
|
+
> - **(a) Set override** — add `snippet_skill_root_override: {observed_prefix}` to `config.yaml`. Snippets keep their on-disk prefix; the managed section references the real location.
|
|
49
|
+
> - **(b) Proceed with IDE mapping** — step 4 will rewrite every snippet's root path to the IDE's skill_root. Use this only if the IDE's skill directory actually contains the skill files.
|
|
50
|
+
> - **(c) Cancel** — abort export and investigate.
|
|
51
|
+
>
|
|
52
|
+
> If multiple distinct prefixes were observed, the snippets disagree with each other — investigate before choosing (a).
|
|
53
|
+
|
|
54
|
+
Wait for user choice.
|
|
55
|
+
|
|
56
|
+
**Headless default:** when `{headless_mode}`, default to **(b) Proceed with IDE mapping** and log the observed prefix(es) so the mismatch is visible in run logs (not silent).
|
|
57
|
+
|
|
58
|
+
## Choice handling
|
|
59
|
+
|
|
60
|
+
### (a) Set override
|
|
61
|
+
|
|
62
|
+
Halt and instruct the user to update `config.yaml` with `snippet_skill_root_override: {observed_prefix}`, then re-run export. Exit code 6, `halt_reason: "user-cancelled"` (configuration change is out-of-band — workflow does not edit config.yaml on the user's behalf).
|
|
63
|
+
|
|
64
|
+
### (b) Proceed with IDE mapping
|
|
65
|
+
|
|
66
|
+
Continue to §2. Step 4's root-rewrite algorithm will rewrite every snippet's prefix to the reference `skill_root`. The user is accepting that the IDE's skill directory contains the actual files; if it does not, the resulting managed section will reference paths that don't resolve.
|
|
67
|
+
|
|
68
|
+
### (c) Cancel
|
|
69
|
+
|
|
70
|
+
HALT. Exit code 6, `halt_reason: "user-cancelled"`. No files written.
|
|
71
|
+
|
|
72
|
+
## No-mismatch fast path
|
|
73
|
+
|
|
74
|
+
**If all observed prefixes match the reference `skill_root` (or no existing snippets were found):** no warning, no gate. Return control to §1b and proceed silently to §2.
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'health-check.md'
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
<!-- Config: communicate in {communication_language}. Render the user-facing summary in {document_output_language}. -->
|
|
6
|
+
|
|
5
7
|
# Step 6: Summary
|
|
6
8
|
|
|
7
9
|
## STEP GOAL:
|
|
@@ -12,12 +14,10 @@ To present a complete export summary showing all files written, token counts, an
|
|
|
12
14
|
|
|
13
15
|
- Focus only on summarizing what was done and providing next steps — no additional file writes
|
|
14
16
|
- Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is NOT the terminal step
|
|
15
|
-
- **Multi-skill mode:** emit ONE consolidated summary and ONE result contract for the whole batch. The files-written table lists every skill in `skill_batch` (one row per skill's `context-snippet.md` + one row per target managed-section file, shared across the batch). The result contract's `outputs` enumerates every context-snippet file plus every target context file. Distribution instructions (§2) key off `source_authority` per skill — present one block per distinct authority value observed in the batch, listing the skills it applies to. See step
|
|
17
|
+
- **Multi-skill mode:** emit ONE consolidated summary and ONE result contract for the whole batch. The files-written table lists every skill in `skill_batch` (one row per skill's `context-snippet.md` + one row per target managed-section file, shared across the batch). The result contract's `outputs` enumerates every context-snippet file plus every target context file. Distribution instructions (§2) key off `source_authority` per skill — present one block per distinct authority value observed in the batch, listing the skills it applies to. See step 1 §1c.
|
|
16
18
|
|
|
17
19
|
## MANDATORY SEQUENCE
|
|
18
20
|
|
|
19
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
20
|
-
|
|
21
21
|
### 1. Compile Export Summary
|
|
22
22
|
|
|
23
23
|
"**Export Complete{if dry-run: ' (Dry Run)'}**
|
|
@@ -99,7 +99,7 @@ To install this skill into the current project right now:
|
|
|
99
99
|
npx skills add {resolved_skill_package}
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
Replace `{resolved_skill_package}` with the absolute path to the package folder shown above (from step
|
|
102
|
+
Replace `{resolved_skill_package}` with the absolute path to the package folder shown above (from step 2), e.g. `{skills_output_folder}/{skill-name}/{version}/{skill-name}/`.
|
|
103
103
|
|
|
104
104
|
For other source formats (registry name, git URL, tarball, etc.), see the **Installation → Source Formats** section at <https://www.npmjs.com/package/skills>.
|
|
105
105
|
|
|
@@ -130,18 +130,30 @@ No files were written. To run the export for real:
|
|
|
130
130
|
|
|
131
131
|
### 6. Result Contract
|
|
132
132
|
|
|
133
|
-
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{
|
|
133
|
+
Write the result contract per `shared/references/output-contract-schema.md`: the per-run record at `{skills_output_folder}/export-skill-result-{timestamp}.json` (reuse the activation-stored `{timestamp}`, resolution to seconds) and a copy at `{skills_output_folder}/export-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include all context files and target managed-section files in `outputs`; include total always-on and on-trigger token counts in `summary`.
|
|
134
|
+
|
|
135
|
+
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):
|
|
136
|
+
|
|
137
|
+
```
|
|
138
|
+
SKF_EXPORT_RESULT_JSON: {"status":"success","skills":{skill_batch_names},"context_files_updated":{context_files_updated},"manifest_path":"{skills_output_folder}/.export-manifest.json","headless_decisions":{headless_decisions},"exit_code":0,"halt_reason":null}
|
|
139
|
+
```
|
|
134
140
|
|
|
135
|
-
|
|
141
|
+
Substitute `{skill_batch_names}`, `{context_files_updated}`, and `{headless_decisions}` as JSON arrays. When `--dry-run` was set, emit `"status":"dry-run"` instead and report what *would* have been written without performing the writes.
|
|
142
|
+
|
|
143
|
+
**`deviations[]` field (export-skill-specific extension):** when step 4 §4c.1 detected manifest-orphan managed rows and the operator (or `{headless_mode}`) chose **(b) Preserve verbatim**, also include a `deviations[]` array in the contract. Each entry has the shape:
|
|
136
144
|
|
|
137
145
|
```json
|
|
138
146
|
{
|
|
139
147
|
"kind": "preserve_external_skills",
|
|
140
|
-
"skills": [
|
|
148
|
+
"skills": [
|
|
149
|
+
{"name": "skill-name", "version": "1.0.0", "source_files": ["CLAUDE.md", ".cursorrules"]}
|
|
150
|
+
],
|
|
141
151
|
"rationale": "managed-section row exists but no manifest entry / no source draft"
|
|
142
152
|
}
|
|
143
153
|
```
|
|
144
154
|
|
|
155
|
+
`source_files` per skill records the prior context files the orphan was found in (the §4c.1 multi-file scan deduplicates by `(skill, version)` and tracks which target context files originally carried the row — useful when an operator later debugs which IDE's managed section first introduced the external skill).
|
|
156
|
+
|
|
145
157
|
Other workflow choices that diverge from the strict spec path may add their own entries with a distinct `kind` value — auditors then have one place to look for "what did this run choose to do differently from the canonical flow." Omit the field when there are no deviations rather than writing an empty array, so the absence is readable as "ran the canonical path."
|
|
146
158
|
|
|
147
159
|
### 7. Chain to Health Check
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'summary.md'
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
<!-- Config: communicate in {communication_language}. Render the token report in {document_output_language}. -->
|
|
6
|
+
|
|
5
7
|
# Step 5: Token Report
|
|
6
8
|
|
|
7
9
|
## STEP GOAL:
|
|
@@ -12,15 +14,13 @@ To calculate approximate token counts for all exported artifacts and present a c
|
|
|
12
14
|
|
|
13
15
|
- Focus only on token counting and reporting — read-only measurement
|
|
14
16
|
- Auto-proceed when complete
|
|
15
|
-
- **Multi-skill mode:** when step
|
|
17
|
+
- **Multi-skill mode:** when step 1 loaded more than one skill (`len(skill_batch) > 1`), compute token counts per skill, then present one aggregate table with one row per skill (context-snippet.md, SKILL.md, metadata.json, references/, package total). Measure the managed section once for the run — it is shared across the batch. See step 1 §1c.
|
|
16
18
|
|
|
17
19
|
## MANDATORY SEQUENCE
|
|
18
20
|
|
|
19
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
20
|
-
|
|
21
21
|
### 1. Calculate Token Counts
|
|
22
22
|
|
|
23
|
-
For each artifact, estimate tokens using the heuristic: **words * 1.3** (approximate for GPT/Claude tokenizers). This same heuristic is used in step
|
|
23
|
+
For each artifact, estimate tokens using the heuristic: **words * 1.3** (approximate for GPT/Claude tokenizers). This same heuristic is used in step 3 for snippet token estimation.
|
|
24
24
|
|
|
25
25
|
**Artifacts to measure:**
|
|
26
26
|
|
package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md}
RENAMED
|
@@ -1,8 +1,32 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
3
|
-
managedSectionData: '
|
|
2
|
+
nextStepFile: 'token-report.md'
|
|
3
|
+
managedSectionData: '{managedSectionFormatPath}'
|
|
4
|
+
# Resolve `{rebuildManagedSectionsHelper}` by probing
|
|
5
|
+
# `{rebuildManagedSectionsProbeOrder}` in order (installed SKF module path
|
|
6
|
+
# first, src/ dev-checkout fallback); first existing path wins. §9 uses
|
|
7
|
+
# the `replace` action for the surgical between-marker swap with
|
|
8
|
+
# atomic temp-file + rename, marker preservation, and post-write verify.
|
|
9
|
+
# HALT if no candidate exists — the in-prompt prose path silently regresses
|
|
10
|
+
# the Case 4 (malformed markers) HARD HALT guarantee.
|
|
11
|
+
rebuildManagedSectionsProbeOrder:
|
|
12
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-rebuild-managed-sections.py'
|
|
13
|
+
- '{project-root}/src/shared/scripts/skf-rebuild-managed-sections.py'
|
|
14
|
+
# Resolve `{manifestOpsHelper}` similarly. §9b uses `read` / `set` for
|
|
15
|
+
# atomic v2-schema-aware manifest mutation (handles v1→v2 migration and
|
|
16
|
+
# `platforms`→`ides` rename internally).
|
|
17
|
+
manifestOpsProbeOrder:
|
|
18
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-manifest-ops.py'
|
|
19
|
+
- '{project-root}/src/shared/scripts/skf-manifest-ops.py'
|
|
20
|
+
# Resolve `{atomicWriteHelper}` similarly. §6 Case 1 (Create) and §6
|
|
21
|
+
# Case 2 (Append) use it via `write` for safe artifact emission — the
|
|
22
|
+
# in-prompt write would risk half-written files on process kill.
|
|
23
|
+
atomicWriteProbeOrder:
|
|
24
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
25
|
+
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
4
26
|
---
|
|
5
27
|
|
|
28
|
+
<!-- Config: communicate in {communication_language}. Render the change preview and managed section in {document_output_language}. -->
|
|
29
|
+
|
|
6
30
|
# Step 4: Update Context
|
|
7
31
|
|
|
8
32
|
## STEP GOAL:
|
|
@@ -14,16 +38,14 @@ To update the managed `<!-- SKF:BEGIN/END -->` section in the platform-appropria
|
|
|
14
38
|
- Focus only on the managed section update in the target context file
|
|
15
39
|
- Do not modify any content outside `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` markers
|
|
16
40
|
- Do not write without user confirmation — this modifies shared project files
|
|
17
|
-
- If `passive_context: false` was detected in step
|
|
18
|
-
- **Multi-skill mode:** this step executes ONCE for the whole batch, not once per skill. §4b already builds the exported skill set from the manifest (plus current export targets), so a multi-skill run naturally appears as a single rebuild. The only batch adjustment is in §9b: update the manifest entry for every skill in `skill_batch` (not just one), and include all of them when computing `ides_written`. See step
|
|
41
|
+
- If `passive_context: false` was detected in step 1, skip this step entirely
|
|
42
|
+
- **Multi-skill mode:** this step executes ONCE for the whole batch, not once per skill. §4b already builds the exported skill set from the manifest (plus current export targets), so a multi-skill run naturally appears as a single rebuild. The only batch adjustment is in §9b: update the manifest entry for every skill in `skill_batch` (not just one), and include all of them when computing `ides_written`. See step 1 §1c.
|
|
19
43
|
|
|
20
44
|
## MANDATORY SEQUENCE
|
|
21
45
|
|
|
22
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
23
|
-
|
|
24
46
|
### 1. Check Passive Context Setting
|
|
25
47
|
|
|
26
|
-
**If `passive_context: false` was detected in step
|
|
48
|
+
**If `passive_context: false` was detected in step 1:**
|
|
27
49
|
|
|
28
50
|
"**Passive context disabled in preferences.yaml. Skipping context update.**"
|
|
29
51
|
|
|
@@ -37,7 +59,7 @@ Load {managedSectionData} and read the complete format template and four-case lo
|
|
|
37
59
|
|
|
38
60
|
### 3. Determine Target File(s)
|
|
39
61
|
|
|
40
|
-
Using the `target_context_files` list resolved in step
|
|
62
|
+
Using the `target_context_files` list resolved in step 1, determine all target files. Each entry has `{context_file, skill_root}` — the context file to write and the IDE's skill directory for root path resolution.
|
|
41
63
|
|
|
42
64
|
For each entry in `target_context_files`, resolve target file path: `{context_file}`
|
|
43
65
|
|
|
@@ -49,87 +71,29 @@ For each entry in `target_context_files`, resolve target file path: `{context_fi
|
|
|
49
71
|
|
|
50
72
|
A context file becomes orphaned when its IDE is removed from `config.yaml` after a prior export. The file still contains an SKF managed section pointing to stale skill versions, but no future export will rewrite it.
|
|
51
73
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
1. For each known context file in `{CLAUDE.md, .cursorrules, AGENTS.md}`:
|
|
55
|
-
- If the context file is in `target_context_files`, skip (it will be rewritten in the main loop)
|
|
56
|
-
- Otherwise, check whether the file exists at `{context_file}`
|
|
57
|
-
- If the file exists, read it and check for the `<!-- SKF:BEGIN -->` marker
|
|
58
|
-
- If the marker is present, add the file path to `orphaned_context_files` along with the context file name
|
|
59
|
-
|
|
60
|
-
2. If `orphaned_context_files` is non-empty, emit a warning:
|
|
61
|
-
|
|
62
|
-
"**Orphaned context files detected.** The following files contain SKF managed sections but no configured IDEs target them:
|
|
63
|
-
{list: context file → file path}
|
|
64
|
-
|
|
65
|
-
The managed sections in these files are stale. Options:
|
|
66
|
-
- **(a) clear** — remove the SKF managed section from each orphaned file (surgical marker replacement, leaves user content intact)
|
|
67
|
-
- **(b) keep** — leave them untouched (they will remain stale until you re-add an IDE that targets this file or delete the file)
|
|
68
|
-
- **(c) rewrite** — also rewrite the orphaned files with the current skill index (use this if the IDE was removed by mistake)"
|
|
69
|
-
|
|
70
|
-
3. Wait for user choice. In non-interactive mode (dry-run or unattended), default to **(b) keep** and print the warning only.
|
|
71
|
-
|
|
72
|
-
4. If the user chose **(a) clear**: for each orphaned file, replace everything between `<!-- SKF:BEGIN` and `<!-- SKF:END -->` (inclusive) with an empty string, preserving surrounding content byte-exactly. Record the cleared files in `orphans_cleared`.
|
|
73
|
-
|
|
74
|
-
5. If the user chose **(c) rewrite**: add each orphaned context file to a separate `rewrite_context_files` list (kept distinct from `target_context_files` so the user's intent to only export to configured IDEs is preserved in the manifest). Use `.agents/skills/` as the default skill root for rewritten orphans. Sections 4–9a will loop over `target_context_files + rewrite_context_files` for this run only. Record the rewritten files in `orphans_rewritten`.
|
|
74
|
+
**Cheap pre-check (always run, ~3 file existence checks):** build `orphaned_context_files` — for each known context file in `{CLAUDE.md, .cursorrules, AGENTS.md}` that is NOT in `target_context_files`, check whether it exists on disk and contains the `<!-- SKF:BEGIN -->` marker. If yes, add `{context_file, file_path}` to `orphaned_context_files`.
|
|
75
75
|
|
|
76
|
-
|
|
76
|
+
**If `orphaned_context_files` is non-empty:** load `references/orphan-context-detection.md` and follow its (a) clear / (b) keep / (c) rewrite gate protocol. The reference handles user prompting, headless default (keep), and downstream-state recording (`orphans_cleared`, `orphans_rewritten`, `rewrite_context_files`). When the user chooses (c), the §4–§9a loop iterates over `target_context_files + rewrite_context_files`.
|
|
77
77
|
|
|
78
|
-
|
|
78
|
+
**If `orphaned_context_files` is empty:** proceed to §4.
|
|
79
79
|
|
|
80
80
|
### 4. Rebuild Complete Skill Index
|
|
81
81
|
|
|
82
82
|
#### 4a. Read Export Manifest (v2 — version-aware)
|
|
83
83
|
|
|
84
|
-
Read `{
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
**v2 manifest** (`schema_version: "2"`):
|
|
89
|
-
```json
|
|
90
|
-
{
|
|
91
|
-
"schema_version": "2",
|
|
92
|
-
"exports": {
|
|
93
|
-
"skill-name": {
|
|
94
|
-
"active_version": "0.6.0",
|
|
95
|
-
"versions": {
|
|
96
|
-
"0.1.0": {
|
|
97
|
-
"ides": ["claude-code"],
|
|
98
|
-
"last_exported": "2026-01-15",
|
|
99
|
-
"status": "deprecated"
|
|
100
|
-
},
|
|
101
|
-
"0.5.0": {
|
|
102
|
-
"ides": ["claude-code"],
|
|
103
|
-
"last_exported": "2026-03-15",
|
|
104
|
-
"status": "archived"
|
|
105
|
-
},
|
|
106
|
-
"0.6.0": {
|
|
107
|
-
"ides": ["claude-code", "github-copilot"],
|
|
108
|
-
"last_exported": "2026-04-04",
|
|
109
|
-
"status": "active"
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
84
|
+
Read the manifest via `{manifestOpsHelper}` (resolved at §9 from `{manifestOpsProbeOrder}` — see frontmatter):
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
python3 {manifestOpsHelper} {skills_output_folder} read
|
|
115
88
|
```
|
|
116
89
|
|
|
117
|
-
|
|
118
|
-
- `"active"` — currently exported; snippet appears in managed sections
|
|
119
|
-
- `"archived"` — previously exported, not active; files retained for rollback
|
|
120
|
-
- `"deprecated"` — dropped via drop-skill workflow; excluded from all exports (files may or may not exist on disk)
|
|
121
|
-
- `"draft"` — created but never exported
|
|
90
|
+
The helper handles v2-schema enforcement, v1→v2 migration, and the `platforms`→`ides` rename internally. The returned JSON is always in canonical v2 shape regardless of on-disk state.
|
|
122
91
|
|
|
123
|
-
**
|
|
92
|
+
**Schema reference:** `references/manifest-rebuild.md` documents the v2 shape, the status enum (`active`/`archived`/`deprecated`/`draft`), the v1 migration path, and the `active_version` integrity invariant. Load that file only when an inline schema reminder is needed — the helper enforces the shape so the in-prompt prose is not load-bearing.
|
|
124
93
|
|
|
125
|
-
**
|
|
126
|
-
1. For each entry in `exports`, read its `last_exported` (v1 had no per-version IDE list)
|
|
127
|
-
2. Resolve the skill's current version from `{resolved_skill_package}/metadata.json`
|
|
128
|
-
3. Wrap in v2 structure: set `active_version` to the resolved version, create a single entry in `versions` with `status: "active"`, `ides: []` (unknown — will be filled on next successful export), and `last_exported`
|
|
129
|
-
4. Set `schema_version: "2"` at root
|
|
130
|
-
5. Hold the migrated structure in context (it will be written in section 9b)
|
|
94
|
+
**Integrity guard:** if the helper returns an entry where `active_version` does not resolve to a key in `versions`, the manifest is inconsistent. Skip the affected skill and log: "**Manifest integrity warning:** `{skill-name}.active_version = v{active_version}` has no matching entry under `versions`. Skipping. Re-run `[EX] Export Skill` on `{skill-name}` to repair the manifest entry."
|
|
131
95
|
|
|
132
|
-
**If the
|
|
96
|
+
**If the manifest does not exist** (first export or fresh forge): the helper returns `{"schema_version": "2", "exports": {}}`. Only the current export target will appear in the rebuilt index.
|
|
133
97
|
|
|
134
98
|
#### 4b. Build Exported Skill Set (version-aware)
|
|
135
99
|
|
|
@@ -158,32 +122,23 @@ Instead of globbing `{skills_output_folder}/*/context-snippet.md`, resolve snipp
|
|
|
158
122
|
|
|
159
123
|
#### 4c.1 Detect Orphaned Managed-Section Rows (manifest-absent skills)
|
|
160
124
|
|
|
161
|
-
A managed-section row becomes orphaned when a `[skill-name v...]` entry already exists in the prior managed section but the skill is not in the exported skill set built in 4b — typically an externally-installed skill
|
|
162
|
-
|
|
163
|
-
Detect this case before §5 assembly so the operator (or `{headless_mode}`) makes an explicit choice:
|
|
164
|
-
|
|
165
|
-
1. Read the prior managed section from the **first target context file** (`target_context_files[0].context_file`). Parse the `[skill-name v...]` rows between `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` into `prior_section_rows` — a list of `{skill_name, version}` pairs. If the file does not exist or has no managed section, set `prior_section_rows = []` and skip to §5.
|
|
166
|
-
2. Build `orphan_managed_rows` — every entry in `prior_section_rows` whose `skill_name` is NOT in the exported skill set built in 4b (manifest entries plus current-export targets). For each orphan, capture the original snippet line(s) verbatim from the prior section.
|
|
167
|
-
3. **If `orphan_managed_rows` is non-empty**, present a halt-gate:
|
|
168
|
-
|
|
169
|
-
"**Managed-section rows present but absent from manifest:**
|
|
170
|
-
|
|
171
|
-
{list each as `- {skill_name} v{version}`}
|
|
125
|
+
A managed-section row becomes orphaned when a `[skill-name v...]` entry already exists in the prior managed section but the skill is not in the exported skill set built in 4b — typically an externally-installed skill authored in a different repo and dropped into `{skills_output_folder}` without going through export-skill. Strict ADR-K would silently drop such rows, but the user's managed section is load-bearing — silent removal is a regression.
|
|
172
126
|
|
|
173
|
-
|
|
127
|
+
**Cheap pre-check (always run before §5 assembly).** Scan **every** target context file (not just the first), deduplicate by `(skill_name, version)`, and present one consolidated gate. Asymmetric orphans — a row present in `.cursorrules` but absent from `CLAUDE.md`, or vice versa — must be detected; otherwise the §4 rebuild loop silently overwrites the orphan-bearing file's content (ADR-J violation: silent loss of user content).
|
|
174
128
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
129
|
+
1. Initialize `orphan_managed_rows = []` (a list of `{skill_name, version, snippet_text, source_files: []}` entries — `source_files` carries provenance for the gate display and the audit `deviations[]` entry).
|
|
130
|
+
2. **Iterate every entry in `target_context_files`:**
|
|
131
|
+
a. Read the prior managed section from `{entry.context_file}`. If the file does not exist or has no `<!-- SKF:BEGIN -->` marker, skip this entry — it has no orphans by definition.
|
|
132
|
+
b. Parse the `[skill-name v...]` rows between `<!-- SKF:BEGIN -->` and `<!-- SKF:END -->` into `file_rows` — a list of `{skill_name, version, snippet_text}` triples (capture the original snippet line(s) verbatim so they can be re-emitted unchanged if (b) is chosen).
|
|
133
|
+
c. For each `row` in `file_rows`:
|
|
134
|
+
- If `row.skill_name` is in the exported skill set built in 4b (manifest entries plus current-export targets), skip — not an orphan.
|
|
135
|
+
- Otherwise look up `(row.skill_name, row.version)` in `orphan_managed_rows`:
|
|
136
|
+
- If already present, append `entry.context_file` to that row's `source_files` list (deduplicated). Keep the first-encountered `snippet_text` — divergent snippets across files for the same `(skill, version)` are themselves a user-content asymmetry but the `(b) Preserve verbatim` semantic writes one canonical row to every target file, so picking the first is deterministic and avoids silently choosing.
|
|
137
|
+
- If new, append `{skill_name: row.skill_name, version: row.version, snippet_text: row.snippet_text, source_files: [entry.context_file]}`.
|
|
178
138
|
|
|
179
|
-
|
|
180
|
-
- **(a) Drop:** Do not include any orphan rows in the rebuilt section. Record `orphans_dropped = [{skill_name, version}, …]` in workflow context for the §6 result contract.
|
|
181
|
-
- **(b) Preserve verbatim:** Append each captured snippet to the assembled section after the manifest-driven entries, preserving alphabetical order in the merged list. Append `{kind: "preserve_external_skills", skills: [{name, version}, …], rationale: "managed-section row exists but no manifest entry / no source draft"}` to the `deviations[]` array in the §6 result contract. The same orphans are written to **every** target context file in the loop (so all configured IDEs end up with consistent managed sections).
|
|
182
|
-
- **(c) Cancel:** HALT the workflow. Do not rewrite any context file. Do not update the manifest. Do not produce a result contract.
|
|
139
|
+
**If `orphan_managed_rows` is non-empty:** load `references/orphan-row-detection.md` and follow its (a) Drop / (b) Preserve verbatim / (c) Cancel gate protocol. The reference handles user prompting (with per-orphan `source_files` provenance), headless default (Preserve verbatim), `deviations[]` recording (including `source_files` per orphan for audit), and §6 result-contract integration.
|
|
183
140
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
This detection runs once per export run (not per target context file) — orphan rows are inherent to the prior state of the first context file and the choice is global.
|
|
141
|
+
**If `orphan_managed_rows` is empty:** proceed to §4d.
|
|
187
142
|
|
|
188
143
|
#### 4d. Rewrite Root Paths for Target Context File
|
|
189
144
|
|
|
@@ -246,8 +201,9 @@ Assemble the complete managed section:
|
|
|
246
201
|
- Preserved: ALL content before `<!-- SKF:BEGIN` and after `<!-- SKF:END -->`
|
|
247
202
|
|
|
248
203
|
**Case 4: Malformed markers (file contains `<!-- SKF:BEGIN` but no `<!-- SKF:END -->`)**
|
|
249
|
-
- Action: HALT with warning: "Malformed SKF markers detected in `{target-file}` — `<!-- SKF:BEGIN` found but `<!-- SKF:END -->` is missing. Please restore the end marker manually before running export."
|
|
250
|
-
- Do NOT attempt to write or append — the file is in an inconsistent state
|
|
204
|
+
- Action: HALT (exit code 5, `halt_reason: "malformed-markers"`) with warning: "Malformed SKF markers detected in `{target-file}` — `<!-- SKF:BEGIN` found but `<!-- SKF:END -->` is missing. Please restore the end marker manually before running export."
|
|
205
|
+
- Do NOT attempt to write or append — the file is in an inconsistent state.
|
|
206
|
+
- In headless mode, emit the error envelope per SKILL.md "Result Contract (Headless)" with `manifest_path: null`, `context_files_updated: []`.
|
|
251
207
|
|
|
252
208
|
### 7. Present Change Preview
|
|
253
209
|
|
|
@@ -280,18 +236,19 @@ Auto-proceed to {nextStepFile}.
|
|
|
280
236
|
|
|
281
237
|
**If NOT dry-run:**
|
|
282
238
|
|
|
283
|
-
Display: "**Select:** [C] Continue — write changes to {target-file}"
|
|
239
|
+
Display: "**Select:** [C] Continue — write changes to {target-file} | [X] Cancel and exit (or type `cancel` / `exit` / `:q`)"
|
|
284
240
|
|
|
285
241
|
**Multi-target behavior:** When processing multiple context files, present all previews together before asking for a single confirmation. After confirmation, write all target files sequentially, verifying each one.
|
|
286
242
|
|
|
287
243
|
"**Targets:** {list all context-file → target-file pairs}
|
|
288
244
|
**Ready to write changes to all targets?**"
|
|
289
245
|
|
|
290
|
-
Display: "**Select:** [C] Continue — write changes to all targets"
|
|
246
|
+
Display: "**Select:** [C] Continue — write changes to all targets | [X] Cancel and exit"
|
|
291
247
|
|
|
292
248
|
#### Menu Handling Logic:
|
|
293
249
|
|
|
294
250
|
- IF C: Write the changes to all target files (or single target), verify each write succeeded, then load, read entire file, then execute {nextStepFile}
|
|
251
|
+
- IF X (or `cancel` / `exit` / `:q`): Display "Cancelled — no context files were written." and HALT (exit code 6, `halt_reason: "user-cancelled"`). In headless, emit the error envelope per SKILL.md "Result Contract (Headless)" with the resolved `skills`, `context_files_updated: []`, and `manifest_path: null`.
|
|
295
252
|
- IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
|
|
296
253
|
|
|
297
254
|
#### EXECUTION RULES:
|
|
@@ -303,16 +260,49 @@ Display: "**Select:** [C] Continue — write changes to all targets"
|
|
|
303
260
|
|
|
304
261
|
### 9. Write and Verify (Non-Dry-Run Only)
|
|
305
262
|
|
|
306
|
-
After user confirms with 'C':
|
|
263
|
+
After user confirms with 'C', resolve the helpers in parallel — these are independent file-existence checks that batch into one tool-call message:
|
|
264
|
+
|
|
265
|
+
- `{rebuildManagedSectionsHelper}` ← first existing path in `{rebuildManagedSectionsProbeOrder}` (used for Cases 2 and 3)
|
|
266
|
+
- `{atomicWriteHelper}` ← first existing path in `{atomicWriteProbeOrder}` (used for Case 1)
|
|
267
|
+
- `{manifestOpsHelper}` ← first existing path in `{manifestOpsProbeOrder}` (used in §9b)
|
|
307
268
|
|
|
308
|
-
|
|
309
|
-
2. Re-read the written file
|
|
310
|
-
3. Verify `<!-- SKF:BEGIN` and `<!-- SKF:END -->` markers are present
|
|
311
|
-
4. Verify content outside markers is unchanged (for Cases 2 and 3)
|
|
312
|
-
5. Report: "**{target-file} updated successfully.** Verified: markers present, external content preserved."
|
|
269
|
+
If any helper has no existing candidate, HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) and emit the error envelope per SKILL.md "Result Contract (Headless)" — the rewrite's safety guarantees depend on these helpers and a fall-through to LLM-driven writes would silently regress atomicity, marker preservation, and the Case 4 malformed-marker HARD HALT contract.
|
|
313
270
|
|
|
314
|
-
|
|
315
|
-
|
|
271
|
+
For each target context file, dispatch by case:
|
|
272
|
+
|
|
273
|
+
**Case 1 (Create — file does not exist):**
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
echo "{new_managed_section_text}" | python3 {atomicWriteHelper} write "{target-file}"
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
The helper stages the content into `<target>.skf-tmp`, fsyncs, and atomically renames into place.
|
|
280
|
+
|
|
281
|
+
**Case 2 (Append — file exists, no `<!-- SKF:BEGIN` marker):**
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
python3 {rebuildManagedSectionsHelper} {target-file} insert --content "{new_managed_section_text}"
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
The helper appends the managed section to the end of the file via the same atomic temp-file + rename pattern.
|
|
288
|
+
|
|
289
|
+
**Case 3 (Regenerate — file contains `<!-- SKF:BEGIN` and `<!-- SKF:END -->`):**
|
|
290
|
+
|
|
291
|
+
```bash
|
|
292
|
+
python3 {rebuildManagedSectionsHelper} {target-file} replace --content "{new_managed_section_text}"
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
The helper performs the surgical between-marker swap with post-write verification (markers present, content outside markers byte-identical).
|
|
296
|
+
|
|
297
|
+
**Case 4 (malformed markers — already HALTed in §6):** never reaches here.
|
|
298
|
+
|
|
299
|
+
**Verification (deferred to helpers):** the `replace`/`insert`/`write` actions above each perform their own verification. Treat any non-zero exit as a write failure:
|
|
300
|
+
|
|
301
|
+
- HALT (exit code 4, `halt_reason: "context-rebuild-failed"`) and report `{target-file}: {captured stderr}`.
|
|
302
|
+
- In headless mode, emit the error envelope.
|
|
303
|
+
- Continue to the next target file only on success — partial-batch writes are acceptable in single-skill mode but the overall envelope reports per-target outcomes.
|
|
304
|
+
|
|
305
|
+
On success per file, report: "**{target-file} updated successfully.** Verified by `{rebuildManagedSectionsHelper}` (or `{atomicWriteHelper}` for Case 1)."
|
|
316
306
|
|
|
317
307
|
### 9b. Update Export Manifest (Non-Dry-Run Only)
|
|
318
308
|
|
|
@@ -342,11 +332,17 @@ After user confirms with 'C':
|
|
|
342
332
|
- If the version already exists in `versions`, union its existing `ides` with `ides_written` (deduplicate, keep sorted), refresh `last_exported`, and set `status: "active"`
|
|
343
333
|
- If this is a new version, add it to `versions` with `status: "active"` and set any previously-active version's status to `"archived"`
|
|
344
334
|
- Preserve all other version entries in `versions` (do not delete archived versions)
|
|
345
|
-
5. Write the updated manifest
|
|
335
|
+
5. Write the updated manifest atomically via `{manifestOpsHelper}` after all skills in the batch have been applied. For each skill / version pair, invoke:
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
python3 {manifestOpsHelper} {skills_output_folder} set {skill-name} {version}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
The helper handles v2-schema validation, v1→v2 migration, and `platforms`→`ides` rename internally — no in-prompt JSON manipulation needed. Each `set` invocation merges the per-version `ides` and `last_exported` fields into the existing entry. After all skills have been set, re-read the manifest via `{manifestOpsHelper} {skills_output_folder} read` to confirm the final state matches expectations.
|
|
346
342
|
|
|
347
343
|
**Dry-run mode:** Do NOT update the manifest. Display: "**[DRY RUN] Export manifest would be updated for {skill-name-list} — ides: {ides_written}.**" (list every skill in `skill_batch`)
|
|
348
344
|
|
|
349
|
-
**Error handling:** If
|
|
345
|
+
**Error handling:** If `{manifestOpsHelper}` exits non-zero, HALT (exit code 4, `halt_reason: "manifest-write-failed"`) with the captured `stderr`. The managed section was already written successfully; the operator's recovery path is to manually reconcile the on-disk managed section with the manifest, then re-run `[EX] Export Skill --all` to refresh the manifest. In headless mode, emit the error envelope per SKILL.md "Result Contract (Headless)" with `manifest_path: null` and the partial `context_files_updated` list.
|
|
350
346
|
|
|
351
347
|
## CRITICAL STEP COMPLETION NOTE
|
|
352
348
|
|