bmad-module-skill-forge 1.9.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.nvmrc +1 -1
- package/README.md +10 -5
- package/docs/_data/pinned.yaml +2 -2
- package/docs/agents.md +11 -2
- package/docs/architecture.md +5 -4
- package/docs/bmad-synergy.md +30 -7
- package/docs/campaign.md +172 -0
- package/docs/examples.md +7 -3
- package/docs/forge-auto.md +90 -0
- package/docs/getting-started.md +9 -0
- package/docs/how-it-works.md +6 -4
- package/docs/index.md +4 -3
- package/docs/skill-model.md +1 -1
- package/docs/troubleshooting.md +17 -1
- package/docs/verifying-a-skill.md +2 -2
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +64 -24
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +4 -3
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +6 -3
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- package/src/shared/scripts/skf-comention-pairs.py +350 -0
- package/src/shared/scripts/skf-count-tokens.py +222 -0
- package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +240 -4
- package/src/shared/scripts/skf-detect-language.py +82 -3
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- package/src/shared/scripts/skf-find-cycles.py +246 -0
- package/src/shared/scripts/skf-hash-content.py +487 -2
- package/src/shared/scripts/skf-language-corpora.py +100 -0
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
- package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
- package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
- package/src/shared/scripts/skf-shape-detect.py +576 -25
- package/src/shared/scripts/skf-shard-body.py +461 -0
- package/src/shared/scripts/skf-skill-inventory.py +139 -3
- package/src/shared/scripts/skf-structural-diff.py +307 -67
- package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
- package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
- package/src/shared/scripts/skf-validate-output.py +443 -10
- package/src/shared/scripts/skf-validate-pins.py +3 -3
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +2 -0
- package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
- package/src/skf-analyze-source/references/continue.md +8 -13
- package/src/skf-analyze-source/references/generate-briefs.md +28 -12
- package/src/skf-analyze-source/references/headless-contract.md +33 -0
- package/src/skf-analyze-source/references/health-check.md +1 -2
- package/src/skf-analyze-source/references/identify-units.md +25 -36
- package/src/skf-analyze-source/references/init.md +12 -25
- package/src/skf-analyze-source/references/map-and-detect.md +8 -20
- package/src/skf-analyze-source/references/recommend.md +4 -14
- package/src/skf-analyze-source/references/scan-project.md +3 -11
- package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
- package/src/skf-audit-skill/SKILL.md +9 -6
- package/src/skf-audit-skill/customize.toml +2 -0
- package/src/skf-audit-skill/references/init.md +58 -32
- package/src/skf-audit-skill/references/re-index.md +15 -34
- package/src/skf-audit-skill/references/report.md +11 -58
- package/src/skf-audit-skill/references/semantic-diff.md +4 -22
- package/src/skf-audit-skill/references/severity-classify.md +53 -87
- package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
- package/src/skf-audit-skill/references/structural-diff.md +43 -68
- package/src/skf-brief-skill/SKILL.md +7 -36
- package/src/skf-brief-skill/assets/scope-templates.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +13 -18
- package/src/skf-brief-skill/references/confirm-brief.md +2 -15
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +27 -24
- package/src/skf-brief-skill/references/headless-args.md +1 -1
- package/src/skf-brief-skill/references/health-check.md +1 -22
- package/src/skf-brief-skill/references/invocation-contract.md +37 -0
- package/src/skf-brief-skill/references/scope-definition.md +6 -15
- package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
- package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +19 -13
- package/src/skf-campaign/SKILL.md +121 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +75 -0
- package/src/skf-campaign/manifest.yaml +15 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +121 -0
- package/src/skf-campaign/references/step-02-strategy.md +102 -0
- package/src/skf-campaign/references/step-03-pins.md +56 -0
- package/src/skf-campaign/references/step-04-provenance.md +63 -0
- package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
- package/src/skf-campaign/references/step-06-batch.md +88 -0
- package/src/skf-campaign/references/step-07-capstone.md +63 -0
- package/src/skf-campaign/references/step-08-verify.md +75 -0
- package/src/skf-campaign/references/step-09-refine.md +83 -0
- package/src/skf-campaign/references/step-10-export.md +106 -0
- package/src/skf-campaign/references/step-11-maintenance.md +84 -0
- package/src/skf-campaign/references/step-resume.md +115 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +244 -0
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
- package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
- package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
- package/src/skf-campaign/templates/campaign-report-template.md +54 -0
- package/src/skf-campaign/templates/kickoff-template.md +48 -0
- package/src/skf-create-skill/SKILL.md +15 -4
- package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
- package/src/skf-create-skill/assets/skill-sections.md +9 -100
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
- package/src/skf-create-skill/customize.toml +13 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
- package/src/skf-create-skill/references/compile.md +37 -47
- package/src/skf-create-skill/references/component-extraction.md +8 -35
- package/src/skf-create-skill/references/ecosystem-check.md +9 -25
- package/src/skf-create-skill/references/enrich.md +4 -17
- package/src/skf-create-skill/references/extract.md +20 -27
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +10 -8
- package/src/skf-create-skill/references/generate-artifacts.md +20 -25
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +27 -14
- package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +33 -15
- package/src/skf-create-skill/references/step-doc-sources.md +13 -4
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
- package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
- package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
- package/src/skf-create-skill/references/validate.md +69 -29
- package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
- package/src/skf-create-stack-skill/SKILL.md +15 -9
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +10 -0
- package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
- package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
- package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
- package/src/skf-create-stack-skill/references/generate-output.md +24 -75
- package/src/skf-create-stack-skill/references/init.md +9 -81
- package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
- package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
- package/src/skf-create-stack-skill/references/report.md +27 -62
- package/src/skf-create-stack-skill/references/validate.md +35 -31
- package/src/skf-drop-skill/SKILL.md +20 -23
- package/src/skf-drop-skill/customize.toml +10 -0
- package/src/skf-drop-skill/references/execute.md +67 -36
- package/src/skf-drop-skill/references/headless-contract.md +18 -0
- package/src/skf-drop-skill/references/health-check.md +1 -13
- package/src/skf-drop-skill/references/report.md +44 -10
- package/src/skf-drop-skill/references/select.md +93 -48
- package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
- package/src/skf-export-skill/SKILL.md +17 -14
- package/src/skf-export-skill/assets/managed-section-format.md +2 -5
- package/src/skf-export-skill/customize.toml +10 -6
- package/src/skf-export-skill/references/generate-snippet.md +21 -35
- package/src/skf-export-skill/references/load-skill.md +44 -42
- package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
- package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
- package/src/skf-export-skill/references/package.md +27 -33
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
- package/src/skf-export-skill/references/result-envelope.md +28 -0
- package/src/skf-export-skill/references/summary.md +11 -5
- package/src/skf-export-skill/references/token-report.md +42 -24
- package/src/skf-export-skill/references/update-context.md +32 -33
- package/src/skf-forger/SKILL.md +32 -39
- package/src/skf-forger/references/pipeline-mode.md +34 -0
- package/src/skf-forger/scripts/parse-pipeline.py +270 -0
- package/src/skf-quick-skill/SKILL.md +10 -60
- package/src/skf-quick-skill/customize.toml +9 -0
- package/src/skf-quick-skill/references/batch-mode.md +6 -4
- package/src/skf-quick-skill/references/compile.md +15 -52
- package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
- package/src/skf-quick-skill/references/finalize.md +12 -6
- package/src/skf-quick-skill/references/halt-contract.md +54 -0
- package/src/skf-quick-skill/references/health-check.md +3 -4
- package/src/skf-quick-skill/references/quick-extract.md +7 -18
- package/src/skf-quick-skill/references/registry-resolution.md +1 -23
- package/src/skf-quick-skill/references/resolve-target.md +27 -34
- package/src/skf-quick-skill/references/write-and-validate.md +10 -25
- package/src/skf-refine-architecture/SKILL.md +16 -8
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +10 -8
- package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
- package/src/skf-refine-architecture/references/health-check.md +1 -1
- package/src/skf-refine-architecture/references/improvements.md +9 -25
- package/src/skf-refine-architecture/references/init.md +9 -16
- package/src/skf-refine-architecture/references/issue-detection.md +10 -25
- package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
- package/src/skf-refine-architecture/references/report.md +14 -11
- package/src/skf-rename-skill/SKILL.md +11 -21
- package/src/skf-rename-skill/customize.toml +10 -0
- package/src/skf-rename-skill/references/execute.md +112 -82
- package/src/skf-rename-skill/references/exit-codes.md +12 -0
- package/src/skf-rename-skill/references/report.md +16 -8
- package/src/skf-rename-skill/references/select.md +69 -42
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
- package/src/skf-setup/SKILL.md +21 -13
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +11 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +10 -8
- package/src/skf-setup/references/report.md +26 -32
- package/src/skf-setup/references/tier-rules.md +2 -32
- package/src/skf-setup/references/write-config.md +9 -10
- package/src/skf-test-skill/SKILL.md +10 -8
- package/src/skf-test-skill/customize.toml +2 -0
- package/src/skf-test-skill/references/coherence-check.md +19 -31
- package/src/skf-test-skill/references/coverage-check.md +111 -67
- package/src/skf-test-skill/references/detect-mode.md +10 -41
- package/src/skf-test-skill/references/external-validators.md +11 -19
- package/src/skf-test-skill/references/init.md +39 -21
- package/src/skf-test-skill/references/migration-section-rules.md +4 -4
- package/src/skf-test-skill/references/report.md +60 -40
- package/src/skf-test-skill/references/score.md +32 -64
- package/src/skf-test-skill/references/scoring-rules.md +6 -62
- package/src/skf-test-skill/references/source-access-protocol.md +15 -5
- package/src/skf-test-skill/references/step-hard-gate.md +1 -3
- package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
- package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
- package/src/skf-test-skill/scripts/compute-score.py +135 -4
- package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
- package/src/skf-update-skill/SKILL.md +17 -5
- package/src/skf-update-skill/customize.toml +11 -6
- package/src/skf-update-skill/references/detect-changes.md +48 -36
- package/src/skf-update-skill/references/health-check.md +5 -11
- package/src/skf-update-skill/references/init.md +40 -32
- package/src/skf-update-skill/references/manual-section-rules.md +1 -2
- package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
- package/src/skf-update-skill/references/merge.md +13 -57
- package/src/skf-update-skill/references/re-extract.md +27 -25
- package/src/skf-update-skill/references/report.md +14 -7
- package/src/skf-update-skill/references/validate.md +32 -30
- package/src/skf-update-skill/references/write.md +86 -51
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
- package/src/skf-verify-stack/SKILL.md +11 -21
- package/src/skf-verify-stack/customize.toml +12 -3
- package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
- package/src/skf-verify-stack/references/coverage.md +21 -10
- package/src/skf-verify-stack/references/exit-codes.md +14 -0
- package/src/skf-verify-stack/references/health-check.md +1 -1
- package/src/skf-verify-stack/references/init.md +20 -25
- package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
- package/src/skf-verify-stack/references/integrations.md +44 -49
- package/src/skf-verify-stack/references/report.md +28 -34
- package/src/skf-verify-stack/references/requirements.md +3 -3
- package/src/skf-verify-stack/references/synthesize.md +36 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
- package/tools/cli/lib/ui.js +3 -2
- package/docs/deepwiki.md +0 -89
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -25,6 +25,21 @@ buildChangeManifestProbeOrder:
|
|
|
25
25
|
provenanceGapDispatchProbeOrder:
|
|
26
26
|
- '{project-root}/_bmad/skf/shared/scripts/skf-provenance-gap-dispatch.py'
|
|
27
27
|
- '{project-root}/src/shared/scripts/skf-provenance-gap-dispatch.py'
|
|
28
|
+
# Resolve `{detectScriptsAssetsHelper}` to the first existing path; HALT if
|
|
29
|
+
# neither candidate exists. §Category D uses `detect` to walk the current
|
|
30
|
+
# source tree for scripts/assets (directory conventions, shebang signals,
|
|
31
|
+
# `package.json` `bin` entry-points, asset filename patterns) so NEW_FILE
|
|
32
|
+
# detection mirrors create-skill §4c exactly. Falling back to prose-driven
|
|
33
|
+
# file walking would let the LLM drift on the heuristic list and miss new
|
|
34
|
+
# scripts/assets at deeper directory depths — and on installed modules
|
|
35
|
+
# (no `src/` tree) the LLM would otherwise guess a non-existent path.
|
|
36
|
+
detectScriptsAssetsProbeOrder:
|
|
37
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-scripts-assets.py'
|
|
38
|
+
- '{project-root}/src/shared/scripts/skf-detect-scripts-assets.py'
|
|
39
|
+
# `{newFileDiffHelper}` derives NEW_FILE (inventory source_files not in the
|
|
40
|
+
# provenance map, minus [MANUAL] paths) — the set-difference §Category D would
|
|
41
|
+
# otherwise ask the model to compute by hand. Per-skill helper, always bundled.
|
|
42
|
+
newFileDiffHelper: 'scripts/skf-new-file-diff.py'
|
|
28
43
|
---
|
|
29
44
|
|
|
30
45
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -40,7 +55,7 @@ Compare current source code state against the provenance map to produce a comple
|
|
|
40
55
|
- Focus only on detecting and classifying changes — do not extract or merge
|
|
41
56
|
- Use subprocess Pattern 4 (parallel) when available; if unavailable, compare sequentially
|
|
42
57
|
|
|
43
|
-
##
|
|
58
|
+
## Steps
|
|
44
59
|
|
|
45
60
|
### 0. Check for Test Report Input (Gap-Driven Mode)
|
|
46
61
|
|
|
@@ -94,7 +109,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
94
109
|
|
|
95
110
|
### 1b. Discovered Authoritative Files Protocol (Mirror)
|
|
96
111
|
|
|
97
|
-
**Purpose:** mirror `skf-create-skill` §2a into update-skill. `skf-create-skill` §2a catches authoritative AI documentation files (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.) during **creation
|
|
112
|
+
**Purpose:** mirror `skf-create-skill` §2a into update-skill. `skf-create-skill` §2a catches authoritative AI documentation files (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.) during **creation**, but a project may add these files *after* the skill was created. Without this mirror, update-skill would either miss the new file entirely (if it doesn't match the provenance map's file patterns) or classify it as a generic ADDED file in §2 Category A with no authoritative-file treatment. The mirror surfaces the discovery with the same P/S/U prompt create-skill uses, honoring any prior amendments.
|
|
98
113
|
|
|
99
114
|
**Skip this section entirely if:**
|
|
100
115
|
|
|
@@ -166,11 +181,11 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
166
181
|
|
|
167
182
|
**Record for evidence report:** the update-skill evidence report appends `authoritative_files_mirror: {candidates: N, promoted: P, skipped: S, pre_decided: A, already_tracked: T, decisions: [{path, action, heuristic, reason}]}`.
|
|
168
183
|
|
|
169
|
-
**Interaction with §2 change detection:** promoted docs live in `promoted_docs_new[]`,
|
|
184
|
+
**Interaction with §2 change detection:** promoted docs live in `promoted_docs_new[]`, not in the change manifest. §2.0's `change_detection_excludes` set (built below) is what stops §2 Category A from re-classifying them as ADDED — it is the only coordination that survives across the parallel Category A subprocesses.
|
|
170
185
|
|
|
171
186
|
### 1c. Major-Version Scope Reconciliation (Pre-Detection)
|
|
172
187
|
|
|
173
|
-
**Purpose:**
|
|
188
|
+
**Purpose:** §1b handles new authoritative-doc files; §1c handles new **code globs** that fall outside the original scope when upstream restructures (rebrand, package restructure, major-version rewrite) so the brief's `scope.include` no longer reflects the real public API. Without it, update-skill silently misses the new public surface and pays the gap cost on every future update.
|
|
174
189
|
|
|
175
190
|
**Skip this section entirely if:**
|
|
176
191
|
|
|
@@ -222,7 +237,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
222
237
|
- `status: "pre-decided-demoted"` → record as `pre_decided`; do not re-prompt (`prior_action` ∈ `demoted-include`, `demoted-exclude`).
|
|
223
238
|
- `status: "unresolved"` → continue to step 4 (user prompt).
|
|
224
239
|
|
|
225
|
-
**Note:** the Out-of-Scope section is an optional audit-skill output
|
|
240
|
+
**Note:** the Out-of-Scope section is an optional audit-skill output and is often absent or empty — new-file detection is update-skill's job (§1b/§2.2), not audit-skill's — so the `no-report` / `no-candidates` paths above are the common case.
|
|
226
241
|
|
|
227
242
|
3. **Prompt for each unresolved candidate.** Present the same menu shape as §1b:
|
|
228
243
|
|
|
@@ -305,7 +320,20 @@ Launch subprocesses in parallel that compare source state against provenance map
|
|
|
305
320
|
|
|
306
321
|
**Category C — Rename detection:**
|
|
307
322
|
- Cross-reference deleted files/exports with added files/exports
|
|
308
|
-
- If content similarity > 80
|
|
323
|
+
- If content similarity > 80% (fixed bundled threshold — not configurable): classify as RENAMED instead of deleted+added. **Similarity mechanism by tier:** Quick: compare file size ratio (within 20%) and export name overlap (>70% of exports match by name). Forge and above: use ast-grep to compare export signatures between the deleted and added files. Forge+/Deep: use CCC semantic similarity when available
|
|
324
|
+
|
|
325
|
+
**Subprocess return contract.** Hand each Category worker its exact output slice so it returns parse-ready JSON, not prose the parent must re-read. Each worker returns ONLY its own object — no prose, no commentary, no markdown fences (parent strips wrapping fences before parsing). The slice each worker fills is exactly the key §3's `build` helper consumes (the `category_a/b/c` shape below; Category D is helper-driven, not a worker):
|
|
326
|
+
|
|
327
|
+
```json
|
|
328
|
+
// Category A worker returns ONLY:
|
|
329
|
+
{"category_a": {"modified": [...], "added": [...], "deleted": [...]}}
|
|
330
|
+
// Category B worker returns ONLY:
|
|
331
|
+
{"category_b": {"modified_exports": [...], "new_exports": [...], "deleted_exports": [...], "moved_exports": [...]}}
|
|
332
|
+
// Category C worker returns ONLY:
|
|
333
|
+
{"category_c": {"renamed_files": [...], "renamed_exports": [...]}}
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
The parent merges the three slices (plus Category D and the `degraded_mode`/`update_mode` flags) into the single category-JSON object §3 pipes to the `build` helper.
|
|
309
337
|
|
|
310
338
|
**Category D — Script/asset file changes:**
|
|
311
339
|
|
|
@@ -334,9 +362,14 @@ Translate the helper's output into the change manifest:
|
|
|
334
362
|
- `DELETED_FILE` rows → add to manifest as DELETED_FILE
|
|
335
363
|
- `UNCHANGED` rows → omit from the manifest (no action needed)
|
|
336
364
|
|
|
337
|
-
The helper
|
|
365
|
+
The compare helper reports only tracked files; NEW_FILE detection (a file present in source but absent from the provenance map) is a set-difference, so it runs through a script rather than the prompt. Pipe the same deterministic detector create-skill step 3 §4c uses (resolved via `detectScriptsAssetsProbeOrder`) into `{newFileDiffHelper}`, which subtracts the provenance map's `file_entries[].source_file` and sets aside user-authored `[MANUAL]` paths:
|
|
338
366
|
|
|
339
|
-
|
|
367
|
+
```bash
|
|
368
|
+
uv run {detectScriptsAssetsHelper} detect <source-root> \
|
|
369
|
+
| uv run {newFileDiffHelper} {forge_version}/provenance-map.json
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
It emits `{"new_files":[{source_file, kind}], "skipped_manual":[...], "already_tracked":[...], "stats":{...}}`. Add each `new_files[]` entry to the manifest as NEW_FILE — `kind` (`script`/`asset`) selects the target array. `skipped_manual[]` are user-authored files under `scripts/[MANUAL]/` or `assets/[MANUAL]/`, preserved and not touched; `already_tracked[]` were handled by the compare above.
|
|
340
373
|
|
|
341
374
|
Aggregate all subprocess results into a unified change manifest.
|
|
342
375
|
|
|
@@ -356,7 +389,7 @@ echo "{category JSON}" | uv run {buildChangeManifestHelper} deletion-ratio \
|
|
|
356
389
|
--provenance-map {forge_version}/provenance-map.json
|
|
357
390
|
```
|
|
358
391
|
|
|
359
|
-
The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. The output envelope:
|
|
392
|
+
The helper handles the three skip conditions internally — when the input has `update_mode: "gap-driven"`, `degraded_mode: true`, or the provenance has zero entries, it returns `skip_reason` set and `should_trigger: false`. `should_trigger` fires when the deletion ratio reaches the fixed bundled threshold of 50% (`ratio >= 0.50`, baked into the helper — not configurable). The output envelope:
|
|
360
393
|
|
|
361
394
|
```json
|
|
362
395
|
{
|
|
@@ -399,8 +432,6 @@ The upstream surface appears to have been substantially replaced. The brief's
|
|
|
399
432
|
- **[B] Brief:** halt with status `halted-for-brief-refinement`. Display: `"Halting update-skill. Re-run skf-brief-skill to refine scope for {skill_name}, then re-run skf-update-skill."` Change manifest discarded — no partial writes.
|
|
400
433
|
- **[A] Audit:** halt with status `halted-for-audit`. Display: `"Halting update-skill. Run skf-audit-skill against {skill_name} to map the new surface — its drift report will feed §1c on the next update-skill run."` Change manifest discarded.
|
|
401
434
|
|
|
402
|
-
**Why both §1c and §2.2:** §1c is precise (per-path P/S/U) but requires upstream signal from audit-skill. §2.2 is coarse (single halt/continue) but self-contained — it fires even when the user runs update-skill directly without audit. Together they cover the major-version case across the two real workflows.
|
|
403
|
-
|
|
404
435
|
### 3. Build Change Manifest
|
|
405
436
|
|
|
406
437
|
Hand the assembled Category A/B/C/D JSON to the helper:
|
|
@@ -460,7 +491,7 @@ The skill `{skill_name}` is current — no update needed.
|
|
|
460
491
|
|
|
461
492
|
→ Skip steps 03-06, immediately load {noChangeReportFile} with "no changes" status.
|
|
462
493
|
|
|
463
|
-
### 5. Display Change Summary and
|
|
494
|
+
### 5. Display Change Summary and Route
|
|
464
495
|
|
|
465
496
|
"**Change Detection Complete:**
|
|
466
497
|
|
|
@@ -470,30 +501,11 @@ The skill `{skill_name}` is current — no update needed.
|
|
|
470
501
|
| Files added | {count} |
|
|
471
502
|
| Files deleted | {count} |
|
|
472
503
|
| Files moved/renamed | {count} |
|
|
473
|
-
| Exports affected | {total_export_changes} |
|
|
474
|
-
|
|
475
|
-
**Proceeding to re-extraction of {affected_file_count if normal mode, or gap_count if gap-driven mode} changes...**"
|
|
476
|
-
|
|
477
|
-
### 6. Present MENU OPTIONS
|
|
478
|
-
|
|
479
|
-
Display: "**Proceeding to re-extraction...**"
|
|
480
|
-
|
|
481
|
-
#### Menu Handling Logic:
|
|
482
|
-
|
|
483
|
-
- **If `detect_only_mode` is true:** display "**Detect-only mode — skipping re-extract/merge/validate/write.** Loading report..." and load `{noChangeReportFile}` (report.md). The report handles the detect-only envelope. Do NOT load `{nextStepFile}`.
|
|
484
|
-
- Else, after change manifest is built, immediately load, read entire file, then execute `{nextStepFile}`.
|
|
485
|
-
- **EXCEPTION:** If no changes detected (section 4), load `{noChangeReportFile}` instead.
|
|
486
|
-
|
|
487
|
-
#### EXECUTION RULES:
|
|
488
|
-
|
|
489
|
-
- This is an auto-proceed step with no user choices
|
|
490
|
-
- Proceed directly to next step after change detection completes (or to report when `detect_only_mode` is true)
|
|
491
|
-
|
|
492
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
504
|
+
| Exports affected | {total_export_changes} |"
|
|
493
505
|
|
|
494
|
-
|
|
506
|
+
This step auto-proceeds — no user choices. Once the change manifest is fully built, load and fully read the next file, then execute it, per the branch that applies:
|
|
495
507
|
|
|
496
|
-
-
|
|
497
|
-
- No changes detected → load `{noChangeReportFile}` (report.md)
|
|
498
|
-
- Otherwise → load `{nextStepFile}` (re-extract.md) to begin re-extraction.
|
|
508
|
+
- **`detect_only_mode == true`** → display "**Detect-only mode — skipping re-extract/merge/validate/write.** Loading report..." and load `{noChangeReportFile}` (report.md), which emits status `detect-only`. Do not load `{nextStepFile}`.
|
|
509
|
+
- **No changes detected** (section 4) → load `{noChangeReportFile}` (report.md), which emits status `no-changes`.
|
|
510
|
+
- **Otherwise** → display "**Proceeding to re-extraction of {affected_file_count if normal mode, or gap_count if gap-driven mode} changes...**" and load `{nextStepFile}` (re-extract.md) to begin re-extraction.
|
|
499
511
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
# `shared/health-check.md` resolves relative to the SKF module root
|
|
3
|
-
# (`_bmad/skf/` when installed, `src/` during
|
|
4
|
-
# to this step file.
|
|
3
|
+
# (`{project-root}/_bmad/skf/` when installed, `{project-root}/src/` during
|
|
4
|
+
# development), NOT relative to this step file.
|
|
5
5
|
nextStepFile: 'shared/health-check.md'
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -11,15 +11,9 @@ nextStepFile: 'shared/health-check.md'
|
|
|
11
11
|
|
|
12
12
|
## STEP GOAL:
|
|
13
13
|
|
|
14
|
-
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done.
|
|
14
|
+
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done. This step only releases the concurrency lock and delegates: no user-facing reports, file writes, or result contracts here (those belong in step 7).
|
|
15
15
|
|
|
16
|
-
##
|
|
17
|
-
|
|
18
|
-
- No user-facing reports, file writes, or result contracts in this step — those belong in step 7
|
|
19
|
-
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
20
|
-
- Do not attempt any other action between loading this step and executing `{nextStepFile}` (other than the lock release below)
|
|
21
|
-
|
|
22
|
-
## MANDATORY SEQUENCE
|
|
16
|
+
## Steps
|
|
23
17
|
|
|
24
18
|
1. **Release the concurrency lock** acquired by init.md §1b (skip when `detect_only_mode` or `dry_run_mode` is true — those modes never acquired one):
|
|
25
19
|
|
|
@@ -27,6 +21,6 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
|
|
|
27
21
|
rm -f "{forge_data_folder}/{skill_name}/.skf-update.lock"
|
|
28
22
|
```
|
|
29
23
|
|
|
30
|
-
|
|
24
|
+
Release the lock before delegating to the shared health-check: the health-check is the terminal step, so once it returns the workflow is done and any still-held lock is orphaned until the next run clears it. Releasing here keeps the lock lifecycle tight against the workflow's actual span.
|
|
31
25
|
|
|
32
26
|
2. Load `{nextStepFile}`, read it fully, then execute it.
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'detect-changes.md'
|
|
3
3
|
manualSectionRulesFile: 'references/manual-section-rules.md'
|
|
4
|
+
# Resolve `{hashContentHelper}` to the first existing path; HALT if neither
|
|
5
|
+
# candidate exists. §5 uses its `manual-inventory` subcommand to capture the
|
|
6
|
+
# exact pre-write [MANUAL] inventory (per-block byte-exact interior hashes),
|
|
7
|
+
# which write.md §1 (HALT gate) and validate.md Check B later verify against.
|
|
8
|
+
# An LLM marker-count would miss an interior truncation that leaves the marker
|
|
9
|
+
# count unchanged.
|
|
10
|
+
hashContentProbeOrder:
|
|
11
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-hash-content.py'
|
|
12
|
+
- '{project-root}/src/shared/scripts/skf-hash-content.py'
|
|
4
13
|
---
|
|
5
14
|
|
|
6
15
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -16,7 +25,7 @@ Load the existing skill and all its provenance data, detect whether this is an i
|
|
|
16
25
|
- Focus only on loading existing artifacts and establishing the baseline — read-only operations
|
|
17
26
|
- Do not begin change detection (Step 02)
|
|
18
27
|
|
|
19
|
-
##
|
|
28
|
+
## Steps
|
|
20
29
|
|
|
21
30
|
### 1. Request Skill Path
|
|
22
31
|
|
|
@@ -27,6 +36,7 @@ Provide either:
|
|
|
27
36
|
- A full path to the skill folder
|
|
28
37
|
- A skill name with `--from-test-report` to use the test report's gap findings instead of source drift detection
|
|
29
38
|
- `--allow-workspace-drift` (gap-driven mode only) to intentionally bypass the step 3 §0.a guard that halts when the local workspace HEAD does not match `metadata.source_commit`. Only use this if you know the spot-checks should read the current workspace instead of the pinned tree — step 6 will NOT automatically re-pin
|
|
39
|
+
- `--allow-degraded` (headless mode only) to pre-authorize the lossy degraded full re-extraction if §4 finds no provenance map — without it, a headless run halts `blocked` there rather than silently rebuilding
|
|
30
40
|
- `--detect-only` to run detect-changes only and exit; emits the change manifest with no further work and no writes
|
|
31
41
|
- `--dry-run` to run detect-changes + re-extract and exit before merge/write; emits what WOULD change without modifying any artifact
|
|
32
42
|
|
|
@@ -38,6 +48,7 @@ Provide either:
|
|
|
38
48
|
3. If not in manifest: check for `active` symlink at `{skills_output_folder}/{skill-name}/active` — resolve to `{skill_group}/active/{skill-name}/`
|
|
39
49
|
4. If neither: fall back to flat path `{skills_output_folder}/{skill-name}/`. If SKILL.md exists at the flat path, auto-migrate per `knowledge/version-paths.md` migration rules
|
|
40
50
|
5. Store the resolved path as `{resolved_skill_package}` for all subsequent artifact loading
|
|
51
|
+
6. Bind `{baseline_version}` to the pre-update version — for an update this is the version being updated, i.e. the `{active_version}` resolved in step 1 above (the flat-path fallback in step 4 has no version, so use the package version read from metadata.json in §2). Step 2 §1c passes `{baseline_version}` to `skf-provenance-gap-dispatch.py` as a required argument; leaving it unbound makes the helper search a wrong/empty directory and silently return `no-report`, dropping the major-version off-ramp.
|
|
41
52
|
|
|
42
53
|
Resolve the path to an absolute skill folder location.
|
|
43
54
|
|
|
@@ -53,6 +64,8 @@ If a report is located, set `test_report_path` in context to the resolved absolu
|
|
|
53
64
|
|
|
54
65
|
**If `--allow-workspace-drift` was provided:** set `allow_workspace_drift: true` in workflow context. This flag is consumed by step 3 §0.a's pre-flight drift guard (gap-driven mode only) and has no effect in normal source-drift mode.
|
|
55
66
|
|
|
67
|
+
**If `--allow-degraded` was provided:** set `allow_degraded: true` in workflow context. This flag is consumed by §4 below when no provenance map is found under `{headless_mode}`; it has no effect interactively (the [D]/[X] prompt is shown) or when a provenance map is present.
|
|
68
|
+
|
|
56
69
|
**If `--detect-only` was provided:** set `detect_only_mode: true` in workflow context. After step 2 (detect-changes) completes, jump directly to step 7 (report) — skip re-extract, merge, validate, and write. The report emits the change manifest and a `SKF_UPDATE_RESULT_JSON` envelope with `status: "detect-only"`. **Compatibility:** `--detect-only` short-circuits before §0.a runs, so `--allow-workspace-drift` is silently ignored in detect-only mode (warn the user once at flag-parse time: "`--allow-workspace-drift` has no effect with `--detect-only` — workspace drift guard runs in step 3 §0.a, which is skipped").
|
|
57
70
|
|
|
58
71
|
**If `--dry-run` was provided:** set `dry_run_mode: true` in workflow context. After step 3 (re-extract) completes, jump directly to step 7 (report) — skip merge, validate, and write. The report emits what would change with `status: "dry-run"` in the envelope. No artifact on disk is modified — `--dry-run` is the "show me what an update would do without committing" mode.
|
|
@@ -80,8 +93,8 @@ if [ -f "$LOCK" ]; then
|
|
|
80
93
|
# (LLM emits SKF_UPDATE_RESULT_JSON status=halted-for-concurrent-run, see below)
|
|
81
94
|
exit 1
|
|
82
95
|
fi
|
|
83
|
-
#
|
|
84
|
-
echo "skf-update-skill: clearing
|
|
96
|
+
# Dead PID — lock left by a prior halted or crashed run; clear + overwrite
|
|
97
|
+
echo "skf-update-skill: clearing lock from a prior halted/crashed run (pid=$HELD_PID)"
|
|
85
98
|
fi
|
|
86
99
|
|
|
87
100
|
# Acquire: write our PID + start timestamp (one per line)
|
|
@@ -95,9 +108,9 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
|
|
|
95
108
|
|
|
96
109
|
**Release contract:**
|
|
97
110
|
|
|
98
|
-
- The terminal health-check step (step 8) deletes the lock
|
|
99
|
-
-
|
|
100
|
-
- The lock is best-effort: a crash
|
|
111
|
+
- The terminal health-check step (step 8) deletes the lock as its final action — the normal end of every non-inspection run. The two init-stage headless halts below (§4 no-provenance-map, §6 invalid-source-path) also delete it explicitly, since they fire right after acquisition, before the terminal step runs.
|
|
112
|
+
- Mid-workflow halts (detect-changes, re-extract, merge, write) do **not** delete the lock themselves — they rely on the self-heal below. This is deliberate: several of those halt sites are also reachable under `--detect-only`/`--dry-run`, which never acquired this lock, so a blind `rm -f` there could clobber a concurrent real update's lock.
|
|
113
|
+
- The lock is best-effort and self-healing: whatever a halt or crash (process kill, host reboot) leaves behind is cleared by the next run's live-PID check above, since the stored PID is a short-lived bash PID that is already dead. No manual cleanup needed in the common case.
|
|
101
114
|
|
|
102
115
|
### 2. Validate Required Artifacts
|
|
103
116
|
|
|
@@ -112,7 +125,7 @@ printf '%s\n%s\n' "$$" "$(date -u +%Y-%m-%dT%H:%M:%SZ)" > "$LOCK"
|
|
|
112
125
|
|
|
113
126
|
**Detect skill type from metadata:**
|
|
114
127
|
- If `skill_type == "single"` or absent: flag as single skill
|
|
115
|
-
- If `skill_type == "stack"`: flag as stack skill
|
|
128
|
+
- If `skill_type == "stack"`: flag as stack skill — the guard below redirects it
|
|
116
129
|
|
|
117
130
|
### Stack Skill Guard
|
|
118
131
|
|
|
@@ -125,6 +138,8 @@ After loading metadata.json, check `skill_type`:
|
|
|
125
138
|
If you came here from an audit report, the drift report identifies which constituent libraries changed — use that to decide whether re-composition is needed."
|
|
126
139
|
- Exit the workflow (do not proceed to step 2)
|
|
127
140
|
|
|
141
|
+
**This guard is the single gate for stack skills** — every stack is redirected to `skf-create-stack-skill` here, before step 2, and no flag (`--detect-only`, `--dry-run`, `--from-test-report`, `--allow-workspace-drift`) bypasses it. Every later stage therefore runs against a single skill only and carries no stack-merge branch.
|
|
142
|
+
|
|
128
143
|
### 3. Load Forge Tier Configuration
|
|
129
144
|
|
|
130
145
|
**Load `{sidecar_path}/forge-tier.yaml`:**
|
|
@@ -159,18 +174,22 @@ Select: [D] Degraded / [X] Abort"
|
|
|
159
174
|
- If D: set `degraded_mode = true`, proceed with full extraction scope
|
|
160
175
|
- If X: **ABORT**
|
|
161
176
|
|
|
177
|
+
**In `{headless_mode}` without `--allow-degraded` (default):** do not auto-select [D]. Degraded mode is a full, lossy T1-low re-extraction — choosing it unattended would silently swap surgical update for a create-skill-equivalent rebuild, a policy call that belongs to an operator. Halt instead: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:load-provenance-map", path: "{forge_version}/provenance-map.json", reason: "no provenance map at versioned or flat path; degraded full re-extraction needs a human decision"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
|
|
178
|
+
|
|
179
|
+
**In `{headless_mode}` with `--allow-degraded` (`allow_degraded: true`):** the operator pre-authorized the lossy rebuild for this run, so treat it as an auto-resolved [D] rather than a halt. Set `degraded_mode = true`, proceed with full extraction scope, and append to in-context `headless_decisions[]`: `{gate: "init.degraded-rebuild", default_action: "X", taken_action: "D", reason: "headless: --allow-degraded pre-authorized degraded full re-extraction", evidence: "no provenance map at {forge_version}/provenance-map.json or flat fallback"}`. Continue to step 2.
|
|
180
|
+
|
|
162
181
|
### 5. Load [MANUAL] Section Inventory
|
|
163
182
|
|
|
164
|
-
Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
|
|
183
|
+
Load {manualSectionRulesFile} to understand [MANUAL] detection patterns (the human-readable rules for markers, parent-section mapping, and orphan/nesting handling).
|
|
165
184
|
|
|
166
|
-
**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
185
|
+
**Capture the [MANUAL] inventory deterministically.** The workflow's headline rule is "[MANUAL] sections survive regeneration with zero content loss" — the pre-write inventory captured here is the exact baseline that write.md §1 and validate.md Check B verify against, so it must be a per-block byte-exact hash, not an eyeballed marker count. Run the `manual-inventory` subcommand of `{hashContentHelper}` and persist its JSON:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
uv run {hashContentHelper} manual-inventory {resolved_skill_package}/SKILL.md \
|
|
189
|
+
> {forge_version}/.manual-inventory.json
|
|
190
|
+
```
|
|
170
191
|
|
|
171
|
-
|
|
172
|
-
- All `references/*.md` files for [MANUAL] markers
|
|
173
|
-
- All `references/integrations/*.md` files for [MANUAL] markers
|
|
192
|
+
The emitted JSON is `{"blocks":[{name, content_hash, byte_offset, parent_heading}...], "count":N}` — each `content_hash` covers the block's byte-exact interior, so a later interior truncation that leaves the marker count unchanged is still caught. Bind the persisted path as `{manual_inventory}` in context; write.md §1 and validate.md Check B pass it to `manual-verify`. Surface the block `count` in the baseline summary (§7 `{manual_count}`).
|
|
174
193
|
|
|
175
194
|
### 6. Resolve Source Code Path
|
|
176
195
|
|
|
@@ -185,6 +204,8 @@ Load {manualSectionRulesFile} to understand [MANUAL] detection patterns.
|
|
|
185
204
|
Provide the current source code path:
|
|
186
205
|
**Path:** {user provides path}"
|
|
187
206
|
|
|
207
|
+
**In `{headless_mode}`:** there is no operator to supply a path. Halt: release the lock (`rm -f "$LOCK"`), emit `SKF_UPDATE_RESULT_JSON` with `status: "blocked"`, `error: {phase: "init:resolve-source-path", path: "{source_root}", reason: "source_root from provenance map is invalid or inaccessible and no interactive path can be supplied"}`, and exit. No `headless_decisions[]` entry — this is a hard halt, not an auto-resolved gate.
|
|
208
|
+
|
|
188
209
|
### 7. Present Baseline Summary
|
|
189
210
|
|
|
190
211
|
"**Update Skill Baseline:**
|
|
@@ -192,7 +213,7 @@ Provide the current source code path:
|
|
|
192
213
|
| Property | Value |
|
|
193
214
|
|----------|-------|
|
|
194
215
|
| **Skill** | {skill_name} |
|
|
195
|
-
| **Type** |
|
|
216
|
+
| **Type** | single |
|
|
196
217
|
| **Version** | {version} |
|
|
197
218
|
| **Created** | {created date} |
|
|
198
219
|
| **Source** | {source_root} |
|
|
@@ -209,22 +230,9 @@ Provide the current source code path:
|
|
|
209
230
|
|
|
210
231
|
**Ready to detect changes and update this skill?**"
|
|
211
232
|
|
|
212
|
-
### 8.
|
|
213
|
-
|
|
214
|
-
Display: "**Select:** [C] Continue to Change Detection"
|
|
215
|
-
|
|
216
|
-
#### Menu Handling Logic:
|
|
217
|
-
|
|
218
|
-
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
219
|
-
- IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
|
|
220
|
-
|
|
221
|
-
#### EXECUTION RULES:
|
|
222
|
-
|
|
223
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
224
|
-
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past update confirmation". **Also append to in-context `headless_decisions[]`** (step 7 surfaces this list in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. The headless_decisions[] array is the structured audit trail for non-interactive runs — see `src/shared/scripts/schemas/skf-update-result-envelope.v1.json` for the entry shape.
|
|
225
|
-
- ONLY proceed to next step when user selects 'C'
|
|
233
|
+
### 8. Confirmation Gate
|
|
226
234
|
|
|
227
|
-
|
|
235
|
+
Present "**Select:** [C] Continue to Change Detection" and wait for the user to confirm; on [C], load, read the full file, then execute {nextStepFile}.
|
|
228
236
|
|
|
229
|
-
|
|
237
|
+
**Headless (`{headless_mode}` true):** auto-continue and append to in-context `headless_decisions[]` (step 7 surfaces it in `SKF_UPDATE_RESULT_JSON`): `{gate: "init.update-confirmation", default_action: "C", taken_action: "C", reason: "headless: no user to prompt"}`. Entry shape: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`.
|
|
230
238
|
|
|
@@ -26,8 +26,7 @@ It must be preserved during any update operation.
|
|
|
26
26
|
2. **Preserve marker positions** — if the surrounding generated content moves, the [MANUAL] block moves with its logical parent section
|
|
27
27
|
3. **Orphan detection** — if the parent section is deleted (export removed), flag as WARNING and present to user
|
|
28
28
|
4. **Multiple [MANUAL] blocks** — a single SKILL.md may have multiple [MANUAL] sections; preserve all
|
|
29
|
-
5. **
|
|
30
|
-
6. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
|
|
29
|
+
5. **Nested [MANUAL] forbidden** — [MANUAL] blocks cannot be nested; if detected, flag as ERROR
|
|
31
30
|
|
|
32
31
|
### Conflict Types
|
|
33
32
|
|
|
@@ -4,58 +4,7 @@ type: static-reference
|
|
|
4
4
|
|
|
5
5
|
# Merge Conflict Rules
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
### Category 1: Modified Exports (signature/type change)
|
|
10
|
-
|
|
11
|
-
- **Action:** Re-extract affected export with fresh AST analysis
|
|
12
|
-
- **Merge:** Replace generated content for that export; preserve adjacent [MANUAL] blocks
|
|
13
|
-
- **Confidence:** Same tier as original (T1/T1-low/T2)
|
|
14
|
-
|
|
15
|
-
### Category 2: New Exports (added since last generation)
|
|
16
|
-
|
|
17
|
-
- **Action:** Extract new export with full AST analysis
|
|
18
|
-
- **Merge:** Append to appropriate section based on export type (function, type, class, constant)
|
|
19
|
-
- **Confidence:** Label with extraction tier confidence
|
|
20
|
-
- **[MANUAL] impact:** None — new content, no existing [MANUAL] blocks
|
|
21
|
-
|
|
22
|
-
### Category 3: Deleted Exports (removed from source)
|
|
23
|
-
|
|
24
|
-
- **Action:** Remove generated content for that export
|
|
25
|
-
- **Merge:** Check for attached [MANUAL] blocks before deletion
|
|
26
|
-
- **If [MANUAL] attached:** Flag as orphan, present to user for decision
|
|
27
|
-
- **If no [MANUAL]:** Auto-remove generated content
|
|
28
|
-
|
|
29
|
-
### Category 4: Moved Exports (file relocated)
|
|
30
|
-
|
|
31
|
-
- **Action:** Update provenance map file references
|
|
32
|
-
- **Merge:** Update file:line citations in generated content
|
|
33
|
-
- **Confidence:** Retain original tier if AST structure unchanged; downgrade to T1-low if structure changed
|
|
34
|
-
- **[MANUAL] impact:** Preserve — content unchanged, only provenance metadata updates
|
|
35
|
-
|
|
36
|
-
### Category 5: Renamed Exports (identifier changed)
|
|
37
|
-
|
|
38
|
-
- **Action:** Re-extract with new identifier
|
|
39
|
-
- **Merge:** Replace old identifier references in generated content
|
|
40
|
-
- **[MANUAL] impact:** Flag if [MANUAL] blocks reference old identifier name
|
|
41
|
-
|
|
42
|
-
## Merge Priority Order
|
|
43
|
-
|
|
44
|
-
1. Process deleted exports first (remove generated content, flag [MANUAL] orphans)
|
|
45
|
-
2. Process moved exports second (update references only)
|
|
46
|
-
3. Process renamed exports third (update identifiers)
|
|
47
|
-
4. Process modified exports fourth (re-extract and replace)
|
|
48
|
-
5. Process new exports last (append to sections)
|
|
49
|
-
|
|
50
|
-
## Stack Skill Merge Rules
|
|
51
|
-
|
|
52
|
-
For stack skills with multi-file outputs:
|
|
53
|
-
|
|
54
|
-
1. **SKILL.md:** Apply standard merge rules above
|
|
55
|
-
2. **references/{library}.md:** Merge per-library, preserving [MANUAL] blocks within each
|
|
56
|
-
3. **references/integrations/{pair}.md:** Merge per-integration-pair
|
|
57
|
-
4. **metadata.json:** Regenerate completely (no [MANUAL] support in JSON)
|
|
58
|
-
5. **context-snippet.md:** Regenerate completely (no [MANUAL] support — too concise)
|
|
7
|
+
> Change-category actions and the merge priority order (deleted → moved → renamed → modified → new, plus the gap-driven priorities) are specified authoritatively in `merge.md` §3. This reference carries only the one thing §3 does not: the conflict-resolution strategy table below.
|
|
59
8
|
|
|
60
9
|
## Conflict Resolution Strategies
|
|
61
10
|
|
|
@@ -10,21 +10,21 @@ mergeConflictRulesFile: 'references/merge-conflict-rules.md'
|
|
|
10
10
|
|
|
11
11
|
## STEP GOAL:
|
|
12
12
|
|
|
13
|
-
Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content.
|
|
13
|
+
Merge freshly extracted export data into the existing SKILL.md content while preserving all [MANUAL] sections. Detect and resolve conflicts where regenerated content overlaps developer-authored content.
|
|
14
14
|
|
|
15
15
|
## Rules
|
|
16
16
|
|
|
17
17
|
- Focus only on merging extractions into existing skill content
|
|
18
18
|
- Never delete or modify [MANUAL] section content
|
|
19
|
-
- Write merged SKILL.md
|
|
19
|
+
- Write merged SKILL.md directly to disk at section 6b — Claude Code's Edit/Write tools commit on call, so there is no held-in-memory "edit plan" primitive; subsequent steps validate and verify against the on-disk files
|
|
20
20
|
- If [MANUAL] conflicts detected: halt and present to user. If clean merge: auto-proceed
|
|
21
21
|
|
|
22
|
-
##
|
|
22
|
+
## Steps
|
|
23
23
|
|
|
24
24
|
### 1. Load Merge Rules
|
|
25
25
|
|
|
26
26
|
Load {manualSectionRulesFile} for [MANUAL] detection and preservation patterns.
|
|
27
|
-
Load {mergeConflictRulesFile} for change
|
|
27
|
+
Load {mergeConflictRulesFile} for the conflict-resolution strategy table (the change-category actions and priority order live in §3 below).
|
|
28
28
|
|
|
29
29
|
### 2. Extract [MANUAL] Blocks
|
|
30
30
|
|
|
@@ -35,7 +35,7 @@ From the [MANUAL] inventory captured in step 01:
|
|
|
35
35
|
|
|
36
36
|
### 3. Apply Merge by Priority Order
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Apply merge in the following priority order:
|
|
39
39
|
|
|
40
40
|
**Priority 1 — Process DELETED exports:**
|
|
41
41
|
- Remove generated content for deleted exports
|
|
@@ -146,20 +146,6 @@ Select: [K] Keep / [R] Remove / [E] Edit"
|
|
|
146
146
|
|
|
147
147
|
Process each conflict with user's decision.
|
|
148
148
|
|
|
149
|
-
### 5. Stack Skill Merge (Conditional)
|
|
150
|
-
|
|
151
|
-
**ONLY if skill_type == "stack":**
|
|
152
|
-
|
|
153
|
-
Apply the same merge process to each stack output file:
|
|
154
|
-
- `references/{library}.md` — merge per-library changes, preserve [MANUAL] blocks
|
|
155
|
-
- `references/integrations/{pair}.md` — merge per-integration-pair
|
|
156
|
-
- `metadata.json` — regenerate completely (no [MANUAL] support)
|
|
157
|
-
- `context-snippet.md` — regenerate completely (no [MANUAL] support)
|
|
158
|
-
|
|
159
|
-
Report stack file merge status for each file.
|
|
160
|
-
|
|
161
|
-
**If skill_type != "stack":** Skip with notice: "Individual skill — single file merge."
|
|
162
|
-
|
|
163
149
|
### 6. Compile Merge Results
|
|
164
150
|
|
|
165
151
|
Build merge result summary:
|
|
@@ -176,30 +162,22 @@ Merge Results:
|
|
|
176
162
|
manual_conflicts_resolved: [count]
|
|
177
163
|
manual_orphans_kept: [count]
|
|
178
164
|
manual_orphans_removed: [count]
|
|
179
|
-
|
|
180
|
-
stack_files_merged: [count] (if stack skill)
|
|
181
165
|
```
|
|
182
166
|
|
|
183
167
|
### 6b. Write Merged Files to Disk
|
|
184
168
|
|
|
185
|
-
Write the merged content produced by sections 3–
|
|
169
|
+
Write the merged content produced by sections 3–4 directly to disk now. Later steps read from these files for validation and verification. The write must happen exactly once, here.
|
|
186
170
|
|
|
187
171
|
**Write SKILL.md:**
|
|
188
172
|
- Use the `Edit` or `Write` tool to write merged SKILL.md content to `{skill_package}/SKILL.md`
|
|
189
173
|
- Preserve UTF-8 encoding
|
|
190
174
|
- If the source version detected during step 3 differs from the previous metadata version, create the new `{skill_package}` directory (`{skill_group}/{new_version}/`) first and write there — the previous version's directory is preserved on disk. Update `{skill_package}` in context to point at the new path.
|
|
191
175
|
|
|
192
|
-
**Write stack reference files (if `skill_type == "stack"`):**
|
|
193
|
-
- For each affected file from section 5, use `Edit` or `Write` to write:
|
|
194
|
-
- `references/{library}.md` with merged per-library content
|
|
195
|
-
- `references/integrations/{pair}.md` with merged per-integration content
|
|
196
|
-
- Preserve [MANUAL] blocks exactly as captured in section 2.
|
|
197
|
-
|
|
198
176
|
**Do NOT write here:**
|
|
199
177
|
- `metadata.json`, `provenance-map.json`, `evidence-report.md` — derived from merge + validation output, written by step 6 sections 2–4
|
|
200
178
|
- `context-snippet.md` — regenerated from the on-disk SKILL.md + metadata.json by step 6 section 5
|
|
201
179
|
|
|
202
|
-
**Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill.
|
|
180
|
+
**Halt-on-tool-failure:** If any `Edit`/`Write` call errors (permission denied, disk full, path invalid, etc.), halt with status `halted-for-write-failure` and report the failure — do not proceed to step 5 validation. The skill package may be in a partial state and will need manual recovery before re-running update-skill. In `{headless_mode}`, emit the halt envelope per SKILL.md §Headless (`error: {phase: "merge:write-skill-md", path: "{skill_package}/SKILL.md", reason: "..."}`).
|
|
203
181
|
|
|
204
182
|
### 7. Display Merge Summary
|
|
205
183
|
|
|
@@ -213,36 +191,14 @@ Write the merged content produced by sections 3–5 directly to disk now. Later
|
|
|
213
191
|
| [MANUAL] sections preserved | {count} |
|
|
214
192
|
| Conflicts resolved | {count} |"
|
|
215
193
|
|
|
216
|
-
### 8.
|
|
217
|
-
|
|
218
|
-
**If conflicts were resolved (user interaction occurred):**
|
|
219
|
-
|
|
220
|
-
Display: "**Merge complete with conflict resolution. Select:** [C] Continue to Validation"
|
|
221
|
-
|
|
222
|
-
#### Menu Handling Logic:
|
|
223
|
-
|
|
224
|
-
- IF C: Load, read entire file, then execute {nextStepFile}
|
|
225
|
-
- IF Any other: help user respond, then [Redisplay Menu Options](#8-present-menu-options)
|
|
226
|
-
|
|
227
|
-
#### EXECUTION RULES:
|
|
228
|
-
|
|
229
|
-
- ALWAYS halt and wait for user input after conflict resolution
|
|
230
|
-
- **GATE [default: C if clean merge]** — If `{headless_mode}` and merge is clean (no [MANUAL] conflicts): auto-proceed with [C] Continue, log: "headless: clean merge, auto-continue". **Also append to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`. If conflicts exist, HALT even in headless mode — conflicts require human judgment, and the headless_decisions[] array does NOT get a continue-on-conflict entry (the workflow status becomes `halted-for-manual-mismatch` instead).
|
|
231
|
-
- ONLY proceed when user selects 'C'
|
|
232
|
-
|
|
233
|
-
**If clean merge (no conflicts):**
|
|
234
|
-
|
|
235
|
-
Display: "**Clean merge — proceeding to validation...**"
|
|
236
|
-
|
|
237
|
-
#### Clean Merge Menu Handling Logic:
|
|
238
|
-
|
|
239
|
-
- Immediately load, read entire file, then execute {nextStepFile}
|
|
194
|
+
### 8. Gate to Validation
|
|
240
195
|
|
|
241
|
-
|
|
196
|
+
**Clean merge (no conflicts):** display "**Clean merge — proceeding to validation...**", then load, read the full file, and execute {nextStepFile} (auto-proceed).
|
|
242
197
|
|
|
243
|
-
|
|
198
|
+
**Conflicts were resolved (user interaction occurred):** present "**Merge complete with conflict resolution. Select:** [C] Continue to Validation" and wait for the user to confirm before loading {nextStepFile}.
|
|
244
199
|
|
|
245
|
-
|
|
200
|
+
**Headless (`{headless_mode}` true):**
|
|
246
201
|
|
|
247
|
-
|
|
202
|
+
- Clean merge → auto-continue and append to in-context `headless_decisions[]` (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "merge.clean-merge-gate", default_action: "C", taken_action: "C", reason: "headless: clean merge, no conflicts to resolve"}`.
|
|
203
|
+
- Conflicts present → halt even in headless mode (conflicts require human judgment): status `halted-for-manual-mismatch`, emitting the halt envelope per SKILL.md §Headless (`error: {phase: "merge:conflict-resolution", reason: "..."}`); no `headless_decisions[]` entry is added.
|
|
248
204
|
|