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,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'write-config.md'
|
|
3
3
|
# Resolve `{mergeCccExclusionsHelper}` by probing `{mergeCccExclusionsProbeOrder}`
|
|
4
4
|
# in order (installed SKF module path first, src/ dev-checkout fallback); first
|
|
5
5
|
# existing path wins. HALT if neither resolves — the script owns config-value
|
|
@@ -16,7 +16,7 @@ mergeCccExclusionsProbeOrder:
|
|
|
16
16
|
|
|
17
17
|
## STEP GOAL:
|
|
18
18
|
|
|
19
|
-
If ccc is available (`{ccc: true}` from step
|
|
19
|
+
If ccc is available (`{ccc: true}` from step 1), invoke `{mergeCccExclusionsHelper}` to validate config-driven SKF exclusion patterns and merge them into `.cocoindex_code/settings.yml`, then verify the project's ccc index exists and create or refresh it if needed. Store index state and exclusion-merge results in context for step 2 to write into forge-tier.yaml and for step 4 to surface in the JSON envelope.
|
|
20
20
|
|
|
21
21
|
For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed.
|
|
22
22
|
|
|
@@ -31,49 +31,34 @@ For Quick and Forge tiers, or when ccc is unavailable, skip silently and proceed
|
|
|
31
31
|
|
|
32
32
|
### 1. Check Eligibility
|
|
33
33
|
|
|
34
|
-
Read `{ccc}` from
|
|
34
|
+
Read `{ccc}` and `{ccc_skip_index}` from context.
|
|
35
35
|
|
|
36
36
|
**If `{ccc}` is false:** Set `{ccc_index_result: "none", ccc_indexed_path: null, ccc_last_indexed: null, ccc_exclude_patterns: [], ccc_exclusion_warnings: [], settings_yml_written: false, settings_yml_patterns_added: 0}`. Proceed directly to section 4 (Auto-Proceed) — no output, no messaging.
|
|
37
37
|
|
|
38
|
-
**If `{ccc}` is true:**
|
|
38
|
+
**If `{ccc}` is true AND `{ccc_skip_index}` is true:** Run the exclusion-merge (section 3) so settings.yml stays current, then set `{ccc_index_result: "skipped", ccc_indexed_path: null, ccc_last_indexed: null}` and proceed to section 4 — do NOT run `ccc init` or `ccc index`. The envelope's `ccc_index.status` will be `"skipped"` so pipelines that plan an out-of-band re-index can distinguish "the operator opted out" from "indexing failed".
|
|
39
39
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
Read existing forge-tier.yaml at `{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml` (if it exists from a previous run).
|
|
40
|
+
**If `{ccc}` is true AND `{ccc_skip_index}` is false:** Continue to section 2.
|
|
43
41
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
Check the `ccc_index` section:
|
|
42
|
+
### 2. Check Existing Index State
|
|
47
43
|
|
|
48
|
-
|
|
49
|
-
- Check freshness: if `ccc_index.last_indexed` is within `staleness_threshold_hours` of now → index is fresh
|
|
50
|
-
- Store `{ccc_index_result: "fresh", ccc_indexed_path: {project-root}, ccc_last_indexed: {existing timestamp}}`
|
|
51
|
-
- Set `{needs_reindex: false}` — exclusions still get merged in section 3, which may force a re-index
|
|
44
|
+
Consume prior CCC state from stage 1's detector output (`prior.previous_ccc_*` context flags) — no YAML re-parse here, the detector already read forge-tier.yaml. Use `prior.previous_ccc_staleness_threshold_hours` if set, else default 24 hours.
|
|
52
45
|
|
|
53
|
-
|
|
54
|
-
- Set `{needs_reindex: true}`
|
|
46
|
+
Decide `{needs_reindex}` and `{ccc_index_result}` from those flags:
|
|
55
47
|
|
|
56
|
-
- If `
|
|
57
|
-
|
|
48
|
+
- If `previous_ccc_indexed_path` matches `{project-root}` AND `previous_ccc_index_status` is `"fresh"` or `"created"` AND `previous_ccc_last_indexed` is within `staleness_threshold_hours` of now → index is fresh. Set `{needs_reindex: false}`, `{ccc_index_result: "fresh", ccc_indexed_path: {project-root}, ccc_last_indexed: <existing timestamp>}`. Exclusions still merge in section 3 (which may force a re-index).
|
|
49
|
+
- If path matches but the timestamp is older than threshold, or if the path doesn't match, or if any prior CCC field is null → `{needs_reindex: true}`.
|
|
58
50
|
|
|
59
51
|
### 3. Merge SKF Exclusion Patterns
|
|
60
52
|
|
|
61
53
|
SKF infrastructure and output directories must be excluded from the CCC index — they contain workflow instructions, build artifacts, and generated skills that pollute semantic search results with zero extraction value.
|
|
62
54
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
1. Substitute `{project-root}` in each value with the resolved absolute project root.
|
|
66
|
-
2. Reduce the substituted value to its last path segment (basename) — `**/skills`, `**/forge-data` are the patterns the script is designed to emit. Sub-paths under `{project-root}` (e.g. `_bmad-output/forge-data`) keep the segments below `{project-root}` (`_bmad-output/forge-data`), not the full absolute path.
|
|
67
|
-
|
|
68
|
-
Concretely: given `skills_output_folder: '{project-root}/skills'`, pass `skills`. Given `forge_data_folder: '{project-root}/_bmad-output/forge-data'`, pass `_bmad-output/forge-data`. The script's PR #248 validator rejects unresolved placeholders (`{`, `}`) and absolute paths (`/abs/...`) as a backstop, but the step is responsible for delivering values the script can interpolate cleanly — surfacing a warning and silently dropping the pattern is worse than getting the pre-processing right here.
|
|
69
|
-
|
|
70
|
-
Run the merge helper, forwarding the **resolved** config values. Invoke via `uv run` so PEP 723 inline metadata resolves the script's PyYAML dependency automatically (per `docs/getting-started.md`'s prereq list — uv exists for this exact purpose). Bare `python3` will fail on a fresh Python with `ModuleNotFoundError: No module named 'yaml'`.
|
|
55
|
+
Forward `skills_output_folder` and `forge_data_folder` from `{project-root}/_bmad/skf/config.yaml` **verbatim** — the script resolves `{project-root}/...` template strings and rejects absolute paths / placeholders / glob meta-chars internally. The step does no string surgery; that work moved into the helper. Invoke via `uv run` so PEP 723 inline metadata resolves the script's PyYAML dependency automatically (per `docs/getting-started.md`'s prereq list — uv exists for this exact purpose). Bare `python3` will fail on a fresh Python with `ModuleNotFoundError: No module named 'yaml'`.
|
|
71
56
|
|
|
72
57
|
```bash
|
|
73
58
|
uv run {mergeCccExclusionsHelper} \
|
|
74
59
|
--project-root "{project-root}" \
|
|
75
|
-
--skills-output-folder "{
|
|
76
|
-
--forge-data-folder "{
|
|
60
|
+
--skills-output-folder "{skills_output_folder}" \
|
|
61
|
+
--forge-data-folder "{forge_data_folder}"
|
|
77
62
|
```
|
|
78
63
|
|
|
79
64
|
The script (see `src/shared/scripts/skf-merge-ccc-exclusions.py` docstring for the full schema) builds the SKF exclusion list (4 always-include hardcoded patterns + 2 conditional from validated config), applies the PR #248 validation rules to reject empty / absolute / glob-meta config values with actionable warnings, and performs an idempotent set-union merge into `{project-root}/.cocoindex_code/settings.yml`. User customizations are preserved. When the file does not exist yet (first-time setup before `ccc init`) the script creates it; when nothing new needs adding the script skips the write entirely (mtime preserved).
|
|
@@ -83,8 +68,8 @@ The script (see `src/shared/scripts/skf-merge-ccc-exclusions.py` docstring for t
|
|
|
83
68
|
- `{settings_yml_existed}` ← `settings_yml_existed`
|
|
84
69
|
- `{settings_yml_written}` ← `written`
|
|
85
70
|
- `{settings_yml_patterns_added}` ← `patterns_added`
|
|
86
|
-
- `{ccc_exclude_patterns}` ←
|
|
87
|
-
- `{ccc_exclusion_warnings}` ← `warnings` (a list — step
|
|
71
|
+
- `{ccc_exclude_patterns}` ← `effective_patterns` (the script returns the final, sorted, deduplicated SKF pattern set after validation — consume verbatim; do NOT re-derive in prose).
|
|
72
|
+
- `{ccc_exclusion_warnings}` ← `warnings` (a list — step 4 folds them into the envelope's warnings array)
|
|
88
73
|
|
|
89
74
|
**If `{settings_yml_written}` is true** (new patterns merged into settings.yml): set `{needs_reindex: true}` — new exclusions require re-indexing for the index to reflect them. Display: "**CCC exclusions configured:** {patterns_added} SKF patterns applied to .cocoindex_code/settings.yml"
|
|
90
75
|
|
|
@@ -127,7 +112,7 @@ ccc index
|
|
|
127
112
|
|
|
128
113
|
**If fails:**
|
|
129
114
|
|
|
130
|
-
- Store `{ccc_index_result: "failed", ccc_indexed_path: null, ccc_last_indexed: null, ccc_indexing_failed_reason: {error}}` (the failed-reason flag flows into step
|
|
115
|
+
- Store `{ccc_index_result: "failed", ccc_indexed_path: null, ccc_last_indexed: null, ccc_indexing_failed_reason: {error}}` (the failed-reason flag flows into step 4's envelope warnings)
|
|
131
116
|
- Display: "CCC indexing failed: {error}. Extraction will use direct AST scanning — semantic pre-ranking unavailable this session."
|
|
132
117
|
- Continue — this is NOT a workflow error
|
|
133
118
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'ccc-index.md'
|
|
3
3
|
# Resolve `{detectToolsHelper}` by probing `{detectToolsProbeOrder}` in order
|
|
4
4
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
5
|
# path wins. HALT if neither resolves — the script is the source of truth for
|
|
@@ -27,17 +27,14 @@ Verify availability of the four forge tools (ast-grep, gh, qmd, ccc), read any e
|
|
|
27
27
|
|
|
28
28
|
### 1. Check for Existing Configuration (Re-run Detection)
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- If exists: store the current `tier` value as `{previous_tier}`, `tier_detected_at` as `{previous_detection_date}`, and the `tools` map as `{previous_tools}` (for the tool-set delta detection step-04 needs to surface newly-installed tools on same-tier re-runs).
|
|
33
|
-
- If not found: set `{previous_tier}` to null and `{previous_tools}` to an empty map (first run).
|
|
30
|
+
Prior state lives in two files; the detector helper (§2) reads forge-tier.yaml itself when invoked with `--prior-state-from`, so this section only handles preferences.yaml directly and the first-run preamble.
|
|
34
31
|
|
|
35
32
|
**Read existing preferences.yaml** at `{project-root}/_bmad/_memory/forger-sidecar/preferences.yaml`:
|
|
36
33
|
|
|
37
34
|
- If exists: check for `tier_override` value
|
|
38
35
|
- If not found: set `{tier_override}` to null
|
|
39
36
|
|
|
40
|
-
**First-run preamble** — when `
|
|
37
|
+
**First-run preamble** — when the prior-state read (§2 below, `prior.previous_tier`) returns null AND `{headless_mode}` is `false`, display this preamble before continuing so the user knows what is about to happen and can abort cleanly with Esc / Ctrl+C before any writes. (When `{headless_mode}` is true, skip the preamble entirely — pipelines never need it.)
|
|
41
38
|
|
|
42
39
|
"**About to set up the forge.** This workflow will:
|
|
43
40
|
|
|
@@ -53,7 +50,7 @@ Press Esc or Ctrl+C now if this isn't the right project — no files have been w
|
|
|
53
50
|
|
|
54
51
|
### 2. Run Detection Helper
|
|
55
52
|
|
|
56
|
-
Build the Bash invocation
|
|
53
|
+
Build the Bash invocation: `uv run {detectToolsHelper} --prior-state-from "{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml"`. If `{tier_override}` is non-null, append `--tier-override "{tier_override}"`. If `{require_tier}` is non-null, append `--require-tier "{require_tier}"`. Then execute. (The script's PEP 723 metadata is why `uv run` is required — bare `python3` skips dependency resolution.)
|
|
57
54
|
|
|
58
55
|
The script (see `src/shared/scripts/skf-detect-tools.py` docstring for the full `DETECT_OUTPUT_SCHEMA`) probes ast-grep / gh / qmd / ccc concurrently with two-step verification for qmd and ccc (binary-identity check + daemon-health check, including the `CocoIndex Code` identity-marker substring check that rejects PATH-shadowing aliases). It applies the 4-rule tier table, performs the tier-override sanity check (override is honored but flagged unsafe when underlying tools are missing), and evaluates `--require-tier` using a tool-prerequisite check (Deep does NOT subsume Forge+ — Deep does not require ccc). Output is one JSON document on stdout.
|
|
59
56
|
|
|
@@ -68,7 +65,7 @@ From `tools`:
|
|
|
68
65
|
- `{gh_cli}` ← `tools.gh_cli.available`
|
|
69
66
|
- `{gh_cli_version}` ← `tools.gh_cli.version`
|
|
70
67
|
- `{qmd}` ← `tools.qmd.available`
|
|
71
|
-
- `{qmd_status}` ← `tools.qmd.status` (`"absent" | "daemon_stopped" | "healthy"` — drives the climb-hint distinction in step
|
|
68
|
+
- `{qmd_status}` ← `tools.qmd.status` (`"absent" | "daemon_stopped" | "healthy"` — drives the climb-hint distinction in step 4)
|
|
72
69
|
- `{qmd_version}` ← `tools.qmd.version`
|
|
73
70
|
- `{ccc}` ← `tools.ccc.available`
|
|
74
71
|
- `{ccc_daemon}` ← `tools.ccc.daemon` (`"healthy" | "stopped" | "error" | null`)
|
|
@@ -82,15 +79,31 @@ From `tier`:
|
|
|
82
79
|
- `{tier_override_active}` ← `tier.override_applied`
|
|
83
80
|
- `{tier_override_invalid}` ← `tier.override_invalid`
|
|
84
81
|
- `{tier_override_invalid_value}` ← `tier.override_invalid_value`
|
|
85
|
-
- `{tier_override_invalid_suggestion}` ← `tier.override_invalid_suggestion` (closest valid tier name from a fuzzy match — `null` when no candidate cleared the cutoff or when override is valid; consumed by step
|
|
82
|
+
- `{tier_override_invalid_suggestion}` ← `tier.override_invalid_suggestion` (closest valid tier name from a fuzzy match — `null` when no candidate cleared the cutoff or when override is valid; consumed by step 4's invalid-override note as a "did you mean ...?" hint)
|
|
86
83
|
- `{tier_override_unsafe}` ← `tier.override_unsafe`
|
|
87
|
-
- `{tier_override_unsafe_missing}` ← `tier.override_unsafe_missing` (a list — step
|
|
84
|
+
- `{tier_override_unsafe_missing}` ← `tier.override_unsafe_missing` (a list — step 4 joins with `", "` for display)
|
|
88
85
|
|
|
89
86
|
From `require_tier`:
|
|
90
87
|
|
|
91
88
|
- `{require_tier_satisfied}` ← `require_tier.satisfied` (`true | false | null`; null when `--require-tier` was not set)
|
|
92
89
|
- `{require_tier_failure_missing_tools}` ← `require_tier.missing_tools` (a list)
|
|
93
90
|
|
|
91
|
+
From `prior` (populated by `--prior-state-from`; all fields null/empty on first run):
|
|
92
|
+
|
|
93
|
+
- `{previous_tier}` ← `prior.previous_tier`
|
|
94
|
+
- `{previous_detection_date}` ← `prior.previous_detection_date`
|
|
95
|
+
- `{previous_tools}` ← `prior.previous_tools`
|
|
96
|
+
- `{previous_ccc_index_status}` ← `prior.previous_ccc_index_status`
|
|
97
|
+
- `{previous_ccc_indexed_path}` ← `prior.previous_ccc_indexed_path`
|
|
98
|
+
- `{previous_ccc_last_indexed}` ← `prior.previous_ccc_last_indexed`
|
|
99
|
+
- `{previous_ccc_staleness_threshold_hours}` ← `prior.previous_ccc_staleness_threshold_hours`
|
|
100
|
+
|
|
101
|
+
From `deltas` (computed by the script from current tools + prior; eliminates LLM-side set arithmetic in the report banner):
|
|
102
|
+
|
|
103
|
+
- `{tools_added}` ← `deltas.tools_added` (the list)
|
|
104
|
+
- `{tools_removed}` ← `deltas.tools_removed` (the list)
|
|
105
|
+
- `{tier_changed}` ← `deltas.tier_changed` (boolean)
|
|
106
|
+
|
|
94
107
|
**The script is the source of truth.** Every tier-rules edge case (override-honored-but-unsafe, Deep-doesn't-subsume-Forge+, qmd-binary-vs-daemon distinction, ccc-identity-marker rejection of foreign binaries) is locked into the test suite at `test/test-skf-detect-tools.py`. Substituting prose-driven logic for the script's output here will cause subtle re-run regressions that the prompt's prose is no longer detailed enough to catch.
|
|
95
108
|
|
|
96
109
|
### 4. Auto-Proceed
|
|
@@ -15,7 +15,7 @@ Chain to the shared workflow self-improvement health check at `{nextStepFile}`.
|
|
|
15
15
|
|
|
16
16
|
## Rules
|
|
17
17
|
|
|
18
|
-
- 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 4
|
|
19
19
|
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
20
20
|
- Do not attempt any other action between loading this step and executing `{nextStepFile}`
|
|
21
21
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
tierRulesData: 'references/tier-rules.md'
|
|
3
|
-
nextStepFile: '
|
|
3
|
+
nextStepFile: 'health-check.md'
|
|
4
4
|
# Resolve `{emitEnvelopeHelper}` by probing `{emitEnvelopeProbeOrder}` in order
|
|
5
5
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
6
6
|
# path wins. HALT if neither resolves when the headless envelope must be emitted
|
|
@@ -31,9 +31,9 @@ Display the forge status report with positive capability framing, surface tier c
|
|
|
31
31
|
|
|
32
32
|
## Headless Mode Display Rule
|
|
33
33
|
|
|
34
|
-
When `{headless_mode}` is `true`, sections 2 (the human-readable banner) and 3 (the REQUIRED TIER NOT MET human prose block) are **skipped entirely**. The single line of stdout in
|
|
34
|
+
When `{headless_mode}` is `true` OR `{quiet_mode}` is `true`, sections 2 (the human-readable banner) and 3 (the REQUIRED TIER NOT MET human prose block) are **skipped entirely**. The single line of stdout in those modes is the `SKF_SETUP_RESULT_JSON: {…}` envelope from section 4 — every signal the human banner would have surfaced is already in the envelope (`tier`, `previous_tier`, `tier_changed`, `tools`, `tools_added`, `tools_removed`, `files_written`, `tier_override_*`, `require_tier_satisfied`, `warnings`, `error`). Parent skills, CI pipelines, and expert re-runners consume the envelope alone; they should not be forced to scroll past 30 lines of ASCII-art they cannot use.
|
|
35
35
|
|
|
36
|
-
When `{headless_mode}`
|
|
36
|
+
When both `{headless_mode}` and `{quiet_mode}` are `false`, sections 2 and 3 display normally and section 4 is skipped (interactive runs read the human banner; envelope emission would just be log noise).
|
|
37
37
|
|
|
38
38
|
## MANDATORY SEQUENCE
|
|
39
39
|
|
|
@@ -41,7 +41,7 @@ When `{headless_mode}` is `false`, sections 2 and 3 display normally and section
|
|
|
41
41
|
|
|
42
42
|
Load and read {tierRulesData} for the tier capability descriptions and re-run messages. Needed by section 2; safe to load unconditionally — the data load itself is silent.
|
|
43
43
|
|
|
44
|
-
### 2. Display Forge Status Report (skip when `{headless_mode}` is true)
|
|
44
|
+
### 2. Display Forge Status Report (skip when `{headless_mode}` or `{quiet_mode}` is true)
|
|
45
45
|
|
|
46
46
|
**Format the report as follows:**
|
|
47
47
|
|
|
@@ -80,7 +80,11 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
|
|
|
80
80
|
{end if}
|
|
81
81
|
|
|
82
82
|
{if hygiene_result is "completed" and hygiene_healthy is 0:}
|
|
83
|
-
QMD Registry: empty — collections are created automatically when you run
|
|
83
|
+
QMD Registry: empty — collections are created automatically when you run /skf-create-skill.
|
|
84
|
+
{end if}
|
|
85
|
+
|
|
86
|
+
{if hygiene_result is "qmd_unavailable":}
|
|
87
|
+
QMD Registry: skipped (daemon error — retry after `qmd start`).
|
|
84
88
|
{end if}
|
|
85
89
|
|
|
86
90
|
{if tools.ccc is true:}
|
|
@@ -95,9 +99,7 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
|
|
|
95
99
|
{if preferences_yaml_created is true:}
|
|
96
100
|
- preferences.yaml — {project-root}/_bmad/_memory/forger-sidecar/preferences.yaml (first-run defaults)
|
|
97
101
|
{end if}
|
|
98
|
-
{
|
|
99
|
-
- {forge_data_folder}/ (directory created)
|
|
100
|
-
{end if}
|
|
102
|
+
- {forge_data_folder}/ (directory ensured)
|
|
101
103
|
{if settings_yml_written is true:}
|
|
102
104
|
- .cocoindex_code/settings.yml — {project-root}/.cocoindex_code/settings.yml ({settings_yml_patterns_added} SKF exclusion pattern(s) merged)
|
|
103
105
|
{end if}
|
|
@@ -119,13 +121,13 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
|
|
|
119
121
|
rely on the missing tool(s) will fail at runtime. Install the missing tool(s) or remove
|
|
120
122
|
the override from preferences.yaml.
|
|
121
123
|
|
|
122
|
-
{if
|
|
124
|
+
{if {tier_changed} is true:}
|
|
123
125
|
{appropriate upgrade/downgrade message from tier-rules.md}
|
|
124
126
|
|
|
125
|
-
{if
|
|
127
|
+
{if {tier_changed} is false and {tools_added} is empty and {tools_removed} is empty and {previous_tier} is non-null:}
|
|
126
128
|
{same-tier message from tier-rules.md}
|
|
127
129
|
|
|
128
|
-
{if
|
|
130
|
+
{if {tier_changed} is false and ({tools_added} or {tools_removed} is non-empty):}
|
|
129
131
|
Tier unchanged: {calculated_tier}.
|
|
130
132
|
{if {tools_added} non-empty:} Newly detected: {comma-separated tool names from tools_added}{if ccc was added and tier is Deep: " — ccc enhances Deep tier transparently."}
|
|
131
133
|
{if {tools_removed} non-empty:} No longer detected: {comma-separated tool names from tools_removed} — re-install to restore those capabilities.
|
|
@@ -135,10 +137,10 @@ Load and read {tierRulesData} for the tier capability descriptions and re-run me
|
|
|
135
137
|
═══════════════════════════════════════
|
|
136
138
|
|
|
137
139
|
{if {headless_mode} is false:}
|
|
138
|
-
Next: try
|
|
140
|
+
Next: try `/skf-brief-skill` to scope your first compilation target, or `/skf-quick-skill` for a fast template-driven path. Already have a skill? `/skf-audit-skill` drift-checks an existing skill against current sources.
|
|
139
141
|
```
|
|
140
142
|
|
|
141
|
-
|
|
143
|
+
All re-run-delta context flags (`{tools_added}`, `{tools_removed}`, `{tier_changed}`) come from the detector's `deltas` block bound in stage 1 — no LLM-side recomputation, no set arithmetic in prose.
|
|
142
144
|
|
|
143
145
|
**Tool display rules:**
|
|
144
146
|
|
|
@@ -146,9 +148,9 @@ The same-tier-with-tool-deltas branch reads `{tools_added}` and `{tools_removed}
|
|
|
146
148
|
- Do NOT list unavailable tools
|
|
147
149
|
- Do NOT show a "missing" column or section
|
|
148
150
|
|
|
149
|
-
### 3. Display Required-Tier Failure Block (when applicable; skip when `{headless_mode}` is true)
|
|
151
|
+
### 3. Display Required-Tier Failure Block (when applicable; skip when `{headless_mode}` or `{quiet_mode}` is true)
|
|
150
152
|
|
|
151
|
-
If `{require_tier_satisfied}` is `false` AND `{headless_mode}`
|
|
153
|
+
If `{require_tier_satisfied}` is `false` AND both `{headless_mode}` and `{quiet_mode}` are `false`, display this block immediately after the status report. In headless or quiet modes the failure surfaces via the envelope's `require_tier_satisfied: false` and the synthesized `warnings` entry — the human prose block would be log noise.
|
|
152
154
|
|
|
153
155
|
When the block does fire (interactive run with require-tier failure):
|
|
154
156
|
|
|
@@ -170,7 +172,7 @@ This block exists to make pipeline failures visible without the operator parsing
|
|
|
170
172
|
|
|
171
173
|
### 4. Emit Headless JSON Envelope
|
|
172
174
|
|
|
173
|
-
When `{headless_mode}` is `true`, build the context payload from this step's accumulated flags and forward it to `{emitEnvelopeHelper}` on stdin. Invoke via `uv run` so the script's PEP 723 dependency declarations are honored (the canonical runtime invocation per `docs/getting-started.md`'s uv prereq — bare `python3` skips the metadata block and breaks on a fresh interpreter). The script computes derived fields (`tools_added`, `tools_removed`, `tier_changed`, `warnings`), validates the assembled envelope against the JSON Schema at `src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`, and emits the single prefixed line `SKF_SETUP_RESULT_JSON: {…}` on stdout.
|
|
175
|
+
When `{headless_mode}` is `true` OR `{quiet_mode}` is `true`, build the context payload from this step's accumulated flags and forward it to `{emitEnvelopeHelper}` on stdin. Invoke via `uv run` so the script's PEP 723 dependency declarations are honored (the canonical runtime invocation per `docs/getting-started.md`'s uv prereq — bare `python3` skips the metadata block and breaks on a fresh interpreter). The script computes derived fields (`tools_added`, `tools_removed`, `tier_changed`, `warnings`), validates the assembled envelope against the JSON Schema at `src/shared/scripts/schemas/skf-setup-result-envelope.v1.json`, and emits the single prefixed line `SKF_SETUP_RESULT_JSON: {…}` on stdout.
|
|
174
176
|
|
|
175
177
|
```bash
|
|
176
178
|
echo '{
|
|
@@ -205,12 +207,12 @@ echo '{
|
|
|
205
207
|
}' | uv run {emitEnvelopeHelper} emit
|
|
206
208
|
```
|
|
207
209
|
|
|
208
|
-
The script's documented context-payload shape (see `src/shared/scripts/skf-emit-result-envelope.py` docstring) tolerates two `tools` shapes — bare booleans OR `skf-detect-tools.py`'s `{key: {available: bool, ...}}` output — so either step
|
|
210
|
+
The script's documented context-payload shape (see `src/shared/scripts/skf-emit-result-envelope.py` docstring) tolerates two `tools` shapes — bare booleans OR `skf-detect-tools.py`'s `{key: {available: bool, ...}}` output — so either step 1's normalized booleans OR the raw detect-tools output forwarded as-is will produce the correct envelope.
|
|
209
211
|
|
|
210
212
|
**If the script exits non-zero:** the assembled envelope failed schema validation, which means a context flag from an earlier step is malformed. Surface the error to stderr and continue (the human-readable banner is already displayed; missing JSON envelope on a headless run is a degraded but non-fatal state — the pipeline observer will see no envelope and treat that as "agent did not complete cleanly").
|
|
211
213
|
|
|
212
|
-
**When `{headless_mode}`
|
|
214
|
+
**When both `{headless_mode}` and `{quiet_mode}` are `false`, do NOT invoke the script** — interactive runs read the human-readable banner.
|
|
213
215
|
|
|
214
216
|
### 5. Chain to Health Check
|
|
215
217
|
|
|
216
|
-
After the forge status report (and any failure block + JSON envelope) has been displayed, load `{nextStepFile}`, read it fully, and execute it — UNLESS `{require_tier_satisfied}` is `false`, in which case halt the workflow here without chaining to step
|
|
218
|
+
After the forge status report (and any failure block + JSON envelope) has been displayed, load `{nextStepFile}`, read it fully, and execute it — UNLESS `{require_tier_satisfied}` is `false`, in which case halt the workflow here without chaining to step 5. The health-check step is the true terminal step on success — do not stop after the report on a passing run even though it reads as final. step 5 in turn delegates to `shared/health-check.md`; after that returns, the setup workflow is fully done.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
| ast-grep | `ast-grep --version` | Returns version string without error |
|
|
8
8
|
| gh | `gh --version` | Returns version string without error |
|
|
9
9
|
| qmd | `qmd status` | Returns status indicating initialized and operational |
|
|
10
|
-
| ccc | Step A: `ccc --help` Step B: `ccc doctor` | Step A: exits 0 AND help output identifies the binary as cocoindex-code. Step B: daemon healthy. See `
|
|
10
|
+
| ccc | Step A: `ccc --help` Step B: `ccc doctor` | Step A: exits 0 AND help output identifies the binary as cocoindex-code. Step B: daemon healthy. See `references/detect-and-tier.md` §7 for the full identity-marker procedure. |
|
|
11
11
|
|
|
12
12
|
**Important:** Use verification commands, not existence checks (`which`, `command -v`). A tool must be functional, not just present on PATH. For daemon-based tools (ccc), verify both binary identity and daemon health — a binary with the right name but the wrong implementation is a false positive, not a tool.
|
|
13
13
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'auto-index.md'
|
|
3
3
|
# Resolve `{forgeTierRwHelper}` by probing `{forgeTierRwProbeOrder}` in order
|
|
4
4
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
5
|
# path wins. HALT if neither resolves — the script owns the canonical
|
|
@@ -10,6 +10,12 @@ nextStepFile: './step-03-auto-index.md'
|
|
|
10
10
|
forgeTierRwProbeOrder:
|
|
11
11
|
- '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
|
|
12
12
|
- '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
|
|
13
|
+
# Resolve `{emitEnvelopeHelper}` for the headless/quiet blocked-envelope emit
|
|
14
|
+
# on write failures (the regular envelope assembly happens in step 4, but
|
|
15
|
+
# write halts never reach step 4 — see section 1's blocked-emit protocol).
|
|
16
|
+
emitEnvelopeProbeOrder:
|
|
17
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
|
|
18
|
+
- '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
|
|
13
19
|
---
|
|
14
20
|
|
|
15
21
|
<!-- Config: communicate in {communication_language}. Halt-on-write-failure messages render in the user's language. -->
|
|
@@ -23,7 +29,7 @@ Write the detected tool availability and calculated tier to `forge-tier.yaml` (p
|
|
|
23
29
|
## Rules
|
|
24
30
|
|
|
25
31
|
- Focus only on writing configuration files and creating directories
|
|
26
|
-
- Do not re-detect tools — use results from step
|
|
32
|
+
- Do not re-detect tools — use results from step 1
|
|
27
33
|
- Never inline a YAML template for forge-tier.yaml or preferences.yaml — the script owns the canonical format
|
|
28
34
|
- File write failures are errors — report clearly and halt the workflow
|
|
29
35
|
|
|
@@ -31,7 +37,7 @@ Write the detected tool availability and calculated tier to `forge-tier.yaml` (p
|
|
|
31
37
|
|
|
32
38
|
### 1. Write forge-tier.yaml
|
|
33
39
|
|
|
34
|
-
Build the JSON payload from context flags set by step
|
|
40
|
+
Build the JSON payload from context flags set by step 1 and step 1b. The payload must include `tools`, `tier`, and `ccc_index`; the script handles `tier_detected_at` defaulting to "now" if absent and preserves `qmd_collections`, `ccc_index_registry`, and a user-customized `ccc_index.staleness_threshold_hours` from any existing file.
|
|
35
41
|
|
|
36
42
|
Invoke via `uv run` so the script's PEP 723 PyYAML dependency resolves automatically (this is what `docs/getting-started.md`'s uv prereq exists for). Bare `python3` would fail on a fresh interpreter with `ModuleNotFoundError`.
|
|
37
43
|
|
|
@@ -59,13 +65,13 @@ echo '{
|
|
|
59
65
|
|
|
60
66
|
The script atomically writes the file via temp + fsync + rename (mirrors `skf-atomic-write.py`'s crash-safety contract) and returns a JSON response with `wrote`, `preserved_arrays.qmd_collections` count, `preserved_arrays.ccc_index_registry` count, and the resolved `tier`.
|
|
61
67
|
|
|
62
|
-
**Parse the response and set context flags for step
|
|
68
|
+
**Parse the response and set context flags for step 4:**
|
|
63
69
|
|
|
64
70
|
- `{forge_tier_yaml_path}` ← `wrote`
|
|
65
71
|
- `{forge_tier_qmd_collections_count}` ← `preserved_arrays.qmd_collections`
|
|
66
72
|
- `{forge_tier_ccc_registry_count}` ← `preserved_arrays.ccc_index_registry`
|
|
67
73
|
|
|
68
|
-
**If the script exits non-zero**: parse the stderr JSON `{"status":"error","message":...}`, set `{error: {phase: "step
|
|
74
|
+
**If the script exits non-zero**: parse the stderr JSON `{"status":"error","message":...}`, set `{error: {phase: "step 2:write-tools", path: "{project-root}/_bmad/_memory/forger-sidecar/forge-tier.yaml", reason: <message>}}`, and halt the workflow before chaining to step 3. When `{headless_mode}` or `{quiet_mode}` is true, first pipe the same `{phase, reason, path}` payload to `python3 {emitEnvelopeHelper} emit-blocked` so the pipeline sees the blocked envelope before the halt (see `references/report.md` frontmatter for the helper probe order; the subcommand declares zero dependencies).
|
|
69
75
|
|
|
70
76
|
### 2. Initialize preferences.yaml
|
|
71
77
|
|
|
@@ -76,20 +82,15 @@ uv run {forgeTierRwHelper} init-prefs \
|
|
|
76
82
|
|
|
77
83
|
The script creates the file with first-run defaults (matching the prior inline template — `tier_override: ~`, `passive_context: true`, `headless_mode: false`, `compact_greeting: false`, plus reserved-for-future-use commented fields) IF the file does not exist. When the file already exists, the script refuses to overwrite (preserves user customization) and reports `wrote: false`.
|
|
78
84
|
|
|
79
|
-
**Parse the response and set context flags for step
|
|
85
|
+
**Parse the response and set context flags for step 4:**
|
|
80
86
|
|
|
81
87
|
- `{preferences_yaml_created}` ← `wrote` (true on first run, false on re-run when the file pre-existed)
|
|
82
88
|
|
|
83
|
-
**If the script exits non-zero**: same halt-and-
|
|
89
|
+
**If the script exits non-zero**: same halt-and-blocked-envelope-emit pattern as section 1, with `phase: "step 2:init-prefs"` and the matching path.
|
|
84
90
|
|
|
85
91
|
### 3. Ensure forge-data/ Directory
|
|
86
92
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
- If missing: create it. Store `{forge_data_dir_created: true}` in context.
|
|
90
|
-
- If exists: skip silently. Store `{forge_data_dir_created: false}` in context.
|
|
91
|
-
|
|
92
|
-
If the create fails (parent unwritable, disk full, permission denied), set `{error: {phase: "step-02:forge-data-dir", path: "{forge_data_folder}", reason: <error message>}}` for step-04's envelope and halt the workflow.
|
|
93
|
+
Run `mkdir -p {forge_data_folder}`. The `-p` flag is idempotent (creates parents, exits 0 if the directory already exists), so the prompt does no existence-check reasoning. On non-zero exit, halt with the same blocked-envelope-emit pattern as section 1, using `phase: "step 2:forge-data-dir"` and the matching path.
|
|
93
94
|
|
|
94
95
|
### 4. Auto-Proceed
|
|
95
96
|
|
|
@@ -9,6 +9,15 @@ description: Cognitive completeness verification — quality gate before export.
|
|
|
9
9
|
|
|
10
10
|
Verifies that a skill is complete enough to be useful to an AI agent by checking coverage of the public API surface (naive mode) or validating SKILL.md + references coherence (contextual mode). Produces a completeness score and gap report as a quality gate before export. Every finding must trace to actual code with file:line citations.
|
|
11
11
|
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
15
|
+
- `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
|
|
16
|
+
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
17
|
+
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
18
|
+
- `{skill-name}` resolves to the skill directory's basename.
|
|
19
|
+
- Step files use `## STEP GOAL:` headings rather than the `## MANDATORY SEQUENCE` + `## CRITICAL STEP COMPLETION NOTE` pattern used by generate-driven SKF workflows — this skill is a validation harness with score-driven step semantics, not a chain that produces new artifacts.
|
|
20
|
+
|
|
12
21
|
## Role
|
|
13
22
|
|
|
14
23
|
You are a skill auditor and completeness analyst operating in Ferris's Audit mode. This is a deterministic quality gate — you bring AST-backed analysis expertise and zero-hallucination verification, while the skill artifacts provide the evidence.
|
|
@@ -18,11 +27,8 @@ You are a skill auditor and completeness analyst operating in Ferris's Audit mod
|
|
|
18
27
|
These rules apply to every step in this workflow:
|
|
19
28
|
|
|
20
29
|
- Zero hallucination — every finding must trace to actual code with file:line citations
|
|
21
|
-
- Read each step file completely before taking any action
|
|
22
|
-
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
23
30
|
- Only load one step file at a time — never preload future steps
|
|
24
31
|
- Update `stepsCompleted` in output file frontmatter before loading next step
|
|
25
|
-
- If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
|
|
26
32
|
- Always communicate in `{communication_language}`
|
|
27
33
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
28
34
|
|
|
@@ -30,23 +36,54 @@ These rules apply to every step in this workflow:
|
|
|
30
36
|
|
|
31
37
|
| # | Step | File | Auto-proceed |
|
|
32
38
|
|---|------|------|--------------|
|
|
33
|
-
| 1 | Initialize & Load Skill |
|
|
34
|
-
| 2 | Detect Mode |
|
|
35
|
-
| 3 | Coverage Check |
|
|
36
|
-
| 4 | Coherence Check |
|
|
37
|
-
| 4b | External Validators |
|
|
38
|
-
| 5 | Score |
|
|
39
|
-
| 6 | Report |
|
|
40
|
-
| 7 | Workflow Health Check |
|
|
39
|
+
| 1 | Initialize & Load Skill | references/init.md | Yes |
|
|
40
|
+
| 2 | Detect Mode | references/detect-mode.md | Yes |
|
|
41
|
+
| 3 | Coverage Check | references/coverage-check.md | Yes |
|
|
42
|
+
| 4 | Coherence Check | references/coherence-check.md | Yes |
|
|
43
|
+
| 4b | External Validators | references/external-validators.md | Yes |
|
|
44
|
+
| 5 | Score | references/score.md | Yes |
|
|
45
|
+
| 6 | Report | references/report.md | No (confirm) |
|
|
46
|
+
| 7 | Workflow Health Check | references/health-check.md | Yes |
|
|
41
47
|
|
|
42
48
|
## Invocation Contract
|
|
43
49
|
|
|
44
50
|
| Aspect | Detail |
|
|
45
51
|
|--------|--------|
|
|
46
|
-
| **Inputs** | skill_name [required] |
|
|
47
|
-
| **Gates** | step
|
|
48
|
-
| **Outputs** | test-report-{skill_name}.md with completeness score and result (PASS/FAIL) |
|
|
52
|
+
| **Inputs** | skill_name [required]; optional flags: `--allow-workspace-drift`, `--no-discovery` (skip §4b Discovery Testing), `--no-health-check` (skip §7 health-check dispatch), `--tier=<Quick\|Forge\|Forge+\|Deep>` (bypass forge-tier.yaml sidecar requirement), `--threshold=<N>` (override pass threshold; CLI wins over `workflow.default_threshold` scalar) |
|
|
53
|
+
| **Gates** | step 6: Confirm Gate [C] |
|
|
54
|
+
| **Outputs** | test-report-{skill_name}.md with completeness score and result (PASS/FAIL); per-run `skf-test-skill-result-{run_id}.json` and `skf-test-skill-result-latest.json` written atomically under `{forge_version}/` |
|
|
49
55
|
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
|
|
56
|
+
| **Exit codes** | See "Exit Codes" below |
|
|
57
|
+
|
|
58
|
+
## Exit Codes
|
|
59
|
+
|
|
60
|
+
Every terminal state in this workflow exits with a stable code so headless automators can branch on the verdict (and any HARD HALT) without grepping message text:
|
|
61
|
+
|
|
62
|
+
| Code | Meaning | Raised by |
|
|
63
|
+
| ---- | -------------------- | ------------------------------------------------------------------------------------------ |
|
|
64
|
+
| 0 | success / PASS | step 6 §6b — `testResult: 'pass'` (after the result contract is written in §4c) |
|
|
65
|
+
| 2 | fail / FAIL | step 6 §6b — `testResult: 'fail'` (after the result contract is written in §4c) |
|
|
66
|
+
| 3 | inconclusive | step 6 §6b — `testResult: 'inconclusive'` (distinct from fail so orchestrators can route to manual-review queues) |
|
|
67
|
+
| 4 | pass-with-drift | step 6 §6b — `testResult: 'pass-with-drift'` (distinct from clean pass — `--allow-workspace-drift` was in effect; orchestrators MUST route to re-test-against-pinned-commit queues and refuse export; never exit 0 under drift override) |
|
|
68
|
+
|
|
69
|
+
## Result Contract (Headless)
|
|
70
|
+
|
|
71
|
+
When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
|
|
72
|
+
|
|
73
|
+
```
|
|
74
|
+
SKF_TEST_RESULT_JSON: {"status":"success|error","skill_name":"…","verdict":"PASS|FAIL|INCONCLUSIVE|pass-with-drift","score":N,"threshold":N,"report_path":"…|null","next_workflow":"export-skill|update-skill|null","exit_code":0,"halt_reason":null}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
`status` is `"success"` on the terminal happy path (any of PASS / FAIL / INCONCLUSIVE / pass-with-drift — the workflow completed), `"error"` on any HARD HALT before §4c. `verdict` is the canonical result string. `next_workflow` is `"export-skill"` only when `verdict == "PASS"`; `"update-skill"` for `FAIL` or `pass-with-drift`; `null` for `INCONCLUSIVE` (manual review). `halt_reason` is `null` on the terminal path or one of the workflow-defined halt strings (`"forge-tier-missing"`, `"target-inaccessible"`, `"write-failed"`, `"step-completeness-violation"`, `"report-anchor-missing"`, `"health-check-missing"`, `"atomic-writer-missing"`). `exit_code` matches the table above.
|
|
78
|
+
|
|
79
|
+
The same payload is persisted to disk by step 6 §4c (atomic write) at two locations under `{forge_version}/`:
|
|
80
|
+
|
|
81
|
+
| Path | Purpose |
|
|
82
|
+
| --------------------------------------------- | -------------------------------------------------------------------------- |
|
|
83
|
+
| `skf-test-skill-result-{run_id}.json` | Per-run record. `{run_id}` carries UTC timestamp + PID + random suffix. |
|
|
84
|
+
| `skf-test-skill-result-latest.json` | Latest copy — stable path for pipeline consumers (copy, not symlink). |
|
|
85
|
+
|
|
86
|
+
The on-disk payload is the richer form: it adds `outputs[]` (report-path entries), `summary` (`score`, `threshold`, `result`, `testMode`, `activeCategories[]`, `inconclusiveReasons[]` when present), `runId`, and `healthCheckDispatched`. The stdout envelope is the compact subset documented above.
|
|
50
87
|
|
|
51
88
|
## On Activation
|
|
52
89
|
|
|
@@ -56,4 +93,29 @@ These rules apply to every step in this workflow:
|
|
|
56
93
|
|
|
57
94
|
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
|
|
58
95
|
|
|
59
|
-
3.
|
|
96
|
+
3. **Resolve workflow customization.** Run:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
|
100
|
+
--skill {skill-root} --key workflow
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
|
|
104
|
+
|
|
105
|
+
- `{skill-root}/customize.toml` — bundled defaults
|
|
106
|
+
- `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
|
|
107
|
+
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
108
|
+
|
|
109
|
+
If the script fails or is missing, fall back to reading `{skill-root}/customize.toml` directly — the bundled defaults are an empty string for each path scalar.
|
|
110
|
+
|
|
111
|
+
Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the three scalars, if the merged value is empty or absent, use the bundled default:
|
|
112
|
+
|
|
113
|
+
- `{testReportTemplatePath}` ← `workflow.test_report_template_path` if non-empty, else `templates/test-report-template.md`
|
|
114
|
+
- `{outputFormatsPath}` ← `workflow.output_formats_path` if non-empty, else `assets/output-section-formats.md`
|
|
115
|
+
- `{scoringRulesPath}` ← `workflow.scoring_rules_path` if non-empty, else `references/scoring-rules.md`
|
|
116
|
+
- `{defaultThreshold}` ← `workflow.default_threshold` if non-empty/non-null, else `80`. CLI `--threshold=<N>` (when present) wins over the scalar at the usage site in `references/score.md`.
|
|
117
|
+
- `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty string. When empty, the post-finalization hook in `references/report.md` is a no-op.
|
|
118
|
+
|
|
119
|
+
Stash all five as workflow-context variables. Stage files reference `{testReportTemplatePath}` / `{outputFormatsPath}` / `{scoringRulesPath}` / `{defaultThreshold}` / `{onCompleteCommand}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies without forking the skill.
|
|
120
|
+
|
|
121
|
+
4. Load, read the full file, and then execute `references/init.md` to begin the workflow.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-test-skill.
|
|
4
|
+
|
|
5
|
+
[workflow]
|
|
6
|
+
|
|
7
|
+
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
|
8
|
+
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
9
|
+
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
10
|
+
|
|
11
|
+
# Steps to run before the standard activation (uv probe, config load).
|
|
12
|
+
# Overrides append. Use for org-wide pre-flight checks (auth, network,
|
|
13
|
+
# compliance) that must precede any quality-test work.
|
|
14
|
+
|
|
15
|
+
activation_steps_prepend = []
|
|
16
|
+
|
|
17
|
+
# Steps to run after activation but before the first stage executes.
|
|
18
|
+
# Overrides append. Use for context loads or banner customization that
|
|
19
|
+
# should run once activation completes successfully.
|
|
20
|
+
|
|
21
|
+
activation_steps_append = []
|
|
22
|
+
|
|
23
|
+
# Persistent facts the workflow keeps in mind for the whole run
|
|
24
|
+
# (house style, severity policies, grading guardrails).
|
|
25
|
+
# Overrides append.
|
|
26
|
+
#
|
|
27
|
+
# Each entry is either:
|
|
28
|
+
# - a literal sentence, e.g. "Test failures of CRITICAL severity block release."
|
|
29
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
30
|
+
# "file:{project-root}/docs/test-policy.md" (globs supported; file
|
|
31
|
+
# contents are loaded and treated as facts).
|
|
32
|
+
|
|
33
|
+
persistent_facts = [
|
|
34
|
+
"file:{project-root}/**/project-context.md",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
# --- Optional asset overrides ---
|
|
38
|
+
#
|
|
39
|
+
# Lift the canonical asset paths so orgs can substitute house-style copies
|
|
40
|
+
# without forking the skill. Empty string = use the bundled default.
|
|
41
|
+
|
|
42
|
+
test_report_template_path = ""
|
|
43
|
+
output_formats_path = ""
|
|
44
|
+
scoring_rules_path = ""
|
|
45
|
+
|
|
46
|
+
# Pass threshold (percent). CLI `--threshold=<N>` wins over this scalar.
|
|
47
|
+
# Override here to change the org-wide default without forking the skill.
|
|
48
|
+
default_threshold = 80
|
|
49
|
+
|
|
50
|
+
# Optional post-finalization hook. When non-empty, the workflow invokes:
|
|
51
|
+
# <on_complete> --result-path=<path-to-skf-test-skill-result-{run_id}.json>
|
|
52
|
+
# after the result JSON is finalized. Failures are recorded to
|
|
53
|
+
# workflow_warnings[] but never fail the workflow. Empty = no-op.
|
|
54
|
+
on_complete = ""
|