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,9 +1,15 @@
|
|
|
1
1
|
---
|
|
2
2
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
3
|
-
schemaFile: '
|
|
3
|
+
schemaFile: 'assets/skill-brief-schema.md'
|
|
4
|
+
writeSkillBriefProbeOrder:
|
|
5
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-write-skill-brief.py'
|
|
6
|
+
- '{project-root}/src/shared/scripts/skf-write-skill-brief.py'
|
|
4
7
|
validateBriefSchemaProbeOrder:
|
|
5
8
|
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-brief-schema.py'
|
|
6
9
|
- '{project-root}/src/shared/scripts/skf-validate-brief-schema.py'
|
|
10
|
+
scanManifestsProbeOrder:
|
|
11
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
|
|
12
|
+
- '{project-root}/src/shared/scripts/skf-scan-manifests.py'
|
|
7
13
|
nextStepFile: 'health-check.md'
|
|
8
14
|
---
|
|
9
15
|
|
|
@@ -13,71 +19,112 @@ nextStepFile: 'health-check.md'
|
|
|
13
19
|
|
|
14
20
|
## STEP GOAL:
|
|
15
21
|
|
|
16
|
-
To
|
|
22
|
+
To write a valid skill-brief.yaml for each confirmed unit through the brief writer, append the generation results to the analysis report, recommend the next workflow for each unit and end the run with its result files and envelope, completing the analyze-source workflow (also when no unit was confirmed).
|
|
17
23
|
|
|
18
24
|
## Rules
|
|
19
25
|
|
|
20
26
|
- Generate only for units in confirmed_units — no extras, no omissions
|
|
21
|
-
- Do not
|
|
27
|
+
- Do not revisit the per-unit decisions of step 5: the §4 preview confirms only the write
|
|
22
28
|
- Every generated field must trace back to data collected in steps 02-05
|
|
29
|
+
- Briefs are written only by the brief writer, from a context file: never render or hand-edit brief YAML
|
|
23
30
|
- Chains to the local health-check step via `{nextStepFile}` after completion — the user-facing summary is not the terminal step
|
|
24
31
|
|
|
25
32
|
## MANDATORY SEQUENCE
|
|
26
33
|
|
|
34
|
+
Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one and the envelope fields the site names, then run
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
|
|
41
|
+
|
|
27
42
|
### 1. Load Context
|
|
28
43
|
|
|
29
44
|
Read {outputFile} completely to obtain:
|
|
30
45
|
- `confirmed_units` from frontmatter (names of units approved in step 05)
|
|
31
|
-
- `
|
|
32
|
-
-
|
|
46
|
+
- `confirmed_composites` from frontmatter (composites approved in step 04, each with its constituents' names and paths)
|
|
47
|
+
- `project_paths`, `refs`, `forge_tier`, `user_name`, `forge_data_folder` from frontmatter
|
|
48
|
+
- Recommendation cards from "## Recommendations" section (proposed brief fields and the project path of each unit)
|
|
33
49
|
- Export map and integration data from prior sections
|
|
34
50
|
|
|
35
51
|
Load {schemaFile} for validation reference.
|
|
36
52
|
|
|
37
|
-
**
|
|
53
|
+
**No confirmed unit:** If `confirmed_units` is empty, present:
|
|
38
54
|
"**No confirmed units to generate briefs for.** The analysis is complete with no skill briefs produced. Run analyze-source again with different scope or parameters if needed."
|
|
39
|
-
|
|
55
|
+
The run still ends through the same sequence as one that wrote briefs: skip §2 to §6 and continue at §7, which appends the Generation Results with no brief and adds `generate-briefs` to `stepsCompleted` (so a re-run starts a fresh analysis instead of resuming into this guard), then §8, §9 (an envelope and result contract with `brief_paths: []` and `unit_counts.confirmed: 0`), §9b and §10.
|
|
56
|
+
|
|
57
|
+
### 2. Build Each Brief's Context
|
|
40
58
|
|
|
41
|
-
|
|
59
|
+
**Resolve `{writeSkillBriefHelper}`** from `{writeSkillBriefProbeOrder}` and **`{validateBriefSchemaHelper}`** from `{validateBriefSchemaProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `generate-briefs:2`): "`{the missing script}` is missing. Re-install SKF."
|
|
42
60
|
|
|
43
|
-
For each unit in `confirmed_units`,
|
|
61
|
+
The brief writer renders, checks and writes each brief, and applies the version precedence (`target_version`, then `detected_version`, then `1.0.0`): this step supplies the values. For each unit in `confirmed_units`, take them from:
|
|
44
62
|
|
|
45
63
|
**Field mapping:**
|
|
46
64
|
|
|
47
65
|
| Field | Source |
|
|
48
66
|
|-------|--------|
|
|
49
|
-
| name | Confirmed name from step 05 recommendation card |
|
|
50
|
-
| version |
|
|
51
|
-
| source_repo | `
|
|
67
|
+
| name | Confirmed name from step 05 recommendation card: the name identify-units Step C derived, unless step 5 renamed the unit |
|
|
68
|
+
| version | Not set here: `detected_version` comes by {schemaFile}'s **Version Detection**, for the unit's own manifest in its project path's manifest scan, `{run_dir}/manifests-{i}.json` (scan-project and discover-additional-source write it). When that file is missing, as in a session that resumed the report, run `uv run {scanManifestsHelper} scan "{scan_root}" > "{run_dir}/manifests-{i}.json"` first, `{scanManifestsHelper}` the first existing path of `{scanManifestsProbeOrder}` |
|
|
69
|
+
| source_repo | The unit's project path, the `project_paths[]` entry it was found under (a composite's constituents share one) |
|
|
70
|
+
| target_ref | The unit's ref: its project path's entry in `refs`, else null. Never a version: `target_version` stays null |
|
|
52
71
|
| language | Language the skill **documents** (primary language detected in step 03). For a language / spec reference this is the *documented* language, which may differ from the source language it is extracted from — e.g. a SurrealQL reference extracted from a Rust engine records `surrealql`, not `rust` (see {schemaFile} "Documented vs source language") |
|
|
53
72
|
| scope.type | Scope type from step 05 recommendation card |
|
|
54
|
-
| scope.include | Include patterns from step 05 recommendation card |
|
|
73
|
+
| scope.include | Include patterns from step 05 recommendation card, plus, for a composite (`Boundary: Composite` on its card), `<path>/**` for every constituent path of its `confirmed_composites` entry (such as `crates/animato-core/**`), so the brief spans every constituent. Find the entry by those paths, which the card's Path lists, not by name: step 05 may rename the unit |
|
|
55
74
|
| scope.exclude | Inferred from heuristics (test files, generated code) |
|
|
56
75
|
| scope.tier_a_include | Optional — narrower tier-A surface for stratified-scope monorepos and `reference-app` pattern surfaces; usually left to skf-brief-skill to refine |
|
|
57
76
|
| scope.notes | Rationale from step 05 recommendation card |
|
|
58
77
|
| description | Description from step 05 recommendation card |
|
|
59
78
|
| forge_tier | `{forge_tier}` from frontmatter |
|
|
60
|
-
| created | Current date
|
|
79
|
+
| created | Current date, `YYYY-MM-DD` |
|
|
61
80
|
| created_by | `{user_name}` from frontmatter |
|
|
62
81
|
|
|
82
|
+
Write each unit's context as `{run_dir}/brief-{unit-name}.json`, a file and never an echo'd string:
|
|
83
|
+
|
|
84
|
+
```json
|
|
85
|
+
{
|
|
86
|
+
"name": "{unit-name}",
|
|
87
|
+
"target_version": null,
|
|
88
|
+
"target_ref": "{the unit's ref, or null}",
|
|
89
|
+
"detected_version": "{version, or null}",
|
|
90
|
+
"source_type": "source",
|
|
91
|
+
"source_repo": "{source_repo}",
|
|
92
|
+
"language": "{language}",
|
|
93
|
+
"description": "{description}",
|
|
94
|
+
"forge_tier": "{forge_tier}",
|
|
95
|
+
"created": "{current_date}",
|
|
96
|
+
"created_by": "{user_name}",
|
|
97
|
+
"scope_type": "{scope.type}",
|
|
98
|
+
"scope_include": ["{scope.include}"],
|
|
99
|
+
"scope_exclude": ["{scope.exclude}"],
|
|
100
|
+
"scope_notes": "{scope.notes}",
|
|
101
|
+
"scope_rationale": null,
|
|
102
|
+
"scope_tier_a_include": null,
|
|
103
|
+
"scope_amendments": null,
|
|
104
|
+
"scope_registry_path": null,
|
|
105
|
+
"scope_ui_variants": null,
|
|
106
|
+
"scope_demo_patterns": null,
|
|
107
|
+
"doc_urls": null,
|
|
108
|
+
"scripts_intent": null,
|
|
109
|
+
"assets_intent": null,
|
|
110
|
+
"source_authority": null,
|
|
111
|
+
"source_ref": null
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
63
115
|
### 3. Validate Each Brief
|
|
64
116
|
|
|
65
|
-
Validation has two parts: a **deterministic
|
|
117
|
+
Validation has two parts: a **deterministic gate** (authoritative for structure) and **semantic cross-checks** the schema cannot express. Run the gate first.
|
|
66
118
|
|
|
67
|
-
**3a. Deterministic
|
|
119
|
+
**3a. Deterministic gate.** Render each brief into the run folder, then run on it the schema check `skf-brief-skill` runs when it reads a brief, so a brief that passes here is not rejected there for structural reasons:
|
|
68
120
|
|
|
69
121
|
```bash
|
|
70
|
-
uv run {
|
|
71
|
-
{
|
|
72
|
-
YAML
|
|
122
|
+
uv run {writeSkillBriefHelper} write --target "{run_dir}/briefs/{unit-name}/skill-brief.yaml" --from-flat < "{run_dir}/brief-{unit-name}.json"
|
|
123
|
+
uv run {validateBriefSchemaHelper} "{run_dir}/briefs/{unit-name}/skill-brief.yaml"
|
|
73
124
|
```
|
|
74
125
|
|
|
75
|
-
The
|
|
76
|
-
|
|
77
|
-
- **`valid: false`** — the `errors[]` name the offending field (e.g. a `description` mis-indented under `scope:`, which leaves the required top-level `description` absent). Repair the assembled YAML and re-run the helper until `valid: true`. A brief is written only after it passes this gate.
|
|
78
|
-
- **`valid: true`** — carry any non-empty `warnings[]` into the §4 preview, then proceed.
|
|
79
|
-
|
|
80
|
-
This catches structural YAML errors where they are created, rather than letting them surface downstream as a HALT in `skf-brief-skill`'s ratify path.
|
|
126
|
+
- **The writer exits non-zero, or the validator answers `valid: false`:** the `message` and `field` of the writer's stderr JSON, or the validator's `errors[]`, name the offending field. Correct that value in `{run_dir}/brief-{unit-name}.json` when it is a value you mistyped from the recommendation card, and run both commands again; a value the user must decide is presented in §4 for correction (`M`). In headless mode a brief still rejected after one correction is a HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:3`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5): "The brief for {unit-name} was rejected: {the message}." A brief is written only after it passes this gate.
|
|
127
|
+
- **Both pass:** carry the writer's and the validator's non-empty `warnings` into the §4 preview, then proceed.
|
|
81
128
|
|
|
82
129
|
**3b. Semantic cross-checks** (not expressible in the JSON schema — apply in addition to 3a):
|
|
83
130
|
|
|
@@ -90,7 +137,8 @@ This catches structural YAML errors where they are created, rather than letting
|
|
|
90
137
|
|
|
91
138
|
**If any check fails:**
|
|
92
139
|
- Document the failure with specific field and reason
|
|
93
|
-
-
|
|
140
|
+
- Correct the context (3a) or present to user for correction (3b semantic issues) before writing: an invalid brief is not written
|
|
141
|
+
- In headless mode no one corrects it: correct what the recommendation card and the report settle and check again, once; a brief still failing a 3b check is a HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:3`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5), as in 3a: "The brief for {unit-name} failed the {check} check: {the reason}."
|
|
94
142
|
|
|
95
143
|
### 4. Present Generation Preview
|
|
96
144
|
|
|
@@ -100,9 +148,9 @@ This catches structural YAML errors where they are created, rather than letting
|
|
|
100
148
|
|
|
101
149
|
{For each unit:}
|
|
102
150
|
---
|
|
103
|
-
**{unit-name}** → `{forge_data_folder}/{unit-name}/skill-brief.yaml`
|
|
151
|
+
**{unit-name}** → `{forge_data_folder}/{unit-name}/skill-brief.yaml`{, replacing the earlier brief there when the unit is in `existing_briefs`}
|
|
104
152
|
```yaml
|
|
105
|
-
{
|
|
153
|
+
{the content of {run_dir}/briefs/{unit-name}/skill-brief.yaml, as the writer rendered it}
|
|
106
154
|
```
|
|
107
155
|
---
|
|
108
156
|
|
|
@@ -113,20 +161,29 @@ This catches structural YAML errors where they are created, rather than letting
|
|
|
113
161
|
|
|
114
162
|
Wait for explicit user confirmation before writing files.
|
|
115
163
|
|
|
116
|
-
**GATE [default: Y]
|
|
164
|
+
**GATE [default: Y]**: if `{headless_mode}` is true, auto-confirm [Y] and write all briefs, and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "generate-briefs.write", "default_action": "Y", "taken_action": "Y", "reason": "headless: auto-write {count} briefs", "evidence": {"briefs": [<each unit name>]}}`, then run
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
If the command fails, go on: only that entry is lost. Do not stall at this gate: it is the deliverable-producing step of a headless or pipeline run.
|
|
117
171
|
|
|
118
172
|
### 5. Write Files
|
|
119
173
|
|
|
120
174
|
**IF user confirms (Y):**
|
|
121
175
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
176
|
+
Write each brief to its place from the context that passed §3 (the writer renders the same bytes the preview showed, creates the folder and writes atomically):
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
uv run {writeSkillBriefHelper} write --target "{forge_data_folder}/{unit-name}/skill-brief.yaml" --from-flat < "{run_dir}/brief-{unit-name}.json"
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Keep each `brief_path` it prints for §9. If it exits non-zero, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:5`, path `{forge_data_folder}/{unit-name}/skill-brief.yaml`, with `unit_counts` from step 5 and the `brief_paths` written so far): "The brief for {unit-name} could not be written: {its `message`}."
|
|
126
183
|
|
|
127
184
|
**IF user modifies (M):**
|
|
128
185
|
- Ask which brief and what to change
|
|
129
|
-
- Update the
|
|
186
|
+
- Update `{run_dir}/brief-{unit-name}.json`, run the §3 gate again, present again
|
|
130
187
|
- Return to confirmation prompt
|
|
131
188
|
|
|
132
189
|
**IF user skips writing (N):**
|
|
@@ -134,7 +191,7 @@ For each confirmed brief:
|
|
|
134
191
|
- Skip file writing, proceed to report update
|
|
135
192
|
|
|
136
193
|
**IF user cancels (X):**
|
|
137
|
-
- HARD HALT
|
|
194
|
+
- HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `generate-briefs:4`), with `brief_paths: []` and `unit_counts` reflecting the confirmed/skipped/maybe state from step 5 in its payload: "Cancelled before any brief was written."
|
|
138
195
|
|
|
139
196
|
### 6. Determine Next Workflow Per Unit
|
|
140
197
|
|
|
@@ -204,41 +261,50 @@ nextWorkflow: '{primary recommendation}'
|
|
|
204
261
|
|
|
205
262
|
To refine any brief, run the recommended next workflow. To re-analyze with different scope, run analyze-source again."
|
|
206
263
|
|
|
207
|
-
### 9.
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
264
|
+
### 9. End the Run
|
|
265
|
+
|
|
266
|
+
The shared emitter writes the result files and prints the envelope; this section stages their content, in every mode. Write `{run_dir}/result-context.json`:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"status": "success",
|
|
271
|
+
"report_path": "{outputFile as an absolute path}",
|
|
272
|
+
"brief_paths": ["{the brief_path of each brief §5 wrote}"],
|
|
273
|
+
"unit_counts": {"confirmed": <confirmed count from step 5>, "skipped": <rejected count from step 5>, "maybe": 0},
|
|
274
|
+
"mode": "interactive",
|
|
275
|
+
"result_contract": {
|
|
276
|
+
"skill": "skf-analyze-source",
|
|
277
|
+
"status": "success",
|
|
278
|
+
"outputs": [{"type": "report", "path": "{outputFile as an absolute path}"}, {"type": "brief", "path": "{each brief_path}"}],
|
|
279
|
+
"summary": {"mode": "interactive", "brief_count": <briefs written>, "confirmed_units": <confirmed count>, "stack_skill_candidates": <count>, "next_workflow": "{primary recommendation}"}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
212
283
|
|
|
213
|
-
|
|
284
|
+
`brief_paths` is empty, and so is the brief part of `outputs`, when no unit was confirmed or the user skipped writing with [N]. Then run:
|
|
214
285
|
|
|
286
|
+
```bash
|
|
287
|
+
uv run {emitEnvelopeHelper} emit --workflow skf-analyze-source --run-dir "{run_dir}" --result-dir "{forge_data_folder}" < "{run_dir}/result-context.json"
|
|
215
288
|
```
|
|
216
|
-
SKF_ANALYZE_RESULT_JSON: {"status":"success","report_path":"{outputFile_abs_path}","brief_paths":["{brief_path_1}",…,"{brief_path_N}"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive"}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
- `report_path` — absolute path to {outputFile}.
|
|
220
|
-
- `brief_paths` — every `skill-brief.yaml` written in §5 (empty array when the user skipped writing with [N]).
|
|
221
|
-
- `unit_counts` — confirmed/skipped counts from step 5 (`maybe` reserved; see `references/headless-contract.md`).
|
|
222
289
|
|
|
223
|
-
|
|
290
|
+
The emitter stamps the UTC time and the run id into the record, writes `{forge_data_folder}/analyze-source-result-{YYYYMMDD-HHmmss}.json` and its `analyze-source-result-latest.json` copy (the stable path pipeline consumers read), and prints the `SKF_ANALYZE_RESULT_JSON:` line on stdout (field rules in `references/headless-contract.md`). When `{headless_mode}` is true, display the line verbatim: it is the success signal of a headless run. A result file that could not be written leaves the line's `result_path` null and a `result_file_write_failed` warning in it, and the run still finishes. If the emitter exits non-zero, correct `result-context.json` from the message on its stderr and run it once more; if it fails again, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `generate-briefs:9`, path `{forge_data_folder}`, with `brief_paths` and `unit_counts` from the payload): "The result contract could not be written: {its message}."
|
|
224
291
|
|
|
225
292
|
### 9b. On-Complete Hook (pipeline integration)
|
|
226
293
|
|
|
227
|
-
If `{onCompleteCommand}` is non-empty, invoke it now
|
|
294
|
+
If `{onCompleteCommand}` is non-empty and the §9 line's `result_path` is not null, invoke it now, after the emitter wrote the timestamped result JSON and its `analyze-source-result-latest.json` copy:
|
|
228
295
|
|
|
229
296
|
```
|
|
230
|
-
{onCompleteCommand} --result-path={
|
|
297
|
+
{onCompleteCommand} --result-path={forge_data_folder}/analyze-source-result-latest.json
|
|
231
298
|
```
|
|
232
299
|
|
|
233
|
-
|
|
300
|
+
The stable `-latest` path is preferred over the timestamped copy so downstream consumers don't need to discover the timestamp.
|
|
234
301
|
|
|
235
|
-
- On success:
|
|
236
|
-
- On non-zero exit / process error:
|
|
302
|
+
- On success: display the hook's stderr, if it wrote any, as information (`on_complete hook stderr: …`).
|
|
303
|
+
- On non-zero exit / process error: display the hook failure (`on_complete hook failed (exit {code}): {stderr_snippet}`); it never fails the run.
|
|
237
304
|
- **Never fail the workflow on hook errors** — the hook is for pipeline integration (Slack, dashboards, CI), not for gating skill-brief production.
|
|
238
305
|
|
|
239
306
|
If `{onCompleteCommand}` is empty, skip this section entirely (default behavior — no hook configured).
|
|
240
307
|
|
|
241
308
|
### 10. Chain to Health Check
|
|
242
309
|
|
|
243
|
-
After the briefs are written (or skipped
|
|
244
|
-
|
|
310
|
+
After the briefs are written (or skipped, or none was confirmed), the report updated, the summary presented, the run ended in §9 and the on-complete hook invoked (or skipped per empty `{onCompleteCommand}`), delete the run folder, whose payloads the emitter has read: `rm -rf "{run_dir}"`. Then load, read the full file, and execute `{nextStepFile}`. The health-check step is the true terminal step: continue past the summary even though it reads as final.
|
|
@@ -1,24 +1,51 @@
|
|
|
1
1
|
# Headless Result Contract & Exit Codes
|
|
2
2
|
|
|
3
|
-
Canonical headless/pipeline contract for skf-analyze-source.
|
|
3
|
+
Canonical headless/pipeline contract for skf-analyze-source. The shared emitter, `shared/scripts/skf-emit-result-envelope.py` (`{emitEnvelopeHelper}`, bound at SKILL.md On Activation §1), builds every line from the payload a step stages in `{run_dir}` and checks it against `shared/scripts/schemas/skf-analyze-result-envelope.v1.json`, so no step types an envelope.
|
|
4
4
|
|
|
5
5
|
## Result Envelope
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
The step that ends a run (step 6 §9, step 1a §9, or the docs-only branch §5) prints the envelope on **stdout** before chaining to step 7, and displays it when `{headless_mode}` is true. Every HARD HALT of a headless run prints it on **stderr** with `status: "error"`, so an automator branches on the failure class without grepping message text.
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
SKF_ANALYZE_RESULT_JSON: {"status":"success|error|redirect|skipped","report_path":"…|null","brief_paths":["…"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive|auto"}
|
|
10
|
+
SKF_ANALYZE_RESULT_JSON: {"status":"success|error|redirect|skipped","report_path":"…|null","brief_paths":["…"],"unit_counts":{"confirmed":N,"skipped":N,"maybe":N},"exit_code":0,"halt_reason":null,"mode":"interactive|auto","result_path":"…|null"}
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
- `status
|
|
14
|
-
- `halt_reason`
|
|
15
|
-
- `exit_code`
|
|
16
|
-
- `report_path
|
|
17
|
-
- `brief_paths
|
|
13
|
+
- `status`: `"success"` when the run ends, also with zero confirmed units (`brief_paths: []`, `unit_counts.confirmed: 0`); `"error"` on any HALT; `"redirect"` when coexistence routes to US (merge); `"skipped"` when the user skips a conflicting target.
|
|
14
|
+
- `halt_reason`: `null` unless the run halted, else one of `"input-missing"`, `"resolution-failure"`, `"pin-invalid"`, `"write-failed"`, `"user-cancelled"`. A brief the writer or the brief schema gate rejects halts with `"write-failed"`.
|
|
15
|
+
- `exit_code`: the emitter derives it from `halt_reason`, per the table below.
|
|
16
|
+
- `report_path`: absolute path to the analysis report, or `null` on a redirect, a skip and an early HALT.
|
|
17
|
+
- `brief_paths`: absolute path of every `skill-brief.yaml` the run wrote (empty array if none). A brief is written only after it passed the brief writer and, outside the docs-only branch, the schema gate.
|
|
18
18
|
- `unit_counts` — `confirmed` (units approved for briefs) and `skipped` (rejected in step 5, or the skipped target in coexistence §0c) counts; auto mode reports `confirmed:N, skipped:0`. `maybe` is a reserved slot, currently always `0`.
|
|
19
|
-
- `mode
|
|
19
|
+
- `mode`: `"auto"` when the invocation carries `[auto]`, from activation through step 1a and the docs-only branch; `"interactive"` otherwise, also in the step-by-step chain an `[auto]` run falls back to (step 1a §3, exit 1).
|
|
20
|
+
- `result_path`: the per-run result file the emitter wrote, stamped by it; `null` for a HALT, which writes no result file, and when the write failed (a `result_file_write_failed` warning then says why).
|
|
21
|
+
- `error`: on a HALT only, `{"phase", "reason"}` plus `path` when the halt names one.
|
|
22
|
+
- `headless_decisions`: present when the run recorded an auto-decision: step 1a's §3b merge-or-split decision (gate `auto-scope.cohesion`), its §4 choices of shape for a repository on a framework or a parser library (gate `auto-scope.shape`) and its §5 choice of the documented language (gate `auto-scope.language`), and each gate default a headless run of the step-by-step chain took: `scan-project.scan`, `identify-units.classifications`, `map-and-detect.findings` (with the composite merges it accepted), `recommend.recommendations` and `generate-briefs.write`.
|
|
23
|
+
- `warnings`: present when the run recorded at least one.
|
|
20
24
|
|
|
21
|
-
In auto mode the envelope also carries `coexistence` (the §0c decision) and, when a pin resolves, `pinned_ref`/`pinned_version
|
|
25
|
+
In auto mode the envelope also carries `coexistence` (the §0c decision) and, when a pin resolves, `pinned_ref`/`pinned_version`; `step-auto-scope.md` §0b/§0c define those field semantics. A redirect adds `redirect_to`, `skill_name` and `skill_path`, a skip `skipped_reason`, and the docs-only path `source_type: "docs-only"`.
|
|
26
|
+
|
|
27
|
+
## Ending a Run
|
|
28
|
+
|
|
29
|
+
The step that ends the run stages `{run_dir}/result-context.json` with the envelope fields it knows and a `result_contract` object, the record the result files hold (`skill`, `status`, `outputs`, `summary`, per `shared/references/output-contract-schema.md`), and runs the emitter in every mode:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
uv run {emitEnvelopeHelper} emit --workflow skf-analyze-source --run-dir "{run_dir}" --result-dir "{forge_data_folder}" < "{run_dir}/result-context.json"
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The emitter stamps the UTC time, the run id, the decisions and warnings the run recorded into the record, writes `{forge_data_folder}/analyze-source-result-{YYYYMMDD-HHmmss}.json` and its `analyze-source-result-latest.json` copy, and prints the line. A result file that could not be written leaves `result_path` null and a `result_file_write_failed` warning in the line, and the run still finishes. If the emitter exits non-zero, the step corrects the payload from the message on its stderr and runs it once more; if it fails again, it HARD HALTs with exit code 4 (`write-failed`). Then `{onCompleteCommand}` runs, when it is set and `result_path` is not null, with `--result-path={forge_data_folder}/analyze-source-result-latest.json`; a hook failure is displayed and never fails the run. Last, the step deletes `{run_dir}` and chains to step 7.
|
|
36
|
+
|
|
37
|
+
## Halt Envelope
|
|
38
|
+
|
|
39
|
+
Every HARD HALT names its exit code, `halt_reason` and phase where it stops. In headless mode it prints its envelope before it stops: it stages `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "<auto or interactive>"}`, plus `"path"` when the halt names one, runs the first command below and displays the line it prints verbatim. A halt before SKILL.md On Activation §5 created `{run_dir}` hands that payload, on one line, to the second command. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. The emitter gives every field the payload leaves out its default (`null`, `[]`, zero counts, `"interactive"`) and derives `exit_code` from `halt_reason`. When the helper is missing, exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing. A halt writes no result file and keeps `{run_dir}`.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
43
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --target stderr <<'SKF_ANALYZE_HALT'
|
|
44
|
+
{"phase": "on-activation:config", "reason": "<the halt message>", "halt_reason": "input-missing", "mode": "interactive"}
|
|
45
|
+
SKF_ANALYZE_HALT
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Each step file states this rule in its own opening, so the HALTs of a step never depend on this file.
|
|
22
49
|
|
|
23
50
|
## Exit Codes
|
|
24
51
|
|
|
@@ -26,8 +53,8 @@ Every HARD HALT exits with a stable code so headless automators can branch on th
|
|
|
26
53
|
|
|
27
54
|
| Code | Meaning | Raised by |
|
|
28
55
|
| ---- | -------------------- | ------------------------------------------------------------------------------------------ |
|
|
29
|
-
| 0 | success / skipped / redirect | step
|
|
30
|
-
| 2 | input-missing | On Activation (config.yaml not loadable); step 1 §3 (project path
|
|
31
|
-
| 3 | resolution-failure | step 1 §2 (`forge-tier.yaml` missing at `{sidecar_path}/forge-tier.yaml`); step 1 §
|
|
32
|
-
| 4 | write-failed | a failed write of the analysis report (step 1 §6 / step 1a §7 / §
|
|
33
|
-
| 6 | user-cancelled | any interactive menu in steps 2/3/5/6 (user selected `[X]` Cancel and exit) |
|
|
56
|
+
| 0 | success / skipped / redirect | the step that ends the run: step 6 §9 (briefs written, or none when no unit was confirmed), step 1a §9, docs-only §5; coexistence `"skipped"`/`"redirect"` statuses from §0c |
|
|
57
|
+
| 2 | input-missing | On Activation §2 (config.yaml not loadable); step 1 §2b (auto mode without `--project-path`); step 1 §3 (no project path in headless mode); step 1 §4 (`--target-refs` given with `--target-ref`, or a `--target-refs` key that matches no project path) |
|
|
58
|
+
| 3 | resolution-failure | step 1 §2 (`forge-tier.yaml` missing at `{sidecar_path}/forge-tier.yaml`); step 1 §2b and §4 (project path does not exist or remote URL inaccessible, headless); step 1a §0 (a documentation URL that git reads as a repository, which on most hosts is the repository's main page, one whose server asks for credentials, or one that gives git no answer in 20 s: rerun with its `.git` clone URL, its address without https:// or its SSH address, or a documentation URL that answers; a repository browser page git cannot read at that address, such as a Bitbucket Data Center `/projects/<p>/repos/<r>` page, a SourceForge or Launchpad code page or a link to a file or folder inside a repository, is still read as documentation, so give its clone URL); step 1a §0a (docs-only URL unreachable); step 1a §0b (`halt_reason: "pin-invalid"` when the supplied `--pin` matches no tag or branch, `resolution-failure` when the pin helper fails); step 1a §2 (a remote path cannot be fetched, another path halts as in §0, or the target's files cannot be listed); step 1a §3 (shape detection script error, exit code 2); step 2 §2 (a project path cannot be fetched at its ref); step 3 §1 and step 4 §1 (a scan root a resumed session makes again cannot be fetched); a shared helper script found at none of its probe paths (On Activation §1; step 1 §5; step 1a §0, §0b, §2, §3, §5 and §8, and its split branch; docs-only §2 and §4; step 2 §2; step 3 §2 and §4; step 4 §2, §3 and §5, and the [D] discover file of steps 4 and 5; step 6 §2) |
|
|
59
|
+
| 4 | write-failed | On Activation §5 (the run folder cannot be created); step 1 §1 (an earlier report cannot be archived); a failed write of the analysis report (step 1 §6 / step 1a §7 / docs-only §3); a brief the writer or the schema gate rejects, or a brief write that fails (step 6 §3 and §5 / step 1a §8 / docs-only §4), and a brief that still fails a semantic check of step 6 §3 in headless mode; the emitter failing twice when the run ends (step 6 §9 / step 1a §9 / docs-only §5) |
|
|
60
|
+
| 6 | user-cancelled | any interactive menu in steps 2/3/4/5/6 (user selected `[X]` Cancel and exit) |
|