bmad-module-skill-forge 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +51 -49
- package/docs/404.md +10 -8
- package/docs/_data/pinned.yaml +22 -13
- package/docs/_internal/STABILITY.md +58 -35
- package/docs/agents.md +39 -53
- package/docs/architecture.md +65 -51
- package/docs/bmad-synergy.md +53 -51
- package/docs/campaign.md +127 -75
- package/docs/concepts.md +34 -28
- package/docs/examples.md +70 -68
- package/docs/forge-auto.md +34 -31
- package/docs/getting-started.md +118 -57
- package/docs/how-it-works.md +25 -21
- package/docs/index.md +15 -15
- package/docs/skill-model.md +70 -59
- package/docs/troubleshooting.md +135 -18
- package/docs/verifying-a-skill.md +83 -57
- package/docs/why-skf.md +24 -22
- package/docs/workflows.md +274 -110
- package/package.json +18 -10
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/agentskills-spec.md +2 -0
- package/src/knowledge/ccc-bridge.md +40 -24
- package/src/knowledge/confidence-tiers.md +9 -5
- package/src/knowledge/overview.md +3 -3
- package/src/knowledge/progressive-capability.md +8 -8
- package/src/knowledge/provenance-tracking.md +9 -5
- package/src/knowledge/qmd-registry.md +2 -2
- package/src/knowledge/skf-knowledge-index.csv +2 -2
- package/src/knowledge/skill-lifecycle.md +18 -11
- package/src/knowledge/split-body-strategy.md +0 -3
- package/src/knowledge/tool-resolution.md +4 -2
- package/src/knowledge/version-paths.md +101 -15
- package/src/module-help.csv +3 -3
- package/src/module.yaml +10 -0
- package/src/shared/data/ast-grep-recipes.yaml +608 -0
- package/src/shared/data/ide-context-files.json +30 -0
- package/src/shared/health-check.md +32 -12
- package/src/shared/references/description-guard-protocol.md +14 -9
- package/src/shared/references/feasibility-report-schema.md +19 -13
- package/src/shared/references/headless-gate-convention.md +55 -3
- package/src/shared/references/output-contract-schema.md +19 -8
- package/src/shared/references/pipeline-contracts.md +94 -29
- package/src/shared/references/tessl-review.md +77 -0
- package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
- package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
- package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
- package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
- package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
- package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
- package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
- package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
- package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
- package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
- package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
- package/src/shared/scripts/skf-atomic-write.py +30 -14
- package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
- package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
- package/src/shared/scripts/skf-check-unit-records.py +184 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
- package/src/shared/scripts/skf-classify-changed-files.py +694 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
- package/src/shared/scripts/skf-count-imports.py +1867 -0
- package/src/shared/scripts/skf-count-tokens.py +1 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
- package/src/shared/scripts/skf-description-guard.py +117 -9
- package/src/shared/scripts/skf-detect-docs.py +892 -4
- package/src/shared/scripts/skf-detect-language.py +486 -107
- package/src/shared/scripts/skf-detect-registry.py +887 -0
- package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
- package/src/shared/scripts/skf-detect-tools.py +215 -27
- package/src/shared/scripts/skf-detect-workspaces.py +506 -30
- package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
- package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
- package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
- package/src/shared/scripts/skf-extract-public-api.py +4084 -85
- package/src/shared/scripts/skf-extraction-inventory.py +746 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
- package/src/shared/scripts/skf-fetch-temporal.py +674 -0
- package/src/shared/scripts/skf-find-cycles.py +97 -29
- package/src/shared/scripts/skf-find-test-report.py +476 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +661 -0
- package/src/shared/scripts/skf-hash-content.py +166 -12
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +159 -27
- package/src/shared/scripts/skf-manifest-ops.py +1 -1
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
- package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
- package/src/shared/scripts/skf-names-present.py +221 -0
- package/src/shared/scripts/skf-pair-intersect.py +119 -28
- package/src/shared/scripts/skf-parse-gaps.py +1384 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-preflight.py +161 -27
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
- package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
- package/src/shared/scripts/skf-quick-batch.py +774 -0
- package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
- package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
- package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
- package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
- package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
- package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
- package/src/shared/scripts/skf-resolve-package.py +523 -106
- package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
- package/src/shared/scripts/skf-run-lock.py +577 -0
- package/src/shared/scripts/skf-scan-manifests.py +998 -57
- package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
- package/src/shared/scripts/skf-severity-classify.py +712 -108
- package/src/shared/scripts/skf-shape-detect.py +298 -204
- package/src/shared/scripts/skf-shard-body.py +9 -8
- package/src/shared/scripts/skf-skill-inventory.py +2412 -89
- package/src/shared/scripts/skf-skills-module.py +472 -0
- package/src/shared/scripts/skf-source-tree.py +1796 -0
- package/src/shared/scripts/skf-structural-diff.py +670 -119
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +5 -5
- package/src/shared/scripts/skf-update-run-state.py +624 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
- package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
- package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
- package/src/shared/scripts/skf-validate-output.py +712 -64
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +116 -10
- package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
- package/src/shared/scripts/skf-write-skill-brief.py +367 -19
- package/src/shared/tool-requirements.yaml +201 -0
- package/src/skf-analyze-source/SKILL.md +41 -36
- package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
- package/src/skf-analyze-source/customize.toml +36 -24
- package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
- package/src/skf-analyze-source/references/continue.md +2 -13
- package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
- package/src/skf-analyze-source/references/generate-briefs.md +121 -55
- package/src/skf-analyze-source/references/headless-contract.md +42 -15
- package/src/skf-analyze-source/references/identify-units.md +96 -110
- package/src/skf-analyze-source/references/init.md +73 -71
- package/src/skf-analyze-source/references/map-and-detect.md +123 -105
- package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
- package/src/skf-analyze-source/references/recommend.md +51 -70
- package/src/skf-analyze-source/references/scan-project.md +60 -84
- package/src/skf-analyze-source/references/scan-root.md +39 -0
- package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
- package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
- package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
- package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
- package/src/skf-audit-skill/SKILL.md +43 -51
- package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
- package/src/skf-audit-skill/customize.toml +41 -20
- package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
- package/src/skf-audit-skill/references/doc-drift.md +141 -0
- package/src/skf-audit-skill/references/headless-contract.md +29 -0
- package/src/skf-audit-skill/references/init.md +148 -210
- package/src/skf-audit-skill/references/re-index.md +96 -108
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +27 -18
- package/src/skf-audit-skill/references/severity-classify.md +79 -65
- package/src/skf-audit-skill/references/severity-rules.md +15 -6
- package/src/skf-audit-skill/references/structural-diff.md +75 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
- package/src/skf-brief-skill/SKILL.md +36 -25
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +17 -24
- package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +142 -125
- package/src/skf-brief-skill/references/confirm-brief.md +10 -8
- package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
- package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
- package/src/skf-brief-skill/references/gather-intent.md +87 -182
- package/src/skf-brief-skill/references/headless-args.md +84 -16
- package/src/skf-brief-skill/references/health-check.md +1 -1
- package/src/skf-brief-skill/references/invocation-contract.md +18 -13
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
- package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
- package/src/skf-brief-skill/references/scope-definition.md +123 -47
- package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +3 -2
- package/src/skf-brief-skill/references/write-brief.md +66 -57
- package/src/skf-campaign/SKILL.md +31 -34
- package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
- package/src/skf-campaign/customize.toml +47 -16
- package/src/skf-campaign/references/campaign-contracts.md +39 -29
- package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
- package/src/skf-campaign/references/health-check.md +7 -16
- package/src/skf-campaign/references/step-01-setup.md +46 -84
- package/src/skf-campaign/references/step-02-strategy.md +31 -30
- package/src/skf-campaign/references/step-03-pins.md +26 -18
- package/src/skf-campaign/references/step-04-provenance.md +24 -23
- package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
- package/src/skf-campaign/references/step-06-batch.md +41 -34
- package/src/skf-campaign/references/step-07-capstone.md +40 -25
- package/src/skf-campaign/references/step-08-verify.md +28 -29
- package/src/skf-campaign/references/step-09-refine.md +29 -30
- package/src/skf-campaign/references/step-10-export.md +48 -36
- package/src/skf-campaign/references/step-11-maintenance.md +31 -34
- package/src/skf-campaign/references/step-resume.md +37 -68
- package/src/skf-campaign/scripts/campaign-deps.py +57 -18
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
- package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
- package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
- package/src/skf-campaign/scripts/campaign-report.py +204 -37
- package/src/skf-campaign/scripts/campaign-state.py +1128 -0
- package/src/skf-campaign/scripts/campaign-status.py +10 -74
- package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
- package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
- package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
- package/src/skf-campaign/templates/campaign-report-template.md +5 -1
- package/src/skf-campaign/templates/kickoff-template.md +0 -14
- package/src/skf-create-skill/SKILL.md +27 -20
- package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
- package/src/skf-create-skill/assets/skill-sections.md +17 -6
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
- package/src/skf-create-skill/references/batch-mode.md +81 -0
- package/src/skf-create-skill/references/ccc-index-check.md +27 -0
- package/src/skf-create-skill/references/compile.md +107 -29
- package/src/skf-create-skill/references/component-extraction.md +113 -91
- package/src/skf-create-skill/references/enrich.md +41 -23
- package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
- package/src/skf-create-skill/references/extract.md +200 -161
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
- package/src/skf-create-skill/references/extraction-patterns.md +584 -196
- package/src/skf-create-skill/references/generate-artifacts.md +145 -93
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +53 -36
- package/src/skf-create-skill/references/relabel-rule.md +12 -0
- package/src/skf-create-skill/references/report.md +28 -59
- package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
- package/src/skf-create-skill/references/step-auto-shard.md +20 -93
- package/src/skf-create-skill/references/step-doc-rot.md +44 -60
- package/src/skf-create-skill/references/step-doc-sources.md +55 -18
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -57
- package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
- package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
- package/src/skf-create-skill/references/validate.md +173 -99
- package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
- package/src/skf-create-stack-skill/SKILL.md +29 -56
- package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
- package/src/skf-create-stack-skill/customize.toml +23 -12
- package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
- package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
- package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
- package/src/skf-create-stack-skill/references/generate-output.md +138 -128
- package/src/skf-create-stack-skill/references/init.md +90 -32
- package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
- package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
- package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
- package/src/skf-create-stack-skill/references/report.md +39 -33
- package/src/skf-create-stack-skill/references/validate.md +20 -39
- package/src/skf-drop-skill/SKILL.md +28 -51
- package/src/skf-drop-skill/customize.toml +44 -30
- package/src/skf-drop-skill/references/execute.md +79 -146
- package/src/skf-drop-skill/references/invocation-contract.md +64 -0
- package/src/skf-drop-skill/references/report.md +46 -30
- package/src/skf-drop-skill/references/select.md +118 -124
- package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
- package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
- package/src/skf-export-skill/SKILL.md +40 -62
- package/src/skf-export-skill/assets/managed-section-format.md +14 -50
- package/src/skf-export-skill/assets/snippet-format.md +3 -1
- package/src/skf-export-skill/customize.toml +42 -13
- package/src/skf-export-skill/references/generate-snippet.md +54 -46
- package/src/skf-export-skill/references/health-check.md +2 -0
- package/src/skf-export-skill/references/invocation-contract.md +15 -0
- package/src/skf-export-skill/references/load-skill.md +88 -62
- package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
- package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
- package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
- package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
- package/src/skf-export-skill/references/package.md +15 -73
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
- package/src/skf-export-skill/references/result-envelope.md +31 -16
- package/src/skf-export-skill/references/summary.md +41 -17
- package/src/skf-export-skill/references/token-report.md +4 -12
- package/src/skf-export-skill/references/update-context.md +118 -237
- package/src/skf-forger/SKILL.md +61 -37
- package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
- package/src/skf-forger/customize.toml +43 -0
- package/src/skf-forger/references/pipeline-mode.md +73 -18
- package/src/skf-forger/scripts/forge-status.py +299 -0
- package/src/skf-forger/scripts/parse-pipeline.py +322 -54
- package/src/skf-forger/scripts/pipeline-gate.py +428 -0
- package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
- package/src/skf-quick-skill/SKILL.md +54 -53
- package/src/skf-quick-skill/assets/skill-template.md +4 -2
- package/src/skf-quick-skill/customize.toml +51 -20
- package/src/skf-quick-skill/references/batch-mode.md +74 -21
- package/src/skf-quick-skill/references/compile.md +30 -31
- package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
- package/src/skf-quick-skill/references/finalize.md +69 -18
- package/src/skf-quick-skill/references/halt-contract.md +41 -29
- package/src/skf-quick-skill/references/health-check.md +5 -3
- package/src/skf-quick-skill/references/quick-extract.md +114 -45
- package/src/skf-quick-skill/references/registry-resolution.md +9 -64
- package/src/skf-quick-skill/references/resolve-target.md +116 -66
- package/src/skf-quick-skill/references/write-and-validate.md +79 -40
- package/src/skf-refine-architecture/SKILL.md +43 -53
- package/src/skf-refine-architecture/customize.toml +49 -20
- package/src/skf-refine-architecture/references/compile.md +97 -54
- package/src/skf-refine-architecture/references/exit-codes.md +30 -0
- package/src/skf-refine-architecture/references/finding-storage.md +21 -0
- package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
- package/src/skf-refine-architecture/references/improvements.md +14 -20
- package/src/skf-refine-architecture/references/init.md +98 -57
- package/src/skf-refine-architecture/references/issue-detection.md +32 -39
- package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
- package/src/skf-refine-architecture/references/report.md +65 -54
- package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
- package/src/skf-rename-skill/SKILL.md +19 -54
- package/src/skf-rename-skill/customize.toml +32 -26
- package/src/skf-rename-skill/references/execute.md +230 -184
- package/src/skf-rename-skill/references/exit-codes.md +7 -7
- package/src/skf-rename-skill/references/health-check.md +1 -7
- package/src/skf-rename-skill/references/invocation-contract.md +25 -0
- package/src/skf-rename-skill/references/report.md +63 -52
- package/src/skf-rename-skill/references/select.md +197 -115
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
- package/src/skf-setup/SKILL.md +26 -26
- package/src/skf-setup/customize.toml +14 -10
- package/src/skf-setup/references/auto-index.md +50 -63
- package/src/skf-setup/references/ccc-index.md +29 -89
- package/src/skf-setup/references/detect-and-tier.md +58 -66
- package/src/skf-setup/references/health-check.md +2 -0
- package/src/skf-setup/references/invocation-contract.md +14 -0
- package/src/skf-setup/references/report.md +43 -166
- package/src/skf-setup/references/tier-rules.md +5 -5
- package/src/skf-setup/references/write-config.md +34 -57
- package/src/skf-test-skill/SKILL.md +17 -57
- package/src/skf-test-skill/assets/output-section-formats.md +33 -34
- package/src/skf-test-skill/customize.toml +27 -13
- package/src/skf-test-skill/references/coherence-check.md +134 -62
- package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
- package/src/skf-test-skill/references/coverage-check.md +217 -254
- package/src/skf-test-skill/references/detect-mode.md +5 -5
- package/src/skf-test-skill/references/external-validators.md +94 -82
- package/src/skf-test-skill/references/health-check.md +6 -7
- package/src/skf-test-skill/references/init.md +163 -88
- package/src/skf-test-skill/references/invocation-contract.md +66 -0
- package/src/skf-test-skill/references/migration-section-rules.md +5 -2
- package/src/skf-test-skill/references/report.md +162 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +41 -155
- package/src/skf-test-skill/references/source-access-protocol.md +19 -92
- package/src/skf-test-skill/references/step-hard-gate.md +51 -33
- package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
- package/src/skf-test-skill/scripts/build-result-context.py +287 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
- package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
- package/src/skf-test-skill/scripts/compute-score.py +223 -45
- package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
- package/src/skf-test-skill/scripts/score-signatures.py +459 -0
- package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
- package/src/skf-test-skill/templates/test-report-template.md +21 -15
- package/src/skf-update-skill/SKILL.md +38 -25
- package/src/skf-update-skill/customize.toml +27 -12
- package/src/skf-update-skill/references/detect-changes.md +233 -222
- package/src/skf-update-skill/references/gap-driven.md +336 -0
- package/src/skf-update-skill/references/health-check.md +31 -5
- package/src/skf-update-skill/references/init.md +250 -84
- package/src/skf-update-skill/references/invocation-contract.md +12 -0
- package/src/skf-update-skill/references/manual-section-rules.md +6 -23
- package/src/skf-update-skill/references/merge.md +180 -47
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +100 -35
- package/src/skf-update-skill/references/write.md +331 -149
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
- package/src/skf-verify-stack/SKILL.md +23 -42
- package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
- package/src/skf-verify-stack/customize.toml +55 -22
- package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
- package/src/skf-verify-stack/references/coverage.md +67 -64
- package/src/skf-verify-stack/references/exit-codes.md +21 -8
- package/src/skf-verify-stack/references/init.md +107 -62
- package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
- package/src/skf-verify-stack/references/integrations.md +106 -65
- package/src/skf-verify-stack/references/report.md +59 -42
- package/src/skf-verify-stack/references/requirements.md +32 -9
- package/src/skf-verify-stack/references/synthesize.md +53 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
- package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
- package/tools/cli/commands/install.js +11 -4
- package/tools/cli/commands/status.js +15 -3
- package/tools/cli/commands/update.js +11 -4
- package/tools/cli/lib/tool-check.js +320 -0
- package/tools/cli/lib/version-check.js +22 -9
- package/tools/cli/skf-cli.js +4 -1
- package/.gitattributes +0 -16
- package/.nvmrc +0 -1
- package/docs/_internal/RELEASING.md +0 -645
- package/release-audits/v1.0.0-launch-audit.md +0 -728
- package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
- package/src/skf-campaign/manifest.yaml +0 -15
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
- package/src/skf-create-skill/references/ecosystem-check.md +0 -74
- package/src/skf-drop-skill/references/headless-contract.md +0 -18
- package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
- package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
- package/src/skf-update-skill/references/validate.md +0 -124
- package/tools/validate-docs-drift.js +0 -233
- package/tools/validate-docs-links.js +0 -665
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'identify-units.md'
|
|
3
3
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
4
|
-
heuristicsFile: '
|
|
4
|
+
heuristicsFile: 'references/unit-detection-heuristics.md'
|
|
5
|
+
scanRootFile: 'references/scan-root.md'
|
|
5
6
|
scanManifestsProbeOrder:
|
|
6
7
|
- '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
|
|
7
8
|
- '{project-root}/src/shared/scripts/skf-scan-manifests.py'
|
|
9
|
+
detectWorkspacesProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-workspaces.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-detect-workspaces.py'
|
|
8
12
|
---
|
|
9
13
|
|
|
10
14
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -13,71 +17,75 @@ scanManifestsProbeOrder:
|
|
|
13
17
|
|
|
14
18
|
## STEP GOAL:
|
|
15
19
|
|
|
16
|
-
To map
|
|
20
|
+
To map each project path's structure from its file list, its package manifests and its workspace layout, which the helpers read, and to list the candidate boundaries that subsequent steps use for unit identification.
|
|
17
21
|
|
|
18
22
|
## Rules
|
|
19
23
|
|
|
20
24
|
- Focus only on structural scanning — do not classify units or map exports yet
|
|
21
|
-
-
|
|
22
|
-
- Delegate per-file scanning to subagents in parallel when many files are involved (main-thread fallback is fine)
|
|
23
|
-
- Tier-aware scanning depth: Quick (file structure), Forge (+ manifest parsing), Deep (+ config analysis)
|
|
25
|
+
- Read no file contents: the helpers read the manifests
|
|
24
26
|
|
|
25
27
|
## MANDATORY SEQUENCE
|
|
26
28
|
|
|
29
|
+
Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one, then run
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
|
|
36
|
+
|
|
27
37
|
### 1. Load Context
|
|
28
38
|
|
|
29
39
|
Read {outputFile} frontmatter to obtain:
|
|
30
|
-
- `project_paths[]
|
|
31
|
-
- `
|
|
32
|
-
- `
|
|
33
|
-
- Scope hints (if any were provided in step 01)
|
|
40
|
+
- `project_paths[]`: the root(s) to scan (one or more paths/URLs)
|
|
41
|
+
- `refs`: each project path's ref (a path it leaves out has none)
|
|
42
|
+
- `scope_hint`: the folders or packages to focus on or skip (may be empty)
|
|
34
43
|
|
|
35
44
|
Load {heuristicsFile} for reference on detection signals.
|
|
36
45
|
|
|
37
46
|
### 2. Scan Directory Structure
|
|
38
47
|
|
|
39
|
-
**Resolve `{scanManifestsHelper}`** from `{scanManifestsProbeOrder}`; first existing path wins.
|
|
48
|
+
**Resolve `{scanManifestsHelper}`** from `{scanManifestsProbeOrder}` and **`{detectWorkspacesHelper}`** from `{detectWorkspacesProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `scan-project:2`): "`{the missing script}` is missing. Re-install SKF."
|
|
40
49
|
|
|
41
|
-
**
|
|
50
|
+
**The scan root of each project path.** Every helper from here on reads a local folder, the path's **scan root**, which §6 records in `scan_roots` so the later steps read the same files. Load {scanRootFile} and make the scan root of each entry of `project_paths[]` as it says. If a command there fails, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `scan-project:2`, path `{path}`): "{path} could not be fetched: {the first stderr line}."
|
|
42
51
|
|
|
43
|
-
**
|
|
52
|
+
**For each path in `project_paths[]`**, the `{i}`-th, scan its scan root with the helpers, never by walking its tree yourself (aggregate the results across all repos, grouped by project path):
|
|
44
53
|
|
|
45
|
-
1.
|
|
46
|
-
2. Identify workspace configuration files (pnpm-workspace.yaml, lerna.json, Cargo.toml [workspace], go.work, etc.)
|
|
47
|
-
3. Enumerate package manifests deterministically — invoke `uv run {scanManifestsHelper} scan {path}` and parse the JSON envelope. The script returns `{manifests[], total_unique, monorepo, warnings?}` covering npm/python/rust/go/maven/gradle/ruby/composer/swift; record each `{path, ecosystem}` for the manifests catalog in §4 and capture `monorepo` for the boundary-signal pass in §3
|
|
48
|
-
4. Locate entry point files (index.ts, main.ts, app.ts, main.go, main.rs, __init__.py, etc.)
|
|
49
|
-
5. Detect service configuration (Dockerfile, docker-compose.yml, kubernetes manifests, serverless.yml) — keep this step LLM-driven; file glob + presence check is sufficient, no parsing required
|
|
50
|
-
6. Return structured findings — file paths and types only, not contents. When `constituent_refs` was used, include the resolved ref in each repo-level result group: `{path, ref, manifests[], monorepo, warnings?}`
|
|
54
|
+
1. List its files once. For a scan root inside a git work tree (`git -C "{scan_root}" rev-parse --is-inside-work-tree` prints `true`) run the first command, which lists the tracked files and the untracked ones git does not ignore, as `skf-disqualify-candidates.py` lists a boundary's files. Run the second for any other folder, and when the first fails or writes an empty file (a folder that an outer work tree ignores). If neither lists a file, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `scan-project:2`, path `{path}`): "The files of {path} could not be listed: {the first stderr line}."
|
|
51
55
|
|
|
52
|
-
|
|
56
|
+
```bash
|
|
57
|
+
git -C "{scan_root}" -c core.quotePath=false ls-files --cached --others --exclude-standard > "{run_dir}/tree-{i}.txt"
|
|
58
|
+
(cd "{scan_root}" && find . -type f -not -path '*/.git/*' | sed 's#^\./##') > "{run_dir}/tree-{i}.txt"
|
|
59
|
+
```
|
|
53
60
|
|
|
54
|
-
|
|
55
|
-
- If specific directories were given, scan only those
|
|
56
|
-
- If exclusion patterns were given, skip matching directories
|
|
61
|
+
2. Take the structure overview and the workspace layout from the tree snapshot, which counts the listing so you never do:
|
|
57
62
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
- If QMD is available, query for temporal context on the project: recent changes, active development areas, refactoring patterns
|
|
62
|
-
- Record Deep-tier findings separately — they supplement (not replace) the Quick/Forge scan results
|
|
63
|
+
```bash
|
|
64
|
+
uv run {detectWorkspacesHelper} --tree-file "{run_dir}/tree-{i}.txt" --manifest-dir "{scan_root}" --snapshot > "{run_dir}/snapshot-{i}.json"
|
|
65
|
+
```
|
|
63
66
|
|
|
64
|
-
|
|
67
|
+
It holds `file_count`, `dir_count`, `top_level_files`, `top_level_dirs`, the workspace layout (`manifest_kind`) and its `workspaces` (`{name, path, manifest}` each), and `warnings`.
|
|
68
|
+
3. Enumerate the package manifests and the candidate boundaries, with the snapshot's workspaces:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
uv run {scanManifestsHelper} scan "{scan_root}" --workspaces-file "{run_dir}/snapshot-{i}.json" > "{run_dir}/manifests-{i}.json"
|
|
72
|
+
```
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
The envelope holds `manifests[]` (npm/python/rust/go/maven/gradle/ruby/composer/swift, each with its `path` and `ecosystem`, for the §4 catalog), `monorepo`, `services[]` (each Docker, compose or serverless file, for the §4 catalog: a presence check, no parsing), `candidates[]` (§3) and `warnings`.
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
76
|
+
Keep, per project path, `{path, ref, scan_root}`, the snapshot's structure overview and the scan's `manifests[]`, `services[]`, `candidates[]`, `monorepo` and `warnings`: §3 to §6 read them.
|
|
77
|
+
|
|
78
|
+
### 3. Detect Service Boundaries
|
|
79
|
+
|
|
80
|
+
Each project path's candidate boundaries are its scan's `candidates[]` ({heuristicsFile}'s **Candidate Boundaries**). When `scope_hint` is not empty, keep only the candidates inside the folders or packages it focuses on, and drop those inside the folders it skips. A candidate's signals are reported, never judged: an independent package manifest (its `manifests`), a Docker or service definition (its `services`) and workspace membership (its `workspace_member`). Judge only each candidate's boundary type and confidence.
|
|
73
81
|
|
|
74
82
|
**Document each detected boundary with:**
|
|
75
|
-
-
|
|
83
|
+
- The project path it was found under, and its path relative to that path's scan root
|
|
76
84
|
- Boundary type (service / package / module)
|
|
77
85
|
- Detection signals found (list specific files)
|
|
78
86
|
- Confidence level (strong / moderate / weak)
|
|
79
87
|
|
|
80
|
-
### 4. Catalog Manifests and
|
|
88
|
+
### 4. Catalog Manifests and Service Configurations
|
|
81
89
|
|
|
82
90
|
Create a structured catalog:
|
|
83
91
|
|
|
@@ -86,71 +94,39 @@ Create a structured catalog:
|
|
|
86
94
|
|------|------|-------------------|
|
|
87
95
|
| {path} | {manifest_type} | {language} |
|
|
88
96
|
|
|
89
|
-
**Entry points found:**
|
|
90
|
-
| Path | Type |
|
|
91
|
-
|------|------|
|
|
92
|
-
| {path} | {entry_type} |
|
|
93
|
-
|
|
94
97
|
**Service configurations found:**
|
|
95
98
|
| Path | Type |
|
|
96
99
|
|------|------|
|
|
97
100
|
| {path} | {config_type} |
|
|
98
101
|
|
|
99
|
-
### 5. Present Scan
|
|
102
|
+
### 5. Present the Scan and Confirm
|
|
100
103
|
|
|
101
|
-
"
|
|
104
|
+
Show the user, per project path: the structure overview, each detected boundary (path, type, signals, confidence), the §4 catalogs (manifests, service configurations), and the scope applied (`scope_hint`, or "Full project scan"). Then display:
|
|
102
105
|
|
|
103
|
-
**
|
|
104
|
-
**Forge Tier:** {forge_tier}
|
|
106
|
+
"Anything to rescan, investigate further or skip? Tell me, or **Select:** [C] Continue to Unit Identification | [X] Cancel and exit"
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
{top-level directory tree}
|
|
108
|
-
|
|
109
|
-
**Detected Boundaries:** {count}
|
|
110
|
-
{list each boundary with path, type, confidence}
|
|
111
|
-
|
|
112
|
-
**Manifests Found:** {count}
|
|
113
|
-
{summary table}
|
|
114
|
-
|
|
115
|
-
**Entry Points Found:** {count}
|
|
116
|
-
{summary table}
|
|
117
|
-
|
|
118
|
-
**Service Configurations:** {count}
|
|
119
|
-
{summary table}
|
|
108
|
+
#### Menu Handling Logic:
|
|
120
109
|
|
|
121
|
-
|
|
110
|
+
- IF C: go to §6
|
|
111
|
+
- IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `scan-project:5`): "Cancelled at the project scan."
|
|
112
|
+
- IF Any other: rescan or skip as directed, show what changed, then [Redisplay Menu Options](#5-present-the-scan-and-confirm)
|
|
122
113
|
|
|
123
|
-
|
|
114
|
+
**GATE [default: C]**: present the menu and wait for the user's choice. If `{headless_mode}`: continue with [C], and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "scan-project.scan", "default_action": "C", "taken_action": "C", "reason": "headless: auto-continue past scan results", "evidence": {"project_paths": <the project path count>, "boundaries": <the boundary count>}}`, then run
|
|
124
115
|
|
|
125
|
-
|
|
116
|
+
```bash
|
|
117
|
+
uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
118
|
+
```
|
|
126
119
|
|
|
127
|
-
|
|
120
|
+
If the command fails, go on: only that entry is lost.
|
|
128
121
|
|
|
129
|
-
|
|
122
|
+
### 6. Append to Report and Continue
|
|
130
123
|
|
|
131
|
-
Replace the placeholder `[Appended by scan-project]` with the
|
|
132
|
-
- Structure overview
|
|
133
|
-
- Detected boundaries table
|
|
134
|
-
- Manifests catalog
|
|
135
|
-
- Entry points catalog
|
|
136
|
-
- Service configurations catalog
|
|
137
|
-
- Scope notes
|
|
124
|
+
Replace the placeholder `[Appended by scan-project]` in {outputFile} with the scan results: the structure overview, the detected boundaries table, the manifests and service configurations catalogs, and the scope notes, grouped by project path when there are several. Update its frontmatter:
|
|
138
125
|
|
|
139
|
-
Update {outputFile} frontmatter:
|
|
140
126
|
```yaml
|
|
141
127
|
stepsCompleted: [append 'scan-project' to existing array]
|
|
142
128
|
lastStep: 'scan-project'
|
|
129
|
+
scan_roots: {each project path: its scan root}
|
|
143
130
|
```
|
|
144
131
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
Display: "**Select:** [C] Continue to Unit Identification | [X] Cancel and exit"
|
|
148
|
-
|
|
149
|
-
#### Menu Handling Logic:
|
|
150
|
-
|
|
151
|
-
- IF C: Save scan results to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
|
|
152
|
-
- IF X: HARD HALT with exit code 6 (`user-cancelled`). Emit the error envelope on stderr with `halt_reason: "user-cancelled"` and counts/paths reflecting state at cancellation (shape in `references/headless-contract.md`)
|
|
153
|
-
- IF Any other: help user, then [Redisplay Menu Options](#7-present-menu-options)
|
|
154
|
-
|
|
155
|
-
**GATE [default: C]** — present the menu and wait for the user's choice. If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-continue past scan results".
|
|
156
|
-
|
|
132
|
+
Then load, read the entire file, then execute {nextStepFile}.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
---
|
|
2
|
+
skillInventoryProbeOrder:
|
|
3
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
4
|
+
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
8
|
+
|
|
9
|
+
# The Scan Root of a Project Path
|
|
10
|
+
|
|
11
|
+
Every helper of the step-by-step analysis reads a local folder, the project path's **scan root**, never `{project-root}` (the forge workspace). scan-project makes one for each entry of `project_paths[]` and records it in the report's `scan_roots`, discover-additional-source makes one for the path it adds, and identify-units and map-and-detect make one again when a session that resumed the report no longer finds it. `{i}` is the path's place in `project_paths[]` (1 for the first), and its **ref** is its entry in the report's `refs` (a path `refs` leaves out has none). In every command below, a leading `~` of a local path is written as `$HOME`: the commands quote every path, and a `~` inside double quotes does not expand.
|
|
12
|
+
|
|
13
|
+
**What the path is.** The helper that names every unit tells a local path from a repository and gives the URL git clones a repository from. Resolve `{skillInventoryHelper}` from `{skillInventoryProbeOrder}` (first existing path wins; with none, the command below fails with "`skf-skill-inventory.py` is missing. Re-install SKF." as its first stderr line) and run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
uv run {skillInventoryHelper} derive-name --target "{path}" --probe-git
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Its `kind` is `local` for a local path, `remote` for a repository and `docs` for a documentation URL, and its `clone_url` is the URL git reads for a repository.
|
|
20
|
+
|
|
21
|
+
- **A local path** (`kind` is `local`) **with no ref:** the path itself. Nothing is copied.
|
|
22
|
+
- **A local path with a ref:** the path's folder inside a copy of its repository at the ref, so a package folder of a monorepo is read at the ref too. Print the repository's top folder and the path's place in it, then copy the top folder:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
git -C "{path}" rev-parse --show-toplevel --show-prefix
|
|
26
|
+
git clone --quiet --branch {ref} "{the first line it printed}" "{run_dir}/source-{i}"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The scan root is `{run_dir}/source-{i}/` followed by the second line without its trailing slash, or `{run_dir}/source-{i}` itself when that line is empty (the path is the top folder).
|
|
30
|
+
- **A remote path** (`kind` is `remote`): a copy at its ref, or at the default branch when it has none, which is the scan root:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
git clone --quiet --depth 1 {ref_flag} "{clone_url}" "{run_dir}/source-{i}"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`{ref_flag}` is `--branch {ref}` when the path has a ref, else nothing. The project path stays as it was given everywhere else: in `project_paths[]`, the keys of `scan_roots` and `refs`, and each brief's `source_repo`.
|
|
37
|
+
- **A documentation URL** (`kind` is `docs`): there is no repository to scan. Treat it as a command that failed with its `halt_message` as the first stderr line when it gives one (the message the [auto] path halts with), else with "{path} is a documentation URL: run the analysis with [auto] for a docs-only brief".
|
|
38
|
+
|
|
39
|
+
When a command fails, the file that loaded this one says what happens, with the first line it printed on stderr.
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
2
|
+
|
|
3
|
+
# Step 1a §0c: Coexistence Gate
|
|
4
|
+
|
|
5
|
+
Loaded by `step-auto-scope.md` when a skill already holds the name or the source this run would forge: from §0c when its `matches[]` has one or more entries, and from §6 when the derived name belongs to a skill from another source, which §6 passes as the one `matches[]` entry. Each entry is `{name, active_version, source_repo, active_path, match_reason, skf_skill}`; `skf_skill` is true when SKF generated the matched skill. Only those are offered for a merge: a merge hands the skill to update-skill, which rewrites its files, and SKF changes only the skills it generated.
|
|
6
|
+
|
|
7
|
+
## MANDATORY SEQUENCE
|
|
8
|
+
|
|
9
|
+
### 4. Present the Coexistence Gate
|
|
10
|
+
|
|
11
|
+
Present the user with the coexistence decision, one bullet per `matches[]` entry (`{skill_name}` = `matches[].name`, `{version}` = `matches[].active_version`, `{source_repo}` = `matches[].source_repo`). Append " (not SKF output, merge not offered)" to the bullet of every entry whose `matches[].skf_skill` is false, and leave the `[M]erge` line out when no entry has `matches[].skf_skill` true:
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
⚠️ Existing skill(s) found for {target_name}:
|
|
15
|
+
|
|
16
|
+
• {skill_name} (v{version}), source: {source_repo}
|
|
17
|
+
[repeat for each entry in matches[]]
|
|
18
|
+
|
|
19
|
+
Actions:
|
|
20
|
+
[A]longside: Create a new wiki skill with "-wiki" suffix (existing skill untouched)
|
|
21
|
+
[M]erge: Update the existing skill via US workflow (wiki data enriches it; SKF-generated skills only)
|
|
22
|
+
[S]kip: Do not create or modify any skill for this library
|
|
23
|
+
|
|
24
|
+
Choose [A/M/S]:
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**GATE [default: A]**: in headless mode (`{headless_mode}` is true), auto-select `[A]longside` and log: "Headless: coexistence detected for {target_name}, auto-selecting [A]longside". The envelope's `coexistence` field carries the choice.
|
|
28
|
+
|
|
29
|
+
### 5. Handle the Selection
|
|
30
|
+
|
|
31
|
+
- **[A]longside:** Set `{coexistence_suffix}` to `-wiki`; the existing skill is untouched. Return to the section that loaded this file: from §0c, continue with `references/auto-docs-only.md` for a documentation URL and with §1 for every other input; from §6, go on with §6.
|
|
32
|
+
|
|
33
|
+
- **[M]erge:** Offered only for entries whose `matches[].skf_skill` is true. If more than one such entry exists, prompt the user to select which one to merge into before proceeding. Read `{matched_skill_name}` = the selected entry's `matches[].name` and `{matched_active_path}` = its `matches[].active_path`. End the run as `step-auto-scope.md` §9 says, with a redirect that signals the forger to route to the US workflow for the selected skill: write `{run_dir}/result-context.json` as
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{"status": "redirect", "redirect_to": "US", "skill_name": "{matched_skill_name}", "skill_path": "{matched_active_path}", "mode": "auto", "coexistence": "merge", "result_contract": {"skill": "skf-analyze-source", "status": "redirect", "outputs": [], "summary": {"mode": "auto", "redirect_to": "US", "skill_name": "{matched_skill_name}"}}}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
and go to §9 of `step-auto-scope.md`. **STOP HERE: do not proceed to the docs-only sub-flow or §1.**
|
|
40
|
+
|
|
41
|
+
- **[S]kip:** End the run as `step-auto-scope.md` §9 says, with a skip: write `{run_dir}/result-context.json` as
|
|
42
|
+
|
|
43
|
+
```json
|
|
44
|
+
{"status": "skipped", "unit_counts": {"confirmed": 0, "skipped": 1, "maybe": 0}, "mode": "auto", "coexistence": "skip", "skipped_reason": "Existing skill for {matched_skill_name}", "result_contract": {"skill": "skf-analyze-source", "status": "skipped", "outputs": [], "summary": {"mode": "auto", "skipped_reason": "Existing skill for {matched_skill_name}"}}}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
and go to §9 of `step-auto-scope.md`. **STOP HERE: do not proceed to the docs-only sub-flow or §1.**
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
languageCorporaProbeOrder:
|
|
3
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-language-corpora.py'
|
|
4
|
+
- '{project-root}/src/shared/scripts/skf-language-corpora.py'
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
8
|
+
|
|
9
|
+
# Step 1a §6b: Seed Companion Corpora (whole-language references only)
|
|
10
|
+
|
|
11
|
+
Loaded by `step-auto-scope.md` §6 only when §3 classified the repo as `language-reference` **via a whole-language signal**: its `signals` array holds a `grammar_file:` or `tree_triad:` entry (a compiler, interpreter or grammar repo such as rust-lang/rust, TypeScript or CPython). A `language-reference` that fired only from `parser_producer:` or `parser_dep:` signals (a parser *library* such as pest or lalrpop) never loads it: there the code **is** the product, so no companion prose is needed and no caveat applies.
|
|
12
|
+
|
|
13
|
+
A whole-language skill's value is in the language's **prose** (the guide or Book, the standard and library API docs, idioms), not the compiler internals. Seed those canonical corpora so the forged skill teaches the language rather than its implementation. This file sets `{corpus_seeds}`, `{corpus_caveat}` and the Companion Corpora subsection, then returns to §6. It never halts: the lookup is best-effort.
|
|
14
|
+
|
|
15
|
+
## MANDATORY SEQUENCE
|
|
16
|
+
|
|
17
|
+
### 1. Look Up the Canonical Corpora
|
|
18
|
+
|
|
19
|
+
**Resolve `{languageCorporaHelper}`** from `{languageCorporaProbeOrder}` (first existing path wins). When neither path exists, record the warning `language_corpora_unavailable: skf-language-corpora.py is missing` with `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning '<the warning>'` and treat `{corpus_seeds}` as empty.
|
|
20
|
+
|
|
21
|
+
1. **The corpus language key `{corpus_language}`** ← `{detected_language}` from §5, which a manifest-less toolchain such as CPython or Ruby gets from its source files.
|
|
22
|
+
2. **Look up canonical corpora:**
|
|
23
|
+
```bash
|
|
24
|
+
uv run {languageCorporaHelper} --language {corpus_language}
|
|
25
|
+
```
|
|
26
|
+
- exit 0: parse the `[{url, label, source}]` array (each seed carries `source: language-registry`); these are `{corpus_seeds}`.
|
|
27
|
+
- exit 1: no registry entry (a long-tail language), so `{corpus_seeds}` is empty (README detection in brief-skill remains the only source).
|
|
28
|
+
- exit 2: record the warning `language_corpora_failed: <its first stderr line>` the same way and treat it as empty.
|
|
29
|
+
3. Record `{N}` = the number of seeds and `{corpus_labels}` = their labels, comma-joined.
|
|
30
|
+
|
|
31
|
+
### 2. Build the Caveat and the Brief's Doc URLs
|
|
32
|
+
|
|
33
|
+
`{corpus_caveat}`, which §6 appends to `scope.notes`, tells the operator that a code-only whole-language skill is low-value:
|
|
34
|
+
|
|
35
|
+
- `{N}` ≥ 1: `" LANGUAGE-REFERENCE CAVEAT: this skill's value is the {corpus_language} prose (guide/Book + std/library docs), not compiler internals. Seeded {N} corpus URL(s): {corpus_labels}. create-skill foregrounds this registry prose as the skill's Language Guide and demotes compiler-internal signatures to a reference-only section: review the forged skill if compiler internals still dominate."`
|
|
36
|
+
- `{N}` == 0: `" LANGUAGE-REFERENCE CAVEAT: no canonical corpora were found for {corpus_language} (README detection and the registry both came up empty). This skill is LOW-VALUE as code-only: attach the {corpus_language} guide + std/library docs manually (re-run with a doc URL, or enrich via US) before forging."`
|
|
37
|
+
|
|
38
|
+
`{corpus_doc_urls}`, which §8 writes as the brief's `doc_urls`: one `{"url": "{seed.url}", "label": "{seed.label}", "source": "{seed.source}"}` per seed (its `source` is `language-registry`), so the language's prose is fetched and assembled alongside the code (brief-skill's README detection then merges more docs on top, existing entries winning); null when `{N}` is 0.
|
|
39
|
+
|
|
40
|
+
### 3. The Companion Corpora Subsection
|
|
41
|
+
|
|
42
|
+
§7 appends this to the report, so the operator sees whether the skill has the prose that makes it useful. The status comes from the **final** brief `doc_urls` (the entries that will actually be fetched), not the seed count alone:
|
|
43
|
+
|
|
44
|
+
```markdown
|
|
45
|
+
## Companion Corpora (language-reference)
|
|
46
|
+
|
|
47
|
+
**Why:** A whole-language skill's value is its prose (guide/Book, std/library docs, idioms), not compiler internals.
|
|
48
|
+
**Corpora in brief doc_urls:** {final_doc_urls_count}
|
|
49
|
+
- {label}: {url} # one line per doc_urls entry
|
|
50
|
+
**Status:** {ATTACHED: canonical corpora present | DEGRADED: code-only, no canonical corpora; attach the {corpus_language} guide + std/library docs before forging}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Then return to `step-auto-scope.md` §6.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
---
|
|
2
|
+
skillInventoryProbeOrder:
|
|
3
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
4
|
+
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
5
|
+
detectLanguageProbeOrder:
|
|
6
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
|
|
7
|
+
- '{project-root}/src/shared/scripts/skf-detect-language.py'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
11
|
+
|
|
12
|
+
# Step 1a §4a: Split a Monorepo into N Skills
|
|
13
|
+
|
|
14
|
+
Loaded by `step-auto-scope.md` §3b only when its cohesion check decided to **split** a monorepo (members independently published with distinct surfaces, and no umbrella re-exporting them). It replaces §4, §5 and §6 for a repo that produces N > 1 skills, then returns to §7 with the N boundaries. `{run_dir}`, `{scan_root}`, `{pinned_ref}`, `{coexistence_suffix}`, `intent_hint`, `scope_hint` and the §2 records carry into it.
|
|
15
|
+
|
|
16
|
+
## MANDATORY SEQUENCE
|
|
17
|
+
|
|
18
|
+
Every HARD HALT in this file names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "auto"}`, plus `"path"` when the halt names one, then run
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
|
|
25
|
+
|
|
26
|
+
**Resolve `{skillInventoryHelper}`** from `{skillInventoryProbeOrder}` and **`{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `step-auto-scope-split:0`): "`{the missing script}` is missing. Re-install SKF."
|
|
27
|
+
|
|
28
|
+
### 4a. Decompose by Workspace Package
|
|
29
|
+
|
|
30
|
+
Each workspace package of the §2 manifest scan with its own manifest becomes a separate skill boundary; trivial workspace members (no source files, no exports) are excluded, and so is a member outside the folders `scope_hint` focuses on or under a folder it skips. Name the boundaries in one call to the helper that names every brief, one entry per boundary with its manifest `name` and `private` from §2:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uv run {skillInventoryHelper} derive-name --from - --skills-folder "{skills_output_folder}" <<'SKF_BOUNDARY_NAMES'
|
|
34
|
+
[{"target": "<boundary path>", "manifest_name": "<its manifest name>", "private": <its private flag>}, ...]
|
|
35
|
+
SKF_BOUNDARY_NAMES
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Each boundary's skill name is its `names[].name`: boundaries whose names would clash are already told apart by their parent folders, and the entries `unnamed` and `duplicates` list take a name you give them from their folder. A name whose `existing` is not null belongs to a skill from another source (§0c already offered the ones from this repository): give that boundary the `-wiki` suffix, as [A]longside does, and record it as a warning, so it reaches the envelope:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning 'coexistence: {name} exists, forging {name}-wiki alongside'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
(a single quote in the name written as a backtick; if the command fails, go on). Then append `{coexistence_suffix}` to every name that does not already end with it, when it is non-empty.
|
|
45
|
+
|
|
46
|
+
**Per-boundary shape to scope mapping:** for each boundary, apply the §4 mapping independently, re-running the shape-to-scope ladder of `step-shape-detect.md` per package with each package's own manifest data. Packages may have different shapes (for example a `library-API` core and a `reference-app` CLI).
|
|
47
|
+
|
|
48
|
+
### 5a. Generate Multi-Scope Patterns
|
|
49
|
+
|
|
50
|
+
For boundary `{i}`, list its files, detect its language from them without `--workspace-signal` (the workspace root's language would answer for every boundary) and read it as §5 says, the boundary's own manifest standing for the scan-root manifest. Its include and exclude patterns are the ones `scope-patterns` prints for that language, rooted at the boundary's source folder (`packages/auth/src/**/*.ts`):
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
awk -v p="<boundary path>/" 'index($0, p) == 1' "{run_dir}/tree.txt" > "{run_dir}/tree-{i}.txt"
|
|
54
|
+
uv run {detectLanguageHelper} --tree-file "{run_dir}/tree-{i}.txt"
|
|
55
|
+
uv run {detectLanguageHelper} scope-patterns --tree-file "{run_dir}/tree-{i}.txt" --language <its language>
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### 6a. Build Multi-Scope
|
|
59
|
+
|
|
60
|
+
This is the one statement of what each boundary's brief holds; §8 writes these values and the ones every brief shares (version, `source_repo`, `forge_tier`, `created`, `created_by` and the §0b pin: the pin targets a repo-level ref, not a package-level version). For boundary `{i}` of `{N}`:
|
|
61
|
+
|
|
62
|
+
- **Name:** the one §4a gave it, suffix included.
|
|
63
|
+
- **Scope:** `scope.type` from its §4a mapping, `scope.include` and `scope.exclude` from §5a, and `scope.notes` ← `Decomposed from {project_name} ({N} skills): boundary {i}/{N}, {boundary role}.`, where `{boundary role}` says in a few words what the boundary is for (for example `core library` or `CLI`).
|
|
64
|
+
- **Language:** the one §5a detected.
|
|
65
|
+
- **Description:** one to three sentences naming the parent project and the boundary's role (for example "Core library package of the my-monorepo project, providing..."), worded toward `intent_hint` when it is not empty.
|
|
66
|
+
|
|
67
|
+
### 7. The Decomposition Report
|
|
68
|
+
|
|
69
|
+
§7 writes `decomposition` into the frontmatter and appends this body in place of the single-scope section:
|
|
70
|
+
|
|
71
|
+
```markdown
|
|
72
|
+
## Auto-Scope Analysis: Decomposition ({N} skills)
|
|
73
|
+
|
|
74
|
+
**Mode:** auto
|
|
75
|
+
**Decomposition:** {reason} ({N} boundaries)
|
|
76
|
+
**Parent Shape:** {shape} (confidence: {confidence})
|
|
77
|
+
**Export Count:** {export_count}
|
|
78
|
+
**Package Count:** {package_count}
|
|
79
|
+
|
|
80
|
+
### Boundary 1: {boundary_name}
|
|
81
|
+
**Scope Type:** {scope_type}
|
|
82
|
+
**Boundary Path:** {boundary_path}
|
|
83
|
+
**Include Patterns:** {include patterns}
|
|
84
|
+
**Exclude Patterns:** {exclude patterns}
|
|
85
|
+
**Rationale:** {boundary_rationale}
|
|
86
|
+
|
|
87
|
+
### Boundary 2: {boundary_name}
|
|
88
|
+
...
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
After building all N scopes, return to `step-auto-scope.md` §7 with the full set of boundaries.
|