bmad-module-skill-forge 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +51 -49
- package/docs/404.md +10 -8
- package/docs/_data/pinned.yaml +22 -13
- package/docs/_internal/STABILITY.md +58 -35
- package/docs/agents.md +39 -53
- package/docs/architecture.md +65 -51
- package/docs/bmad-synergy.md +53 -51
- package/docs/campaign.md +127 -75
- package/docs/concepts.md +34 -28
- package/docs/examples.md +70 -68
- package/docs/forge-auto.md +34 -31
- package/docs/getting-started.md +118 -57
- package/docs/how-it-works.md +25 -21
- package/docs/index.md +15 -15
- package/docs/skill-model.md +70 -59
- package/docs/troubleshooting.md +135 -18
- package/docs/verifying-a-skill.md +83 -57
- package/docs/why-skf.md +24 -22
- package/docs/workflows.md +274 -110
- package/package.json +18 -10
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/agentskills-spec.md +2 -0
- package/src/knowledge/ccc-bridge.md +40 -24
- package/src/knowledge/confidence-tiers.md +9 -5
- package/src/knowledge/overview.md +3 -3
- package/src/knowledge/progressive-capability.md +8 -8
- package/src/knowledge/provenance-tracking.md +9 -5
- package/src/knowledge/qmd-registry.md +2 -2
- package/src/knowledge/skf-knowledge-index.csv +2 -2
- package/src/knowledge/skill-lifecycle.md +18 -11
- package/src/knowledge/split-body-strategy.md +0 -3
- package/src/knowledge/tool-resolution.md +4 -2
- package/src/knowledge/version-paths.md +101 -15
- package/src/module-help.csv +3 -3
- package/src/module.yaml +10 -0
- package/src/shared/data/ast-grep-recipes.yaml +608 -0
- package/src/shared/data/ide-context-files.json +30 -0
- package/src/shared/health-check.md +32 -12
- package/src/shared/references/description-guard-protocol.md +14 -9
- package/src/shared/references/feasibility-report-schema.md +19 -13
- package/src/shared/references/headless-gate-convention.md +55 -3
- package/src/shared/references/output-contract-schema.md +19 -8
- package/src/shared/references/pipeline-contracts.md +94 -29
- package/src/shared/references/tessl-review.md +77 -0
- package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
- package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
- package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
- package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
- package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
- package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
- package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
- package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
- package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
- package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
- package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
- package/src/shared/scripts/skf-atomic-write.py +30 -14
- package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
- package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
- package/src/shared/scripts/skf-check-unit-records.py +184 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
- package/src/shared/scripts/skf-classify-changed-files.py +694 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
- package/src/shared/scripts/skf-count-imports.py +1867 -0
- package/src/shared/scripts/skf-count-tokens.py +1 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
- package/src/shared/scripts/skf-description-guard.py +117 -9
- package/src/shared/scripts/skf-detect-docs.py +892 -4
- package/src/shared/scripts/skf-detect-language.py +486 -107
- package/src/shared/scripts/skf-detect-registry.py +887 -0
- package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
- package/src/shared/scripts/skf-detect-tools.py +215 -27
- package/src/shared/scripts/skf-detect-workspaces.py +506 -30
- package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
- package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
- package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
- package/src/shared/scripts/skf-extract-public-api.py +4084 -85
- package/src/shared/scripts/skf-extraction-inventory.py +746 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
- package/src/shared/scripts/skf-fetch-temporal.py +674 -0
- package/src/shared/scripts/skf-find-cycles.py +97 -29
- package/src/shared/scripts/skf-find-test-report.py +476 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +661 -0
- package/src/shared/scripts/skf-hash-content.py +166 -12
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +159 -27
- package/src/shared/scripts/skf-manifest-ops.py +1 -1
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
- package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
- package/src/shared/scripts/skf-names-present.py +221 -0
- package/src/shared/scripts/skf-pair-intersect.py +119 -28
- package/src/shared/scripts/skf-parse-gaps.py +1384 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-preflight.py +161 -27
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
- package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
- package/src/shared/scripts/skf-quick-batch.py +774 -0
- package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
- package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
- package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
- package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
- package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
- package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
- package/src/shared/scripts/skf-resolve-package.py +523 -106
- package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
- package/src/shared/scripts/skf-run-lock.py +577 -0
- package/src/shared/scripts/skf-scan-manifests.py +998 -57
- package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
- package/src/shared/scripts/skf-severity-classify.py +712 -108
- package/src/shared/scripts/skf-shape-detect.py +298 -204
- package/src/shared/scripts/skf-shard-body.py +9 -8
- package/src/shared/scripts/skf-skill-inventory.py +2412 -89
- package/src/shared/scripts/skf-skills-module.py +472 -0
- package/src/shared/scripts/skf-source-tree.py +1796 -0
- package/src/shared/scripts/skf-structural-diff.py +670 -119
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +5 -5
- package/src/shared/scripts/skf-update-run-state.py +624 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
- package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
- package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
- package/src/shared/scripts/skf-validate-output.py +712 -64
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +116 -10
- package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
- package/src/shared/scripts/skf-write-skill-brief.py +367 -19
- package/src/shared/tool-requirements.yaml +201 -0
- package/src/skf-analyze-source/SKILL.md +41 -36
- package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
- package/src/skf-analyze-source/customize.toml +36 -24
- package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
- package/src/skf-analyze-source/references/continue.md +2 -13
- package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
- package/src/skf-analyze-source/references/generate-briefs.md +121 -55
- package/src/skf-analyze-source/references/headless-contract.md +42 -15
- package/src/skf-analyze-source/references/identify-units.md +96 -110
- package/src/skf-analyze-source/references/init.md +73 -71
- package/src/skf-analyze-source/references/map-and-detect.md +123 -105
- package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
- package/src/skf-analyze-source/references/recommend.md +51 -70
- package/src/skf-analyze-source/references/scan-project.md +60 -84
- package/src/skf-analyze-source/references/scan-root.md +39 -0
- package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
- package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
- package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
- package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
- package/src/skf-audit-skill/SKILL.md +43 -51
- package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
- package/src/skf-audit-skill/customize.toml +41 -20
- package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
- package/src/skf-audit-skill/references/doc-drift.md +141 -0
- package/src/skf-audit-skill/references/headless-contract.md +29 -0
- package/src/skf-audit-skill/references/init.md +148 -210
- package/src/skf-audit-skill/references/re-index.md +96 -108
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +27 -18
- package/src/skf-audit-skill/references/severity-classify.md +79 -65
- package/src/skf-audit-skill/references/severity-rules.md +15 -6
- package/src/skf-audit-skill/references/structural-diff.md +75 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
- package/src/skf-brief-skill/SKILL.md +36 -25
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +17 -24
- package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +142 -125
- package/src/skf-brief-skill/references/confirm-brief.md +10 -8
- package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
- package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
- package/src/skf-brief-skill/references/gather-intent.md +87 -182
- package/src/skf-brief-skill/references/headless-args.md +84 -16
- package/src/skf-brief-skill/references/health-check.md +1 -1
- package/src/skf-brief-skill/references/invocation-contract.md +18 -13
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
- package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
- package/src/skf-brief-skill/references/scope-definition.md +123 -47
- package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +3 -2
- package/src/skf-brief-skill/references/write-brief.md +66 -57
- package/src/skf-campaign/SKILL.md +31 -34
- package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
- package/src/skf-campaign/customize.toml +47 -16
- package/src/skf-campaign/references/campaign-contracts.md +39 -29
- package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
- package/src/skf-campaign/references/health-check.md +7 -16
- package/src/skf-campaign/references/step-01-setup.md +46 -84
- package/src/skf-campaign/references/step-02-strategy.md +31 -30
- package/src/skf-campaign/references/step-03-pins.md +26 -18
- package/src/skf-campaign/references/step-04-provenance.md +24 -23
- package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
- package/src/skf-campaign/references/step-06-batch.md +41 -34
- package/src/skf-campaign/references/step-07-capstone.md +40 -25
- package/src/skf-campaign/references/step-08-verify.md +28 -29
- package/src/skf-campaign/references/step-09-refine.md +29 -30
- package/src/skf-campaign/references/step-10-export.md +48 -36
- package/src/skf-campaign/references/step-11-maintenance.md +31 -34
- package/src/skf-campaign/references/step-resume.md +37 -68
- package/src/skf-campaign/scripts/campaign-deps.py +57 -18
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
- package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
- package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
- package/src/skf-campaign/scripts/campaign-report.py +204 -37
- package/src/skf-campaign/scripts/campaign-state.py +1128 -0
- package/src/skf-campaign/scripts/campaign-status.py +10 -74
- package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
- package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
- package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
- package/src/skf-campaign/templates/campaign-report-template.md +5 -1
- package/src/skf-campaign/templates/kickoff-template.md +0 -14
- package/src/skf-create-skill/SKILL.md +27 -20
- package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
- package/src/skf-create-skill/assets/skill-sections.md +17 -6
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
- package/src/skf-create-skill/references/batch-mode.md +81 -0
- package/src/skf-create-skill/references/ccc-index-check.md +27 -0
- package/src/skf-create-skill/references/compile.md +107 -29
- package/src/skf-create-skill/references/component-extraction.md +113 -91
- package/src/skf-create-skill/references/enrich.md +41 -23
- package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
- package/src/skf-create-skill/references/extract.md +200 -161
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
- package/src/skf-create-skill/references/extraction-patterns.md +584 -196
- package/src/skf-create-skill/references/generate-artifacts.md +145 -93
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +53 -36
- package/src/skf-create-skill/references/relabel-rule.md +12 -0
- package/src/skf-create-skill/references/report.md +28 -59
- package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
- package/src/skf-create-skill/references/step-auto-shard.md +20 -93
- package/src/skf-create-skill/references/step-doc-rot.md +44 -60
- package/src/skf-create-skill/references/step-doc-sources.md +55 -18
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -57
- package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
- package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
- package/src/skf-create-skill/references/validate.md +173 -99
- package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
- package/src/skf-create-stack-skill/SKILL.md +29 -56
- package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
- package/src/skf-create-stack-skill/customize.toml +23 -12
- package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
- package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
- package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
- package/src/skf-create-stack-skill/references/generate-output.md +138 -128
- package/src/skf-create-stack-skill/references/init.md +90 -32
- package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
- package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
- package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
- package/src/skf-create-stack-skill/references/report.md +39 -33
- package/src/skf-create-stack-skill/references/validate.md +20 -39
- package/src/skf-drop-skill/SKILL.md +28 -51
- package/src/skf-drop-skill/customize.toml +44 -30
- package/src/skf-drop-skill/references/execute.md +79 -146
- package/src/skf-drop-skill/references/invocation-contract.md +64 -0
- package/src/skf-drop-skill/references/report.md +46 -30
- package/src/skf-drop-skill/references/select.md +118 -124
- package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
- package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
- package/src/skf-export-skill/SKILL.md +40 -62
- package/src/skf-export-skill/assets/managed-section-format.md +14 -50
- package/src/skf-export-skill/assets/snippet-format.md +3 -1
- package/src/skf-export-skill/customize.toml +42 -13
- package/src/skf-export-skill/references/generate-snippet.md +54 -46
- package/src/skf-export-skill/references/health-check.md +2 -0
- package/src/skf-export-skill/references/invocation-contract.md +15 -0
- package/src/skf-export-skill/references/load-skill.md +88 -62
- package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
- package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
- package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
- package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
- package/src/skf-export-skill/references/package.md +15 -73
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
- package/src/skf-export-skill/references/result-envelope.md +31 -16
- package/src/skf-export-skill/references/summary.md +41 -17
- package/src/skf-export-skill/references/token-report.md +4 -12
- package/src/skf-export-skill/references/update-context.md +118 -237
- package/src/skf-forger/SKILL.md +61 -37
- package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
- package/src/skf-forger/customize.toml +43 -0
- package/src/skf-forger/references/pipeline-mode.md +73 -18
- package/src/skf-forger/scripts/forge-status.py +299 -0
- package/src/skf-forger/scripts/parse-pipeline.py +322 -54
- package/src/skf-forger/scripts/pipeline-gate.py +428 -0
- package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
- package/src/skf-quick-skill/SKILL.md +54 -53
- package/src/skf-quick-skill/assets/skill-template.md +4 -2
- package/src/skf-quick-skill/customize.toml +51 -20
- package/src/skf-quick-skill/references/batch-mode.md +74 -21
- package/src/skf-quick-skill/references/compile.md +30 -31
- package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
- package/src/skf-quick-skill/references/finalize.md +69 -18
- package/src/skf-quick-skill/references/halt-contract.md +41 -29
- package/src/skf-quick-skill/references/health-check.md +5 -3
- package/src/skf-quick-skill/references/quick-extract.md +114 -45
- package/src/skf-quick-skill/references/registry-resolution.md +9 -64
- package/src/skf-quick-skill/references/resolve-target.md +116 -66
- package/src/skf-quick-skill/references/write-and-validate.md +79 -40
- package/src/skf-refine-architecture/SKILL.md +43 -53
- package/src/skf-refine-architecture/customize.toml +49 -20
- package/src/skf-refine-architecture/references/compile.md +97 -54
- package/src/skf-refine-architecture/references/exit-codes.md +30 -0
- package/src/skf-refine-architecture/references/finding-storage.md +21 -0
- package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
- package/src/skf-refine-architecture/references/improvements.md +14 -20
- package/src/skf-refine-architecture/references/init.md +98 -57
- package/src/skf-refine-architecture/references/issue-detection.md +32 -39
- package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
- package/src/skf-refine-architecture/references/report.md +65 -54
- package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
- package/src/skf-rename-skill/SKILL.md +19 -54
- package/src/skf-rename-skill/customize.toml +32 -26
- package/src/skf-rename-skill/references/execute.md +230 -184
- package/src/skf-rename-skill/references/exit-codes.md +7 -7
- package/src/skf-rename-skill/references/health-check.md +1 -7
- package/src/skf-rename-skill/references/invocation-contract.md +25 -0
- package/src/skf-rename-skill/references/report.md +63 -52
- package/src/skf-rename-skill/references/select.md +197 -115
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
- package/src/skf-setup/SKILL.md +26 -26
- package/src/skf-setup/customize.toml +14 -10
- package/src/skf-setup/references/auto-index.md +50 -63
- package/src/skf-setup/references/ccc-index.md +29 -89
- package/src/skf-setup/references/detect-and-tier.md +58 -66
- package/src/skf-setup/references/health-check.md +2 -0
- package/src/skf-setup/references/invocation-contract.md +14 -0
- package/src/skf-setup/references/report.md +43 -166
- package/src/skf-setup/references/tier-rules.md +5 -5
- package/src/skf-setup/references/write-config.md +34 -57
- package/src/skf-test-skill/SKILL.md +17 -57
- package/src/skf-test-skill/assets/output-section-formats.md +33 -34
- package/src/skf-test-skill/customize.toml +27 -13
- package/src/skf-test-skill/references/coherence-check.md +134 -62
- package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
- package/src/skf-test-skill/references/coverage-check.md +217 -254
- package/src/skf-test-skill/references/detect-mode.md +5 -5
- package/src/skf-test-skill/references/external-validators.md +94 -82
- package/src/skf-test-skill/references/health-check.md +6 -7
- package/src/skf-test-skill/references/init.md +163 -88
- package/src/skf-test-skill/references/invocation-contract.md +66 -0
- package/src/skf-test-skill/references/migration-section-rules.md +5 -2
- package/src/skf-test-skill/references/report.md +162 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +41 -155
- package/src/skf-test-skill/references/source-access-protocol.md +19 -92
- package/src/skf-test-skill/references/step-hard-gate.md +51 -33
- package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
- package/src/skf-test-skill/scripts/build-result-context.py +287 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
- package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
- package/src/skf-test-skill/scripts/compute-score.py +223 -45
- package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
- package/src/skf-test-skill/scripts/score-signatures.py +459 -0
- package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
- package/src/skf-test-skill/templates/test-report-template.md +21 -15
- package/src/skf-update-skill/SKILL.md +38 -25
- package/src/skf-update-skill/customize.toml +27 -12
- package/src/skf-update-skill/references/detect-changes.md +233 -222
- package/src/skf-update-skill/references/gap-driven.md +336 -0
- package/src/skf-update-skill/references/health-check.md +31 -5
- package/src/skf-update-skill/references/init.md +250 -84
- package/src/skf-update-skill/references/invocation-contract.md +12 -0
- package/src/skf-update-skill/references/manual-section-rules.md +6 -23
- package/src/skf-update-skill/references/merge.md +180 -47
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +100 -35
- package/src/skf-update-skill/references/write.md +331 -149
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
- package/src/skf-verify-stack/SKILL.md +23 -42
- package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
- package/src/skf-verify-stack/customize.toml +55 -22
- package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
- package/src/skf-verify-stack/references/coverage.md +67 -64
- package/src/skf-verify-stack/references/exit-codes.md +21 -8
- package/src/skf-verify-stack/references/init.md +107 -62
- package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
- package/src/skf-verify-stack/references/integrations.md +106 -65
- package/src/skf-verify-stack/references/report.md +59 -42
- package/src/skf-verify-stack/references/requirements.md +32 -9
- package/src/skf-verify-stack/references/synthesize.md +53 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
- package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
- package/tools/cli/commands/install.js +11 -4
- package/tools/cli/commands/status.js +15 -3
- package/tools/cli/commands/update.js +11 -4
- package/tools/cli/lib/tool-check.js +320 -0
- package/tools/cli/lib/version-check.js +22 -9
- package/tools/cli/skf-cli.js +4 -1
- package/.gitattributes +0 -16
- package/.nvmrc +0 -1
- package/docs/_internal/RELEASING.md +0 -645
- package/release-audits/v1.0.0-launch-audit.md +0 -728
- package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
- package/src/skf-campaign/manifest.yaml +0 -15
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
- package/src/skf-create-skill/references/ecosystem-check.md +0 -74
- package/src/skf-drop-skill/references/headless-contract.md +0 -18
- package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
- package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
- package/src/skf-update-skill/references/validate.md +0 -124
- package/tools/validate-docs-drift.js +0 -233
- package/tools/validate-docs-links.js +0 -665
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# /// script
|
|
2
|
-
# requires-python = ">=3.
|
|
2
|
+
# requires-python = ">=3.11"
|
|
3
3
|
# dependencies = ["pyyaml"]
|
|
4
4
|
# ///
|
|
5
5
|
"""SKF Derive Assembly Shape — decide whether a brief is a whole-language reference.
|
|
@@ -15,7 +15,8 @@ The gate is a single, structured, schema-validated condition: the brief's
|
|
|
15
15
|
`doc_urls` contains at least one entry with `source: "language-registry"`
|
|
16
16
|
(issue #432). Registry-sourced corpora are stamped ONLY by
|
|
17
17
|
skf-language-corpora.py, which is invoked ONLY for a whole-language reference
|
|
18
|
-
(a grammar_file:/tree_triad: signal) in step-auto-scope.md
|
|
18
|
+
(a grammar_file:/tree_triad: signal) in step-auto-scope-corpora.md, which
|
|
19
|
+
step-auto-scope.md §6 loads for that signal. So the gate
|
|
19
20
|
fires exactly when there is registry-guaranteed prose to foreground, and never
|
|
20
21
|
for an ordinary library, a parser library (pest), a component-library, a
|
|
21
22
|
reference-app, or a docs-only brief — none of which carry a language-registry
|
|
@@ -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 Description Guard — defend SKILL.md frontmatter description against
|
|
@@ -23,7 +23,7 @@ Subcommands:
|
|
|
23
23
|
where schema_hash covers the full frontmatter block (handy for
|
|
24
24
|
tamper detection if the caller wants belt-and-braces verification).
|
|
25
25
|
|
|
26
|
-
verify-restore <skill-md> --captured-description <STR>
|
|
26
|
+
verify-restore <skill-md> (--captured-description <STR> | --captured-file <PATH>)
|
|
27
27
|
Re-read the file, compare current description against the captured
|
|
28
28
|
value using token-stream equality (split on whitespace, compare
|
|
29
29
|
element-by-element). If diverged, atomically rewrite the frontmatter
|
|
@@ -32,6 +32,21 @@ Subcommands:
|
|
|
32
32
|
"current_description": "..."}
|
|
33
33
|
If not diverged (including whitespace-only differences), emit
|
|
34
34
|
{"diverged": false, "restored": false, "diff_kind": "none"|"whitespace-only"}
|
|
35
|
+
--captured-file names a JSON file whose `description` string is the
|
|
36
|
+
captured value: `capture`'s output saved to a file, or a metadata.json,
|
|
37
|
+
so the value never passes through a shell string. A file that cannot
|
|
38
|
+
be read, is not a JSON object or has no string `description` exits 1.
|
|
39
|
+
An empty or whitespace-only captured value is refused with exit 1
|
|
40
|
+
before the skill file is read: there is nothing to restore from, and
|
|
41
|
+
writing it back would blank the very field this guard protects.
|
|
42
|
+
|
|
43
|
+
sanitize <skill-md>
|
|
44
|
+
Replace every `<` with `{` and every `>` with `}` in the on-disk
|
|
45
|
+
`description` (create-skill's compile-time substitution, applied
|
|
46
|
+
again) and rewrite the frontmatter only when something changed. Emits
|
|
47
|
+
{"substitutions": N, "sanitized": true|false, "description": "..."}
|
|
48
|
+
where `description` is the value now on disk. No shell quoting of the
|
|
49
|
+
description is involved, so backticks and `$` in it are safe.
|
|
35
50
|
|
|
36
51
|
Token-stream comparison is the documented sweet spot — catches replaced
|
|
37
52
|
words, truncation, and reintroduced angle-brackets while ignoring cosmetic
|
|
@@ -44,11 +59,16 @@ is auto-resolved:
|
|
|
44
59
|
uv run skf-description-guard.py capture <skill-md>
|
|
45
60
|
uv run skf-description-guard.py verify-restore <skill-md> \\
|
|
46
61
|
--captured-description "the snapshot string"
|
|
62
|
+
uv run skf-description-guard.py capture <skill-md> > guard.json
|
|
63
|
+
uv run skf-description-guard.py verify-restore <skill-md> \\
|
|
64
|
+
--captured-file guard.json
|
|
65
|
+
uv run skf-description-guard.py sanitize <skill-md>
|
|
47
66
|
|
|
48
67
|
Exit codes:
|
|
49
68
|
0 — operation succeeded (including no-divergence verify)
|
|
50
|
-
1 — user error (bad args, file missing,
|
|
51
|
-
|
|
69
|
+
1 — user error (bad args, empty captured description, file missing,
|
|
70
|
+
frontmatter unparseable)
|
|
71
|
+
2 — operation failure (restore or sanitize write failed)
|
|
52
72
|
"""
|
|
53
73
|
|
|
54
74
|
from __future__ import annotations
|
|
@@ -57,6 +77,7 @@ import argparse
|
|
|
57
77
|
import hashlib
|
|
58
78
|
import json
|
|
59
79
|
import os
|
|
80
|
+
import stat
|
|
60
81
|
import sys
|
|
61
82
|
import tempfile
|
|
62
83
|
from pathlib import Path
|
|
@@ -168,11 +189,16 @@ def restore_description(skill_md: Path, captured: str) -> None:
|
|
|
168
189
|
block scalars and nested `description:` keys in sibling mappings.
|
|
169
190
|
|
|
170
191
|
Key order is preserved (PyYAML's `safe_dump` honours dict insertion order;
|
|
171
|
-
this module's `requires-python = ">=3.
|
|
192
|
+
this module's `requires-python = ">=3.11"` guarantees ordered dicts).
|
|
172
193
|
Quoting style of *other* fields may change to whatever `safe_dump`
|
|
173
194
|
chooses for each scalar — downstream readers parse YAML, so any valid
|
|
174
195
|
YAML emission is acceptable.
|
|
175
196
|
"""
|
|
197
|
+
if not captured.strip():
|
|
198
|
+
# Defence in depth for library callers: the CLI refuses this earlier,
|
|
199
|
+
# but no code path may ever write an empty description.
|
|
200
|
+
raise ValueError("cannot restore: captured description is empty or whitespace-only")
|
|
201
|
+
|
|
176
202
|
text = skill_md.read_text(encoding="utf-8")
|
|
177
203
|
leading, fm_yaml, body = _split_frontmatter(text)
|
|
178
204
|
if not fm_yaml:
|
|
@@ -206,7 +232,9 @@ def restore_description(skill_md: Path, captured: str) -> None:
|
|
|
206
232
|
prefix=skill_md.name + ".", suffix=".skf-guard.tmp", dir=skill_md.parent
|
|
207
233
|
)
|
|
208
234
|
try:
|
|
209
|
-
|
|
235
|
+
# newline="" writes "\n" untranslated: text mode would turn every
|
|
236
|
+
# line ending into "\r\n" on Windows.
|
|
237
|
+
with os.fdopen(fd, "w", encoding="utf-8", newline="") as tmp:
|
|
210
238
|
tmp.write(new_text)
|
|
211
239
|
tmp.flush()
|
|
212
240
|
os.fsync(tmp.fileno())
|
|
@@ -237,7 +265,44 @@ def _cmd_capture(args: argparse.Namespace) -> int:
|
|
|
237
265
|
return 0
|
|
238
266
|
|
|
239
267
|
|
|
268
|
+
def read_captured_file(path: Path) -> str:
|
|
269
|
+
"""The `description` string of a JSON file: capture's output, or a metadata.json.
|
|
270
|
+
|
|
271
|
+
Raises ValueError when the file cannot be read, holds no JSON object, or
|
|
272
|
+
has no string `description`.
|
|
273
|
+
"""
|
|
274
|
+
try:
|
|
275
|
+
data = json.loads(path.read_text(encoding="utf-8"))
|
|
276
|
+
except (OSError, UnicodeDecodeError) as exc:
|
|
277
|
+
raise ValueError(f"cannot read {path}: {exc}") from exc
|
|
278
|
+
except json.JSONDecodeError as exc:
|
|
279
|
+
raise ValueError(f"{path} is not JSON: {exc}") from exc
|
|
280
|
+
if not isinstance(data, dict) or not isinstance(data.get("description"), str):
|
|
281
|
+
raise ValueError(f"{path} has no string `description`")
|
|
282
|
+
return data["description"]
|
|
283
|
+
|
|
284
|
+
|
|
240
285
|
def _cmd_verify_restore(args: argparse.Namespace) -> int:
|
|
286
|
+
if args.captured_file is not None:
|
|
287
|
+
try:
|
|
288
|
+
captured = read_captured_file(Path(args.captured_file))
|
|
289
|
+
except ValueError as exc:
|
|
290
|
+
_fail(str(exc))
|
|
291
|
+
source = f"the description in {args.captured_file}"
|
|
292
|
+
else:
|
|
293
|
+
captured = args.captured_description
|
|
294
|
+
source = "--captured-description"
|
|
295
|
+
if not captured.strip():
|
|
296
|
+
# Restoring an empty snapshot would blank the field the guard exists
|
|
297
|
+
# to protect. The snapshot was lost from context, or the description
|
|
298
|
+
# was already empty before the tool ran; either way there is nothing
|
|
299
|
+
# to restore, so refuse before touching the file.
|
|
300
|
+
_fail(
|
|
301
|
+
f"{source} is empty or whitespace-only; refusing to "
|
|
302
|
+
"overwrite the on-disk description with an empty value (the capture "
|
|
303
|
+
"was lost, or the field was already empty before the tool ran)"
|
|
304
|
+
)
|
|
305
|
+
|
|
241
306
|
skill_md = Path(args.skill_md)
|
|
242
307
|
if not skill_md.is_file():
|
|
243
308
|
_fail(f"file not found: {skill_md}")
|
|
@@ -246,7 +311,6 @@ def _cmd_verify_restore(args: argparse.Namespace) -> int:
|
|
|
246
311
|
except ValueError as exc:
|
|
247
312
|
_fail(str(exc))
|
|
248
313
|
|
|
249
|
-
captured = args.captured_description
|
|
250
314
|
diff_kind = classify_divergence(captured, current)
|
|
251
315
|
diverged = is_diverged(diff_kind)
|
|
252
316
|
|
|
@@ -271,6 +335,39 @@ def _cmd_verify_restore(args: argparse.Namespace) -> int:
|
|
|
271
335
|
return 0
|
|
272
336
|
|
|
273
337
|
|
|
338
|
+
def sanitize_angle_brackets(description: str) -> tuple[str, int]:
|
|
339
|
+
"""Replace every `<` with `{` and every `>` with `}`; return (value, substitutions)."""
|
|
340
|
+
count = description.count("<") + description.count(">")
|
|
341
|
+
return description.replace("<", "{").replace(">", "}"), count
|
|
342
|
+
|
|
343
|
+
|
|
344
|
+
def _cmd_sanitize(args: argparse.Namespace) -> int:
|
|
345
|
+
skill_md = Path(args.skill_md)
|
|
346
|
+
try:
|
|
347
|
+
st = os.stat(skill_md) # not Path.is_file(): Python 3.14 hides EACCES there
|
|
348
|
+
except OSError as exc:
|
|
349
|
+
_fail(f"cannot read {skill_md}: {exc.strerror or exc}")
|
|
350
|
+
if not stat.S_ISREG(st.st_mode):
|
|
351
|
+
_fail(f"not a file: {skill_md}")
|
|
352
|
+
try:
|
|
353
|
+
current, _ = read_description(skill_md)
|
|
354
|
+
except (OSError, ValueError) as exc:
|
|
355
|
+
_fail(str(exc))
|
|
356
|
+
sanitized, count = sanitize_angle_brackets(current)
|
|
357
|
+
result = {"substitutions": count, "sanitized": False, "description": current}
|
|
358
|
+
if count:
|
|
359
|
+
try:
|
|
360
|
+
restore_description(skill_md, sanitized)
|
|
361
|
+
except (OSError, ValueError) as exc:
|
|
362
|
+
json.dump({**result, "write_error": str(exc)}, sys.stdout)
|
|
363
|
+
sys.stdout.write("\n")
|
|
364
|
+
return 2
|
|
365
|
+
result.update(sanitized=True, description=sanitized)
|
|
366
|
+
json.dump(result, sys.stdout)
|
|
367
|
+
sys.stdout.write("\n")
|
|
368
|
+
return 0
|
|
369
|
+
|
|
370
|
+
|
|
274
371
|
def _fail(msg: str) -> None:
|
|
275
372
|
print(f"error: {msg}", file=sys.stderr)
|
|
276
373
|
raise SystemExit(1)
|
|
@@ -292,13 +389,24 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
292
389
|
help="verify on-disk description against captured snapshot; restore if diverged",
|
|
293
390
|
)
|
|
294
391
|
p_ver.add_argument("skill_md", help="path to SKILL.md")
|
|
295
|
-
p_ver.
|
|
392
|
+
captured = p_ver.add_mutually_exclusive_group(required=True)
|
|
393
|
+
captured.add_argument(
|
|
296
394
|
"--captured-description",
|
|
297
|
-
required=True,
|
|
298
395
|
help="the description string captured before the tool call",
|
|
299
396
|
)
|
|
397
|
+
captured.add_argument(
|
|
398
|
+
"--captured-file",
|
|
399
|
+
help="a JSON file whose `description` is the captured value (capture's output saved to a file)",
|
|
400
|
+
)
|
|
300
401
|
p_ver.set_defaults(func=_cmd_verify_restore)
|
|
301
402
|
|
|
403
|
+
p_san = sub.add_parser(
|
|
404
|
+
"sanitize",
|
|
405
|
+
help="replace every < with { and every > with } in the on-disk description",
|
|
406
|
+
)
|
|
407
|
+
p_san.add_argument("skill_md", help="path to SKILL.md")
|
|
408
|
+
p_san.set_defaults(func=_cmd_sanitize)
|
|
409
|
+
|
|
302
410
|
return parser
|
|
303
411
|
|
|
304
412
|
|