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
|
@@ -10,13 +10,11 @@ Reference document for invoking `skf-shape-detect.py` — the shared shape class
|
|
|
10
10
|
|
|
11
11
|
## Invocation Contract
|
|
12
12
|
|
|
13
|
-
**Resolve `{shapeDetectHelper}`** from `{shapeDetectProbeOrder}`; first existing path wins
|
|
13
|
+
**Resolve `{shapeDetectHelper}`** from `{shapeDetectProbeOrder}`; first existing path wins. If neither resolves, step-auto-scope.md §3 HARD HALTs with exit code 3 (`resolution-failure`).
|
|
14
14
|
|
|
15
|
-
**Command
|
|
16
|
-
```
|
|
17
|
-
uv run {shapeDetectHelper} --repo-url <url>
|
|
18
|
-
--manifests <path1,path2,...> \
|
|
19
|
-
--grammar-files <g1,g2,...> --tree-paths <d1/,d2/,file,...>
|
|
15
|
+
**Command** (step-auto-scope.md §3 runs it on the manifest scan and the file list §2 wrote to `{run_dir}/manifests-1.json` and `{run_dir}/tree.txt`):
|
|
16
|
+
```bash
|
|
17
|
+
uv run {shapeDetectHelper} --repo-url "<url>" --manifests-file "{run_dir}/manifests-1.json" --manifest-dir "{scan_root}" --tree-file "{run_dir}/tree.txt"
|
|
20
18
|
```
|
|
21
19
|
|
|
22
20
|
**Arguments:**
|
|
@@ -24,9 +22,11 @@ uv run {shapeDetectHelper} --repo-url <url> \
|
|
|
24
22
|
| Arg | Required | Description |
|
|
25
23
|
|-----|----------|-------------|
|
|
26
24
|
| `--repo-url` | Yes | Repository URL (context only — no cloning performed) |
|
|
27
|
-
| `--manifests` |
|
|
28
|
-
| `--
|
|
29
|
-
| `--
|
|
25
|
+
| `--manifests-file` | One of the two | The JSON envelope `skf-scan-manifests.py scan` printed: the script keeps the manifest types it classifies (the supported manifests below) and resolves each `path` against `--manifest-dir`, so no caller filters, resolves or joins the list |
|
|
26
|
+
| `--manifest-dir` | With `--manifests-file` | The folder the scan ran on, the scan root |
|
|
27
|
+
| `--manifests` | One of the two | Comma-separated local file paths to manifest files, in place of `--manifests-file` (may be empty when a tree-level signal carries the classification) |
|
|
28
|
+
| `--tree-file` | No | The repository's whole file list, one path per line (`git ls-tree -r --name-only HEAD`, `git ls-files` or `find` output) or JSON. The script finds the tree-level signals in it itself (grammar files such as `*.y`, `*.g4`, `Grammar/python.gram` or a root `grammar.js`; a `compiler/` folder or a lexer+parser+ast triad), with its own gates, so no caller filters the list first |
|
|
29
|
+
| `--grammar-files`, `--tree-paths` | No | The older way to pass the same signals, harvested by the caller; not with `--tree-file` |
|
|
30
30
|
|
|
31
31
|
**Supported manifests:** `package.json`, `pyproject.toml`, `Cargo.toml`, `go.mod`, `pom.xml`, `build.gradle`, `build.gradle.kts`, `Package.swift`
|
|
32
32
|
|
|
@@ -47,7 +47,7 @@ JSON object on stdout:
|
|
|
47
47
|
| Code | Meaning | Consumer Action |
|
|
48
48
|
|------|---------|-----------------|
|
|
49
49
|
| 0 | Shape classified (not unknown) | Use shape result for scope mapping |
|
|
50
|
-
| 1 | Unknown shape (no heuristic matched) | Fall back to interactive mode |
|
|
50
|
+
| 1 | Unknown shape (no heuristic matched) | Fall back to interactive mode: set the report's `mode: 'interactive'` first, so a resumed session takes the interactive chain |
|
|
51
51
|
| 2 | Error (invalid args, missing/unreadable files, parse failure) | HARD HALT with `resolution-failure` |
|
|
52
52
|
|
|
53
53
|
On exit code 2, error details are written to stderr as JSON: `{"error": "message", "code": "ERROR_CODE"}`
|
|
@@ -59,7 +59,9 @@ On exit code 2, error details are written to stderr as JSON: `{"error": "message
|
|
|
59
59
|
| `library-API` | `full-library` | export_count ≤ 200 |
|
|
60
60
|
| `library-API` | `public-api` | export_count > 200 (surface too large for full coverage) |
|
|
61
61
|
| `reference-app` | `reference-app` | Direct mapping — apps, CLIs, demos |
|
|
62
|
-
| `
|
|
62
|
+
| `reference-app` with an `app_or_library:framework_dep` signal | `reference-app`, or the `library-API` mapping | The only app signal is a framework dependency, which a library that extends the framework declares too. An application or demo built on the framework stays `reference-app`; a library that extends or wraps the framework takes the `library-API` mapping (`full-library` or `public-api` by `export_count`). step-auto-scope.md §4 judges which |
|
|
63
|
+
| Any shape with a `language_or_user:parser_dep` signal | That shape's mapping, or `language-reference`'s | A parser library among the runtime dependencies (`parser_dep:`) fits a language built on it and a project that only reads its input with it alike. A repository that implements a language, DSL, query language or grammar on it (a compiler, an interpreter, a rule or template engine) takes `language-reference`; one that parses a data format, a config file, command-line text or source code in existing languages with it (an editor, a linter, code search or an indexer) keeps its shape. step-auto-scope.md §4 judges which |
|
|
64
|
+
| `language-reference` | `full-library` | Language tools/parsers are library-shaped from a skill perspective. **Corpora-dependent** for a *whole-language* reference (a `grammar_file:`/`tree_triad:` signal: a compiler/interpreter): its value is the language's prose (guide/Book + std/library docs), not compiler internals, so step-auto-scope-corpora.md, which step-auto-scope.md §6 loads for that signal, seeds companion corpora, and §6/§7 record an honest DEGRADED caveat when none are found (mirrors the §3b facet-coverage guard). A parser library, or a language built on one (`parser_producer:`/`parser_dep:`), is exempt: no `grammar_file:` or `tree_triad:` signal, so §6 seeds no corpora. |
|
|
63
65
|
| `stack-compose` | `full-library` | Decomposition candidate when `package_count > 3` — cohesion-checked in step-auto-scope.md §3b |
|
|
64
66
|
| `unknown` | N/A | Triggers fallback to interactive mode |
|
|
65
67
|
|
|
@@ -79,7 +81,7 @@ When neither threshold is met, the single-scope flow proceeds unchanged.
|
|
|
79
81
|
|
|
80
82
|
The five-shape heuristic ladder applies in order (first match wins):
|
|
81
83
|
|
|
82
|
-
1. **language-reference
|
|
84
|
+
1. **language-reference**: parser/grammar/language-toolchain project. Signals, strongest first: a hand-written-compiler tree structure (a dedicated `compiler/` directory with a lexer+parser+ast triad plus a codegen/VM/type-checker member, as in rustc, TypeScript, Go); a declared grammar file (`Grammar/python.gram`, a root `parse.y`, a `*.g4`, as in CPython, Ruby); or the repo's own name being a known parser/grammar tool (pest, lalrpop, lark: the producer). A parser library among the core members' runtime dependencies (the consumer) decides only when no rung below answers and no manifest declares a bin (a bare DSL manifest); otherwise the shape that answers carries the `language_or_user:parser_dep` question. Delegating consumers (formatters, linters, bundlers that depend on a parser) and markup/DSL parsers (CSS, markdown, GraphQL) are excluded.
|
|
83
85
|
2. **stack-compose** — multi-ecosystem composite project. Signals: manifests from 2+ distinct ecosystems
|
|
84
86
|
3. **reference-app** — application, CLI, or demo project. Signals: npm `bin` field, Rust `[[bin]]`, framework deps (next, fastapi, axum, etc.)
|
|
85
87
|
4. **library-API** — library exposing a programmatic API. Signals: `main`/`module`/`exports` fields, `[lib]` target, export count
|
|
@@ -36,6 +36,12 @@ Rules for identifying discrete skillable units within a project. A "skillable un
|
|
|
36
36
|
| Comment boundaries | Code comments marking sections | `// --- Auth Module ---` |
|
|
37
37
|
| Import clustering | Files that import primarily from each other | Tight import graph cluster |
|
|
38
38
|
|
|
39
|
+
`skf-disqualify-candidates.py` reports the signals a boundary's file list shows, in each record's `signals` (identify-units §2): an independent manifest (`own_manifest`), a separate entry point (`entry_point`), a Docker/service definition (`service_definition`), README.md presence (`readme`), a separate test suite (`test_suite`), a CI/CD pipeline reference (`ci_reference`) and a large directory (`large_directory`). Workspace membership is reported too, as each candidate's `workspace_member` (**Candidate Boundaries**): scan-project passes the scan the workspaces `skf-detect-workspaces.py --snapshot` resolves from the workspace configuration, and a path discover-additional-source adds has none (null). The other signals are judged from the code.
|
|
40
|
+
|
|
41
|
+
## Candidate Boundaries
|
|
42
|
+
|
|
43
|
+
The boundaries scan-project and discover-additional-source propose for a project path, which identify-units then classifies, are the `candidates[]` of its `skf-scan-manifests.py` scan, which applies the rule itself: the folders that hold a manifest or a Docker, compose or serverless file, less a workspace root with no code of its own (`.` is the scan root). Name a candidate by its folder.
|
|
44
|
+
|
|
39
45
|
## Boundary Classification
|
|
40
46
|
|
|
41
47
|
### Service Boundary
|
|
@@ -72,71 +78,60 @@ Rules for identifying discrete skillable units within a project. A "skillable un
|
|
|
72
78
|
|
|
73
79
|
### Composite Boundary
|
|
74
80
|
- Two or more Package or Module boundaries that only deliver value together (no constituent is independently useful to the skill consumer)
|
|
75
|
-
- Hard cross-boundary dependency: constituents
|
|
76
|
-
- Common pattern: a set of crates/packages in the same repo that implement a protocol together (e.g., plugin crates for a framework, verification + encoding halves of a cryptographic library)
|
|
81
|
+
- Hard cross-boundary dependency: consumers use the constituents together, through types, traits or interfaces they share, or through one facade that re-exports them all
|
|
82
|
+
- Common pattern: a set of crates/packages in the same repo that implement a protocol together (e.g., plugin crates for a framework, verification + encoding halves of a cryptographic library), or a facade package over its sub-packages
|
|
77
83
|
- Scope type: inherits from the dominant constituent (typically `full-library` or `specific-modules`)
|
|
78
84
|
|
|
79
|
-
**Detection heuristic (
|
|
80
|
-
1. Among the qualifying units, find groups of ≥2 boundaries where
|
|
81
|
-
- **Mutual hard dependency:**
|
|
85
|
+
**Detection heuristic (map-and-detect §5, once the import graph and the integration map exist):**
|
|
86
|
+
1. Among the qualifying units, find groups of ≥2 boundaries where any trigger holds:
|
|
87
|
+
- **Mutual hard dependency:** the constituents import each other in a cycle (`skf-find-cycles.py` over the `skf-count-imports.py` edges), AND no constituent's public API is self-contained (removing any one breaks the others)
|
|
82
88
|
- **Shared integration surface:** Constituents share types/traits defined in one constituent but consumed by all others, AND the consuming constituents have no independent barrel (their value depends on the shared definitions)
|
|
89
|
+
- Any of the **Cohesion Triggers** below
|
|
83
90
|
2. For each detected group, propose merging into a single composite unit:
|
|
84
|
-
- Name:
|
|
91
|
+
- Name: by the Unit Names rule below, for a merged unit
|
|
85
92
|
- Constituents: list of merged boundary names and paths
|
|
86
|
-
- Rationale: which
|
|
87
|
-
3. The merge is a **recommendation
|
|
93
|
+
- Rationale: which trigger fired, with its evidence
|
|
94
|
+
3. The merge is a **recommendation**: the user confirms it in map-and-detect §6, and a headless run accepts it. A group that merges is not also a stack skill candidate.
|
|
95
|
+
|
|
96
|
+
### Cohesion Triggers
|
|
97
|
+
|
|
98
|
+
The one statement of when a monorepo's members belong in one cohesive skill rather than one skill per package. The `[auto]` path (step-auto-scope §3b) and the interactive chain (map-and-detect §5, and discover-additional-source for a path [D] adds) apply it. Empirically, 5/5 real monorepos (animato 15 crates, trpc, react 38 packages, aws-sdk-js-v3 442 packages, plus zod) were best served as one cohesive skill or a curated few, not one skill per package. The evidence comes from the `skf-scan-manifests.py` scan (`umbrella_candidates[]`, and each member's `name`, `private` and `internal_deps`), never from opening each member manifest.
|
|
99
|
+
|
|
100
|
+
Merge when **any** of these holds:
|
|
101
|
+
|
|
102
|
+
- **Umbrella facade:** one package re-exports the members: a root or named package whose dependencies include the other workspace members (an `umbrella_candidates[]` entry, with the members its `internal_deps` cover), or which `pub use` / `export *`s them. The facade *is* the public surface (e.g. animato's `crates/animato` re-exporting its 15 sub-crates).
|
|
103
|
+
- **Shared runtime contract:** the members are consumed together through one entry point, and teaching the shared invariant covers them (e.g. tRPC's adapters around `@trpc/server`; aws-sdk's `new XClient(...) → client.send(new YCommand(...))` shared by every `@aws-sdk/client-*`).
|
|
104
|
+
- **Internal building blocks:** the members are private/internal pieces of one product, not independently meaningful to a consumer (`private: true` on the members).
|
|
105
|
+
|
|
106
|
+
Split instead when the members are **independently published with distinct public surfaces serving different concerns**, **and no umbrella re-exports them**: e.g. `react-dom` and `react-server-dom-*` are separate installs with separate jobs, or a federated SDK where a consumer only ever wants one service. Each genuinely distinct facet earns its own skill.
|
|
88
107
|
|
|
89
108
|
## Disqualification Rules
|
|
90
109
|
|
|
91
110
|
Do not recommend a boundary as a skillable unit when:
|
|
92
111
|
|
|
93
|
-
1. **Too small**: Fewer than 3 source files or 100 lines of code
|
|
94
|
-
2. **Generated code**:
|
|
112
|
+
1. **Too small**: Fewer than 3 source files or 100 lines of code. `skf-disqualify-candidates.py` counts the source files that are not generated: lockfiles, documentation, data and configuration files, manifests and build tool files (`setup.py`, `build.gradle`, `gradlew`, `vite.config.ts` and the like) are not source files
|
|
113
|
+
2. **Generated code**: every source file is generated (protobuf, GraphQL codegen, etc.): under a vendored or cache folder (`node_modules/`, `vendor/`, `__pycache__/` and the like) at any depth, under a build output folder (`dist/`, `build/`, `target/`) directly below the unit or beside a manifest, or opening with a generated-code header such as `@generated`. A source folder of an output folder's name further down (`src/build/`, the Java package folder `com/acme/build/`) is the unit's own code. A boundary with only some generated files stays, with those files left out of its counts, and identify-units judges it
|
|
95
114
|
3. **Pure configuration**: Only config files with no logic
|
|
96
115
|
4. **Test-only**: Test utilities with no production code
|
|
97
116
|
5. **Vendor/dependency**: Third-party code copied into project
|
|
98
117
|
6. **Already skilled**: Existing skill found in forge_data_folder (recommend update-skill instead)
|
|
99
118
|
|
|
100
|
-
##
|
|
101
|
-
|
|
102
|
-
During per-unit analysis, check for scripts and assets alongside code exports.
|
|
103
|
-
|
|
104
|
-
**Script signals:**
|
|
119
|
+
## Unit Names
|
|
105
120
|
|
|
106
|
-
|
|
107
|
-
|----------|-----------------------------------------------------------------------------------------------|-----------------------------------------------------|
|
|
108
|
-
| Strong | Entry point in `package.json` `bin`, Cargo.toml `[[bin]]`, pyproject.toml `[project.scripts]` | `"bin": { "migrate": "scripts/migrate.js" }` |
|
|
109
|
-
| Strong | Shebang + executable file | `#!/usr/bin/env python` in `scripts/setup.py` |
|
|
110
|
-
| Moderate | File in `scripts/`, `bin/`, `tools/`, `cli/` directory | `scripts/validate.sh` |
|
|
111
|
-
| Moderate | CI/CD reference to script | `.github/workflows/test.yml` runs `scripts/test.sh` |
|
|
121
|
+
Every unit, composite and brief is named by `skf-skill-inventory.py derive-name`, from the same inputs on the `[auto]` path (step-auto-scope §6 and its split branch) and the interactive chain (identify-units §2, map-and-detect §5, discover-additional-source), so one unit gets one name on both:
|
|
112
122
|
|
|
113
|
-
**
|
|
123
|
+
- **A single unit** passes its own manifest's `name` and `private` flag. A private manifest names nothing, so a monorepo's workspace root or an internal app takes its folder's or repository's name; a published package takes its manifest's (`@trpc/server` gives `trpc-server`).
|
|
124
|
+
- **A merged unit** (a composite, or a monorepo the cohesion check merges) passes the facade's manifest name when the umbrella facade trigger fired, and its members' manifest names: a composite's constituents, a merged monorepo's published members (its private examples and tools left out). Without a facade it takes the name the members share (`trpc` for `@trpc/server` and `@trpc/client`), else the repository's.
|
|
114
125
|
|
|
115
|
-
|
|
116
|
-
|----------|--------------------------------------------------------------------------------|----------------------------------|
|
|
117
|
-
| Strong | JSON Schema file with `$schema` key | `schemas/config.schema.json` |
|
|
118
|
-
| Strong | Config template with `.example` or `.template` extension | `config.yaml.example` |
|
|
119
|
-
| Moderate | File in `assets/`, `templates/`, `schemas/`, `configs/`, `examples/` directory | `templates/report.hbs` |
|
|
120
|
-
| Moderate | OpenAPI/GraphQL definition | `openapi.json`, `schema.graphql` |
|
|
121
|
-
|
|
122
|
-
**Per-unit output:** Record `has_scripts: boolean`, `has_assets: boolean`, `script_files: string[]`, `asset_files: string[]`.
|
|
123
|
-
|
|
124
|
-
**Disqualify:** Generated files (dist/, build/), vendored dependencies, IDE configs (.vscode/, .idea/), binary files (.so, .dll, .jar).
|
|
126
|
+
Names that would clash in one call are told apart by their parent folders (`server-api`, `client-api`).
|
|
125
127
|
|
|
126
128
|
## Stack Skill Candidate Detection
|
|
127
129
|
|
|
128
|
-
Flag units as stack skill candidates when:
|
|
130
|
+
Flag units as stack skill candidates when (map-and-detect §5, in the same pass as the composite merges):
|
|
129
131
|
|
|
130
|
-
1. **Co-import frequency**: Two or more units are imported together in 3+ files
|
|
132
|
+
1. **Co-import frequency**: Two or more units are imported together in 3+ files (a `skf-pair-intersect.py` pair over the `skf-count-imports.py` importer lists with an `intersection_count` of 3 or more)
|
|
131
133
|
2. **Integration adapter**: A unit exists primarily to bridge two other units
|
|
132
134
|
3. **Shared state**: Multiple units read/write to the same data store
|
|
133
135
|
4. **Orchestration layer**: A unit coordinates calls across multiple other units
|
|
134
136
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
| Forge Tier | Scanning Approach |
|
|
138
|
-
|------------|----------------------------------------------------------------------------------------------------|
|
|
139
|
-
| Quick | File structure analysis: directory trees, manifest files, entry points, naming conventions |
|
|
140
|
-
| Forge | AST analysis: export surfaces, import graphs, dependency trees, type hierarchies |
|
|
141
|
-
| Forge+ | AST + CCC: semantic file pre-ranking before structural analysis, CCC signals for relevance scoring |
|
|
142
|
-
| Deep | AST + QMD: temporal evolution, refactoring patterns, semantic relationships, architectural drift |
|
|
137
|
+
Stack skill candidates are useful separately and also together; units that only deliver value together are a Composite Boundary instead, never both.
|
|
@@ -7,16 +7,18 @@ description: Drift detection between skill and current source code. Use when the
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
Detects drift between
|
|
10
|
+
Detects drift between a skill and its current source code and writes a severity-graded drift report with AST-backed findings and remediation suggestions; analysis depth follows the forge tier (Quick/Forge/Forge+/Deep). Stack skills: a compose-mode stack checks its constituents' freshness by metadata hash; a code-mode stack is diffed library by library. A docs-only skill is audited by its documents' hashes; a skill with no provenance map has no baseline, so step 1 stops it.
|
|
11
11
|
|
|
12
12
|
## Conventions
|
|
13
13
|
|
|
14
14
|
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
15
|
-
- **Module-level path exception:** bare paths beginning with `knowledge/` or `shared/` resolve from the SKF module root (`{project-root}/_bmad/skf/` installed, `src/` in dev), not the skill root
|
|
16
|
-
-
|
|
15
|
+
- **Module-level path exception:** bare paths beginning with `knowledge/` or `shared/` resolve from the SKF module root (`{project-root}/_bmad/skf/` installed, `src/` in dev), not the skill root.
|
|
16
|
+
- **Sibling skills:** a path that names another SKF skill's folder (`skf-<name>/...`) resolves from the SKF module root, and that skill must be installed with this one.
|
|
17
|
+
- `scripts/` holds `render-drift-tables.py`, which steps 3, 5 and 6 run to print their drift tables.
|
|
17
18
|
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
18
19
|
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
19
20
|
- `{skill-name}` resolves to the skill directory's basename.
|
|
21
|
+
- **Cross-skill data coupling:** `re-index.md` loads `extraction-patterns.md` and `tier-degradation-rules.md` from `skf-create-skill/references/`.
|
|
20
22
|
|
|
21
23
|
## Role
|
|
22
24
|
|
|
@@ -24,91 +26,81 @@ You are a skill auditor in Ferris Audit mode: a deterministic drift-detection wo
|
|
|
24
26
|
|
|
25
27
|
## Workflow Rules
|
|
26
28
|
|
|
27
|
-
These rules apply to every step in this workflow:
|
|
28
|
-
|
|
29
29
|
- Never fabricate findings — all data must trace to source code with file:line citations
|
|
30
30
|
- Only load one step file at a time — never preload future steps
|
|
31
31
|
- Update `stepsCompleted` in output file frontmatter before loading next step
|
|
32
32
|
- Always communicate in `{communication_language}`
|
|
33
|
-
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
33
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision; step 1's gates (manifest-vs-link, upstream-drift, baseline confirm) also record theirs in the run sink as they decide
|
|
34
|
+
- Every HARD HALT names its exit code, `halt_reason` and phase; in headless mode it prints its envelope through the shared emitter, as each stage's **Halt envelope** paragraph shows
|
|
35
|
+
- Once the [C] of `references/upstream-checkout.md` has bound `{source_tree}` (the private tree it read the upstream ref into), every step reads the source there, never at the recorded `source_path`, and every HALT after it first runs `uv run {sourceTreeHelper} close --tree "{source_tree}"` from `{project-root}` and goes on whatever it prints
|
|
36
|
+
- Run state (the gates' decisions, the warnings, the emitter's payloads) lives in `{run_dir}`: step 6 deletes it, a HALT keeps it
|
|
34
37
|
|
|
35
38
|
## Stages
|
|
36
39
|
|
|
37
40
|
| # | Step | File | Auto-proceed |
|
|
38
41
|
|---|------|------|--------------|
|
|
39
|
-
| 1 | Initialize & Baseline | references/init.md | No (confirm) |
|
|
42
|
+
| 1 | Initialize & Baseline | references/init.md | No (confirm on a doubt: tier below the compile tier, or provenance map over 90 days old) |
|
|
43
|
+
| 1b | Upstream Checkout (only when upstream moved) | references/upstream-checkout.md | No (Upstream-Drift Gate) |
|
|
44
|
+
| 1c | Constituent Freshness (compose-mode stacks only) | references/constituent-freshness.md | Yes |
|
|
40
45
|
| 2 | Re-Index Source | references/re-index.md | Yes |
|
|
41
46
|
| 3 | Structural Diff | references/structural-diff.md | Yes |
|
|
42
47
|
| 4 | Semantic Diff | references/semantic-diff.md | Yes (skip at non-Deep) |
|
|
43
48
|
| 5 | Severity Classification | references/severity-classify.md | Yes |
|
|
44
|
-
| 5a | Doc Drift | references/
|
|
49
|
+
| 5a | Doc Drift | references/doc-drift.md | Yes |
|
|
45
50
|
| 6 | Report | references/report.md | Yes |
|
|
46
51
|
| 7 | Workflow Health Check | references/health-check.md | Yes |
|
|
47
52
|
|
|
53
|
+
Stage 1b returns to init.md at §5b's **Record for report**, then §6. Step 1 §4 picks stage 1c from the provenance map: it replaces stages 2 to 4 for a compose-mode stack, which has no source tree to re-index (init.md → constituent-freshness.md → severity-classify.md). A docs-only skill skips stages 2 to 4 too (step 1 §3): init.md → doc-drift.md → severity-classify.md → report.md.
|
|
54
|
+
|
|
48
55
|
## Invocation Contract
|
|
49
56
|
|
|
50
57
|
| Aspect | Detail |
|
|
51
58
|
|--------|--------|
|
|
52
|
-
| **Inputs** | `skill_name` [required], `skill_path` [optional
|
|
53
|
-
| **Gates** | step 1: Manifest-vs-Symlink Gate [N] · Upstream-Drift Gate [C/S/X]
|
|
54
|
-
| **Outputs** |
|
|
55
|
-
| **Headless** |
|
|
56
|
-
| **Exit codes** |
|
|
57
|
-
|
|
58
|
-
## Exit Codes
|
|
59
|
-
|
|
60
|
-
Every hard halt in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
|
|
61
|
-
|
|
62
|
-
| Code | Meaning | Raised by |
|
|
63
|
-
| ---- | -------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
64
|
-
| 0 | success | step 7 (terminal health-check) |
|
|
65
|
-
| 2 | input-missing | step 1 §1 — no `skill_name` supplied in headless mode (interactive prompt cannot resolve) |
|
|
66
|
-
| 3 | resolution-failure | step 1 §1 (skill not found at resolved path: missing `SKILL.md`); step 1 §2 (`forge-tier.yaml` missing — setup-forge not run); step 1 §5 (source directory from provenance map no longer exists / inaccessible) |
|
|
67
|
-
| 4 | write-failure | step 1 §6 / step 6 §3 (drift report write failed: read-only mount, disk full, permissions denied) |
|
|
68
|
-
| 6 | user-cancelled | step 1 §1 manifest-vs-symlink gate `[X]` · step 1 §4 degraded-mode gate `[X]` · step 1 §5b upstream-drift gate `[X]` · step 1 §5b dirty-worktree sub-gate `[A]` (and `[A]` headless default) |
|
|
69
|
-
|
|
70
|
-
## Result Contract (Headless)
|
|
71
|
-
|
|
72
|
-
When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every hard halt emits the same envelope shape on **stderr** with `status: "error"`:
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
SKF_AUDIT_RESULT_JSON: {"status":"success|error","skill_name":"…","drift_score":"CLEAN|MINOR|SIGNIFICANT|CRITICAL|null","report_path":"…|null","next_workflow":"update-skill|null","audit_ref":"…|null","exit_code":0,"halt_reason":null}
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
`status` is `"success"` on the terminal happy path, `"error"` on any halt. `drift_score` is `null` when the workflow halted before severity classification ran. `next_workflow` is `"update-skill"` when CRITICAL or HIGH findings exist, otherwise `null`. `halt_reason` is one of: `null` (success), `"input-missing"`, `"skill-not-found"`, `"forge-tier-missing"`, `"source-dir-missing"`, `"write-failed"`, `"user-cancelled"`. `exit_code` matches the table above.
|
|
59
|
+
| **Inputs** | `skill_name` [required], `skill_path` [optional: the skill folder, bypassing manifest/symlink resolution], `tier_override` [optional: Quick / Forge / Forge+ / Deep, in place of the detected tier], `upstream_drift_choice` [optional: C / S / X; answers the upstream-drift gate in references/upstream-checkout.md; C, auditing the upstream ref from a private tree, when unset] |
|
|
60
|
+
| **Gates** | step 1: Manifest-vs-Symlink Gate [N/M/X] · Upstream-Drift Gate [C/S/X] (references/upstream-checkout.md, only when upstream moved) · Baseline Confirm Gate [C/X] (only on a doubt: the forge tier is below the compile tier, or the provenance map is more than 90 days old) |
|
|
61
|
+
| **Outputs** | The drift report, the JSON it was built from and the result contract, in `{forge_version}/` (the audited version's folder): `references/headless-contract.md` names each file |
|
|
62
|
+
| **Headless** | Every gate takes its default action, a pre-supplied `upstream_drift_choice` answers the upstream-drift gate, `tier_override` sets the tier (step 1 §2), and each gate's decision lands in the envelope's `headless_decisions` |
|
|
63
|
+
| **Exit codes** | `references/headless-contract.md`: each halt class's exit code and `halt_reason`, and the `SKF_AUDIT_RESULT_JSON` envelope |
|
|
79
64
|
|
|
80
65
|
## On Activation
|
|
81
66
|
|
|
82
67
|
1. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:
|
|
83
68
|
- `project_name`, `output_folder`, `user_name`, `communication_language`, `document_output_language`
|
|
84
69
|
- `skills_output_folder`, `forge_data_folder`, `sidecar_path`
|
|
85
|
-
-
|
|
70
|
+
- `timestamp` ← now, as `YYYYMMDD-HHmmss`, fixed for the whole run
|
|
71
|
+
- `run_dir` ← `{project-root}/_bmad-output/.skf-run/skf-audit-skill-{timestamp}`, the run folder step 4 below creates
|
|
86
72
|
|
|
87
|
-
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml
|
|
73
|
+
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in `{sidecar_path}/preferences.yaml`. Default: false.
|
|
88
74
|
|
|
89
75
|
3. **Resolve workflow customization.** Run:
|
|
90
76
|
|
|
91
77
|
```bash
|
|
92
|
-
|
|
93
|
-
--skill {skill-root} --key workflow
|
|
78
|
+
uv run {project-root}/_bmad/scripts/resolve_customization.py --skill {skill-root} --project-root {project-root} --key workflow
|
|
94
79
|
```
|
|
95
80
|
|
|
96
|
-
|
|
81
|
+
It merges the bundled `{skill-root}/customize.toml` with `{project-root}/_bmad/custom/skf-audit-skill.toml` (team overrides, committed) and `.user.toml` (personal overrides, gitignored). When it exits non-zero, prints no JSON or is missing, print one line, `[activation/warn] customization_resolver_unavailable: <reason>` (`<reason>`: its first stderr line, `not found` when the script is missing, `no JSON` when it printed none). If the resolver cannot run, read `{skill-root}/customize.toml` alone and use its bundled defaults: the `{project-root}/_bmad/custom/` overrides do not apply to this run. Then keep the reason as `{customization_resolver_unavailable}`, which step 6 hands to the emitter as a warning.
|
|
82
|
+
|
|
83
|
+
Bind the two scalars the stages read, each to its bundled default when the merged value is empty or absent:
|
|
97
84
|
|
|
98
|
-
- `{
|
|
99
|
-
- `
|
|
100
|
-
- `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)
|
|
85
|
+
- `{driftReportTemplatePath}` ← `workflow.drift_report_template_path`, else `assets/drift-report-template.md`
|
|
86
|
+
- `{onCompleteCommand}` ← `workflow.on_complete`, else empty (step 6 then runs no hook)
|
|
101
87
|
|
|
102
|
-
|
|
88
|
+
Run `workflow.activation_steps_prepend` now, treat `workflow.persistent_facts` as standing context for the run (a `file:` entry loads its file or glob contents as facts: the bundled default loads every `project-context.md` under `{project-root}`; an entry prefixed `!` drops each earlier entry it names and loads nothing itself, so an override's `"!file:{project-root}/**/project-context.md"` turns that default off), then run `workflow.activation_steps_append` once step 4 below has passed.
|
|
103
89
|
|
|
104
|
-
|
|
90
|
+
4. **Pre-flight: `uv`, the helpers and the run folder.** Before the first prompt, resolve `{emitEnvelopeHelper}` ← `{project-root}/_bmad/skf/shared/scripts/skf-emit-result-envelope.py`, else `{project-root}/src/shared/scripts/skf-emit-result-envelope.py`. If neither exists, HALT (exit code 3, `halt_reason: "helper-missing"`) and display only: "Audit Skill cannot run without `skf-emit-result-envelope.py`, which is not installed. Re-install SKF."
|
|
105
91
|
|
|
106
|
-
- `
|
|
107
|
-
- `{severityRulesPath}` ← `workflow.severity_rules_path` if non-empty, else `references/severity-rules.md`
|
|
108
|
-
- `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — report.md skips the hook invocation entirely)
|
|
92
|
+
Run `uv --version`, and check that `skf-load-provenance.py`, `skf-structural-diff.py`, `skf-severity-classify.py` and `skf-detect-docs.py` each exist in `{project-root}/_bmad/skf/shared/scripts/` or `{project-root}/src/shared/scripts/`. If `uv --version` fails, or a helper is in neither folder, HALT (exit code 3, `halt_reason: "helper-missing"`) at phase `on-activation:helpers`, naming what is missing: "Audit Skill cannot run without `<uv or the script>`, which is not installed. Install uv (<https://docs.astral.sh/uv/>) or re-install SKF, then re-run." Then create the run folder:
|
|
109
93
|
|
|
110
|
-
|
|
94
|
+
```bash
|
|
95
|
+
mkdir -p "{project-root}/_bmad-output/.skf-run" && mkdir "{run_dir}"
|
|
96
|
+
```
|
|
111
97
|
|
|
112
|
-
|
|
98
|
+
If the command fails, HALT (exit code 4, `halt_reason: "write-failed"`) at phase `on-activation:run-folder`: "Cannot create the run folder `{run_dir}`: {the first stderr line}." With no folder to stage in, a headless HALT of this step passes its payload to the emitter directly, through `python3` in place of `uv run` when `uv` is what is missing:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-audit-skill --target stderr <<'SKF_AS_HALT'
|
|
102
|
+
{"phase": "<the phase>", "reason": "<the halt message>", "halt_reason": "<the halt_reason>"}
|
|
103
|
+
SKF_AS_HALT
|
|
104
|
+
```
|
|
113
105
|
|
|
114
|
-
|
|
106
|
+
5. Load, read the full file, and then execute `references/init.md` to begin the workflow.
|
|
@@ -8,6 +8,28 @@ skill_name: ''
|
|
|
8
8
|
skill_path: ''
|
|
9
9
|
source_path: ''
|
|
10
10
|
forge_tier: ''
|
|
11
|
+
# Run context, written as each value is known (init §6, re-index §5,
|
|
12
|
+
# structural-diff §6), so later steps read it from this file.
|
|
13
|
+
audited_version: ''
|
|
14
|
+
audited_version_reason: ''
|
|
15
|
+
manifest_version: ''
|
|
16
|
+
docs_only_skill: ''
|
|
17
|
+
provenance_map: ''
|
|
18
|
+
provenance_generated_at: ''
|
|
19
|
+
provenance_age_days: ''
|
|
20
|
+
baseline_ref: ''
|
|
21
|
+
baseline_commit: ''
|
|
22
|
+
audit_ref: ''
|
|
23
|
+
audit_ref_source: ''
|
|
24
|
+
audit_commit: ''
|
|
25
|
+
latest_tag: ''
|
|
26
|
+
remote_head: ''
|
|
27
|
+
upstream_fetch: ''
|
|
28
|
+
upstream_moved: ''
|
|
29
|
+
upstream_ref: ''
|
|
30
|
+
source_tree: ''
|
|
31
|
+
ast_fallback_files: []
|
|
32
|
+
applied_transforms: []
|
|
11
33
|
drift_score: ''
|
|
12
34
|
nextWorkflow: ''
|
|
13
35
|
previousWorkflow: 'create-skill'
|
|
@@ -17,7 +39,6 @@ previousWorkflow: 'create-skill'
|
|
|
17
39
|
|
|
18
40
|
## Audit Summary
|
|
19
41
|
|
|
20
|
-
**Confidence Mode:** {confidence_mode}
|
|
21
42
|
**Skill:** {skill_name}
|
|
22
43
|
**Source:** {source_path}
|
|
23
44
|
**Tier:** {forge_tier}
|
|
@@ -36,7 +57,9 @@ previousWorkflow: 'create-skill'
|
|
|
36
57
|
|
|
37
58
|
## Structural Drift
|
|
38
59
|
|
|
39
|
-
<!-- Appended by structural-diff -->
|
|
60
|
+
<!-- Appended by structural-diff, or for a compose-mode stack by constituent-freshness -->
|
|
61
|
+
<!-- Constituent Freshness (compose-mode stacks): drifted, missing and not-compared constituents; each drifted (HIGH) or missing (MEDIUM) one is a finding -->
|
|
62
|
+
<!-- Provenance label differences (not drift): informational table, rendered only when label_changes[] is non-empty and excluded from Total Drift Items -->
|
|
40
63
|
|
|
41
64
|
---
|
|
42
65
|
|
|
@@ -54,13 +77,14 @@ previousWorkflow: 'create-skill'
|
|
|
54
77
|
|
|
55
78
|
## Documentation Drift
|
|
56
79
|
|
|
57
|
-
<!-- Appended by
|
|
80
|
+
<!-- Appended by doc-drift -->
|
|
58
81
|
|
|
59
82
|
---
|
|
60
83
|
|
|
61
84
|
## Remediation Suggestions
|
|
62
85
|
|
|
63
86
|
<!-- Appended by report -->
|
|
87
|
+
<!-- Out-of-Scope New Public API: one row per file outside the skill's scope whose public API a package entry point exports (the snapshot's outside_scope), which update-skill's scope reconciliation reads; left out when there is none -->
|
|
64
88
|
|
|
65
89
|
---
|
|
66
90
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# DO NOT EDIT -- overwritten on every update.
|
|
2
2
|
#
|
|
3
3
|
# Workflow customization surface for skf-audit-skill.
|
|
4
|
-
# Team overrides: _bmad/custom/skf-audit-skill.toml
|
|
5
|
-
# Personal overrides: _bmad/custom/skf-audit-skill.user.toml
|
|
4
|
+
# Team overrides: {project-root}/_bmad/custom/skf-audit-skill.toml
|
|
5
|
+
# Personal overrides: {project-root}/_bmad/custom/skf-audit-skill.user.toml
|
|
6
6
|
|
|
7
7
|
[workflow]
|
|
8
8
|
|
|
@@ -10,42 +10,63 @@
|
|
|
10
10
|
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
11
11
|
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
12
12
|
|
|
13
|
-
# Steps
|
|
14
|
-
#
|
|
15
|
-
#
|
|
13
|
+
# Steps SKILL.md On Activation step 3 runs once this file resolves: after the
|
|
14
|
+
# config load and the headless flag, before step 4's pre-flight (the uv and
|
|
15
|
+
# helper checks, the run folder) and before any stage. Overrides append. Use
|
|
16
|
+
# for org-wide pre-flight checks (auth, network, compliance) that must precede
|
|
17
|
+
# any audit work.
|
|
16
18
|
|
|
17
19
|
activation_steps_prepend = []
|
|
18
20
|
|
|
19
|
-
# Steps to run
|
|
20
|
-
#
|
|
21
|
-
#
|
|
21
|
+
# Steps to run once activation completes (step 4's pre-flight passed), before
|
|
22
|
+
# references/init.md (the first stage) loads. Overrides append. Use for
|
|
23
|
+
# context loads or banner customization.
|
|
22
24
|
|
|
23
25
|
activation_steps_append = []
|
|
24
26
|
|
|
25
27
|
# Persistent facts the workflow keeps in mind for the whole run
|
|
26
|
-
# (house style,
|
|
27
|
-
#
|
|
28
|
+
# (house style, audit guardrails). Overrides append. Severity grades are not
|
|
29
|
+
# a fact: skf-severity-classify.py grades every finding by its own rule table.
|
|
28
30
|
#
|
|
29
|
-
# Each entry is
|
|
31
|
+
# Each entry is one of:
|
|
30
32
|
# - a literal sentence, e.g. "Critical drift requires CODEOWNERS notification."
|
|
31
33
|
# - a file reference prefixed with `file:`, e.g.
|
|
32
34
|
# "file:{project-root}/docs/audit-policy.md" (globs supported; file
|
|
33
35
|
# contents are loaded and treated as facts).
|
|
36
|
+
# - an entry prefixed with `!`, which loads nothing and drops each earlier
|
|
37
|
+
# entry it names.
|
|
38
|
+
#
|
|
39
|
+
# The default below loads every project-context.md under {project-root}.
|
|
40
|
+
# Overrides append, so they cannot delete it; to stop loading those files,
|
|
41
|
+
# set in {project-root}/_bmad/custom/skf-audit-skill.toml:
|
|
42
|
+
# persistent_facts = ["!file:{project-root}/**/project-context.md"]
|
|
34
43
|
|
|
35
44
|
persistent_facts = [
|
|
36
45
|
"file:{project-root}/**/project-context.md",
|
|
37
46
|
]
|
|
38
47
|
|
|
39
|
-
# --- Optional
|
|
40
|
-
#
|
|
41
|
-
# Lift the canonical asset paths so orgs can substitute house-style copies
|
|
42
|
-
# without forking the skill. Empty string = use the bundled default.
|
|
48
|
+
# --- Optional overrides. An empty string means the default named below. ---
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
# The template step 1 (references/init.md section 6) creates the drift report
|
|
51
|
+
# from. Default: assets/drift-report-template.md, a path from the skill root.
|
|
52
|
+
# Keep a house-style copy outside the skill folder, which every update
|
|
53
|
+
# overwrites, and name it as {project-root}/<path to the copy>. The copy may
|
|
54
|
+
# restyle the report body and must keep:
|
|
55
|
+
# - every frontmatter key of the bundled template: the steps write the run
|
|
56
|
+
# context, stepsCompleted, drift_score and nextWorkflow there, and step 6
|
|
57
|
+
# builds the Provenance table from them;
|
|
58
|
+
# - the `## Audit Summary` section with its severity count table, which
|
|
59
|
+
# step 6 fills in. The stages write every drift section themselves.
|
|
46
60
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
#
|
|
61
|
+
drift_report_template_path = "assets/drift-report-template.md"
|
|
62
|
+
|
|
63
|
+
# Optional post-audit hook: a shell command run from {project-root}, not an
|
|
64
|
+
# agent instruction. Step 6 (references/report.md) runs it on a finished
|
|
65
|
+
# audit, after the emitter wrote the result files, as:
|
|
66
|
+
# <on_complete> --result-path=<{forge_version}/audit-skill-result-<YYYYMMDD-HHmmss>.json>
|
|
67
|
+
# It never runs on a halt, nor when the result file could not be written. A
|
|
68
|
+
# failure is shown to the user and never fails the audit.
|
|
69
|
+
#
|
|
70
|
+
# Empty string = no-op (default).
|
|
50
71
|
|
|
51
72
|
on_complete = ""
|