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: 'fetch-docs.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,23 +8,23 @@ 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 3b: Fetch Temporal Context
|
|
12
14
|
|
|
13
15
|
## STEP GOAL:
|
|
14
16
|
|
|
15
|
-
To fetch temporal context (issues, PRs, changelogs, release notes) from the source repository and index it into a QMD collection for Deep tier enrichment. This ensures step
|
|
17
|
+
To fetch temporal context (issues, PRs, changelogs, release notes) from the source repository and index it into a QMD collection for Deep tier enrichment. This ensures step 4 has historical data to search when annotating extracted functions with T2 provenance.
|
|
16
18
|
|
|
17
19
|
## Rules
|
|
18
20
|
|
|
19
21
|
- Deep tier only — Quick, Forge, and Forge+ tiers skip this step entirely and silently
|
|
20
22
|
- GitHub repositories only — other source types degrade gracefully
|
|
21
23
|
- Do not halt the workflow if fetching or indexing fails
|
|
22
|
-
- Do not modify extraction data from step
|
|
24
|
+
- Do not modify extraction data from step 3 — this step only creates QMD collections
|
|
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 sequentially. **If ANY condition fails, skip silently to section 5 (auto-proceed) with no output:**
|
|
@@ -69,57 +69,65 @@ Create a staging directory: `_bmad-output/{skill-name}-temporal/`
|
|
|
69
69
|
|
|
70
70
|
Resolve the `owner` and `repo` from `source_repo` (e.g., `acme/toolkit` from `https://github.com/acme/toolkit`).
|
|
71
71
|
|
|
72
|
-
Execute the
|
|
73
|
-
|
|
74
|
-
1. **Issues (last 100):** (rationale: 100 is `gh issue list`'s default max-per-page; a single paginated call captures recent activity without extra round trips or rate-limit pressure)
|
|
72
|
+
Execute the four fetches below **in parallel** — they are independent and the network round-trips dominate wall-clock. Background each, then `wait` for the batch. **If any individual fetch fails, log a warning and continue with the others.** The 4-concurrent fan-out is well under GitHub's authenticated REST rate limit (5000/hr); no bounded-concurrency guard is needed for this set.
|
|
75
73
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
74
|
+
```bash
|
|
75
|
+
mkdir -p {staging}
|
|
76
|
+
# 1. Issues (last 100)
|
|
77
|
+
( gh issue list -R {owner}/{repo} --state all --limit 100 \
|
|
78
|
+
--json number,title,state,labels,createdAt,closedAt,body \
|
|
79
|
+
| jq -r '...' > {staging}/issues.md ) &
|
|
80
|
+
# 2. Merged PRs (last 100)
|
|
81
|
+
( gh pr list -R {owner}/{repo} --state merged --limit 100 \
|
|
82
|
+
--json number,title,mergedAt,labels,body \
|
|
83
|
+
| jq -r '...' > {staging}/prs.md ) &
|
|
84
|
+
# 3. Release tags only (the per-tag fetch loop runs sequentially below to
|
|
85
|
+
# preserve append-immediately crash-resume semantics for releases.md)
|
|
86
|
+
( gh release list -R {owner}/{repo} --limit 10 \
|
|
87
|
+
--json tagName,name,publishedAt > {staging}/.release-tags.json ) &
|
|
88
|
+
# 4. Changelog (404 is silent skip — note `set +e` so the subshell doesn't
|
|
89
|
+
# propagate `gh api`'s non-zero exit on missing file)
|
|
90
|
+
( set +e
|
|
91
|
+
gh api repos/{owner}/{repo}/contents/CHANGELOG.md --jq '.content' \
|
|
92
|
+
| base64 -d > {staging}/changelog.md 2>/dev/null
|
|
93
|
+
[ -s {staging}/changelog.md ] || rm -f {staging}/changelog.md ) &
|
|
94
|
+
wait
|
|
95
|
+
```
|
|
79
96
|
|
|
80
|
-
|
|
97
|
+
Per-call rationale:
|
|
81
98
|
|
|
82
|
-
|
|
99
|
+
1. **Issues (last 100):** 100 is `gh issue list`'s default max-per-page; one paginated call captures recent activity without extra round trips or rate-limit pressure. Output → `{staging}/issues.md` formatted as a markdown document with one section per issue.
|
|
83
100
|
|
|
84
|
-
|
|
85
|
-
gh pr list -R {owner}/{repo} --state merged --limit 100 --json number,title,mergedAt,labels,body | ...
|
|
86
|
-
```
|
|
101
|
+
2. **Merged PRs (last 100):** Same 100-per-page convention as issues — captures the most recent merges in one API call. Output → `{staging}/prs.md`.
|
|
87
102
|
|
|
88
|
-
|
|
103
|
+
3. **Release tags + per-release fetches (last 10):** Release notes accumulate slowly relative to issues/PRs; the most recent 10 tags cover roughly the last 6-18 months of changelog-relevant history for typical OSS projects, which is enough context for T2-past annotations without fanning out to dozens of `gh release view` calls.
|
|
89
104
|
|
|
90
|
-
|
|
105
|
+
**Note:** `gh release list --json` does **not** support the `body` field. The parallel block above fetches tags only (Step 1). After `wait`, run **Step 2 sequentially** to preserve the append-immediately crash-resume contract:
|
|
91
106
|
|
|
92
|
-
|
|
107
|
+
If `{staging}/.release-tags.json` is empty (no releases), skip Step 2 and omit the releases section entirely. Otherwise:
|
|
93
108
|
|
|
94
109
|
```bash
|
|
95
|
-
#
|
|
96
|
-
|
|
110
|
+
# Sequential per-tag loop. Iterate the JSON tag array verbatim so a
|
|
111
|
+
# crash mid-loop leaves a partial-but-well-formed releases.md on disk.
|
|
112
|
+
echo "# Releases (partial if interrupted)" > {staging}/releases.md
|
|
113
|
+
ERR_FILE="{staging}/.gh-release-err" # per-run stderr capture inside staging
|
|
114
|
+
jq -r '.[].tagName' {staging}/.release-tags.json | while IFS= read -r tag; do
|
|
115
|
+
if gh release view "$tag" -R {owner}/{repo} \
|
|
116
|
+
--json tagName,name,publishedAt,body 2>"$ERR_FILE"; then
|
|
117
|
+
jq -r '...' >> {staging}/releases.md # one ## {tag} block per release
|
|
118
|
+
else
|
|
119
|
+
echo "## $tag — fetch failed: $(cat "$ERR_FILE")" \
|
|
120
|
+
>> {staging}/releases.md
|
|
121
|
+
fi
|
|
122
|
+
done
|
|
123
|
+
rm -f "$ERR_FILE"
|
|
97
124
|
```
|
|
98
125
|
|
|
99
|
-
|
|
126
|
+
Failed individual fetches get a one-line placeholder; the loop continues with remaining tags. If a rate limit (HTTP 429) is hit, stop the release loop, keep the partial `releases.md` file in place (do NOT delete it), and log: "Release fetch stopped at tag {N}/{total} due to rate limiting — partial releases.md retained."
|
|
100
127
|
|
|
101
|
-
|
|
102
|
-
# Step 2: For EACH tagName from Step 1, fetch the full release
|
|
103
|
-
gh release view {tagName} -R {owner}/{repo} --json tagName,name,publishedAt,body
|
|
104
|
-
```
|
|
128
|
+
**Why sequential here when the rest is parallel:** the append-per-release pattern guarantees that a mid-loop abort (rate limit, network drop, user interrupt) leaves a partial but well-formed `releases.md` with every release fetched so far. Parallel writers appending to the same file would need file locking and per-writer ordering — the simpler sequential loop is robust for free, and 10 release fetches contribute only ~5-10s of the total wall-clock.
|
|
105
129
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
Write an empty `{staging}/releases.md` with a header (`# Releases (partial if interrupted)`) before the loop, then append one `## {tagName} — {name} ({publishedAt})` section per successful fetch. Failed individual fetches get a one-line placeholder: `## {tagName} — fetch failed: {error}`.
|
|
109
|
-
|
|
110
|
-
If `gh release view` fails for a specific tag, log a warning and skip that release — continue with remaining tags. If a rate limit (HTTP 429) is hit, stop the release loop, keep the partial `releases.md` file in place (do NOT delete it), and log: "Release fetch stopped at tag {N}/{total} due to rate limiting — partial releases.md retained."
|
|
111
|
-
|
|
112
|
-
Format each section as a markdown block with tag, name, date, and body.
|
|
113
|
-
|
|
114
|
-
4. **Changelog (if exists):**
|
|
115
|
-
|
|
116
|
-
Check if `CHANGELOG.md` or `RELEASES.md` exists in the repository root:
|
|
117
|
-
|
|
118
|
-
```bash
|
|
119
|
-
gh api repos/{owner}/{repo}/contents/CHANGELOG.md --jq '.content' | base64 -d
|
|
120
|
-
```
|
|
121
|
-
|
|
122
|
-
If found, write to `{staging}/changelog.md`. If not found (404), skip silently.
|
|
130
|
+
4. **Changelog:** `CHANGELOG.md` or `RELEASES.md` at the repository root. The parallel block above writes to `{staging}/changelog.md` only when the file exists; non-existence (404 from `gh api`) leaves no file behind.
|
|
123
131
|
|
|
124
132
|
#### 3b. Targeted Function Searches (Uses Extraction Inventory)
|
|
125
133
|
|
|
@@ -127,19 +135,42 @@ After the generic fetches above, perform **targeted searches** using the top-lev
|
|
|
127
135
|
|
|
128
136
|
**Short-circuit on empty `top_exports`:** If `extraction_inventory.top_exports` is missing or `== []` (docs-only mode, or a source extraction that produced zero public exports), skip this sub-section entirely with a one-line log: "No exports in inventory — skipping targeted function searches." The generic fetches from §3 remain in place and continue to provide baseline temporal context.
|
|
129
137
|
|
|
130
|
-
**Limit:** Search the top **10 function names** maximum to control API call volume and avoid `gh` rate limiting. (rationale: 10 targeted searches + generic fetches from §3 stays well under GitHub's unauthenticated search rate limit of 10 requests/minute and authenticated 30/minute; matches the `top_exports[]` size emitted by step
|
|
138
|
+
**Limit:** Search the top **10 function names** maximum to control API call volume and avoid `gh` rate limiting. (rationale: 10 targeted searches + generic fetches from §3 stays well under GitHub's unauthenticated search rate limit of 10 requests/minute and authenticated 30/minute; matches the `top_exports[]` size emitted by step 3 §5 so every tracked export gets one search.)
|
|
131
139
|
|
|
132
140
|
For each function name in `top_exports[]` (up to 10), **sanitize first**: strip every character that is not in `[A-Za-z0-9_]` from `function_name` to produce `safe_name`. This prevents shell injection and `gh` query parser errors when an export name contains punctuation (e.g., `<T>`, `.method`, `::namespace`, quotes). If `safe_name` is empty after sanitization (the original was entirely punctuation — rare but possible for symbol exports), fall back to piping the original name through stdin via `--query-from-file -`-style indirection if your `gh` version supports it; otherwise skip that one entry with a log line — never substitute the unsanitized name back into the shell command.
|
|
133
141
|
|
|
142
|
+
**Parallel fan-out (bounded concurrency = 5):** sanitized searches are independent and benefit from parallelism. Use `xargs -P 5` so at most 5 `gh search` calls are in flight at once — this stays well under GitHub's authenticated search rate limit (30/min) while saving ~5-8s of wall-clock on a top-10 export list compared to fully sequential.
|
|
143
|
+
|
|
134
144
|
```bash
|
|
135
|
-
#
|
|
136
|
-
#
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
145
|
+
# 1. Sanitize and write one safe_name per line; skip empties.
|
|
146
|
+
# Python is the canonical sanitizer because awk/sed regex semantics
|
|
147
|
+
# vary across platforms.
|
|
148
|
+
jq -r '.top_exports[]' {extraction_inventory.json} \
|
|
149
|
+
| python3 -c 'import sys,re
|
|
150
|
+
for line in sys.stdin:
|
|
151
|
+
s = re.sub(r"[^A-Za-z0-9_]", "", line.strip())
|
|
152
|
+
if s: print(s)' > {staging}/.safe-names.txt
|
|
153
|
+
|
|
154
|
+
# 2. Fan out to gh search, 5 in flight. Each writer emits a self-contained
|
|
155
|
+
# section to its own per-name file; we concatenate after the wait.
|
|
156
|
+
# --limit 5: top-5 issues per function keeps signal-to-noise high and caps
|
|
157
|
+
# total response size across 10 fan-outs at 50 issues.
|
|
158
|
+
mkdir -p {staging}/targeted
|
|
159
|
+
cat {staging}/.safe-names.txt | xargs -P 5 -I {} bash -c '
|
|
160
|
+
gh search issues --repo {owner}/{repo} "{}" --limit 5 \
|
|
161
|
+
--json number,title,state,body 2>/dev/null \
|
|
162
|
+
| jq -r ". | \"## {}\\n\" + (...)" > {staging}/targeted/{}.md \
|
|
163
|
+
|| echo "## {} — fetch failed" > {staging}/targeted/{}.md
|
|
164
|
+
'
|
|
165
|
+
|
|
166
|
+
# 3. Concatenate in stable order (alpha by safe_name) into the single
|
|
167
|
+
# aggregated file the rest of the workflow expects.
|
|
168
|
+
sort {staging}/.safe-names.txt | while IFS= read -r name; do
|
|
169
|
+
cat "{staging}/targeted/$name.md"
|
|
170
|
+
done > {staging}/targeted-issues.md
|
|
140
171
|
```
|
|
141
172
|
|
|
142
|
-
Aggregate all targeted search results into a single file: `{staging}/targeted-issues.md`.
|
|
173
|
+
Aggregate all targeted search results into a single file: `{staging}/targeted-issues.md`. The per-name temp directory `{staging}/targeted/` can be removed after concat — it exists only to give each parallel writer an isolated output stream.
|
|
143
174
|
|
|
144
175
|
**If `gh search` is unavailable** (older `gh` CLI versions): skip targeted searches silently. The generic fetches from section 3 still provide baseline temporal context.
|
|
145
176
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
nextStepFile: '
|
|
2
|
+
nextStepFile: 'generate-artifacts.md'
|
|
3
3
|
tesslDismissalData: 'assets/tessl-dismissal-rules.md'
|
|
4
|
+
descriptionGuardProtocol: '{project-root}/src/shared/references/description-guard-protocol.md'
|
|
4
5
|
# Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
|
|
5
6
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
6
7
|
# path wins. HALT if neither resolves — losing atomic-write guarantees is not
|
|
@@ -8,8 +9,18 @@ tesslDismissalData: 'assets/tessl-dismissal-rules.md'
|
|
|
8
9
|
atomicWriteProbeOrder:
|
|
9
10
|
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
10
11
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
12
|
+
# Resolve `{descriptionGuardHelper}` by probing `{descriptionGuardProbeOrder}`
|
|
13
|
+
# in order (installed SKF module path first, src/ dev-checkout fallback);
|
|
14
|
+
# first existing path wins. HALT if neither resolves — letting an external
|
|
15
|
+
# tool's rewrite of the description field stand would silently regress
|
|
16
|
+
# discovery quality.
|
|
17
|
+
descriptionGuardProbeOrder:
|
|
18
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-description-guard.py'
|
|
19
|
+
- '{project-root}/src/shared/scripts/skf-description-guard.py'
|
|
11
20
|
---
|
|
12
21
|
|
|
22
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
23
|
+
|
|
13
24
|
# Step 6: Validate
|
|
14
25
|
|
|
15
26
|
## STEP GOAL:
|
|
@@ -20,38 +31,19 @@ To validate the compiled SKILL.md content against the agentskills.io specificati
|
|
|
20
31
|
|
|
21
32
|
- Focus only on validating compiled content against spec — only fix spec compliance issues
|
|
22
33
|
- Validation and auto-fix modify files in the staging directory
|
|
23
|
-
- `<staging-skill-dir>` resolves to `_bmad-output/{skill-name}/` as created by step
|
|
34
|
+
- `<staging-skill-dir>` resolves to `_bmad-output/{skill-name}/` as created by step 5. The directory name must match the skill's frontmatter `name` field exactly — `skill-check`'s `frontmatter.name_matches_directory` rule rejects any suffix.
|
|
24
35
|
- If skill-check unavailable: skip validation, add warning to evidence report
|
|
25
36
|
- Ignore non-zero exit codes from skill-check if JSON output shows 0 errors
|
|
26
37
|
|
|
27
38
|
## MANDATORY SEQUENCE
|
|
28
39
|
|
|
29
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise.
|
|
30
|
-
|
|
31
40
|
### 0. Description Guard Protocol
|
|
32
41
|
|
|
33
42
|
**Used by:** §2 (`skill-check check --fix`), §4 (`split-body`), and any future tool invocation that may modify SKILL.md.
|
|
34
43
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
To prevent this, any tool invocation that may touch SKILL.md must run inside the following four-phase guard:
|
|
38
|
-
|
|
39
|
-
1. **Capture.** Before invoking the tool, read the current SKILL.md frontmatter and snapshot the exact `description` value into a local variable (e.g., `guarded_description`). Capture the in-context copy as well.
|
|
40
|
-
2. **Execute.** Run the tool as specified in its section.
|
|
41
|
-
3. **Verify.** After the tool completes, re-read the on-disk SKILL.md and compare its frontmatter `description` against `guarded_description` as **token streams**: split each string on whitespace (`str.split()` — any run of spaces/tabs/newlines collapses) and compare the resulting lists element-by-element. This catches content divergence (missing words, replaced phrases, truncation, angle-bracket re-introduction) while ignoring cosmetic whitespace changes that a tool may apply (trailing newline, re-wrapped quoted strings). Do NOT use a normalized-string equality — a tool that rewrites `"foo bar"` to `"foo bar"` (collapsed inner run) would trip a naive normalization even though no semantic content changed, and a tool that swapped one word would slip past a looser fuzzy match. Token-stream comparison is the sweet spot.
|
|
42
|
-
4. **Restore on divergence.** If the post-tool description differs from `guarded_description` in any way other than whitespace normalization, write `guarded_description` back to the on-disk SKILL.md frontmatter and update the in-context copy to match. Record `description_guard_restored: true` with the tool name in context for the evidence report.
|
|
43
|
-
5. **Re-validate restored description.** After a restore, run `uv run {project-root}/src/shared/scripts/skf-validate-frontmatter.py <staging-skill-dir>/SKILL.md` against the on-disk file to confirm the restored description still satisfies the frontmatter contract (length limits, forbidden tokens, required fields). The script declares pyyaml in its PEP 723 inline metadata; `uv run` resolves it automatically (per `docs/getting-started.md`'s uv prereq), while bare `python3` would `ModuleNotFoundError` on a fresh interpreter. Capture `schema_revalidation_result` in context. If the validator exits non-zero OR reports failure for the `description` field: flip the Schema result back to `FAIL` in the evidence report (overriding any prior PASS/WARN from §2), record `description_guard_revalidation: FAIL` with the validator's diagnostic message, and continue — do not halt (step-09 health-check and result contract still need to run so the failure is surfaced through the normal artifact path).
|
|
44
|
-
|
|
45
|
-
**What counts as divergence:**
|
|
44
|
+
Load `{descriptionGuardProtocol}` for the full prose explanation of the four-phase guard (why it exists, what counts as divergence, why token-stream comparison is the right shape). The deterministic phases are executed via `{descriptionGuardHelper}` — the calling sections (§2 and §4) invoke the helper at the capture and verify-restore points.
|
|
46
45
|
|
|
47
|
-
-
|
|
48
|
-
- The description was truncated (suffix missing).
|
|
49
|
-
- Angle-bracket tokens were re-introduced (should never happen after step-05 §2a, but protect anyway).
|
|
50
|
-
- The field was deleted entirely (extreme tool behavior).
|
|
51
|
-
|
|
52
|
-
**What does NOT count as divergence:** whitespace-only differences (trailing newline, trimmed spaces) — treat as equivalent.
|
|
53
|
-
|
|
54
|
-
**Why this is centralized:** previously, §2 and §4 each contained their own capture/verify/restore prose. Duplicated defensive code drifts: a fix in one section doesn't propagate to the other, and adding a new tool invocation in the future requires remembering to copy the pattern. Centralizing the protocol gives step-06 one place to update when external validator behavior changes.
|
|
46
|
+
**This skill's post-restore re-validation hook:** after `{descriptionGuardHelper}` reports `restored: true`, run `uv run {project-root}/src/shared/scripts/skf-validate-frontmatter.py <staging-skill-dir>/SKILL.md` and capture `schema_revalidation_result` in context. If the validator exits non-zero OR reports failure for the `description` field, flip the Schema result back to `FAIL` in the evidence report (overriding any prior PASS/WARN from §2), record `description_guard_revalidation: FAIL` with the validator's diagnostic message, and continue — do not halt (step 9 health-check and result contract still need to run so the failure is surfaced through the normal artifact path).
|
|
55
47
|
|
|
56
48
|
### 1. Check Tool Availability
|
|
57
49
|
|
|
@@ -69,11 +61,11 @@ Run the external skill-check tool against the compiled skill staging directory.
|
|
|
69
61
|
**Flag probe (run once, cache the result for §4 and §5 re-invocations):**
|
|
70
62
|
|
|
71
63
|
```bash
|
|
72
|
-
npx skill-check --help 2>/dev/null | grep -- --no-security-scan
|
|
64
|
+
npx skill-check check --help 2>/dev/null | grep -- --no-security-scan
|
|
73
65
|
```
|
|
74
66
|
|
|
75
67
|
- If the probe matches `--no-security-scan`: set `{security_scan_flag} = "--no-security-scan"`.
|
|
76
|
-
- Else run a second probe — `npx skill-check --help 2>/dev/null | grep -- --skip-security` — and if it matches, set `{security_scan_flag} = "--skip-security"`.
|
|
68
|
+
- Else run a second probe — `npx skill-check check --help 2>/dev/null | grep -- --skip-security` — and if it matches, set `{security_scan_flag} = "--skip-security"`.
|
|
77
69
|
- If neither flag exists: set `{security_scan_flag} = ""` (empty) AND set `{skill_check_flag_fallback} = true`. Skip §2 and §4 automated flows entirely — fall through to §3 manual frontmatter validation. Record in evidence-report: `skill_check_flag_probe: neither --no-security-scan nor --skip-security supported by installed skill-check; validation performed manually`.
|
|
78
70
|
|
|
79
71
|
**If a security-scan-disable flag was resolved (probe succeeded):**
|
|
@@ -86,7 +78,21 @@ This performs frontmatter validation, description quality checks, body limit enf
|
|
|
86
78
|
|
|
87
79
|
**Parse the JSON output** for: `qualityScore` (0-100), `diagnostics[]` (remaining issues), `fixed[]` (auto-corrected issues).
|
|
88
80
|
|
|
89
|
-
**Description Guard Protocol:** This invocation may modify SKILL.md (especially when `fixed[]` is non-empty). Wrap the `skill-check check --fix` call in the four-phase
|
|
81
|
+
**Description Guard Protocol:** This invocation may modify SKILL.md (especially when `fixed[]` is non-empty). Wrap the `skill-check check --fix` call in the four-phase guard defined in §0 by invoking `{descriptionGuardHelper}` at the capture and verify-restore points:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
# Phase 1 — capture before the tool call
|
|
85
|
+
uv run {descriptionGuardHelper} capture <staging-skill-dir>/SKILL.md
|
|
86
|
+
# stash the returned `description` as `guarded_description` in workflow context
|
|
87
|
+
|
|
88
|
+
# Phase 2 — run skill-check (see command block above)
|
|
89
|
+
|
|
90
|
+
# Phases 3+4 — verify and restore after the tool call
|
|
91
|
+
uv run {descriptionGuardHelper} verify-restore <staging-skill-dir>/SKILL.md \
|
|
92
|
+
--captured-description "{guarded_description}"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If `restored: true` in the verify-restore output, apply §0's post-restore re-validation hook. If `fixed[]` was non-empty in the skill-check output, also re-read the modified SKILL.md to sync the in-context copy before proceeding — this prevents silent divergence between the in-context and on-disk versions that step 7 will use for artifact generation.
|
|
90
96
|
|
|
91
97
|
**Note:** `skill-check` may return non-zero exit code even when `errorCount` is 0. Always rely on parsed JSON, not the shell exit code.
|
|
92
98
|
|
|
@@ -113,7 +119,21 @@ If fails: auto-fix (deterministic), re-validate once, record result. If passes:
|
|
|
113
119
|
|
|
114
120
|
**If step 2 reported `body.max_lines` failure:**
|
|
115
121
|
|
|
116
|
-
**Description Guard Protocol:** Split operations may rewrite the frontmatter. Wrap the split invocation in the four-phase
|
|
122
|
+
**Description Guard Protocol:** Split operations may rewrite the frontmatter. Wrap the split invocation in the four-phase guard defined in §0:
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Phase 1 — capture before the split
|
|
126
|
+
uv run {descriptionGuardHelper} capture <staging-skill-dir>/SKILL.md
|
|
127
|
+
# stash returned `description` as `guarded_description`
|
|
128
|
+
|
|
129
|
+
# Phase 2 — run the split (selective extraction or, last-resort, split-body --write)
|
|
130
|
+
|
|
131
|
+
# Phases 3+4 — verify and restore after the split
|
|
132
|
+
uv run {descriptionGuardHelper} verify-restore <staging-skill-dir>/SKILL.md \
|
|
133
|
+
--captured-description "{guarded_description}"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
If `restored: true` in the verify-restore output, apply §0's post-restore re-validation hook.
|
|
117
137
|
|
|
118
138
|
**Mandatory approach — selective split:** Identify Tier 2 sections by their `## Full` heading prefix (e.g., `## Full API Reference`, `## Full Type Definitions`, `## Full Integration Patterns`). Extract ONLY those sections to `references/`, starting with the largest. Keep ALL Tier 1 content and any smaller sections inline. Inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval (per Vercel research).
|
|
119
139
|
|
|
@@ -162,7 +182,7 @@ Parse output for: `description_score`, `content_score`, `review_score`, `validat
|
|
|
162
182
|
**Apply dismissal rules** in this order:
|
|
163
183
|
|
|
164
184
|
1. **Check score thresholds** against the "Score Thresholds" table in `{tesslDismissalData}`. Most importantly:
|
|
165
|
-
- If `description_score < 100`: follow the **recover-then-halt** path defined by the `description-xml-tags-guarded-upstream` rule in `{tesslDismissalData}`. Re-apply step
|
|
185
|
+
- If `description_score < 100`: follow the **recover-then-halt** path defined by the `description-xml-tags-guarded-upstream` rule in `{tesslDismissalData}`. Re-apply step 5 §2a's `<`/`>` → `{`/`}` substitution in place on the staging SKILL.md frontmatter `description`, re-sync the in-context copy, and re-run `npx -y tessl skill review <staging-skill-dir>` once. **Re-run gate:** treat `description_score == 100` on the re-run as the only successful recovery outcome. ANY value strictly less than 100 on the re-run — including 99, intermediate-but-improved scores like 95 (formerly tolerated as "close enough"), or 0 — counts as recovery failure: halt with the original `description-xml-tags-guarded-upstream` failure message from `{tesslDismissalData}`, do NOT proceed to §6b, and do NOT downgrade the recovery to a warning. If the re-run produces `description_score == 100`, log `description-recovery: applied ({count} substitutions)` in the evidence report under "Dismissed tessl suggestions" and continue suggestion iteration against the rerun's `judge_suggestions[]`.
|
|
166
186
|
- If `review_score < 60` or `content_score < 60`: record warnings in the evidence report, continue.
|
|
167
187
|
2. **Iterate `judge_suggestions[]`.** For each suggestion:
|
|
168
188
|
- Cross-reference against the rules in `{tesslDismissalData}` in order.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: skf-create-stack-skill
|
|
3
|
-
description: Consolidated project stack skill with integration patterns — code-mode (analyzes manifests) or compose-mode (synthesizes from existing skills + architecture doc). Use when the user requests to "create a stack skill.
|
|
3
|
+
description: Consolidated project stack skill with integration patterns — code-mode (analyzes manifests) or compose-mode (synthesizes from existing skills + architecture doc). Use when the user requests to "create a stack skill", "forge a stack", or "stack this project".
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Create Stack Skill
|
|
@@ -9,46 +9,80 @@ description: Consolidated project stack skill with integration patterns — code
|
|
|
9
9
|
|
|
10
10
|
Produces a consolidated stack skill documenting how libraries connect. **Code-mode** analyzes dependency manifests and co-import patterns from actual source code. **Compose-mode** synthesizes from pre-generated individual skills and architecture documents when no codebase exists yet. Every finding must trace to actual code with file:line citations; in compose-mode, inferred integrations are permitted but must be labeled `[inferred from shared domain]`.
|
|
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
|
+
|
|
12
20
|
## Role
|
|
13
21
|
|
|
14
|
-
You are a dependency analyst and integration architect
|
|
22
|
+
You are a dependency analyst and integration architect. You bring expertise in dependency analysis, cross-library integration patterns, and compositional architecture, while the user brings their project knowledge and scope preferences.
|
|
15
23
|
|
|
16
24
|
## Workflow Rules
|
|
17
25
|
|
|
18
26
|
These rules apply to every step in this workflow:
|
|
19
27
|
|
|
20
28
|
- Zero hallucination — all extracted content must trace to actual source code (compose-mode inferences must be labeled)
|
|
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
29
|
- Only load one step file at a time — never preload future steps
|
|
24
30
|
- If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
|
|
25
31
|
- Always communicate in `{communication_language}`
|
|
26
32
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
27
|
-
-
|
|
33
|
+
- Warnings use a single accumulator — see `## Workflow state contract` below for shape and surfacing.
|
|
34
|
+
|
|
35
|
+
## Workflow state contract
|
|
36
|
+
|
|
37
|
+
Every step that emits a warning ("log a warning", "record in workflow state for the evidence report", "Warning: ...", etc.) appends a structured entry to a single in-memory list named `workflow_warnings[]`. Each entry has the shape `{step: "step-NN", severity: "info|warn|error", code: "<short-slug>", message: "<human text>", context: {<optional fields>}}`. Step 7 surfaces these in `evidence-report.md`; step 8 may add validation findings; step 9 §5 reads the accumulated list and renders the user-facing "Warnings" section. There is exactly one accumulator for the whole workflow — do not invent per-step channels.
|
|
28
38
|
|
|
29
39
|
## Stages
|
|
30
40
|
|
|
31
41
|
| # | Step | File | Auto-proceed |
|
|
32
42
|
|---|------|------|--------------|
|
|
33
|
-
| 1 | Initialize & Mode Detection |
|
|
34
|
-
| 2 | Detect Manifests |
|
|
35
|
-
| 3 | Rank & Confirm Libraries |
|
|
36
|
-
| 4 | Parallel Extract |
|
|
37
|
-
| 5 | Detect Integrations |
|
|
38
|
-
| 6 | Compile Stack |
|
|
39
|
-
| 7 | Generate Output |
|
|
40
|
-
| 8 | Validate |
|
|
41
|
-
| 9 | Report |
|
|
42
|
-
| 10 | Workflow Health Check |
|
|
43
|
+
| 1 | Initialize & Mode Detection | references/init.md | No (confirm) |
|
|
44
|
+
| 2 | Detect Manifests | references/detect-manifests.md | Yes |
|
|
45
|
+
| 3 | Rank & Confirm Libraries | references/rank-and-confirm.md | No (confirm) |
|
|
46
|
+
| 4 | Parallel Extract | references/parallel-extract.md | Yes |
|
|
47
|
+
| 5 | Detect Integrations | references/detect-integrations.md | Yes |
|
|
48
|
+
| 6 | Compile Stack | references/compile-stack.md | No (review) |
|
|
49
|
+
| 7 | Generate Output | references/generate-output.md | Yes |
|
|
50
|
+
| 8 | Validate | references/validate.md | Yes |
|
|
51
|
+
| 9 | Report | references/report.md | Yes |
|
|
52
|
+
| 10 | Workflow Health Check | references/health-check.md | Yes |
|
|
43
53
|
|
|
44
54
|
## Invocation Contract
|
|
45
55
|
|
|
46
56
|
| Aspect | Detail |
|
|
47
57
|
|--------|--------|
|
|
48
58
|
| **Inputs** | project_path [required], mode (code/compose) [auto-detected] |
|
|
49
|
-
| **Gates** | step
|
|
59
|
+
| **Gates** | step 3: Confirm Gate [C] | step 6: Review Gate [C] |
|
|
50
60
|
| **Outputs** | SKILL.md (stack), context-snippet.md, metadata.json |
|
|
51
61
|
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
|
|
62
|
+
| **Exit codes** | See "Exit Codes" below |
|
|
63
|
+
|
|
64
|
+
## Exit Codes
|
|
65
|
+
|
|
66
|
+
Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
|
|
67
|
+
|
|
68
|
+
| Code | Meaning | Raised by |
|
|
69
|
+
| ---- | -------------------- | ------------------------------------------------------------------------------------------ |
|
|
70
|
+
| 0 | success | step 10 (terminal handoff to shared health-check) |
|
|
71
|
+
| 2 | input-missing / input-invalid | step 1 §0 (`config.yaml` missing or malformed); step 2 §2 headless cannot proceed without manifests (S2); step 4 §3 all extractions failed (B7); step 5 §2 feasibility-report `schemaVersion` mismatch; compose-mode-rules `schemaVersion` mismatch |
|
|
72
|
+
| 3 | resolution-failure | step 1 §1 (`forge-tier.yaml` missing); step 2 §0 compose-mode skill resolution corruption (manifest + symlink both fail); step 2 §0 compose-mode zero qualifying skills (S1/S3) |
|
|
73
|
+
| 4 | write-failure | step 7 §1 stage-dir / commit-dir failure; step 7 §1 group-dir collision when an existing non-stack skill occupies the target path |
|
|
74
|
+
| 5 | overwrite-cancelled | step 7 collision when the user declines to replace an existing stack package |
|
|
75
|
+
| 6 | user-cancelled | any interactive menu in step 3 / step 6 (user selected `[X]` Cancel and exit) |
|
|
76
|
+
|
|
77
|
+
## Result Contract (Headless)
|
|
78
|
+
|
|
79
|
+
When `{headless_mode}` is true, step 9 emits a single-line JSON envelope on **stdout** before chaining to step 10, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
SKF_STACK_RESULT_JSON: {"status":"success|error","skill_package":"…|null","skill_name":"…","stack_libraries":["…"],"mode":"code|compose","exit_code":0,"halt_reason":null}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
`status` is `"success"` on the terminal happy path, `"error"` on any HALT. `skill_package` is the absolute path to the committed stack-skill directory (or `null` on error before commit). `skill_name` is the stack skill's published name (e.g. `{project_name}-stack`). `stack_libraries` is the array of library names included in the stack (constituent skill names in compose-mode, dependency names in code-mode). `mode` is `"code"` or `"compose"` per the run's resolved mode. `halt_reason` is one of: `null` (success), `"input-missing"`, `"input-invalid"`, `"forge-tier-missing"`, `"config-missing"`, `"no-manifests"`, `"all-extractions-failed"`, `"schema-version-mismatch"`, `"resolution-failure"`, `"write-failure"`, `"overwrite-cancelled"`, `"user-cancelled"`. `exit_code` matches the table above.
|
|
52
86
|
|
|
53
87
|
## On Activation
|
|
54
88
|
|
|
@@ -61,4 +95,29 @@ These rules apply to every step in this workflow:
|
|
|
61
95
|
3. **Preferences fallback.** Otherwise, read `headless_mode` from `{sidecar_path}/preferences.yaml` (`true` or `false`).
|
|
62
96
|
4. **Default:** `false`.
|
|
63
97
|
|
|
64
|
-
3.
|
|
98
|
+
3. **Resolve workflow customization.** Run:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
python3 {project-root}/_bmad/scripts/resolve_customization.py \
|
|
102
|
+
--skill {skill-root} --key workflow
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):
|
|
106
|
+
|
|
107
|
+
- `{skill-root}/customize.toml` — bundled defaults
|
|
108
|
+
- `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)
|
|
109
|
+
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
110
|
+
|
|
111
|
+
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.
|
|
112
|
+
|
|
113
|
+
Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each of the five scalars, if the merged value is empty or absent, use the bundled default:
|
|
114
|
+
|
|
115
|
+
- `{stackSkillTemplatePath}` ← `workflow.stack_skill_template_path` if non-empty, else `assets/stack-skill-template.md`
|
|
116
|
+
- `{integrationPatternsPath}` ← `workflow.integration_patterns_path` if non-empty, else `references/integration-patterns.md`
|
|
117
|
+
- `{manifestPatternsPath}` ← `workflow.manifest_patterns_path` if non-empty, else `references/manifest-patterns.md`
|
|
118
|
+
- `{composeModeRulesPath}` ← `workflow.compose_mode_rules_path` if non-empty, else `references/compose-mode-rules.md`
|
|
119
|
+
- `{provenanceMapSchemaPath}` ← `workflow.provenance_map_schema_path` if non-empty, else `assets/provenance-map-schema.md`
|
|
120
|
+
|
|
121
|
+
Stash all five as workflow-context variables. Stage files reference `{stackSkillTemplatePath}` / `{integrationPatternsPath}` / `{manifestPatternsPath}` / `{composeModeRulesPath}` / `{provenanceMapSchemaPath}` 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.
|
|
122
|
+
|
|
123
|
+
4. Load, read the full file, and then execute `references/init.md` to begin the workflow.
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
type: static-reference
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# provenance-map.json Schema
|
|
6
|
+
|
|
7
|
+
Canonical schema templates for the workspace `provenance-map.json` artifact written in step 7 §7. Two variants exist — choose by the run's resolved mode:
|
|
8
|
+
|
|
9
|
+
- **code-mode** — when the workflow analyzed a real codebase with manifest files and AST-extracted exports
|
|
10
|
+
- **compose-mode** — when the workflow synthesized a stack from pre-generated constituent skills + an architecture document
|
|
11
|
+
|
|
12
|
+
Both variants share the top-level `provenance_version`, `skill_name`, `skill_type`, `generated_at`, `entries[]`, and `integrations[]` shape. They differ in source-anchor fields (`source_repo` / `source_commit` / `source_ref`), in `entries[].extraction_method` values, in `integrations[].detection_method` values, and in compose-mode's additional `constituents[]` array which enables drift detection via metadata-hash comparison.
|
|
13
|
+
|
|
14
|
+
> **Note:** Per-export entries use the same schema as single skills (see `skill-sections.md`), with `source_library` identifying the originating library. In compose-mode, `constituents[]` enables audit to detect constituent drift via metadata hash comparison.
|
|
15
|
+
|
|
16
|
+
## Code-mode variant
|
|
17
|
+
|
|
18
|
+
Used when the workflow ran in code-mode against an actual codebase. `source_repo` and `source_commit` capture the upstream anchor(s); `entries[].extraction_method` records how each export was discovered (`ast_bridge`, `source_reading`, or `qmd_bridge`). `integrations[].detection_method` is `"co-import grep"` because integration pairs are confirmed by co-import file evidence.
|
|
19
|
+
|
|
20
|
+
```json
|
|
21
|
+
{
|
|
22
|
+
"provenance_version": "2.0",
|
|
23
|
+
"skill_name": "{project_name}-stack",
|
|
24
|
+
"skill_type": "stack",
|
|
25
|
+
"source_repo": ["{repo_url_1}", "{repo_url_2}"],
|
|
26
|
+
"source_commit": {"{repo_1}": "{hash_1}", "{repo_2}": "{hash_2}"},
|
|
27
|
+
"generated_at": "{ISO-8601}",
|
|
28
|
+
"entries": [
|
|
29
|
+
{
|
|
30
|
+
"export_name": "{name}",
|
|
31
|
+
"export_type": "{type}",
|
|
32
|
+
"source_library": "{library-name}",
|
|
33
|
+
"params": [],
|
|
34
|
+
"return_type": "{type}",
|
|
35
|
+
"source_file": "{file}",
|
|
36
|
+
"source_line": 0,
|
|
37
|
+
"confidence": "T1|T1-low|T2",
|
|
38
|
+
"extraction_method": "ast_bridge|source_reading|qmd_bridge",
|
|
39
|
+
"signature_source": "T1|T2|T3"
|
|
40
|
+
}
|
|
41
|
+
],
|
|
42
|
+
"integrations": [
|
|
43
|
+
{
|
|
44
|
+
"libraries": ["{libA}", "{libB}"],
|
|
45
|
+
"pattern_type": "{type}",
|
|
46
|
+
"detection_method": "co-import grep",
|
|
47
|
+
"co_import_files": [{"file": "{path}", "line": 0}],
|
|
48
|
+
"confidence": "T1|T2"
|
|
49
|
+
}
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Compose-mode variant
|
|
55
|
+
|
|
56
|
+
Used when the workflow ran in compose-mode against pre-generated constituent skills. Source-anchor fields (`source_repo`, `source_commit`, `source_ref`) are `null` because there is no codebase to anchor against — provenance traces back to the constituent skills instead, captured in the `constituents[]` array. Each entry's `extraction_method` is `"compose-from-skill"`; integrations have `detection_method` of `"architecture_co_mention"` (named in the architecture doc) or `"inferred_from_shared_domain"` (synthesized inference, must carry T2/T3 confidence).
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"provenance_version": "2.0",
|
|
61
|
+
"skill_name": "{project_name}-stack",
|
|
62
|
+
"skill_type": "stack",
|
|
63
|
+
"source_repo": null,
|
|
64
|
+
"source_commit": null,
|
|
65
|
+
"source_ref": null,
|
|
66
|
+
"generated_at": "{ISO-8601}",
|
|
67
|
+
"entries": [
|
|
68
|
+
{
|
|
69
|
+
"export_name": "{name}",
|
|
70
|
+
"export_type": "{type}",
|
|
71
|
+
"source_library": "{library-name}",
|
|
72
|
+
"params": [],
|
|
73
|
+
"return_type": "{type}",
|
|
74
|
+
"source_file": "{from constituent skill}",
|
|
75
|
+
"source_line": 0,
|
|
76
|
+
"confidence": "T1|T1-low|T2",
|
|
77
|
+
"extraction_method": "compose-from-skill",
|
|
78
|
+
"signature_source": "T1|T2|T3"
|
|
79
|
+
}
|
|
80
|
+
],
|
|
81
|
+
"integrations": [
|
|
82
|
+
{
|
|
83
|
+
"libraries": ["{libA}", "{libB}"],
|
|
84
|
+
"pattern_type": "{type}",
|
|
85
|
+
"detection_method": "architecture_co_mention|inferred_from_shared_domain",
|
|
86
|
+
"co_import_files": [],
|
|
87
|
+
"confidence": "T2|T3"
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"constituents": [
|
|
91
|
+
{
|
|
92
|
+
"skill_name": "{constituent-skill-name}",
|
|
93
|
+
"skill_path": "skills/{skill-dir}/",
|
|
94
|
+
"version": "{version from constituent metadata.json}",
|
|
95
|
+
"composed_at": "{ISO-8601}",
|
|
96
|
+
"metadata_hash": "sha256:{hash of constituent metadata.json}"
|
|
97
|
+
}
|
|
98
|
+
]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Use the `metadata_hash` value already stored in workflow state during step 2 (S13) — do NOT re-read and re-hash at step 7 time. The stored hash captures the state as it was at manifest-detection time, which is the correct provenance anchor.**
|
|
@@ -32,7 +32,7 @@ description: >
|
|
|
32
32
|
|
|
33
33
|
| Library | Imports | Key Exports | Confidence | Reference |
|
|
34
34
|
|---------|---------|-------------|------------|-----------|
|
|
35
|
-
| {name} | {count} | {top_exports} | {tier} | [ref](
|
|
35
|
+
| {name} | {count} | {top_exports} | {tier} | [ref](references/{name}.md) |
|
|
36
36
|
|
|
37
37
|
## Per-Library Summaries
|
|
38
38
|
|