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
|
@@ -4,10 +4,17 @@ forgeTierConfig: '{sidecar_path}/forge-tier.yaml'
|
|
|
4
4
|
# Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
|
|
5
5
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
6
6
|
# path wins. HALT if neither resolves — the active-symlink flip and registry
|
|
7
|
-
# writes below
|
|
7
|
+
# writes below go through the atomic helper for concurrency safety.
|
|
8
8
|
atomicWriteProbeOrder:
|
|
9
9
|
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
10
10
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
11
|
+
# Resolve `{forgeTierRwHelper}` by probing `{forgeTierRwProbeOrder}` in order
|
|
12
|
+
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
13
|
+
# path wins. HALT if neither resolves — §6b's ccc-index registry round-trip is
|
|
14
|
+
# comment-preserving and has no prose fallback.
|
|
15
|
+
forgeTierRwProbeOrder:
|
|
16
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
|
|
17
|
+
- '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
|
|
11
18
|
---
|
|
12
19
|
|
|
13
20
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -73,7 +80,7 @@ Write these 4 files from the compiled content:
|
|
|
73
80
|
|
|
74
81
|
**Note on `file_type: "doc"` entries** (promoted authoritative docs from step 3 §2a):
|
|
75
82
|
|
|
76
|
-
Promoted docs are tracked in `file_entries[]` with `file_type: "doc"` for drift detection but are **
|
|
83
|
+
Promoted docs are tracked in `file_entries[]` with `file_type: "doc"` for drift detection but are **not** copied into the skill package. The source file remains at its original location outside `{skill_package}`. Step-07 must skip any `file_entries[]` row where `file_type == "doc"` when iterating for file copy — these entries exist only for provenance tracking, not bundling. Step-07 verification (§5) also does not check for doc files in the skill package.
|
|
77
84
|
|
|
78
85
|
### 3. Write Workspace Artifacts to {forge_version}
|
|
79
86
|
|
|
@@ -101,7 +108,7 @@ python3 {atomicWriteHelper} flip-link \
|
|
|
101
108
|
|
|
102
109
|
The helper returns non-zero (exit 2) if `{skill_group}/active` already exists as a real directory or file rather than a symlink — in that case, halt with: "Refusing to flip `{skill_group}/active` — existing path is not a symlink. Investigate manually; expected a symlink pointing at a version directory."
|
|
103
110
|
|
|
104
|
-
|
|
111
|
+
Do not `rm` + `ln -s` the active link by hand. The bare-rm pattern has two failure modes: (1) a concurrent reader sees a missing `active` mid-flip, and (2) a bug or typo that replaces `{skill_group}/active` with a plain directory turns the next manual `rm -rf {skill_group}/active` into data loss. The helper encapsulates both guards.
|
|
105
112
|
|
|
106
113
|
### 5. Verify Write Completion
|
|
107
114
|
|
|
@@ -174,10 +181,10 @@ If an entry with `name: "{name}-extraction"` already exists, replace it. Otherwi
|
|
|
174
181
|
Write the updated forge-tier.yaml.
|
|
175
182
|
|
|
176
183
|
**Error handling:**
|
|
177
|
-
- If QMD collection creation fails: log the error, note that indexing can be retried via [SF] setup. Do
|
|
184
|
+
- If QMD collection creation fails: log the error, note that indexing can be retried via [SF] setup. Do not fail the workflow.
|
|
178
185
|
- If forge-tier.yaml update fails: log the error, continue. The collection exists in QMD even if the registry entry failed.
|
|
179
186
|
|
|
180
|
-
**IF forge tier is
|
|
187
|
+
**IF forge tier is not Deep:** Skip this section silently. No messaging.
|
|
181
188
|
|
|
182
189
|
### 6b. CCC Index Registry Registration (Forge+ and Deep with ccc)
|
|
183
190
|
|
|
@@ -195,34 +202,22 @@ Ensure the source path used for extraction is indexed by ccc and registered in t
|
|
|
195
202
|
|
|
196
203
|
**Registry update:**
|
|
197
204
|
|
|
198
|
-
|
|
205
|
+
**Resolve `{forgeTierRwHelper}`** from `{forgeTierRwProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
206
|
+
|
|
207
|
+
Register the indexed source path via `register-ccc-index` — a comment-preserving round-trip on `forge-tier.yaml`. This differs from §6, which mutates the registry with an inline read→modify→atomic-write under `flock`; here the helper owns the read→modify→write internally so the `ccc_index_registry` deduplication logic stays in the script. Acquire an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock`, then:
|
|
199
208
|
|
|
200
209
|
```bash
|
|
201
210
|
echo '{"source_repo":"{brief.source_repo}","path":"{source_root}","skill_name":"{name}","indexed_at":"{current ISO date}","source_workflow":"create-skill"}' \
|
|
202
|
-
| uv run {
|
|
211
|
+
| uv run {forgeTierRwHelper} register-ccc-index --target {forgeTierConfig}
|
|
203
212
|
```
|
|
204
213
|
|
|
205
|
-
Deduplicates by `source_repo` + `skill_name` (
|
|
214
|
+
Deduplicates by `source_repo` + `skill_name` (not local `path`, which may be ephemeral). Release the lock after the command completes. If `flock` is unavailable, fall back to read-CAS-by-mtime.
|
|
206
215
|
|
|
207
|
-
**Error handling:** If ccc indexing or registry update fails, log and continue — do
|
|
216
|
+
**Error handling:** If ccc indexing or registry update fails, log and continue — do not fail the workflow.
|
|
208
217
|
|
|
209
218
|
**IF `tools.ccc` is false:** Skip this section silently.
|
|
210
219
|
|
|
211
|
-
### 7.
|
|
212
|
-
|
|
213
|
-
**Auto-proceed step — no user interaction.**
|
|
214
|
-
|
|
215
|
-
After all artifacts are written, verified, and optionally indexed into QMD, immediately load, read entire file, then execute `{nextStepFile}`.
|
|
216
|
-
|
|
217
|
-
#### EXECUTION RULES:
|
|
218
|
-
|
|
219
|
-
- This is an auto-proceed file writing step with no user choices
|
|
220
|
-
- All 7 files must be written before proceeding
|
|
221
|
-
- QMD indexing failure does NOT block proceeding
|
|
222
|
-
- File write failures are real errors — halt, do not proceed with partial output
|
|
223
|
-
- Proceed directly to next step after successful generation
|
|
224
|
-
|
|
225
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
220
|
+
### 7. Auto-Proceed
|
|
226
221
|
|
|
227
|
-
|
|
222
|
+
No user interaction. Once all 7 files are written and verified (and optionally indexed into QMD), load `{nextStepFile}`, read it fully, then execute it. A QMD-indexing failure does not block; a file-write failure halts (§5) rather than proceeding with partial output.
|
|
228
223
|
|
|
@@ -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
|
|
|
@@ -40,14 +40,14 @@ Extract and report:
|
|
|
40
40
|
- `tools`: which tools are available (gh, ast-grep, ccc, qmd)
|
|
41
41
|
- `ccc_index`: ccc index state (status, indexed_path, last_indexed) — needed by step 2b
|
|
42
42
|
|
|
43
|
-
**Apply tier override:** Read `{preferencesFile}`. If `tier_override` is set and is one of the exact valid tier values (`Quick`, `Forge`, `Forge+`, `Deep`), use it instead of the detected tier. **If `tier_override` is set but is
|
|
43
|
+
**Apply tier override:** Read `{preferencesFile}`. If `tier_override` is set and is one of the exact valid tier values (`Quick`, `Forge`, `Forge+`, `Deep`), use it instead of the detected tier. **If `tier_override` is set but is not one of those four values:** log a warning — "Unknown tier_override `{value}` in preferences.yaml; falling back to detected tier `{detected_tier}`. Valid values: Quick, Forge, Forge+, Deep." — and use the detected tier. Never silently apply an unknown override value, and never map it heuristically to a tier.
|
|
44
44
|
|
|
45
45
|
**Record the decision:** append an entry to the in-context `headless_decisions[]` buffer (initialize to `[]` at the start of this step if absent) whenever a non-interactive choice is made automatically — both the valid-override path AND the rejected-override path:
|
|
46
46
|
|
|
47
47
|
- Valid override applied: `{step: "load-brief", gate: "tier-override", decision: "apply", value: "{tier_override}", rationale: "explicit preferences.yaml tier_override", timestamp: {ISO}}`
|
|
48
48
|
- Invalid override rejected: `{step: "load-brief", gate: "tier-override", decision: "reject-invalid", value: "{tier_override}", fallback: "{detected_tier}", rationale: "tier_override not in {Quick,Forge,Forge+,Deep}", timestamp: {ISO}}`
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
These entries stay in the in-context buffer until §3 establishes the on-disk auto-decision sink and seeds it with the buffer-so-far; from then on every later gate's decision is appended to the sink as it lands (per the headless Workflow Rule). Step 5 §7 renders the sink into the evidence-report `## Auto-Decisions` table and step 6 §8 reconciles it, so reviewers can audit every silent choice even on a run long enough to compact the in-context buffer before step 5.
|
|
51
51
|
|
|
52
52
|
### 2. Discover Skill Brief
|
|
53
53
|
|
|
@@ -58,7 +58,7 @@ Step-05 §7 reads `headless_decisions[]` and emits an "Auto-Decisions" section i
|
|
|
58
58
|
|
|
59
59
|
**If user invoked with --batch flag:**
|
|
60
60
|
- Check `{sidecar_path}/batch-state.yaml` for an active batch checkpoint:
|
|
61
|
-
- If `batch_active: true`: validate the checkpoint before trusting it
|
|
61
|
+
- If `batch_active: true`: validate the checkpoint before trusting it — both conditions below must hold:
|
|
62
62
|
1. `0 <= current_index < len(brief_list)` — the index points inside the recorded list.
|
|
63
63
|
2. `os.path.exists(brief_list[current_index])` — the brief file is still on disk.
|
|
64
64
|
If both hold, load the brief at `brief_list[current_index]` (resuming a batch loop from step 8). If **either** check fails, the checkpoint is stale (briefs renamed, moved, or deleted between runs; index off the end after a partial failure). Log a warning — "Stale batch checkpoint — current_index={i}, brief_list length={n}, brief_exists={bool}. Resetting and re-discovering." — then set `batch_active: false` in `batch-state.yaml` and fall through to the no-checkpoint branch below.
|
|
@@ -95,9 +95,19 @@ The helper emits:
|
|
|
95
95
|
|
|
96
96
|
**If `valid` is true:** continue with `brief` (the parsed object) for downstream sections. Surface any `warnings[]` to the user but do not halt.
|
|
97
97
|
|
|
98
|
+
**Establish the auto-decision sink (durable headless audit).** The brief is now confirmed, so create the on-disk audit sink at `{sidecar_path}/auto-decisions.jsonl` — one compact JSON object per line — and seed it with whatever is already in the in-context `headless_decisions[]` buffer (the §1 tier-override row, or nothing if none fired). This truncates any stale sink a prior brief left behind:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
: > {sidecar_path}/auto-decisions.jsonl # truncate / create empty
|
|
102
|
+
# then, for each entry already in headless_decisions[], append its compact JSON:
|
|
103
|
+
printf '%s\n' '{decision-json}' >> {sidecar_path}/auto-decisions.jsonl
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
From here on, **every time a later gate appends an auto-decision to `headless_decisions[]`, append that same object as a line to this sink the moment it lands** (the on-landing append the headless Workflow Rule mandates). The array is tiny, so the append costs nothing and keeps a complete on-disk copy across the token-heavy step 3→5 extraction window — the point where a long component-library run can compact the in-context buffer. Step 5 §7 renders this sink into the evidence-report `## Auto-Decisions` table and step 6 §8 reconciles it, so the audit table and `auto_decision_count` stay complete even when the buffer is lost.
|
|
107
|
+
|
|
98
108
|
**Field reference (for human readers):**
|
|
99
109
|
|
|
100
|
-
The complete contract — required fields, optional fields, types, and rules — lives in `src/shared/scripts/schemas/skill-brief.v1.json` and the prose mirror at `src/skf-brief-skill/assets/skill-brief-schema.md`. Read those if you need to explain a specific field; do
|
|
110
|
+
The complete contract — required fields, optional fields, types, and rules — lives in `src/shared/scripts/schemas/skill-brief.v1.json` and the prose mirror at `src/skf-brief-skill/assets/skill-brief-schema.md`. Read those if you need to explain a specific field; do not restate the rules here.
|
|
101
111
|
|
|
102
112
|
### 4. Resolve Source Code Location
|
|
103
113
|
|
|
@@ -137,19 +147,7 @@ Where tier_description follows positive capability framing:
|
|
|
137
147
|
- Forge+: "Semantic-guided precision — ccc pre-ranks files before AST extraction"
|
|
138
148
|
- Deep: "Full intelligence — structural + contextual + QMD knowledge synthesis"
|
|
139
149
|
|
|
140
|
-
### 6.
|
|
141
|
-
|
|
142
|
-
**Auto-proceed step — no user interaction.**
|
|
143
|
-
|
|
144
|
-
After initialization is complete and all data is loaded (including `target_version` if present in the brief), immediately load, read entire file, then execute `{nextStepFile}`.
|
|
145
|
-
|
|
146
|
-
#### EXECUTION RULES:
|
|
147
|
-
|
|
148
|
-
- This is an auto-proceed initialization step with no user choices
|
|
149
|
-
- Proceed directly to next step after successful initialization
|
|
150
|
-
- If any prerequisite check fails, HALT with actionable error — do NOT proceed
|
|
151
|
-
|
|
152
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
150
|
+
### 6. Auto-Proceed
|
|
153
151
|
|
|
154
|
-
|
|
152
|
+
No user interaction. After initialization completes and all data is loaded (including `target_version` if present), load `{nextStepFile}`, read it fully, then execute it. A failed prerequisite check above has already halted with an actionable error rather than reaching here.
|
|
155
153
|
|
|
@@ -20,7 +20,7 @@ To display the final compilation summary — skill name, version, source, export
|
|
|
20
20
|
|
|
21
21
|
- Focus only on reporting compilation results — do not modify any files
|
|
22
22
|
- Deliver structured report with confidence breakdown
|
|
23
|
-
- Chains to the local health-check step via `{nextStepFile}` after completion (non-batch mode, or after the final batch brief) — the user-facing report is
|
|
23
|
+
- Chains to the local health-check step via `{nextStepFile}` after completion (non-batch mode, or after the final batch brief) — the user-facing report is not the terminal step
|
|
24
24
|
|
|
25
25
|
## MANDATORY SEQUENCE
|
|
26
26
|
|
|
@@ -72,11 +72,6 @@ If there were warnings from extraction, validation, or enrichment, display them:
|
|
|
72
72
|
|
|
73
73
|
If no warnings, omit this section entirely.
|
|
74
74
|
|
|
75
|
-
**Next steps:** After reviewing the report, recommend the next workflow:
|
|
76
|
-
- **TS** (test skill) — verify completeness before export
|
|
77
|
-
- **EX** (export) — publish to your IDE's context system
|
|
78
|
-
- If issues were flagged, suggest **reviewing the SKILL.md** and re-running compilation
|
|
79
|
-
|
|
80
75
|
### 4. Suggest Next Steps
|
|
81
76
|
|
|
82
77
|
"**Recommended next steps:**
|
|
@@ -125,21 +120,39 @@ End workflow. No further steps.
|
|
|
125
120
|
|
|
126
121
|
**Resolve the schema reference:** before writing, verify that `{project-root}/src/shared/references/output-contract-schema.md` exists and is readable. Try in order: `{project-root}/src/shared/references/output-contract-schema.md`, then `{project-root}/_bmad/skf/shared/references/output-contract-schema.md` (installed-forge path).
|
|
127
122
|
|
|
128
|
-
- **If resolved:** write the result contract per the schema — the per-run record at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/create-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include `SKILL.md`, `context-snippet.md`,
|
|
123
|
+
- **If resolved:** write the result contract per the schema — the per-run record at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (UTC timestamp, resolution to seconds) and a copy at `{forge_version}/create-skill-result-latest.json` (stable path for pipeline consumers — copy, not symlink). Include `SKILL.md`, `context-snippet.md`, `metadata.json`, **and `{forge_version}/evidence-report.md`** paths in `outputs` (the evidence report carries the `## Auto-Decisions` audit table where every silent auto-decision is recorded — pipeline consumers follow this path to audit the run) and confidence distribution in `summary`. Also set `summary.auto_decision_count` to the number of decision rows in the reconciled evidence-report `## Auto-Decisions` table (0 when the run was interactive and the section holds only the no-auto-decisions line) so a consumer can tell from the result JSON alone whether any gate auto-resolved. Count the persisted rows — the durable audit record step 6 §8 reconciled from disk — rather than the in-context `headless_decisions[]` length, so the count matches the table even if a long headless run compacted the buffer. Use `python3 {atomicWriteHelper} write --target {forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` (stdin-piped JSON) for the per-run record, then the same helper for the `-latest.json` copy.
|
|
129
124
|
|
|
130
125
|
- **If neither candidate path resolves:** skip the result-contract write entirely. Append a warning to `evidence-report.md`: "Result contract skipped — `shared/references/output-contract-schema.md` could not be resolved at either candidate path." Then set `validation_status: 'schema-unavailable'` in `metadata.json` (and re-write metadata.json via `skf-atomic-write.py write`). Pipeline consumers will observe the missing `-latest.json` and the metadata flag.
|
|
131
126
|
|
|
132
|
-
|
|
127
|
+
**Post-completion hook (optional).** After the result JSON and `metadata.json` are finalized, if `{onCompleteCommand}` is non-empty (resolved at SKILL.md On Activation §3 from `workflow.on_complete`), invoke it:
|
|
133
128
|
|
|
134
|
-
|
|
129
|
+
```bash
|
|
130
|
+
{onCompleteCommand} --result-path={forge_version}/create-skill-result-latest.json
|
|
131
|
+
```
|
|
135
132
|
|
|
136
|
-
|
|
133
|
+
Log success or failure to `workflow_warnings[]` but never fail the workflow on a hook error — the skill is already written and the result contract is final. The hook runs last so a git-add, registry registration, notifier, or downstream-skill chain sees a complete package. When `{onCompleteCommand}` is empty (bundled default), skip the invocation entirely.
|
|
137
134
|
|
|
138
|
-
|
|
135
|
+
### Result Contract on HARD HALT
|
|
139
136
|
|
|
140
|
-
|
|
137
|
+
The success-variant contract above is only reached at step 8. The ~10 HARD HALT conditions in steps 1–7 (forge-config missing, no brief, brief invalid, source not found, prerequisite failure in load-brief; atomic/detect/auth helper unresolved and the Tier-1 split-count drop in extract/validate; the non-symlink active-link refusal in generate-artifacts) otherwise print a human string and exit with **no machine-readable outcome** — a pipeline polling `create-skill-result-latest.json` cannot distinguish "halted at brief-invalid" from "still running" from "crashed". Mirror skf-quick-skill: **whenever `{headless_mode}` is true, every HARD HALT must surface an error-variant result before exiting.**
|
|
138
|
+
|
|
139
|
+
**For every HARD HALT under `{headless_mode}` (regardless of phase)** — emit a single line on **stderr** (one line, no pretty-print; matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`):
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
SKF_CREATE_SKILL_RESULT_JSON: {"status":"failed","phase":"<step-slug>","outputs":{},"summary":{"halt_reason":"<short class>","evidence_report":"<path-or-null>"},"skill_package":"<path-or-null>"}
|
|
143
|
+
```
|
|
141
144
|
|
|
142
|
-
|
|
145
|
+
Use `status: "partial"` instead of `"failed"` when artifacts were already staged or promoted before the HALT (i.e. the HALT fired at step 7 generate-artifacts after some files were written); use `"failed"` for HALTs before any artifact exists on disk (steps 1–6).
|
|
143
146
|
|
|
144
|
-
|
|
147
|
+
**Additionally, when `{forge_version}` is resolved** (HALT at step 7 onward, where the staging tree has been promoted) — write the same JSON object (without the `SKF_CREATE_SKILL_RESULT_JSON: ` prefix) to disk at `{forge_version}/create-skill-result-{YYYYMMDD-HHmmss}.json` and a copy at `{forge_version}/create-skill-result-latest.json` (copy, not symlink) via `python3 {atomicWriteHelper} write`, so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. Set `summary.evidence_report` to `{forge_version}/evidence-report.md` whenever that file exists, so the consumer can still reach the `## Auto-Decisions` audit on a failed run. HALTs before step 7 cannot write to disk because `{forge_version}` is only created at step 7 §1; for those, the stderr envelope is the contract and `summary.evidence_report` is `null`.
|
|
148
|
+
|
|
149
|
+
When `{headless_mode}` is false, HARD HALTs display their human message only — no envelope is emitted.
|
|
150
|
+
|
|
151
|
+
### 6. Chain to Health Check
|
|
152
|
+
|
|
153
|
+
**If not batch mode (or all batch briefs complete):**
|
|
154
|
+
|
|
155
|
+
Only after the compilation report, warnings (if any), recommended next steps, and result contract have been handled do you load `{nextStepFile}`, read it fully, and execute it. The health-check step is the true terminal step — do not stop here even though the report reads as final.
|
|
156
|
+
|
|
157
|
+
**If batch mode with remaining briefs:** Skip the health-check chain — load and execute `references/load-brief.md` for the next brief instead. The health check runs only after the final brief in the batch.
|
|
145
158
|
|
|
@@ -123,7 +123,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
|
|
|
123
123
|
|
|
124
124
|
If fetch or checkout fails, proceed to the **ephemeral fallback** (step 5).
|
|
125
125
|
|
|
126
|
-
**If `{workspace_repo_path}/.git/` does
|
|
126
|
+
**If `{workspace_repo_path}/.git/` does not exist (workspace miss):**
|
|
127
127
|
|
|
128
128
|
Clone the repository into the workspace for persistent reuse. Create the parent directory first (`{workspace_root}/repos/{host}/{owner}/`):
|
|
129
129
|
|
|
@@ -131,7 +131,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
|
|
|
131
131
|
mkdir -p "{workspace_root}/repos/{host}/{owner}/"
|
|
132
132
|
```
|
|
133
133
|
|
|
134
|
-
Clone with the appropriate branch flag — `--branch` is only valid for real branch/tag names, not for `HEAD`. **Do
|
|
134
|
+
Clone with the appropriate branch flag — `--branch` is only valid for real branch/tag names, not for `HEAD`. **Do not pass `--single-branch`** here: workspace clones are persistent and re-used for future forges with different `source_ref` values (a later run may target a different tag or branch). A single-branch workspace clone would force every re-forge with a new ref to fall through to ephemeral cloning, defeating the workspace cache:
|
|
135
135
|
|
|
136
136
|
```
|
|
137
137
|
# If source_ref is a real branch or tag (not HEAD/null):
|
|
@@ -154,7 +154,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
|
|
|
154
154
|
- `remote_clone_path = {workspace_repo_path}`
|
|
155
155
|
- `remote_clone_type = "workspace"`
|
|
156
156
|
|
|
157
|
-
**Scope filtering:** Since the workspace uses a full checkout (no sparse-checkout), apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
|
|
157
|
+
**Scope filtering:** Since the workspace uses a full checkout (no sparse-checkout), apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`, `build.gradle.kts`, `Package.swift`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
|
|
158
158
|
|
|
159
159
|
5. **Ephemeral fallback (on any workspace failure):**
|
|
160
160
|
|
|
@@ -216,7 +216,7 @@ Also store `source_ref` in context (from tag resolution above, or `HEAD` if no t
|
|
|
216
216
|
|
|
217
217
|
## Version Reconciliation (all tiers, source mode only)
|
|
218
218
|
|
|
219
|
-
**Target version override:** If `brief.target_version` is present, use it as the authoritative version for the skill. Do
|
|
219
|
+
**Target version override:** If `brief.target_version` is present, use it as the authoritative version for the skill. Do not warn about a brief-vs-source version mismatch — the user intentionally specified this version. Set the working version to `brief.target_version` and skip the rest of this reconciliation section. The `target_version` field indicates deliberate user intent (e.g., targeting an older version, or providing the version for a docs-only skill).
|
|
220
220
|
|
|
221
221
|
**If `source_type: "docs-only"`:** skip this section — no source files exist to reconcile.
|
|
222
222
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'step-doc-rot.md'
|
|
3
|
+
# Resolve `{shardBodyHelper}` by probing `{shardBodyProbeOrder}` in order
|
|
4
|
+
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
|
+
# path wins. HALT if neither resolves — hand line-counting is the least reliable
|
|
6
|
+
# deterministic op and would silently ship an over-budget body or wrongly HALT.
|
|
7
|
+
shardBodyProbeOrder:
|
|
8
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-shard-body.py'
|
|
9
|
+
- '{project-root}/src/shared/scripts/skf-shard-body.py'
|
|
3
10
|
---
|
|
4
11
|
|
|
5
12
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -15,42 +22,66 @@ Proactively reduce oversized SKILL.md bodies to under 400 lines by extracting Ti
|
|
|
15
22
|
- Auto-proceed step — no user interaction required
|
|
16
23
|
- Graceful skip — if body is under threshold, proceed without modification
|
|
17
24
|
- Only extract Tier 2 sections (identified by `## Full` heading prefix)
|
|
18
|
-
- Tier 1 sections
|
|
25
|
+
- Tier 1 sections stay inline — moving one to references/ would break the standalone SKILL.md the two-tier design guarantees
|
|
19
26
|
- Do not modify frontmatter — only body content and references/ directory
|
|
20
27
|
- Do not invoke `npx skill-check split-body` — this step uses direct extraction
|
|
21
28
|
- Do not invoke the Description Guard Protocol — frontmatter is untouched
|
|
22
29
|
|
|
23
30
|
## MANDATORY SEQUENCE
|
|
24
31
|
|
|
32
|
+
### §0. Run the Shard Script (primary path)
|
|
33
|
+
|
|
34
|
+
The counting, boundary detection, size-sort, file writes, and blockquote replacement described in §1–§5 are fully deterministic and run every invocation — so a script owns them, not the model. Do not count body lines or extract sections by hand when the script ran.
|
|
35
|
+
|
|
36
|
+
**Resolve `{shardBodyHelper}`** from `{shardBodyProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
37
|
+
|
|
38
|
+
Run:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv run {shardBodyHelper} <staging-skill-dir>/SKILL.md --budget 400
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
The script performs everything §1–§5 document — it counts the body between the frontmatter close and EOF, enumerates the `## Full` Tier 2 sections, extracts the largest first to `references/` until the body fits, writes the extracted files and the trimmed SKILL.md through the atomic-write helper, rewrites each section as a cross-reference blockquote, and checks Tier 1 preservation and cross-reference integrity. Read its JSON and set context directly:
|
|
45
|
+
|
|
46
|
+
- **`action: "skip"`** → the body was already within budget. Log `"auto-shard: skipped (body {body_lines_before} lines)"`, set `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before`/`body_lines_after` from the report, then skip to §6.
|
|
47
|
+
- **`action: "shard"`** → set `auto_shard_triggered: true` and copy `sections_extracted`, `body_lines_before`, `body_lines_after` straight from the report.
|
|
48
|
+
- **HALT** if `tier1_preserved` is false: `"Auto-shard removed Tier 1 section(s) {tier1_missing}. Aborting."`
|
|
49
|
+
- **HALT** if `xref_ok` is false: `"Auto-shard cross-references did not resolve. Aborting."`
|
|
50
|
+
- If `under_budget` is false, selective Tier 2 extraction alone could not bring the body under budget (rare — Tier 1 itself exceeds ~300 lines). Apply the §4 editing-judgment trim, then continue.
|
|
51
|
+
|
|
52
|
+
Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`, then proceed to §6.
|
|
53
|
+
|
|
54
|
+
**Manual fallback (only when `uv`/Python is unavailable):** perform §1–§5 by hand as documented below — they describe exactly what the script does.
|
|
55
|
+
|
|
25
56
|
### §1. Count Body Lines
|
|
26
57
|
|
|
27
|
-
|
|
58
|
+
The script counts all lines in the staging SKILL.md between the frontmatter closing `---` and EOF, excluding trailing blank lines, and reports the total as `body_lines_before`.
|
|
28
59
|
|
|
29
60
|
```
|
|
30
61
|
body_lines_before = body_line_count
|
|
31
62
|
```
|
|
32
63
|
|
|
33
|
-
**IF `body_line_count` <= 400:**
|
|
64
|
+
**IF `body_line_count` <= 400:** the script emits `action: "skip"` and writes nothing —
|
|
34
65
|
- Log: `"auto-shard: skipped (body {body_line_count} lines)"`
|
|
35
66
|
- Set context: `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before: {body_line_count}`, `body_lines_after: {body_line_count}`
|
|
36
67
|
- Skip to §6 (Auto-Proceed)
|
|
37
68
|
|
|
38
|
-
**ELSE:**
|
|
69
|
+
**ELSE:** the script proceeds to §2.
|
|
39
70
|
|
|
40
71
|
### §2. Selective Shard — Tier 2 Extraction
|
|
41
72
|
|
|
42
|
-
|
|
73
|
+
The script identifies Tier 2 sections by their `## Full` heading prefix:
|
|
43
74
|
- `## Full API Reference` → `references/full-api-reference.md`
|
|
44
75
|
- `## Full Type Definitions` → `references/full-type-definitions.md`
|
|
45
76
|
- `## Full Integration Patterns` → `references/full-integration-patterns.md`
|
|
46
77
|
|
|
47
|
-
|
|
78
|
+
Sections are sorted by line count descending (largest first).
|
|
48
79
|
|
|
49
80
|
**FOR EACH Tier 2 section (largest first):**
|
|
50
81
|
|
|
51
82
|
1. Extract the full section content (from `## Full` heading to the next `##` heading or EOF)
|
|
52
83
|
2. Derive the reference filename from the heading: kebab-case (as shown above)
|
|
53
|
-
3. Write the extracted content (preserving the `##` heading) to `<staging-skill-dir>/references/{filename}`
|
|
84
|
+
3. Write the extracted content (preserving the `##` heading) to `<staging-skill-dir>/references/{filename}` via the atomic-write helper
|
|
54
85
|
4. Replace the extracted section in SKILL.md with a cross-reference blockquote:
|
|
55
86
|
```markdown
|
|
56
87
|
> See [Full API Reference](references/full-api-reference.md)
|
|
@@ -58,44 +89,40 @@ Sort identified sections by line count descending (extract largest first).
|
|
|
58
89
|
5. Re-count body lines
|
|
59
90
|
6. **IF `body_line_count` <= 400:** stop extracting, proceed to §3
|
|
60
91
|
|
|
61
|
-
|
|
92
|
+
The report's `sections_extracted: [{heading, file, lines}]` records exactly which sections were pulled.
|
|
62
93
|
|
|
63
94
|
### §3. Tier 1 Preservation Check
|
|
64
95
|
|
|
65
|
-
|
|
96
|
+
The script verifies ALL Tier 1 sections that were inline before extraction remain inline in SKILL.md afterward. These headings:
|
|
66
97
|
|
|
67
98
|
- `## Overview`
|
|
68
99
|
- `## Quick Start`
|
|
69
100
|
- `## Common Workflows`
|
|
70
101
|
- `## Key API Summary` (or `## Component Catalog` for component-library scope)
|
|
71
|
-
- `## Migration & Deprecation Warnings` (conditional — only
|
|
102
|
+
- `## Migration & Deprecation Warnings` (conditional — only checked if it was present before extraction)
|
|
72
103
|
- `## Key Types`
|
|
73
104
|
- `## Architecture at a Glance`
|
|
74
|
-
- `## CLI` (conditional — only
|
|
75
|
-
- `## Scripts & Assets` (conditional — only
|
|
76
|
-
- `## Manual Sections` (conditional — only
|
|
105
|
+
- `## CLI` (conditional — only checked if present before extraction)
|
|
106
|
+
- `## Scripts & Assets` (conditional — only checked if present before extraction)
|
|
107
|
+
- `## Manual Sections` (conditional — only checked if present before extraction)
|
|
108
|
+
|
|
109
|
+
The result surfaces as `tier1_preserved` (with any pulled headings in `tier1_missing`).
|
|
77
110
|
|
|
78
|
-
**IF
|
|
111
|
+
**IF `tier1_preserved` is false:**
|
|
79
112
|
HALT: `"Auto-shard removed Tier 1 section {name}. Aborting."`
|
|
80
113
|
|
|
81
114
|
### §4. Post-Shard Validation
|
|
82
115
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
body_lines_after = body_line_count
|
|
87
|
-
```
|
|
116
|
+
The report's `body_lines_after` is the recount after all extraction. `under_budget` is true when the body now fits.
|
|
88
117
|
|
|
89
|
-
**IF `
|
|
118
|
+
**IF `under_budget` is false** (body still > 400 after all Tier 2 sections extracted — this is the one genuine editing-judgment step):
|
|
90
119
|
- Trim oversized Tier 1 sections: reduce `## Key API Summary` and `## Architecture at a Glance` content to fit within the 400-line budget
|
|
91
|
-
- Do
|
|
92
|
-
- Re-count and update `body_lines_after`
|
|
120
|
+
- Do not move any Tier 1 section to references/
|
|
121
|
+
- Re-run `{shardBodyHelper}` (or re-count) and update `body_lines_after`
|
|
93
122
|
|
|
94
123
|
### §5. Cross-Reference Integrity
|
|
95
124
|
|
|
96
|
-
|
|
97
|
-
1. Verify the file exists at `<staging-skill-dir>/references/{filename}`
|
|
98
|
-
2. Verify the cross-reference blockquote in SKILL.md contains a link resolving to the file
|
|
125
|
+
The script verifies, for each extracted reference file, that the file exists at `<staging-skill-dir>/references/{filename}` and that the cross-reference blockquote in SKILL.md links to it — reported as `xref_ok`. HALT if `xref_ok` is false.
|
|
99
126
|
|
|
100
127
|
Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`
|
|
101
128
|
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'validate.md'
|
|
3
|
+
scanDocRotHelper: 'scripts/scan-doc-rot.py'
|
|
3
4
|
---
|
|
4
5
|
|
|
5
6
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -8,7 +9,7 @@ nextStepFile: 'validate.md'
|
|
|
8
9
|
|
|
9
10
|
## STEP GOAL:
|
|
10
11
|
|
|
11
|
-
Scan feeder artifacts for doc-rot correction indicators and annotate the compiled SKILL.md with `## CORRECTION` blocks. Matching is grep
|
|
12
|
+
Scan feeder artifacts for doc-rot correction indicators and annotate the compiled SKILL.md with `## CORRECTION` blocks. Matching is a deterministic substring grep performed by `{scanDocRotHelper}` (`scripts/scan-doc-rot.py`) — no AI judgment is used for detection. The prompt keeps only the genuine judgment the script cannot make: enriching each match's `affected` symbol (§2) and choosing where each `## CORRECTION` block goes (§3).
|
|
12
13
|
|
|
13
14
|
## Rules
|
|
14
15
|
|
|
@@ -23,12 +24,12 @@ Scan feeder artifacts for doc-rot correction indicators and annotate the compile
|
|
|
23
24
|
|
|
24
25
|
### §1. Locate Feeder Artifacts
|
|
25
26
|
|
|
26
|
-
Identify the feeder artifacts in the staging directory for the current skill:
|
|
27
|
+
Identify the feeder artifacts in the **staging directory** for the current skill. This step (5c) runs **before** step 7 promotes the staging tree to `{forge_data_folder}/{skill-name}/{version}/`, so the feeder artifacts only exist under the staging path compile (step 5 §1a) wrote — reading the not-yet-promoted `{forge_data_folder}` path would make every match a no-op:
|
|
27
28
|
|
|
28
|
-
1. **Evidence report:** `
|
|
29
|
-
2. **Provenance map:** `
|
|
29
|
+
1. **Evidence report:** `_bmad-output/{skill-name}/evidence-report.md`
|
|
30
|
+
2. **Provenance map:** `_bmad-output/{skill-name}/provenance-map.json` — focus on T2/T3 entries with temporal annotations
|
|
30
31
|
3. **Temporal context:** changelogs, migration guides, and issue/PR data fetched by step 3b and enriched by step 4 (available in workflow context)
|
|
31
|
-
4. **Compiled SKILL.md:** the staged SKILL.md itself — check for `[QMD:...]` or `[DOC:...]` annotations referencing corrections
|
|
32
|
+
4. **Compiled SKILL.md:** the staged `_bmad-output/{skill-name}/SKILL.md` itself — check for `[QMD:...]` or `[DOC:...]` annotations referencing corrections. **Do not treat its own `## Migration & Deprecation Warnings` section (§4b) as a correction source:** compile (step 5 §4b) already authored that section from the same T2-future annotations, so its bullets are already-surfaced corrections — §2 discards matches that land inside it.
|
|
32
33
|
|
|
33
34
|
For each artifact, attempt to load its content. If an artifact does not exist or is empty, skip it — this is not an error.
|
|
34
35
|
|
|
@@ -36,7 +37,31 @@ Store: `feeder_artifacts_scanned: [{list of artifacts that were loaded}]`
|
|
|
36
37
|
|
|
37
38
|
### §2. Grep for Correction Indicators
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
The scan is deterministic plumbing — a fixed-table substring grep with one correct answer per input — so it runs in `{scanDocRotHelper}`, **not** in-prompt. Do not hand-grep the feeder artifacts: identical feeders must yield identical `correction_matches`, and only the script guarantees that across multi-KB inputs. Pass the `## Migration & Deprecation Warnings`-bearing compiled SKILL.md (feeder #4) as `--skill-md` and every other loaded feeder as a positional argument:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv run {scanDocRotHelper} \
|
|
44
|
+
--skill-md _bmad-output/{skill-name}/SKILL.md \
|
|
45
|
+
_bmad-output/{skill-name}/evidence-report.md \
|
|
46
|
+
_bmad-output/{skill-name}/provenance-map.json \
|
|
47
|
+
_bmad-output/{skill-name}-temporal/*.md
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
(Pass whichever of the §1 feeder paths actually exist — the script skips any that are missing or empty, and reports the loaded set in `scanned`.)
|
|
51
|
+
|
|
52
|
+
The script emits `{scanned: [...], matches: [...], match_count, excluded_count}` on stdout. Each entry in `matches` is a match record with the deterministic fields the script owns:
|
|
53
|
+
|
|
54
|
+
- `source`: the feeder artifact path where the match was found
|
|
55
|
+
- `pattern`: the specific pattern string that matched
|
|
56
|
+
- `category`: the category label
|
|
57
|
+
- `context_line`: the line containing the match
|
|
58
|
+
- `line_number`: the 1-indexed line the match sits on
|
|
59
|
+
|
|
60
|
+
Read `matches` into `correction_matches: [{match records}]`. Then add the one judgment field the script cannot infer:
|
|
61
|
+
|
|
62
|
+
- `affected`: the function name, API, or section the correction relates to — enrich each record from surrounding context (use the `[QMD:...]`/`[DOC:...]` annotations and nearby symbols); if not identifiable, set to `"unknown"`.
|
|
63
|
+
|
|
64
|
+
**What the script does (the contract it implements — keep this table and the script's `PATTERN_TABLE` in lockstep):** it matches every feeder line against the following correction patterns. All matches are **case-insensitive substring matches** — no regex interpretation, no semantic analysis.
|
|
40
65
|
|
|
41
66
|
| Pattern | Category |
|
|
42
67
|
|---------|----------|
|
|
@@ -54,16 +79,9 @@ Scan each loaded feeder artifact for the following correction patterns. All matc
|
|
|
54
79
|
| `migration required` | Migration |
|
|
55
80
|
| `signature changed` | Signature change |
|
|
56
81
|
|
|
57
|
-
|
|
58
|
-
- `source`: the feeder artifact path or citation where the match was found
|
|
59
|
-
- `pattern`: the specific pattern string that matched
|
|
60
|
-
- `category`: the category from the table above
|
|
61
|
-
- `context_line`: the line or excerpt containing the match
|
|
62
|
-
- `affected`: the function name, API, or section the correction relates to (extract from surrounding context if identifiable; otherwise set to `"unknown"`)
|
|
63
|
-
|
|
64
|
-
Store all matches as `correction_matches: [{match records}]`
|
|
82
|
+
**Exclusion — drop already-surfaced §4b corrections (deterministic, no AI judgment, applied inside the script before it emits):** the script discards any match whose `source` is the compiled SKILL.md (feeder #4) **and** whose `context_line` sits inside that file's own `## Migration & Deprecation Warnings` section — i.e. on a line at or after the `## Migration & Deprecation Warnings` heading and before the next `##` heading (`excluded_count` reports how many it dropped). Compile (step 5 §4b) authored that section from the same T2-future annotations, so re-emitting its bullets as `## CORRECTION` blocks in §3 would duplicate already-surfaced content verbatim. This is a positional heading-boundary check on text already loaded, not a semantic assessment. Set `feeder_artifacts_scanned` from the script's `scanned` list.
|
|
65
83
|
|
|
66
|
-
**IF `correction_matches` is empty
|
|
84
|
+
**IF `correction_matches` is empty** (the script returned `match_count: 0`, or the run had no feeder files to pass)**:**
|
|
67
85
|
- Log: `"doc-rot: skipped (no correction indicators found in feeder artifacts)"`
|
|
68
86
|
- Set context: `doc_rot_triggered: false`, `corrections_added: 0`
|
|
69
87
|
- Skip to §5 (Auto-Proceed)
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'step-auto-shard.md'
|
|
3
|
+
# Resolve `{detectDocsHelper}` by probing `{detectDocsProbeOrder}` in order
|
|
4
|
+
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
|
+
# path wins. HALT if neither resolves — §2 has no prose fallback for doc-source
|
|
6
|
+
# detection (Pages-API walk, docs/ folder scan, content hashing).
|
|
7
|
+
detectDocsProbeOrder:
|
|
8
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-docs.py'
|
|
9
|
+
- '{project-root}/src/shared/scripts/skf-detect-docs.py'
|
|
3
10
|
---
|
|
4
11
|
|
|
5
12
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -21,7 +28,7 @@ Record detected documentation pages and README with content hashes in metadata.j
|
|
|
21
28
|
|
|
22
29
|
### 1. Check for Upstream Doc Detection Results
|
|
23
30
|
|
|
24
|
-
Check if `doc_detection_results` is already populated in the workflow context (set by BS auto-brief in the
|
|
31
|
+
Check if `doc_detection_results` is already populated in the workflow context (set by BS auto-brief in the forge-auto pipeline).
|
|
25
32
|
|
|
26
33
|
- **If upstream results exist:** use them directly, skip to step 3.
|
|
27
34
|
- **If no upstream results:** continue to step 2.
|
|
@@ -37,10 +44,12 @@ Check that `{source_repo}` is available from the skill brief.
|
|
|
37
44
|
|
|
38
45
|
**If `{source_repo}` is available:**
|
|
39
46
|
|
|
47
|
+
**Resolve `{detectDocsHelper}`** from `{detectDocsProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
48
|
+
|
|
40
49
|
Invoke the detect-docs script:
|
|
41
50
|
|
|
42
51
|
```bash
|
|
43
|
-
uv run
|
|
52
|
+
uv run {detectDocsHelper} \
|
|
44
53
|
--repo-url {source_repo} \
|
|
45
54
|
[--local-path {source_path}] \
|
|
46
55
|
[--skip-pages-api]
|
|
@@ -85,10 +94,10 @@ Map each detection result to the `doc_sources` schema:
|
|
|
85
94
|
Field mapping from `skf-detect-docs.py` output:
|
|
86
95
|
- `url` ← `url` (direct copy)
|
|
87
96
|
- `detected_via` ← `detected_via` (direct copy; or `"readme_always"` for the mandatory README entry)
|
|
88
|
-
- `content_hash` ← `content_hash` (direct copy, already in `sha256:{hexdigest}` format
|
|
97
|
+
- `content_hash` ← `content_hash` (direct copy, already in `sha256:{hexdigest}` format)
|
|
89
98
|
- `recorded_at` ← generated at step execution time (ISO-8601 with timezone)
|
|
90
99
|
|
|
91
|
-
Note: `content_type` from detect-docs output is
|
|
100
|
+
Note: `content_type` from detect-docs output is not carried into `doc_sources`.
|
|
92
101
|
|
|
93
102
|
### 5. Update metadata.json
|
|
94
103
|
|
|
@@ -82,7 +82,7 @@ Set `{ccc_discovery: []}` in context.
|
|
|
82
82
|
|
|
83
83
|
Display: "CCC discovery unavailable — proceeding with standard extraction."
|
|
84
84
|
|
|
85
|
-
Do
|
|
85
|
+
Do not halt. This is not an error.
|
|
86
86
|
|
|
87
87
|
**If search returns empty results:**
|
|
88
88
|
|
|
@@ -92,16 +92,5 @@ No message needed — empty results are normal for small or highly focused libra
|
|
|
92
92
|
|
|
93
93
|
### 5. Auto-Proceed
|
|
94
94
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
#### EXECUTION RULES:
|
|
98
|
-
|
|
99
|
-
- This is an auto-proceed step with no user choices
|
|
100
|
-
- Quick/Forge tiers skip directly with no output
|
|
101
|
-
- Forge+/Deep with ccc displays brief discovery summary then auto-proceeds
|
|
102
|
-
- CCC failures do not halt — degrade and proceed
|
|
103
|
-
|
|
104
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
105
|
-
|
|
106
|
-
ONLY WHEN discovery is complete (Forge+/Deep with ccc) or the step is skipped (Quick/Forge or ccc unavailable) will you proceed to load `{nextStepFile}` for AST extraction.
|
|
95
|
+
No user interaction. Load `{nextStepFile}`, read it fully, then execute it. CCC failures degrade and proceed — they never halt.
|
|
107
96
|
|