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
|
@@ -10,69 +10,49 @@ The version-aware skill-enumeration protocol (export-manifest primary → active
|
|
|
10
10
|
|
|
11
11
|
## Compose-mode Co-mention Precision
|
|
12
12
|
|
|
13
|
-
Prose co-mention detection is heuristic
|
|
13
|
+
Prose co-mention detection is heuristic: it can only provide `Plausible`-class evidence (compared to code-mode's co-imports, which are literal). The matcher in step 5 §2 applies two guards, and reports two evidence fields that step 5 §2 weighs instead of filtering on them:
|
|
14
14
|
|
|
15
|
-
1. **Word-boundary matching** (`\b{skill_name}\b`, case-insensitive). Substring matches are rejected (no `react` inside `reactive`).
|
|
16
|
-
2. **
|
|
17
|
-
3.
|
|
15
|
+
1. **Word-boundary matching** (`\b{skill_name}\b`, case-insensitive). Substring matches are rejected (no `react` inside `reactive`). Headings are never co-mention sources.
|
|
16
|
+
2. **Listed pairs left out.** A pair named only in separate list items, table rows or code lines, as a Tech Stack table names every pair, is no candidate: `list_only_pair_count` counts those pairs.
|
|
17
|
+
3. **`excluded_section`.** True on an evidence entry whose paragraph sits under an introductory H1/H2 header (Overview, Introduction, Glossary and the like; `skf-comention-pairs.py`'s docstring lists the set): such sections often enumerate every library without describing an integration.
|
|
18
|
+
4. **`paragraph_count`.** The number of body paragraphs that name both libraries. One is enough to make a candidate: whether that passage describes an integration is a judgment on its excerpt.
|
|
18
19
|
|
|
19
|
-
**Known limitations:** even with
|
|
20
|
+
**Known limitations:** even with the guards, a co-mention only witnesses that two libraries are discussed together; it does not prove an integration exists, so every pair the matcher reports is a candidate step 5 §2 judges.
|
|
20
21
|
|
|
21
22
|
## Architecture Integration Mapping
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
1. Load the architecture document from `{architecture_doc_path}`
|
|
26
|
-
2. Parse section headers and prose paragraphs for references to loaded skill names
|
|
27
|
-
3. A **co-mention** is detected when a paragraph or section references 2+ loaded skill names
|
|
28
|
-
4. For each co-mention pair, load both skills' export lists and API signatures from their `SKILL.md`
|
|
29
|
-
5. Compose an integration section describing how the two libraries connect based on:
|
|
30
|
-
- Shared types or interfaces between the two skills' API surfaces
|
|
31
|
-
- Architecture document prose describing their interaction
|
|
32
|
-
- Complementary domain roles (e.g., one produces data the other consumes)
|
|
24
|
+
Step 5 §2 keeps a pair the architecture document names together only once its `unit_excerpt` shows how the two libraries work together, and writes it in the format below.
|
|
33
25
|
|
|
34
26
|
## Confidence Tier Inheritance
|
|
35
27
|
|
|
36
|
-
- All compose-mode evidence inherits confidence tiers from the source individual skills
|
|
37
|
-
-
|
|
38
|
-
-
|
|
39
|
-
- If either skill is T2, the structural confidence still inherits the lower of T1/T1-low from the pair — the T2 temporal annotations from that skill are carried as an additive enrichment marker, not a tier upgrade
|
|
40
|
-
- T1 + T2 pair: inherits `T1 [composed, +T2 annotations]` — the T1 skill provides full structural confidence
|
|
41
|
-
- T1-low + T2 pair: inherits `T1-low [composed, +T2 annotations]` — T1-low structural confidence with T2 temporal annotations noted
|
|
42
|
-
- If both skills are T2 (no T1/T1-low base available): the integration confidence is `T1-low [composed, +T2 annotations from both]` — T2 temporal enrichment depends on structural extraction, so the most conservative structural tier is assumed
|
|
43
|
-
- Compose-mode integrations add suffix: `[composed]` — e.g., `T1 [composed]`, `T1-low [composed, +T2 annotations]`
|
|
28
|
+
- All compose-mode evidence inherits confidence tiers from the source individual skills. Each constituent's tier is its `per_library_extractions[].confidence`, which step 4 §0 takes from the constituent's `evidence_tier`.
|
|
29
|
+
- An integration's tier is the pair tier `skf-render-stack-metadata.py` gives it (`combine_pair_tier`, the one rule both modes use, stated in its `--help`); step 5 §3 runs it for every pair.
|
|
30
|
+
- Compose-mode integrations add suffix: `[composed]`, e.g. `T1 [composed]` or `T2 [composed]`, except one inferred from shared domain keywords, which takes `[inferred from shared domain]` instead.
|
|
44
31
|
|
|
45
32
|
## Integration Evidence Format
|
|
46
33
|
|
|
47
34
|
Each integration entry must cite both source skills by name with function signatures:
|
|
48
35
|
|
|
49
36
|
```
|
|
50
|
-
{Skill A name} + {Skill B name}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
37
|
+
#### {Skill A name} + {Skill B name}
|
|
38
|
+
**Type:** {pattern type from integration-patterns.md}
|
|
39
|
+
**Evidence:**
|
|
40
|
+
[from skill: {Skill A name}] {exported_function_signature}
|
|
41
|
+
[from skill: {Skill B name}] {exported_function_signature}
|
|
42
|
+
**Architecture reference:** "{unit_excerpt}" (architecture doc line {unit_line})
|
|
43
|
+
**Confidence:** {pair tier} ({qualifier}) [composed]
|
|
57
44
|
```
|
|
58
45
|
|
|
59
|
-
|
|
46
|
+
A pair found with no architecture document cites its own evidence in place of the architecture reference: `**Contract reference:** "{excerpt}" ({doc} line {line})` for a constituent-documented contract, or `**Shared domain:** {keywords}` for an inferred integration.
|
|
60
47
|
|
|
61
|
-
|
|
48
|
+
## Feasibility Report Integration
|
|
62
49
|
|
|
63
|
-
|
|
64
|
-
- **Schema version guard:** Parse frontmatter and confirm `schemaVersion == "1.0"`. On mismatch, HALT with an explicit error; never silently proceed with an unknown version.
|
|
65
|
-
- **Overall verdict tokens** (frontmatter `overallVerdict`, case-sensitive): exactly one of `FEASIBLE | CONDITIONALLY_FEASIBLE | NOT_FEASIBLE`.
|
|
66
|
-
- **Per-pair verdict tokens** (in the `## Integration Verdicts` table, case-sensitive): exactly one of `Verified | Plausible | Risky | Blocked`. Any unknown token is a hard error.
|
|
67
|
-
- Include the verdict in the integration evidence: `VS overall: {overallVerdict}`, `VS pair: {verdict}`.
|
|
68
|
-
- Flag pairs where VS reported `Risky` or `Blocked`.
|
|
50
|
+
Step 5 §2 reads the [VS] report (`shared/references/feasibility-report-schema.md`) through `skf-validate-feasibility-report.py --locate`. An architecture pair it rates (its bundle entry's `vs`) adds `VS overall: {overallVerdict}` and `VS pair: {verdict}` lines after its Architecture reference, and its Confidence line ends with a `[VS: Risky]` or `[VS: Blocked]` annotation for those verdicts. Pairs found without an architecture document carry no verdict: the report covers architecture-described interactions only.
|
|
69
51
|
|
|
70
52
|
## Inferred Integrations (No Architecture Document)
|
|
71
53
|
|
|
72
|
-
|
|
73
|
-
- Infer potential integrations from skills sharing the same `language` field
|
|
74
|
-
- Infer from skills sharing domain keywords in their `SKILL.md` descriptions
|
|
75
|
-
- Mark all inferred integrations: `[inferred from shared domain]`
|
|
76
|
-
- Inferred integrations default to lowest confidence of the pair with `[inferred from shared domain]` suffix (use this instead of `[composed]` for inferred integrations)
|
|
54
|
+
Step 5 §2 finds and judges these pairs in the constituents' own docs and domain keywords, never on a shared language alone.
|
|
77
55
|
|
|
78
|
-
|
|
56
|
+
- A docs mention step 5 §2 confirmed (a verifiable cross-library contract a constituent's own docs state, e.g. a grep-verified upstream seam) is recorded with `detection_method: constituent_documented_contract` (see `assets/provenance-map-schema.md`), NOT `inferred_from_shared_domain`, and labeled `[composed]`: a cited contract, not a synthesized guess.
|
|
57
|
+
- A shared-domain pair step 5 §2 kept is labeled `[inferred from shared domain]`.
|
|
58
|
+
- Detection method never sets the tier: each pair takes the tier `skf-render-stack-metadata.py` gives it.
|
|
@@ -9,6 +9,17 @@ comentionProbeOrder:
|
|
|
9
9
|
validateFeasibilityReportProbeOrder:
|
|
10
10
|
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-feasibility-report.py'
|
|
11
11
|
- '{project-root}/src/shared/scripts/skf-validate-feasibility-report.py'
|
|
12
|
+
renderStackMetadataProbeOrder:
|
|
13
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-render-stack-metadata.py'
|
|
14
|
+
- '{project-root}/src/shared/scripts/skf-render-stack-metadata.py'
|
|
15
|
+
emitEnvelopeProbeOrder:
|
|
16
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
|
|
17
|
+
- '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
|
|
18
|
+
bundleFile: '{run_dir}/extraction-bundle.json'
|
|
19
|
+
importCountsFile: '{run_dir}/import-counts.json'
|
|
20
|
+
pairsFile: '{run_dir}/pair-intersect.json'
|
|
21
|
+
# A fixed path: the compose rules are not a customization surface.
|
|
22
|
+
composeModeRulesPath: 'references/compose-mode-rules.md'
|
|
12
23
|
---
|
|
13
24
|
|
|
14
25
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -21,43 +32,40 @@ Analyze co-import patterns between confirmed libraries to identify integration p
|
|
|
21
32
|
|
|
22
33
|
## Rules
|
|
23
34
|
|
|
24
|
-
- Focus on detecting cross-library patterns
|
|
35
|
+
- Focus on detecting cross-library patterns from step 3's import counts and the pair helpers; never grep for imports by hand
|
|
25
36
|
- Do not compile SKILL.md (Step 06)
|
|
26
37
|
|
|
27
38
|
## MANDATORY SEQUENCE
|
|
28
39
|
|
|
40
|
+
**Halt envelope.** Every HALT in this step names its exit code, `halt_reason` and phase. Stage `{run_dir}/halt.json` as `{"phase": "<phase>", "halt_reason": "<halt_reason>", "reason": "<the halt message, one line>", "skill_name": "{stack_name}", "mode": "<code|compose>", "stack_libraries": ["<confirmed library>", ...]}`, adding `"path"` when the halt names a file, then run:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-create-stack-skill --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Display the line it prints, then stop with the halt's exit code (`references/invocation-contract.md` lists every halt). If `{emitEnvelopeHelper}` is not bound, resolve it from `{emitEnvelopeProbeOrder}`; if no path exists, or the emitter exits non-zero or prints no line, display the halt message alone.
|
|
47
|
+
|
|
48
|
+
**Warnings.** Each `workflow_warnings[]` entry this step appends is recorded at once: write its `[{step}/{severity}] {code}: {message}` line to `{run_dir}/warning.txt` with a file write, then run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning "$(cat "{run_dir}/warning.txt")"`.
|
|
49
|
+
|
|
50
|
+
Every library's tier (`per_library_extractions[].confidence`) comes from `{bundleFile}`, which step 4 wrote.
|
|
51
|
+
|
|
29
52
|
### 1. Generate Library Pairs
|
|
30
53
|
|
|
31
|
-
|
|
54
|
+
**If `compose_mode` is true:** step 3 counts no imports, so there are no per-library file lists to intersect: the §2 compose branch finds the candidates. Skip to [Detect Co-Import Files](#2-detect-co-import-files).
|
|
32
55
|
|
|
33
|
-
**
|
|
56
|
+
**If not compose_mode:**
|
|
34
57
|
|
|
35
|
-
1
|
|
36
|
-
```json
|
|
37
|
-
[
|
|
38
|
-
{"name": "<library-name>", "files": ["<rel-path-forward-slash>", ...]},
|
|
39
|
-
...
|
|
40
|
-
]
|
|
41
|
-
```
|
|
42
|
-
2. **Invoke the script** via stdin (or a temp file under `{forge_data_folder}/` if stdin piping is unavailable):
|
|
58
|
+
Of the N*(N-1)/2 pairs of `confirmed_dependencies`, only those whose per-library file lists overlap can integrate. This pass finds them for every N, and their shared files are §2's co-import evidence.
|
|
43
59
|
|
|
44
|
-
|
|
60
|
+
**Compute the intersection deterministically via the shared script.** Resolve `{pairIntersectHelper}` from `{pairIntersectProbeOrder}`; first existing path wins. If no candidate exists, HALT (exit 3, `halt_reason: "helper-missing"`, phase `detect-integrations:pair-intersect`) with "**Cannot proceed.** `skf-pair-intersect.py` is missing, so no library pair can be found. Re-install SKF, then re-run."
|
|
45
61
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
{
|
|
52
|
-
"pairs": [{"a": "<lib>", "b": "<lib>", "intersection_count": N, "files": [...]}, ...],
|
|
53
|
-
"truncated": <bool>,
|
|
54
|
-
"total_pairs": <int>
|
|
55
|
-
}
|
|
56
|
-
```
|
|
57
|
-
`pairs[]` is sorted by `intersection_count` DESC, then `(a, b)` ASC for stable ordering. Default Top-K cap is **20** (matches S7 below); pass `--top-k N` to override.
|
|
58
|
-
3. **Parse the JSON result** and use `pairs[]` as the qualifying-pair set for §2 onward. The `intersection_count` is the candidate file count for the §2 2-file threshold pre-grep; `files[]` is the grep-scope for that pair.
|
|
62
|
+
```bash
|
|
63
|
+
uv run {pairIntersectHelper} intersect --counts "{importCountsFile}" --only "<names>" > "{pairsFile}"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`{importCountsFile}` is the step 3 import-count JSON, read as it stands, and `--only` names the confirmed libraries, comma-separated, less those step 4 reported an extraction failure for. Its JSON, in `{pairsFile}`, holds `pairs[]` (`a`, `b`, `intersection_count` and `files[]`, each `{path, line_a, line_b}`: a file that imports both libraries, with the first line that imports each), sorted by `intersection_count` and capped at the Top-K below, with `truncated` and `total_pairs`. Use `pairs[]` as the candidate-pair set for §2 onward.
|
|
59
67
|
|
|
60
|
-
**Top-K cap (S7, 20):**
|
|
68
|
+
**Top-K cap (S7, 20):** When the script reports `truncated: true`, warn the user and append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "warn"`, `code: "pair-cap-truncated"`, `message`: "non-empty-intersection pair count {total_pairs} exceeds cap: analyzing top 20 by intersection size; {total_pairs - 20} pairs skipped"), which the evidence report lists.
|
|
61
69
|
|
|
62
70
|
Report: "**Analyzing {pair_count} library pairs for integration patterns** (pruned from {N*(N-1)/2} via file-list intersection; {capped_count} after Top-K if applicable)**...**"
|
|
63
71
|
|
|
@@ -65,122 +73,111 @@ Report: "**Analyzing {pair_count} library pairs for integration patterns** (prun
|
|
|
65
73
|
|
|
66
74
|
**If `compose_mode` is true:**
|
|
67
75
|
|
|
68
|
-
|
|
76
|
+
A helper reports candidate pairs with their evidence; a candidate becomes an integration only when that evidence shows how the two libraries work together. **Resolve `{comentionHelper}`** from `{comentionProbeOrder}`; first existing path wins. If no candidate exists, HALT (exit 3, `halt_reason: "helper-missing"`, phase `detect-integrations:comention`) with "**Cannot proceed.** `skf-comention-pairs.py` is missing, so no compose-mode pair can be found. Re-install SKF, then re-run."
|
|
69
77
|
|
|
70
|
-
1. Load `{composeModeRulesPath}` for integration evidence format
|
|
71
|
-
2. **If `{architecture_doc_path}` is null or not available:**
|
|
72
|
-
3. **
|
|
73
|
-
|
|
74
|
-
**Resolve `{comentionHelper}`** from `{comentionProbeOrder}`; first existing path wins.
|
|
78
|
+
1. Load `{composeModeRulesPath}` for the integration evidence format and labels
|
|
79
|
+
2. **If `{architecture_doc_path}` is null or not available:** skip to the **No architecture document** path below
|
|
80
|
+
3. **Find the candidates with the shared script:**
|
|
75
81
|
|
|
76
82
|
```bash
|
|
77
83
|
uv run {comentionHelper} comention --doc {architecture_doc_path} --skills -
|
|
78
84
|
```
|
|
79
|
-
piping the
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
"evidence": [{"header": "<governing-header-or-null>", "excerpt": "<text>"}, ...]},
|
|
85
|
-
...
|
|
86
|
-
],
|
|
87
|
-
"excluded_section_count": M
|
|
88
|
-
}
|
|
89
|
-
```
|
|
90
|
-
`pairs[]` contains only qualifying pairs (≥2 distinct body paragraphs), sorted by `paragraph_count` DESC then `(a, b)` ASC. Use `pairs[]` as the detected-integration-pair set for step 4 onward; each pair's `evidence[]` supplies the governing header and paragraph excerpts to quote as architecture-reference evidence.
|
|
85
|
+
piping the `confirmed_dependencies` names as a JSON array on stdin (e.g. `["react", "express"]`; if stdin piping is unavailable, write it to `{run_dir}/skills.json` and pass that path to `--skills`). Its `pairs[]` holds each pair a body paragraph names in one unit or through a lead-in, with `paragraph_count`, `comention_count`, `lead_in_count` and one `evidence[]` entry per paragraph naming both; `unit_excerpt` quotes a `co-mention` or `lead-in` entry, from `unit_line` (a `list-only` entry quotes nothing), and `excluded_section` is true under an introductory heading (Overview, Introduction and the like). `list_only_pair_count` counts the pairs only listed together, which it leaves out. When `pairs[]` is empty, append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "info"`, `code: "comention-no-candidates"`, `message`: "no passage names two confirmed libraries together ({list_only_pair_count} pairs only listed, {excluded_section_count} introductory sections)").
|
|
86
|
+
|
|
87
|
+
4. **Pairs only listed together.** When `list_only_pair_count` is above 0, append one `workflow_warnings[]` entry (`step: "step-05"`, `severity: "info"`, `code: "comention-list-only"`, `message`: "{list_only_pair_count} pairs only listed together"), which the evidence report lists.
|
|
88
|
+
5. **Confirm each candidate** from the `unit_excerpt` of its `co-mention` and `lead-in` entries. Keep the pair only when an excerpt says how the two libraries work together: data flows from one to the other, one wraps or adapts the other, one configures or initializes the other, or one handles the other's events. The script reads fenced code as text, so a diagram line counts too: a Mermaid edge between the two (`react --> express`) shows data flow. Two names side by side ("built with React and Express") do not confirm a pair, and an `excluded_section` entry whose excerpt only names both confirms nothing; one excerpt that says how the two work together is enough, wherever it sits. Drop each pair no excerpt confirms and append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "warn"`, `code: "comention-unconfirmed"`, `message`: the pair and the excerpts read).
|
|
89
|
+
6. For each confirmed pair, compose an integration section in the evidence format of `{composeModeRulesPath}` from both skills' export lists and API signatures, with the confirming `unit_excerpt` as its architecture reference and the VS verdicts below; §4 keeps them in the pair's bundle entry. Its tier comes from `{renderStackMetadataHelper}` in §3 (see **Confidence Tier Inheritance** in `{composeModeRulesPath}`), and every compose-mode label takes the `[composed]` suffix except an inferred-shared-domain one.
|
|
91
90
|
|
|
92
|
-
|
|
93
|
-
4. For each detected integration pair (from `pairs[]`):
|
|
94
|
-
- Load both skills' export lists and API signatures
|
|
95
|
-
- Compose an integration section following the format from `{composeModeRulesPath}`
|
|
96
|
-
- Include VS feasibility verdict if a feasibility report matching the filename pattern defined in `src/shared/references/feasibility-report-schema.md` exists under `{forge_data_folder}/` (timestamped `feasibility-report-{project_slug}-{YYYYMMDD-HHmmss}.md` or the stable `feasibility-report-{project_slug}-latest.md` copy). Schema version `"1.0"` is required; see the schema for the full contract.
|
|
97
|
-
- Cite evidence from both skills: `[from skill: {skill_name}]`
|
|
91
|
+
**VS verdicts (architecture-document pairs).** Resolve `{validateFeasibilityReportHelper}` from `{validateFeasibilityReportProbeOrder}` (first existing path wins) and locate the [VS] report through it (see `shared/references/feasibility-report-schema.md`):
|
|
98
92
|
|
|
99
|
-
|
|
93
|
+
```bash
|
|
94
|
+
uv run {validateFeasibilityReportHelper} --locate "{forge_data_folder}" --project-name "{project_name}"
|
|
95
|
+
```
|
|
100
96
|
|
|
101
|
-
|
|
97
|
+
Act on the first of these that applies:
|
|
102
98
|
|
|
103
|
-
-
|
|
104
|
-
-
|
|
99
|
+
- **`status: "ok"`:** add each confirmed pair's `pairVerdicts` row (`lib_a` and `lib_b` in either order) and the `overallVerdict` to its evidence, as `{composeModeRulesPath}` shows.
|
|
100
|
+
- **`status: "not-found"`, or no JSON** (no candidate resolves, or `uv` cannot run it): compose without VS verdicts. With no JSON, append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "warn"`, `code: "vs-report-unread"`, `message`: the reason).
|
|
101
|
+
- **`schemaVersionOk` is false:** never interpret the report. HALT (exit 2, `halt_reason: "schema-version-mismatch"`, phase `detect-integrations:vs-report`, `path` the report's `path`) with "feasibility-report schemaVersion mismatch: expected '1.0', got '{schemaVersion}'; refusing to proceed".
|
|
102
|
+
- **`unknownTokens` is not empty:** a verdict token outside the schema's set is a hard error, as the schema requires: HALT (exit 2, `halt_reason: "unknown-verdict-token"`, phase `detect-integrations:vs-report`, `path` the report's `path`), naming each token with its line and pair, and never drop or map one.
|
|
103
|
+
- **Any other exit `1`, or exit `2` with a JSON:** the report breaks the contract otherwise (a section missing or out of order, no verdict table or a second one) or could not be read. Read no verdict from it: compose without VS verdicts and append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "warn"`, `code: "vs-report-unusable"`, `message`: its `path` and each problem its JSON names, or its `error`).
|
|
105
104
|
|
|
106
|
-
|
|
107
|
-
python3 {validateFeasibilityReportHelper} <located-report-path>
|
|
108
|
-
```
|
|
105
|
+
**No architecture document.** Find the candidates in the constituents themselves, with the `{comentionHelper}` resolved above:
|
|
109
106
|
|
|
110
|
-
|
|
107
|
+
```bash
|
|
108
|
+
uv run {comentionHelper} infer --skills - --top-k 20
|
|
109
|
+
```
|
|
111
110
|
|
|
112
|
-
|
|
113
|
-
SKF_STACK_RESULT_JSON: {"status":"error","skill_package":null,"skill_name":"{project_name}-stack","stack_libraries":[],"mode":"compose","exit_code":2,"halt_reason":"schema-version-mismatch"}
|
|
114
|
-
```
|
|
115
|
-
- Read `overallVerdict` from frontmatter (exactly one of `FEASIBLE|CONDITIONALLY_FEASIBLE|NOT_FEASIBLE`).
|
|
116
|
-
- Parse the `## Integration Verdicts` markdown table for per-pair verdicts (exactly one of `Verified|Plausible|Risky|Blocked`). Any unknown verdict token is a hard error per the schema — do not silently drop or map.
|
|
117
|
-
- For each architecture-detected pair, include `VS overall: {overallVerdict}` and `VS pair: {verdict}` in the integration evidence per the format in `{composeModeRulesPath}`. VS verdicts do not apply to inferred integrations since the VS report operates on architecture-described interactions only. Additionally, flag any pairs where VS reported `Risky` or `Blocked` by appending a `[VS: Risky]` or `[VS: Blocked]` warning annotation to the integration entry.
|
|
111
|
+
piping one object per confirmed skill on stdin: `{"name": "<skill>", "keywords": ["<keyword>", ...], "language": "<language>", "docs": ["<path>", ...]}`. Its `keywords` are the domain terms its SKILL.md `description` names (such as `orm` or `validation`, never a language), `language` is the one step 2 read from its `metadata.json`, and `docs` are its `SKILL.md` and the `.md` files in its `references/`, under `skill_package_path`. A pair is a candidate only on this evidence, never on a shared language alone, and each candidate is judged like a co-mention:
|
|
118
112
|
|
|
119
|
-
|
|
120
|
-
-
|
|
121
|
-
|
|
122
|
-
-
|
|
113
|
+
- **`docs-mention`:** one skill's own docs name the other; `excerpt` quotes the first such line (`doc`, `line`). Keep the pair as a `constituent-documented-contract` integration only when that line says how the two work together, never on a "see also" or "unlike" line.
|
|
114
|
+
- **`shared-keywords`:** the two share a domain keyword. Keep the pair as an `inferred-shared-domain` integration only when both skills' descriptions and exports show how that domain makes them work together (one feeds, wraps, configures or consumes the other), never for two libraries that do the same job, such as `zod` and `yup` or `express` and `fastify`.
|
|
115
|
+
|
|
116
|
+
Drop every other candidate and append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "warn"`, `code: "infer-unconfirmed"`, `message`: the pair and the evidence read). When `truncated` is true, append an entry (`step: "step-05"`, `severity: "warn"`, `code: "infer-cap-truncated"`, `message`: its `total_pairs` and the top 20 analyzed); when `language_only_pair_count` is above 0, append an entry (`step: "step-05"`, `severity: "info"`, `code: "infer-language-only"`) giving that count. On exit `1` its stderr names the input it refused, such as a `docs` path that is missing, unreadable or not UTF-8: fix or drop it and run the call again. On exit `2`, or when `uv` cannot run it, compose with no inferred pairs and append an entry (`step: "step-05"`, `severity: "warn"`, `code: "infer-unavailable"`, `message`: the reason).
|
|
123
117
|
|
|
124
118
|
Skip to section 3 (Classify Integration Types) with the compose-mode pairs.
|
|
125
119
|
|
|
126
120
|
**If not compose_mode:**
|
|
127
121
|
|
|
128
|
-
|
|
122
|
+
The pair's co-import files stay in `{pairsFile}`: each `files[]` entry of a §1 pair is a file that imports both libraries, as step 3's helper matched them, with `line_a` and `line_b`.
|
|
129
123
|
|
|
130
|
-
**
|
|
124
|
+
**Threshold:** A pair must have 2+ co-import files (`intersection_count` 2 or more) to qualify as an integration pattern (single file co-imports may be incidental).
|
|
131
125
|
|
|
132
|
-
**
|
|
126
|
+
**CCC Semantic Augmentation (Forge+ and Deep with ccc):**
|
|
133
127
|
|
|
134
|
-
|
|
128
|
+
If `tools.ccc` is true in forge-tier.yaml, augment each qualifying pair with one semantic search, with one exception: when `ccc_index.status` is `"none"` or `"failed"`, setup built no project index and this step builds none, so skip augmentation. Every other status augments: `"fresh"`, `"created"`, `"skipped"` (setup's `--ccc-skip-index` lane still wrote `settings.yml` with the SKF exclusions, so the first refresh search builds the index safely), or a status this SKF does not know, such as a `"stale"` an older SKF recorded.
|
|
135
129
|
|
|
136
|
-
|
|
130
|
+
For each pair with 2 or more co-import files, run `ccc_bridge.search("{libA} {libB}", project_root, top_k=10)` (`project_root` from step 1, where setup built the index) to rank the files where the two libraries interact. CCC never changes which pairs qualify: a file that imports both libraries is already in the pair's `files[]`, so a pair below the threshold, or one past the Top-K cap, gains nothing from a search.
|
|
137
131
|
|
|
138
|
-
**
|
|
132
|
+
**CCC precision guard (H3):** keep a CCC-surfaced file only when the pair's `files[]` lists it (both paths are relative to `{project_root}`, so they compare as they stand), and use the files kept to pick the ones §3 cites. Drop every other CCC file (one library only name-dropped in a comment or a string, say), and append a `workflow_warnings[]` entry (`step: "step-05"`, `severity: "info"`, `code: "ccc-files-dropped"`, `message`: the pair and each file dropped) for the evidence report.
|
|
139
133
|
|
|
140
|
-
**
|
|
134
|
+
**Tool resolution for ccc_bridge.search:** Use `/ccc` skill search (Claude Code), ccc MCP server (Cursor), or `cd {project_root} && ccc search --limit 10 "{libA} {libB}"` (CLI). `ccc search` reads the index in the current working directory and has no project-selector flag (`--path` is a file-path glob filter *within* the index, and the result cap is `--limit`, not `--top`). See `knowledge/tool-resolution.md`.
|
|
141
135
|
|
|
142
|
-
|
|
136
|
+
**Refresh first:** run this step's first search as `cd {project_root} && ccc search --refresh --limit 10 "{libA} {libB}"`, with an extended timeout, because the refresh pass brings the index up to date before searching; later searches in this step can drop `--refresh`. The ccc MCP search tool refreshes by default: leave its `refresh_index` set to true. If the refresh search fails or times out, run the plain search once, with the same timeout, before treating it as a CCC failure.
|
|
143
137
|
|
|
144
|
-
|
|
138
|
+
CCC failures: skip augmentation silently; §3 picks its files from the pair's `files[]` alone.
|
|
145
139
|
|
|
146
|
-
|
|
140
|
+
### 3. Classify Integration Types
|
|
147
141
|
|
|
148
|
-
|
|
142
|
+
Load `{integrationPatternsPath}` for classification rules.
|
|
149
143
|
|
|
150
|
-
For
|
|
144
|
+
For each qualifying pair, classify the integration type against those pattern types (**in compose mode**: the candidates §2 kept qualify, with no co-import file threshold; **in code mode**: a pair must have 2+ co-import files).
|
|
151
145
|
|
|
152
|
-
|
|
146
|
+
**Pair tiers.** Resolve `{renderStackMetadataHelper}` from `{renderStackMetadataProbeOrder}`; first existing path wins. It holds the one rule for an integration's tier in both modes, so no step works a tier out by hand. If no candidate exists, HALT (exit 3, `halt_reason: "helper-missing"`, phase `detect-integrations:pair-tiers`) with "**Cannot proceed.** `skf-render-stack-metadata.py` is missing, so no integration tier can be set. Re-install SKF, then re-run."
|
|
153
147
|
|
|
154
|
-
|
|
148
|
+
When at least one pair qualifies, run it once on all of them:
|
|
155
149
|
|
|
156
|
-
|
|
150
|
+
```bash
|
|
151
|
+
uv run {renderStackMetadataHelper} pair-tiers --input -
|
|
152
|
+
```
|
|
157
153
|
|
|
158
|
-
|
|
154
|
+
piping `{"mode": "code|compose", "libraries": [{"name": "<library>", "confidence": "<its per_library_extractions[].confidence>"}, ...], "integrations": [{"a": "<library>", "b": "<library>"}, ...]}` on stdin, each qualifying pair once. Each entry of its `integrations[]` gives a pair's `tier`. On exit `2` its stderr names the input it refused, such as a pair naming a library the list lacks: fix the input and run it again.
|
|
159
155
|
|
|
160
156
|
For each detected integration:
|
|
161
|
-
- Identify the top 3 files demonstrating the pattern
|
|
157
|
+
- Identify the top 3 files demonstrating the pattern (the CCC files §2 kept first, when there are any)
|
|
162
158
|
- Extract a brief description of how the libraries connect
|
|
163
|
-
- **Assign confidence (M1/M3)
|
|
164
|
-
- `grep-co-import
|
|
165
|
-
- `
|
|
166
|
-
- `
|
|
167
|
-
- `
|
|
168
|
-
- `
|
|
169
|
-
- Render as `{tier} ({qualifier})` — e.g., `T1-low (grep-co-import)`, `T1 (ccc-augmented)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `{composeModeRulesPath}` is appended after the qualifier in compose-mode.
|
|
159
|
+
- **Assign confidence (M1/M3): the pair's `tier` and a detection-method qualifier, never AST:** integration detection here is co-import file evidence from step 3's import counts, or a compose-mode candidate §2 confirmed. Append the qualifier that says how the pair was found:
|
|
160
|
+
- `grep-co-import`: the pair qualified on the co-import files its two libraries' import counts share (the default).
|
|
161
|
+
- `architecture-co-mention`: compose-mode pair the architecture document names together, confirmed from its excerpt in §2. Maps to `detection_method: architecture_co_mention` in `provenance-map.json`.
|
|
162
|
+
- `constituent-documented-contract`: compose-mode pair with no architecture document whose contract a constituent's own docs state, a docs mention §2 confirmed. Maps to `detection_method: constituent_documented_contract` in `provenance-map.json`.
|
|
163
|
+
- `inferred-shared-domain`: compose-mode pair with no architecture document, a shared-keywords candidate §2 kept (no cited contract, never a shared language alone). Maps to `detection_method: inferred_from_shared_domain` in `provenance-map.json`.
|
|
164
|
+
- Render as `{tier} ({qualifier})`, e.g. `T1-low (grep-co-import)`, `T1 (grep-co-import)`, `T1-low (architecture-co-mention) [composed]`. The `[composed]`/`[inferred from shared domain]` suffix from `{composeModeRulesPath}` is appended after the qualifier in compose-mode.
|
|
170
165
|
|
|
171
|
-
**Provenance ↔ SKILL.md tier parity:**
|
|
166
|
+
**Provenance ↔ SKILL.md tier parity:** write the pair's `tier` to both the SKILL.md integration label and `provenance-map.json` `integrations[].confidence`. The qualifier, and the `detection_method` it maps to, say how the edge was found and never change the tier.
|
|
172
167
|
|
|
173
168
|
### 4. Build Integration Graph
|
|
174
169
|
|
|
175
170
|
Assemble the integration graph:
|
|
176
171
|
- **Nodes:** Confirmed libraries (with extraction data from step 04)
|
|
177
|
-
- **Edges:** Detected integration pairs with type, file count, and description
|
|
172
|
+
- **Edges:** Detected integration pairs with type, co-import file count (the pair's `intersection_count` in `{pairsFile}`, 0 in compose mode), and description
|
|
178
173
|
- Identify **hub libraries** (connected to 3+ other libraries)
|
|
179
174
|
- Identify **cross-cutting patterns** (patterns spanning 3+ libraries)
|
|
180
175
|
|
|
176
|
+
Write the graph into `{bundleFile}`: its `integrations[]` gets one entry per detected pair, `{"a": "<library>", "b": "<library>", "type": "<pattern type>", "tier": "<the pair's tier>", "qualifier": "<detection qualifier>", "detection_method": "<provenance detection_method>", "key_files": ["<path:line>"], "description": "<how they connect>"}`, and `hubs` and `cross_cutting` list the hub libraries and cross-cutting patterns, so steps 6 and 7 read the integration layer from disk. In compose mode each entry also holds its evidence in the format of `{composeModeRulesPath}`: `"evidence": ["[from skill: <A>] <signature>", "[from skill: <B>] <signature>"]`, `"reference": "<its Architecture reference, Contract reference or Shared domain line>"` and `"vs": {"pair": "<verdict>", "overall": "<overallVerdict>"}`, `null` when no usable [VS] report rated the pair; code mode leaves the three out.
|
|
177
|
+
|
|
181
178
|
### 5. Display Integration Summary
|
|
182
179
|
|
|
183
|
-
If integrations were detected, report the integration graph (`{lib_count}` libraries, `{pair_count}` pairs): the hub libraries (connected to 3+ others) with their partners, each detected pair (library A, library B, type, co-import file count, confidence tier), and any cross-cutting patterns spanning 3+ libraries. If none were detected, report that
|
|
180
|
+
If integrations were detected, report the integration graph (`{lib_count}` libraries, `{pair_count}` pairs): the hub libraries (connected to 3+ others) with their partners, each detected pair (library A, library B, type, co-import file count, confidence tier), and any cross-cutting patterns spanning 3+ libraries. If none were detected, report that the libraries appear to operate independently: the stack skill carries library summaries without an integration layer.
|
|
184
181
|
|
|
185
182
|
### 6. Auto-Proceed to Next Step
|
|
186
183
|
|