bmad-module-skill-forge 2.2.0 → 4.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 +143 -18
- package/docs/verifying-a-skill.md +87 -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 +3 -3
- 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 +31 -59
- 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 +233 -64
- package/src/shared/scripts/skf-build-change-manifest.py +2753 -28
- 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 +772 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +267 -105
- 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 +21 -3
- 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 +197 -55
- 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 +5247 -96
- package/src/shared/scripts/skf-extraction-inventory.py +1280 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +664 -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 +469 -205
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +700 -0
- package/src/shared/scripts/skf-hash-content.py +180 -20
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +161 -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 +143 -20
- 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 +176 -28
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +64 -8
- 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 +155 -14
- 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 +787 -121
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +120 -67
- 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 +23 -2
- 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 +3945 -152
- package/src/shared/scripts/skf-write-skill-brief.py +406 -25
- 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 +28 -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/health-check.md +2 -0
- package/src/skf-audit-skill/references/init.md +149 -210
- package/src/skf-audit-skill/references/re-index.md +103 -110
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +34 -25
- 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 +80 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +712 -0
- package/src/skf-brief-skill/SKILL.md +37 -26
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +18 -25
- package/src/skf-brief-skill/assets/skill-brief-schema.md +30 -23
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +144 -127
- package/src/skf-brief-skill/references/confirm-brief.md +11 -9
- 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 +26 -100
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +7 -10
- 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 +11 -8
- package/src/skf-create-skill/assets/skill-sections.md +21 -11
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +36 -58
- 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 +119 -70
- 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 +37 -0
- package/src/skf-create-skill/references/extract.md +204 -162
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +11 -11
- package/src/skf-create-skill/references/extraction-patterns.md +588 -201
- 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 +37 -57
- package/src/skf-create-skill/references/source-resolution-protocols.md +58 -169
- 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 +83 -146
- package/src/skf-drop-skill/references/health-check.md +2 -0
- 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 +122 -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 +209 -264
- 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 +164 -91
- 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 +164 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +42 -155
- package/src/skf-test-skill/references/source-access-protocol.md +18 -94
- 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 +380 -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 +1666 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +1198 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +547 -79
- package/src/skf-test-skill/scripts/score-signatures.py +479 -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 +133 -56
- 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 +253 -223
- 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 +254 -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 +182 -49
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +102 -35
- package/src/skf-update-skill/references/write.md +357 -155
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +183 -46
- 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,22 +1,50 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# /// script
|
|
3
|
-
# requires-python = ">=3.
|
|
3
|
+
# requires-python = ">=3.11"
|
|
4
4
|
# dependencies = []
|
|
5
5
|
# ///
|
|
6
6
|
"""Deterministic contextual-coherence aggregator.
|
|
7
7
|
|
|
8
8
|
Pure-function tally + weighted mean for the SKF test-skill workflow
|
|
9
9
|
(step-04, coherence-check.md §5c). The prompt keeps the judgment — deciding
|
|
10
|
-
which
|
|
11
|
-
complete (§5). This script does
|
|
12
|
-
the
|
|
10
|
+
which skill, type-import and integration-pattern references are accurate
|
|
11
|
+
(§4) and which integration patterns are complete (§5). This script does the
|
|
12
|
+
counting and the arithmetic those judgments feed: it counts the valid
|
|
13
|
+
references from the per-reference results, then computes the
|
|
14
|
+
reference-validity ratio, the integration-completeness ratio, and their
|
|
13
15
|
fixed 0.6 / 0.4 weighted mean. That way the 18%-weight `coherence` input to
|
|
14
16
|
compute-score.py is computed once, deterministically, instead of by hand on
|
|
15
17
|
every run (this skill grades other skills — a false PASS is catastrophic, so
|
|
16
18
|
every scoring input is scripted for run-to-run reproducibility).
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
+
Per-reference input (the files coherence-check.md §5c passes):
|
|
21
|
+
--references skf-scan-skill-md-structure.py reference-check output: its
|
|
22
|
+
`references[]` hold the file-path and script/asset
|
|
23
|
+
references, each valid when its `status` is "ok"
|
|
24
|
+
("missing": no file inside an allowed root; "escapes":
|
|
25
|
+
outside every root)
|
|
26
|
+
--judged the §4 subagent results for the other references (skill,
|
|
27
|
+
type-import, integration-pattern), as the subagent returned
|
|
28
|
+
them (a wrapping markdown fence is stripped): a JSON array,
|
|
29
|
+
or an object with a `references` array, of
|
|
30
|
+
{"reference", "line", "target_exists", "type_match",
|
|
31
|
+
"signature_match", "issues"}; valid when the three
|
|
32
|
+
booleans are true and `issues` is empty. Optional: a skill
|
|
33
|
+
with no such reference has no file.
|
|
34
|
+
--integration the §5 integration JSON ({"patterns_documented",
|
|
35
|
+
"patterns_complete", ...}, fence stripped)
|
|
36
|
+
`total_references` is the number of entries in both, `valid_references`
|
|
37
|
+
the number of valid ones, and `invalidReferences[]` lists each invalid
|
|
38
|
+
one with its `status`: "missing" or "escapes" from the scan, and for a
|
|
39
|
+
judged one "missing" (target_exists false) or "inaccurate". Each entry
|
|
40
|
+
also carries what coherence-check.md §5c needs for its gap, so the
|
|
41
|
+
caller never matches it back to the per-reference files: a scanned
|
|
42
|
+
one's `canonical` (the realpath the scanner checked, which an escape
|
|
43
|
+
names) and `root`, and a judged one's `issues` (when the subagent gave
|
|
44
|
+
none, the flags that are false, such as "type_match: false").
|
|
45
|
+
|
|
46
|
+
Formula (this script is its one home: scoring-rules.md points here, and
|
|
47
|
+
coherence-check.md §5 defines what makes a pattern complete):
|
|
20
48
|
|
|
21
49
|
reference_validity = (valid_references / total_references) * 100
|
|
22
50
|
integration_completeness = (complete_patterns / total_patterns) * 100
|
|
@@ -27,7 +55,7 @@ Field-name mapping: the step-04 §5 integration JSON calls the pattern counts
|
|
|
27
55
|
(= complete_patterns); this script's input uses those step-04 names directly
|
|
28
56
|
so §5c passes them through unrenamed.
|
|
29
57
|
|
|
30
|
-
Edge cases (
|
|
58
|
+
Edge cases (absence is never penalized):
|
|
31
59
|
* patterns_documented == 0 -> no integration patterns to weigh, so
|
|
32
60
|
combined_coherence == reference_validity and integrationCompleteness is
|
|
33
61
|
null. (Do not divide by zero.)
|
|
@@ -46,11 +74,18 @@ Input schema (one JSON object):
|
|
|
46
74
|
|
|
47
75
|
Output (JSON):
|
|
48
76
|
{
|
|
49
|
-
"input": { ...echo... },
|
|
77
|
+
"input": { ...echo, or the counts the files gave... },
|
|
50
78
|
"referenceValidity": <0-100>,
|
|
51
79
|
"integrationCompleteness": <0-100 | null when patterns_documented == 0>,
|
|
52
80
|
"combinedCoherence": <0-100>,
|
|
53
|
-
"patternsScored": <bool
|
|
81
|
+
"patternsScored": <bool>,
|
|
82
|
+
"invalidReferences": [{"source": "scan" | "judged", "line": N | null,
|
|
83
|
+
"target": "...", "status": "...",
|
|
84
|
+
"canonical": "..." | null, "root": "..." | null,
|
|
85
|
+
"issues": ["..."]}]
|
|
86
|
+
# with the per-reference files only; canonical
|
|
87
|
+
# and root are null for a judged entry, and
|
|
88
|
+
# issues is empty for a scanned one
|
|
54
89
|
}
|
|
55
90
|
or {"error": ..., "code": "INVALID_INPUT"} on a schema violation.
|
|
56
91
|
|
|
@@ -58,14 +93,20 @@ Percentages use the same JavaScript-compatible 2-decimal rounding as
|
|
|
58
93
|
compute-score.py so the two scoring scripts agree to the last digit.
|
|
59
94
|
|
|
60
95
|
CLI usage (mirrors compute-score.py):
|
|
61
|
-
uv run aggregate-coherence.py
|
|
62
|
-
uv run aggregate-coherence.py
|
|
63
|
-
|
|
96
|
+
uv run aggregate-coherence.py --references <scan.json> [--judged <file>] --integration <file>
|
|
97
|
+
uv run aggregate-coherence.py '<JSON>' # counts, positional arg
|
|
98
|
+
uv run aggregate-coherence.py --json-input '<JSON>' # counts, explicit flag form
|
|
99
|
+
cat input.json | uv run aggregate-coherence.py --stdin # counts, piped input
|
|
100
|
+
|
|
101
|
+
--output <file> also writes the result to a file (UTF-8 JSON), the one
|
|
102
|
+
compute-score.py --coherence reads; a refused input removes a file left
|
|
103
|
+
there earlier.
|
|
64
104
|
|
|
65
105
|
Exit codes (same convention as compute-score.py / reconcile-coverage.py):
|
|
66
|
-
0
|
|
67
|
-
1
|
|
68
|
-
|
|
106
|
+
0 a result object was emitted
|
|
107
|
+
1 input could not be parsed at all (no input provided, malformed JSON,
|
|
108
|
+
or a file that cannot be read)
|
|
109
|
+
2 input parsed but schema/semantics invalid
|
|
69
110
|
|
|
70
111
|
Both 1 and 2 emit an {"error": ..., "code": "INVALID_INPUT"} envelope on stdout,
|
|
71
112
|
so the envelope's presence — not the specific code — tells a caller the input was
|
|
@@ -75,11 +116,13 @@ refused rather than scored.
|
|
|
75
116
|
from __future__ import annotations
|
|
76
117
|
|
|
77
118
|
import argparse
|
|
119
|
+
import importlib.util
|
|
78
120
|
import json
|
|
79
121
|
import math
|
|
80
122
|
import sys
|
|
123
|
+
from pathlib import Path
|
|
81
124
|
|
|
82
|
-
# Weights for the combined-coherence mean
|
|
125
|
+
# Weights for the combined-coherence mean. Kept as
|
|
83
126
|
# named constants so the 0.6 / 0.4 split lives in exactly one place.
|
|
84
127
|
REFERENCE_VALIDITY_WEIGHT = 0.6
|
|
85
128
|
INTEGRATION_COMPLETENESS_WEIGHT = 0.4
|
|
@@ -91,6 +134,26 @@ COUNT_FIELDS = (
|
|
|
91
134
|
"patterns_complete",
|
|
92
135
|
)
|
|
93
136
|
|
|
137
|
+
# reference-check statuses (skf-scan-skill-md-structure.py); only "ok" is valid.
|
|
138
|
+
SCAN_STATUSES = ("ok", "missing", "escapes")
|
|
139
|
+
JUDGED_FLAGS = ("target_exists", "type_match", "signature_match")
|
|
140
|
+
|
|
141
|
+
_INVENTORY_MODULE = None
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
def _inventory_module():
|
|
145
|
+
"""validate-inventory.py beside this script: the fence rule lives there."""
|
|
146
|
+
global _INVENTORY_MODULE
|
|
147
|
+
if _INVENTORY_MODULE is None:
|
|
148
|
+
sibling = Path(__file__).resolve().parent / "validate-inventory.py"
|
|
149
|
+
spec = importlib.util.spec_from_file_location("skf_validate_inventory", sibling)
|
|
150
|
+
if spec is None or spec.loader is None or not sibling.is_file():
|
|
151
|
+
raise ImportError(f"validate-inventory.py not found beside {Path(__file__).name}")
|
|
152
|
+
module = importlib.util.module_from_spec(spec)
|
|
153
|
+
spec.loader.exec_module(module)
|
|
154
|
+
_INVENTORY_MODULE = module
|
|
155
|
+
return _INVENTORY_MODULE
|
|
156
|
+
|
|
94
157
|
|
|
95
158
|
def round2(value):
|
|
96
159
|
"""Round to 2 decimals with JavaScript-compatible half-up rounding.
|
|
@@ -207,6 +270,98 @@ def aggregate_coherence(inp):
|
|
|
207
270
|
}
|
|
208
271
|
|
|
209
272
|
|
|
273
|
+
def count_references(scan, judged):
|
|
274
|
+
"""Count the valid references from the per-reference results.
|
|
275
|
+
|
|
276
|
+
`scan` is the reference-check output (an object with `references[]`),
|
|
277
|
+
`judged` the list of subagent results (or None). Returns
|
|
278
|
+
(valid, total, invalid[]) or an error string.
|
|
279
|
+
|
|
280
|
+
>>> scan = {"references": [{"line": 3, "target": "a.md", "status": "ok"},
|
|
281
|
+
... {"line": 5, "target": "../x", "status": "escapes"}]}
|
|
282
|
+
>>> judged = [{"reference": "react", "line": 9, "target_exists": True, "type_match": True,
|
|
283
|
+
... "signature_match": True, "issues": []},
|
|
284
|
+
... {"reference": "./types", "line": 12, "target_exists": True, "type_match": False,
|
|
285
|
+
... "signature_match": True, "issues": []}]
|
|
286
|
+
>>> valid, total, invalid = count_references(scan, judged)
|
|
287
|
+
>>> valid, total, [(i["target"], i["status"]) for i in invalid]
|
|
288
|
+
(2, 4, [('../x', 'escapes'), ('./types', 'inaccurate')])
|
|
289
|
+
>>> invalid[1]["issues"], invalid[1]["canonical"]
|
|
290
|
+
(['type_match: false'], None)
|
|
291
|
+
"""
|
|
292
|
+
refs = scan.get("references") if isinstance(scan, dict) else None
|
|
293
|
+
if not isinstance(refs, list):
|
|
294
|
+
return "--references holds no `references` array (pass the reference-check output)"
|
|
295
|
+
valid, invalid = 0, []
|
|
296
|
+
for index, ref in enumerate(refs):
|
|
297
|
+
if not isinstance(ref, dict) or ref.get("status") not in SCAN_STATUSES:
|
|
298
|
+
return f"--references references[{index}] has no status in {list(SCAN_STATUSES)}"
|
|
299
|
+
if ref["status"] == "ok":
|
|
300
|
+
valid += 1
|
|
301
|
+
else:
|
|
302
|
+
invalid.append({"source": "scan", "line": ref.get("line"),
|
|
303
|
+
"target": ref.get("target"), "status": ref["status"],
|
|
304
|
+
"canonical": ref.get("canonical"), "root": ref.get("root"),
|
|
305
|
+
"issues": []})
|
|
306
|
+
for index, ref in enumerate(judged or []):
|
|
307
|
+
if not isinstance(ref, dict):
|
|
308
|
+
return f"--judged [{index}] is not an object"
|
|
309
|
+
for flag in JUDGED_FLAGS:
|
|
310
|
+
if not isinstance(ref.get(flag), bool):
|
|
311
|
+
return f"--judged [{index}] `{flag}` must be true or false"
|
|
312
|
+
issues = ref.get("issues", [])
|
|
313
|
+
if not isinstance(issues, list):
|
|
314
|
+
return f"--judged [{index}] `issues` must be a list"
|
|
315
|
+
if all(ref[flag] for flag in JUDGED_FLAGS) and not issues:
|
|
316
|
+
valid += 1
|
|
317
|
+
else:
|
|
318
|
+
invalid.append({"source": "judged", "line": ref.get("line"), "target": ref.get("reference"),
|
|
319
|
+
"status": "missing" if not ref["target_exists"] else "inaccurate",
|
|
320
|
+
"canonical": None, "root": None,
|
|
321
|
+
"issues": [str(i) for i in issues]
|
|
322
|
+
or [f"{flag}: false" for flag in JUDGED_FLAGS if not ref[flag]]})
|
|
323
|
+
return valid, len(refs) + len(judged or []), invalid
|
|
324
|
+
|
|
325
|
+
|
|
326
|
+
def _read_json_file(path, label, fenced=False):
|
|
327
|
+
"""Parse a JSON file; a subagent response may come wrapped in a markdown fence."""
|
|
328
|
+
text = Path(path).read_bytes().decode("utf-8-sig")
|
|
329
|
+
if fenced:
|
|
330
|
+
text = _inventory_module().strip_fences(text)
|
|
331
|
+
try:
|
|
332
|
+
return json.loads(text)
|
|
333
|
+
except json.JSONDecodeError as exc:
|
|
334
|
+
raise ValueError(f"{label} {path} is not valid JSON: {exc.msg}") from exc
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
def aggregate_from_files(references, judged=None, integration=None):
|
|
338
|
+
"""Aggregate from the per-reference files and the §5 integration JSON."""
|
|
339
|
+
scan = _read_json_file(references, "--references")
|
|
340
|
+
results = None
|
|
341
|
+
if judged is not None:
|
|
342
|
+
results = _read_json_file(judged, "--judged", fenced=True)
|
|
343
|
+
if isinstance(results, dict):
|
|
344
|
+
results = results.get("references")
|
|
345
|
+
if not isinstance(results, list):
|
|
346
|
+
return make_error(f"--judged {judged} holds no array of reference results")
|
|
347
|
+
patterns = _read_json_file(integration, "--integration", fenced=True)
|
|
348
|
+
if not isinstance(patterns, dict):
|
|
349
|
+
return make_error(f"--integration {integration} is not a JSON object")
|
|
350
|
+
counted = count_references(scan, results)
|
|
351
|
+
if isinstance(counted, str):
|
|
352
|
+
return make_error(counted)
|
|
353
|
+
valid, total, invalid = counted
|
|
354
|
+
result = aggregate_coherence({
|
|
355
|
+
"valid_references": valid,
|
|
356
|
+
"total_references": total,
|
|
357
|
+
"patterns_documented": patterns.get("patterns_documented"),
|
|
358
|
+
"patterns_complete": patterns.get("patterns_complete"),
|
|
359
|
+
})
|
|
360
|
+
if result.get("code") != "INVALID_INPUT":
|
|
361
|
+
result["invalidReferences"] = invalid
|
|
362
|
+
return result
|
|
363
|
+
|
|
364
|
+
|
|
210
365
|
def _build_parser() -> argparse.ArgumentParser:
|
|
211
366
|
parser = argparse.ArgumentParser(
|
|
212
367
|
prog="aggregate-coherence",
|
|
@@ -240,9 +395,25 @@ def _build_parser() -> argparse.ArgumentParser:
|
|
|
240
395
|
action="store_true",
|
|
241
396
|
help="Read the JSON object from stdin.",
|
|
242
397
|
)
|
|
398
|
+
parser.add_argument("--references", metavar="PATH",
|
|
399
|
+
help="skf-scan-skill-md-structure.py reference-check output")
|
|
400
|
+
parser.add_argument("--judged", metavar="PATH",
|
|
401
|
+
help="the subagent results for the skill, type-import and integration references")
|
|
402
|
+
parser.add_argument("--integration", metavar="PATH",
|
|
403
|
+
help="the integration JSON (patterns_documented, patterns_complete)")
|
|
404
|
+
parser.add_argument("--output", metavar="PATH", help="also write the result to this file")
|
|
243
405
|
return parser
|
|
244
406
|
|
|
245
407
|
|
|
408
|
+
def _write_output(path, result):
|
|
409
|
+
target = Path(path)
|
|
410
|
+
if result.get("code") == "INVALID_INPUT":
|
|
411
|
+
target.unlink(missing_ok=True)
|
|
412
|
+
return
|
|
413
|
+
target.parent.mkdir(parents=True, exist_ok=True)
|
|
414
|
+
target.write_bytes((json.dumps(result, indent=2) + "\n").encode("utf-8"))
|
|
415
|
+
|
|
416
|
+
|
|
246
417
|
def _resolve_input(args: argparse.Namespace) -> str:
|
|
247
418
|
if args.stdin:
|
|
248
419
|
return sys.stdin.read()
|
|
@@ -256,22 +427,39 @@ def _resolve_input(args: argparse.Namespace) -> str:
|
|
|
256
427
|
def main(argv: list[str] | None = None) -> int:
|
|
257
428
|
parser = _build_parser()
|
|
258
429
|
args = parser.parse_args(argv)
|
|
259
|
-
|
|
260
|
-
if not
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
430
|
+
files = (args.references, args.judged, args.integration)
|
|
431
|
+
if any(f is not None for f in files):
|
|
432
|
+
if args.stdin or args.json_input_flag is not None or args.json_input is not None:
|
|
433
|
+
parser.error("pass the counts or the files (--references, --judged, --integration), not both")
|
|
434
|
+
if args.references is None or args.integration is None:
|
|
435
|
+
parser.error("--references and --integration go together (--judged is optional)")
|
|
436
|
+
try:
|
|
437
|
+
result = aggregate_from_files(*files)
|
|
438
|
+
except (OSError, UnicodeDecodeError, ValueError) as exc:
|
|
439
|
+
print(json.dumps(make_error(str(exc)), indent=2))
|
|
440
|
+
if args.output:
|
|
441
|
+
Path(args.output).unlink(missing_ok=True)
|
|
442
|
+
return 1
|
|
443
|
+
else:
|
|
444
|
+
raw = _resolve_input(args)
|
|
445
|
+
if not raw.strip():
|
|
446
|
+
parser.print_usage(file=sys.stderr)
|
|
447
|
+
print(
|
|
448
|
+
"error: no input provided (--references and --integration, positional arg, "
|
|
449
|
+
"--json-input, or --stdin)",
|
|
450
|
+
file=sys.stderr,
|
|
451
|
+
)
|
|
452
|
+
return 1
|
|
267
453
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
454
|
+
try:
|
|
455
|
+
data = json.loads(raw)
|
|
456
|
+
except json.JSONDecodeError as exc:
|
|
457
|
+
print(json.dumps(make_error(f"Invalid JSON: {exc.msg}"), indent=2))
|
|
458
|
+
return 1
|
|
273
459
|
|
|
274
|
-
|
|
460
|
+
result = aggregate_coherence(data)
|
|
461
|
+
if args.output:
|
|
462
|
+
_write_output(args.output, result)
|
|
275
463
|
print(json.dumps(result, indent=2))
|
|
276
464
|
# Same convention as compute-score.py / reconcile-coverage.py. This script
|
|
277
465
|
# produces the coherence percentage that score.md §3a feeds to
|