bmad-module-skill-forge 2.2.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 +49 -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 +12 -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 +99 -11
- package/src/shared/scripts/skf-detect-docs.py +694 -2
- 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 +209 -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 +15 -5
- 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 +28 -19
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -59
- 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 -90
- package/src/skf-setup/references/detect-and-tier.md +58 -67
- 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 -679
- 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,5 +1,5 @@
|
|
|
1
1
|
# /// script
|
|
2
|
-
# requires-python = ">=3.
|
|
2
|
+
# requires-python = ">=3.11"
|
|
3
3
|
# dependencies = ["pyyaml"]
|
|
4
4
|
# ///
|
|
5
5
|
"""SKF Resolve Authoritative Files — §2a deterministic pre-prompt pipeline.
|
|
@@ -27,7 +27,7 @@ drift-prone parts. The helper consolidates them into one `resolve` call.
|
|
|
27
27
|
|
|
28
28
|
Subcommand:
|
|
29
29
|
resolve --source-root <path> --brief <brief.yaml-path>
|
|
30
|
-
[--preview-lines 20]
|
|
30
|
+
[--preview-lines 20] [--provenance-map <provenance-map.json>]
|
|
31
31
|
|
|
32
32
|
Output JSON (stdout):
|
|
33
33
|
|
|
@@ -35,10 +35,14 @@ Output JSON (stdout):
|
|
|
35
35
|
"status": "no-candidates" | "candidates-found",
|
|
36
36
|
"summary": {
|
|
37
37
|
"candidates_total": N,
|
|
38
|
+
"already_tracked_count": N,
|
|
38
39
|
"already_in_scope_count": N,
|
|
39
40
|
"pre_decided_count": N,
|
|
40
41
|
"unresolved_count": N
|
|
41
42
|
},
|
|
43
|
+
"already_tracked": [
|
|
44
|
+
{"path": "...", "heuristic": "llms.txt"}
|
|
45
|
+
],
|
|
42
46
|
"already_in_scope": [
|
|
43
47
|
{"path": "...", "heuristic": "llms.txt", "size_bytes": N,
|
|
44
48
|
"line_count": N, "content_hash": "sha256:..."}
|
|
@@ -53,13 +57,21 @@ Output JSON (stdout):
|
|
|
53
57
|
{"path": "...", "heuristic": "...", "size_bytes": N,
|
|
54
58
|
"line_count": N, "content_hash": "sha256:...",
|
|
55
59
|
"preview": "<first N lines as a string>",
|
|
56
|
-
"excluded_by_pattern": "<glob>" | "not matched by any scope.include"
|
|
60
|
+
"excluded_by_pattern": "<glob>" | "not matched by any scope.include",
|
|
61
|
+
"prior_action": null | "deferred-headless"}
|
|
57
62
|
]
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
Paths are emitted relative to `source-root`, forward-slash form
|
|
61
66
|
(cross-platform JSON convention — same as skf-detect-scripts-assets.py).
|
|
62
67
|
|
|
68
|
+
`already_tracked` semantics (update-skill's mirror of this protocol):
|
|
69
|
+
with `--provenance-map`, a candidate the map already names, in
|
|
70
|
+
`entries[].source_file` or `file_entries[].source_file`, is tracked:
|
|
71
|
+
change detection handles it, so it is listed here, with no hash, and in
|
|
72
|
+
no other bucket. Without `--provenance-map` the list is empty.
|
|
73
|
+
`candidates_total` counts every candidate, tracked ones included.
|
|
74
|
+
|
|
63
75
|
`pre_decided` semantics:
|
|
64
76
|
- `prior_action="promoted"` AND `should_add_to_promoted_docs=true` →
|
|
65
77
|
the path is in scope but the caller still needs to add it to
|
|
@@ -68,9 +80,18 @@ Paths are emitted relative to `source-root`, forward-slash form
|
|
|
68
80
|
- `prior_action="skipped"` → the user previously declined; caller
|
|
69
81
|
does nothing. Hash/size/lines are null (no need to read the file).
|
|
70
82
|
|
|
83
|
+
`unresolved` semantics: nobody has decided the path yet, so an
|
|
84
|
+
interactive run asks. `prior_action="deferred-headless"` means a headless
|
|
85
|
+
run already met the path and left the decision to the next interactive
|
|
86
|
+
run (an amendment with `action: "deferred-headless"`); a headless run
|
|
87
|
+
does not record it again. A `skipped` amendment whose reason is the
|
|
88
|
+
headless default, "headless: no user to prompt", was written that way by
|
|
89
|
+
a headless run before `deferred-headless` existed: no person declined
|
|
90
|
+
the file, so it counts as `deferred-headless` too.
|
|
91
|
+
|
|
71
92
|
Exit codes:
|
|
72
|
-
0
|
|
73
|
-
1
|
|
93
|
+
0 operation succeeded (any status)
|
|
94
|
+
1 user error (paths invalid, brief or provenance map unparseable)
|
|
74
95
|
"""
|
|
75
96
|
|
|
76
97
|
from __future__ import annotations
|
|
@@ -86,6 +107,12 @@ from typing import Iterable
|
|
|
86
107
|
import yaml
|
|
87
108
|
|
|
88
109
|
|
|
110
|
+
# skf-classify-changed-files.py loads this file for load_brief,
|
|
111
|
+
# extract_scope, glob_match, scope_match, normalize_rel_path and
|
|
112
|
+
# EXCLUDED_DIR_NAMES, and skf-detect-registry.py for glob_match, load_brief
|
|
113
|
+
# and extract_scope: keep those names and what they take and return.
|
|
114
|
+
|
|
115
|
+
|
|
89
116
|
# --------------------------------------------------------------------------
|
|
90
117
|
# Heuristic list — case-insensitive basename match
|
|
91
118
|
# --------------------------------------------------------------------------
|
|
@@ -267,7 +294,8 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
|
|
|
267
294
|
|
|
268
295
|
amendments_by_path maps each path to a list of actions seen, in the
|
|
269
296
|
order they appear in the brief (so reconcile() can pick most-recent
|
|
270
|
-
by iterating in reverse).
|
|
297
|
+
by iterating in reverse). A legacy headless skip is listed as
|
|
298
|
+
'deferred-headless' (see _amendment_action).
|
|
271
299
|
"""
|
|
272
300
|
scope = brief.get("scope") if isinstance(brief.get("scope"), dict) else {}
|
|
273
301
|
includes = scope.get("include") if isinstance(scope.get("include"), list) else []
|
|
@@ -279,8 +307,8 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
|
|
|
279
307
|
if not isinstance(amend, dict):
|
|
280
308
|
continue
|
|
281
309
|
path = amend.get("path")
|
|
282
|
-
action = amend
|
|
283
|
-
if isinstance(path, str) and
|
|
310
|
+
action = _amendment_action(amend)
|
|
311
|
+
if isinstance(path, str) and action is not None:
|
|
284
312
|
by_path.setdefault(path, []).append(action)
|
|
285
313
|
|
|
286
314
|
# filter to strings only — schema requires strings but defensively guard
|
|
@@ -289,6 +317,48 @@ def extract_scope(brief: dict) -> tuple[list[str], list[str], dict[str, list[str
|
|
|
289
317
|
return includes, excludes, by_path
|
|
290
318
|
|
|
291
319
|
|
|
320
|
+
# --------------------------------------------------------------------------
|
|
321
|
+
# Provenance map: the files it already tracks
|
|
322
|
+
# --------------------------------------------------------------------------
|
|
323
|
+
|
|
324
|
+
|
|
325
|
+
def normalize_rel_path(path: str) -> str:
|
|
326
|
+
"""A provenance or brief path in the form this helper emits: forward
|
|
327
|
+
slashes, no leading `./`."""
|
|
328
|
+
path = path.strip().replace("\\", "/")
|
|
329
|
+
while path.startswith("./"):
|
|
330
|
+
path = path[2:]
|
|
331
|
+
return path
|
|
332
|
+
|
|
333
|
+
|
|
334
|
+
def load_tracked_files(provenance_path: Path) -> set[str]:
|
|
335
|
+
"""Every `entries[].source_file` and `file_entries[].source_file` of a
|
|
336
|
+
provenance map. Raises ValueError when the map cannot be read."""
|
|
337
|
+
try:
|
|
338
|
+
data = json.loads(provenance_path.read_text(encoding="utf-8"))
|
|
339
|
+
except OSError as exc:
|
|
340
|
+
raise ValueError(f"cannot read provenance map at {provenance_path}: {exc}") from exc
|
|
341
|
+
except ValueError as exc:
|
|
342
|
+
raise ValueError(
|
|
343
|
+
f"provenance map at {provenance_path} is not valid JSON: {exc}"
|
|
344
|
+
) from exc
|
|
345
|
+
if not isinstance(data, dict):
|
|
346
|
+
raise ValueError(
|
|
347
|
+
f"provenance map at {provenance_path} must be a JSON object; got "
|
|
348
|
+
f"{type(data).__name__}"
|
|
349
|
+
)
|
|
350
|
+
tracked: set[str] = set()
|
|
351
|
+
for key in ("entries", "file_entries"):
|
|
352
|
+
rows = data.get(key)
|
|
353
|
+
if not isinstance(rows, list):
|
|
354
|
+
continue
|
|
355
|
+
for row in rows:
|
|
356
|
+
source = row.get("source_file") if isinstance(row, dict) else None
|
|
357
|
+
if isinstance(source, str) and source.strip():
|
|
358
|
+
tracked.add(normalize_rel_path(source))
|
|
359
|
+
return tracked
|
|
360
|
+
|
|
361
|
+
|
|
292
362
|
# --------------------------------------------------------------------------
|
|
293
363
|
# File metadata: hash + size + lines + preview
|
|
294
364
|
# --------------------------------------------------------------------------
|
|
@@ -338,13 +408,28 @@ def load_preview(path: Path, *, max_lines: int) -> str:
|
|
|
338
408
|
|
|
339
409
|
_PROMOTED = "promoted"
|
|
340
410
|
_SKIPPED = "skipped"
|
|
411
|
+
_DEFERRED = "deferred-headless"
|
|
412
|
+
# The reason a headless run gave its automatic skip before deferred-headless
|
|
413
|
+
# existed. Such a skip was never a person's decision.
|
|
414
|
+
_LEGACY_HEADLESS_REASON = "headless: no user to prompt"
|
|
415
|
+
|
|
416
|
+
|
|
417
|
+
def _amendment_action(amend: dict) -> str | None:
|
|
418
|
+
"""The action an amendment records, reading a legacy headless skip as a deferral."""
|
|
419
|
+
action = amend.get("action")
|
|
420
|
+
if not isinstance(action, str):
|
|
421
|
+
return None
|
|
422
|
+
reason = amend.get("reason")
|
|
423
|
+
if action == _SKIPPED and isinstance(reason, str) and reason.strip() == _LEGACY_HEADLESS_REASON:
|
|
424
|
+
return _DEFERRED
|
|
425
|
+
return action
|
|
341
426
|
|
|
342
427
|
|
|
343
428
|
def _latest_action(actions: list[str]) -> str | None:
|
|
344
429
|
"""Most-recent matching amendment wins. Returns 'promoted', 'skipped',
|
|
345
|
-
or None if no recognized action was seen."""
|
|
430
|
+
'deferred-headless', or None if no recognized action was seen."""
|
|
346
431
|
for action in reversed(actions):
|
|
347
|
-
if action in (_PROMOTED, _SKIPPED):
|
|
432
|
+
if action in (_PROMOTED, _SKIPPED, _DEFERRED):
|
|
348
433
|
return action
|
|
349
434
|
return None
|
|
350
435
|
|
|
@@ -354,17 +439,25 @@ def resolve(
|
|
|
354
439
|
brief_path: Path,
|
|
355
440
|
*,
|
|
356
441
|
preview_lines: int = 20,
|
|
442
|
+
provenance_map: Path | None = None,
|
|
357
443
|
) -> dict:
|
|
358
444
|
"""Run the §2a deterministic pipeline. See module docstring for output shape."""
|
|
359
445
|
brief = load_brief(brief_path)
|
|
360
446
|
includes, excludes, amendments_by_path = extract_scope(brief)
|
|
447
|
+
tracked = load_tracked_files(provenance_map) if provenance_map is not None else set()
|
|
361
448
|
|
|
449
|
+
already_tracked: list[dict] = []
|
|
362
450
|
already_in_scope: list[dict] = []
|
|
363
451
|
pre_decided: list[dict] = []
|
|
364
452
|
unresolved: list[dict] = []
|
|
365
453
|
|
|
366
454
|
for file_path, heuristic in iter_auth_doc_files(source_root):
|
|
367
455
|
rel = file_path.relative_to(source_root).as_posix()
|
|
456
|
+
if rel in tracked:
|
|
457
|
+
# The provenance map already names it: change detection handles
|
|
458
|
+
# it, and no decision is asked for.
|
|
459
|
+
already_tracked.append({"path": rel, "heuristic": heuristic})
|
|
460
|
+
continue
|
|
368
461
|
in_scope, excluded_by = scope_match(rel, includes, excludes)
|
|
369
462
|
prior_action = _latest_action(amendments_by_path.get(rel, []))
|
|
370
463
|
|
|
@@ -398,6 +491,7 @@ def resolve(
|
|
|
398
491
|
continue
|
|
399
492
|
|
|
400
493
|
if prior_action == _SKIPPED:
|
|
494
|
+
# A person declined the file; a headless deferral never lands here.
|
|
401
495
|
pre_decided.append({
|
|
402
496
|
"path": rel,
|
|
403
497
|
"heuristic": heuristic,
|
|
@@ -409,7 +503,8 @@ def resolve(
|
|
|
409
503
|
})
|
|
410
504
|
continue
|
|
411
505
|
|
|
412
|
-
#
|
|
506
|
+
# Out of scope and undecided (no amendment, or a headless deferral
|
|
507
|
+
# that waits for the next interactive run) → unresolved
|
|
413
508
|
unresolved.append({
|
|
414
509
|
"path": rel,
|
|
415
510
|
"heuristic": heuristic,
|
|
@@ -418,24 +513,28 @@ def resolve(
|
|
|
418
513
|
"content_hash": sha256_of_file(file_path),
|
|
419
514
|
"preview": load_preview(file_path, max_lines=preview_lines),
|
|
420
515
|
"excluded_by_pattern": excluded_by,
|
|
516
|
+
"prior_action": prior_action,
|
|
421
517
|
})
|
|
422
518
|
|
|
423
519
|
# Deterministic ordering for stable diffs / cache keys
|
|
520
|
+
already_tracked.sort(key=lambda r: r["path"])
|
|
424
521
|
already_in_scope.sort(key=lambda r: r["path"])
|
|
425
522
|
pre_decided.sort(key=lambda r: r["path"])
|
|
426
523
|
unresolved.sort(key=lambda r: r["path"])
|
|
427
524
|
|
|
428
525
|
candidates_total = (
|
|
429
|
-
len(already_in_scope) + len(pre_decided) + len(unresolved)
|
|
526
|
+
len(already_tracked) + len(already_in_scope) + len(pre_decided) + len(unresolved)
|
|
430
527
|
)
|
|
431
528
|
return {
|
|
432
529
|
"status": "candidates-found" if candidates_total > 0 else "no-candidates",
|
|
433
530
|
"summary": {
|
|
434
531
|
"candidates_total": candidates_total,
|
|
532
|
+
"already_tracked_count": len(already_tracked),
|
|
435
533
|
"already_in_scope_count": len(already_in_scope),
|
|
436
534
|
"pre_decided_count": len(pre_decided),
|
|
437
535
|
"unresolved_count": len(unresolved),
|
|
438
536
|
},
|
|
537
|
+
"already_tracked": already_tracked,
|
|
439
538
|
"already_in_scope": already_in_scope,
|
|
440
539
|
"pre_decided": pre_decided,
|
|
441
540
|
"unresolved": unresolved,
|
|
@@ -461,8 +560,17 @@ def _cmd_resolve(args: argparse.Namespace) -> int:
|
|
|
461
560
|
if args.preview_lines < 1:
|
|
462
561
|
print("error: --preview-lines must be >= 1", file=sys.stderr)
|
|
463
562
|
return 1
|
|
563
|
+
provenance_map = Path(args.provenance_map) if args.provenance_map else None
|
|
564
|
+
if provenance_map is not None and not provenance_map.is_file():
|
|
565
|
+
print(f"error: provenance map not found: {provenance_map}", file=sys.stderr)
|
|
566
|
+
return 1
|
|
464
567
|
try:
|
|
465
|
-
result = resolve(
|
|
568
|
+
result = resolve(
|
|
569
|
+
source_root,
|
|
570
|
+
brief_path,
|
|
571
|
+
preview_lines=args.preview_lines,
|
|
572
|
+
provenance_map=provenance_map,
|
|
573
|
+
)
|
|
466
574
|
except ValueError as exc:
|
|
467
575
|
print(f"error: {exc}", file=sys.stderr)
|
|
468
576
|
return 1
|
|
@@ -490,6 +598,13 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
490
598
|
default=20,
|
|
491
599
|
help="number of lines to capture for the prompt preview (default: 20)",
|
|
492
600
|
)
|
|
601
|
+
p.add_argument(
|
|
602
|
+
"--provenance-map",
|
|
603
|
+
help=(
|
|
604
|
+
"path to provenance-map.json: candidates it already tracks are "
|
|
605
|
+
"listed in already_tracked and in no other bucket"
|
|
606
|
+
),
|
|
607
|
+
)
|
|
493
608
|
p.set_defaults(func=_cmd_resolve)
|
|
494
609
|
return parser
|
|
495
610
|
|