bmad-module-skill-forge 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/.nvmrc +1 -1
- package/docs/_data/pinned.yaml +1 -1
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +2 -2
- package/src/shared/scripts/skf-comention-pairs.py +350 -0
- package/src/shared/scripts/skf-count-tokens.py +222 -0
- package/src/shared/scripts/skf-detect-docs.py +232 -1
- package/src/shared/scripts/skf-detect-language.py +77 -0
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-find-cycles.py +246 -0
- package/src/shared/scripts/skf-hash-content.py +487 -2
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
- package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
- package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
- package/src/shared/scripts/skf-shard-body.py +461 -0
- package/src/shared/scripts/skf-skill-inventory.py +139 -3
- package/src/shared/scripts/skf-structural-diff.py +307 -67
- package/src/shared/scripts/skf-validate-brief-schema.py +39 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
- package/src/shared/scripts/skf-validate-output.py +443 -10
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/customize.toml +2 -0
- package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
- package/src/skf-analyze-source/references/continue.md +8 -13
- package/src/skf-analyze-source/references/generate-briefs.md +28 -12
- package/src/skf-analyze-source/references/headless-contract.md +33 -0
- package/src/skf-analyze-source/references/health-check.md +1 -2
- package/src/skf-analyze-source/references/identify-units.md +25 -36
- package/src/skf-analyze-source/references/init.md +12 -25
- package/src/skf-analyze-source/references/map-and-detect.md +8 -20
- package/src/skf-analyze-source/references/recommend.md +4 -14
- package/src/skf-analyze-source/references/scan-project.md +3 -11
- package/src/skf-analyze-source/references/step-auto-scope.md +42 -180
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
- package/src/skf-audit-skill/SKILL.md +9 -6
- package/src/skf-audit-skill/customize.toml +2 -0
- package/src/skf-audit-skill/references/init.md +58 -32
- package/src/skf-audit-skill/references/re-index.md +15 -34
- package/src/skf-audit-skill/references/report.md +11 -58
- package/src/skf-audit-skill/references/semantic-diff.md +4 -22
- package/src/skf-audit-skill/references/severity-classify.md +53 -87
- package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
- package/src/skf-audit-skill/references/structural-diff.md +43 -68
- package/src/skf-brief-skill/SKILL.md +7 -36
- package/src/skf-brief-skill/assets/scope-templates.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +6 -14
- package/src/skf-brief-skill/references/confirm-brief.md +2 -14
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +19 -22
- package/src/skf-brief-skill/references/headless-args.md +1 -1
- package/src/skf-brief-skill/references/health-check.md +1 -22
- package/src/skf-brief-skill/references/invocation-contract.md +37 -0
- package/src/skf-brief-skill/references/scope-definition.md +4 -14
- package/src/skf-brief-skill/references/step-auto-brief.md +1 -5
- package/src/skf-brief-skill/references/step-auto-validate.md +1 -5
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +17 -10
- package/src/skf-campaign/SKILL.md +15 -84
- package/src/skf-campaign/customize.toml +2 -0
- package/src/skf-campaign/manifest.yaml +4 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +14 -103
- package/src/skf-campaign/references/step-01-setup.md +4 -5
- package/src/skf-campaign/references/step-02-strategy.md +8 -3
- package/src/skf-campaign/references/step-03-pins.md +1 -1
- package/src/skf-campaign/references/step-04-provenance.md +1 -1
- package/src/skf-campaign/references/step-05-skill-loop.md +1 -1
- package/src/skf-campaign/references/step-06-batch.md +7 -6
- package/src/skf-campaign/references/step-11-maintenance.md +2 -2
- package/src/skf-campaign/references/step-resume.md +9 -8
- package/src/skf-campaign/scripts/campaign-deps.py +10 -1
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +1 -1
- package/src/skf-create-skill/SKILL.md +14 -3
- package/src/skf-create-skill/assets/compile-assembly-rules.md +17 -38
- package/src/skf-create-skill/assets/skill-sections.md +9 -100
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
- package/src/skf-create-skill/customize.toml +13 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
- package/src/skf-create-skill/references/compile.md +34 -47
- package/src/skf-create-skill/references/component-extraction.md +8 -35
- package/src/skf-create-skill/references/ecosystem-check.md +9 -25
- package/src/skf-create-skill/references/enrich.md +4 -17
- package/src/skf-create-skill/references/extract.md +14 -29
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +7 -7
- package/src/skf-create-skill/references/generate-artifacts.md +9 -23
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +12 -15
- package/src/skf-create-skill/references/source-resolution-protocols.md +3 -3
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +30 -12
- package/src/skf-create-skill/references/step-doc-sources.md +2 -2
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +8 -50
- package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
- package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
- package/src/skf-create-skill/references/validate.md +59 -28
- package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
- package/src/skf-create-stack-skill/SKILL.md +15 -9
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +10 -0
- package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
- package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
- package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
- package/src/skf-create-stack-skill/references/generate-output.md +24 -75
- package/src/skf-create-stack-skill/references/init.md +9 -81
- package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
- package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
- package/src/skf-create-stack-skill/references/report.md +27 -62
- package/src/skf-create-stack-skill/references/validate.md +35 -31
- package/src/skf-drop-skill/SKILL.md +20 -23
- package/src/skf-drop-skill/customize.toml +10 -0
- package/src/skf-drop-skill/references/execute.md +51 -31
- package/src/skf-drop-skill/references/headless-contract.md +18 -0
- package/src/skf-drop-skill/references/health-check.md +1 -13
- package/src/skf-drop-skill/references/report.md +42 -10
- package/src/skf-drop-skill/references/select.md +88 -48
- package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
- package/src/skf-export-skill/SKILL.md +17 -14
- package/src/skf-export-skill/assets/managed-section-format.md +2 -5
- package/src/skf-export-skill/customize.toml +10 -6
- package/src/skf-export-skill/references/generate-snippet.md +21 -35
- package/src/skf-export-skill/references/load-skill.md +44 -42
- package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
- package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
- package/src/skf-export-skill/references/package.md +27 -33
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
- package/src/skf-export-skill/references/result-envelope.md +28 -0
- package/src/skf-export-skill/references/summary.md +11 -5
- package/src/skf-export-skill/references/token-report.md +42 -24
- package/src/skf-export-skill/references/update-context.md +32 -33
- package/src/skf-forger/SKILL.md +27 -39
- package/src/skf-forger/references/pipeline-mode.md +34 -0
- package/src/skf-forger/scripts/parse-pipeline.py +270 -0
- package/src/skf-quick-skill/SKILL.md +10 -60
- package/src/skf-quick-skill/customize.toml +9 -0
- package/src/skf-quick-skill/references/batch-mode.md +6 -4
- package/src/skf-quick-skill/references/compile.md +15 -52
- package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
- package/src/skf-quick-skill/references/finalize.md +12 -6
- package/src/skf-quick-skill/references/halt-contract.md +54 -0
- package/src/skf-quick-skill/references/health-check.md +3 -4
- package/src/skf-quick-skill/references/quick-extract.md +7 -18
- package/src/skf-quick-skill/references/registry-resolution.md +1 -23
- package/src/skf-quick-skill/references/resolve-target.md +27 -34
- package/src/skf-quick-skill/references/write-and-validate.md +10 -25
- package/src/skf-refine-architecture/SKILL.md +14 -7
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +9 -7
- package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
- package/src/skf-refine-architecture/references/health-check.md +1 -1
- package/src/skf-refine-architecture/references/improvements.md +9 -25
- package/src/skf-refine-architecture/references/init.md +9 -16
- package/src/skf-refine-architecture/references/issue-detection.md +10 -25
- package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
- package/src/skf-refine-architecture/references/report.md +13 -10
- package/src/skf-rename-skill/SKILL.md +11 -21
- package/src/skf-rename-skill/customize.toml +10 -0
- package/src/skf-rename-skill/references/execute.md +107 -78
- package/src/skf-rename-skill/references/exit-codes.md +12 -0
- package/src/skf-rename-skill/references/report.md +16 -8
- package/src/skf-rename-skill/references/select.md +69 -42
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
- package/src/skf-setup/SKILL.md +20 -12
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +9 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +6 -8
- package/src/skf-setup/references/report.md +22 -31
- package/src/skf-setup/references/tier-rules.md +2 -32
- package/src/skf-setup/references/write-config.md +9 -10
- package/src/skf-test-skill/SKILL.md +10 -8
- package/src/skf-test-skill/customize.toml +2 -0
- package/src/skf-test-skill/references/coherence-check.md +19 -31
- package/src/skf-test-skill/references/coverage-check.md +109 -75
- package/src/skf-test-skill/references/detect-mode.md +10 -41
- package/src/skf-test-skill/references/external-validators.md +11 -19
- package/src/skf-test-skill/references/init.md +38 -20
- package/src/skf-test-skill/references/migration-section-rules.md +4 -4
- package/src/skf-test-skill/references/report.md +60 -40
- package/src/skf-test-skill/references/score.md +32 -64
- package/src/skf-test-skill/references/scoring-rules.md +6 -62
- package/src/skf-test-skill/references/source-access-protocol.md +6 -6
- package/src/skf-test-skill/references/step-hard-gate.md +1 -3
- package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
- package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
- package/src/skf-test-skill/scripts/compute-score.py +131 -1
- package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
- package/src/skf-update-skill/SKILL.md +17 -5
- package/src/skf-update-skill/customize.toml +14 -0
- package/src/skf-update-skill/references/detect-changes.md +19 -37
- package/src/skf-update-skill/references/health-check.md +3 -9
- package/src/skf-update-skill/references/init.md +39 -32
- package/src/skf-update-skill/references/manual-section-rules.md +1 -2
- package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
- package/src/skf-update-skill/references/merge.md +13 -57
- package/src/skf-update-skill/references/re-extract.md +12 -24
- package/src/skf-update-skill/references/report.md +14 -7
- package/src/skf-update-skill/references/validate.md +32 -30
- package/src/skf-update-skill/references/write.md +86 -51
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
- package/src/skf-verify-stack/SKILL.md +11 -21
- package/src/skf-verify-stack/customize.toml +12 -3
- package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
- package/src/skf-verify-stack/references/coverage.md +21 -10
- package/src/skf-verify-stack/references/exit-codes.md +14 -0
- package/src/skf-verify-stack/references/health-check.md +1 -1
- package/src/skf-verify-stack/references/init.md +20 -25
- package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
- package/src/skf-verify-stack/references/integrations.md +44 -49
- package/src/skf-verify-stack/references/report.md +28 -34
- package/src/skf-verify-stack/references/requirements.md +3 -3
- package/src/skf-verify-stack/references/synthesize.md +36 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'compile-stack.md'
|
|
3
|
-
integrationPatterns: 'references/integration-patterns.md'
|
|
4
|
-
composeModeRules: 'references/compose-mode-rules.md'
|
|
5
3
|
pairIntersectProbeOrder:
|
|
6
4
|
- '{project-root}/_bmad/skf/shared/scripts/skf-pair-intersect.py'
|
|
7
5
|
- '{project-root}/src/shared/scripts/skf-pair-intersect.py'
|
|
6
|
+
comentionProbeOrder:
|
|
7
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-comention-pairs.py'
|
|
8
|
+
- '{project-root}/src/shared/scripts/skf-comention-pairs.py'
|
|
9
|
+
validateFeasibilityReportProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-feasibility-report.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-validate-feasibility-report.py'
|
|
8
12
|
---
|
|
9
13
|
|
|
10
14
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -19,7 +23,6 @@ Analyze co-import patterns between confirmed libraries to identify integration p
|
|
|
19
23
|
|
|
20
24
|
- Focus on detecting cross-library patterns using subprocess Pattern 1 (grep/search)
|
|
21
25
|
- Do not compile SKILL.md (Step 06)
|
|
22
|
-
- Integration detection is the core differentiator of stack skills vs individual skills
|
|
23
26
|
|
|
24
27
|
## MANDATORY SEQUENCE
|
|
25
28
|
|
|
@@ -54,7 +57,7 @@ From `confirmed_dependencies`, conceptually you have N*(N-1)/2 unordered pairs.
|
|
|
54
57
|
`pairs[]` is sorted by `intersection_count` DESC, then `(a, b)` ASC for stable ordering. Default Top-K cap is **20** (matches S7 below); pass `--top-k N` to override.
|
|
55
58
|
3. **Parse the JSON result** and use `pairs[]` as the qualifying-pair set for §2 onward. The `intersection_count` is the candidate file count for the §2 2-file threshold pre-grep; `files[]` is the grep-scope for that pair.
|
|
56
59
|
|
|
57
|
-
**Top-K cap (S7, 20):** If the script's response has `truncated: true`, more pairs than the cap had non-empty intersections. Surface a user-visible warning composed as: `"non-empty-intersection pair count {total_pairs} exceeds cap — analyzing top 20 by intersection size; {total_pairs - 20} pairs skipped"`. Record this cap in the evidence report. (Tie-break by intersection size is what the script sorts on; if you need to override the cap intentionally, pass `--top-k N` and document the rationale.) The
|
|
60
|
+
**Top-K cap (S7, 20):** If the script's response has `truncated: true`, more pairs than the cap had non-empty intersections. Surface a user-visible warning composed as: `"non-empty-intersection pair count {total_pairs} exceeds cap — analyzing top 20 by intersection size; {total_pairs - 20} pairs skipped"`. Record this cap in the evidence report. (Tie-break by intersection size is what the script sorts on; if you need to override the cap intentionally, pass `--top-k N` and document the rationale.) The cap is a second-order safety limit, not a primary strategy — the file-intersection prune does the bulk of the work.
|
|
58
61
|
|
|
59
62
|
Report: "**Analyzing {pair_count} library pairs for integration patterns** (pruned from {N*(N-1)/2} via file-list intersection; {capped_count} after Top-K if applicable)**...**"
|
|
60
63
|
|
|
@@ -64,29 +67,54 @@ Report: "**Analyzing {pair_count} library pairs for integration patterns** (prun
|
|
|
64
67
|
|
|
65
68
|
Instead of co-import grep, detect integrations from architecture document:
|
|
66
69
|
|
|
67
|
-
1. Load `{
|
|
70
|
+
1. Load `{composeModeRulesPath}` for integration evidence format rules
|
|
68
71
|
2. **If `{architecture_doc_path}` is null or not available:** Skip directly to the "If no architecture document available" fallback below
|
|
69
|
-
3.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
3. **Compute qualifying co-mention pairs deterministically via the shared script.** The precision guards (word-boundary matching `\b{skill_name}\b` case-insensitive to reject substrings like `react` inside `reactive`; H1/H2 section exclusion for headers that normalise to `introduction`, `overview`, `glossary`, `table of contents`, `references`, `appendix`, or `index`, with heading text itself never a co-mention source; and the ≥2-distinct-body-paragraph gate) are a scan-and-count with one correct answer per `(architecture_doc, skill-name-set)` — do not perform them in-prompt. Risks and rationale stay documented in `{composeModeRulesPath}` under "Compose-mode co-mention precision".
|
|
73
|
+
|
|
74
|
+
**Resolve `{comentionHelper}`** from `{comentionProbeOrder}`; first existing path wins.
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv run {comentionHelper} comention --doc {architecture_doc_path} --skills -
|
|
78
|
+
```
|
|
79
|
+
piping the loaded skill names — the `confirmed_dependencies` names — as a JSON array on stdin (e.g. `["react", "express"]`; use a temp file under `{forge_data_folder}/` if stdin piping is unavailable). The script emits:
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"pairs": [
|
|
83
|
+
{"a": "<skill>", "b": "<skill>", "paragraph_count": N,
|
|
84
|
+
"evidence": [{"header": "<governing-header-or-null>", "excerpt": "<text>"}, ...]},
|
|
85
|
+
...
|
|
86
|
+
],
|
|
87
|
+
"excluded_section_count": M
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
`pairs[]` contains only qualifying pairs (≥2 distinct body paragraphs), sorted by `paragraph_count` DESC then `(a, b)` ASC. Use `pairs[]` as the detected-integration-pair set for step 4 onward; each pair's `evidence[]` supplies the governing header and paragraph excerpts to quote as architecture-reference evidence.
|
|
91
|
+
|
|
92
|
+
**Graceful degradation:** if no `{comentionProbeOrder}` candidate exists (e.g. `uv` unavailable on claude.ai web), perform the equivalent scan directly per the guards above and the script's `--help` contract, then proceed with the same qualifying-pair set.
|
|
93
|
+
4. For each detected integration pair (from `pairs[]`):
|
|
76
94
|
- Load both skills' export lists and API signatures
|
|
77
|
-
- Compose an integration section following the format from `{
|
|
95
|
+
- Compose an integration section following the format from `{composeModeRulesPath}`
|
|
78
96
|
- Include VS feasibility verdict if a feasibility report matching the filename pattern defined in `src/shared/references/feasibility-report-schema.md` exists under `{forge_data_folder}/` (timestamped `feasibility-report-{project_slug}-{YYYYMMDD-HHmmss}.md` or the stable `feasibility-report-{project_slug}-latest.md` copy). Schema version `"1.0"` is required; see the schema for the full contract.
|
|
79
97
|
- Cite evidence from both skills: `[from skill: {skill_name}]`
|
|
80
98
|
|
|
81
|
-
All integration evidence inherits confidence tiers from the source skills. Load and apply the full **Confidence Tier Inheritance** matrix from `{
|
|
99
|
+
All integration evidence inherits confidence tiers from the source skills. Load and apply the full **Confidence Tier Inheritance** matrix from `{composeModeRulesPath}` to compute the correct tier for each pair (covers T1+T1, T1+T1-low, T1-low+T1-low, T1+T2, T1-low+T2, T2+T2 cases). Apply the `[composed]` suffix to all confidence labels — e.g., `T1 [composed]`, `T1-low [composed, +T2 annotations]`.
|
|
82
100
|
|
|
83
101
|
**VS verdict parsing (if feasibility report exists):** The feasibility report format is defined by the shared schema at `src/shared/references/feasibility-report-schema.md` (single source of truth; skf-verify-stack is the producer, this skill is the consumer). Follow the schema strictly:
|
|
84
102
|
|
|
85
103
|
- Locate the report via the filename pattern in the schema: `{forge_data_folder}/feasibility-report-{project_slug}-{YYYYMMDD-HHmmss}.md` (or the stable `feasibility-report-{project_slug}-latest.md` copy next to it).
|
|
86
|
-
- **Schema version guard
|
|
104
|
+
- **Schema version guard (deterministic gate):** Resolve `{validateFeasibilityReportHelper}` from `{validateFeasibilityReportProbeOrder}` (first existing path wins) and run it against the located report:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
python3 {validateFeasibilityReportHelper} <located-report-path>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Consume `schemaVersionOk` / `schemaVersionFound` from its JSON. If `schemaVersionOk` is false, HALT with `"feasibility-report schemaVersion mismatch: expected '1.0', got '{schemaVersionFound}' — refusing to proceed"`, then emit the result envelope on stderr per the Result Contract in SKILL.md and exit `2`. The script's structural findings (`headingsOk` / `orderViolations`) are advisory for this consumer — it gates only on schemaVersion. **If the helper does not resolve or cannot run,** parse the report's YAML frontmatter directly and compare `schemaVersion` to the literal `1.0`, applying the same HALT (a missing or mismatched version halts identically). Unknown versions are never interpreted.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":2,"halt_reason":"schema-version-mismatch"}
|
|
114
|
+
```
|
|
87
115
|
- Read `overallVerdict` from frontmatter (exactly one of `FEASIBLE|CONDITIONALLY_FEASIBLE|NOT_FEASIBLE`).
|
|
88
116
|
- Parse the `## Integration Verdicts` markdown table for per-pair verdicts (exactly one of `Verified|Plausible|Risky|Blocked`). Any unknown verdict token is a hard error per the schema — do not silently drop or map.
|
|
89
|
-
- For each architecture-detected pair, include `VS overall: {overallVerdict}` and `VS pair: {verdict}` in the integration evidence per the format in `{
|
|
117
|
+
- For each architecture-detected pair, include `VS overall: {overallVerdict}` and `VS pair: {verdict}` in the integration evidence per the format in `{composeModeRulesPath}`. VS verdicts do not apply to inferred integrations since the VS report operates on architecture-described interactions only. Additionally, flag any pairs where VS reported `Risky` or `Blocked` by appending a `[VS: Risky]` or `[VS: Blocked]` warning annotation to the integration entry.
|
|
90
118
|
|
|
91
119
|
If no architecture document available:
|
|
92
120
|
- Infer potential integrations from skills sharing the same `language` field or sharing domain keywords in their SKILL.md descriptions (use the `usage_patterns` and `exports` fields from `per_library_extractions[]` built in step 4, or reload SKILL.md from the version-aware path: use `skill_package_path` from step 2, or resolve via `{skills_output_folder}/{skill_dir}/active/{skill_dir}/SKILL.md` — see `knowledge/version-paths.md`)
|
|
@@ -115,7 +143,7 @@ If `tools.ccc` is true AND `ccc_index.status` is `"fresh"` or `"stale"` in forge
|
|
|
115
143
|
|
|
116
144
|
For each library pair with **0 or 1 co-import files** (below the 2-file threshold — S9, symmetric to give the 0-hit case the same chance as the 1-hit case), run `ccc_bridge.search("{libA} {libB}", source_root, top_k=10)` to find files where the two libraries interact semantically — even without explicit import co-location. If CCC returns additional files where both libraries appear, add them to the pair's co-import candidate list and re-evaluate against the 2-file threshold.
|
|
117
145
|
|
|
118
|
-
**CCC precision guard for 1-file pairs (H3):** When a CCC hit would elevate a 1-file pair to qualifying status, run a post-hoc verification on that file: re-grep the file and confirm it contains explicit import statements for **both** libraries (per the ecosystem import patterns from `
|
|
146
|
+
**CCC precision guard for 1-file pairs (H3):** When a CCC hit would elevate a 1-file pair to qualifying status, run a post-hoc verification on that file: re-grep the file and confirm it contains explicit import statements for **both** libraries (per the ecosystem import patterns from `{manifestPatternsPath}`). If either import is missing (e.g., one library is only name-dropped in a comment or string), drop the CCC-added file from the candidate list. Only pairs with ≥2 files that each contain explicit imports for both libraries qualify. Log rejected CCC candidates in workflow state for the evidence report.
|
|
119
147
|
|
|
120
148
|
**Tool resolution for ccc_bridge.search:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `ccc search "{libA} {libB}" --path {source_root} --top 10` (CLI). See `knowledge/tool-resolution.md`.
|
|
121
149
|
|
|
@@ -125,16 +153,9 @@ CCC failures: skip augmentation silently, proceed with grep-only results.
|
|
|
125
153
|
|
|
126
154
|
### 3. Classify Integration Types
|
|
127
155
|
|
|
128
|
-
Load `{
|
|
156
|
+
Load `{integrationPatternsPath}` for classification rules.
|
|
129
157
|
|
|
130
|
-
For each qualifying pair, analyze to classify the integration type (**in compose-mode**: all architecture-document-detected pairs qualify automatically — the 2+ co-import file threshold applies only in code-mode; **in code-mode**: pair must have 2+ co-import files):
|
|
131
|
-
|
|
132
|
-
- **Type 1: Middleware Chain** — Sequential function calls piping output between libraries
|
|
133
|
-
- **Type 2: Shared Types** — Type definitions exchanged between libraries
|
|
134
|
-
- **Type 3: Configuration Bridge** — One library configuring or initializing another
|
|
135
|
-
- **Type 4: Event Handler** — Event patterns crossing library boundaries
|
|
136
|
-
- **Type 5: Adapter/Wrapper** — Thin wrapper connecting library interfaces
|
|
137
|
-
- **Type 6: State Sharing** — Shared state stores or context providers
|
|
158
|
+
For each qualifying pair, analyze to classify the integration type against those pattern types (**in compose-mode**: all architecture-document-detected pairs qualify automatically — the 2+ co-import file threshold applies only in code-mode; **in code-mode**: pair must have 2+ co-import files):
|
|
138
159
|
|
|
139
160
|
For each detected integration:
|
|
140
161
|
- Identify the top 3 files demonstrating the pattern
|
|
@@ -145,7 +166,7 @@ For each detected integration:
|
|
|
145
166
|
- `architecture-co-mention` — compose-mode pair qualified via word-boundary co-mention in the architecture document (per §2 H2 guards). Maps to `detection_method: architecture_co_mention` in `provenance-map.json`.
|
|
146
167
|
- `constituent-documented-contract` — compose-mode pair whose cross-library contract is documented in a constituent skill's integration docs (cited, e.g. a grep-verified upstream seam) but not co-mentioned in the architecture document. Maps to `detection_method: constituent_documented_contract` in `provenance-map.json`.
|
|
147
168
|
- `inferred-shared-domain` — compose-mode pair without an architecture document, inferred from shared `language` or domain keywords (no cited contract). Maps to `detection_method: inferred_from_shared_domain` in `provenance-map.json`.
|
|
148
|
-
- Render as `{tier} ({qualifier})` — e.g., `T1-low (grep-co-import)`, `T1 (ccc-augmented)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `
|
|
169
|
+
- Render as `{tier} ({qualifier})` — e.g., `T1-low (grep-co-import)`, `T1 (ccc-augmented)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `{composeModeRulesPath}` is appended after the qualifier in compose-mode.
|
|
149
170
|
|
|
150
171
|
**Provenance ↔ SKILL.md tier parity:** The tier derived above is the single value for this edge — write the *same* tier to both the SKILL.md integration label and `provenance-map.json` `integrations[].confidence`. The detection-method qualifier (and the `provenance-map.json` `detection_method` it maps to) records *how* the edge was found and is orthogonal to confidence; it never forces the tier into a fixed band.
|
|
151
172
|
|
|
@@ -159,33 +180,7 @@ Assemble the integration graph:
|
|
|
159
180
|
|
|
160
181
|
### 5. Display Integration Summary
|
|
161
182
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
"**Integration detection complete.**
|
|
165
|
-
|
|
166
|
-
**Integration graph:** {lib_count} libraries, {pair_count} integration pairs
|
|
167
|
-
|
|
168
|
-
**Hub libraries** (connected to 3+ others):
|
|
169
|
-
{For each hub:} - **{library}** — integrates with {partner_list}
|
|
170
|
-
|
|
171
|
-
**Detected integrations:**
|
|
172
|
-
| Library A | Library B | Type | Co-import Files | Confidence |
|
|
173
|
-
|-----------|-----------|------|-----------------|------------|
|
|
174
|
-
| {name} | {name} | {type} | {count} | {tier} |
|
|
175
|
-
|
|
176
|
-
{If cross-cutting patterns:}
|
|
177
|
-
**Cross-cutting patterns:**
|
|
178
|
-
- {description spanning 3+ libraries}
|
|
179
|
-
|
|
180
|
-
**Proceeding to stack compilation...**"
|
|
181
|
-
|
|
182
|
-
**If no integrations detected:**
|
|
183
|
-
|
|
184
|
-
"**No co-import integration patterns detected** between confirmed libraries.
|
|
185
|
-
|
|
186
|
-
The libraries in this project appear to operate independently. The stack skill will contain library summaries without an integration layer.
|
|
187
|
-
|
|
188
|
-
**Proceeding to stack compilation...**"
|
|
183
|
+
If integrations were detected, report the integration graph (`{lib_count}` libraries, `{pair_count}` pairs): the hub libraries (connected to 3+ others) with their partners, each detected pair (library A, library B, type, co-import file count, confidence tier), and any cross-cutting patterns spanning 3+ libraries. If none were detected, report that no co-import integration patterns were found — the libraries appear to operate independently, so the stack skill will carry library summaries without an integration layer.
|
|
189
184
|
|
|
190
185
|
### 6. Auto-Proceed to Next Step
|
|
191
186
|
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'rank-and-confirm.md'
|
|
3
|
-
manifestPatterns: 'references/manifest-patterns.md'
|
|
4
3
|
scanManifestsProbeOrder:
|
|
5
4
|
- '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
|
|
6
5
|
- '{project-root}/src/shared/scripts/skf-scan-manifests.py'
|
|
6
|
+
enumerateStackSkillsProbeOrder:
|
|
7
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-enumerate-stack-skills.py'
|
|
8
|
+
- '{project-root}/src/shared/scripts/skf-enumerate-stack-skills.py'
|
|
7
9
|
---
|
|
8
10
|
|
|
9
11
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -26,7 +28,7 @@ Scan the project root for dependency manifest files, parse each to extract depen
|
|
|
26
28
|
|
|
27
29
|
**If `compose_mode` is true AND `explicit_deps` was provided in step 01:**
|
|
28
30
|
|
|
29
|
-
Use the explicit dependency list directly. Store the explicit list as `raw_dependencies` with `source: "explicit"` and skip to [Auto-Proceed to Next Step](#
|
|
31
|
+
Use the explicit dependency list directly. Store the explicit list as `raw_dependencies` with `source: "explicit"` and skip to [Auto-Proceed to Next Step](#4-auto-proceed-to-next-step).
|
|
30
32
|
|
|
31
33
|
**If `compose_mode` is true AND `explicit_deps` was NOT provided:**
|
|
32
34
|
|
|
@@ -39,7 +41,11 @@ Discover skills in `{skills_output_folder}` using version-aware resolution — s
|
|
|
39
41
|
**Stale manifest fallback (H6):** If a manifest entry resolves to a path that does not exist (broken `active_version`, deleted version dir, missing `SKILL.md` / `metadata.json`), do NOT HALT for that single entry. Instead:
|
|
40
42
|
a. Fall back to the symlink scan (rule 2) **for that one skill only**: probe `{skills_output_folder}/{skill-name}/active/{skill-name}/SKILL.md`.
|
|
41
43
|
b. If the symlink-based path resolves, use it and log a warning: `"export-manifest entry '{skill-name}' is stale — resolved via active symlink instead"`.
|
|
42
|
-
c. If BOTH the manifest path AND the symlink path fail, only then HALT with a manifest-corruption diagnostic naming the affected skill and pointing the user at `[SKF-update-skill]` to repair.
|
|
44
|
+
c. If BOTH the manifest path AND the symlink path fail, only then HALT with a manifest-corruption diagnostic naming the affected skill and pointing the user at `[SKF-update-skill]` to repair. Emit the result envelope on stderr per the Result Contract in SKILL.md, then STOP:
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":3,"halt_reason":"resolution-failure"}
|
|
48
|
+
```
|
|
43
49
|
|
|
44
50
|
**Manifest JSON parse guard (B3):** Wrap the `.export-manifest.json` parse in try/except. If JSON parsing fails for any reason, fall through entirely to the `active` symlink scan (rule 2) across all skills; log a warning and validate each symlink target exists before including it.
|
|
45
51
|
|
|
@@ -53,26 +59,33 @@ Discover skills in `{skills_output_folder}` using version-aware resolution — s
|
|
|
53
59
|
|
|
54
60
|
Maintain a **visited set keyed by `skill_dir`** (the top-level dir under `{skills_output_folder}`) while resolving. If a skill would be revisited via a circular reference (e.g., a constituent that claims another stack as dependency), skip the duplicate and log a warning `"cycle detected at {skill_dir} — skipping"`. Stack skills must not be loaded as source dependencies to avoid self-referencing loops.
|
|
55
61
|
|
|
56
|
-
**If zero skills remain after filtering:** HALT with: "**Cannot proceed in compose-mode.** No individual skills found in `{skills_output_folder}` (after filtering stack skills). Run [CS] Create Skill or [QS] Quick Skill to generate individual skills first, then re-run [SS]."
|
|
62
|
+
**If zero skills remain after filtering:** HALT with: "**Cannot proceed in compose-mode.** No individual skills found in `{skills_output_folder}` (after filtering stack skills). Run [CS] Create Skill or [QS] Quick Skill to generate individual skills first, then re-run [SS]." Then emit the result envelope on stderr per the Result Contract in SKILL.md, and STOP:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":3,"halt_reason":"resolution-failure"}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Deterministic metadata hashing (S13) — script-driven:** Do NOT compute `sha256` in-prompt (a model cannot reproduce a digest, so a hand-computed hash would false-diverge against step 4's script-computed hash). Invoke the same enumeration helper step 4 §0 uses to obtain every constituent's `metadata_hash` in one deterministic call:
|
|
69
|
+
|
|
70
|
+
**Resolve `{enumerateStackSkillsHelper}`** from `{enumerateStackSkillsProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
uv run {enumerateStackSkillsHelper} enumerate {skills_output_folder}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Key the emitted `skills[].metadata_hash` (a `sha256:`-prefixed digest of the raw `metadata.json`, or `null` when no metadata.json is present) by `skills[].name` for use in rule 5 below. The script's `name` is the top-level subdirectory under `{skills_output_folder}` — i.e. the `skill_dir` captured in rule 3, not the metadata `name` — so join on `skill_dir`.
|
|
57
77
|
|
|
58
78
|
For each skill found:
|
|
59
79
|
1. Read `metadata.json` from the resolved version-aware path (`{skill_package}` or `{active_skill}`). **Skill-type gate (S1):** the sibling `metadata.json` MUST be present AND parseable AND contain a `skill_type` field whose value is one of the known set (`skill`, `stack`, or any future values explicitly recognised by this workflow). Directories lacking a qualifying `metadata.json`/`skill_type` are NOT treated as skills — log `"{dir_name}: not a skill (no valid metadata.json/skill_type) — excluding"` and skip.
|
|
60
80
|
2. Extract: name, language, confidence_tier, source_repo, exports count, version
|
|
61
81
|
3. Store the skill group directory name as `skill_dir` (the top-level name under `{skills_output_folder}`, distinct from `name` — the directory may differ from the metadata name)
|
|
62
82
|
4. Store the resolved package path as `skill_package_path` for use in later steps
|
|
63
|
-
5. **
|
|
83
|
+
5. **Record the constituent metadata_hash (S13):** take this skill's `metadata_hash` from the enumerate-script inventory above (matched on `skill_dir`) and store it in workflow state alongside `skill_package_path`. The script is the single source of this hash — never hand-compute — so the step-4 drift check compares script-hash to script-hash and never false-positives on a model recomputation. Step-07 uses this stored hash (not a re-read) for `constituents[].metadata_hash` in `provenance-map.json`, so drift between step 2 read and step 7 write is captured.
|
|
64
84
|
6. Store as `raw_dependencies` with source: "existing_skill"
|
|
65
85
|
|
|
66
|
-
|
|
67
|
-
"**Loaded {N} existing skills as dependencies.**
|
|
68
|
-
|
|
69
|
-
| Skill | Language | Tier | Exports | Source |
|
|
70
|
-
|-------|----------|------|---------|--------|
|
|
71
|
-
| {name} | {lang} | {tier} | {count} | {repo} |
|
|
72
|
-
|
|
73
|
-
**Proceeding to scope confirmation...**"
|
|
86
|
+
Report the `{N}` loaded skills — for each: name, language, confidence tier, export count, and source.
|
|
74
87
|
|
|
75
|
-
Skip to [Auto-Proceed to Next Step](#
|
|
88
|
+
Skip to [Auto-Proceed to Next Step](#4-auto-proceed-to-next-step) — this loaded-skills summary serves as the detection summary.
|
|
76
89
|
|
|
77
90
|
**If not compose_mode:** Continue with section 1 (existing flow).
|
|
78
91
|
|
|
@@ -84,7 +97,7 @@ Skip to [Auto-Proceed to Next Step](#5-auto-proceed-to-next-step) — the skills
|
|
|
84
97
|
|
|
85
98
|
**Dependencies:** {explicit_deps_count} libraries provided"
|
|
86
99
|
|
|
87
|
-
Store the explicit list as `raw_dependencies` and skip to [Display Detection Summary](#
|
|
100
|
+
Store the explicit list as `raw_dependencies` and skip to [Display Detection Summary](#3-display-detection-summary).
|
|
88
101
|
|
|
89
102
|
**If no explicit list:** Continue to section 2.
|
|
90
103
|
|
|
@@ -98,7 +111,7 @@ Invoke the deterministic manifest scanner — it walks the project root, parses
|
|
|
98
111
|
uv run {scanManifestsHelper} scan {scan_root}
|
|
99
112
|
```
|
|
100
113
|
|
|
101
|
-
Where `{scan_root}` is the project root path. Load `{
|
|
114
|
+
Where `{scan_root}` is the project root path. Load `{manifestPatternsPath}` for the ecosystem reference table that documents supported filenames, dependency keys, and normalisation rules; the script implements exactly that table (npm/pnpm/yarn, python pip/poetry/pdm, rust cargo, go modules, java/kotlin maven + gradle, ruby bundler, composer, swift package manager). Exclusion patterns (`node_modules/`, `.venv/`, `vendor/`, `dist/`, `build/`, `target/`, `.git/`, hidden dirs) are applied internally.
|
|
102
115
|
|
|
103
116
|
Parse the JSON output — shape:
|
|
104
117
|
|
|
@@ -116,7 +129,11 @@ Parse the JSON output — shape:
|
|
|
116
129
|
|
|
117
130
|
If `manifests` is empty:
|
|
118
131
|
|
|
119
|
-
**Headless auto-cancel (S2):** If `{headless_mode}` is true, do NOT wait for user input. Emit
|
|
132
|
+
**Headless auto-cancel (S2):** If `{headless_mode}` is true, do NOT wait for user input. Emit the result envelope on stderr per the Result Contract in SKILL.md and exit `2`. Headless mode cannot proceed without an explicit dependency list.
|
|
133
|
+
|
|
134
|
+
```
|
|
135
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"code","exit_code":2,"halt_reason":"no-manifests"}
|
|
136
|
+
```
|
|
120
137
|
|
|
121
138
|
**Interactive mode:**
|
|
122
139
|
|
|
@@ -135,21 +152,11 @@ STOP — wait for user response.
|
|
|
135
152
|
|
|
136
153
|
Otherwise, store the parsed `manifests[]` and `total_unique` as `raw_dependencies` (dedup is already applied by the scanner), surface any `warnings[]` to the user as parse-quality notes, and inspect the `monorepo` flag: if `true`, mention the monorepo layout in the detection summary so the user can decide whether to scope the ranking to a specific package or proceed across all manifests.
|
|
137
154
|
|
|
138
|
-
###
|
|
139
|
-
|
|
140
|
-
"**Manifest detection complete.**
|
|
141
|
-
|
|
142
|
-
**Manifests found:** {count}
|
|
143
|
-
{For each manifest:}
|
|
144
|
-
- `{file_path}` ({ecosystem}) — {dep_count} dependencies
|
|
145
|
-
|
|
146
|
-
**Total unique dependencies:** {total_count}
|
|
147
|
-
- Runtime: {runtime_count}
|
|
148
|
-
- Dev-only: {dev_count}
|
|
155
|
+
### 3. Display Detection Summary
|
|
149
156
|
|
|
150
|
-
|
|
157
|
+
Report the detected manifests (for each: path, ecosystem, dependency count) and the total unique dependency count split into runtime vs dev-only.
|
|
151
158
|
|
|
152
|
-
###
|
|
159
|
+
### 4. Auto-Proceed to Next Step
|
|
153
160
|
|
|
154
161
|
Load, read the full file and then execute `{nextStepFile}`.
|
|
155
162
|
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'validate.md'
|
|
3
|
-
stackSkillTemplate: 'assets/stack-skill-template.md'
|
|
4
|
-
provenanceMapSchemaPath: 'assets/provenance-map-schema.md'
|
|
5
3
|
# Resolve `{atomicWriteHelper}` by probing `{atomicWriteProbeOrder}` in order
|
|
6
4
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
7
5
|
# path wins. HALT if neither resolves — stage/commit/flip-link/write below
|
|
@@ -49,7 +47,7 @@ Resolve `{version}` per S11 below — the primary library version in code-mode,
|
|
|
49
47
|
|
|
50
48
|
Where the skill name is `{project_name}-stack` and `{version}` is the semver version (with build metadata stripped per `knowledge/version-paths.md`).
|
|
51
49
|
|
|
52
|
-
**Primary library definition (S11):** In code-mode, the primary library is the dependency with the highest import count from step 3; its `version` (from the manifest) becomes `{primary_library_version}`, falling back to `1.0.0` if unavailable. In compose-mode, the stack carries its own release identity: default `{version}` to `1.0.0` (a stack-local scheme)
|
|
50
|
+
**Primary library definition (S11):** In code-mode, the primary library is the dependency with the highest import count from step 3; its `version` (from the manifest) becomes `{primary_library_version}`, falling back to `1.0.0` if unavailable. In compose-mode, the stack carries its own release identity: default `{version}` to `1.0.0` (a stack-local scheme) rather than borrowing the highest constituent semver. Constituent versions are preserved in `dependencies[]`, so no information is lost, and the stack's version does not track whichever constituent happens to have the highest version. The `1.0.0` default applies only to a **genuinely new** stack — see the re-composition rule below.
|
|
53
51
|
|
|
54
52
|
**Re-composition versioning (S11, compose-mode):** When the S3 pre-flight resolves a `{prior_stack_version}` (re-composing a stack that already has a release line), continue that line instead of resetting — defaulting to `1.0.0` would publish a version *below* the existing release (e.g. `1.0.0` shadowing a prior `3.0.5`, a backward jump). Bump `{prior_stack_version}`:
|
|
55
53
|
|
|
@@ -62,7 +60,11 @@ Never emit a `{version}` ≤ `{prior_stack_version}`. Narrate the resolved versi
|
|
|
62
60
|
|
|
63
61
|
"**Cannot proceed.** `{skills_output_folder}/{project_name}-stack/` exists but is not a stack skill (`skill_type={found_type}`). Rename the existing directory or choose a different `project_name` to avoid collision."
|
|
64
62
|
|
|
65
|
-
Do NOT proceed to staging or commit.
|
|
63
|
+
Do NOT proceed to staging or commit. Emit the result envelope on stderr per the Result Contract in SKILL.md and exit `4` (`stack_libraries` carries the confirmed library names; nothing was committed, so `skill_package` is `null`):
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":4,"halt_reason":"write-failure"}
|
|
67
|
+
```
|
|
66
68
|
|
|
67
69
|
If that metadata exists and `skill_type == "stack"`, this run is a **re-composition**: capture its `version` as `{prior_stack_version}` and its `libraries` array as `{prior_libraries}` for the S11 re-composition rule above. If the group dir is absent — or exists but has no resolvable `active` stack metadata — treat this as a new stack and leave `{prior_stack_version}` unset.
|
|
68
70
|
|
|
@@ -92,7 +94,11 @@ mkdir -p {forge_version}
|
|
|
92
94
|
python3 {atomicWriteHelper} commit-dir --rollback --target {skill_package}
|
|
93
95
|
```
|
|
94
96
|
|
|
95
|
-
Then abort
|
|
97
|
+
Then abort (see B7): purge any `{forge_version}/*-tmp` staging artifacts, emit the result envelope on stderr per the Result Contract in SKILL.md, and halt the workflow. This is the single rollback exit shared by §7 (workspace-write failure) and §9 (commit-dir failure):
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":4,"halt_reason":"write-failure"}
|
|
101
|
+
```
|
|
96
102
|
|
|
97
103
|
### 2. Stage SKILL.md
|
|
98
104
|
|
|
@@ -102,20 +108,20 @@ Write the approved `skill_content` from step 06 to `{skill_staging}/SKILL.md` (r
|
|
|
102
108
|
|
|
103
109
|
For each confirmed library, write `{skill_staging}/references/{library_name}.md`:
|
|
104
110
|
|
|
105
|
-
Load structure from `{
|
|
111
|
+
Load structure from `{stackSkillTemplatePath}` references section:
|
|
106
112
|
- Library name, version from manifest (**in compose-mode**: version from source skill `metadata.json`)
|
|
107
113
|
- Import count and file count (**in compose-mode**: export count from source skill metadata)
|
|
108
114
|
- Key exports with signatures
|
|
109
115
|
- Usage patterns with file:line citations (**in compose-mode**: usage patterns from source skill SKILL.md)
|
|
110
116
|
- Confidence tier label
|
|
111
117
|
|
|
112
|
-
**If the catalog was extracted** (large stack — step 06 §4 placed the `Library Reference Index` + `Per-Library Summaries` out of SKILL.md), also write `{skill_staging}/references/stack-catalog.md` using the structure in `{
|
|
118
|
+
**If the catalog was extracted** (large stack — step 06 §4 placed the `Library Reference Index` + `Per-Library Summaries` out of SKILL.md), also write `{skill_staging}/references/stack-catalog.md` using the structure in `{stackSkillTemplatePath}`, and confirm SKILL.md carries the inline pointer instead of the two sections. Small stacks keep the catalog inline and write no `stack-catalog.md`.
|
|
113
119
|
|
|
114
120
|
### 4. Stage Integration Pair Reference Files
|
|
115
121
|
|
|
116
122
|
For each detected integration pair, write `{skill_staging}/references/integrations/{libraryA}-{libraryB}.md`:
|
|
117
123
|
|
|
118
|
-
Load structure from `{
|
|
124
|
+
Load structure from `{stackSkillTemplatePath}` integrations section:
|
|
119
125
|
- Library pair and integration type
|
|
120
126
|
- Co-import file count
|
|
121
127
|
- Integration pattern description with file:line citations
|
|
@@ -131,7 +137,7 @@ Write `{skill_staging}/context-snippet.md`:
|
|
|
131
137
|
Use the Vercel-aligned indexed format targeting **~80-120 tokens** (M2). Token estimation is heuristic — use `ceil(char_count / 4)` as the working approximation (the standard rule-of-thumb for English text in BPE-style tokenizers; precise counts differ per model). Compute against the rendered snippet body (excluding trailing newline).
|
|
132
138
|
|
|
133
139
|
```
|
|
134
|
-
[{project_name}-stack v{version —
|
|
140
|
+
[{project_name}-stack v{version — resolved in §1}]|root: skills/{project_name}-stack/
|
|
135
141
|
|IMPORTANT: {project_name}-stack — read SKILL.md before writing integration code. Do NOT rely on training data.
|
|
136
142
|
|stack: {dep-1}@{v1}, {dep-2}@{v2}, {dep-3}@{v3}
|
|
137
143
|
|integrations: {pattern-1}, {pattern-2}
|
|
@@ -151,52 +157,12 @@ If the snippet is still over budget after step 4, log a warning to workflow_warn
|
|
|
151
157
|
|
|
152
158
|
### 6. Stage metadata.json
|
|
153
159
|
|
|
154
|
-
Write `{skill_staging}/metadata.json
|
|
155
|
-
|
|
156
|
-
Populate all fields from the metadata.json schema defined in `{stackSkillTemplate}`.
|
|
160
|
+
Write `{skill_staging}/metadata.json`, populating every field from the metadata.json schema in `{stackSkillTemplatePath}` (loaded in §3) — that template is the single schema source; do not re-transcribe it here. Resolve the field values whose template placeholders don't spell out the rule:
|
|
157
161
|
|
|
158
|
-
|
|
162
|
+
- `version` — the `{version}` resolved in §1 (not the template's literal `1.0.0`, which is only the new-stack default).
|
|
159
163
|
- `forge_tier` — the run tier (Quick/Forge/Forge+/Deep) resolved in step 1.
|
|
160
164
|
- `confidence_tier` — the dominant T-code from `confidence_distribution`. Pick the tier with the highest count; resolve ties toward the weaker tier (T1-low > T1, T2 > T1-low, T3 > T2) so the reported value never overstates confidence. When `confidence_distribution` is empty (no libraries extracted), emit `"T1-low"` as the conservative default.
|
|
161
|
-
|
|
162
|
-
```json
|
|
163
|
-
{
|
|
164
|
-
"skill_type": "stack",
|
|
165
|
-
"name": "{project_name}-stack",
|
|
166
|
-
"version": "{version — resolved per S11: code-mode primary_library_version or 1.0.0; compose-mode 1.0.0 (new stack) or bumped {prior_stack_version} (re-composition)}",
|
|
167
|
-
"generation_date": "{current_date}",
|
|
168
|
-
"forge_tier": "{Quick|Forge|Forge+|Deep — the tier under which this run executed}",
|
|
169
|
-
"confidence_tier": "{T1|T1-low|T2|T3 — dominant T-code from confidence_distribution below}",
|
|
170
|
-
"spec_version": "1.3",
|
|
171
|
-
"source_authority": "{official|community|internal — use the lowest authority among constituent skills}",
|
|
172
|
-
"generated_by": "create-stack-skill",
|
|
173
|
-
"exports": [],
|
|
174
|
-
"library_count": N,
|
|
175
|
-
"integration_count": N,
|
|
176
|
-
"libraries": ["lib1", "lib2"],
|
|
177
|
-
"integration_pairs": [["lib1", "lib2"]],
|
|
178
|
-
"language": "{primary language or list of languages from constituent skills}",
|
|
179
|
-
"ast_node_count": "{number or omit if no AST extraction performed}",
|
|
180
|
-
"confidence_distribution": {"t1": N, "t1_low": N, "t2": N, "t3": N},
|
|
181
|
-
"tool_versions": {
|
|
182
|
-
"ast_grep": "{version or null}",
|
|
183
|
-
"qmd": "{version or null}",
|
|
184
|
-
"skf": "{skf_version}"
|
|
185
|
-
},
|
|
186
|
-
"stats": {
|
|
187
|
-
"exports_documented": N,
|
|
188
|
-
"exports_public_api": N,
|
|
189
|
-
"exports_internal": N,
|
|
190
|
-
"exports_total": N,
|
|
191
|
-
"public_api_coverage": 0.0,
|
|
192
|
-
"total_coverage": 0.0,
|
|
193
|
-
"scripts_count": N,
|
|
194
|
-
"assets_count": N
|
|
195
|
-
},
|
|
196
|
-
"dependencies": [],
|
|
197
|
-
"compatibility": "{semver-range}"
|
|
198
|
-
}
|
|
199
|
-
```
|
|
165
|
+
- `source_authority` — the lowest authority among constituent skills (official > community > internal).
|
|
200
166
|
|
|
201
167
|
### 7. Write Forge Data Artifacts (Workspace)
|
|
202
168
|
|
|
@@ -216,7 +182,7 @@ Use the schema from `{provenanceMapSchemaPath}` — see that asset for the canon
|
|
|
216
182
|
- **In code-mode:** use the code-mode variant (`source_repo` / `source_commit` populated; `extraction_method` ∈ `ast_bridge|source_reading|qmd_bridge`; `detection_method = "co-import grep"`).
|
|
217
183
|
- **In compose-mode:** use the compose-mode variant (source-anchor fields `null`; `extraction_method = "compose-from-skill"`; `detection_method ∈ "architecture_co_mention|constituent_documented_contract|inferred_from_shared_domain"`; includes the additional `constituents[]` array for drift detection).
|
|
218
184
|
|
|
219
|
-
|
|
185
|
+
Populate compose-mode `constituents[].metadata_hash` from the value stored in workflow state at step 2 (S13), not a fresh re-hash at step-7 time — `{provenanceMapSchemaPath}` carries the rationale for why the manifest-detection-time hash is the correct provenance anchor.
|
|
220
186
|
|
|
221
187
|
**evidence-report.md:**
|
|
222
188
|
- Extraction summary per library
|
|
@@ -226,9 +192,9 @@ Use the schema from `{provenanceMapSchemaPath}` — see that asset for the canon
|
|
|
226
192
|
|
|
227
193
|
### 8. Pre-Commit Frontmatter & Body-Size Gate
|
|
228
194
|
|
|
229
|
-
The full schema/frontmatter validation runs in step 8 (`validate.md`) — but that runs *after* commit-dir and flip-link have already published the package. The most common non-auto-fixable `skill-check` hard rejects — a `description` over the 1024-char limit (which `skill-check --fix` cannot trim for you)
|
|
195
|
+
The full schema/frontmatter validation runs in step 8 (`validate.md`) — but that runs *after* commit-dir and flip-link have already published the package. The most common non-auto-fixable `skill-check` hard rejects — a `description` over the 1024-char limit (which `skill-check --fix` cannot trim for you) and a SKILL.md body over the `body.max_lines` limit (default **500**) — would therefore only surface on an already-committed, symlink-active artifact, forcing edits to the live `SKILL.md`. `skill-check` also *warns* (non-blocking) when the body exceeds `body.max_tokens` (default **5000**). Additive re-composition of an already-large stack grows the body monotonically, so body overflow is the likeliest trigger. Catch these here, while the package is still in `.skf-tmp`.
|
|
230
196
|
|
|
231
|
-
Resolve `{frontmatterValidator}` from `{frontmatterValidatorProbeOrder}` (first existing path wins). Run it against the **staged** `SKILL.md`, passing the real skill name so the directory-match check is not fooled by the `.skf-tmp` staging suffix, `--max-body-lines 500` to assert the skill-check body-line limit, and `--max-body-tokens 5000` to
|
|
197
|
+
Resolve `{frontmatterValidator}` from `{frontmatterValidatorProbeOrder}` (first existing path wins). Run it against the **staged** `SKILL.md`, passing the real skill name so the directory-match check is not fooled by the `.skf-tmp` staging suffix, `--max-body-lines 500` to assert the skill-check body-line limit, and `--max-body-tokens 5000` to surface the skill-check body-token *warning* pre-commit (advisory — see disposition below):
|
|
232
198
|
|
|
233
199
|
```bash
|
|
234
200
|
uv run {frontmatterValidator} {skill_staging}/SKILL.md --skill-dir-name {project_name}-stack --max-body-lines 500 --max-body-tokens 5000
|
|
@@ -238,10 +204,10 @@ The validator emits JSON: `status` (`pass`/`warn`/`fail`), `issues[]` (each with
|
|
|
238
204
|
|
|
239
205
|
- **`status` is `fail`, OR any `issues[]` entry has `severity` `high` or `medium`** — a hard violation that `npx skill-check` (step 8) would reject and `--fix` cannot auto-correct. HALT-to-fix **in staging**, then re-run the validator until it clears. Remediate by `field`:
|
|
240
206
|
- `description` / `name` / `compatibility` — trim/correct `{skill_staging}/SKILL.md` (e.g. shorten `description` to ≤ 1024 chars).
|
|
241
|
-
- `body` (`body lines N exceeds max 500`
|
|
207
|
+
- `body` (`body lines N exceeds max 500`) — reduce the staged body: prefer a **selective split** of the largest Tier-2 section(s) into `{skill_staging}/references/`, keeping Tier-1 content inline (mirrors `validate.md` §3); or trim redundant content. Re-run the gate until `body_lines ≤ 500`. (An over-`body_tokens` estimate is advisory, not a hard stop — see the low-severity note below.)
|
|
242
208
|
|
|
243
209
|
Do NOT proceed to §9 commit-dir with an unresolved high/medium issue. Note: an over-long `description` is rated `medium` and exits `0`, so key the HALT on the issue severities above — not on the exit code.
|
|
244
|
-
- **Only `low`-severity issues (e.g. an unexpected field)** — record each as a WARNING in the evidence report and proceed; these do not block the commit.
|
|
210
|
+
- **Only `low`-severity issues (e.g. an unexpected field, or a `body token estimate N exceeds max 5000` advisory)** — record each as a WARNING in the evidence report and proceed; these do not block the commit. The body-token estimate is a char/4 heuristic that runs higher than `skill-check`'s own whitespace-split count, and `skill-check` treats `body.max_tokens` as a non-blocking warning — so an over-token estimate is advisory here, not a HALT (the `body.max_lines` gate above remains the hard body pre-check).
|
|
245
211
|
|
|
246
212
|
**If `{frontmatterValidator}` does not resolve** (neither probe path exists) **or the invocation cannot run**, emit a WARNING ("pre-commit frontmatter + body-size gate skipped — validator unavailable") and proceed. Step 8 (`validate.md`) remains the post-commit backstop (including the `body.max_lines` split path in its §3); this gate is a best-effort early catch, never a new hard dependency.
|
|
247
213
|
|
|
@@ -269,24 +235,7 @@ If `flip-link` fails, emit a warning (the committed package is still valid), not
|
|
|
269
235
|
|
|
270
236
|
### 11. Display Write Summary
|
|
271
237
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
**Deliverables** ({skill_package}):
|
|
275
|
-
- SKILL.md ({line_count} lines)
|
|
276
|
-
- context-snippet.md ({token_estimate} tokens)
|
|
277
|
-
- metadata.json
|
|
278
|
-
- references/ -- {lib_count} library files
|
|
279
|
-
- references/integrations/ -- {pair_count} integration files
|
|
280
|
-
|
|
281
|
-
**Workspace** ({forge_version}):
|
|
282
|
-
- provenance-map.json
|
|
283
|
-
- evidence-report.md
|
|
284
|
-
|
|
285
|
-
**Symlink:** {skill_group}/active -> {version}
|
|
286
|
-
|
|
287
|
-
**Total files written:** {total_count}
|
|
288
|
-
|
|
289
|
-
**Proceeding to validation...**"
|
|
238
|
+
Report the files written: the `{skill_package}` deliverables (SKILL.md with `{line_count}` lines, context-snippet.md with `{token_estimate}` tokens, metadata.json, `references/` `{lib_count}` library files, `references/integrations/` `{pair_count}` integration files), the `{forge_version}` workspace (provenance-map.json, evidence-report.md), the `{skill_group}/active -> {version}` symlink, and the `{total_count}` total.
|
|
290
239
|
|
|
291
240
|
### 12. Auto-Proceed to Next Step
|
|
292
241
|
|