bmad-module-skill-forge 1.4.0 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +0 -8
- package/docs/_data/pinned.yaml +1 -1
- package/docs/_internal/STABILITY.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/examples.md +1 -1
- package/docs/workflows.md +5 -5
- package/package.json +2 -2
- package/src/README.md +1 -1
- package/src/knowledge/ccc-bridge.md +12 -12
- package/src/knowledge/qmd-registry.md +5 -5
- package/src/shared/health-check.md +5 -5
- package/src/shared/references/description-guard-protocol.md +100 -0
- package/src/shared/references/output-contract-schema.md +1 -1
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
- package/src/shared/scripts/skf-build-change-manifest.py +420 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
- package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
- package/src/shared/scripts/skf-description-guard.py +359 -0
- package/src/shared/scripts/skf-detect-language.py +2 -2
- package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
- package/src/shared/scripts/skf-detect-tools.py +97 -8
- package/src/shared/scripts/skf-detect-workspaces.py +1 -1
- package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
- package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
- package/src/shared/scripts/skf-hash-content.py +284 -0
- package/src/shared/scripts/skf-load-provenance.py +295 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +45 -1
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
- package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
- package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
- package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
- package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
- package/src/skf-audit-skill/SKILL.md +66 -15
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
- package/src/skf-audit-skill/customize.toml +49 -0
- package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-audit-skill/references/init.md +305 -0
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -16
- package/src/skf-brief-skill/SKILL.md +48 -18
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
- package/src/skf-brief-skill/customize.toml +44 -0
- package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
- package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
- package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
- package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
- package/src/skf-brief-skill/references/headless-args.md +9 -9
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
- package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
- package/src/skf-brief-skill/references/version-resolution.md +2 -2
- package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
- package/src/skf-create-skill/SKILL.md +25 -19
- package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
- package/src/skf-create-skill/assets/skill-sections.md +5 -5
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
- package/src/skf-create-skill/customize.toml +35 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
- package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
- package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
- package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
- package/src/skf-create-skill/references/extraction-patterns.md +8 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +17 -9
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
- package/src/skf-create-stack-skill/SKILL.md +76 -17
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +46 -0
- package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
- package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
- package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
- package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
- package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
- package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
- package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
- package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
- package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
- package/src/skf-drop-skill/SKILL.md +84 -12
- package/src/skf-drop-skill/customize.toml +57 -0
- package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
- package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
- package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
- package/src/skf-export-skill/SKILL.md +85 -16
- package/src/skf-export-skill/assets/managed-section-format.md +3 -3
- package/src/skf-export-skill/assets/snippet-format.md +2 -2
- package/src/skf-export-skill/customize.toml +49 -0
- package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +18 -12
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +21 -51
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +30 -6
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +116 -91
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +14 -22
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
- package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
- package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
- package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
- package/src/skf-test-skill/references/health-check.md +14 -0
- package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
- package/src/skf-test-skill/references/migration-section-rules.md +4 -2
- package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
- package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
- package/src/skf-test-skill/references/scoring-rules.md +8 -6
- package/src/skf-test-skill/references/source-access-protocol.md +7 -5
- package/src/skf-test-skill/scripts/compute-score.py +88 -17
- package/src/skf-test-skill/templates/test-report-template.md +13 -13
- package/src/skf-update-skill/SKILL.md +23 -14
- package/src/skf-update-skill/customize.toml +44 -0
- package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
- package/src/skf-update-skill/references/health-check.md +32 -0
- package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
- package/src/skf-update-skill/references/manual-section-rules.md +4 -0
- package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
- package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
- package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
- package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
- package/src/skf-update-skill/references/report.md +214 -0
- package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
- package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
- package/src/skf-verify-stack/SKILL.md +89 -17
- package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
- package/src/skf-verify-stack/customize.toml +50 -0
- package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
- package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
- package/src/skf-verify-stack/references/init.md +166 -0
- package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
- package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
- package/tools/validate-docs-drift.js +1 -1
- package/src/skf-audit-skill/steps-c/step-01-init.md +0 -221
- package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
- package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
- package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
- package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
- package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
- package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
|
@@ -20,39 +20,39 @@ nextWorkflow: ''
|
|
|
20
20
|
# Test Report: {{skillName}}
|
|
21
21
|
|
|
22
22
|
<!--
|
|
23
|
-
Section order is LOAD-BEARING: step
|
|
23
|
+
Section order is LOAD-BEARING: step 5 §5 enforces it, step 6 §5 verifies
|
|
24
24
|
stepsCompleted against the canonical chain. Do not reorder or delete anchors.
|
|
25
25
|
|
|
26
26
|
Anchor / Step mapping:
|
|
27
|
-
Test Summary →
|
|
28
|
-
Coverage Analysis →
|
|
29
|
-
Coherence Analysis →
|
|
30
|
-
External Validation→
|
|
31
|
-
Completeness Score →
|
|
32
|
-
Gap Report →
|
|
27
|
+
Test Summary → detect-mode
|
|
28
|
+
Coverage Analysis → coverage-check
|
|
29
|
+
Coherence Analysis → coherence-check
|
|
30
|
+
External Validation→ external-validators
|
|
31
|
+
Completeness Score → score
|
|
32
|
+
Gap Report → report (includes Discovery Quality subsection)
|
|
33
33
|
-->
|
|
34
34
|
|
|
35
35
|
## Test Summary
|
|
36
36
|
|
|
37
|
-
<!-- Populated by
|
|
37
|
+
<!-- Populated by detect-mode §3 -->
|
|
38
38
|
|
|
39
39
|
## Coverage Analysis
|
|
40
40
|
|
|
41
|
-
<!-- Populated by
|
|
41
|
+
<!-- Populated by coverage-check §5 -->
|
|
42
42
|
|
|
43
43
|
## Coherence Analysis
|
|
44
44
|
|
|
45
|
-
<!-- Populated by
|
|
45
|
+
<!-- Populated by coherence-check §6 (naive or contextual variant) -->
|
|
46
46
|
|
|
47
47
|
## External Validation
|
|
48
48
|
|
|
49
|
-
<!-- Populated by
|
|
49
|
+
<!-- Populated by external-validators §5 -->
|
|
50
50
|
|
|
51
51
|
## Completeness Score
|
|
52
52
|
|
|
53
|
-
<!-- Populated by
|
|
53
|
+
<!-- Populated by score §6 -->
|
|
54
54
|
|
|
55
55
|
## Gap Report
|
|
56
56
|
|
|
57
|
-
<!-- Populated by
|
|
57
|
+
<!-- Populated by report §3-§4b (includes Discovery Quality subsection) -->
|
|
58
58
|
|
|
@@ -9,6 +9,15 @@ description: Smart regeneration preserving [MANUAL] sections after source change
|
|
|
9
9
|
|
|
10
10
|
Surgically updates existing skills when source code changes, preserving all [MANUAL] developer content while re-extracting only affected exports with full provenance tracking. Only changed exports are re-extracted — unchanged content is never touched. Every regenerated instruction must trace to code with file:line citations. Stack skills (`skill_type: "stack"` in metadata.json) are not supported by surgical update — use `skf-create-stack-skill` to re-compose from updated constituents. If a stack skill is provided, this workflow exits with a redirect message.
|
|
11
11
|
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
15
|
+
- `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
|
|
16
|
+
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
17
|
+
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
18
|
+
- `{skill-name}` resolves to the skill directory's basename.
|
|
19
|
+
- **Cross-skill data coupling:** stages in this workflow load four shared assets from `skf-create-skill` to keep extraction semantics aligned between create and update — `re-extract.md` pulls `extraction-patterns.md`, `extraction-patterns-tracing.md`, and `tier-degradation-rules.md` from `skf-create-skill/references/`; `remote-source-resolution.md` references `source-resolution-protocols.md`; `write.md` reads `skill-sections.md` from `skf-create-skill/assets/`. Update-skill assumes these files are present at install time and that their semantics are stable across the two skills' versions.
|
|
20
|
+
|
|
12
21
|
## Role
|
|
13
22
|
|
|
14
23
|
You are a precision code analyst operating in Ferris Surgeon mode. This is a surgical operation, not an exploratory session. You bring AST-backed structural analysis and provenance-driven change detection expertise, while the source code provides the ground truth.
|
|
@@ -19,8 +28,6 @@ These rules apply to every step in this workflow:
|
|
|
19
28
|
|
|
20
29
|
- Never hallucinate — every statement must have AST provenance
|
|
21
30
|
- [MANUAL] sections survive regeneration with zero content loss
|
|
22
|
-
- Read each step file completely before taking any action
|
|
23
|
-
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
24
31
|
- Only load one step file at a time — never preload future steps
|
|
25
32
|
- Always communicate in `{communication_language}`
|
|
26
33
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
@@ -29,23 +36,25 @@ These rules apply to every step in this workflow:
|
|
|
29
36
|
|
|
30
37
|
| # | Step | File | Auto-proceed |
|
|
31
38
|
|---|------|------|--------------|
|
|
32
|
-
| 1 | Initialize & Load |
|
|
33
|
-
| 2 | Detect Changes |
|
|
34
|
-
| 3 | Re-Extract |
|
|
35
|
-
| 4 | Merge |
|
|
36
|
-
| 5 | Validate |
|
|
37
|
-
| 6 | Write |
|
|
38
|
-
| 7 | Report |
|
|
39
|
-
| 8 | Workflow Health Check |
|
|
39
|
+
| 1 | Initialize & Load | references/init.md | No (confirm) |
|
|
40
|
+
| 2 | Detect Changes | references/detect-changes.md | Yes |
|
|
41
|
+
| 3 | Re-Extract | references/re-extract.md | Yes |
|
|
42
|
+
| 4 | Merge | references/merge.md | Yes |
|
|
43
|
+
| 5 | Validate | references/validate.md | Yes |
|
|
44
|
+
| 6 | Write | references/write.md | Yes |
|
|
45
|
+
| 7 | Report | references/report.md | Yes |
|
|
46
|
+
| 8 | Workflow Health Check | references/health-check.md | Yes |
|
|
40
47
|
|
|
41
48
|
## Invocation Contract
|
|
42
49
|
|
|
43
50
|
| Aspect | Detail |
|
|
44
51
|
|--------|--------|
|
|
45
52
|
| **Inputs** | skill_name [required] |
|
|
46
|
-
| **
|
|
47
|
-
| **
|
|
48
|
-
| **
|
|
53
|
+
| **Flags** | `--headless` / `-H` (auto-resolve all gates); `--from-test-report` (gap-driven mode); `--allow-workspace-drift` (gap-driven only — bypass §0.a pinning guard); `--detect-only` (run detect-changes only, exit before re-extract; envelope `status="detect-only"`); `--dry-run` (run detect-changes + re-extract, exit before merge/write; envelope `status="dry-run"` describes what would change). If both `--detect-only` and `--dry-run` are passed, `--detect-only` wins. |
|
|
54
|
+
| **Gates** | step 1: Confirm Gate [C] | step 4: Confirm Gate [C if clean merge, HALT if conflicts] |
|
|
55
|
+
| **Outputs** | Updated SKILL.md, updated provenance-map.json, evidence-report.md (none when `--detect-only` or `--dry-run` is set — those modes are read-only inspection paths) |
|
|
56
|
+
| **Concurrency** | Two simultaneous real-update runs against the same skill would corrupt provenance. init.md §1b acquires a PID-file lock at `{forge_data_folder}/{skill_name}/.skf-update.lock` before any artifact read; live-PID collisions halt with `status: "halted-for-concurrent-run"`. Stale locks (dead PID) are cleared silently with a warning. The lock is released by the terminal health-check step (step 8) and by every documented halt path. Read-only modes (`--detect-only`, `--dry-run`) skip the lock entirely — they're safe alongside a concurrent real update. |
|
|
57
|
+
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true. Each auto-resolved gate appends a `{gate, default_action, taken_action, reason, evidence?}` entry to `headless_decisions[]`, surfaced in step 7's `SKF_UPDATE_RESULT_JSON` envelope so non-interactive runs can be audited post-hoc. Pipeline branches on the envelope's top-level `status` field (`success`, `no-changes`, `detect-only`, `dry-run`, or one of the documented `halted-for-*` codes). The first four are successful exits — pipelines treating non-success as failure must include them in the success set. Schema: `src/shared/scripts/schemas/skf-update-result-envelope.v1.json`. |
|
|
49
58
|
|
|
50
59
|
## On Activation
|
|
51
60
|
|
|
@@ -55,4 +64,4 @@ These rules apply to every step in this workflow:
|
|
|
55
64
|
|
|
56
65
|
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
|
|
57
66
|
|
|
58
|
-
3. Load, read the full file, and then execute
|
|
67
|
+
3. Load, read the full file, and then execute `references/init.md` to begin the workflow.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-update-skill.
|
|
4
|
+
|
|
5
|
+
[workflow]
|
|
6
|
+
|
|
7
|
+
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
|
8
|
+
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
9
|
+
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
10
|
+
|
|
11
|
+
# Steps to run before the standard activation (uv probe, config load).
|
|
12
|
+
# Overrides append. Use for org-wide pre-flight checks (auth, network,
|
|
13
|
+
# compliance) that must precede any skill update work.
|
|
14
|
+
|
|
15
|
+
activation_steps_prepend = []
|
|
16
|
+
|
|
17
|
+
# Steps to run after activation but before the first stage executes.
|
|
18
|
+
# Overrides append. Use for context loads or banner customization that
|
|
19
|
+
# should run once activation completes successfully.
|
|
20
|
+
|
|
21
|
+
activation_steps_append = []
|
|
22
|
+
|
|
23
|
+
# Persistent facts the workflow keeps in mind for the whole run
|
|
24
|
+
# (drift policies, manual-section preservation rules, compliance
|
|
25
|
+
# guardrails). Overrides append.
|
|
26
|
+
#
|
|
27
|
+
# Each entry is either:
|
|
28
|
+
# - a literal sentence, e.g. "Updates must preserve [MANUAL] sections verbatim."
|
|
29
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
30
|
+
# "file:{project-root}/docs/update-policy.md" (globs supported; file
|
|
31
|
+
# contents are loaded and treated as facts).
|
|
32
|
+
|
|
33
|
+
persistent_facts = [
|
|
34
|
+
"file:{project-root}/**/project-context.md",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
# --- Optional gate thresholds ---
|
|
38
|
+
#
|
|
39
|
+
# Override the default thresholds used by detect-changes and merge. Empty
|
|
40
|
+
# string or commented = use the bundled default (50% deletion ratio,
|
|
41
|
+
# 80% rename similarity).
|
|
42
|
+
|
|
43
|
+
deletion_ratio_threshold = ""
|
|
44
|
+
rename_similarity_threshold = ""
|
package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md}
RENAMED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
3
|
-
noChangeReportFile: '
|
|
2
|
+
nextStepFile: 're-extract.md'
|
|
3
|
+
noChangeReportFile: 'report.md'
|
|
4
|
+
# Resolve `{hashContentHelper}` to the first existing path; HALT if neither
|
|
5
|
+
# candidate exists — §1b and §Category D rely on the helper for deterministic
|
|
6
|
+
# SHA-256 hashing (file-read + size + line-count) and provenance comparison
|
|
7
|
+
# (UNCHANGED / MODIFIED_FILE / DELETED_FILE classification). Falling back to
|
|
8
|
+
# prose-driven hashing would lose hash stability across runs.
|
|
9
|
+
hashContentProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-hash-content.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-hash-content.py'
|
|
12
|
+
# Resolve `{buildChangeManifestHelper}` to the first existing path; HALT if
|
|
13
|
+
# neither candidate exists. §3 uses `build` to aggregate Category A/B/C/D
|
|
14
|
+
# results into the unified manifest; §2.2 uses `deletion-ratio` to compute
|
|
15
|
+
# the major-version trigger. Falling back to prose-driven count rollups
|
|
16
|
+
# would let the LLM drift on manifest shape across runs.
|
|
17
|
+
buildChangeManifestProbeOrder:
|
|
18
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-build-change-manifest.py'
|
|
19
|
+
- '{project-root}/src/shared/scripts/skf-build-change-manifest.py'
|
|
20
|
+
# Resolve `{provenanceGapDispatchHelper}` to the first existing path; HALT
|
|
21
|
+
# if neither exists. §1c uses it to discover the latest drift report, parse
|
|
22
|
+
# Out-of-Scope candidates, and classify them against brief.scope.amendments[]
|
|
23
|
+
# in one call. Falling back to prose-driven markdown parsing would let
|
|
24
|
+
# report-format drift produce silent skips of out-of-scope candidates.
|
|
25
|
+
provenanceGapDispatchProbeOrder:
|
|
26
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-provenance-gap-dispatch.py'
|
|
27
|
+
- '{project-root}/src/shared/scripts/skf-provenance-gap-dispatch.py'
|
|
4
28
|
---
|
|
5
29
|
|
|
30
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
31
|
+
|
|
6
32
|
# Step 2: Detect Changes
|
|
7
33
|
|
|
8
34
|
## STEP GOAL:
|
|
@@ -16,11 +42,9 @@ Compare current source code state against the provenance map to produce a comple
|
|
|
16
42
|
|
|
17
43
|
## MANDATORY SEQUENCE
|
|
18
44
|
|
|
19
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
20
|
-
|
|
21
45
|
### 0. Check for Test Report Input (Gap-Driven Mode)
|
|
22
46
|
|
|
23
|
-
**If `update_mode == "gap-driven"` (set in step
|
|
47
|
+
**If `update_mode == "gap-driven"` (set in step 1 via `--from-test-report`):**
|
|
24
48
|
|
|
25
49
|
Load the test report at `{test_report_path}` and extract findings:
|
|
26
50
|
|
|
@@ -36,9 +60,9 @@ Load the test report at `{test_report_path}` and extract findings:
|
|
|
36
60
|
| Medium | Stale documentation | MODIFIED_EXPORT (docs reference removed export) |
|
|
37
61
|
| Low | Missing metadata/examples | metadata update |
|
|
38
62
|
|
|
39
|
-
4. Build the change manifest from translated gaps — no file-level timestamp comparison needed since source hasn't changed. For each manifest entry, propagate these fields from the test report finding so step
|
|
63
|
+
4. Build the change manifest from translated gaps — no file-level timestamp comparison needed since source hasn't changed. For each manifest entry, propagate these fields from the test report finding so step 3 can resolve the export against live source:
|
|
40
64
|
|
|
41
|
-
- **`severity`** — the Gap Report severity (`Critical`, `High`, `Medium`, `Low`, `Info`). Step-03 §0 and step
|
|
65
|
+
- **`severity`** — the Gap Report severity (`Critical`, `High`, `Medium`, `Low`, `Info`). Step-03 §0 and step 6 §3 gate the null-citation fallback on severity: Critical/High gaps must produce AST provenance, Medium/Low/Info gaps may degrade to `unknown`.
|
|
42
66
|
- **`source_citation: {file, line}`** — populated only when the finding's `Source:` field is a `file:line` pair (e.g., a Gap Report row that cites `packages/utils/src/builder-utils.ts:33`). Step-03 §0 uses this field to perform a live spot-check against source rather than flagging the export as `unknown`. Omit when the `Source:` field is a region reference (e.g., `@storybook/addon-docs control primitives`) or missing.
|
|
43
67
|
- **`remediation_paths: [path, ...]`** — path-like tokens extracted from the finding's `Remediation:` text: any substring matching a recognized source file extension (`.ts`, `.tsx`, `.js`, `.jsx`, `.mjs`, `.cjs`, `.py`, `.rs`, `.go`, `.java`, `.rb`, `.c`, `.h`, `.cpp`), or a directory/glob fragment under the project's source root. Include every matching path verbatim. Step-03 §0a uses this list as the source set for its Targeted Re-Extraction Branch when `source_citation` is absent and severity is Critical/High. Omit the field when the Remediation text names no paths — the entry then falls through to `unknown` or to §0a's halt, depending on severity.
|
|
44
68
|
5. Set `gap_count` from the total number of translated entries
|
|
@@ -100,7 +124,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
100
124
|
[U] Update — halt this run and return to skf-brief-skill to refine scope
|
|
101
125
|
```
|
|
102
126
|
|
|
103
|
-
5. **Headless mode (`{headless_mode}` is true):** auto-select `[S] Skip` for every candidate — record `action: "skipped"`, `reason: "headless: no user to prompt"`, `workflow: "skf-update-skill"`. A non-interactive update run must never silently add files to scope.
|
|
127
|
+
5. **Headless mode (`{headless_mode}` is true):** auto-select `[S] Skip` for every candidate — record `action: "skipped"`, `reason: "headless: no user to prompt"`, `workflow: "skf-update-skill"`. A non-interactive update run must never silently add files to scope. **Also append one entry per candidate to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "detect-changes.promoted-doc-prompt", default_action: "S", taken_action: "S", reason: "headless: no user to prompt", evidence: {path: "<candidate.path>"}}`.
|
|
104
128
|
|
|
105
129
|
6. **Apply decision:**
|
|
106
130
|
|
|
@@ -108,7 +132,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
108
132
|
1. Append `candidate.path` to `brief.scope.include` as a literal glob.
|
|
109
133
|
2. Append a `brief.scope.amendments[]` entry: `action: "promoted"`, `path: candidate.path`, `reason: {user-provided or auto: "discovered post-creation — matched heuristic {basename}"}`, `heuristic: {basename}`, `date: {today ISO}`, `workflow: "skf-update-skill"`.
|
|
110
134
|
3. **Write the amended brief back to disk immediately** at `{forge_data_folder}/{skill_name}/skill-brief.yaml`. Preserve all other fields.
|
|
111
|
-
4. **
|
|
135
|
+
4. **Hash the candidate** via `uv run {hashContentHelper} hash {candidate.path}` — emits `{content_hash, size_bytes, line_count}` as JSON. Combine with the existing context fields and append to the in-context `promoted_docs_new[]` list: `{path, heuristic, size_bytes, line_count, content_hash}`. This list is consumed by §4 merge Priority 7 to write new `file_entries[]` rows — promoted docs do NOT go through §3 code re-extraction, which would produce ghost entries on non-code files.
|
|
112
136
|
5. Display: `"Promoted {path} — brief amended, scheduled as new file_entries row for file_type doc."`
|
|
113
137
|
|
|
114
138
|
- **[S] Skip:**
|
|
@@ -143,23 +167,51 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
143
167
|
|
|
144
168
|
**Procedure:**
|
|
145
169
|
|
|
146
|
-
1. **
|
|
170
|
+
1. **Discover, parse, and reconcile in one call.** The helper handles drift-report discovery (glob, timestamp-DESC sort, latest wins), Out-of-Scope section extraction (both `## Out-of-Scope Observations` and `### Out-of-Scope New Public API` under `## Remediation Suggestions` heading shapes), candidate parsing (bullet and table markdown formats), and amendment reconciliation against `brief.scope.amendments[]`:
|
|
147
171
|
|
|
148
|
-
|
|
172
|
+
```bash
|
|
173
|
+
uv run {provenanceGapDispatchHelper} dispatch \
|
|
174
|
+
--skill-name {skill_name} \
|
|
175
|
+
--baseline-version {baseline_version} \
|
|
176
|
+
--forge-data-folder {forge_data_folder} \
|
|
177
|
+
--brief {forge_data_folder}/{skill_name}/skill-brief.yaml
|
|
178
|
+
```
|
|
149
179
|
|
|
150
|
-
|
|
151
|
-
|
|
180
|
+
Output envelope:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"status": "no-report" | "no-candidates" | "candidates-found",
|
|
185
|
+
"report_path": "<abs path>" | null,
|
|
186
|
+
"candidates_total": N,
|
|
187
|
+
"classified": [
|
|
188
|
+
{
|
|
189
|
+
"path": "<glob or file path>",
|
|
190
|
+
"evidence": "<one-liner>",
|
|
191
|
+
"status": "already-in-scope" | "pre-decided-skipped"
|
|
192
|
+
| "pre-decided-demoted" | "unresolved",
|
|
193
|
+
"prior_action": "promoted" | "skipped"
|
|
194
|
+
| "demoted-include" | "demoted-exclude"
|
|
195
|
+
| null
|
|
196
|
+
}, ...
|
|
197
|
+
],
|
|
198
|
+
"summary": {"pre_decided_count": N, "unresolved_count": N}
|
|
199
|
+
}
|
|
200
|
+
```
|
|
152
201
|
|
|
153
|
-
|
|
202
|
+
2. **Dispatch on `status`:**
|
|
154
203
|
|
|
155
|
-
|
|
204
|
+
- **`no-report`** — no drift report under `{forge_data_folder}/{skill_name}/{baseline_version}/`. **Skip §1c entirely** — proceed to step 6's summary line (omit). §2.2's post-detection deletion-ratio trigger still catches major restructures.
|
|
205
|
+
- **`no-candidates`** — report exists but the Out-of-Scope section is absent or empty. Proceed to step 6's summary line with `"no out-of-scope observations in drift report."`
|
|
206
|
+
- **`candidates-found`** — iterate `classified[]`:
|
|
207
|
+
- `status: "already-in-scope"` → skip silently (`prior_action: "promoted"`).
|
|
208
|
+
- `status: "pre-decided-skipped"` → honor silently (`prior_action: "skipped"`).
|
|
209
|
+
- `status: "pre-decided-demoted"` → record as `pre_decided`; do not re-prompt (`prior_action` ∈ `demoted-include`, `demoted-exclude`).
|
|
210
|
+
- `status: "unresolved"` → continue to step 4 (user prompt).
|
|
156
211
|
|
|
157
|
-
-
|
|
158
|
-
- `action: "skipped"` AND `path` matches → user previously declined, honor silently.
|
|
159
|
-
- `action: "demoted-include"` or `action: "demoted-exclude"` AND `path` matches → user previously narrowed scope on this path, do not re-prompt; record as `pre_decided`.
|
|
160
|
-
- No matching amendment → continue to user prompt.
|
|
212
|
+
**Note:** the Out-of-Scope section is an optional audit-skill output. `skf-audit-skill` does not currently discover new files (per `src/skf-audit-skill/references/re-index.md` — new-file detection is the responsibility of update-skill). The section is a forward-looking integration point: manual additions or a future audit-skill enhancement populate it.
|
|
161
213
|
|
|
162
|
-
|
|
214
|
+
3. **Prompt for each unresolved candidate.** Present the same menu shape as §1b:
|
|
163
215
|
|
|
164
216
|
```
|
|
165
217
|
**Out-of-scope new public API discovered**
|
|
@@ -175,9 +227,9 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
175
227
|
[U] Update — halt this run and return to skf-brief-skill to refine scope
|
|
176
228
|
```
|
|
177
229
|
|
|
178
|
-
|
|
230
|
+
4. **Headless mode (`{headless_mode}` is true):** auto-select `[S] Skip` for every candidate — record `action: "skipped"`, `category: "scope-expansion"`, `reason: "headless: no user to prompt"`, `workflow: "skf-update-skill"`. A non-interactive update run must never silently expand scope. **Also append one entry per candidate to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "detect-changes.scope-expansion", default_action: "S", taken_action: "S", reason: "headless: no user to prompt", evidence: {path: "<candidate.path>"}}`.
|
|
179
231
|
|
|
180
|
-
|
|
232
|
+
5. **Apply decision:**
|
|
181
233
|
|
|
182
234
|
- **[P] Promote:**
|
|
183
235
|
1. Append `candidate.path` to `brief.scope.include` as a literal glob (preserve any wildcards from the drift report).
|
|
@@ -197,7 +249,7 @@ Read the source directory at `{source_root}` and build a current file inventory:
|
|
|
197
249
|
2. Display: `"Halting update-skill. Re-run skf-brief-skill to refine scope for {skill_name}, then re-run skf-update-skill."`
|
|
198
250
|
3. Exit with status `halted-for-brief-refinement`. Change manifest is not yet built — no partial writes to provenance.
|
|
199
251
|
|
|
200
|
-
|
|
252
|
+
6. **Summary:** After all candidates are resolved (or none were found):
|
|
201
253
|
|
|
202
254
|
- `"Scope reconciliation: {N} candidates, {P} promoted, {S} skipped, {A} pre-decided from amendments."`
|
|
203
255
|
- If N = 0 (section absent or empty): `"Scope reconciliation: no out-of-scope observations in drift report."`
|
|
@@ -215,7 +267,7 @@ Before launching parallel subprocesses, build a `change_detection_excludes` set
|
|
|
215
267
|
|
|
216
268
|
The exclusion set includes:
|
|
217
269
|
|
|
218
|
-
- Every path in `promoted_docs_new[]` (populated by §1b). These files are tracked as `file_entries[]` via step
|
|
270
|
+
- Every path in `promoted_docs_new[]` (populated by §1b). These files are tracked as `file_entries[]` via step 4 Priority 7, not through Category A code extraction. Without this exclusion, Category A would classify them as ADDED (because they're in source but not yet in the provenance map) and §3 re-extract would send them to AST extraction, producing ghost entries.
|
|
219
271
|
- Every source path in `file_entries[].source_file` where `file_type == "doc"` in the existing provenance map. These are already-tracked authoritative docs; any drift in them is handled by Category D (script/asset file changes), not Category A.
|
|
220
272
|
|
|
221
273
|
Record the set size: "**Change-detection excludes:** {count} paths ({promoted_docs_new count} new promotions + {existing doc file_entries count} already tracked)."
|
|
@@ -227,7 +279,7 @@ Launch subprocesses in parallel that compare source state against provenance map
|
|
|
227
279
|
**Category A — File-level changes:**
|
|
228
280
|
- Files in provenance map but missing from source → DELETED
|
|
229
281
|
- Files in source but not in provenance map AND not in `change_detection_excludes` → ADDED
|
|
230
|
-
- Files in `change_detection_excludes`: skip entirely (routed to file_entries via §1b → step
|
|
282
|
+
- Files in `change_detection_excludes`: skip entirely (routed to file_entries via §1b → step 4 Priority 7, never through Category A)
|
|
231
283
|
- Files in both but with different timestamps/sizes → MODIFIED
|
|
232
284
|
- Files with same content at different paths → MOVED
|
|
233
285
|
|
|
@@ -243,12 +295,35 @@ Launch subprocesses in parallel that compare source state against provenance map
|
|
|
243
295
|
- If content similarity > 80%: 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
|
|
244
296
|
|
|
245
297
|
**Category D — Script/asset file changes:**
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
-
|
|
298
|
+
|
|
299
|
+
Run the bulk comparison once via:
|
|
300
|
+
|
|
301
|
+
```bash
|
|
302
|
+
uv run {hashContentHelper} compare <source-root> \
|
|
303
|
+
--provenance-map <provenance-map-path>
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
The helper emits:
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"comparisons": [
|
|
311
|
+
{"source_file": "...", "classification": "UNCHANGED|MODIFIED_FILE|DELETED_FILE",
|
|
312
|
+
"stored_hash": "sha256:...", "current_hash": "sha256:..."|null,
|
|
313
|
+
"current_size_bytes": N|null}, ...
|
|
314
|
+
],
|
|
315
|
+
"stats": {"total": N, "unchanged": U, "modified": M, "deleted": D}
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Translate the helper's output into the change manifest:
|
|
320
|
+
- `MODIFIED_FILE` rows → add to manifest as MODIFIED_FILE
|
|
321
|
+
- `DELETED_FILE` rows → add to manifest as DELETED_FILE
|
|
322
|
+
- `UNCHANGED` rows → omit from the manifest (no action needed)
|
|
323
|
+
|
|
324
|
+
The helper does NOT detect NEW_FILE — its job is provenance comparison only. Detect new files via `skf-detect-scripts-assets.py` from create-skill step 3 §4c against the current source tree, then subtract the paths already present in `provenance.file_entries[].source_file`. Remaining files matching detection patterns (`scripts/`, `bin/`, `assets/`, `templates/`) and NOT under `scripts/[MANUAL]/` or `assets/[MANUAL]/` are NEW_FILE.
|
|
325
|
+
|
|
326
|
+
Files in `scripts/[MANUAL]/` or `assets/[MANUAL]/` → SKIP (user-authored, preserved).
|
|
252
327
|
|
|
253
328
|
Aggregate all subprocess results into a unified change manifest.
|
|
254
329
|
|
|
@@ -261,22 +336,29 @@ Aggregate all subprocess results into a unified change manifest.
|
|
|
261
336
|
|
|
262
337
|
**Purpose:** §1c catches the major-version case when an audit drift report supplies explicit candidates. §2.2 is the safety net that fires when no audit was run (or audit emitted no out-of-scope section): it inspects the just-built Category A/B results for the deletion-ratio signature of a major-version restructure and gives the user an off-ramp before §3 commits the change manifest.
|
|
263
338
|
|
|
264
|
-
**
|
|
265
|
-
|
|
266
|
-
- `update_mode == "gap-driven"` (test-report mode), OR
|
|
267
|
-
- `degraded_mode == true` (no provenance baseline to compare against — every export looks "modified", deletion ratio is meaningless), OR
|
|
268
|
-
- Provenance map's tracked export count is zero.
|
|
269
|
-
|
|
270
|
-
**Trigger:** Compute
|
|
339
|
+
**Trigger computation:** invoke the helper with the same Category A/B/C/D JSON used for §3, plus the provenance map:
|
|
271
340
|
|
|
341
|
+
```bash
|
|
342
|
+
echo "{category JSON}" | uv run {buildChangeManifestHelper} deletion-ratio \
|
|
343
|
+
--provenance-map {forge_version}/provenance-map.json
|
|
272
344
|
```
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
345
|
+
|
|
346
|
+
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:
|
|
347
|
+
|
|
348
|
+
```json
|
|
349
|
+
{
|
|
350
|
+
"skip_reason": "gap-driven" | "degraded-mode" | "zero-provenance-exports" | null,
|
|
351
|
+
"deleted_export_count": N,
|
|
352
|
+
"total_provenance_exports": N,
|
|
353
|
+
"deletion_ratio": 0.X,
|
|
354
|
+
"deleted_file_count": N,
|
|
355
|
+
"added_in_scope_count": N,
|
|
356
|
+
"renamed_or_moved_count": N,
|
|
357
|
+
"should_trigger": <bool>
|
|
358
|
+
}
|
|
277
359
|
```
|
|
278
360
|
|
|
279
|
-
If `
|
|
361
|
+
If `skip_reason` is non-null OR `should_trigger` is false, skip the prompt and continue to §3. If `should_trigger` is true, present the prompt below.
|
|
280
362
|
|
|
281
363
|
**Prompt:**
|
|
282
364
|
|
|
@@ -296,7 +378,7 @@ The upstream surface appears to have been substantially replaced. The brief's
|
|
|
296
378
|
[A] Audit — halt and run skf-audit-skill to map the new surface, then re-run update-skill
|
|
297
379
|
```
|
|
298
380
|
|
|
299
|
-
**Headless mode (`{headless_mode}` is true):** auto-select `[C] Continue`, log a WARN-level entry to the evidence report (`scope_reconciliation_post: {trigger: "deletion-ratio", ratio: X, decision: "headless-continue"}`), and surface the warning in step
|
|
381
|
+
**Headless mode (`{headless_mode}` is true):** auto-select `[C] Continue`, log a WARN-level entry to the evidence report (`scope_reconciliation_post: {trigger: "deletion-ratio", ratio: X, decision: "headless-continue"}`), and surface the warning in step 7's report. A non-interactive run must not silently halt, but the user must be able to see the signal post-hoc. **Also append to in-context `headless_decisions[]`** (surfaced via `SKF_UPDATE_RESULT_JSON` by step 7): `{gate: "detect-changes.deletion-ratio", default_action: "C", taken_action: "C", reason: "headless: deletion-ratio threshold exceeded but no user to halt", evidence: {deletion_ratio: <ratio>, deleted_export_count: <N>, total_provenance_exports: <T>}}`.
|
|
300
382
|
|
|
301
383
|
**Apply decision:**
|
|
302
384
|
|
|
@@ -308,30 +390,51 @@ The upstream surface appears to have been substantially replaced. The brief's
|
|
|
308
390
|
|
|
309
391
|
### 3. Build Change Manifest
|
|
310
392
|
|
|
311
|
-
|
|
393
|
+
Hand the assembled Category A/B/C/D JSON to the helper:
|
|
312
394
|
|
|
395
|
+
```bash
|
|
396
|
+
echo "{category JSON}" | uv run {buildChangeManifestHelper} build
|
|
313
397
|
```
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
398
|
+
|
|
399
|
+
The category JSON shape is:
|
|
400
|
+
|
|
401
|
+
```json
|
|
402
|
+
{
|
|
403
|
+
"category_a": {"modified": [...], "added": [...], "deleted": [...]},
|
|
404
|
+
"category_b": {"modified_exports": [...], "new_exports": [...],
|
|
405
|
+
"deleted_exports": [...], "moved_exports": [...]},
|
|
406
|
+
"category_c": {"renamed_files": [...], "renamed_exports": [...]},
|
|
407
|
+
"category_d": {"scripts_modified": [...], "scripts_added": [...],
|
|
408
|
+
"scripts_deleted": [...], "assets_modified": [...],
|
|
409
|
+
"assets_added": [...], "assets_deleted": [...]},
|
|
410
|
+
"degraded_mode": <bool>,
|
|
411
|
+
"update_mode": "normal" | "gap-driven"
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
The helper emits the unified manifest envelope:
|
|
416
|
+
|
|
417
|
+
```json
|
|
418
|
+
{
|
|
419
|
+
"no_changes": <bool>,
|
|
420
|
+
"degraded_mode": <bool>,
|
|
421
|
+
"counts": {
|
|
422
|
+
"files_changed": N, "files_added": N, "files_deleted": N, "files_moved": N,
|
|
423
|
+
"exports_modified": N, "exports_new": N, "exports_deleted": N,
|
|
424
|
+
"exports_renamed": N, "exports_moved": N,
|
|
425
|
+
"scripts_modified": N, "scripts_added": N, "scripts_deleted": N,
|
|
426
|
+
"assets_modified": N, "assets_added": N, "assets_deleted": N
|
|
427
|
+
},
|
|
428
|
+
"total_export_changes": N,
|
|
429
|
+
"per_file": [
|
|
430
|
+
{"file_path": "...", "status": "MODIFIED|ADDED|DELETED|MOVED",
|
|
431
|
+
"exports_affected": [{name, change_type, old_line, new_line}, ...]}
|
|
432
|
+
]
|
|
433
|
+
}
|
|
333
434
|
```
|
|
334
435
|
|
|
436
|
+
`per_file` entries are sorted MODIFIED → ADDED → DELETED → MOVED, then alphabetically within each status group, so downstream stages can rely on stable ordering. MOVED entries include an extra `old_path` field. Stash the envelope as the change manifest in workflow context.
|
|
437
|
+
|
|
335
438
|
### 4. Check for No-Change Shortcut
|
|
336
439
|
|
|
337
440
|
**If zero changes detected across all categories:**
|
|
@@ -364,15 +467,20 @@ Display: "**Proceeding to re-extraction...**"
|
|
|
364
467
|
|
|
365
468
|
#### Menu Handling Logic:
|
|
366
469
|
|
|
367
|
-
-
|
|
368
|
-
-
|
|
470
|
+
- **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}`.
|
|
471
|
+
- Else, after change manifest is built, immediately load, read entire file, then execute `{nextStepFile}`.
|
|
472
|
+
- **EXCEPTION:** If no changes detected (section 4), load `{noChangeReportFile}` instead.
|
|
369
473
|
|
|
370
474
|
#### EXECUTION RULES:
|
|
371
475
|
|
|
372
476
|
- This is an auto-proceed step with no user choices
|
|
373
|
-
- Proceed directly to next step after change detection completes
|
|
477
|
+
- Proceed directly to next step after change detection completes (or to report when `detect_only_mode` is true)
|
|
374
478
|
|
|
375
479
|
## CRITICAL STEP COMPLETION NOTE
|
|
376
480
|
|
|
377
|
-
ONLY WHEN the change manifest is fully built will you load
|
|
481
|
+
ONLY WHEN the change manifest is fully built will you load the next file:
|
|
482
|
+
|
|
483
|
+
- `detect_only_mode == true` → load `{noChangeReportFile}` (report.md). Report emits status `detect-only`.
|
|
484
|
+
- No changes detected → load `{noChangeReportFile}` (report.md). Report emits status `no-changes`.
|
|
485
|
+
- Otherwise → load `{nextStepFile}` (re-extract.md) to begin re-extraction.
|
|
378
486
|
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
# `shared/health-check.md` resolves relative to the SKF module root
|
|
3
|
+
# (`_bmad/skf/` when installed, `src/` during development), NOT relative
|
|
4
|
+
# to this step file.
|
|
5
|
+
nextStepFile: 'shared/health-check.md'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
9
|
+
|
|
10
|
+
# Step 8: Workflow Health Check
|
|
11
|
+
|
|
12
|
+
## STEP GOAL:
|
|
13
|
+
|
|
14
|
+
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of update-skill — after the shared health check completes, the workflow is fully done.
|
|
15
|
+
|
|
16
|
+
## Rules
|
|
17
|
+
|
|
18
|
+
- No user-facing reports, file writes, or result contracts in this step — those belong in step 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
|
|
23
|
+
|
|
24
|
+
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
|
+
|
|
26
|
+
```bash
|
|
27
|
+
rm -f "{forge_data_folder}/{skill_name}/.skf-update.lock"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
The lock release MUST run before delegating to the shared health-check, since the health-check is the terminal step — once it returns, the workflow is done and any held lock becomes orphaned for the next run to clean up. Releasing here keeps the lock lifecycle tight against the workflow's actual span.
|
|
31
|
+
|
|
32
|
+
2. Load `{nextStepFile}`, read it fully, then execute it.
|