bmad-module-skill-forge 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +0 -8
- package/docs/_data/pinned.yaml +1 -1
- package/docs/_internal/STABILITY.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/examples.md +1 -1
- package/docs/workflows.md +5 -5
- package/package.json +2 -2
- package/src/README.md +1 -1
- package/src/knowledge/ccc-bridge.md +12 -12
- package/src/knowledge/qmd-registry.md +5 -5
- package/src/shared/health-check.md +5 -5
- package/src/shared/references/description-guard-protocol.md +100 -0
- package/src/shared/references/output-contract-schema.md +1 -1
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
- package/src/shared/scripts/skf-build-change-manifest.py +420 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
- package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
- package/src/shared/scripts/skf-description-guard.py +359 -0
- package/src/shared/scripts/skf-detect-language.py +2 -2
- package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
- package/src/shared/scripts/skf-detect-tools.py +97 -8
- package/src/shared/scripts/skf-detect-workspaces.py +1 -1
- package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
- package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
- package/src/shared/scripts/skf-hash-content.py +284 -0
- package/src/shared/scripts/skf-load-provenance.py +295 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +34 -4
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
- package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
- package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
- package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
- package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
- package/src/skf-audit-skill/SKILL.md +66 -15
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
- package/src/skf-audit-skill/customize.toml +49 -0
- package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-audit-skill/{steps-c/step-01-init.md → references/init.md} +57 -19
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -17
- package/src/skf-brief-skill/SKILL.md +48 -18
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
- package/src/skf-brief-skill/customize.toml +44 -0
- package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
- package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
- package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
- package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
- package/src/skf-brief-skill/references/headless-args.md +9 -9
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
- package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
- package/src/skf-brief-skill/references/version-resolution.md +2 -2
- package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
- package/src/skf-create-skill/SKILL.md +25 -19
- package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
- package/src/skf-create-skill/assets/skill-sections.md +5 -5
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
- package/src/skf-create-skill/customize.toml +35 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
- package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
- package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
- package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
- package/src/skf-create-skill/references/extraction-patterns.md +8 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +11 -11
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
- package/src/skf-create-stack-skill/SKILL.md +76 -17
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +46 -0
- package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
- package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
- package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
- package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
- package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
- package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
- package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
- package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
- package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
- package/src/skf-drop-skill/SKILL.md +84 -12
- package/src/skf-drop-skill/customize.toml +57 -0
- package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
- package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
- package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
- package/src/skf-export-skill/SKILL.md +85 -16
- package/src/skf-export-skill/assets/managed-section-format.md +3 -3
- package/src/skf-export-skill/assets/snippet-format.md +2 -2
- package/src/skf-export-skill/customize.toml +49 -0
- package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +11 -11
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +11 -49
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +20 -8
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +109 -113
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +16 -31
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
- package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
- package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
- package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
- package/src/skf-test-skill/references/health-check.md +14 -0
- package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
- package/src/skf-test-skill/references/migration-section-rules.md +4 -2
- package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
- package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
- package/src/skf-test-skill/references/scoring-rules.md +8 -6
- package/src/skf-test-skill/references/source-access-protocol.md +7 -5
- package/src/skf-test-skill/scripts/compute-score.py +88 -17
- package/src/skf-test-skill/templates/test-report-template.md +13 -13
- package/src/skf-update-skill/SKILL.md +23 -14
- package/src/skf-update-skill/customize.toml +44 -0
- package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
- package/src/skf-update-skill/references/health-check.md +32 -0
- package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
- package/src/skf-update-skill/references/manual-section-rules.md +4 -0
- package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
- package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
- package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
- package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
- package/src/skf-update-skill/references/report.md +214 -0
- package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
- package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
- package/src/skf-verify-stack/SKILL.md +89 -17
- package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
- package/src/skf-verify-stack/customize.toml +50 -0
- package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
- package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
- package/src/skf-verify-stack/references/init.md +166 -0
- package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
- package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
- package/tools/validate-docs-drift.js +1 -1
- package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
- package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
- package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
- package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
- package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
- package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
|
@@ -1,18 +1,38 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
3
|
-
componentExtractionStepFile: '
|
|
2
|
+
nextStepFile: 'sub/fetch-temporal.md'
|
|
3
|
+
componentExtractionStepFile: 'component-extraction.md'
|
|
4
4
|
extractionPatternsData: 'references/extraction-patterns.md'
|
|
5
5
|
extractionPatternsTracingData: 'references/extraction-patterns-tracing.md'
|
|
6
6
|
tierDegradationRulesData: 'references/tier-degradation-rules.md'
|
|
7
7
|
sourceResolutionData: 'references/source-resolution-protocols.md'
|
|
8
|
+
authoritativeFilesProtocol: 'references/authoritative-files-protocol.md'
|
|
8
9
|
# Probe installed SKF module path first, src/ dev-checkout fallback. At first
|
|
9
10
|
# use below, resolve `{atomicWriteHelper}` to the first existing path; HALT if
|
|
10
11
|
# neither candidate exists — losing atomic-write guarantees is not an option.
|
|
11
12
|
atomicWriteProbeOrder:
|
|
12
13
|
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
13
14
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
15
|
+
# Resolve `{detectScriptsAssetsHelper}` to the first existing path; HALT if
|
|
16
|
+
# neither candidate exists. §4c relies on the helper for deterministic
|
|
17
|
+
# script/asset detection (file walk, SHA-256 hashing, header-comment purpose
|
|
18
|
+
# extraction); falling back to prose-driven detection would lose hash stability.
|
|
19
|
+
detectScriptsAssetsProbeOrder:
|
|
20
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-scripts-assets.py'
|
|
21
|
+
- '{project-root}/src/shared/scripts/skf-detect-scripts-assets.py'
|
|
22
|
+
# Resolve `{resolveAuthoritativeFilesHelper}` to the first existing path;
|
|
23
|
+
# HALT if neither exists. §2a uses it to scan the source tree for
|
|
24
|
+
# authoritative AI documentation files, classify each against scope
|
|
25
|
+
# filters + amendments, and load previews + content hashes — all five
|
|
26
|
+
# deterministic phases in one call. Falling back to prose-driven file
|
|
27
|
+
# walking + glob matching + hashing would let the LLM drift on the
|
|
28
|
+
# heuristic list and miss auth-doc files at deeper directory depths.
|
|
29
|
+
resolveAuthoritativeFilesProbeOrder:
|
|
30
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-resolve-authoritative-files.py'
|
|
31
|
+
- '{project-root}/src/shared/scripts/skf-resolve-authoritative-files.py'
|
|
14
32
|
---
|
|
15
33
|
|
|
34
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
35
|
+
|
|
16
36
|
# Step 3: Extract
|
|
17
37
|
|
|
18
38
|
## STEP GOAL:
|
|
@@ -27,8 +47,6 @@ To extract all public exports, function signatures, type definitions, and co-imp
|
|
|
27
47
|
|
|
28
48
|
## MANDATORY SEQUENCE
|
|
29
49
|
|
|
30
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
31
|
-
|
|
32
50
|
### 1. Load Extraction Patterns
|
|
33
51
|
|
|
34
52
|
Load `{extractionPatternsData}` completely. Identify the strategy for the current forge tier.
|
|
@@ -41,115 +59,15 @@ From the brief, apply scope and pattern filters:
|
|
|
41
59
|
- `scope.include` — file globs to include
|
|
42
60
|
- `scope.exclude` — file globs to exclude
|
|
43
61
|
|
|
44
|
-
Build the filtered file list from the source tree resolved in step
|
|
62
|
+
Build the filtered file list from the source tree resolved in step 1. Record the result: "**Filtered file count: {N} files in scope**" — this count is the input to the AST Extraction Protocol decision tree in the extraction patterns data file.
|
|
45
63
|
|
|
46
64
|
### 2a. Discovered Authoritative Files Protocol
|
|
47
65
|
|
|
48
66
|
**Skip this section entirely if `source_type: "docs-only"`** — there is no source tree to scan.
|
|
49
67
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
This protocol detects such files, prompts the user, and records the decision in the brief so future runs (re-create, update, audit) honor it.
|
|
53
|
-
|
|
54
|
-
**Heuristic scan list (case-insensitive basename match, any directory depth):**
|
|
55
|
-
|
|
56
|
-
- `llms.txt`, `llms-full.txt`
|
|
57
|
-
- `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `COPILOT.md`
|
|
58
|
-
- `.cursorrules`, `.windsurfrules`, `.clinerules`
|
|
59
|
-
|
|
60
|
-
**Procedure:**
|
|
61
|
-
|
|
62
|
-
1. **Walk the source tree** resolved in step-01 (NOT the filtered file list from §2 — we want files the brief excluded too). Match file basenames against the heuristic list case-insensitively.
|
|
63
|
-
|
|
64
|
-
2. **Diff against filtered list.** For each match, check whether the path is already present in §2's filtered file list:
|
|
65
|
-
- **Already in scope (matched by `scope.include`):** **remove the path from the filtered file list** and add it directly to `promoted_docs[]` with `{path, heuristic, size_bytes, line_count, content_hash}`. No prompt — the user or a prior amendment already said it belongs in scope, but authoritative docs must never reach §4 code extraction. This is both the "already promoted from a prior run" case and the "user manually added to scope.include" case.
|
|
66
|
-
- **Excluded by brief patterns:** this is a **candidate** for the prompt at step 5.
|
|
67
|
-
|
|
68
|
-
3. **Check existing amendments.** Before prompting, consult `brief.scope.amendments[]` (see `src/skf-brief-skill/assets/skill-brief-schema.md` for the schema). If any amendment entry has `path == candidate.path`, the decision is already recorded:
|
|
69
|
-
- `action: "promoted"` → the file should already be in `scope.include` (amendments are write-through). No prompt. **Still populate `promoted_docs[]`** for this path — compute its content hash and add a `{path, heuristic, size_bytes, line_count, content_hash}` entry so step-05 §6 writes the `file_entries[]` row. This is the deterministic replay path for re-runs.
|
|
70
|
-
- `action: "skipped"` → user previously declined. No prompt. Do not add to `promoted_docs[]`. Move on.
|
|
71
|
-
|
|
72
|
-
4. **Load preview.** For each unresolved candidate, read the first 20 lines of the file. Record the line count and file size in bytes.
|
|
73
|
-
|
|
74
|
-
5. **Prompt.** Present each candidate to the user:
|
|
75
|
-
|
|
76
|
-
```
|
|
77
|
-
**Discovered authoritative file excluded by brief scope**
|
|
78
|
-
|
|
79
|
-
Path: {relative_path_from_source_root}
|
|
80
|
-
Size: {line_count} lines, {bytes} bytes
|
|
81
|
-
Matched heuristic: {basename}
|
|
82
|
-
Excluded by pattern: {matching_exclude_pattern or "not matched by any scope.include"}
|
|
83
|
-
|
|
84
|
-
First 20 lines:
|
|
85
|
-
{inline preview}
|
|
86
|
-
|
|
87
|
-
This file is typically authored for AI assistants and may contain canonical usage information not present elsewhere in the source. How should extraction handle it?
|
|
88
|
-
|
|
89
|
-
[P] Promote — include in this extraction run AND amend brief for future runs
|
|
90
|
-
[S] Skip — honor the brief exclusion AND record skip in amendments (no re-prompt)
|
|
91
|
-
[U] Update — halt this run and return to skf-brief-skill to refine scope
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
6. **Headless mode (`{headless_mode}` is true):** auto-select `[S] Skip` for every candidate. Record amendment entries with `action: "skipped"` and `reason: "headless: no user to prompt"`. A non-interactive run must never silently promote files into scope — the decision requires a human.
|
|
95
|
-
|
|
96
|
-
7. **Apply decision:**
|
|
97
|
-
|
|
98
|
-
- **[P] Promote:**
|
|
99
|
-
1. **Do NOT add the path to the filtered file list from §2.** Authoritative documentation files are not code — they must not go through the AST extraction pipeline in §4, which would silently produce no exports (ghost entries). Instead, add the path to a new in-context list `promoted_docs[]` with `{path, heuristic, size_bytes, line_count, content_hash}`. Compute the SHA-256 content hash of the file now.
|
|
100
|
-
2. Append to `brief.scope.include`: add the exact `candidate.path` as a literal glob (no wildcards — the amendment targets this specific file). This write ensures that a re-run of `skf-create-skill` against the amended brief sees the path in scope and skips re-prompting.
|
|
101
|
-
3. Append to `brief.scope.amendments[]` a new entry with `action: "promoted"`, `path: candidate.path`, `reason: {user-provided one-sentence reason or auto-generated "authoritative AI docs — matched heuristic {basename}"}`, `heuristic: {basename}`, `date: {today ISO}`, `workflow: "skf-create-skill"`.
|
|
102
|
-
4. **Write the amended brief back to disk immediately** at `{forge_data_folder}/{skill_name}/skill-brief.yaml`. Immediate write (not deferred to step-07) ensures a crashed run still leaves the amendment recorded. Preserve all other brief fields and formatting. **Use atomic write + backup:** before writing, copy the original brief to `{forge_data_folder}/{skill_name}/skill-brief.yaml.bak` (overwriting any prior `.bak` — the most recent pre-amendment snapshot is the useful one). Then pipe the amended YAML through the shared atomic writer so a crash mid-write cannot corrupt the brief:
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
# 1. Backup
|
|
106
|
-
cp {forge_data_folder}/{skill_name}/skill-brief.yaml \
|
|
107
|
-
{forge_data_folder}/{skill_name}/skill-brief.yaml.bak
|
|
108
|
-
|
|
109
|
-
# 2. Atomic write (stdin → tmp → fsync → rename)
|
|
110
|
-
cat <<'AMENDED_YAML' | python3 {atomicWriteHelper} write \
|
|
111
|
-
--target {forge_data_folder}/{skill_name}/skill-brief.yaml
|
|
112
|
-
{amended brief YAML}
|
|
113
|
-
AMENDED_YAML
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
The helper stages into `{brief}.skf-tmp`, fsyncs, then `os.replace()`s — readers never see a half-written brief.
|
|
117
|
-
5. Display: "**Promoted `{path}`** — tracked as documentation file, amendment recorded."
|
|
118
|
-
|
|
119
|
-
- **[S] Skip:**
|
|
120
|
-
1. Do NOT modify `scope.include` or `scope.exclude`.
|
|
121
|
-
2. Append to `brief.scope.amendments[]` a new entry with `action: "skipped"`, `path: candidate.path`, `reason: {user-provided reason or auto-generated "user declined promotion at create-skill §2a"}`, `heuristic: {basename}`, `date: {today ISO}`, `workflow: "skf-create-skill"`.
|
|
122
|
-
3. **Write the amended brief back to disk** so future runs do not re-prompt. Use the same backup-then-atomic-write pattern as the [P] Promote path (copy to `skill-brief.yaml.bak` first, then pipe through `skf-atomic-write.py write --target {brief_path}`).
|
|
123
|
-
4. Display: "**Skipped `{path}`** — decision recorded in amendments."
|
|
124
|
-
|
|
125
|
-
- **[U] Update:**
|
|
126
|
-
1. Halt the workflow immediately.
|
|
127
|
-
2. Display: "**Halting create-skill.** Re-run `skf-brief-skill` to refine the scope filters for `{skill_name}`, then re-run `skf-create-skill`. Decisions for previously prompted candidates were already persisted to the brief; the current candidate was not written."
|
|
128
|
-
3. Exit with status `halted-for-brief-refinement`.
|
|
129
|
-
|
|
130
|
-
8. **Summary.** After all candidates are resolved (or none were found), display a one-line summary:
|
|
68
|
+
Load `{authoritativeFilesProtocol}` and execute it. The full protocol (heuristic scan list, helper invocation, classification dispatch, prompt flow, P/S/U decision-apply, summary, provenance-map handoff, downstream consumption) lives there. This stub exists so the inline `### 2a` heading stays present in `extract.md`'s table of contents while keeping the body lean.
|
|
131
69
|
|
|
132
|
-
|
|
133
|
-
- If N = 0: `"Authoritative files scan: no candidates."`
|
|
134
|
-
|
|
135
|
-
**Record for evidence report:** `authoritative_files_scan: {candidates: N, promoted: P, skipped: S, pre_decided: A, decisions: [{path, action, heuristic, reason}]}` — step-07 includes this in `evidence-report.md`.
|
|
136
|
-
|
|
137
|
-
**How promoted docs reach the provenance map:**
|
|
138
|
-
|
|
139
|
-
Promoted docs do NOT flow through §4 code extraction. Instead:
|
|
140
|
-
|
|
141
|
-
1. §2a populates the in-context `promoted_docs[]` list with content hashes.
|
|
142
|
-
2. **Step-05 §6** (provenance-map assembly) reads `promoted_docs[]` and emits one `file_entries[]` entry per promoted doc with `file_type: "doc"`, `extraction_method: "promoted-authoritative"`, `confidence: "T1-low"`, and the pre-computed `content_hash`.
|
|
143
|
-
3. **Step-07 §2** does NOT copy doc files into the skill package (unlike scripts and assets). The source file remains at its original path; only the provenance map tracks it. Future audit and update workflows compare against this tracking entry via content hash — no file copy is required because the intent is drift detection on the *source*, not bundling documentation into the skill output.
|
|
144
|
-
|
|
145
|
-
**Re-running `skf-create-skill`** reads the amended brief. Files with `action: "promoted"` amendments already appear in `scope.include`, but §2a still runs — it detects the file is in scope AND has an existing amendment, and takes the "pre-decided" silent path. The `promoted_docs[]` list is rebuilt on each run by scanning amendments with `action: "promoted"` (this is the deterministic replay path).
|
|
146
|
-
|
|
147
|
-
**Downstream workflow consumption** (zero code changes required):
|
|
148
|
-
|
|
149
|
-
- **`skf-update-skill`** reads `provenance-map.json`. Promoted docs appear as `file_entries[]` entries. Update-skill Category D (script/asset file changes) iterates `file_entries` and compares content hashes — this works identically for `file_type: "doc"` entries, giving drift detection for free.
|
|
150
|
-
- **`skf-audit-skill`** (after the bounded re-index fix) scans files from `provenance-map.json`. The re-index builds its list from `entries[].source_file ∪ file_entries[].source_file`, so promoted doc paths are naturally included in the audit scan.
|
|
151
|
-
|
|
152
|
-
The brief is the single source of truth for authored scope intent. The provenance map is the single source of truth for extracted state. `scope.amendments[]` is the bridge that records when those two intentionally diverged. `promoted_docs[]` is the in-memory handoff from §2a to step-05 §6; it is not persisted — the persisted form is the `file_entries[]` list in provenance-map.json.
|
|
70
|
+
Briefly: scan the source tree for authoritative AI documentation files (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.) that the brief's scope filters may have excluded. The `{resolveAuthoritativeFilesHelper}` helper does the deterministic work (walk, scope diff, amendment reconcile, preview load, hashing); the LLM applies the resulting `unresolved[]` prompt loop. Promoted decisions are persisted to the brief immediately so re-runs replay deterministically.
|
|
153
71
|
|
|
154
72
|
### 2b. Resolve Source Access
|
|
155
73
|
|
|
@@ -167,7 +85,7 @@ This ensures source code is accessible regardless of which extraction path is ta
|
|
|
167
85
|
|
|
168
86
|
If ALL of these conditions are true:
|
|
169
87
|
- `tools.ccc` is true in forge-tier.yaml
|
|
170
|
-
- `{ccc_discovery}` is empty (step
|
|
88
|
+
- `{ccc_discovery}` is empty (step 2b deferred because source was remote)
|
|
171
89
|
- `remote_clone_path` is set (source resolution succeeded for a remote URL)
|
|
172
90
|
- Tier is Forge+ or Deep
|
|
173
91
|
|
|
@@ -204,7 +122,7 @@ Then run CCC indexing and discovery on the resolved clone (workspace or ephemera
|
|
|
204
122
|
|
|
205
123
|
**CCC Discovery Integration (Forge+ and Deep with ccc only):**
|
|
206
124
|
|
|
207
|
-
If `{ccc_discovery}` is in context and non-empty (populated by step
|
|
125
|
+
If `{ccc_discovery}` is in context and non-empty (populated by step 2b or deferred discovery above):
|
|
208
126
|
- Sort the filtered file list by CCC relevance score: files appearing in `{ccc_discovery}` results move to the front of the extraction queue, sorted by their relevance score descending
|
|
209
127
|
- Files NOT in CCC results remain in the queue after ranked files — they are not excluded, only deprioritized
|
|
210
128
|
- Display: "**CCC discovery: {N} files pre-ranked by semantic relevance** — extraction will prioritize these first."
|
|
@@ -227,9 +145,9 @@ Load and execute `{componentExtractionStepFile}` completely. When that step comp
|
|
|
227
145
|
|
|
228
146
|
**If `source_type: "docs-only"` in the brief data:**
|
|
229
147
|
|
|
230
|
-
"**Docs-only mode:** No source code to extract. Documentation content will be fetched from `doc_urls` in step
|
|
148
|
+
"**Docs-only mode:** No source code to extract. Documentation content will be fetched from `doc_urls` in step 3c."
|
|
231
149
|
|
|
232
|
-
Build an empty extraction inventory with zero exports. **Set `top_exports = []` explicitly in context** — downstream steps (notably §3b targeted searches and step
|
|
150
|
+
Build an empty extraction inventory with zero exports. **Set `top_exports = []` explicitly in context** — downstream steps (notably §3b targeted searches and step 4 enrichment fan-out) must see an empty list rather than an undefined/missing field so they can short-circuit deterministically. Set `extraction_mode: "docs-only"` in context. Auto-proceed through Gate 2 (section 6) — display the empty inventory and note that T3 content will be produced by the doc-fetcher step.
|
|
233
151
|
|
|
234
152
|
**If `source_type: "source"` (default):** Continue with extraction below.
|
|
235
153
|
|
|
@@ -250,7 +168,7 @@ Source resolution, version reconciliation, and CCC discovery were completed in s
|
|
|
250
168
|
|
|
251
169
|
**Forge/Forge+/Deep Tier (AST available):**
|
|
252
170
|
|
|
253
|
-
⚠️ **CRITICAL:** Before executing AST extraction, load the **AST Extraction Protocol** section from `{extractionPatternsData}`. Follow the decision tree based on the file count from step
|
|
171
|
+
⚠️ **CRITICAL:** Before executing AST extraction, load the **AST Extraction Protocol** section from `{extractionPatternsData}`. Follow the decision tree based on the file count from step 1's file tree. This determines whether to use the MCP tool, scoped YAML rules, or CLI streaming. Never use `ast-grep --json` (without `=stream`) — it loads the entire result set into memory and will fail on large codebases. Always use the explicit `run` subcommand with streaming: `ast-grep run -p '{pattern}' --json=stream`.
|
|
254
172
|
|
|
255
173
|
1. Detect language from brief or file extensions
|
|
256
174
|
2. Follow the AST Extraction Protocol decision tree from `{extractionPatternsData}`:
|
|
@@ -295,15 +213,29 @@ Use the entry point as the authoritative source for `metadata.json`'s `exports[]
|
|
|
295
213
|
|
|
296
214
|
**Default resolution:** If `scripts_intent` is absent from the brief, treat as `"detect"` (auto-detection). If `assets_intent` is absent, treat as `"detect"`. Only an explicit `"none"` value disables detection.
|
|
297
215
|
|
|
298
|
-
|
|
216
|
+
Invoke the deterministic detector — it implements the heuristics from `{extractionPatternsTracingData}` (directory conventions, shebang signals, `package.json` `bin` entry-points, asset filename patterns, binary-extension exclusion, generated-path pruning) so this stage doesn't re-derive them per-run:
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
uv run {detectScriptsAssetsHelper} detect <source-root> \
|
|
220
|
+
--scripts-intent <scripts_intent> \
|
|
221
|
+
--assets-intent <assets_intent> \
|
|
222
|
+
[--scope-include "<glob1>,<glob2>,..."] \
|
|
223
|
+
[--max-lines 500]
|
|
224
|
+
```
|
|
299
225
|
|
|
300
|
-
|
|
226
|
+
The helper emits JSON on stdout:
|
|
301
227
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"scripts_inventory": [ {name, source_file, purpose, language, content_hash, confidence, lines, size_flag}, ... ],
|
|
231
|
+
"assets_inventory": [ {name, source_file, purpose, type, content_hash, confidence, lines, size_flag}, ... ],
|
|
232
|
+
"scripts_skipped": <bool>,
|
|
233
|
+
"assets_skipped": <bool>,
|
|
234
|
+
"stats": { "scripts_found": N, "assets_found": M, "files_scanned": K }
|
|
235
|
+
}
|
|
236
|
+
```
|
|
305
237
|
|
|
306
|
-
|
|
238
|
+
Merge `scripts_inventory[]` and `assets_inventory[]` into the running extraction inventory verbatim — entries already carry `confidence: "T1-low"` and `content_hash` (sha256:...). Records with `size_flag: "oversized"` should be surfaced in §6 (Extraction Summary) so the user can confirm before bundling. If both `scripts_skipped` and `assets_skipped` are true, the helper performs no walk and §4c is effectively a no-op.
|
|
307
239
|
|
|
308
240
|
### 5. Build Extraction Inventory
|
|
309
241
|
|
|
@@ -323,7 +255,7 @@ Compile all extracted data into a structured inventory:
|
|
|
323
255
|
- Total exports found
|
|
324
256
|
- Exports by type (functions, types/interfaces, constants)
|
|
325
257
|
- Confidence breakdown (T1 count, T1-low count)
|
|
326
|
-
- `top_exports[]` — sorted list of the top 10-20 public API function names by prominence (import frequency or documentation position). This named field is consumed by step
|
|
258
|
+
- `top_exports[]` — sorted list of the top 10-20 public API function names by prominence (import frequency or documentation position). This named field is consumed by step 3b for targeted temporal fetching and cache fingerprinting.
|
|
327
259
|
|
|
328
260
|
**Script/asset counts (when detected):**
|
|
329
261
|
- `scripts_found`: count of scripts detected
|
|
@@ -335,7 +267,7 @@ Compile all extracted data into a structured inventory:
|
|
|
335
267
|
|
|
336
268
|
### 6. Present Extraction Summary (Gate 2)
|
|
337
269
|
|
|
338
|
-
**Docs-only note:** If `docs_only_mode` is active (`extraction_mode: "docs-only"`), display a brief note explaining that T3 content will be added by the doc-fetcher step (step
|
|
270
|
+
**Docs-only note:** If `docs_only_mode` is active (`extraction_mode: "docs-only"`), display a brief note explaining that T3 content will be added by the doc-fetcher step (step 3c), then auto-proceed past this gate. Example: "Docs-only mode: extraction inventory is empty. Documentation content will be fetched from `doc_urls` in step 3c. Auto-proceeding."
|
|
339
271
|
|
|
340
272
|
Display the extraction findings for user confirmation:
|
|
341
273
|
|
|
@@ -30,7 +30,7 @@ Structural extraction via ast-grep — verified exports with line-level citation
|
|
|
30
30
|
|
|
31
31
|
> **Note:** `ast_bridge.*`, `qmd_bridge.*`, and `ccc_bridge.*` references below are **conceptual interfaces**, not callable functions. Resolve them as follows:
|
|
32
32
|
> - `ast_bridge.*` → ast-grep MCP tools (`mcp__ast-grep__find_code`, `mcp__ast-grep__find_code_by_rule`) or `ast-grep` CLI
|
|
33
|
-
> - `qmd_bridge.*` → QMD MCP `query` tool (`mcp__plugin_qmd-plugin_qmd__query`) taking `searches=[{type:'lex'|'vec'|'hyde', query, intent}]`, or `qmd` CLI (`qmd search` / `qmd vector-search`). The legacy `vector_search` MCP tool has been removed; if a client surfaces a tool-not-found error, degrade gracefully per the QMD step
|
|
33
|
+
> - `qmd_bridge.*` → QMD MCP `query` tool (`mcp__plugin_qmd-plugin_qmd__query`) taking `searches=[{type:'lex'|'vec'|'hyde', query, intent}]`, or `qmd` CLI (`qmd search` / `qmd vector-search`). The legacy `vector_search` MCP tool has been removed; if a client surfaces a tool-not-found error, degrade gracefully per the QMD step 4 tool-probe note — do not retry the stale name.
|
|
34
34
|
> - `ccc_bridge.*` → `/ccc` skill (Claude Code), ccc MCP server (Cursor), or `ccc` CLI
|
|
35
35
|
> - `gh_bridge.*` → `gh api` commands or direct file I/O for local sources
|
|
36
36
|
>
|
|
@@ -64,10 +64,10 @@ Identical extraction to Forge tier. CCC adds an upstream semantic discovery step
|
|
|
64
64
|
|
|
65
65
|
### When CCC Pre-Discovery Applies
|
|
66
66
|
|
|
67
|
-
CCC pre-discovery runs in
|
|
67
|
+
CCC pre-discovery runs in ccc-discover (before this extraction step) when ALL of the following are true:
|
|
68
68
|
- Tier is Forge+ or Deep
|
|
69
69
|
- `tools.ccc: true` in forge-tier.yaml
|
|
70
|
-
- `ccc_index.status` is `"fresh"`, `"stale"`, `"created"`, or `"none"`/`"failed"` (step
|
|
70
|
+
- `ccc_index.status` is `"fresh"`, `"stale"`, `"created"`, or `"none"`/`"failed"` (step 2b attempts lazy indexing for the latter two)
|
|
71
71
|
|
|
72
72
|
The discovery step stores `{ccc_discovery: [{file, score, snippet}]}` in context. This extraction step consumes those results to pre-rank the file list.
|
|
73
73
|
|
|
@@ -96,16 +96,16 @@ CCC pre-discovery failures (ccc unavailable, command error, empty results) alway
|
|
|
96
96
|
|
|
97
97
|
## Deep Tier (AST + QMD)
|
|
98
98
|
|
|
99
|
-
Same extraction as Forge tier. Deep tier adds enrichment in step
|
|
99
|
+
Same extraction as Forge tier. Deep tier adds enrichment in step 4, not extraction.
|
|
100
100
|
|
|
101
101
|
### Strategy
|
|
102
102
|
- Identical to Forge tier extraction
|
|
103
|
-
- QMD enrichment happens in the next step (
|
|
103
|
+
- QMD enrichment happens in the next step (enrich)
|
|
104
104
|
- Extraction results carry forward unchanged
|
|
105
105
|
|
|
106
106
|
### Confidence
|
|
107
107
|
- Extraction: same as Forge (T1)
|
|
108
|
-
- Enrichment annotations added in step
|
|
108
|
+
- Enrichment annotations added in step 4: T2
|
|
109
109
|
|
|
110
110
|
---
|
|
111
111
|
|
|
@@ -113,7 +113,7 @@ Same extraction as Forge tier. Deep tier adds enrichment in step-04, not extract
|
|
|
113
113
|
|
|
114
114
|
When AST tools are available (Forge/Deep tier), follow this deterministic protocol to prevent output overflow on large codebases.
|
|
115
115
|
|
|
116
|
-
**"Files in scope"** = files remaining after applying `include_patterns` and `exclude_patterns` from the brief, filtered by the target language extension. This is NOT the total repository file count from step
|
|
116
|
+
**"Files in scope"** = files remaining after applying `include_patterns` and `exclude_patterns` from the brief, filtered by the target language extension. This is NOT the total repository file count from step 1's tree listing. Use the filtered count from step 3 section 2 as the decision tree input.
|
|
117
117
|
|
|
118
118
|
### Decision Tree
|
|
119
119
|
|
|
@@ -320,7 +320,7 @@ constraints:
|
|
|
320
320
|
|
|
321
321
|
### Component Library YAML Rule Recipes
|
|
322
322
|
|
|
323
|
-
These patterns are used by `
|
|
323
|
+
These patterns are used by `component-extraction.md` when `scope.type: "component-library"`. They prioritize Props interfaces and PascalCase component exports.
|
|
324
324
|
|
|
325
325
|
**React/TypeScript — Props interfaces (primary API contracts):**
|
|
326
326
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'report.md'
|
|
3
3
|
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
|
|
@@ -10,6 +10,8 @@ atomicWriteProbeOrder:
|
|
|
10
10
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
11
11
|
---
|
|
12
12
|
|
|
13
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
14
|
+
|
|
13
15
|
# Step 7: Generate Artifacts
|
|
14
16
|
|
|
15
17
|
## STEP GOAL:
|
|
@@ -24,8 +26,6 @@ To write all compiled content to disk — 4 deliverable files to `{skill_package
|
|
|
24
26
|
|
|
25
27
|
## MANDATORY SEQUENCE
|
|
26
28
|
|
|
27
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
28
|
-
|
|
29
29
|
### 1. Create Directory Structure
|
|
30
30
|
|
|
31
31
|
Resolve `{version}` from the skill brief's `version` field. Create the following directories:
|
|
@@ -71,7 +71,7 @@ Write these 4 files from the compiled content:
|
|
|
71
71
|
- One file per detected asset, copied from source with content preserved
|
|
72
72
|
- Only created when `assets_inventory` is non-empty
|
|
73
73
|
|
|
74
|
-
**Note on `file_type: "doc"` entries** (promoted authoritative docs from step
|
|
74
|
+
**Note on `file_type: "doc"` entries** (promoted authoritative docs from step 3 §2a):
|
|
75
75
|
|
|
76
76
|
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
77
|
|
|
@@ -87,7 +87,7 @@ Write these 3 files from the compiled content:
|
|
|
87
87
|
|
|
88
88
|
**File 7:** `{forge_version}/extraction-rules.yaml`
|
|
89
89
|
- Language and ast-grep schema used for this extraction (for reproducibility)
|
|
90
|
-
- Note: This file is generated here from extraction data collected during steps 3-4, not assembled in step
|
|
90
|
+
- Note: This file is generated here from extraction data collected during steps 3-4, not assembled in step 5
|
|
91
91
|
|
|
92
92
|
### 4. Create Active Symlink (atomic flip)
|
|
93
93
|
|
|
@@ -108,16 +108,16 @@ The helper returns non-zero (exit 2) if `{skill_group}/active` already exists as
|
|
|
108
108
|
After all files are written, verify:
|
|
109
109
|
- All 4 deliverable artifact types exist (SKILL.md, context-snippet.md, metadata.json, **and** either at least one file in `references/` **or** `references/` is empty AND Tier-2 content is inline in SKILL.md — see "Empty `references/` exception" below), all 3 workspace artifacts exist (provenance-map.json, evidence-report.md, extraction-rules.yaml), plus scripts/ and assets/ files when inventories are non-empty
|
|
110
110
|
- The `active` symlink at `{skill_group}/active` resolves to `{version}`
|
|
111
|
-
- Store `ref_count` = count of files written to `references/` for use in step
|
|
111
|
+
- Store `ref_count` = count of files written to `references/` for use in step 8 report
|
|
112
112
|
- List each file with its path and size
|
|
113
113
|
|
|
114
|
-
**Empty `references/` exception (Tier-2 inline):** `ref_count == 0` is a valid completion state when step
|
|
114
|
+
**Empty `references/` exception (Tier-2 inline):** `ref_count == 0` is a valid completion state when step 6 kept Tier-2 content inline in SKILL.md — e.g., the body was already under the size limit, or `skill-check` was unavailable and the manual fallback (step 6 §3) skipped the split. In that case, append a single line to `{forge_version}/evidence-report.md` recording the inline state so downstream tooling and audits can distinguish "inline by design" from "split-body skipped due to error":
|
|
115
115
|
|
|
116
116
|
```
|
|
117
|
-
ref_count: 0 # Tier-2 kept inline in SKILL.md (no split performed in step
|
|
117
|
+
ref_count: 0 # Tier-2 kept inline in SKILL.md (no split performed in step 6)
|
|
118
118
|
```
|
|
119
119
|
|
|
120
|
-
When `ref_count > 0` is expected (because step
|
|
120
|
+
When `ref_count > 0` is expected (because step 6 ran a split) but no files were written, halt with: "Split-body produced zero reference files. Investigate step 6 output before retrying — empty `references/` after a split is never a valid state."
|
|
121
121
|
|
|
122
122
|
**If any write failed:**
|
|
123
123
|
Halt with: "Artifact generation failed: could not write `{file_path}`. Check permissions and disk space."
|
|
@@ -159,7 +159,7 @@ qmd embed --collection {name}-extraction # generates vector embeddings for sema
|
|
|
159
159
|
|
|
160
160
|
**Registry update:**
|
|
161
161
|
|
|
162
|
-
Read `{forgeTierConfig}` and update the `qmd_collections` array **under an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock`** (see step
|
|
162
|
+
Read `{forgeTierConfig}` and update the `qmd_collections` array **under an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock`** (see step 3b §4 for the full pattern — acquire lock → read → modify → atomic write via `skf-atomic-write.py write` → release). If `flock` is unavailable, fall back to read-CAS-by-mtime.
|
|
163
163
|
|
|
164
164
|
If an entry with `name: "{name}-extraction"` already exists, replace it. Otherwise, append:
|
|
165
165
|
|
|
@@ -187,7 +187,7 @@ Ensure the source path used for extraction is indexed by ccc and registered in t
|
|
|
187
187
|
|
|
188
188
|
**Index verification:**
|
|
189
189
|
|
|
190
|
-
Dispatch to ccc CLI (`ccc index {source_root}`) or ccc MCP tool — `ccc_bridge.ensure_index` is a conceptual interface, not a callable function. This is a no-op if the source was already indexed during setup or step
|
|
190
|
+
Dispatch to ccc CLI (`ccc index {source_root}`) or ccc MCP tool — `ccc_bridge.ensure_index` is a conceptual interface, not a callable function. This is a no-op if the source was already indexed during setup or step 2b.
|
|
191
191
|
|
|
192
192
|
**Registry update:**
|
|
193
193
|
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
nextStepFile: 'shared/health-check.md'
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
9
|
+
|
|
8
10
|
# Step 9: Workflow Health Check
|
|
9
11
|
|
|
10
12
|
## STEP GOAL:
|
|
@@ -13,9 +15,9 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
|
|
|
13
15
|
|
|
14
16
|
## Rules
|
|
15
17
|
|
|
16
|
-
- No user-facing reports, file writes, or result contracts in this step — those belong in step
|
|
18
|
+
- No user-facing reports, file writes, or result contracts in this step — those belong in step 8
|
|
17
19
|
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
18
|
-
- In batch mode, this step is only reached after the final brief — step
|
|
20
|
+
- In batch mode, this step is only reached after the final brief — step 8 loops back to load-brief for remaining briefs and skips chaining here
|
|
19
21
|
- Do not attempt any other action between loading this step and executing `{nextStepFile}`
|
|
20
22
|
|
|
21
23
|
## MANDATORY SEQUENCE
|
|
@@ -1,9 +1,19 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'ecosystem-check.md'
|
|
3
3
|
forgeTierFile: '{sidecar_path}/forge-tier.yaml'
|
|
4
4
|
preferencesFile: '{sidecar_path}/preferences.yaml'
|
|
5
|
+
# Resolve `{validateBriefSchemaHelper}` to the first existing path; HALT if
|
|
6
|
+
# neither candidate exists. §3 relies on the helper for deterministic
|
|
7
|
+
# schema-conformance checks (required fields, regex patterns, enum
|
|
8
|
+
# membership, docs-only conditional rules) so this stage does not re-run
|
|
9
|
+
# those checks in prose.
|
|
10
|
+
validateBriefSchemaProbeOrder:
|
|
11
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-brief-schema.py'
|
|
12
|
+
- '{project-root}/src/shared/scripts/skf-validate-brief-schema.py'
|
|
5
13
|
---
|
|
6
14
|
|
|
15
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
16
|
+
|
|
7
17
|
# Step 1: Load Brief
|
|
8
18
|
|
|
9
19
|
## STEP GOAL:
|
|
@@ -17,8 +27,6 @@ To load and validate the skill-brief.yaml compilation config, resolve the source
|
|
|
17
27
|
|
|
18
28
|
## MANDATORY SEQUENCE
|
|
19
29
|
|
|
20
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
21
|
-
|
|
22
30
|
### 1. Load Forge Tier
|
|
23
31
|
|
|
24
32
|
Load `{forgeTierFile}` completely.
|
|
@@ -30,14 +38,14 @@ Halt with: "Forge halted: No forge configuration found. Run [SF] Setup Forge fir
|
|
|
30
38
|
Extract and report:
|
|
31
39
|
- `tier`: Quick, Forge, Forge+, or Deep
|
|
32
40
|
- `tools`: which tools are available (gh, ast-grep, ccc, qmd)
|
|
33
|
-
- `ccc_index`: ccc index state (status, indexed_path, last_indexed) — needed by step
|
|
41
|
+
- `ccc_index`: ccc index state (status, indexed_path, last_indexed) — needed by step 2b
|
|
34
42
|
|
|
35
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.
|
|
36
44
|
|
|
37
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:
|
|
38
46
|
|
|
39
|
-
- Valid override applied: `{step: "
|
|
40
|
-
- Invalid override rejected: `{step: "
|
|
47
|
+
- Valid override applied: `{step: "load-brief", gate: "tier-override", decision: "apply", value: "{tier_override}", rationale: "explicit preferences.yaml tier_override", timestamp: {ISO}}`
|
|
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}}`
|
|
41
49
|
|
|
42
50
|
Step-05 §7 reads `headless_decisions[]` and emits an "Auto-Decisions" section into `evidence-report.md` so reviewers can audit every silent choice the workflow made.
|
|
43
51
|
|
|
@@ -53,7 +61,7 @@ Step-05 §7 reads `headless_decisions[]` and emits an "Auto-Decisions" section i
|
|
|
53
61
|
- If `batch_active: true`: validate the checkpoint before trusting it. Both conditions below MUST hold:
|
|
54
62
|
1. `0 <= current_index < len(brief_list)` — the index points inside the recorded list.
|
|
55
63
|
2. `os.path.exists(brief_list[current_index])` — the brief file is still on disk.
|
|
56
|
-
If both hold, load the brief at `brief_list[current_index]` (resuming a batch loop from step
|
|
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.
|
|
57
65
|
- If no checkpoint exists or `batch_active` is false: search specified directory for all `skill-brief.yaml` files, list discovered briefs with skill names, store list for batch loop processing, and load the FIRST brief
|
|
58
66
|
|
|
59
67
|
**If no brief found:**
|
|
@@ -61,35 +69,35 @@ Halt with: "No skill brief found. Run [BS] Brief Skill to create one, or use [QS
|
|
|
61
69
|
|
|
62
70
|
### 3. Validate Brief Structure
|
|
63
71
|
|
|
64
|
-
|
|
72
|
+
Run the deterministic schema validator — it checks required fields, regex patterns (`name`, `version`), enum membership (`source_type`, `source_authority`, `forge_tier`, `scope.type`), type correctness, the docs-only conditional rule (`doc_urls` ≥ 1 when `source_type == "docs-only"`), and the version-non-empty-or-whitespace rule:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
uv run {validateBriefSchemaHelper} <path-to-skill-brief.yaml>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The helper emits:
|
|
65
79
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"valid": <bool>,
|
|
83
|
+
"errors": [{"field": "...", "message": "Brief validation failed: ..."}, ...],
|
|
84
|
+
"warnings": [{"field": "...", "message": "..."}, ...],
|
|
85
|
+
"halt_reason": "brief-missing" | "brief-malformed" | "brief-invalid" | null,
|
|
86
|
+
"brief": { ...parsed YAML when loadable... }
|
|
87
|
+
}
|
|
88
|
+
```
|
|
72
89
|
|
|
73
|
-
**
|
|
74
|
-
- `source_type` — `"source"` (default) or `"docs-only"` (external documentation only)
|
|
75
|
-
- `doc_urls` — array of `{url, label}` documentation URLs (required when `source_type: "docs-only"`)
|
|
76
|
-
- `source_branch` — branch to use (default: main/master)
|
|
77
|
-
- `source_authority` — official/community/internal (default: community; forced to `community` for docs-only)
|
|
78
|
-
- `target_version` — specific version to compile against (triggers **explicit** tag resolution for remote repos; see source-resolution-protocols.md). When absent, the workflow falls back to **implicit** tag resolution from `brief.version` for remote sources — see below.
|
|
79
|
-
- `include_patterns` — file glob patterns to include
|
|
80
|
-
- `exclude_patterns` — file glob patterns to exclude
|
|
81
|
-
- `description` — human description of the skill
|
|
82
|
-
- `scripts_intent` — `"none"` to skip scripts detection, omit for default auto-detection
|
|
83
|
-
- `assets_intent` — `"none"` to skip assets detection, omit for default auto-detection
|
|
90
|
+
**If `valid` is false:** HALT and display the first error's `message` field verbatim — the helper already formats messages in the "Brief validation failed: ..." form the user expects. For halt-reasons:
|
|
84
91
|
|
|
85
|
-
|
|
92
|
+
- `brief-missing` — the brief path doesn't exist. Display the helper's message (it includes the `Run [BS] Brief Skill` redirect).
|
|
93
|
+
- `brief-malformed` — the YAML failed to parse. Display the helper's message.
|
|
94
|
+
- `brief-invalid` — schema or conditional-rule violation. Display the first `errors[].message`. Multiple errors may appear; the user typically fixes one source and re-runs.
|
|
86
95
|
|
|
87
|
-
**If
|
|
88
|
-
Halt with specific error: "Brief validation failed: missing required field `{field}`. Update your skill-brief.yaml and re-run."
|
|
96
|
+
**If `valid` is true:** continue with `brief` (the parsed object) for downstream sections. Surface any `warnings[]` to the user but do not halt.
|
|
89
97
|
|
|
90
|
-
**
|
|
98
|
+
**Field reference (for human readers):**
|
|
91
99
|
|
|
92
|
-
|
|
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 NOT restate the rules here.
|
|
93
101
|
|
|
94
102
|
### 4. Resolve Source Code Location
|
|
95
103
|
|
|
@@ -98,8 +106,8 @@ Halt with specific error: "Brief validation failed: missing required field `{fie
|
|
|
98
106
|
**If source_repo is a GitHub URL or owner/repo format:**
|
|
99
107
|
- Verify repository exists via `gh_bridge.list_tree(owner, repo, branch)` — **Tool resolution:** `gh api repos/{owner}/{repo}/git/trees/{branch}?recursive=1` or direct file listing if local; see `knowledge/tool-resolution.md`
|
|
100
108
|
- If branch not specified, detect default branch
|
|
101
|
-
- Store resolved: owner, repo, branch, file tree — note: `source_root` for remote repos is initially set to the remote URL (for detection and API access purposes) and then updated to the local workspace/clone path during step
|
|
102
|
-
- **Version-to-tag pinning intent:** If `brief.target_version` is absent but `brief.version` is present, record the intent to apply **implicit tag resolution** from `brief.version` when step
|
|
109
|
+
- Store resolved: owner, repo, branch, file tree — note: `source_root` for remote repos is initially set to the remote URL (for detection and API access purposes) and then updated to the local workspace/clone path during step 3 source resolution
|
|
110
|
+
- **Version-to-tag pinning intent:** If `brief.target_version` is absent but `brief.version` is present, record the intent to apply **implicit tag resolution** from `brief.version` when step 3 resolves the source. Do not resolve the tag here — tag resolution runs in step 3 alongside the clone. This step only notes the pinning intent so step 3 knows to attempt it. See `references/source-resolution-protocols.md` → "Implicit Tag Resolution".
|
|
103
111
|
|
|
104
112
|
**If source_repo is a local path:**
|
|
105
113
|
- Verify path exists and contains source files
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'health-check.md'
|
|
3
3
|
# Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
|
|
4
4
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
5
|
# path wins. HALT if neither resolves.
|
|
@@ -8,6 +8,8 @@ atomicWriteProbeOrder:
|
|
|
8
8
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
9
9
|
---
|
|
10
10
|
|
|
11
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
12
|
+
|
|
11
13
|
# Step 8: Report
|
|
12
14
|
|
|
13
15
|
## STEP GOAL:
|
|
@@ -22,8 +24,6 @@ To display the final compilation summary — skill name, version, source, export
|
|
|
22
24
|
|
|
23
25
|
## MANDATORY SEQUENCE
|
|
24
26
|
|
|
25
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
26
|
-
|
|
27
27
|
### 1. Display Forge Completion Banner
|
|
28
28
|
|
|
29
29
|
"**Skill forged: {name} v{version} — {export_count} functions, {primary_confidence} confidence.**"
|
|
@@ -107,9 +107,9 @@ completed: [{list of completed skill names}]
|
|
|
107
107
|
last_updated: {ISO timestamp}
|
|
108
108
|
```
|
|
109
109
|
|
|
110
|
-
**Before writing:** validate the same two invariants that step
|
|
110
|
+
**Before writing:** validate the same two invariants that step 1 re-checks on resume — `0 <= current_index < len(brief_list)` AND `os.path.exists(brief_list[current_index])`. If either fails (e.g., the next brief file was deleted mid-batch, or arithmetic pushed the index off the end), set `batch_active: false` and write `batch_halt_reason: "invalid checkpoint at write time — index or file missing"` instead of the active record. The next run will re-discover rather than resume a broken index.
|
|
111
111
|
|
|
112
|
-
Then load and execute `
|
|
112
|
+
Then load and execute `references/load-brief.md` for the next brief. Step-01 detects an active batch via `batch-state.yaml` and loads the brief at `current_index` only after re-validating the same invariants (belt and braces — the checkpoint may have been edited between runs).
|
|
113
113
|
|
|
114
114
|
**If all batch briefs complete:**
|
|
115
115
|
|
|
@@ -135,11 +135,11 @@ End workflow. No further steps.
|
|
|
135
135
|
|
|
136
136
|
ONLY WHEN the compilation report, warnings (if any), recommended next steps, and result contract have been handled will you then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step — do not stop here even though the report reads as final.
|
|
137
137
|
|
|
138
|
-
**If batch mode with remaining briefs:** Skip the health-check chain — load and execute `
|
|
138
|
+
**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.
|
|
139
139
|
|
|
140
140
|
## CRITICAL STEP COMPLETION NOTE
|
|
141
141
|
|
|
142
|
-
This step chains to the local health-check step (`{nextStepFile}`), which in turn delegates to `shared/health-check.md` (unless batch mode loops back to step
|
|
142
|
+
This step chains to the local health-check step (`{nextStepFile}`), which in turn delegates to `shared/health-check.md` (unless batch mode loops back to step 1). After the health check completes, the create-skill workflow is fully done.
|
|
143
143
|
|
|
144
|
-
For batch mode: load and execute `
|
|
144
|
+
For batch mode: load and execute `references/load-brief.md` for remaining briefs via sidecar checkpoint. Health check runs only after the last brief.
|
|
145
145
|
|