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
|
@@ -2,57 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
## Shell Path Quoting
|
|
4
4
|
|
|
5
|
-
Every shell snippet in this document uses `{...}` placeholders for paths. **Always wrap path interpolations in double quotes** when emitting the actual command
|
|
5
|
+
Every shell snippet in this document and in step 3 §2b uses `{...}` placeholders for paths. **Always wrap path interpolations in double quotes** when emitting the actual command: `uv run {sourceTreeHelper} resolve --source-repo "{source_repo}"`, `cd "{remote_clone_path}"`, `cd "{project-root}"`. Home folders on macOS often contain spaces, which break unquoted shell, and WSL2 and Windows paths do too, so the quoting convention applies on every platform.
|
|
6
6
|
|
|
7
7
|
## Tag Resolution
|
|
8
8
|
|
|
9
|
-
Tag resolution maps a declared version in the brief onto a concrete git ref
|
|
9
|
+
Tag resolution maps a declared version in the brief onto a concrete git ref, so the skill is built from code matching its declared version. Three signals can drive it, in priority order: an explicit `brief.target_ref` (a ref the user states verbatim, highest priority), an **explicit** `brief.target_version` (deliberate user intent), or an **implicit** `brief.version` (auto-populated hint from `brief-skill`). They apply only to a remote source read at Forge tier or above: step 3 §2b hands them to the `resolve` subcommand of `{sourceTreeHelper}` as flags (its command shows which), and resolve lists the remote's tags and does the matching. A Quick-tier remote source reads `HEAD`.
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
| The brief sets | What resolve reads |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `target_ref` (it takes priority) | that ref as given: a tag (a tag wins over a branch of the same name), a branch, `HEAD` or a full commit |
|
|
14
|
+
| `target_version` | the first of seven tag forms that exists (Explicit Tag Resolution) |
|
|
15
|
+
| only `version` | the first of two tag forms that exists (Implicit Tag Resolution) |
|
|
16
|
+
| none of them | `HEAD`, the default branch |
|
|
12
17
|
|
|
13
|
-
|
|
18
|
+
`target_ref` is the escape hatch for ref conventions the tag forms do not cover, notably monorepo crate tags whose prefix differs from the skill name (skill `livekit-rust` built from tag `livekit/v0.7.42`). When the brief sets it and a version too, resolve gets both: a `target_ref` the remote does not have adds the warning "target_ref ({target_ref}) does not resolve in {source_repo}; falling back to version matching", and resolve matches the version instead.
|
|
14
19
|
|
|
15
20
|
### Explicit Tag Resolution (when target_version is set)
|
|
16
21
|
|
|
17
|
-
|
|
22
|
+
resolve tries these forms of `{target_version}` against the remote's tags, in priority order (every form but the first drops a leading `v` of the version):
|
|
18
23
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
- **Exact match:** `{target_version}` (e.g., `0.5.0`)
|
|
25
|
+
- **With `v` prefix:** `v{target_version}` (e.g., `v0.5.0`)
|
|
26
|
+
- **With package scope (monorepos):** `{brief.name}@{target_version}` or `@{scope}/{brief.name}@{target_version}`
|
|
27
|
+
- **With crate/package-directory prefix (monorepos):** `{brief.name}/v{target_version}`, `{brief.name}/{target_version}`, or `{brief.name}-v{target_version}` (e.g. `tokio/v1.0.0`). These cover monorepos whose tags are prefixed by the crate or package directory **when that directory equals the skill name**. When it differs (crate `livekit` for skill `livekit-rust`, tag `livekit/v0.7.42`), no form can infer it: set `target_ref` instead.
|
|
22
28
|
|
|
23
|
-
|
|
24
|
-
- **Exact match:** `{target_version}` (e.g., `0.5.0`)
|
|
25
|
-
- **With `v` prefix:** `v{target_version}` (e.g., `v0.5.0`)
|
|
26
|
-
- **With package scope (monorepos):** `{brief.name}@{target_version}` or `@{scope}/{brief.name}@{target_version}`
|
|
27
|
-
- **With crate/package-directory prefix (monorepos):** `{brief.name}/v{target_version}`, `{brief.name}/{target_version}`, or `{brief.name}-v{target_version}` (e.g. `tokio/v1.0.0`). Covers monorepos whose tags are prefixed by the crate/package directory **when that directory equals the skill name**. When the directory differs from the skill name (e.g. crate `livekit` for skill `livekit-rust`, tag `livekit/v0.7.42`), this heuristic can't infer it — set `target_ref` explicitly instead.
|
|
29
|
+
Outcomes, from `tag_resolution.status`:
|
|
28
30
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
- **Zero matches:** ⚠️ Warn: "No git tag found matching version {target_version}. Closest available tags: {list 5 nearest by semver sort}. Falling back to default branch — **extracted code may not match target version.**" Set `source_ref` to `HEAD` and proceed with default branch.
|
|
31
|
+
- **`matched`:** one form matched. resolve read that tag, and it is `source_ref`.
|
|
32
|
+
- **`ambiguous`:** several tags matched, and nothing was read yet: see Several Matching Tags below.
|
|
33
|
+
- **`fallback-head`:** no tag matched, and resolve read `HEAD`; the warning it printed names the nearest tags. ⚠️ Add: "**Extracted code may not match target version {target_version}.**"
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
`source_ref` is written to metadata.json and provenance-map.json for downstream workflows (update-skill, audit-skill) to read the same ref again.
|
|
35
36
|
|
|
36
37
|
### Implicit Tag Resolution (when only brief.version is set)
|
|
37
38
|
|
|
38
|
-
When `brief.target_version` is absent but `brief.version` is present
|
|
39
|
+
When `brief.target_version` is absent but `brief.version` is present, `brief.version` is an **implicit** target version. This matches `brief-skill`'s behavior, which auto-populates `brief.version` from the latest non-prerelease release tag, so a tag matching `brief.version` is the common case, and silently reading HEAD would produce a skill labeled with `brief.version` but built from an unrelated default-branch commit.
|
|
39
40
|
|
|
40
|
-
|
|
41
|
+
With `--implicit`, resolve tries only two forms, in this order:
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
- **With `v` prefix:** `v{brief.version}` (e.g., `v0.3.37`)
|
|
43
|
+
- **Exact match:** `{brief.version}` (e.g., `0.3.37`)
|
|
44
|
+
- **With `v` prefix:** `v{brief.version}` (e.g., `v0.3.37`)
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
- **Single match:** Store the matched tag as `source_ref`. Use it as `{branch}` in all subsequent clone/API commands. Do not warn — this is the expected path.
|
|
48
|
-
- **Multiple matches:** Present the matching tags to the user — "Multiple tags match `brief.version` ({brief.version}): {list}. Which one should I use, or fall back to HEAD?" Wait for selection.
|
|
49
|
-
- **Zero matches:** ⚠️ Warn: "No git tag found matching `brief.version` ({brief.version}). Falling back to default branch — **extracted code may not match the declared version.** If you intended to pin a specific version, set `target_version` explicitly in the brief." Set `source_ref` to `HEAD` and proceed with default branch. Append `tag_resolution: {status: "fallback-head", requested: "{brief.version}", reason: "no-matching-tag"}` to the in-context evidence-report payload so step 5 §7 surfaces the fallback in the evidence report. This turns the warning into a persistent audit trail a reviewer can grep later, not just a one-shot stderr line.
|
|
46
|
+
Package-scoped monorepo forms are **not** tried: they need deliberate user intent through `target_version`, since implicit matching against a monorepo tag like `{brief.name}@{version}` could silently select a sibling package's ref.
|
|
50
47
|
|
|
51
|
-
|
|
48
|
+
Outcomes, from `tag_resolution.status`:
|
|
52
49
|
|
|
53
|
-
|
|
50
|
+
- **`matched`:** no warning; this is the expected path.
|
|
51
|
+
- **`ambiguous`:** see Several Matching Tags below, where `HEAD` is one of the choices.
|
|
52
|
+
- **`fallback-head`:** no tag matched, and resolve read `HEAD`; the warning it printed names the nearest tags. ⚠️ Add: "**Extracted code may not match the declared version {brief.version}.** If you intended to pin a specific version, set `target_version` explicitly in the brief." Keep the `tag_resolution` record resolve printed (`status: "fallback-head"`, `requested`, `reason: "no-matching-tag"`) in the in-context evidence-report payload so step 5 §7 surfaces the fallback in the evidence report: a persistent audit trail a reviewer can grep later, not just a one-shot warning.
|
|
54
53
|
|
|
55
|
-
**
|
|
54
|
+
**Do not halt on zero matches.** Implicit resolution never blocks compilation: `brief.version` is an auto-populated hint, and some repositories simply do not tag releases. The warning is sufficient notice; the evidence report in step 8 will surface the HEAD fallback for reviewers.
|
|
55
|
+
|
|
56
|
+
**Interaction with Version Reconciliation (below):** When implicit tag resolution matches a tag, the tree's source files should carry the same version as `brief.version`, so the Version Reconciliation section's source-vs-brief mismatch warning will not fire. When implicit resolution falls back to HEAD, Version Reconciliation runs normally against the default branch's version file and may produce its own mismatch warning.
|
|
57
|
+
|
|
58
|
+
### Several Matching Tags
|
|
59
|
+
|
|
60
|
+
When resolve prints `ambiguous`, it read nothing, and `tag_resolution.candidates` lists the matching tags in the priority order above. This is the one choice tag resolution leaves to you:
|
|
61
|
+
|
|
62
|
+
- Ask: "Multiple tags match version {tag_resolution.requested}: {candidates}. Which one should I use?", adding "or should I fall back to HEAD?" for an implicit version, and "Setting `target_ref` in the brief skips this question next time." Wait for the selection.
|
|
63
|
+
- **GATE [default: first candidate]**: under `{headless_mode}`, take the first candidate, log "headless: tag {tag} chosen from {candidates} for version {tag_resolution.requested}", and record the auto-decision per the Workflow Rules (step `extract`, gate `tag-choice`, decision `{tag}`): stage `{"step": "extract", "gate": "tag-choice", "decision": "{tag}", "rationale": "headless mode: first matching tag in priority order", "timestamp": "{ISO}"}` as `{run_dir}/decision.json` and run `uv run {emitEnvelopeHelper} record --workflow skf-create-skill --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"`.
|
|
64
|
+
|
|
65
|
+
Step 3 §2b then runs resolve again with the chosen tag (or `HEAD`) as `--target-ref`.
|
|
56
66
|
|
|
57
67
|
### Local Source Warning
|
|
58
68
|
|
|
@@ -68,133 +78,15 @@ Implicit resolution via `brief.version` is **not applied to local sources** —
|
|
|
68
78
|
|
|
69
79
|
## Remote Source Resolution
|
|
70
80
|
|
|
71
|
-
**Note:** Quick-tier remote sources
|
|
72
|
-
|
|
73
|
-
If `source_repo` is a local path: proceed with the tier-appropriate strategy as normal.
|
|
74
|
-
|
|
75
|
-
If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is Forge, Forge+, or Deep:
|
|
76
|
-
|
|
77
|
-
1. **Check `git` availability:** Verify `git` is functional (`git --version`). If `git` is not available, skip to the fallback warning below.
|
|
78
|
-
|
|
79
|
-
2. **Compute workspace path:** Derive a persistent local path from the remote URL:
|
|
80
|
-
|
|
81
|
-
- **Parse the URL** to extract `{host}`, `{owner}`, `{repo}`:
|
|
82
|
-
- `https://github.com/facebook/react` or `https://github.com/facebook/react.git` → `github.com/facebook/react`
|
|
83
|
-
- `git@github.com:facebook/react.git` → `github.com/facebook/react`
|
|
84
|
-
- `facebook/react` (owner/repo shorthand) → `github.com/facebook/react`
|
|
85
|
-
- **Resolve workspace root:** Use environment variable `SKF_WORKSPACE` if set, otherwise `~/.skf/workspace/` (where `~` is the user's home directory on all platforms)
|
|
86
|
-
- **Workspace repo path:** `{workspace_root}/repos/{host}/{owner}/{repo}/`
|
|
87
|
-
|
|
88
|
-
3. **Workspace check — resolve the source locally:**
|
|
89
|
-
|
|
90
|
-
**Concurrency guard:** all of the operations below (fetch, checkout, rev-parse, and the extraction read that follows in step 3) must be wrapped in an exclusive `flock` on `{workspace_repo_path}/.skf-workspace.lock`. Acquire the lock before the workspace-hit check, hold it across fetch + checkout + rev-parse, AND keep holding it through the extraction-time read of the working tree. Two concurrent batch runs that target the same workspace clone but different `source_ref` values would otherwise race — one would `checkout` while the other was reading files mid-extraction, corrupting the inventory. The lock makes the per-workspace-repo unit of work serial. Use `flock -x {lockfile} -c "..."` or `fcntl.flock(LOCK_EX)`. If `flock` is unavailable, log a warning ("Concurrency guard unavailable — concurrent forges against the same workspace repo may produce inconsistent extraction inventories") and proceed.
|
|
91
|
-
|
|
92
|
-
**If `{workspace_repo_path}/.git/` exists (workspace hit):**
|
|
93
|
-
|
|
94
|
-
The repo was previously cloned into the workspace. Fetch updates and checkout the requested ref.
|
|
95
|
-
|
|
96
|
-
**Detect tag vs branch for `source_ref`** (skipped when `source_ref` is `HEAD` — in that case fetch default branch without a ref argument):
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
# Ask the remote whether source_ref exists as a tag
|
|
100
|
-
git -C "{workspace_repo_path}" ls-remote --tags origin {source_ref} | grep -q "refs/tags/{source_ref}$" && ref_kind=tag || ref_kind=branch
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Fetch using the ref-kind-appropriate invocation so tag refs are written into `refs/tags/*` rather than being dropped by a branch-only fetch:
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
if ref_kind == tag:
|
|
107
|
-
git -C "{workspace_repo_path}" fetch origin tag {source_ref}
|
|
108
|
-
else:
|
|
109
|
-
git -C "{workspace_repo_path}" fetch origin {source_ref}
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Check if checkout is needed — skip if the requested ref is already checked out:
|
|
113
|
-
|
|
114
|
-
```
|
|
115
|
-
current_head = git -C "{workspace_repo_path}" rev-parse HEAD
|
|
116
|
-
fetched_head = git -C "{workspace_repo_path}" rev-parse FETCH_HEAD
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
If `current_head != fetched_head`:
|
|
120
|
-
```
|
|
121
|
-
git -C "{workspace_repo_path}" -c advice.detachedHead=false checkout FETCH_HEAD
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
If fetch or checkout fails, proceed to the **ephemeral fallback** (step 5).
|
|
125
|
-
|
|
126
|
-
**If `{workspace_repo_path}/.git/` does not exist (workspace miss):**
|
|
81
|
+
**Note:** Quick-tier remote sources are never read into a tree. Quick tier accesses remote files via the `gh_bridge.read_file` path described in step 3 section 4.
|
|
127
82
|
|
|
128
|
-
|
|
83
|
+
A remote source (a GitHub URL, an `owner/repo` shorthand or another git URL) read at Forge, Forge+ or Deep tier goes through one `resolve` call of `{sourceTreeHelper}` (step 3 §2b). It reads the commit Tag Resolution picks into a private tree of this run's own, which no other run can move, and with `--update-clone` moves SKF's workspace clone to the same commit in the same call, under the clone's `.skf-workspace.lock` and after running `{cccGitHygieneHelper}` there, never forcing a checkout (the `resolve` section of `skf-source-tree.py` has the details). The tree is removed with the helper's `close` subcommand at the end of step 7, or before any HALT after step 3 §2b.
|
|
129
84
|
|
|
130
|
-
|
|
131
|
-
mkdir -p "{workspace_root}/repos/{host}/{owner}/"
|
|
132
|
-
```
|
|
85
|
+
**Compute workspace path:** SKF's workspace clone of a repository is `{workspace_root}/repos/{host}/{owner}/{repo}/`, where `{workspace_root}` is the environment variable `SKF_WORKSPACE` when set, otherwise `~/.skf/workspace/` (where `~` is the user's home directory on all platforms). resolve prints it as `workspace_path`.
|
|
133
86
|
|
|
134
|
-
|
|
87
|
+
**Scope filtering:** the tree is a full checkout (no sparse-checkout), so apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`, `build.gradle.kts`, `Package.swift`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
|
|
135
88
|
|
|
136
|
-
|
|
137
|
-
# If source_ref is a real branch or tag (not HEAD/null):
|
|
138
|
-
git clone --depth 1 --branch {source_ref} "{source_repo}" "{workspace_repo_path}"
|
|
139
|
-
|
|
140
|
-
# If source_ref is HEAD or not set (default branch):
|
|
141
|
-
git clone --depth 1 "{source_repo}" "{workspace_repo_path}"
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
**Note:** No `--filter=blob:none` — blobs for the current tree are needed for indexing and the cost is amortized across all future forges. No sparse-checkout — a full checkout serves all consumers (different briefs with different include/exclude patterns) without configuration conflicts. `--single-branch` is reserved for ephemeral clones (step 5); workspace clones keep all branches available so re-forges against different refs can fetch + checkout without re-cloning.
|
|
145
|
-
|
|
146
|
-
If this is the **first repo** in the workspace (workspace root was just created), print an informational message:
|
|
147
|
-
|
|
148
|
-
"Caching source at `{workspace_repo_path}` (saves time on re-forges). Override location with `SKF_WORKSPACE` env var."
|
|
149
|
-
|
|
150
|
-
If clone fails, proceed to the **ephemeral fallback** (step 5).
|
|
151
|
-
|
|
152
|
-
4. **If workspace resolution succeeds:** Set `source_root = {workspace_repo_path}` — this updates the working source path for all subsequent operations (AST extraction, CCC indexing, artifact generation). Capture the source commit: `git -C "{workspace_repo_path}" rev-parse HEAD` — store as `source_commit` in context. Proceed with the **Forge/Deep Tier** extraction strategy below. Set context:
|
|
153
|
-
- `source_root = {workspace_repo_path}`
|
|
154
|
-
- `remote_clone_path = {workspace_repo_path}`
|
|
155
|
-
- `remote_clone_type = "workspace"`
|
|
156
|
-
|
|
157
|
-
**Scope filtering:** Since the workspace uses a full checkout (no sparse-checkout), apply `include_patterns` and `exclude_patterns` from the brief as **file-level filters** when building the extraction file list. Always-included root files (`pyproject.toml`, `package.json`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`, `build.gradle.kts`, `Package.swift`, `setup.py`, `setup.cfg`, `VERSION`) are exempt from pattern filtering.
|
|
158
|
-
|
|
159
|
-
5. **Ephemeral fallback (on any workspace failure):**
|
|
160
|
-
|
|
161
|
-
If workspace clone or fetch fails for any reason (network error, auth failure, disk full, timeout), fall back to ephemeral cloning — the pre-workspace behavior that always works:
|
|
162
|
-
|
|
163
|
-
```
|
|
164
|
-
temp_path = {system_temp}/skf-ephemeral-{skill-name}-{timestamp}/
|
|
165
|
-
|
|
166
|
-
# If source_ref is a real branch or tag (not HEAD/null):
|
|
167
|
-
git clone --depth 1 --branch {source_ref} --single-branch --filter=blob:none "{source_repo}" "{temp_path}"
|
|
168
|
-
|
|
169
|
-
# If source_ref is HEAD or not set (default branch):
|
|
170
|
-
git clone --depth 1 --single-branch --filter=blob:none "{source_repo}" "{temp_path}"
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
If ephemeral clone succeeds: Set `source_root = {temp_path}`. Capture `source_commit`. Set context:
|
|
174
|
-
- `source_root = {temp_path}`
|
|
175
|
-
- `remote_clone_path = {temp_path}`
|
|
176
|
-
- `remote_clone_type = "ephemeral"`
|
|
177
|
-
|
|
178
|
-
Apply `include_patterns` and `exclude_patterns` from the brief as file-level filters when building the extraction file list.
|
|
179
|
-
|
|
180
|
-
6. **If all cloning fails (workspace AND ephemeral):**
|
|
181
|
-
|
|
182
|
-
⚠️ **Warn the user explicitly:**
|
|
183
|
-
|
|
184
|
-
"Clone of `{source_repo}` failed: {error}. Degrading to source reading (T1-low) for this run. For T1 (AST-verified) confidence, clone the repository locally and update `source_repo` in your brief to the local path."
|
|
185
|
-
|
|
186
|
-
Proceed with Quick tier extraction strategy below. Note the degradation reason in context for the evidence report.
|
|
187
|
-
|
|
188
|
-
**Remote clone cleanup:** After extraction is complete for all files in scope (whether successful or partially failed), before presenting the Gate 2 summary (Section 6):
|
|
189
|
-
|
|
190
|
-
- **If `remote_clone_type == "ephemeral"`:** Cleanup is required.
|
|
191
|
-
1. **Reset working directory first:** Run `cd "{project-root}"` using the **absolute path** captured at workflow start.
|
|
192
|
-
2. **Delete the clone:** `rm -rf "{temp_path}"`
|
|
193
|
-
3. **Log:** "Ephemeral source clone cleaned up."
|
|
194
|
-
|
|
195
|
-
This ensures cleanup runs even if some extractions failed. If any error halts the step before Gate 2, cleanup must still occur.
|
|
196
|
-
|
|
197
|
-
- **If `remote_clone_type == "workspace"`:** No cleanup. The workspace checkout persists for future forges.
|
|
89
|
+
**When no tree can be read** (resolve prints `unavailable`, or does not finish), step 3 §2b warns the user and degrades this run to source reading (T1-low), with the Quick tier extraction strategy.
|
|
198
90
|
|
|
199
91
|
---
|
|
200
92
|
|
|
@@ -205,13 +97,15 @@ If `source_repo` is a remote URL (GitHub URL or owner/repo format) AND tier is F
|
|
|
205
97
|
After the source path is accessible, capture the current commit hash for provenance tracking:
|
|
206
98
|
|
|
207
99
|
- **Local path:** `git -C "{source_root}" rev-parse HEAD` — if the path is a git repo
|
|
208
|
-
- **
|
|
100
|
+
- **Remote source at Forge tier or above:** the `source_commit` resolve printed in step 3 §2b, the commit the tree holds
|
|
209
101
|
- **Quick tier (remote, no clone):** `gh api repos/{owner}/{repo}/commits/{source_ref} --jq '.sha'`
|
|
210
102
|
|
|
211
103
|
Store the result as `source_commit` in context. If capture fails (not a git repo, API unavailable), set `source_commit: null` — this is not an error.
|
|
212
104
|
|
|
213
105
|
Also store `source_ref` in context (from tag resolution above, or `HEAD` if no tag was resolved, or `"local"` for local sources). This value is persisted to metadata.json and provenance-map.json so downstream workflows (update-skill, audit-skill) can re-access the same source ref.
|
|
214
106
|
|
|
107
|
+
**The `source_root` metadata.json records** is `{resolved-source-path}` (`assets/skill-sections.md`): the local path for a local source; the remote URL for a remote source read without a tree (Quick tier, or a run degraded to source reading) or one whose workspace path holds a folder that is not SKF's clone; SKF's workspace clone (resolve's `clone`) for a remote source read from a private tree; null for a docs-only skill. Never the tree itself: step 7 removes it, while update-skill, test-skill and audit-skill read the skill's source from the workspace clone.
|
|
108
|
+
|
|
215
109
|
---
|
|
216
110
|
|
|
217
111
|
## Version Reconciliation (all tiers, source mode only)
|
|
@@ -220,7 +114,7 @@ Also store `source_ref` in context (from tag resolution above, or `HEAD` if no t
|
|
|
220
114
|
|
|
221
115
|
**If `source_type: "docs-only"`:** skip this section — no source files exist to reconcile.
|
|
222
116
|
|
|
223
|
-
After the source path is accessible (local path from step 1, or
|
|
117
|
+
After the source path is accessible (local path from step 1, or the private tree from above), check whether the source contains a version identifier and reconcile it with `brief.version`. Look for the first matching version file in the resolved source path:
|
|
224
118
|
|
|
225
119
|
- Python: `pyproject.toml` (`[project] version`), `setup.py` (`version=`), `__version__` in `__init__.py`
|
|
226
120
|
- JavaScript/TypeScript: `package.json` (`"version"`). **Monorepo resolution:** When multiple `package.json` files exist (workspace root + packages), resolve version using this priority:
|
|
@@ -2,11 +2,18 @@
|
|
|
2
2
|
nextStepFile: 'step-doc-rot.md'
|
|
3
3
|
# Resolve `{shardBodyHelper}` by probing `{shardBodyProbeOrder}` in order
|
|
4
4
|
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
5
|
-
# path wins. HALT
|
|
6
|
-
#
|
|
5
|
+
# path wins. HALT (exit code 3, helper-missing) if neither resolves: hand
|
|
6
|
+
# line-counting would silently ship an over-budget body or wrongly halt.
|
|
7
7
|
shardBodyProbeOrder:
|
|
8
8
|
- '{project-root}/_bmad/skf/shared/scripts/skf-shard-body.py'
|
|
9
9
|
- '{project-root}/src/shared/scripts/skf-shard-body.py'
|
|
10
|
+
# HARD HALT helpers (Rules).
|
|
11
|
+
sourceTreeProbeOrder:
|
|
12
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-source-tree.py'
|
|
13
|
+
- '{project-root}/src/shared/scripts/skf-source-tree.py'
|
|
14
|
+
emitEnvelopeProbeOrder:
|
|
15
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py'
|
|
16
|
+
- '{project-root}/src/shared/scripts/skf-emit-result-envelope.py'
|
|
10
17
|
---
|
|
11
18
|
|
|
12
19
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -26,14 +33,15 @@ Proactively reduce oversized SKILL.md bodies to under 400 lines by extracting Ti
|
|
|
26
33
|
- Do not modify frontmatter — only body content and references/ directory
|
|
27
34
|
- Do not invoke `npx skill-check split-body` — this step uses direct extraction
|
|
28
35
|
- Do not invoke the Description Guard Protocol — frontmatter is untouched
|
|
36
|
+
- A HARD HALT, once step 3 §2b has bound `{source_tree}`, first runs `uv run {sourceTreeHelper} close --tree "{source_tree}"` from `{project-root}` (resolved from `{sourceTreeProbeOrder}`) and goes on whatever it prints, and emits through `{emitEnvelopeHelper}`, resolved from `{emitEnvelopeProbeOrder}` when it is not bound. After its envelope, under `--batch` it ends only this brief: return to `references/batch-mode.md` §3, even when the halt reads as the end of the run.
|
|
29
37
|
|
|
30
38
|
## MANDATORY SEQUENCE
|
|
31
39
|
|
|
32
|
-
### §0. Run the Shard Script
|
|
40
|
+
### §0. Run the Shard Script
|
|
33
41
|
|
|
34
|
-
|
|
42
|
+
A script owns the counting, the section boundaries, the size sort, the file writes and the cross-reference blockquotes, on every run: do not count body lines or extract sections by hand.
|
|
35
43
|
|
|
36
|
-
**Resolve `{shardBodyHelper}`** from `{shardBodyProbeOrder}`; first existing path wins.
|
|
44
|
+
**Resolve `{shardBodyHelper}`** from `{shardBodyProbeOrder}`; first existing path wins. If no candidate exists, **HARD HALT** (exit code 3, `helper-missing`, phase `auto-shard`; stage `{run_dir}/halt.json` per the Workflow Rules and run `uv run {emitEnvelopeHelper} emit-halt --workflow skf-create-skill --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"`): "Cannot shard the body: skf-shard-body.py is missing. Re-install SKF, then re-run create-skill."
|
|
37
45
|
|
|
38
46
|
Run:
|
|
39
47
|
|
|
@@ -41,97 +49,16 @@ Run:
|
|
|
41
49
|
uv run {shardBodyHelper} <staging-skill-dir>/SKILL.md --budget 400
|
|
42
50
|
```
|
|
43
51
|
|
|
44
|
-
The script
|
|
52
|
+
The script counts the body between the frontmatter close and EOF. Over 400 lines, it extracts the Tier 2 sections, the ones whose heading starts `## Full` (`## Full API Reference` goes to `references/full-api-reference.md`, `## Full Type Definitions` to `references/full-type-definitions.md`, `## Full Integration Patterns` to `references/full-integration-patterns.md`), largest first, until the body fits. It writes the extracted files and the trimmed SKILL.md through the atomic-write helper, puts a cross-reference blockquote (`> See [Full API Reference](references/full-api-reference.md)`) in each extracted section's place, and checks that every Tier 1 section inline before is still inline (`tier1_preserved`, with any pulled heading in `tier1_missing`) and that each cross-reference resolves (`xref_ok`). Read its JSON and set context directly:
|
|
45
53
|
|
|
46
|
-
- **`action: "skip"`** → the body was already within budget. Log `"auto-shard: skipped (body {body_lines_before} lines)"`, set `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before`/`body_lines_after` from the report, then skip to §
|
|
54
|
+
- **`action: "skip"`** → the body was already within budget. Log `"auto-shard: skipped (body {body_lines_before} lines)"`, set `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before`/`body_lines_after` from the report, then skip to §1.
|
|
47
55
|
- **`action: "shard"`** → set `auto_shard_triggered: true` and copy `sections_extracted`, `body_lines_before`, `body_lines_after` straight from the report.
|
|
48
|
-
- **HALT**
|
|
49
|
-
- **HALT**
|
|
50
|
-
- If `under_budget` is false, selective Tier 2 extraction alone could not bring the body under budget (rare
|
|
56
|
+
- If `tier1_preserved` is false, **HARD HALT** (exit code 5, `tier1-not-preserved`, phase `auto-shard`; stage `{run_dir}/halt.json` per the Workflow Rules and run `uv run {emitEnvelopeHelper} emit-halt --workflow skf-create-skill --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"`): `"Auto-shard removed Tier 1 section(s) {tier1_missing}. Aborting."`
|
|
57
|
+
- If `xref_ok` is false, **HARD HALT** (exit code 5, `shard-xref-broken`, phase `auto-shard`; stage `{run_dir}/halt.json` per the Workflow Rules and run `uv run {emitEnvelopeHelper} emit-halt --workflow skf-create-skill --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"`): `"Auto-shard cross-references did not resolve. Aborting."`
|
|
58
|
+
- If `under_budget` is false, selective Tier 2 extraction alone could not bring the body under budget (rare: Tier 1 itself exceeds about 300 lines). Trim `## Key API Summary` and `## Architecture at a Glance` until the body fits the 400-line budget, never moving a Tier 1 section to `references/`, then run the script again and take `body_lines_after` from it.
|
|
51
59
|
|
|
52
|
-
Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`, then proceed to §
|
|
60
|
+
Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`, then proceed to §1.
|
|
53
61
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
### §1. Count Body Lines
|
|
57
|
-
|
|
58
|
-
The script counts all lines in the staging SKILL.md between the frontmatter closing `---` and EOF, excluding trailing blank lines, and reports the total as `body_lines_before`.
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
body_lines_before = body_line_count
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**IF `body_line_count` <= 400:** the script emits `action: "skip"` and writes nothing —
|
|
65
|
-
- Log: `"auto-shard: skipped (body {body_line_count} lines)"`
|
|
66
|
-
- Set context: `auto_shard_triggered: false`, `sections_extracted: []`, `body_lines_before: {body_line_count}`, `body_lines_after: {body_line_count}`
|
|
67
|
-
- Skip to §6 (Auto-Proceed)
|
|
68
|
-
|
|
69
|
-
**ELSE:** the script proceeds to §2.
|
|
70
|
-
|
|
71
|
-
### §2. Selective Shard — Tier 2 Extraction
|
|
72
|
-
|
|
73
|
-
The script identifies Tier 2 sections by their `## Full` heading prefix:
|
|
74
|
-
- `## Full API Reference` → `references/full-api-reference.md`
|
|
75
|
-
- `## Full Type Definitions` → `references/full-type-definitions.md`
|
|
76
|
-
- `## Full Integration Patterns` → `references/full-integration-patterns.md`
|
|
77
|
-
|
|
78
|
-
Sections are sorted by line count descending (largest first).
|
|
79
|
-
|
|
80
|
-
**FOR EACH Tier 2 section (largest first):**
|
|
81
|
-
|
|
82
|
-
1. Extract the full section content (from `## Full` heading to the next `##` heading or EOF)
|
|
83
|
-
2. Derive the reference filename from the heading: kebab-case (as shown above)
|
|
84
|
-
3. Write the extracted content (preserving the `##` heading) to `<staging-skill-dir>/references/{filename}` via the atomic-write helper
|
|
85
|
-
4. Replace the extracted section in SKILL.md with a cross-reference blockquote:
|
|
86
|
-
```markdown
|
|
87
|
-
> See [Full API Reference](references/full-api-reference.md)
|
|
88
|
-
```
|
|
89
|
-
5. Re-count body lines
|
|
90
|
-
6. **IF `body_line_count` <= 400:** stop extracting, proceed to §3
|
|
91
|
-
|
|
92
|
-
The report's `sections_extracted: [{heading, file, lines}]` records exactly which sections were pulled.
|
|
93
|
-
|
|
94
|
-
### §3. Tier 1 Preservation Check
|
|
95
|
-
|
|
96
|
-
The script verifies ALL Tier 1 sections that were inline before extraction remain inline in SKILL.md afterward. These headings:
|
|
97
|
-
|
|
98
|
-
- `## Overview`
|
|
99
|
-
- `## Quick Start`
|
|
100
|
-
- `## Common Workflows`
|
|
101
|
-
- `## Key API Summary` (or `## Component Catalog` for component-library scope)
|
|
102
|
-
- `## Migration & Deprecation Warnings` (conditional — only checked if it was present before extraction)
|
|
103
|
-
- `## Key Types`
|
|
104
|
-
- `## Architecture at a Glance`
|
|
105
|
-
- `## CLI` (conditional — only checked if present before extraction)
|
|
106
|
-
- `## Scripts & Assets` (conditional — only checked if present before extraction)
|
|
107
|
-
- `## Manual Sections` (conditional — only checked if present before extraction)
|
|
108
|
-
|
|
109
|
-
The result surfaces as `tier1_preserved` (with any pulled headings in `tier1_missing`).
|
|
110
|
-
|
|
111
|
-
**IF `tier1_preserved` is false:**
|
|
112
|
-
HALT: `"Auto-shard removed Tier 1 section {name}. Aborting."`
|
|
113
|
-
|
|
114
|
-
### §4. Post-Shard Validation
|
|
115
|
-
|
|
116
|
-
The report's `body_lines_after` is the recount after all extraction. `under_budget` is true when the body now fits.
|
|
117
|
-
|
|
118
|
-
**IF `under_budget` is false** (body still > 400 after all Tier 2 sections extracted — this is the one genuine editing-judgment step):
|
|
119
|
-
- Trim oversized Tier 1 sections: reduce `## Key API Summary` and `## Architecture at a Glance` content to fit within the 400-line budget
|
|
120
|
-
- Do not move any Tier 1 section to references/
|
|
121
|
-
- Re-run `{shardBodyHelper}` (or re-count) and update `body_lines_after`
|
|
122
|
-
|
|
123
|
-
### §5. Cross-Reference Integrity
|
|
124
|
-
|
|
125
|
-
The script verifies, for each extracted reference file, that the file exists at `<staging-skill-dir>/references/{filename}` and that the cross-reference blockquote in SKILL.md links to it — reported as `xref_ok`. HALT if `xref_ok` is false.
|
|
126
|
-
|
|
127
|
-
Log: `"auto-shard: {N} sections extracted, body reduced from {body_lines_before} to {body_lines_after} lines"`
|
|
128
|
-
|
|
129
|
-
Set context:
|
|
130
|
-
- `auto_shard_triggered: true`
|
|
131
|
-
- `sections_extracted: [{heading names}]`
|
|
132
|
-
- `body_lines_before: {before}`
|
|
133
|
-
- `body_lines_after: {after}`
|
|
134
|
-
|
|
135
|
-
### §6. Auto-Proceed
|
|
62
|
+
### §1. Auto-Proceed
|
|
136
63
|
|
|
137
64
|
Load, read the entire file, then execute `{nextStepFile}`.
|