bmad-module-skill-forge 2.1.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +51 -49
- package/docs/404.md +10 -8
- package/docs/_data/pinned.yaml +22 -13
- package/docs/_internal/STABILITY.md +58 -35
- package/docs/agents.md +39 -53
- package/docs/architecture.md +65 -51
- package/docs/bmad-synergy.md +53 -51
- package/docs/campaign.md +127 -75
- package/docs/concepts.md +34 -28
- package/docs/examples.md +70 -68
- package/docs/forge-auto.md +34 -31
- package/docs/getting-started.md +118 -57
- package/docs/how-it-works.md +25 -21
- package/docs/index.md +15 -15
- package/docs/skill-model.md +70 -59
- package/docs/troubleshooting.md +135 -18
- package/docs/verifying-a-skill.md +83 -57
- package/docs/why-skf.md +24 -22
- package/docs/workflows.md +274 -110
- package/package.json +18 -10
- package/src/forger/preferences.yaml +8 -1
- package/src/knowledge/agentskills-spec.md +2 -0
- package/src/knowledge/ccc-bridge.md +40 -24
- package/src/knowledge/confidence-tiers.md +9 -5
- package/src/knowledge/overview.md +3 -3
- package/src/knowledge/progressive-capability.md +8 -8
- package/src/knowledge/provenance-tracking.md +9 -5
- package/src/knowledge/qmd-registry.md +2 -2
- package/src/knowledge/skf-knowledge-index.csv +2 -2
- package/src/knowledge/skill-lifecycle.md +18 -11
- package/src/knowledge/split-body-strategy.md +0 -3
- package/src/knowledge/tool-resolution.md +4 -2
- package/src/knowledge/version-paths.md +101 -15
- package/src/module-help.csv +3 -3
- package/src/module.yaml +10 -0
- package/src/shared/data/ast-grep-recipes.yaml +608 -0
- package/src/shared/data/ide-context-files.json +30 -0
- package/src/shared/health-check.md +32 -12
- package/src/shared/references/description-guard-protocol.md +14 -9
- package/src/shared/references/feasibility-report-schema.md +19 -13
- package/src/shared/references/headless-gate-convention.md +55 -3
- package/src/shared/references/output-contract-schema.md +19 -8
- package/src/shared/references/pipeline-contracts.md +94 -29
- package/src/shared/references/tessl-review.md +77 -0
- package/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json +194 -0
- package/src/shared/scripts/schemas/skf-audit-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +32 -4
- package/src/shared/scripts/schemas/skf-campaign-result-envelope.v1.json +174 -0
- package/src/shared/scripts/schemas/skf-create-skill-result-envelope.v1.json +284 -0
- package/src/shared/scripts/schemas/skf-drop-skill-result-envelope.v1.json +164 -0
- package/src/shared/scripts/schemas/skf-export-result-envelope.v1.json +160 -0
- package/src/shared/scripts/schemas/skf-quick-skill-result-envelope.v1.json +261 -0
- package/src/shared/scripts/schemas/skf-refine-architecture-result-envelope.v1.json +192 -0
- package/src/shared/scripts/schemas/skf-rename-skill-result-envelope.v1.json +179 -0
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +27 -11
- package/src/shared/scripts/schemas/skf-stack-result-envelope.v1.json +176 -0
- package/src/shared/scripts/schemas/skf-test-result-envelope.v1.json +173 -0
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +19 -5
- package/src/shared/scripts/schemas/skf-verify-stack-result-envelope.v1.json +180 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +34 -0
- package/src/shared/scripts/schemas/workspace-detection.v1.json +1 -1
- package/src/shared/scripts/skf-atomic-write.py +30 -14
- package/src/shared/scripts/skf-build-change-manifest.py +2203 -24
- package/src/shared/scripts/skf-ccc-git-hygiene.py +532 -0
- package/src/shared/scripts/skf-check-unit-records.py +184 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +538 -9
- package/src/shared/scripts/skf-classify-changed-files.py +694 -0
- package/src/shared/scripts/skf-comention-pairs.py +1333 -123
- package/src/shared/scripts/skf-compare-file-hashes.py +1 -1
- package/src/shared/scripts/skf-count-imports.py +1867 -0
- package/src/shared/scripts/skf-count-tokens.py +1 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +3 -2
- package/src/shared/scripts/skf-description-guard.py +117 -9
- package/src/shared/scripts/skf-detect-docs.py +892 -4
- package/src/shared/scripts/skf-detect-language.py +486 -107
- package/src/shared/scripts/skf-detect-registry.py +887 -0
- package/src/shared/scripts/skf-detect-scripts-assets.py +1 -1
- package/src/shared/scripts/skf-detect-tools.py +215 -27
- package/src/shared/scripts/skf-detect-workspaces.py +506 -30
- package/src/shared/scripts/skf-disqualify-candidates.py +821 -182
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +69 -191
- package/src/shared/scripts/skf-emit-result-envelope.py +1604 -106
- package/src/shared/scripts/skf-enumerate-stack-skills.py +986 -117
- package/src/shared/scripts/skf-extract-public-api.py +4084 -85
- package/src/shared/scripts/skf-extraction-inventory.py +746 -0
- package/src/shared/scripts/skf-extraction-snapshot.py +539 -0
- package/src/shared/scripts/skf-fetch-temporal.py +674 -0
- package/src/shared/scripts/skf-find-cycles.py +97 -29
- package/src/shared/scripts/skf-find-test-report.py +476 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +444 -203
- package/src/shared/scripts/skf-github-fetch.py +365 -0
- package/src/shared/scripts/skf-github-probe.py +661 -0
- package/src/shared/scripts/skf-hash-content.py +166 -12
- package/src/shared/scripts/skf-language-corpora.py +1 -1
- package/src/shared/scripts/skf-load-provenance.py +159 -27
- package/src/shared/scripts/skf-manifest-ops.py +1 -1
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +2307 -223
- package/src/shared/scripts/skf-merge-doc-urls.py +1 -1
- package/src/shared/scripts/skf-names-present.py +221 -0
- package/src/shared/scripts/skf-pair-intersect.py +119 -28
- package/src/shared/scripts/skf-parse-gaps.py +1384 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-preflight.py +161 -27
- package/src/shared/scripts/skf-promote-staged.py +430 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +39 -7
- package/src/shared/scripts/skf-qmd-classify-collections.py +229 -45
- package/src/shared/scripts/skf-quick-batch.py +774 -0
- package/src/shared/scripts/skf-rebuild-managed-sections.py +972 -88
- package/src/shared/scripts/skf-recommend-scope-type.py +323 -156
- package/src/shared/scripts/skf-render-metadata-stats.py +156 -12
- package/src/shared/scripts/skf-render-quick-metadata.py +132 -28
- package/src/shared/scripts/skf-render-stack-metadata.py +976 -0
- package/src/shared/scripts/skf-resolve-authoritative-files.py +128 -13
- package/src/shared/scripts/skf-resolve-package.py +523 -106
- package/src/shared/scripts/skf-rewrite-skill-name.py +433 -47
- package/src/shared/scripts/skf-run-lock.py +577 -0
- package/src/shared/scripts/skf-scan-manifests.py +998 -57
- package/src/shared/scripts/skf-scan-skill-md-structure.py +1341 -37
- package/src/shared/scripts/skf-severity-classify.py +712 -108
- package/src/shared/scripts/skf-shape-detect.py +298 -204
- package/src/shared/scripts/skf-shard-body.py +9 -8
- package/src/shared/scripts/skf-skill-inventory.py +2412 -89
- package/src/shared/scripts/skf-skills-module.py +472 -0
- package/src/shared/scripts/skf-source-tree.py +1796 -0
- package/src/shared/scripts/skf-structural-diff.py +670 -119
- package/src/shared/scripts/skf-tessl-review.py +706 -0
- package/src/shared/scripts/skf-update-active-symlink.py +5 -5
- package/src/shared/scripts/skf-update-run-state.py +624 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +92 -29
- package/src/shared/scripts/skf-validate-brief-schema.py +4 -1
- package/src/shared/scripts/skf-validate-feasibility-report.py +577 -66
- package/src/shared/scripts/skf-validate-frontmatter.py +103 -26
- package/src/shared/scripts/skf-validate-output.py +712 -64
- package/src/shared/scripts/skf-validate-pins.py +1 -1
- package/src/shared/scripts/skf-verify-no-trace.py +116 -10
- package/src/shared/scripts/skf-verify-provenance-completeness.py +2919 -54
- package/src/shared/scripts/skf-write-skill-brief.py +367 -19
- package/src/shared/tool-requirements.yaml +201 -0
- package/src/skf-analyze-source/SKILL.md +41 -36
- package/src/skf-analyze-source/assets/skill-brief-schema.md +7 -8
- package/src/skf-analyze-source/customize.toml +36 -24
- package/src/skf-analyze-source/references/auto-docs-only.md +58 -20
- package/src/skf-analyze-source/references/continue.md +2 -13
- package/src/skf-analyze-source/references/discover-additional-source.md +147 -0
- package/src/skf-analyze-source/references/generate-briefs.md +121 -55
- package/src/skf-analyze-source/references/headless-contract.md +42 -15
- package/src/skf-analyze-source/references/identify-units.md +96 -110
- package/src/skf-analyze-source/references/init.md +73 -71
- package/src/skf-analyze-source/references/map-and-detect.md +123 -105
- package/src/skf-analyze-source/references/map-unit-exports.md +68 -0
- package/src/skf-analyze-source/references/recommend.md +51 -70
- package/src/skf-analyze-source/references/scan-project.md +60 -84
- package/src/skf-analyze-source/references/scan-root.md +39 -0
- package/src/skf-analyze-source/references/step-auto-scope-coexistence.md +47 -0
- package/src/skf-analyze-source/references/step-auto-scope-corpora.md +53 -0
- package/src/skf-analyze-source/references/step-auto-scope-split.md +91 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +208 -293
- package/src/skf-analyze-source/references/step-shape-detect.md +14 -12
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +37 -42
- package/src/skf-audit-skill/SKILL.md +43 -51
- package/src/skf-audit-skill/assets/drift-report-template.md +27 -3
- package/src/skf-audit-skill/customize.toml +41 -20
- package/src/skf-audit-skill/references/constituent-freshness.md +91 -0
- package/src/skf-audit-skill/references/doc-drift.md +141 -0
- package/src/skf-audit-skill/references/headless-contract.md +29 -0
- package/src/skf-audit-skill/references/init.md +148 -210
- package/src/skf-audit-skill/references/re-index.md +96 -108
- package/src/skf-audit-skill/references/report.md +96 -33
- package/src/skf-audit-skill/references/semantic-diff.md +27 -18
- package/src/skf-audit-skill/references/severity-classify.md +79 -65
- package/src/skf-audit-skill/references/severity-rules.md +15 -6
- package/src/skf-audit-skill/references/structural-diff.md +75 -90
- package/src/skf-audit-skill/references/upstream-checkout.md +77 -0
- package/src/skf-audit-skill/scripts/render-drift-tables.py +685 -0
- package/src/skf-brief-skill/SKILL.md +36 -25
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/scope-templates.md +17 -24
- package/src/skf-brief-skill/assets/skill-brief-schema.md +29 -15
- package/src/skf-brief-skill/customize.toml +48 -20
- package/src/skf-brief-skill/references/analyze-target.md +142 -125
- package/src/skf-brief-skill/references/confirm-brief.md +10 -8
- package/src/skf-brief-skill/references/draft-checkpoint.md +36 -17
- package/src/skf-brief-skill/references/gather-intent-ratify.md +68 -0
- package/src/skf-brief-skill/references/gather-intent.md +87 -182
- package/src/skf-brief-skill/references/headless-args.md +84 -16
- package/src/skf-brief-skill/references/health-check.md +1 -1
- package/src/skf-brief-skill/references/invocation-contract.md +18 -13
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +1 -1
- package/src/skf-brief-skill/references/qmd-collection-registration.md +7 -10
- package/src/skf-brief-skill/references/scope-definition.md +123 -47
- package/src/skf-brief-skill/references/step-auto-brief.md +24 -80
- package/src/skf-brief-skill/references/step-auto-validate.md +20 -121
- package/src/skf-brief-skill/references/version-resolution.md +3 -2
- package/src/skf-brief-skill/references/write-brief.md +66 -57
- package/src/skf-campaign/SKILL.md +31 -34
- package/src/skf-campaign/assets/campaign-state-schema.json +25 -4
- package/src/skf-campaign/customize.toml +47 -16
- package/src/skf-campaign/references/campaign-contracts.md +39 -29
- package/src/skf-campaign/references/campaign-directive-spec.md +4 -2
- package/src/skf-campaign/references/health-check.md +7 -16
- package/src/skf-campaign/references/step-01-setup.md +46 -84
- package/src/skf-campaign/references/step-02-strategy.md +31 -30
- package/src/skf-campaign/references/step-03-pins.md +26 -18
- package/src/skf-campaign/references/step-04-provenance.md +24 -23
- package/src/skf-campaign/references/step-05-skill-loop.md +67 -48
- package/src/skf-campaign/references/step-06-batch.md +41 -34
- package/src/skf-campaign/references/step-07-capstone.md +40 -25
- package/src/skf-campaign/references/step-08-verify.md +28 -29
- package/src/skf-campaign/references/step-09-refine.md +29 -30
- package/src/skf-campaign/references/step-10-export.md +48 -36
- package/src/skf-campaign/references/step-11-maintenance.md +31 -34
- package/src/skf-campaign/references/step-resume.md +37 -68
- package/src/skf-campaign/scripts/campaign-deps.py +57 -18
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +361 -54
- package/src/skf-campaign/scripts/campaign-provenance.py +96 -53
- package/src/skf-campaign/scripts/campaign-quality-gate.py +592 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +257 -49
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +343 -50
- package/src/skf-campaign/scripts/campaign-report.py +204 -37
- package/src/skf-campaign/scripts/campaign-state.py +1128 -0
- package/src/skf-campaign/scripts/campaign-status.py +10 -74
- package/src/skf-campaign/scripts/campaign-validate-pins.py +30 -3
- package/src/skf-campaign/scripts/campaign-validate-state.py +34 -4
- package/src/skf-campaign/templates/campaign-brief-template.yaml +4 -5
- package/src/skf-campaign/templates/campaign-report-template.md +5 -1
- package/src/skf-campaign/templates/kickoff-template.md +0 -14
- package/src/skf-create-skill/SKILL.md +27 -20
- package/src/skf-create-skill/assets/compile-assembly-rules.md +6 -5
- package/src/skf-create-skill/assets/skill-sections.md +17 -6
- package/src/skf-create-skill/customize.toml +20 -8
- package/src/skf-create-skill/references/authoritative-files-protocol.md +41 -42
- package/src/skf-create-skill/references/batch-mode.md +81 -0
- package/src/skf-create-skill/references/ccc-index-check.md +27 -0
- package/src/skf-create-skill/references/compile.md +107 -29
- package/src/skf-create-skill/references/component-extraction.md +113 -91
- package/src/skf-create-skill/references/enrich.md +41 -23
- package/src/skf-create-skill/references/entry-points-by-hand.md +20 -0
- package/src/skf-create-skill/references/extract.md +200 -161
- package/src/skf-create-skill/references/extraction-patterns-by-hand.md +141 -0
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +2 -2
- package/src/skf-create-skill/references/extraction-patterns.md +584 -196
- package/src/skf-create-skill/references/generate-artifacts.md +145 -93
- package/src/skf-create-skill/references/health-check.md +1 -1
- package/src/skf-create-skill/references/load-brief.md +53 -36
- package/src/skf-create-skill/references/relabel-rule.md +12 -0
- package/src/skf-create-skill/references/report.md +28 -59
- package/src/skf-create-skill/references/source-resolution-protocols.md +49 -155
- package/src/skf-create-skill/references/step-auto-shard.md +20 -93
- package/src/skf-create-skill/references/step-doc-rot.md +44 -60
- package/src/skf-create-skill/references/step-doc-sources.md +55 -18
- package/src/skf-create-skill/references/sub/ccc-discover.md +18 -7
- package/src/skf-create-skill/references/sub/fetch-docs.md +106 -57
- package/src/skf-create-skill/references/sub/fetch-temporal.md +53 -166
- package/src/skf-create-skill/references/tier-degradation-rules.md +18 -9
- package/src/skf-create-skill/references/validate.md +173 -99
- package/src/skf-create-skill/scripts/scan-doc-rot.py +232 -99
- package/src/skf-create-stack-skill/SKILL.md +29 -56
- package/src/skf-create-stack-skill/assets/metadata-contract.md +51 -0
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +15 -15
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +23 -57
- package/src/skf-create-stack-skill/customize.toml +23 -12
- package/src/skf-create-stack-skill/references/compile-stack.md +57 -66
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +24 -44
- package/src/skf-create-stack-skill/references/detect-integrations.md +92 -95
- package/src/skf-create-stack-skill/references/detect-manifests.md +46 -71
- package/src/skf-create-stack-skill/references/generate-output.md +138 -128
- package/src/skf-create-stack-skill/references/init.md +90 -32
- package/src/skf-create-stack-skill/references/integration-patterns.md +1 -17
- package/src/skf-create-stack-skill/references/invocation-contract.md +34 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +32 -20
- package/src/skf-create-stack-skill/references/parallel-extract.md +112 -38
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +57 -75
- package/src/skf-create-stack-skill/references/report.md +39 -33
- package/src/skf-create-stack-skill/references/validate.md +20 -39
- package/src/skf-drop-skill/SKILL.md +28 -51
- package/src/skf-drop-skill/customize.toml +44 -30
- package/src/skf-drop-skill/references/execute.md +79 -146
- package/src/skf-drop-skill/references/invocation-contract.md +64 -0
- package/src/skf-drop-skill/references/report.md +46 -30
- package/src/skf-drop-skill/references/select.md +118 -124
- package/src/skf-drop-skill/scripts/dir-sizes.py +54 -26
- package/src/skf-drop-skill/scripts/drop-roster.py +322 -0
- package/src/skf-export-skill/SKILL.md +40 -62
- package/src/skf-export-skill/assets/managed-section-format.md +14 -50
- package/src/skf-export-skill/assets/snippet-format.md +3 -1
- package/src/skf-export-skill/customize.toml +42 -13
- package/src/skf-export-skill/references/generate-snippet.md +54 -46
- package/src/skf-export-skill/references/health-check.md +2 -0
- package/src/skf-export-skill/references/invocation-contract.md +15 -0
- package/src/skf-export-skill/references/load-skill.md +88 -62
- package/src/skf-export-skill/references/manifest-rebuild.md +9 -10
- package/src/skf-export-skill/references/multi-skill-mode.md +4 -4
- package/src/skf-export-skill/references/orphan-context-detection.md +13 -5
- package/src/skf-export-skill/references/orphan-row-detection.md +31 -22
- package/src/skf-export-skill/references/package.md +15 -73
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +51 -70
- package/src/skf-export-skill/references/result-envelope.md +31 -16
- package/src/skf-export-skill/references/summary.md +41 -17
- package/src/skf-export-skill/references/token-report.md +4 -12
- package/src/skf-export-skill/references/update-context.md +118 -237
- package/src/skf-forger/SKILL.md +61 -37
- package/src/skf-forger/bmad-skill-manifest.yaml +4 -1
- package/src/skf-forger/customize.toml +43 -0
- package/src/skf-forger/references/pipeline-mode.md +73 -18
- package/src/skf-forger/scripts/forge-status.py +299 -0
- package/src/skf-forger/scripts/parse-pipeline.py +322 -54
- package/src/skf-forger/scripts/pipeline-gate.py +428 -0
- package/src/skf-forger/scripts/pipeline-journal.py +1052 -0
- package/src/skf-quick-skill/SKILL.md +54 -53
- package/src/skf-quick-skill/assets/skill-template.md +4 -2
- package/src/skf-quick-skill/customize.toml +51 -20
- package/src/skf-quick-skill/references/batch-mode.md +74 -21
- package/src/skf-quick-skill/references/compile.md +30 -31
- package/src/skf-quick-skill/references/ecosystem-check.md +7 -57
- package/src/skf-quick-skill/references/finalize.md +69 -18
- package/src/skf-quick-skill/references/halt-contract.md +41 -29
- package/src/skf-quick-skill/references/health-check.md +5 -3
- package/src/skf-quick-skill/references/quick-extract.md +114 -45
- package/src/skf-quick-skill/references/registry-resolution.md +9 -64
- package/src/skf-quick-skill/references/resolve-target.md +116 -66
- package/src/skf-quick-skill/references/write-and-validate.md +79 -40
- package/src/skf-refine-architecture/SKILL.md +43 -53
- package/src/skf-refine-architecture/customize.toml +49 -20
- package/src/skf-refine-architecture/references/compile.md +97 -54
- package/src/skf-refine-architecture/references/exit-codes.md +30 -0
- package/src/skf-refine-architecture/references/finding-storage.md +21 -0
- package/src/skf-refine-architecture/references/gap-analysis.md +101 -38
- package/src/skf-refine-architecture/references/improvements.md +14 -20
- package/src/skf-refine-architecture/references/init.md +98 -57
- package/src/skf-refine-architecture/references/issue-detection.md +32 -39
- package/src/skf-refine-architecture/references/refinement-rules.md +37 -48
- package/src/skf-refine-architecture/references/report.md +65 -54
- package/src/skf-refine-architecture/scripts/skf-check-preservation.py +1619 -0
- package/src/skf-rename-skill/SKILL.md +19 -54
- package/src/skf-rename-skill/customize.toml +32 -26
- package/src/skf-rename-skill/references/execute.md +230 -184
- package/src/skf-rename-skill/references/exit-codes.md +7 -7
- package/src/skf-rename-skill/references/health-check.md +1 -7
- package/src/skf-rename-skill/references/invocation-contract.md +25 -0
- package/src/skf-rename-skill/references/report.md +63 -52
- package/src/skf-rename-skill/references/select.md +197 -115
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -21
- package/src/skf-setup/SKILL.md +26 -26
- package/src/skf-setup/customize.toml +14 -10
- package/src/skf-setup/references/auto-index.md +50 -63
- package/src/skf-setup/references/ccc-index.md +29 -89
- package/src/skf-setup/references/detect-and-tier.md +58 -66
- package/src/skf-setup/references/health-check.md +2 -0
- package/src/skf-setup/references/invocation-contract.md +14 -0
- package/src/skf-setup/references/report.md +43 -166
- package/src/skf-setup/references/tier-rules.md +5 -5
- package/src/skf-setup/references/write-config.md +34 -57
- package/src/skf-test-skill/SKILL.md +17 -57
- package/src/skf-test-skill/assets/output-section-formats.md +33 -34
- package/src/skf-test-skill/customize.toml +27 -13
- package/src/skf-test-skill/references/coherence-check.md +134 -62
- package/src/skf-test-skill/references/coverage-check-tiers.md +35 -0
- package/src/skf-test-skill/references/coverage-check.md +217 -254
- package/src/skf-test-skill/references/detect-mode.md +5 -5
- package/src/skf-test-skill/references/external-validators.md +94 -82
- package/src/skf-test-skill/references/health-check.md +6 -7
- package/src/skf-test-skill/references/init.md +163 -88
- package/src/skf-test-skill/references/invocation-contract.md +66 -0
- package/src/skf-test-skill/references/migration-section-rules.md +5 -2
- package/src/skf-test-skill/references/report.md +162 -142
- package/src/skf-test-skill/references/score.md +80 -107
- package/src/skf-test-skill/references/scoring-rules.md +41 -155
- package/src/skf-test-skill/references/source-access-protocol.md +19 -92
- package/src/skf-test-skill/references/step-hard-gate.md +51 -33
- package/src/skf-test-skill/scripts/aggregate-coherence.py +218 -30
- package/src/skf-test-skill/scripts/build-result-context.py +287 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +37 -4
- package/src/skf-test-skill/scripts/combine-external-scores.py +23 -6
- package/src/skf-test-skill/scripts/compute-score.py +223 -45
- package/src/skf-test-skill/scripts/gap-ledger.py +1381 -0
- package/src/skf-test-skill/scripts/hard-gate.py +203 -0
- package/src/skf-test-skill/scripts/load-coverage-inputs.py +760 -0
- package/src/skf-test-skill/scripts/locate-export-segments.py +835 -0
- package/src/skf-test-skill/scripts/reconcile-coverage.py +273 -79
- package/src/skf-test-skill/scripts/score-signatures.py +459 -0
- package/src/skf-test-skill/scripts/stage-helper-payload.py +148 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +311 -16
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +127 -52
- package/src/skf-test-skill/templates/test-report-template.md +21 -15
- package/src/skf-update-skill/SKILL.md +38 -25
- package/src/skf-update-skill/customize.toml +27 -12
- package/src/skf-update-skill/references/detect-changes.md +233 -222
- package/src/skf-update-skill/references/gap-driven.md +336 -0
- package/src/skf-update-skill/references/health-check.md +31 -5
- package/src/skf-update-skill/references/init.md +250 -84
- package/src/skf-update-skill/references/invocation-contract.md +12 -0
- package/src/skf-update-skill/references/manual-section-rules.md +6 -23
- package/src/skf-update-skill/references/merge.md +180 -47
- package/src/skf-update-skill/references/re-extract.md +53 -262
- package/src/skf-update-skill/references/report.md +100 -35
- package/src/skf-update-skill/references/write.md +331 -149
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +29 -7
- package/src/skf-verify-stack/SKILL.md +23 -42
- package/src/skf-verify-stack/assets/feasibility-report-template.md +11 -5
- package/src/skf-verify-stack/customize.toml +55 -22
- package/src/skf-verify-stack/references/coverage-patterns.md +17 -8
- package/src/skf-verify-stack/references/coverage.md +67 -64
- package/src/skf-verify-stack/references/exit-codes.md +21 -8
- package/src/skf-verify-stack/references/init.md +107 -62
- package/src/skf-verify-stack/references/integration-verification-rules.md +12 -13
- package/src/skf-verify-stack/references/integrations.md +106 -65
- package/src/skf-verify-stack/references/report.md +59 -42
- package/src/skf-verify-stack/references/requirements.md +32 -9
- package/src/skf-verify-stack/references/synthesize.md +53 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +398 -52
- package/src/skf-verify-stack/scripts/skf-previous-report.py +330 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +453 -49
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +240 -27
- package/tools/cli/commands/install.js +11 -4
- package/tools/cli/commands/status.js +15 -3
- package/tools/cli/commands/update.js +11 -4
- package/tools/cli/lib/tool-check.js +320 -0
- package/tools/cli/lib/version-check.js +22 -9
- package/tools/cli/skf-cli.js +4 -1
- package/.gitattributes +0 -16
- package/.nvmrc +0 -1
- package/docs/_internal/RELEASING.md +0 -645
- package/release-audits/v1.0.0-launch-audit.md +0 -728
- package/src/skf-audit-skill/references/step-doc-drift.md +0 -177
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +0 -26
- package/src/skf-campaign/manifest.yaml +0 -15
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +0 -106
- package/src/skf-create-skill/references/ecosystem-check.md +0 -74
- package/src/skf-drop-skill/references/headless-contract.md +0 -18
- package/src/skf-update-skill/references/merge-conflict-rules.md +0 -15
- package/src/skf-update-skill/references/remote-source-resolution.md +0 -98
- package/src/skf-update-skill/references/validate.md +0 -124
- package/tools/validate-docs-drift.js +0 -233
- package/tools/validate-docs-links.js +0 -665
|
@@ -9,10 +9,10 @@ Pipelines chain multiple SKF workflows in sequence. The forger orchestrates the
|
|
|
9
9
|
The forger recognizes pipeline invocations when the user provides multiple workflow codes:
|
|
10
10
|
|
|
11
11
|
```
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
QS[cocoindex] TS EX # space-separated codes, the first code's input in brackets
|
|
13
|
+
QS[cocoindex] -> TS -> EX # arrow-separated (equivalent)
|
|
14
|
+
AN[https://github.com/honojs/hono] CS TS EX # a project path in AN's bracket
|
|
15
|
+
QS[cocoindex] TS[min:80] EX # with circuit breaker threshold
|
|
16
16
|
```
|
|
17
17
|
|
|
18
18
|
The forger also accepts common pipeline aliases:
|
|
@@ -39,6 +39,8 @@ The forger also accepts common pipeline aliases:
|
|
|
39
39
|
|
|
40
40
|
## Pipeline Arguments
|
|
41
41
|
|
|
42
|
+
An alias takes its arguments after it, and they go, in order, to the inputs of the alias's first workflow: `forge-auto <repo-or-doc-url>` gives AN its `project_path`, `forge <repo-url-or-path> <skill-name>` gives BS its `target_repo` and `skill_name`, `forge-quick <package-or-url>` gives QS its `target`, and `maintain <skill>` gives AS its `skill_name`. The forger's `parse-pipeline.py` script binds them and returns them as `args`. A missing or left-over argument, a flag the pipeline does not take, or a `--pin` with no value stops the pipeline before any workflow runs.
|
|
43
|
+
|
|
42
44
|
Pipeline-level arguments (e.g., `--pin <version>`) are passed to the first workflow's data context. The workflow decides how to consume them. For the `forge-auto` pipeline, `--pin` flows to AN, where `step-auto-scope.md §0b` uses it for pin resolution.
|
|
43
45
|
|
|
44
46
|
## Data Flow
|
|
@@ -52,55 +54,117 @@ How outputs from one workflow become inputs to the next:
|
|
|
52
54
|
| BS | CS | `skill-brief.yaml` path | Forger passes the brief path written by BS as `brief_path` to CS |
|
|
53
55
|
| CS | TS | skill name (derived from brief) | Forger passes the `skill_name` from the completed CS to TS |
|
|
54
56
|
| CS | EX | skill name | Same — forger resolves the created skill's name |
|
|
55
|
-
| TS | EX | skill name +
|
|
57
|
+
| TS | EX | skill name + settled verdict | EX runs only when TS settled PASS (`next_workflow` is `export-skill`); FAIL, INCONCLUSIVE and pass-with-drift halt the pipeline before EX, with the verdict as the halt reason |
|
|
56
58
|
| QS | TS | skill name (from `repo_name`) | Forger passes the quick-skill's output name to TS |
|
|
57
59
|
| QS | EX | skill name | Same |
|
|
58
|
-
| AS | US | skill name + drift severity |
|
|
60
|
+
| AS | US | skill name + drift severity + route + upstream ref | The forger's gate reads the drift severity (`drift_score`) and the route (`next_workflow`) from the envelope AS printed. CLEAN skips US unless `next_workflow` is `update-skill`, which AS sets when upstream moved past the ref the skill was built from (`upstream_moved`). AS then hands on its `upstream_ref`: the gate prints it as `handoff.target_ref`, `pipeline-journal.py step --gate` records it, and US takes it as `--target-ref`, so the update reads the ref the audit found |
|
|
61
|
+
| US | TS | skill name | Forger passes the `skill_name` US updated to TS: the skill `maintain` names, or the one a repair updates |
|
|
59
62
|
| VS | RA | architecture doc path | Already known from VS invocation |
|
|
60
63
|
|
|
61
64
|
## Circuit Breakers
|
|
62
65
|
|
|
63
|
-
Circuit breakers halt the pipeline when a workflow's output doesn't meet a quality threshold
|
|
66
|
+
Circuit breakers halt the pipeline when a workflow's output doesn't meet a quality threshold. The forger's `pipeline-gate.py` script applies the AN, TS, AS and VS rows to the result envelope a workflow printed (a field name after a slash is its spelling in the workflow's result record) and answers continue, skip or halt with a reason; CS's row is a hard halt, which stops the pipeline by itself.
|
|
64
67
|
|
|
65
68
|
| Workflow | Check | Default Threshold | Halt Condition |
|
|
66
69
|
|----------|-------|-------------------|----------------|
|
|
67
|
-
| AN | recommended units count | min: 1 |
|
|
70
|
+
| AN | recommended units count (`unit_counts.confirmed`) | min: 1 | Fewer units than the minimum (by default, zero skillable units found) |
|
|
68
71
|
| CS | compilation success | must complete | Hard error during compilation |
|
|
69
|
-
| TS |
|
|
70
|
-
| AS | drift
|
|
71
|
-
| VS |
|
|
72
|
+
| TS | settled verdict (`verdict` / `summary.result`, with `next_workflow`) | TS's own: `TS[min:N]` reaches TS as `--threshold=N`, else the per-pipeline defaults apply (see init.md §1b) | Any verdict but PASS, reported as the halt reason: FAIL (including a FAIL that a post-score cap forced although the score clears the threshold), INCONCLUSIVE or pass-with-drift. TS owns its score, caps and 80% floor: a score between 80% and a higher threshold that TS settles as a fallback PASS with an evidence report continues |
|
|
73
|
+
| AS | drift severity (`drift_score` / `summary.severity`) with the route (`next_workflow` / `summary.next_workflow`) | not CRITICAL | CRITICAL drift found (CLEAN skips a US that comes next, unless `next_workflow` is `update-skill`: upstream moved, so the update still runs) |
|
|
74
|
+
| VS | coverage (`coverage_percentage` / `summary.coveragePercentage`) with the overall verdict (`overall_verdict` / `summary.overallVerdict`) | coverage above 0% | Zero coverage (`zero-coverage`): VS verified none of the architecture's technologies. Every verdict with coverage continues, NOT_FEASIBLE included, since RA takes each Blocked integration as a critical issue |
|
|
72
75
|
|
|
73
|
-
Override syntax: `TS[min:80]` sets the test-skill threshold to 80 for this pipeline run.
|
|
76
|
+
Override syntax: `TS[min:80]` sets the test-skill threshold to 80 for this pipeline run (the forger passes it to TS as `--threshold=80`), and `AN[min:2]` asks AN for at least two units.
|
|
74
77
|
|
|
75
78
|
### Bracket Syntax
|
|
76
79
|
|
|
77
80
|
Brackets after a workflow code (`CODE[value]`) are parsed as follows:
|
|
78
81
|
|
|
79
|
-
- **Circuit breaker override**: `min:N` where N is a number
|
|
82
|
+
- **Circuit breaker override**: `min:N` where N is a number, on AN or TS (the override syntax above), e.g. `TS[min:80]`
|
|
80
83
|
- **Mode flag**: `auto` — e.g., `AN[auto]` activates auto mode for that workflow. The workflow's first step reads the flag from pipeline data context and routes to the appropriate auto-mode step file.
|
|
81
84
|
- **Target argument**: any other value — e.g., `CS[cocoindex]` passes "cocoindex" as the target to CS
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
The keywords `min` and `auto` match in any case (`TS[MIN:80]`). A bracket that starts like `min` but is not `min:<number>` (`TS[min:80%]`, `TS[min=80]`) is malformed: the pipeline stops before any workflow runs rather than pass it on as a target.
|
|
87
|
+
|
|
88
|
+
Only AN (a unit count) and TS (a test threshold) take `min:N`. CS, AS and VS have circuit breakers with no number to set, so a `min:N` on them, as on any other code, is ignored, and the forger warns about it. Target arguments are valid for any workflow that accepts a named input (CS, QS, US, etc.). A bracket holds one value, so a chain led by BS gets its target and skill name only as `forge <repo-url-or-path> <skill-name>`, and RS and DS, which need more than one input, run on their own, outside a chain: `parse-pipeline.py` reports each as the chain's `first_input`.
|
|
84
89
|
|
|
85
90
|
## Pipeline State
|
|
86
91
|
|
|
87
|
-
The forger
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
The forger keeps a chain's state on disk, never only in the conversation, so a closed session, a killed terminal or a compacted context loses nothing. Its `scripts/pipeline-journal.py` writes the state, and nothing else does: a journal, `pipeline-journal.json`, in the run's own folder `{project-root}/_bmad-output/.skf-run/skf-forger-<run_id>/`, written when the chain starts, after every workflow, and when a resume picks the chain up again.
|
|
93
|
+
|
|
94
|
+
| Field | What it holds |
|
|
95
|
+
| --- | --- |
|
|
96
|
+
| `journal_version` | `1` |
|
|
97
|
+
| `run_id` | the UTC time the chain started and a random suffix (`20261001T120000Z-3f9a1c2e`), also the run folder's suffix |
|
|
98
|
+
| `status` | `running` from the start, `halted` once a step halted; a chain cut off mid-step stays `running` |
|
|
99
|
+
| `started_at`, `updated_at` | the UTC times of the journal's first and last write |
|
|
100
|
+
| `invocation` | the whole invocation the chain started from |
|
|
101
|
+
| `alias` | the pipeline alias name (`forge-auto`, `forge`, `forge-quick`, `maintain`), or null for an ad-hoc sequence |
|
|
102
|
+
| `args` | the first workflow's inputs, the parse's `args` (`project_path`, `pin` ...) |
|
|
103
|
+
| `steps` | one entry per workflow, in plan order |
|
|
104
|
+
| `data` | each value a workflow handed the next, by its Data Flow name (`skill_name`, `brief_path` ...); a name one call gave twice holds a list |
|
|
105
|
+
| `outputs` | each result or report path a workflow's envelope named, with its code |
|
|
106
|
+
| `history` | each halt a resume or repair picked up again: its code, reason, repair and time |
|
|
107
|
+
|
|
108
|
+
Each entry of `steps` has one shape, in the journal and in the pipeline result alike:
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{"code": "TS", "min": 90, "mode": null, "target": null, "flags": [], "status": "halted", "reason": "FAIL"}
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
`min`, `mode` and `target` are the plan's bracket values (Bracket Syntax), a resumed chain's first step also taking the journal's skill as its `target`, and `flags` the flags a repair adds (`--from-test-report`). `status` is `pending` (not run yet), `completed`, `skipped` (a gate passed over it) or `halted`, and `reason` is the gate's or the workflow's halt reason, a gate's reason for a skip, or null.
|
|
115
|
+
|
|
116
|
+
Every chained workflow's data context carries `pipeline_mode: true`, which marks pipeline context even for an ad-hoc sequence, and `pipeline_alias`, the journal's `alias`, which TS reads in init.md §1b for the per-pipeline threshold lookup.
|
|
117
|
+
|
|
118
|
+
## Pipeline Result
|
|
119
|
+
|
|
120
|
+
`pipeline-journal.py finish` writes each chain's result from its journal, per `output-contract-schema.md`: the per-run record `{sidecar_path}/pipeline-result-<YYYYMMDD-HHmmss>.json` (UTC; `-2`, `-3` ... when a run already took that second's name) and its copy `{sidecar_path}/pipeline-result-latest.json`, the file consumers read.
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"skill": "skf-forger",
|
|
125
|
+
"status": "partial",
|
|
126
|
+
"timestamp": "2026-10-01T12:31:07Z",
|
|
127
|
+
"run_id": "20261001T120000Z-3f9a1c2e",
|
|
128
|
+
"outputs": [{"type": "report", "path": "forge-data/hono/1.2.0/create-skill-result-latest.json"}],
|
|
129
|
+
"summary": {
|
|
130
|
+
"status": "partial",
|
|
131
|
+
"halt_reason": "FAIL",
|
|
132
|
+
"alias": "forge-auto",
|
|
133
|
+
"steps": [
|
|
134
|
+
{"code": "CS", "min": null, "mode": null, "target": null, "flags": [], "status": "completed", "reason": null},
|
|
135
|
+
{"code": "TS", "min": 90, "mode": null, "target": null, "flags": [], "status": "halted", "reason": "FAIL"}
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
"headless_decisions": [],
|
|
139
|
+
"warnings": []
|
|
140
|
+
}
|
|
102
141
|
```
|
|
103
142
|
|
|
143
|
+
`status` and `summary.status` are `success` when no step halted, `partial` when a step halted after another completed, and `failed` when one halted before any completed, or when the chain stopped before its journal started (at its parse, or a `start` that failed) or lost it: such a record lists no step. `summary.halt_reason` is the halted step's `reason`, null on success, and `summary.steps` lists every step of the plan in the Pipeline State shape, one that never ran as `pending` (the example shows two of five). `headless_decisions` stays empty, and `warnings` names what `finish` could not do: save or read the journal, or delete the run folder.
|
|
144
|
+
|
|
145
|
+
## Resume and Repair
|
|
146
|
+
|
|
147
|
+
At activation the forger runs `pipeline-journal.py resume`, which reads the newest journal a stopped chain left. It offers nothing when no journal is left, when a later chain recorded a result with a step in it (any pipeline result in the sidecar, the per-run records included: a record with no step, such as a parse halt's, supersedes nothing), or when the journal's skill was tested or exported after the journal's last write: a test result record or an export manifest entry, which WS reads too, dated after it. The manifest dates an export by its day only, so an export that same day counts when the manifest was written after the journal, whichever skill that write was for. Otherwise it offers one of two things:
|
|
148
|
+
|
|
149
|
+
- **Resume** after an interruption (the journal is still `running`) or a halt that is no quality verdict, such as a workflow that hard-halted or a result the gate could not read: the chain re-runs the step it stopped on, then the rest of the plan, with the recorded alias, bracket values and arguments.
|
|
150
|
+
- **Repair** after a quality halt: the repair the table below gives, then the chain picks up where the table says, still with the recorded alias and threshold.
|
|
151
|
+
|
|
152
|
+
`finish` prints the same next action when the chain stops, and both print it with its `route`, the next action in one line (`US hono --from-test-report, then TS EX at the recorded threshold of 90`), and its `user_action`, what the user does before the chain picks up again (null when the chain does it all). `pipeline-journal.py reopen` applies the offer the user accepts (the Resume procedure in the forger's pipeline-mode.md), and `discard` deletes a stopped chain's run folder, so its offer is made no more.
|
|
153
|
+
|
|
154
|
+
### Repair Routes
|
|
155
|
+
|
|
156
|
+
| Halted on | Reason | `repair` | `user_action` | The chain picks up at |
|
|
157
|
+
| --- | --- | --- | --- | --- |
|
|
158
|
+
| TS | `FAIL` | `update-from-test-report` | none: `US <skill> --from-test-report` joins the plan as the next step and fixes the gaps the test report lists | TS, at the recorded threshold |
|
|
159
|
+
| TS | `INCONCLUSIVE` | `add-evidence` | add evidence: install skill-check, or move up a tier (the tier's tools, then `SF`) | TS |
|
|
160
|
+
| TS | `pass-with-drift`, `workspace-drift` | `retest-at-pinned-commit` | put the source back at the commit the skill pins | TS, without `--allow-workspace-drift` |
|
|
161
|
+
| AS | `CRITICAL` | `review-drift-report` | review the drift report | the step after AS |
|
|
162
|
+
| VS | `zero-coverage` | `create-missing-skills` | create skills for the architecture's technologies (for example `forge-quick <package>`) | VS |
|
|
163
|
+
| AN | `no-skillable-units`, `units-below-min`, `skipped` | `new-target` | start a new chain with another target, or with a scope hint | no resume |
|
|
164
|
+
| AN | `redirect` | `update-existing-skill` | run `US` on the skill the target already has | no resume |
|
|
165
|
+
|
|
166
|
+
A halt with no resume leaves no journal behind: `finish` deletes its run folder, as it does after a chain that succeeded, and its `route` is `no resume:` and the `user_action`.
|
|
167
|
+
|
|
104
168
|
## Anti-Patterns
|
|
105
169
|
|
|
106
170
|
The forger validates the pipeline sequence and warns about:
|
|
@@ -112,3 +176,4 @@ The forger validates the pipeline sequence and warns about:
|
|
|
112
176
|
| CS without BS or AN | Compiling without brief | Need a brief — use QS for quick path, or AN for brownfield |
|
|
113
177
|
| TS after EX | Testing after export | Move TS before EX |
|
|
114
178
|
| Duplicate codes | Same workflow twice | Remove duplicate |
|
|
179
|
+
| `min:N` on a code other than AN or TS | Threshold ignored | Remove it, or put it on TS |
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Tessl Review
|
|
2
|
+
|
|
3
|
+
Tessl Review scores a skill on Tessl's servers. It runs deterministic validation checks and two AI judges, one for the frontmatter `description` (specificity, completeness, trigger-term quality, distinctiveness) and one for the body and the files beside it (conciseness, actionability, workflow clarity, progressive disclosure), and weighs them into one review score from 0 to 100, with suggestions. It reads the whole skill folder, so a skill whose Tier 2 sections moved to `references/` is judged with them.
|
|
4
|
+
|
|
5
|
+
create-skill (step 6 §6b) and test-skill (step 4b §3) run it through `skf-tessl-review.py`. No step file runs tessl itself, and neither workflow halts, asks the user anything or changes a file because of a review.
|
|
6
|
+
|
|
7
|
+
## When It Runs
|
|
8
|
+
|
|
9
|
+
The helper checks these conditions in order and stops at the first one that fails:
|
|
10
|
+
|
|
11
|
+
1. **Opt-in.** `tessl_review_workspace` in `{sidecar_path}/preferences.yaml` names one of the user's Tessl workspaces. A missing key, `~`, `false` or an empty value means off, the default in interactive and headless runs alike. Setting the key is the user's consent to upload the files listed below to that workspace.
|
|
12
|
+
2. **Installed.** `tessl` is on `PATH`, or its npm launcher is already in the npx cache. SKF never installs tessl.
|
|
13
|
+
3. **Signed in.** `tessl whoami` succeeds: the user ran `tessl login`, or `TESSL_TOKEN` is set for an unattended run.
|
|
14
|
+
|
|
15
|
+
The helper's `submit` then sends the copy as `tessl review run <copy> --workspace <tessl_review_workspace> --no-wait --json` and removes the copy once tessl answers with the review's run id, and its `collect` reads the review with `tessl review view <run id> --json`, the only tessl command it runs. A check that fails without an answer SKF can read, or does not answer in time, is tried again, since Tessl may still finish the review. Every tessl call runs with a temporary folder as its working directory, so tessl never reads or writes the user's project.
|
|
16
|
+
|
|
17
|
+
## What Is Uploaded
|
|
18
|
+
|
|
19
|
+
Only the files an agent loads from the skill: `SKILL.md` and the `references/`, `scripts/` and `assets/` folders, copied without links into a temporary folder named after the skill. `metadata.json`, `context-snippet.md` and the workspace artifacts create-skill stages beside them (`provenance-map.json`, `evidence-report.md`) stay on the machine. Tessl keeps each review in the workspace's review history.
|
|
20
|
+
|
|
21
|
+
create-skill reviews the staged skill, which holds no `scripts/` or `assets/` until step 7 copies them, so for a skill with scripts or assets its validation findings may name those paths as missing. test-skill reviews the finished package.
|
|
22
|
+
|
|
23
|
+
## Cost and Time
|
|
24
|
+
|
|
25
|
+
Each fresh review spends credits from the Tessl account's plan, and each workflow run with the review on can spend one. Re-reviewing a skill folder Tessl has already reviewed can return Tessl's cached result without spending credits. A review takes Tessl about two minutes, and no helper call waits for all of it, so every call ends within two minutes, inside a shell tool's default time limit: `submit` returns as soon as Tessl has accepted the review, and each `collect` checks it for up to 90 seconds, then returns `pending` again or the result. The calling step collects at most six times, about ten minutes in all, and its sixth call passes `--final`, which turns a review still running into `timeout`.
|
|
26
|
+
|
|
27
|
+
## Results
|
|
28
|
+
|
|
29
|
+
The helper prints one JSON object whose keys are always present. Both workflows record its `summary` as the line `Tessl Review: {summary}`:
|
|
30
|
+
|
|
31
|
+
| `status` | Summary starts with | Meaning |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `reviewed` | `reviewed — score` | Tessl finished. The scores, validation findings and suggestions are filled in. |
|
|
34
|
+
| `pending` | `no result yet — Tessl Review run` | Tessl accepted the review and SKF has not seen it finish. The calling step collects it again until its sixth `collect`, which reports `timeout` instead. |
|
|
35
|
+
| `off` | `off —` | `tessl_review_workspace` is not set. |
|
|
36
|
+
| `invalid-config` | `not run — tessl_review_workspace must be` | The key holds something that is not a workspace name of letters, digits, `.`, `_` and `-`. |
|
|
37
|
+
| `not-installed` | `not run — tessl is not installed` | Neither `tessl` nor a cached npm launcher was found. |
|
|
38
|
+
| `signed-out` | `not run — not signed in to Tessl` | `tessl whoami` or the review reported that the user is not signed in. |
|
|
39
|
+
| `command-unavailable` | `not run — the installed tessl has no working review run command` | The installed tessl lacks or replaced `tessl review run`. |
|
|
40
|
+
| `unknown-run` | `no result — Tessl has no review run` | `tessl review view` found no review with the run id `collect` was given, or that id is not a Tessl run id. |
|
|
41
|
+
| `timeout` | `no result — Tessl Review run` | SKF had not seen the review finish when the sixth `collect` ended: Tessl was still working, or its last checks failed or did not answer. The review may still complete in the workspace (`tessl review view <run id>`). |
|
|
42
|
+
| `failed` | `failed —` | tessl's own message, for example about the workspace, or a skill file the helper could not read, or a tessl call that did not answer in time. The steps record `failed — stopped before skf-tessl-review.py reported a result` when the shell tool stopped a helper call, and keep the run id when Tessl had accepted the review. |
|
|
43
|
+
| `parse-failure` | `failed — Tessl Review output could not be read` | tessl printed no review SKF can read. |
|
|
44
|
+
|
|
45
|
+
Only `reviewed` produces a score. For every other status the scores are null, and test-skill then scores External Validation from skill-check alone.
|
|
46
|
+
|
|
47
|
+
## Floors
|
|
48
|
+
|
|
49
|
+
The helper adds a warning for each of the review, description and content scores that is below 60%, and one when validation reports errors. For every status other than `reviewed` and `off` it adds the summary itself as a warning, so a review that was switched on but produced no score shows in the run's warnings. Warnings never fail a run.
|
|
50
|
+
|
|
51
|
+
## Suggestions
|
|
52
|
+
|
|
53
|
+
SKF never applies a Tessl suggestion. Content suggestions would add text SKF cannot cite to source, and the description is compiled from the brief, so a description suggestion is acted on by editing the brief and re-running create-skill. Both workflows list the suggestions as advice and mark each content suggestion that a rule below matches with `(not applicable: <rule-id>)`, because following it would break SKF's design. The judges do not know that design, so lower conciseness and progressive-disclosure scores are expected on SKF skills.
|
|
54
|
+
|
|
55
|
+
### Rule: `keep-manual-markers`
|
|
56
|
+
|
|
57
|
+
- **Matches:** removing, cleaning up or replacing `<!-- [MANUAL] -->` markers, including empty MANUAL placeholder blocks.
|
|
58
|
+
- **Why:** update-skill keeps the content an author writes between these markers when it regenerates the skill.
|
|
59
|
+
|
|
60
|
+
### Rule: `keep-tier2-inline`
|
|
61
|
+
|
|
62
|
+
- **Matches:** moving a `## Full …` section (API reference, type definitions, integration patterns) into a separate file while the body is within the size limit.
|
|
63
|
+
- **Why:** create-skill step 6 §4 moves Tier 2 sections to `references/` only when the body is over the limit, because inline context serves agents better than on-demand retrieval.
|
|
64
|
+
|
|
65
|
+
### Rule: `keep-both-tiers`
|
|
66
|
+
|
|
67
|
+
- **Matches:** merging the Key API Summary or Quick Start into the Full API Reference, or removing parameters that both list.
|
|
68
|
+
- **Why:** Tier 1 lists the key parameters so an agent finds them at once, and Tier 2 holds the complete tables. That is progressive disclosure, not duplication.
|
|
69
|
+
|
|
70
|
+
### Rule: `keep-provenance`
|
|
71
|
+
|
|
72
|
+
- **Matches:** removing, shortening or moving `[SRC:…]`, `[AST:…]`, `[QMD:…]` or `[EXT:…]` citations.
|
|
73
|
+
- **Why:** every claim carries its source, so update-skill can detect drift and audit-skill can verify the claim.
|
|
74
|
+
|
|
75
|
+
## Evolving These Rules
|
|
76
|
+
|
|
77
|
+
Add a rule when a Tessl suggestion keeps coming back that would break an SKF design principle, and name that principle in its **Why** line; a rule that protects no principle is a smell. Change the floor in the helper and here together.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://github.com/armelhbobdad/bmad-module-skill-forge/src/shared/scripts/schemas/skf-analyze-result-envelope.v1.json",
|
|
4
|
+
"title": "SKF_ANALYZE_RESULT_JSON envelope (v1)",
|
|
5
|
+
"description": "Single-line JSON document skf-analyze-source prints, prefixed with the literal 'SKF_ANALYZE_RESULT_JSON: ': on stdout when a run ends (briefs written, zero units confirmed, a coexistence redirect or skip), and on stderr at every HARD HALT of a headless run. The shared emitter builds each line from the payload a step stages, so pipelines branch on status, halt_reason and unit_counts without parsing the human-readable report. src/skf-analyze-source/references/headless-contract.md describes each field.",
|
|
6
|
+
"$defs": {
|
|
7
|
+
"skf-envelope": {
|
|
8
|
+
"description": "The shared emitter's settings for this workflow, read by skf-emit-result-envelope.py: the workflow, the line's prefix, the status a halt carries, the exit code of each halt_reason and the result file stem. Nothing in the schema references this entry, so it constrains no envelope.",
|
|
9
|
+
"const": {
|
|
10
|
+
"workflow": "skf-analyze-source",
|
|
11
|
+
"prefix": "SKF_ANALYZE_RESULT_JSON",
|
|
12
|
+
"wrapper": null,
|
|
13
|
+
"halt_status": "error",
|
|
14
|
+
"exit_codes": {
|
|
15
|
+
"input-missing": 2,
|
|
16
|
+
"resolution-failure": 3,
|
|
17
|
+
"pin-invalid": 3,
|
|
18
|
+
"write-failed": 4,
|
|
19
|
+
"user-cancelled": 6
|
|
20
|
+
},
|
|
21
|
+
"success_exit_code": 0,
|
|
22
|
+
"result_file": "analyze-source-result"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"type": "object",
|
|
27
|
+
"additionalProperties": false,
|
|
28
|
+
"required": ["status", "report_path", "brief_paths", "unit_counts", "exit_code", "halt_reason", "mode", "result_path"],
|
|
29
|
+
"properties": {
|
|
30
|
+
"status": {
|
|
31
|
+
"type": "string",
|
|
32
|
+
"enum": ["success", "error", "redirect", "skipped"],
|
|
33
|
+
"description": "'success' when a run ends with its briefs written, or with none because no unit was confirmed. 'redirect' when the auto coexistence gate routes the target to an update of an existing skill ([M]erge). 'skipped' when it skips the target ([S]kip). 'error' at every HARD HALT."
|
|
34
|
+
},
|
|
35
|
+
"report_path": {
|
|
36
|
+
"type": ["string", "null"],
|
|
37
|
+
"minLength": 1,
|
|
38
|
+
"default": null,
|
|
39
|
+
"description": "Absolute path of the analysis report. Null on a redirect, a skip and a HALT before the report was written."
|
|
40
|
+
},
|
|
41
|
+
"brief_paths": {
|
|
42
|
+
"type": "array",
|
|
43
|
+
"items": { "type": "string", "minLength": 1 },
|
|
44
|
+
"default": [],
|
|
45
|
+
"description": "Absolute path of every skill-brief.yaml the run wrote. A brief is written only after it passed the brief writer and, outside the docs-only branch, the schema gate. Empty when no unit was confirmed, when the user chose not to write the briefs, and on a redirect, a skip and a HALT."
|
|
46
|
+
},
|
|
47
|
+
"unit_counts": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"additionalProperties": false,
|
|
50
|
+
"required": ["confirmed", "skipped", "maybe"],
|
|
51
|
+
"properties": {
|
|
52
|
+
"confirmed": {
|
|
53
|
+
"type": "integer",
|
|
54
|
+
"minimum": 0,
|
|
55
|
+
"description": "Units approved for a brief (step 5, or the units step 1a confirmed)."
|
|
56
|
+
},
|
|
57
|
+
"skipped": {
|
|
58
|
+
"type": "integer",
|
|
59
|
+
"minimum": 0,
|
|
60
|
+
"description": "Units rejected in step 5, or 1 for the target a coexistence [S]kip passed over."
|
|
61
|
+
},
|
|
62
|
+
"maybe": { "type": "integer", "minimum": 0, "description": "Reserved, always 0." }
|
|
63
|
+
},
|
|
64
|
+
"default": { "confirmed": 0, "skipped": 0, "maybe": 0 },
|
|
65
|
+
"description": "The unit counts. A run that confirms no unit reports confirmed 0, which the forger's AN circuit breaker reads as no skillable unit."
|
|
66
|
+
},
|
|
67
|
+
"exit_code": {
|
|
68
|
+
"type": "integer",
|
|
69
|
+
"enum": [0, 2, 3, 4, 6],
|
|
70
|
+
"description": "Process exit code, derived from halt_reason: null gives 0 (success, redirect and skipped), input-missing 2, resolution-failure and pin-invalid 3, write-failed 4, user-cancelled 6."
|
|
71
|
+
},
|
|
72
|
+
"halt_reason": {
|
|
73
|
+
"type": ["string", "null"],
|
|
74
|
+
"enum": [null, "input-missing", "resolution-failure", "pin-invalid", "write-failed", "user-cancelled"],
|
|
75
|
+
"description": "Null unless the run halted. One of the documented HALT classes on error; write-failed also covers a brief the writer or the schema gate rejects."
|
|
76
|
+
},
|
|
77
|
+
"mode": {
|
|
78
|
+
"type": "string",
|
|
79
|
+
"enum": ["interactive", "auto"],
|
|
80
|
+
"default": "interactive",
|
|
81
|
+
"description": "'auto' when the invocation carries [auto], from activation through step 1a and its docs-only branch; 'interactive' otherwise, also in the step-by-step chain an [auto] run falls back to when shape detection cannot classify the repository."
|
|
82
|
+
},
|
|
83
|
+
"result_path": {
|
|
84
|
+
"type": ["string", "null"],
|
|
85
|
+
"description": "The per-run result file the emitter wrote, {forge_data_folder}/analyze-source-result-<YYYYMMDD-HHmmss>.json (UTC), beside its analyze-source-result-latest.json copy. Stamped by the emitter, never typed. Null for a HALT, which writes no result file, and when the write failed (warnings say why)."
|
|
86
|
+
},
|
|
87
|
+
"error": {
|
|
88
|
+
"oneOf": [
|
|
89
|
+
{ "type": "null" },
|
|
90
|
+
{
|
|
91
|
+
"type": "object",
|
|
92
|
+
"additionalProperties": false,
|
|
93
|
+
"required": ["phase", "reason"],
|
|
94
|
+
"properties": {
|
|
95
|
+
"phase": { "type": "string", "minLength": 1, "description": "The step and section that halted, such as 'step-auto-scope:8'." },
|
|
96
|
+
"reason": { "type": "string", "minLength": 1, "description": "The halt's one-line message." },
|
|
97
|
+
"path": { "type": "string", "description": "The file or folder the failed operation targeted, when the halt names one." }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"description": "Optional. On a HALT, the step that halted and its message; absent when the run ended."
|
|
102
|
+
},
|
|
103
|
+
"coexistence": {
|
|
104
|
+
"type": "string",
|
|
105
|
+
"enum": ["alongside", "merge", "skip"],
|
|
106
|
+
"description": "Optional, auto mode only: the coexistence decision of step 1a section 0c when a skill already matched the target ('alongside' writes a -wiki skill beside it)."
|
|
107
|
+
},
|
|
108
|
+
"pinned_ref": {
|
|
109
|
+
"type": "string",
|
|
110
|
+
"minLength": 1,
|
|
111
|
+
"description": "Optional, auto mode only: the git ref the run pinned (the --pin value, or the latest release tag). Absent when no pin resolved."
|
|
112
|
+
},
|
|
113
|
+
"pinned_version": {
|
|
114
|
+
"type": "string",
|
|
115
|
+
"minLength": 1,
|
|
116
|
+
"description": "Optional, auto mode only: the version of pinned_ref. Absent when no pin resolved, and for a pin with no version (a branch, or a latest release whose tag is not a version)."
|
|
117
|
+
},
|
|
118
|
+
"source_type": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"enum": ["docs-only"],
|
|
121
|
+
"description": "Optional: 'docs-only' when the target was a documentation URL, so brief-skill skips repo-based enrichment."
|
|
122
|
+
},
|
|
123
|
+
"redirect_to": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"enum": ["US"],
|
|
126
|
+
"description": "Optional, on a redirect only: the workflow the forger routes to (update-skill)."
|
|
127
|
+
},
|
|
128
|
+
"skill_name": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"minLength": 1,
|
|
131
|
+
"description": "Optional, on a redirect only: the existing skill to update."
|
|
132
|
+
},
|
|
133
|
+
"skill_path": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"minLength": 1,
|
|
136
|
+
"description": "Optional, on a redirect only: the existing skill's active version folder."
|
|
137
|
+
},
|
|
138
|
+
"skipped_reason": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"minLength": 1,
|
|
141
|
+
"description": "Optional, on a skip only: why the target was skipped."
|
|
142
|
+
},
|
|
143
|
+
"headless_decisions": {
|
|
144
|
+
"type": "array",
|
|
145
|
+
"items": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"additionalProperties": false,
|
|
148
|
+
"required": ["gate", "default_action", "taken_action", "reason"],
|
|
149
|
+
"properties": {
|
|
150
|
+
"gate": {
|
|
151
|
+
"type": "string",
|
|
152
|
+
"enum": [
|
|
153
|
+
"auto-scope.cohesion",
|
|
154
|
+
"auto-scope.language",
|
|
155
|
+
"auto-scope.shape",
|
|
156
|
+
"scan-project.scan",
|
|
157
|
+
"identify-units.classifications",
|
|
158
|
+
"map-and-detect.findings",
|
|
159
|
+
"recommend.recommendations",
|
|
160
|
+
"generate-briefs.write"
|
|
161
|
+
],
|
|
162
|
+
"description": "The decision the run took with no one to ask. Step 1a: section 3b's merge-or-split decision for a monorepo, section 4's choice between an app and a library when the only app signal is a framework dependency or between a language and its user when the repository depends on a parser library, and section 5's choice of the documented language when the language helper found more than one. A headless run of the step-by-step chain: the default of each step's gate (continue past the scan, accept the unit classifications, accept every composite merge, confirm every recommendation and flag every stack skill candidate, write the briefs)."
|
|
163
|
+
},
|
|
164
|
+
"default_action": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"minLength": 1,
|
|
167
|
+
"description": "The documented default: 'merge' for the cohesion check, 'reference-app' for the app-or-library choice, the shape the run judged from for the language-or-user choice (after the app-or-library choice when both hold), the helper's first language for the language choice, the menu option a step-by-step gate takes ('C', or 'Y' to write the briefs)."
|
|
168
|
+
},
|
|
169
|
+
"taken_action": {
|
|
170
|
+
"type": "string",
|
|
171
|
+
"minLength": 1,
|
|
172
|
+
"description": "What the run decided: 'merge' or 'split', 'reference-app' or 'library-API', the shape judged from or 'language-reference', the language the brief records, or the option a headless gate took."
|
|
173
|
+
},
|
|
174
|
+
"reason": {
|
|
175
|
+
"type": "string",
|
|
176
|
+
"minLength": 1,
|
|
177
|
+
"description": "One line on why, such as the cohesion trigger that held."
|
|
178
|
+
},
|
|
179
|
+
"evidence": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"additionalProperties": true,
|
|
182
|
+
"description": "Optional decision data: the package count and the members, the languages the helper listed, or what a step-by-step gate accepted (the composites, the confirmed units, the briefs)."
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
},
|
|
186
|
+
"description": "Optional. Each auto-decision the run recorded in its sink the moment it decided, so a halt still reports the decisions taken before it. Present only when there is at least one."
|
|
187
|
+
},
|
|
188
|
+
"warnings": {
|
|
189
|
+
"type": "array",
|
|
190
|
+
"items": { "type": "string", "minLength": 1 },
|
|
191
|
+
"description": "Optional. Non-fatal anomalies the run recorded in its sink or the emitter raised, one string each (for example result_file_write_failed). Present only when there is at least one."
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|