bmad-module-skill-forge 1.9.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/README.md +10 -5
- package/docs/_data/pinned.yaml +2 -2
- package/docs/agents.md +11 -2
- package/docs/architecture.md +5 -4
- package/docs/bmad-synergy.md +30 -7
- package/docs/campaign.md +172 -0
- package/docs/examples.md +7 -3
- package/docs/forge-auto.md +90 -0
- package/docs/getting-started.md +9 -0
- package/docs/how-it-works.md +6 -4
- package/docs/index.md +4 -3
- package/docs/skill-model.md +1 -1
- package/docs/troubleshooting.md +17 -1
- package/docs/verifying-a-skill.md +2 -2
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +64 -24
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +4 -3
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +6 -3
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- 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-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +240 -4
- package/src/shared/scripts/skf-detect-language.py +82 -3
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- 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-language-corpora.py +100 -0
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +1 -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-shape-detect.py +576 -25
- 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 +41 -6
- 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 +3 -3
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- 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 +211 -197
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- 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/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +13 -18
- package/src/skf-brief-skill/references/confirm-brief.md +2 -15
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +27 -24
- 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 +6 -15
- package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
- package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +19 -13
- package/src/skf-campaign/SKILL.md +121 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +75 -0
- package/src/skf-campaign/manifest.yaml +15 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +121 -0
- package/src/skf-campaign/references/step-02-strategy.md +102 -0
- package/src/skf-campaign/references/step-03-pins.md +56 -0
- package/src/skf-campaign/references/step-04-provenance.md +63 -0
- package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
- package/src/skf-campaign/references/step-06-batch.md +88 -0
- package/src/skf-campaign/references/step-07-capstone.md +63 -0
- package/src/skf-campaign/references/step-08-verify.md +75 -0
- package/src/skf-campaign/references/step-09-refine.md +83 -0
- package/src/skf-campaign/references/step-10-export.md +106 -0
- package/src/skf-campaign/references/step-11-maintenance.md +84 -0
- package/src/skf-campaign/references/step-resume.md +115 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +244 -0
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
- package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
- package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
- package/src/skf-campaign/templates/campaign-report-template.md +54 -0
- package/src/skf-campaign/templates/kickoff-template.md +48 -0
- package/src/skf-create-skill/SKILL.md +15 -4
- package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
- 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 +37 -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 +20 -27
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +10 -8
- package/src/skf-create-skill/references/generate-artifacts.md +20 -25
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +27 -14
- package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +33 -15
- package/src/skf-create-skill/references/step-doc-sources.md +13 -4
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
- 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 +69 -29
- 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 +67 -36
- 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 +44 -10
- package/src/skf-drop-skill/references/select.md +93 -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 +32 -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 +16 -8
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +10 -8
- 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 +14 -11
- 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 +112 -82
- 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 +21 -13
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +11 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +10 -8
- package/src/skf-setup/references/report.md +26 -32
- 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 +111 -67
- 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 +39 -21
- 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 +15 -5
- 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 +135 -4
- 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 +11 -6
- package/src/skf-update-skill/references/detect-changes.md +48 -36
- package/src/skf-update-skill/references/health-check.md +5 -11
- package/src/skf-update-skill/references/init.md +40 -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 +27 -25
- 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/tools/cli/lib/ui.js +3 -2
- package/docs/deepwiki.md +0 -89
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -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
|
|
|
@@ -27,74 +27,12 @@ Before anything else, load `{project-root}/_bmad/skf/config.yaml`. If the file i
|
|
|
27
27
|
|
|
28
28
|
**Halting workflow.**"
|
|
29
29
|
|
|
30
|
-
STOP — do not proceed
|
|
30
|
+
Then emit the result envelope on stderr per the Result Contract in SKILL.md (`project_name` is unresolved here, so `skill_name` is `null`), and STOP — do not proceed:
|
|
31
31
|
|
|
32
|
-
### 0b. Resume Check
|
|
33
|
-
|
|
34
|
-
Before any further init work, check for an interrupted prior run.
|
|
35
|
-
|
|
36
|
-
**Probe path.** Resolve `{resume_skill_name}` as `{project_name}-stack` (the same skill name used at step 7) and probe `{forge_data_folder}/{resume_skill_name}/in-progress.json`. (The file lives at the version-agnostic skill root so it can be found before `{version}` resolution.)
|
|
37
|
-
|
|
38
|
-
**If no in-progress.json exists:** Continue to §1.
|
|
39
|
-
|
|
40
|
-
**If in-progress.json exists:** Load and parse it. Read `last_completed_step` and `started_at` (ISO-8601 timestamp). Surface a soft gate:
|
|
41
|
-
|
|
42
|
-
"**Resume previous run?**
|
|
43
|
-
|
|
44
|
-
Found a previous in-progress run at `{forge_data_folder}/{resume_skill_name}/in-progress.json` from {started_at}, last completed at step {last_completed_step}.
|
|
45
|
-
|
|
46
|
-
- **[C] Continue** (recommended) — resume from the next step after {last_completed_step}, restoring saved workflow state.
|
|
47
|
-
- **[F] Fresh** — archive the existing in-progress.json (rename to `in-progress.{timestamp}.json`) and start over from step 1.
|
|
48
|
-
- **[X] Cancel and exit** — leave the in-progress.json untouched and halt.
|
|
49
|
-
|
|
50
|
-
Select [C/F/X]:"
|
|
51
|
-
|
|
52
|
-
**Headless default:** `[C]` Continue.
|
|
53
|
-
|
|
54
|
-
**On [C] Continue:**
|
|
55
|
-
1. Restore workflow context from in-progress.json fields: `last_completed_step`, `workflow_state` (mode, tier, scope), and any accumulator fields (partial extractions, ranked libraries, integration pairs, compile-stack output) that the writing step persisted.
|
|
56
|
-
2. Determine the resume target: the step file that runs immediately after `last_completed_step`.
|
|
57
|
-
3. Jump directly to that step file by loading and executing it (skip the remaining §0b–§5 init substeps for this run).
|
|
58
|
-
|
|
59
|
-
**On [F] Fresh:**
|
|
60
|
-
1. Compute `{archive_timestamp}` as the current UTC time in `YYYYMMDDTHHMMSSZ` form.
|
|
61
|
-
2. Rename `{forge_data_folder}/{resume_skill_name}/in-progress.json` → `{forge_data_folder}/{resume_skill_name}/in-progress.{archive_timestamp}.json`.
|
|
62
|
-
3. Continue with §1 of this file as if no prior run existed.
|
|
63
|
-
|
|
64
|
-
**On [X] Cancel and exit:** HARD HALT with exit code 6 (user-cancelled). Do NOT modify the in-progress.json. Emit the result envelope on stderr per the Result Contract in SKILL.md:
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{resume_skill_name}","stack_libraries":[],"mode":null,"exit_code":6,"halt_reason":"user-cancelled"}
|
|
68
32
|
```
|
|
69
|
-
|
|
70
|
-
**in-progress.json schema (read side).** This PR wires only the READ side of the resume protocol. The WRITE side — each stage step persisting an updated in-progress.json after it completes — is deferred to a follow-up PR. When write-side wiring lands, each step writes the file via `skf-atomic-write.py write` at the end of its mandatory sequence with this shape:
|
|
71
|
-
|
|
72
|
-
```json
|
|
73
|
-
{
|
|
74
|
-
"schema_version": "1.0",
|
|
75
|
-
"skill_name": "{project_name}-stack",
|
|
76
|
-
"started_at": "{ISO-8601 of step 1 start}",
|
|
77
|
-
"updated_at": "{ISO-8601 of most recent step completion}",
|
|
78
|
-
"last_completed_step": "step-NN",
|
|
79
|
-
"workflow_state": {
|
|
80
|
-
"mode": "code|compose",
|
|
81
|
-
"forge_tier": "Quick|Forge|Forge+|Deep",
|
|
82
|
-
"headless_mode": false,
|
|
83
|
-
"scope": {"explicit_deps": [], "scope_overrides": {}, "architecture_doc_path": null}
|
|
84
|
-
},
|
|
85
|
-
"accumulators": {
|
|
86
|
-
"manifests": [],
|
|
87
|
-
"ranked_libraries": [],
|
|
88
|
-
"extractions": {},
|
|
89
|
-
"integration_pairs": [],
|
|
90
|
-
"compiled_stack": null,
|
|
91
|
-
"workflow_warnings": []
|
|
92
|
-
}
|
|
93
|
-
}
|
|
33
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":null,"stack_libraries":[],"mode":null,"exit_code":2,"halt_reason":"config-missing"}
|
|
94
34
|
```
|
|
95
35
|
|
|
96
|
-
Until the write side is wired, in-progress.json will not naturally appear and §0b will fall through to §1 on every run. The resume gate is a no-op until that follow-up lands.
|
|
97
|
-
|
|
98
36
|
### 1. Load Forge Tier Configuration
|
|
99
37
|
|
|
100
38
|
Load `{forgeTierFile}` from the Ferris sidecar.
|
|
@@ -107,7 +45,11 @@ Load `{forgeTierFile}` from the Ferris sidecar.
|
|
|
107
45
|
|
|
108
46
|
**Halting workflow.**"
|
|
109
47
|
|
|
110
|
-
STOP — do not proceed
|
|
48
|
+
Then emit the result envelope on stderr per the Result Contract in SKILL.md (config loaded, so `skill_name` is known; `mode` is not yet resolved), and STOP — do not proceed:
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":null,"exit_code":3,"halt_reason":"forge-tier-missing"}
|
|
52
|
+
```
|
|
111
53
|
|
|
112
54
|
**If forge-tier.yaml exists:**
|
|
113
55
|
|
|
@@ -156,6 +98,7 @@ Skills use version-nested directories — see `knowledge/version-paths.md` for t
|
|
|
156
98
|
- If user provides an architecture document path for composition or explicitly requests compose mode → set `compose_mode: true` and store `architecture_doc_path`
|
|
157
99
|
- If no manifest files exist in project root AND at least one skill is discoverable in `{skills_output_folder}` → suggest compose mode to the user and ask for optional architecture document path
|
|
158
100
|
- **Skill discovery (version-aware):** First, read `{skills_output_folder}/.export-manifest.json` — each entry in `exports` names a skill with an `active_version`, which resolves to `{skills_output_folder}/{skill-name}/{active_version}/{skill-name}/` containing `SKILL.md` and `metadata.json`. If the export manifest does not exist or is empty, fall back to scanning for `active` symlinks: check `{skills_output_folder}/*/active/*/SKILL.md` — each match indicates a skill whose package lives at `{skills_output_folder}/{skill-name}/active/{skill-name}/` (the `{active_skill}` template).
|
|
101
|
+
- **Headless default (B8):** If `{headless_mode}` is true, do NOT prompt — auto-accept the suggestion: set `compose_mode: true` and `architecture_doc_path: null` (unless an architecture doc path was supplied via the optional inputs above). This is the constructive default: with no manifests present, code-mode would only halt at step 2 (`no-manifests`), so compose is the sole path that produces output. Log the auto-decision by appending to `workflow_warnings[]`: `{step: "step-01", severity: "info", code: "headless-compose-autodetect", message: "no manifests + {N} discoverable skills — auto-selected compose mode", context: {discoverable_skills: {N}}}`.
|
|
159
102
|
- If user accepts → set `compose_mode: true` and store `architecture_doc_path` (may be `null` if user chose not to provide one)
|
|
160
103
|
- If user declines → `compose_mode` remains `false`, continue with code-mode
|
|
161
104
|
|
|
@@ -166,22 +109,7 @@ If no optional inputs provided, auto-detection will be used.
|
|
|
166
109
|
|
|
167
110
|
### 4. Display Initialization Summary
|
|
168
111
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
**Project:** {project_name}
|
|
172
|
-
**Forge Tier:** {forge_tier} — {tier_description}
|
|
173
|
-
|
|
174
|
-
Where tier_description follows positive capability framing:
|
|
175
|
-
- Quick: "Source reading and import counting"
|
|
176
|
-
- Forge: "AST-backed structural analysis"
|
|
177
|
-
- Forge+: "AST structural + CCC semantic co-import augmentation"
|
|
178
|
-
- Deep: "Full intelligence — structural + contextual + temporal"
|
|
179
|
-
|
|
180
|
-
**Available Tools:** {tool_list}
|
|
181
|
-
**Input Mode:** {auto-detect | explicit dependency list | compose mode}
|
|
182
|
-
|
|
183
|
-
**If compose mode:** Proceeding to skill loading...
|
|
184
|
-
**If code mode:** Proceeding to manifest detection..."
|
|
112
|
+
Report that the Stack Skill Forge is initialized, naming: the project (`{project_name}`); the forge tier (`{forge_tier}`) with its positive-capability framing (Quick = source reading and import counting; Forge = AST-backed structural analysis; Forge+ = AST structural + CCC semantic co-import augmentation; Deep = full intelligence — structural + contextual + temporal); the available tools (`{tool_list}`); and the resolved input mode (auto-detect, explicit dependency list, or compose mode).
|
|
185
113
|
|
|
186
114
|
### 5. Auto-Proceed to Next Step
|
|
187
115
|
|
|
@@ -15,41 +15,11 @@
|
|
|
15
15
|
| PHP | composer.json | require, require-dev | `use ...`, `require_once` |
|
|
16
16
|
| .NET | *.csproj | PackageReference | `using ...` |
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
4. Deduplicate across multiple manifests
|
|
24
|
-
|
|
25
|
-
## Scan Exclusion Patterns
|
|
26
|
-
|
|
27
|
-
When scanning for manifest files, ALWAYS exclude these directories from glob results:
|
|
28
|
-
|
|
29
|
-
**Dependency/Vendor Directories:**
|
|
30
|
-
- `node_modules/`
|
|
31
|
-
- `.venv/` / `venv/` / `.env/`
|
|
32
|
-
- `vendor/` (PHP Composer, Go modules)
|
|
33
|
-
- `Pods/` (iOS CocoaPods)
|
|
34
|
-
|
|
35
|
-
**Build Output Directories:**
|
|
36
|
-
- `dist/` / `build/` / `out/`
|
|
37
|
-
- `target/` (Rust, Java/Maven)
|
|
38
|
-
- `__pycache__/`
|
|
39
|
-
- `.next/` / `.nuxt/` / `.output/`
|
|
40
|
-
|
|
41
|
-
**Hidden and VCS Directories:**
|
|
42
|
-
- `.git/`
|
|
43
|
-
- Any directory starting with `.` (except project root hidden config files like `.csproj`)
|
|
44
|
-
|
|
45
|
-
**Monorepo Note:** For monorepo structures (e.g., `packages/*/package.json`), the depth 0-1 scan rule already limits scope. If monorepo manifest detection is needed at deeper levels, these exclusions become critical to prevent scanning dependency trees within each package.
|
|
46
|
-
|
|
47
|
-
## Filtering Rules
|
|
48
|
-
|
|
49
|
-
- Exclude dev-only dependencies unless they appear in production imports
|
|
50
|
-
- Exclude build tools (webpack, babel, eslint, etc.) unless significantly imported
|
|
51
|
-
- Include all runtime dependencies by default
|
|
52
|
-
- Flag transitive dependencies that appear in direct imports
|
|
18
|
+
<!-- Manifest scanning, name normalization, dedup, exclusion-dir filtering, and
|
|
19
|
+
dev/build-tool filtering are performed by `skf-scan-manifests.py` (invoked in
|
|
20
|
+
detect-manifests.md §2), which implements exactly the ecosystem table above.
|
|
21
|
+
This file is loaded only for that reference table and the import-counting
|
|
22
|
+
exclusions below — see the script's `--help` for the operative scan contract. -->
|
|
53
23
|
|
|
54
24
|
## Import Counting
|
|
55
25
|
|
|
@@ -60,7 +60,11 @@ The script emits JSON of the form:
|
|
|
60
60
|
}
|
|
61
61
|
```
|
|
62
62
|
|
|
63
|
-
Cache this result as `stack_skill_inventory` in workflow state — the per-skill subagent fan-out at §1+ MUST read from this cache rather than re-reading each skill's `SKILL.md` / `metadata.json` / `references/` to determine exports. Append every entry in `warnings[]` to workflow state for the evidence report (the script already labels them per-skill, e.g. `"<skill-name>: no exports found via any resolution path"`).
|
|
63
|
+
Cache this result as `stack_skill_inventory` in workflow state — the per-skill subagent fan-out at §1+ MUST read from this cache rather than re-reading each skill's `SKILL.md` / `metadata.json` / `references/` to determine exports. Append every entry in `warnings[]` to workflow state for the evidence report (the script already labels them per-skill, e.g. `"<skill-name>: no exports found via any resolution path"`). If `cycles[]` is non-empty, a composes-cycle makes the stack unbuildable — emit the result envelope on stderr per the Result Contract in SKILL.md and exit `3`:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
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"}
|
|
67
|
+
```
|
|
64
68
|
|
|
65
69
|
Build a `per_library_extractions[]` entry for each skill by reading from the cached inventory:
|
|
66
70
|
- `library`: `inventory.skills[i].name`
|
|
@@ -70,15 +74,7 @@ Build a `per_library_extractions[]` entry for each skill by reading from the cac
|
|
|
70
74
|
- `metadata_hash`: `inventory.skills[i].metadata_hash` — record for step 7 provenance (null when exports came from references/ or SKILL.md prose).
|
|
71
75
|
- `usage_patterns`: populated by the §1+ per-skill subagent fan-out, NOT by this script. The script provides the inventory + exports; the subagent does the per-skill usage analysis. They're complementary.
|
|
72
76
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
"**Loaded {N} skill extractions from existing skills.**
|
|
76
|
-
|
|
77
|
-
| Skill | Exports | Confidence | Status |
|
|
78
|
-
|-------|---------|------------|--------|
|
|
79
|
-
| {name} | {count} | {tier} | Loaded |"
|
|
80
|
-
|
|
81
|
-
Auto-proceed to next step.
|
|
77
|
+
Report the loaded extractions — for each skill: export count, confidence tier, and load status. Then auto-proceed to the next step.
|
|
82
78
|
|
|
83
79
|
**If not compose_mode:** Continue with section 1 (existing flow).
|
|
84
80
|
|
|
@@ -177,26 +173,15 @@ For each library extraction:
|
|
|
177
173
|
**If ALL extractions fail:** HALT — cannot produce meaningful stack skill. Before halting (B7):
|
|
178
174
|
|
|
179
175
|
1. Purge any in-flight staging artifacts under the forge workspace: remove `{forge_data_folder}/{project_name}-stack/{version}/*-tmp` and any `{forge_data_folder}/{project_name}-stack/{version}/*.skf-tmp` directories so partial state does not linger.
|
|
180
|
-
2. Emit
|
|
181
|
-
3. Exit with a non-zero status so headless pipelines detect the failure.
|
|
182
|
-
|
|
183
|
-
### 4. Display Extraction Summary
|
|
176
|
+
2. Emit the result envelope on stderr per the Result Contract in SKILL.md (`stack_libraries` carries the confirmed library names that failed extraction), and exit `2`:
|
|
184
177
|
|
|
185
|
-
|
|
178
|
+
```
|
|
179
|
+
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":["<confirmed-lib>", "..."],"mode":"{code|compose}","exit_code":2,"halt_reason":"all-extractions-failed"}
|
|
180
|
+
```
|
|
186
181
|
|
|
187
|
-
|
|
188
|
-
|---------|---------|----------|------------|--------|
|
|
189
|
-
| {name} | {count} | {count} | {tier} | ✓ |
|
|
190
|
-
| {name} | {count} | {count} | {tier} | ✓ |
|
|
191
|
-
| {name} | — | — | — | ⚠ partial |
|
|
192
|
-
|
|
193
|
-
**Results:** {success_count}/{total_count} libraries extracted
|
|
194
|
-
**Confidence distribution:** T1: {count}, T1-low: {count}, T2: {count}
|
|
195
|
-
{If Deep tier:} **T2 enrichment:** {enriched_count}/{total_count} libraries had temporal collections available
|
|
196
|
-
{If libraries without temporal > 0:} **Tip:** Run [CS] Create Skill at Deep tier for individual libraries to generate temporal collections, then re-run [SS] for full T2 enrichment.
|
|
197
|
-
{If warnings:} **Warnings:** {warning_count} issues noted
|
|
182
|
+
### 4. Display Extraction Summary
|
|
198
183
|
|
|
199
|
-
**
|
|
184
|
+
Report the extraction results: per library the export count, pattern count, confidence tier, and success/partial status; the overall `{success_count}/{total_count}` extracted; and the T1 / T1-low / T2 confidence distribution. At Deep tier, add the T2-enrichment count (`{enriched_count}/{total_count}` libraries with temporal collections available); and if any library lacked a temporal collection, add the tip: run **[CS] Create Skill** at Deep tier for those libraries to generate temporal collections, then re-run **[SS]** for full T2 enrichment. Note any warning count.
|
|
200
185
|
|
|
201
186
|
### 5. Auto-Proceed to Next Step
|
|
202
187
|
|
|
@@ -56,7 +56,7 @@ Use ecosystem-appropriate import patterns:
|
|
|
56
56
|
- Python: `import library`, `from library import`
|
|
57
57
|
- Rust: `use library::`, `extern crate library`
|
|
58
58
|
- Go: `"library"` in import blocks
|
|
59
|
-
- (Match patterns from
|
|
59
|
+
- (Match patterns from `{manifestPatternsPath}`)
|
|
60
60
|
|
|
61
61
|
**Subprocess returns:** `{library_name: import_count, files: [file_paths]}` for each dependency.
|
|
62
62
|
|
|
@@ -112,13 +112,13 @@ Apply additions/exclusions, display updated list, and ask for final confirmation
|
|
|
112
112
|
**If custom list provided:**
|
|
113
113
|
Use the custom list as `confirmed_dependencies`.
|
|
114
114
|
|
|
115
|
-
Display
|
|
115
|
+
Display the resolved scope:
|
|
116
116
|
|
|
117
117
|
"**Scope confirmed:** {count} libraries selected for stack skill extraction.
|
|
118
118
|
|
|
119
|
-
{List confirmed libraries}
|
|
119
|
+
{List confirmed libraries}"
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
The extraction itself begins only once the user clears the gate below.
|
|
122
122
|
|
|
123
123
|
### 5. Present MENU OPTIONS
|
|
124
124
|
|
|
@@ -126,9 +126,9 @@ Display: **Select:** [C] Continue to Extraction | [X] Cancel and exit
|
|
|
126
126
|
|
|
127
127
|
#### EXECUTION RULES:
|
|
128
128
|
|
|
129
|
-
-
|
|
129
|
+
- This is a confirmation gate — advancing without the user's `C` would extract and ship a stack scope they never approved. Halt and wait for input after presenting scope.
|
|
130
130
|
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue (accept all ranked libraries), log: "headless: auto-confirm library scope"
|
|
131
|
-
-
|
|
131
|
+
- Proceed to the next step only once the user confirms scope by selecting `C`.
|
|
132
132
|
|
|
133
133
|
#### Menu Handling Logic:
|
|
134
134
|
|