bmad-module-skill-forge 1.4.1 → 1.5.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/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 +147 -16
- 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-manifest-ops.py +22 -6
- 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} +48 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +32 -9
- 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} +16 -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} +63 -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} +35 -17
- package/src/skf-brief-skill/SKILL.md +49 -19
- 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} +27 -15
- 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} +35 -29
- 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 +2 -2
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +27 -20
- 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} +29 -16
- 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 +10 -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} +48 -28
- 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} +37 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +32 -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} +44 -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 +79 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +23 -11
- 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} +37 -73
- 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} +13 -9
- 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 +170 -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} +18 -14
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +27 -42
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +13 -9
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +14 -10
- 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,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
|
|
|
@@ -43,9 +43,9 @@ When `brief.target_version` is absent but `brief.version` is present AND `source
|
|
|
43
43
|
3. **Resolution outcomes:**
|
|
44
44
|
- **Single match:** Store the matched tag as `source_ref`. Use it as `{branch}` in all subsequent clone/API commands. Do not warn — this is the expected path.
|
|
45
45
|
- **Multiple matches:** Present the matching tags to the user — "Multiple tags match `brief.version` ({brief.version}): {list}. Which one should I use, or fall back to HEAD?" Wait for selection.
|
|
46
|
-
- **Zero matches:** ⚠️ Warn: "No git tag found matching `brief.version` ({brief.version}). Falling back to default branch — **extracted code may not match the declared version.** If you intended to pin a specific version, set `target_version` explicitly in the brief." Set `source_ref` to `HEAD` and proceed with default branch. Append `tag_resolution: {status: "fallback-head", requested: "{brief.version}", reason: "no-matching-tag"}` to the in-context evidence-report payload so step
|
|
46
|
+
- **Zero matches:** ⚠️ Warn: "No git tag found matching `brief.version` ({brief.version}). Falling back to default branch — **extracted code may not match the declared version.** If you intended to pin a specific version, set `target_version` explicitly in the brief." Set `source_ref` to `HEAD` and proceed with default branch. Append `tag_resolution: {status: "fallback-head", requested: "{brief.version}", reason: "no-matching-tag"}` to the in-context evidence-report payload so step 5 §7 surfaces the fallback in the evidence report. This turns the warning into a persistent audit trail a reviewer can grep later, not just a one-shot stderr line.
|
|
47
47
|
|
|
48
|
-
4. **Do not halt on zero matches.** Unlike the explicit path, implicit resolution never blocks compilation — `brief.version` is an auto-populated hint, and some repositories simply do not tag releases. The warning is sufficient notice; the evidence report in step
|
|
48
|
+
4. **Do not halt on zero matches.** Unlike the explicit path, implicit resolution never blocks compilation — `brief.version` is an auto-populated hint, and some repositories simply do not tag releases. The warning is sufficient notice; the evidence report in step 8 will surface the HEAD fallback for reviewers.
|
|
49
49
|
|
|
50
50
|
5. **Store `source_ref`** in context exactly as in the explicit path. It flows through to metadata.json and provenance-map.json so downstream workflows (update-skill, audit-skill) can re-clone from the same ref.
|
|
51
51
|
|
|
@@ -65,7 +65,7 @@ Implicit resolution via `brief.version` is **not applied to local sources** —
|
|
|
65
65
|
|
|
66
66
|
## Remote Source Resolution
|
|
67
67
|
|
|
68
|
-
**Note:** Quick-tier remote sources do not use the workspace/clone protocol described below. Quick tier accesses remote files via the `gh_bridge.read_file` path described in step
|
|
68
|
+
**Note:** Quick-tier remote sources do not use the workspace/clone protocol described below. Quick tier accesses remote files via the `gh_bridge.read_file` path described in step 3 section 4.
|
|
69
69
|
|
|
70
70
|
If `source_repo` is a local path: proceed with the tier-appropriate strategy as normal.
|
|
71
71
|
|
|
@@ -84,7 +84,7 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
|
|
|
84
84
|
|
|
85
85
|
3. **Workspace check — resolve the source locally:**
|
|
86
86
|
|
|
87
|
-
**Concurrency guard:** all of the operations below (fetch, checkout, rev-parse, and the extraction read that follows in step
|
|
87
|
+
**Concurrency guard:** all of the operations below (fetch, checkout, rev-parse, and the extraction read that follows in step 3) must be wrapped in an exclusive `flock` on `{workspace_repo_path}/.skf-workspace.lock`. Acquire the lock before the workspace-hit check, hold it across fetch + checkout + rev-parse, AND keep holding it through the extraction-time read of the working tree. Two concurrent batch runs that target the same workspace clone but different `source_ref` values would otherwise race — one would `checkout` while the other was reading files mid-extraction, corrupting the inventory. The lock makes the per-workspace-repo unit of work serial. Use `flock -x {lockfile} -c "..."` or `fcntl.flock(LOCK_EX)`. If `flock` is unavailable, log a warning ("Concurrency guard unavailable — concurrent forges against the same workspace repo may produce inconsistent extraction inventories") and proceed.
|
|
88
88
|
|
|
89
89
|
**If `{workspace_repo_path}/.git/` exists (workspace hit):**
|
|
90
90
|
|
|
@@ -217,7 +217,7 @@ Also store `source_ref` in context (from tag resolution above, or `HEAD` if no t
|
|
|
217
217
|
|
|
218
218
|
**If `source_type: "docs-only"`:** skip this section — no source files exist to reconcile.
|
|
219
219
|
|
|
220
|
-
After the source path is accessible (local path from step
|
|
220
|
+
After the source path is accessible (local path from step 1, or workspace/ephemeral clone from above), check whether the source contains a version identifier and reconcile it with `brief.version`. Look for the first matching version file in the resolved source path:
|
|
221
221
|
|
|
222
222
|
- Python: `pyproject.toml` (`[project] version`), `setup.py` (`version=`), `__version__` in `__init__.py`
|
|
223
223
|
- JavaScript/TypeScript: `package.json` (`"version"`). **Monorepo resolution:** When multiple `package.json` files exist (workspace root + packages), resolve version using this priority:
|
|
@@ -232,7 +232,7 @@ After the source path is accessible (local path from step-01, or workspace/ephem
|
|
|
232
232
|
|
|
233
233
|
⚠️ Warn the user: "Brief version ({brief.version}) differs from source version ({source_version}). Using source version ({source_version})."
|
|
234
234
|
|
|
235
|
-
Update the working version in context to the source version. Record the mismatch in context for the evidence report (step
|
|
235
|
+
Update the working version in context to the source version. Record the mismatch in context for the evidence report (step 8).
|
|
236
236
|
|
|
237
237
|
**If no version file is found or version cannot be extracted:** keep `brief.version` as-is. No warning needed.
|
|
238
238
|
|
package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md}
RENAMED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '../
|
|
2
|
+
nextStepFile: '../extract.md'
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
6
|
+
|
|
5
7
|
# Step 2b: CCC Semantic Discovery
|
|
6
8
|
|
|
7
9
|
## STEP GOAL:
|
|
8
10
|
|
|
9
|
-
If tier is Forge+ or Deep AND ccc is available, perform a semantic discovery pass over the source code to identify the most relevant files for the skill being created. Store ranked discovery results in context to pre-rank the file extraction queue in step
|
|
11
|
+
If tier is Forge+ or Deep AND ccc is available, perform a semantic discovery pass over the source code to identify the most relevant files for the skill being created. Store ranked discovery results in context to pre-rank the file extraction queue in step 3.
|
|
10
12
|
|
|
11
13
|
For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed.
|
|
12
14
|
|
|
@@ -18,8 +20,6 @@ For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed
|
|
|
18
20
|
|
|
19
21
|
## MANDATORY SEQUENCE
|
|
20
22
|
|
|
21
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
22
|
-
|
|
23
23
|
### 1. Check Tier Eligibility
|
|
24
24
|
|
|
25
25
|
**If tier is Quick or Forge:**
|
|
@@ -32,7 +32,7 @@ Check `tools.ccc` from forge-tier.yaml. If `tools.ccc` is false, set `{ccc_disco
|
|
|
32
32
|
|
|
33
33
|
If `tools.ccc` is true, check the remote source guard **before** proceeding to section 2:
|
|
34
34
|
|
|
35
|
-
**Remote source guard:** If `source_root` is a remote URL (GitHub repository — workspace clone or ephemeral clone happens in step
|
|
35
|
+
**Remote source guard:** If `source_root` is a remote URL (GitHub repository — workspace clone or ephemeral clone happens in step 3), CCC cannot operate yet. Set `{ccc_discovery: []}` and display: "CCC discovery deferred — remote source will be indexed after clone in step 3." Auto-proceed to section 5 (step completion). Step-03 will detect the deferred scenario and run CCC discovery on the resolved clone (workspace or ephemeral) before AST extraction begins.
|
|
36
36
|
|
|
37
37
|
If `source_root` is a local path, continue to section 2.
|
|
38
38
|
|
package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md}
RENAMED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '../
|
|
2
|
+
nextStepFile: '../enrich.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 3c: Fetch Remote Documentation
|
|
12
14
|
|
|
13
15
|
## STEP GOAL:
|
|
@@ -23,13 +25,11 @@ Fetch remote documentation from brief-specified URLs using whatever web fetching
|
|
|
23
25
|
|
|
24
26
|
## MANDATORY SEQUENCE
|
|
25
27
|
|
|
26
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
27
|
-
|
|
28
28
|
### 1. Check Eligibility
|
|
29
29
|
|
|
30
30
|
Evaluate the following conditions. **If the condition fails, skip silently to section 7 (auto-proceed) with no output:**
|
|
31
31
|
|
|
32
|
-
1. **`doc_urls` is present in the brief data:** Check that `doc_urls` contains at least one URL entry from step
|
|
32
|
+
1. **`doc_urls` is present in the brief data:** Check that `doc_urls` contains at least one URL entry from step 1 context. If `doc_urls` is absent or empty, skip silently.
|
|
33
33
|
|
|
34
34
|
No tier gate — if `doc_urls` are present, this step runs at Quick, Forge, and Deep tiers alike.
|
|
35
35
|
|
|
@@ -84,12 +84,28 @@ If neither trigger fires, keep the page content as-is and do NOT trigger subpage
|
|
|
84
84
|
|
|
85
85
|
2. **Filter discovered URLs by relevance and origin:** Restrict candidates to the same **registrable domain** as the root URL — strip the URL down to its eTLD+1 (e.g., for root `https://docs.example.com/intro`, accept any subdomain of `example.com` such as `api.example.com` or `docs.example.com`, but reject `example.org` or `cdn.partner.io`). Cross-origin links must be discarded before any fetch. The same-registrable-domain rule prevents Mintlify/Docusaurus link clouds from pulling in tracking pixels, doc-site CDNs, or third-party embeds as if they were canonical docs. From the surviving same-domain candidates, select the most relevant pages by searching for API-related terms in the URL path or title (e.g., `api`, `reference`, `quickstart`, `setup`, `config`, `getting-started`, `guide`, `sdk`, `methods`, `functions`). Exclude pages that are clearly non-API content (e.g., `blog`, `changelog`, `pricing`, `about`, `careers`).
|
|
86
86
|
|
|
87
|
-
3. **Fetch top subpages:** Fetch up to **10** of the most relevant subpages.
|
|
87
|
+
3. **Fetch top subpages (in parallel):** Fetch up to **10** of the most relevant subpages **concurrently** — subpage fetches are independent and network-bound, so wall-clock benefits substantially from parallel execution. Bound concurrency to **4 in flight** at a time to stay polite to documentation hosts (Mintlify/Docusaurus typically allow more, but conservatism here protects against unrecognized rate limits).
|
|
88
|
+
|
|
89
|
+
The parallel pattern depends on the fetch tool:
|
|
90
|
+
|
|
91
|
+
- **LLM-driven tools** (Firecrawl `firecrawl_scrape`, `WebFetch`, MCP fetch, browser tools): issue up to 4 tool calls **in a single message**. The agent runtime executes parallel tool calls concurrently; collect results from the batch before issuing the next set of up to 4. Repeat until all up-to-10 subpages have been attempted or rate limiting halts the batch.
|
|
92
|
+
- **Bash-driven tools** (`curl`, `wget`): use `xargs -P 4 -n 1` to fan out from a newline-separated subpage list. Example:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
printf '%s\n' "${subpages[@]}" | xargs -P 4 -n 1 -I {} bash -c '
|
|
96
|
+
url="{}"
|
|
97
|
+
safe=$(echo -n "$url" | sha256sum | cut -c1-12)
|
|
98
|
+
curl -sSL --max-time 30 "$url" > "{staging}/subpage-$safe.md" \
|
|
99
|
+
|| echo "fetch failed: $url" > "{staging}/subpage-$safe.md"
|
|
100
|
+
'
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For each subpage (regardless of tool):
|
|
88
104
|
- Use the same web fetching tool as the root URL
|
|
89
105
|
- Store with the subpage URL as provenance: `[EXT:{subpage-url}]`
|
|
90
|
-
- If a subpage fetch fails, skip it and continue
|
|
106
|
+
- If a subpage fetch fails, skip it and continue with the rest of the batch — do not halt the whole stage
|
|
91
107
|
|
|
92
|
-
4. **Rate limiting:** If rate limiting (HTTP 429) is encountered during subpage fetching, stop discovery for this root URL. Keep results collected so far. Log: "Subpage discovery stopped due to rate limiting."
|
|
108
|
+
4. **Rate limiting:** If rate limiting (HTTP 429) is encountered during subpage fetching, stop discovery for this root URL. Keep results collected so far. Log: "Subpage discovery stopped due to rate limiting." For the parallel-tool-call pattern, drop any not-yet-issued tool calls from subsequent batches; for the `xargs` pattern, interrupt the pipeline (set `--max-procs 0` is **not** a graceful stop — the simplest stop is to kill the xargs PID and let in-flight writers complete naturally).
|
|
93
109
|
|
|
94
110
|
**If ALL URLs fail (including any subpage fetches):** Log warning: "No documentation could be fetched. Proceeding without T3 content." Skip to section 7 (auto-proceed).
|
|
95
111
|
|
|
@@ -110,8 +126,8 @@ Parse the successfully fetched markdown for:
|
|
|
110
126
|
|
|
111
127
|
**Mode determines merge behavior:**
|
|
112
128
|
|
|
113
|
-
- **`source_type: "docs-only"`** — The doc-fetch inventory IS the extraction inventory. It replaces the empty inventory from step
|
|
114
|
-
- **`source_type: "source"` (supplemental mode)** — Merge T3 items into the existing extraction inventory from step
|
|
129
|
+
- **`source_type: "docs-only"`** — The doc-fetch inventory IS the extraction inventory. It replaces the empty inventory from step 3, since there was no source code to extract from.
|
|
130
|
+
- **`source_type: "source"` (supplemental mode)** — Merge T3 items into the existing extraction inventory from step 3.
|
|
115
131
|
|
|
116
132
|
**Conflict rule:** T3 items NEVER override existing T1, T1-low, or T2 items for the same export. When an export already has a higher-confidence entry, the T3 item is discarded. T3 has the lowest priority.
|
|
117
133
|
|
|
@@ -131,7 +147,7 @@ Parse the successfully fetched markdown for:
|
|
|
131
147
|
1. Write fetched markdown files to a staging directory: `_bmad-output/{skill-name}-docs/`
|
|
132
148
|
2. Index into QMD with atomic replace + rollback: if a `{skill-name}-docs` collection already exists, run `qmd collection remove {skill-name}-docs` first, then `qmd collection add {project-root}/_bmad-output/{skill-name}-docs/ --name {skill-name}-docs --mask "*.md"`. **If `qmd collection add` fails after a successful `remove`:** remove any matching `{skill-name}-docs` entry from `forge-tier.yaml` → `qmd_collections[]` to keep the registry consistent with QMD's actual state, warn in evidence-report, and skip the embed — docs enrichment degrades gracefully.
|
|
133
149
|
3. Generate embeddings scoped to this collection (only if step 2 `add` succeeded): `qmd embed --collection {skill-name}-docs` (required for semantic `type:'vec'` and HyDE `type:'hyde'` sub-queries within the QMD `query` tool). If the installed `qmd` CLI does not accept `--collection`, gate the embed behind a freshness check: skip re-embedding if the existing `{skill-name}-docs` registry entry is within 24 hours, and log the skip in the evidence report to prevent unbounded batch-mode re-embedding.
|
|
134
|
-
4. Register in forge-tier.yaml `qmd_collections` array — **acquire an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock` for the read-modify-write** (see the locking pattern documented in step
|
|
150
|
+
4. Register in forge-tier.yaml `qmd_collections` array — **acquire an exclusive `flock` on `{sidecar_path}/forge-tier.yaml.lock` for the read-modify-write** (see the locking pattern documented in step 3b §4). Write via `python3 {atomicWriteHelper} write --target {sidecar_path}/forge-tier.yaml`. If `flock` is unavailable, fall back to read-CAS-by-mtime (capture `st_mtime` before, re-check after; refuse to clobber if a concurrent run wrote in between).
|
|
135
151
|
|
|
136
152
|
```yaml
|
|
137
153
|
- name: "{skill-name}-docs"
|
|
@@ -190,7 +206,7 @@ ONLY WHEN documentation is fetched and T3 items are merged into the extraction i
|
|
|
190
206
|
- Existing T1/T1-low/T2 items never overridden by T3 data
|
|
191
207
|
- Docs-only mode: doc-fetch inventory correctly replaces empty extraction inventory
|
|
192
208
|
- Supplemental mode: T3 items merged into existing inventory respecting conflict rule
|
|
193
|
-
- Auto-proceeded to step
|
|
209
|
+
- Auto-proceeded to step 4
|
|
194
210
|
|
|
195
211
|
### SYSTEM FAILURE:
|
|
196
212
|
|
|
@@ -199,6 +215,6 @@ ONLY WHEN documentation is fetched and T3 items are merged into the extraction i
|
|
|
199
215
|
- Overriding existing higher-confidence extractions (T1, T1-low, T2) with T3 data
|
|
200
216
|
- Hardcoding a specific fetching tool instead of being tool-agnostic
|
|
201
217
|
- Hallucinating API details not found in the fetched content
|
|
202
|
-
- Beginning compilation in this step (that is step
|
|
218
|
+
- Beginning compilation in this step (that is step 5)
|
|
203
219
|
|
|
204
220
|
**Master Rule:** Documentation fetching is best-effort T3 enrichment. Fetch what you can, cite everything as `[EXT:{url}]`, never override higher-confidence data, and move on. Failures degrade gracefully — they never block the skill compilation pipeline.
|