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
|
@@ -1,7 +1,31 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'recommend.md'
|
|
3
3
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
4
|
-
heuristicsFile: '
|
|
4
|
+
heuristicsFile: 'references/unit-detection-heuristics.md'
|
|
5
|
+
discoverFile: 'references/discover-additional-source.md'
|
|
6
|
+
unitExportsFile: 'references/map-unit-exports.md'
|
|
7
|
+
scanRootFile: 'references/scan-root.md'
|
|
8
|
+
extractPublicApiProbeOrder:
|
|
9
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-extract-public-api.py'
|
|
10
|
+
- '{project-root}/src/shared/scripts/skf-extract-public-api.py'
|
|
11
|
+
scanManifestsProbeOrder:
|
|
12
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-scan-manifests.py'
|
|
13
|
+
- '{project-root}/src/shared/scripts/skf-scan-manifests.py'
|
|
14
|
+
countImportsProbeOrder:
|
|
15
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-count-imports.py'
|
|
16
|
+
- '{project-root}/src/shared/scripts/skf-count-imports.py'
|
|
17
|
+
findCyclesProbeOrder:
|
|
18
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-find-cycles.py'
|
|
19
|
+
- '{project-root}/src/shared/scripts/skf-find-cycles.py'
|
|
20
|
+
pairIntersectProbeOrder:
|
|
21
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-pair-intersect.py'
|
|
22
|
+
- '{project-root}/src/shared/scripts/skf-pair-intersect.py'
|
|
23
|
+
skillInventoryProbeOrder:
|
|
24
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
25
|
+
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
26
|
+
checkUnitRecordsProbeOrder:
|
|
27
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-check-unit-records.py'
|
|
28
|
+
- '{project-root}/src/shared/scripts/skf-check-unit-records.py'
|
|
5
29
|
---
|
|
6
30
|
|
|
7
31
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -10,22 +34,31 @@ heuristicsFile: '{unitDetectionHeuristicsPath}'
|
|
|
10
34
|
|
|
11
35
|
## STEP GOAL:
|
|
12
36
|
|
|
13
|
-
To analyze each qualifying unit's export surface and import graph, detect cross-unit integration points, and flag potential stack skill candidates
|
|
37
|
+
To analyze each qualifying unit's export surface and import graph, detect cross-unit integration points, propose composite merges and flag potential stack skill candidates, completing the analysis foundation needed for recommendations.
|
|
14
38
|
|
|
15
39
|
## Rules
|
|
16
40
|
|
|
17
41
|
- Delegate per-unit deep analysis to a subagent when available (parallelizes across units; main-thread fallback is fine)
|
|
18
42
|
- For each qualifying unit, perform thorough export surface analysis — do not shortcut
|
|
19
43
|
- Do not make recommendations (Step 05)
|
|
20
|
-
- Tier-aware depth: Quick (file-level), Forge (AST), Deep (AST + semantic)
|
|
21
44
|
|
|
22
45
|
## MANDATORY SEQUENCE
|
|
23
46
|
|
|
47
|
+
Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one, then run
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
|
|
54
|
+
|
|
24
55
|
### 1. Load Context
|
|
25
56
|
|
|
26
57
|
Read {outputFile} to obtain:
|
|
27
|
-
- Qualifying units from Identified Units section
|
|
28
|
-
- `forge_tier` from frontmatter
|
|
58
|
+
- Qualifying units from the Identified Units section: names, project paths, paths, scope types, languages, file counts, statuses and each unit's own manifest (path, name and ecosystem). A unit whose status is `deferred` (outside the goal the user stated) stays in the report and is not analyzed here
|
|
59
|
+
- `forge_tier`, `scan_roots` (each project path's scan root) and `refs` from frontmatter
|
|
60
|
+
|
|
61
|
+
**A scan root that is gone.** A session that resumed this report runs in a new run folder, and the folder of the session that made a copy may be gone. When a recorded scan root no longer exists, make it again by {scanRootFile} into this run's `{run_dir}/source-{i}` and update `scan_roots` in {outputFile}'s frontmatter. If a command there fails, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:1`, path `{path}`): "{path} could not be fetched: {the first stderr line}."
|
|
29
62
|
|
|
30
63
|
Load {heuristicsFile} for stack skill candidate detection rules.
|
|
31
64
|
|
|
@@ -33,91 +66,65 @@ Load {heuristicsFile} for stack skill candidate detection rules.
|
|
|
33
66
|
|
|
34
67
|
For each qualifying unit, delegate deep analysis to a subagent so per-unit work runs in parallel and the parent's context stays clean.
|
|
35
68
|
|
|
69
|
+
**Resolve `{extractPublicApiHelper}`** from `{extractPublicApiProbeOrder}` and **`{checkUnitRecordsHelper}`** from `{checkUnitRecordsProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:2`): "`{the missing script}` is missing. Re-install SKF."
|
|
70
|
+
|
|
36
71
|
**Subagent fan-out protocol:**
|
|
37
72
|
|
|
38
|
-
1. **Build the qualifying-unit list.** Read the unit list produced upstream (
|
|
39
|
-
|
|
40
|
-
2. **Delegate per-unit deep analysis to a subagent.** For each qualifying unit, launch a subagent task with these explicit constraints:
|
|
41
|
-
- The subagent reads only that unit's directory tree
|
|
42
|
-
- The subagent analyzes exports / usage / CCC signals / scripts+assets for that one unit
|
|
43
|
-
- **The parent does not read the unit's source files before delegating** (avoid the implicit-read trap — the whole point of fan-out is to keep large source bodies out of the parent's context)
|
|
44
|
-
|
|
45
|
-
3. **Per-unit analysis the subagent performs (scaled by size-aware strategy):**
|
|
46
|
-
|
|
47
|
-
**Size-aware strategy selection:**
|
|
48
|
-
- **< 50 files:** Full export scan — analyze every file for exports
|
|
49
|
-
- **50-200 files:** Targeted scan — entry points (`__init__.py`, `index.ts`, `lib.rs`) + public modules + barrel exports only
|
|
50
|
-
- **200+ files:** Entry-point strategy — analyze top-level entry point for public API surface, list submodule entry points, analyze each submodule entry point only. Report coverage confidence based on percentage of files analyzed.
|
|
51
|
-
|
|
52
|
-
**Tier-aware depth:**
|
|
53
|
-
- **Quick tier:** Count files by type, identify index/barrel files, list directory structure
|
|
54
|
-
- **Forge tier:** Parse export statements, identify public API surface, count exported functions/classes/types
|
|
55
|
-
- **Forge+ tier:** All Forge analysis plus:
|
|
56
|
-
- If `tools.ccc` is true: run `ccc_bridge.search("{unit_name} exports public API", top_k=15)` to discover semantically relevant files beyond directory scan. Tool resolution: prefer the `/ccc` skill search (Claude Code) or ccc MCP server (Cursor); fall back to the `ccc search` CLI if neither is available; if no ccc tool resolves, skip CCC discovery and record `ccc: unavailable` in per-unit findings.
|
|
57
|
-
- Merge CCC-discovered files with scoped file list — files from CCC that are within the unit's directory are added to the analysis queue
|
|
58
|
-
- Record CCC signals in per-unit findings: top 3 CCC-ranked file names (or "—" if no ccc results)
|
|
59
|
-
- **Deep tier:** All Forge analysis plus:
|
|
60
|
-
- ast-grep structural export extraction: `ast-grep -p 'export $$$' --lang typescript` or equivalent per language to build a verified export inventory
|
|
61
|
-
- ast-grep type/interface mapping: `ast-grep -p 'interface $NAME' --lang typescript` or `ast-grep -p 'class $NAME($$$)' --lang python`
|
|
62
|
-
- If QMD available: query for temporal evolution of identified exports (deprecation signals, recent additions, refactoring patterns)
|
|
63
|
-
- Record semantic relationships between exports (which exports reference/depend on each other)
|
|
64
|
-
|
|
65
|
-
**Subagent must also record:**
|
|
66
|
-
- Script/asset presence: check for `scripts/`, `bin/`, `assets/`, `templates/` directories and files matching detection signals in `{heuristicsFile}`
|
|
67
|
-
- Analysis strategy used and coverage confidence
|
|
68
|
-
|
|
69
|
-
4. **Subagent return contract.** Each subagent returns only this JSON object — no prose, no commentary, no markdown fences:
|
|
70
|
-
|
|
71
|
-
```json
|
|
72
|
-
{
|
|
73
|
-
"unit_name": "...",
|
|
74
|
-
"files_count": N,
|
|
75
|
-
"exports_count": N,
|
|
76
|
-
"export_pattern": "...",
|
|
77
|
-
"api_surface": ["..."],
|
|
78
|
-
"scripts_assets": {"scripts": [], "assets": []},
|
|
79
|
-
"ccc_signals": {"top_files": [], "available": <bool>},
|
|
80
|
-
"strategy_used": "ast-grep|regex|main-thread",
|
|
81
|
-
"confidence": "T1|T2|T1-low"
|
|
82
|
-
}
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
5. **Parent post-processing.** Strip any wrapping markdown fences (subagents sometimes wrap JSON in ` ```json … ``` ` despite the contract) before parsing. Validate each payload against the contract; if a key is missing, log a warning to `workflow_warnings[]` and continue with that unit's degraded record.
|
|
86
|
-
|
|
87
|
-
6. **Aggregate.** Collect all per-unit JSON payloads into `per_unit_findings[]` in workflow context for use by §3 (import graph), §4 (integration points), §5 (stack candidates), §6 (findings presentation), and downstream stages (recommend.md, generate-briefs.md).
|
|
73
|
+
1. **Build the qualifying-unit list.** Read the unit list produced upstream (names, project paths, paths, scope types, languages, file counts), leaving out the deferred units. Do not re-scan the project here.
|
|
88
74
|
|
|
89
|
-
**
|
|
75
|
+
2. **Map each unit's exports.** Load, read the entire file, then execute {unitExportsFile} for the qualifying units: it delegates each one to a subagent with `{unit_root}` its path under the scan root of its project path and its file count from Identified Units, has the subagent write the unit's record to `{run_dir}/unit-records/{unit_name}.json`, checks the records and returns them.
|
|
90
76
|
|
|
91
|
-
|
|
92
|
-
|------|-------|---------|----------------|-------------|----------------|-------------|
|
|
93
|
-
| {name} | {count} | {count} | {pattern} | {small/medium/large} | {N scripts, M assets or --} | {CCC signals or --} |
|
|
77
|
+
3. **Aggregate.** Collect the checked `records` into `per_unit_findings[]` in workflow context for use by §3 (import graph), §4 (integration points), §5 (composites and stack candidates), §6 (findings presentation), and downstream stages (recommend.md, generate-briefs.md).
|
|
94
78
|
|
|
95
|
-
**
|
|
79
|
+
**Per-unit export summary (built from `per_unit_findings[]`):**
|
|
80
|
+
|
|
81
|
+
| Unit | Files | Exports | Export Pattern | API Surface | CCC Signals |
|
|
82
|
+
|------|-------|---------|----------------|-------------|-------------|
|
|
83
|
+
| {name} | {count} | {count} | {pattern} | {small/medium/large} | {CCC signals or --} |
|
|
96
84
|
|
|
97
85
|
### 3. Map Import Graph
|
|
98
86
|
|
|
99
|
-
|
|
87
|
+
Which unit imports which, how many files import each unit, which units are imported together and which import each other in a cycle each have one right answer per tree, so the helpers compute them and this section reads their output.
|
|
88
|
+
|
|
89
|
+
**Resolve `{scanManifestsHelper}`, `{countImportsHelper}`, `{findCyclesHelper}` and `{pairIntersectHelper}`** from their probe orders; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:3`): "`{the missing script}` is missing. Re-install SKF."
|
|
90
|
+
|
|
91
|
+
**Units JSON.** One entry per qualifying unit, from its Identified Units row: `{"name": "<unit name>", "path": "<its path, relative to the source root>", "manifest_name": "<its own manifest's name>", "ecosystem": "<its own manifest's ecosystem>"}`, with `manifest_name` and `ecosystem` left out for a unit without a manifest. The import helper works out the names other code imports each unit by from what the unit declares. Add `"modules"` only for a folder without a manifest that code imports by name: a Python package folder (`["acme"]`) or a Go package inside a module (`["example.com/svc/internal/auth"]`).
|
|
92
|
+
|
|
93
|
+
Run this once per project path, the `{i}`-th entry of `project_paths[]`, with `{source_root}` its scan root, over the units under it. `{run_dir}/manifests-{i}.json` is the manifest scan scan-project wrote; when it is missing, as in a session that resumed the report, run `uv run {scanManifestsHelper} scan "{source_root}" > "{run_dir}/manifests-{i}.json"` first.
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
cat > "{run_dir}/units-{i}.json" <<'SKF_UNITS'
|
|
97
|
+
{"units": [<one entry per qualifying unit under {source_root}>]}
|
|
98
|
+
SKF_UNITS
|
|
99
|
+
uv run {countImportsHelper} count "{source_root}" --units "{run_dir}/units-{i}.json" --deps "{run_dir}/manifests-{i}.json" > "{run_dir}/imports-{i}.json"
|
|
100
|
+
uv run {countImportsHelper} summary "{run_dir}/imports-{i}.json" --manifests "{run_dir}/manifests-{i}.json"
|
|
101
|
+
uv run {findCyclesHelper} find --edges "{run_dir}/imports-{i}.json"
|
|
102
|
+
uv run {countImportsHelper} count "{source_root}" --units "{run_dir}/units-{i}.json" --format libraries > "{run_dir}/importers-{i}.json"
|
|
103
|
+
uv run {pairIntersectHelper} intersect --libraries "{run_dir}/importers-{i}.json"
|
|
104
|
+
```
|
|
100
105
|
|
|
101
|
-
|
|
102
|
-
- Which other qualifying units does it depend on?
|
|
103
|
-
- Which external dependencies does it use?
|
|
106
|
+
A helper that exits non-zero names the problem on stderr (a unit name or path given twice, a malformed entry): fix the units JSON and run the block again.
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
+
Read the output. The `summary` line prints the graph without the file lists, which stay in `{run_dir}/imports-{i}.json`:
|
|
109
|
+
|
|
110
|
+
- **Imports From / Imported By:** each summary `units[]` entry's `imports_from` and `imported_by`. Its `file_count` is the number of import sites (files outside the unit that import it).
|
|
111
|
+
- **External Deps:** each summary `units[]` entry's `external_dep_count`, the number of manifest dependencies its files import.
|
|
112
|
+
- **Mutual dependencies:** each `cycles[]` entry (`["a", "b", "a"]` is two units that import each other).
|
|
113
|
+
- **Co-imported units:** each `pairs[]` entry: `intersection_count` files import both units, listed in `files`. When `truncated` is true, run that last call again with `--top-k` set to its `total_pairs`, so no pair is left out.
|
|
114
|
+
- **Cohesion evidence:** the summary's `umbrella_candidates[]` and `manifests[]` (each manifest's `name`, `private` and `internal_deps`), which §5 reads.
|
|
108
115
|
|
|
109
116
|
**Build cross-reference matrix:**
|
|
110
117
|
|
|
111
|
-
| Unit | Imports From | Imported By | External Deps |
|
|
112
|
-
|
|
113
|
-
| {name} | {
|
|
118
|
+
| Unit | Imports From | Imported By | Import Sites | External Deps |
|
|
119
|
+
|------|-------------|-------------|--------------|---------------|
|
|
120
|
+
| {name} | {imports_from} | {imported_by} | {file_count} | {external_dep_count, or --} |
|
|
114
121
|
|
|
115
122
|
### 4. Detect Integration Points
|
|
116
123
|
|
|
117
124
|
Identify cross-unit integration patterns:
|
|
118
125
|
|
|
119
126
|
**Direct integrations:**
|
|
120
|
-
-
|
|
127
|
+
- Each §3 summary `edge_files[]` entry (unit `from` imports from unit `to` in `file_count` files, the first of them listed in `files` with the line of their first import) → document the interface boundary. When the boundary needs every file, read that entry in `{run_dir}/imports-{i}.json`
|
|
121
128
|
- Shared type definitions across units
|
|
122
129
|
- Cross-unit function calls
|
|
123
130
|
|
|
@@ -127,70 +134,81 @@ Identify cross-unit integration patterns:
|
|
|
127
134
|
- Files involved (with paths)
|
|
128
135
|
- Coupling strength (tight / loose / indirect)
|
|
129
136
|
|
|
130
|
-
### 5.
|
|
137
|
+
### 5. Decide Composites and Stack Skill Candidates
|
|
138
|
+
|
|
139
|
+
Decide both here, in one pass over §3's graph and §4's integration map, so each group of units is judged once: a **composite** when its units only deliver value together, a **stack skill candidate** when each is useful on its own and they are also used together. A group is never both.
|
|
131
140
|
|
|
132
|
-
|
|
141
|
+
**Resolve `{skillInventoryHelper}`** from `{skillInventoryProbeOrder}`; first existing path wins. If no candidate exists, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `map-and-detect:5`): "`skf-skill-inventory.py` is missing. Re-install SKF."
|
|
133
142
|
|
|
134
|
-
**For each
|
|
143
|
+
1. **Composite merge proposals.** Apply the Composite Boundary triggers in {heuristicsFile} (mutual hard dependency, shared integration surface, and the Cohesion Triggers: umbrella facade, shared runtime contract, internal building blocks) to the qualifying units. The evidence comes from the helpers: `cycles[]` for a mutual dependency, `edge_files[]` and §4's shared types for a shared integration surface, and the §3 summary's `umbrella_candidates[]` and each manifest's `internal_deps` and `private` for the cohesion triggers. For each group that meets a trigger, propose one composite:
|
|
144
|
+
- **Constituents:** the unit names and paths merged
|
|
145
|
+
- **Heuristic and evidence:** the trigger and what showed it (the cycle, the umbrella candidate and the members its `internal_deps` cover, the `private` flags, the shared types and their files)
|
|
146
|
+
- **Name:** name every proposal in one call to the helper that names every unit and brief ({heuristicsFile}'s Unit Names), one entry each: `target` is its constituents' project path, `manifest_name` the facade's manifest name when an umbrella facade triggered the merge (else null), and `members` the constituents' manifest names:
|
|
147
|
+
```bash
|
|
148
|
+
uv run {skillInventoryHelper} derive-name --from - <<'SKF_COMPOSITE_NAMES'
|
|
149
|
+
[{"target": "<project path>", "manifest_name": "<facade name or null>", "members": ["<constituent manifest name>", ...]}, ...]
|
|
150
|
+
SKF_COMPOSITE_NAMES
|
|
151
|
+
```
|
|
152
|
+
Each `names[].name` is that proposal's name; give the entries `unnamed` and `duplicates` list a name of your own, from their constituents.
|
|
153
|
+
2. **Stack skill candidates.** Check the four stack-skill indicators defined in {heuristicsFile}'s Stack Skill Candidate Detection section against the units no composite proposal groups: co-import frequency is a §3 `pairs[]` entry with an `intersection_count` of 3 or more, and integration adapter, shared state and orchestration layer come from §4. When the user rejects a composite in §6, check its constituents here too.
|
|
154
|
+
|
|
155
|
+
**For each stack skill candidate, document:**
|
|
135
156
|
- Units involved
|
|
136
157
|
- Detection signal
|
|
137
158
|
- Recommended stack skill grouping
|
|
138
159
|
- Evidence (specific files/lines)
|
|
139
160
|
|
|
140
|
-
### 6. Present Findings
|
|
161
|
+
### 6. Present the Findings and Confirm
|
|
141
162
|
|
|
142
|
-
|
|
163
|
+
Show the user the per-unit export summary, the cross-reference matrix, each integration point (source to target, type, coupling), the composite merge proposals, the stack skill candidates (units involved and detection signal), and the observations (key architectural patterns, tightly and loosely coupled areas). Present the proposals as a table:
|
|
143
164
|
|
|
144
|
-
|
|
145
|
-
|
|
165
|
+
| # | Composite Name | Constituents | Heuristic | Evidence |
|
|
166
|
+
|---|----------------|--------------|-----------|----------|
|
|
167
|
+
| 1 | {name} | {constituent unit names and paths} | {mutual hard dependency / shared integration surface / umbrella facade / shared runtime contract / internal building blocks} | {evidence} |
|
|
146
168
|
|
|
147
|
-
|
|
148
|
-
{Import graph matrix}
|
|
169
|
+
Then display:
|
|
149
170
|
|
|
150
|
-
**
|
|
151
|
-
{List each integration with source → target, type, coupling}
|
|
171
|
+
"Accept or reject each composite merge proposal (every one is accepted unless you reject it), or name an integration pattern to investigate further. **Select:** [C] Continue to Recommendations | [D] Discover Additional Source | [X] Cancel and exit"
|
|
152
172
|
|
|
153
|
-
|
|
154
|
-
{List each candidate with units involved and detection signal}
|
|
173
|
+
An approved composite replaces its constituents as one unit: `Boundary Type: Composite`, its constituents' paths as its Path, the project path they share, the scope type and language of its dominant constituent (the one with the most exports), and confidence from the strength of its trigger. A rejected one leaves its constituents as separate units.
|
|
155
174
|
|
|
156
|
-
|
|
157
|
-
- {Key architectural patterns observed}
|
|
158
|
-
- {Tightly coupled areas}
|
|
159
|
-
- {Loosely coupled areas ideal for independent skills}
|
|
175
|
+
#### Menu Handling Logic:
|
|
160
176
|
|
|
161
|
-
|
|
177
|
+
- IF C: go to §7
|
|
178
|
+
- IF D: load, read the entire file, then execute {discoverFile} with the project path the user gives. It adds the new path's units to Identified Units and returns their export records, import graph, composite proposals and stack skill candidates, which join the findings here, so §7 writes the Export Map and Integration Points with them: redisplay §6 with them included.
|
|
179
|
+
- IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `map-and-detect:6`): "Cancelled at the export mapping."
|
|
180
|
+
- IF Any other: apply the composite decisions, investigate what the user named, show what changed, then [Redisplay Menu Options](#6-present-the-findings-and-confirm)
|
|
181
|
+
|
|
182
|
+
**GATE [default: C]**: present the menu and wait for the user's choice. If `{headless_mode}`: accept every composite merge proposal and continue with [C], and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "map-and-detect.findings", "default_action": "C", "taken_action": "C", "reason": "headless: auto-accept {count} composite merges and continue past the integration analysis", "evidence": {"composites": [<the name of each accepted composite>], "stack_skill_candidates": <the candidate count>}}`, then run
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
186
|
+
```
|
|
162
187
|
|
|
163
|
-
|
|
188
|
+
If the command fails, go on: only that entry is lost.
|
|
164
189
|
|
|
165
|
-
### 7. Append to Report
|
|
190
|
+
### 7. Append to Report and Continue
|
|
166
191
|
|
|
167
|
-
|
|
168
|
-
Replace `[Appended by map-and-detect]` under Export Map with:
|
|
192
|
+
Replace `[Appended by map-and-detect]` under Export Map in {outputFile} with:
|
|
169
193
|
- Per-unit export summary table
|
|
170
194
|
- Export pattern analysis
|
|
171
195
|
|
|
172
|
-
Append the complete "## Integration Points" section to {outputFile}:
|
|
173
196
|
Replace `[Appended by map-and-detect]` under Integration Points with:
|
|
174
197
|
- Cross-reference matrix
|
|
175
198
|
- Integration point details
|
|
199
|
+
- Composite merge proposals and decisions: name, constituents with their paths, heuristic, evidence
|
|
176
200
|
- Stack skill candidate flags
|
|
177
201
|
|
|
202
|
+
In the Identified Units classification table, replace the constituent rows of each approved composite with the composite's one row (its Path the constituents' paths), so recommend builds one card for it.
|
|
203
|
+
|
|
178
204
|
Update {outputFile} frontmatter:
|
|
179
205
|
```yaml
|
|
180
206
|
stepsCompleted: [append 'map-and-detect' to existing array]
|
|
181
207
|
lastStep: 'map-and-detect'
|
|
208
|
+
confirmed_composites: [{list of approved composites: {name, constituents: [{name, path}], heuristic}}]
|
|
182
209
|
stack_skill_candidates: [{list flagged candidate groupings}]
|
|
183
210
|
```
|
|
184
211
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
Display: "**Select:** [C] Continue to Recommendations | [D] Discover Additional Source"
|
|
188
|
-
|
|
189
|
-
#### Menu Handling Logic:
|
|
190
|
-
|
|
191
|
-
- IF C: Save findings to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
|
|
192
|
-
- IF D: Accept a new repo path/URL from the user. Run a lightweight scan (directory structure + manifest detection from step 02) and classify (unit identification from step 03) for the new source only. Merge results into the existing report — append new units to the unit list, update `project_paths[]` in frontmatter. Then redisplay this step's export mapping for the new units before returning to the menu.
|
|
193
|
-
- IF Any other: help user, then [Redisplay Menu Options](#8-present-menu-options)
|
|
194
|
-
|
|
195
|
-
**GATE [default: C]** — present the menu and wait for the user's choice. If `{headless_mode}`: auto-proceed with [C] Continue past export/integration findings, log: "headless: auto-continue past integration analysis".
|
|
212
|
+
(`confirmed_composites` is an empty array when no composite was proposed or all were rejected. generate-briefs puts every constituent's path in the composite brief's `scope.include`.)
|
|
196
213
|
|
|
214
|
+
Then load, read the entire file, then execute {nextStepFile}.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
2
|
+
|
|
3
|
+
# Map Each Unit's Exports
|
|
4
|
+
|
|
5
|
+
The per-unit export analysis, stated once for the two files that run it: map-and-detect section 2, for every qualifying unit, and discover-additional-source section 4, for the units it adds. The file that loads this one has resolved `{extractPublicApiHelper}` and `{checkUnitRecordsHelper}` and gives each unit its name, its scope type (`{unit_scope_type}`), its language, its folder (`{unit_root}`: its path under the scan root of its project path) and its file count (the `files_count` of its disqualification record, which the Files column of Identified Units shows); `{forge_tier}` is the report's. This file returns to it with the checked records.
|
|
6
|
+
|
|
7
|
+
## 1. Delegate Each Unit to a Subagent
|
|
8
|
+
|
|
9
|
+
For each unit, launch a subagent task with these explicit constraints:
|
|
10
|
+
|
|
11
|
+
- The subagent reads only that unit's directory tree
|
|
12
|
+
- The subagent analyzes exports / usage / CCC signals for that one unit
|
|
13
|
+
- **The parent does not read the unit's source files before delegating** (avoid the implicit-read trap: the whole point of fan-out is to keep large source bodies out of the parent's context)
|
|
14
|
+
- The subagent writes its record (§3) to a file of the run folder and returns only that file's path, so the parent never copies a record: pass it `{run_dir}` and the resolved `{extractPublicApiHelper}`
|
|
15
|
+
|
|
16
|
+
**Graceful degradation.** If subagents are unavailable in the current runtime, the parent performs the per-unit analysis sequentially in the main thread with the same export-surface call and tier-aware extras. Each main-thread analysis still writes the same JSON record, so the later steps do not depend on the execution mode.
|
|
17
|
+
|
|
18
|
+
## 2. Analyze One Unit
|
|
19
|
+
|
|
20
|
+
**Export surface (every tier):** run the recipe runner on the unit's own folder. For the languages it has ast-grep recipes for (Python, JavaScript and TypeScript, Rust, Go, Vue) it lists the files, runs the recipes, follows the entry points and counts the public API, so the subagent neither greps nor counts those exports by hand:
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv run {extractPublicApiHelper} --mode full --source-root "{unit_root}" --scope-type {unit_scope_type} --tier {forge_tier}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**No recipe for the unit's language:** when `files_in_scope` is 0, or `files_without_recipes` lists the extension of the unit's language (Java, Kotlin, Swift, C#, PHP, Ruby and C or C++ have no recipe), the run counted none of its exports, whatever its exit code. Read the public declarations of the unit's source files by eye, as on exit 3: `exports_count`, `api_surface` and `export_pattern` from what you read (for example "public classes: 14, interfaces: 3"), `strategy_used: "source-read"`, `confidence: "T1-low"`.
|
|
27
|
+
|
|
28
|
+
Otherwise read the JSON by the exit code:
|
|
29
|
+
|
|
30
|
+
- **0 or 1:** `exports_count` ← `counts.exports_public_api`, `api_surface` ← the names in `entry_point_diff.public[]`, `export_pattern` ← `entry_points.status` with `aggregates.by_type` (for example "barrel: 12 functions, 5 classes", marked "capped" when `truncated` is true), `strategy_used: "ast-grep"`, `confidence: "T1"`. Then read by eye what the recipes could not, and name each one in `warnings`: every `entry_point_diff.extraction_gaps[]` name (public, but no recipe found its definition: read it at its `file` and `line`) and every `file_issues[]` file (one the parser could not fully read: add the exports it shows to `api_surface`). Exit 1 (`status: "incomplete"`) means an ast-grep run failed on some files: keep what it returned and put its `errors[]` in `warnings`.
|
|
31
|
+
- **3** (no ast-grep the runner can run): the JSON still lists `entry_points.files`. Read the exports from those entry-point files by eye (from the unit's source files when it lists none), with `strategy_used: "source-read"` and `confidence: "T1-low"`.
|
|
32
|
+
- **2:** an input error, named on stderr (a wrong path or flag): fix the call and run it again.
|
|
33
|
+
|
|
34
|
+
**Tier-aware extras:** when `tools.ccc` is true (Forge+, or Deep with ccc installed), search `"{unit_name} exports public API"` (top 15) with the ccc tool the runtime offers (the `/ccc` skill, a ccc MCP server or the `ccc search` CLI) and record the top 3 files in `ccc_signals.top_files`, with `available: true`; with no ccc tool, record `available: false`.
|
|
35
|
+
|
|
36
|
+
The subagent also records the export-surface call's `strategy_used`, `confidence` and `warnings`.
|
|
37
|
+
|
|
38
|
+
## 3. Record Contract
|
|
39
|
+
|
|
40
|
+
Each subagent writes only this JSON object, with no prose, no commentary and no markdown fence, to `{run_dir}/unit-records/{unit_name}.json` (creating the folder), and returns that path:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"unit_name": "...",
|
|
45
|
+
"files_count": N,
|
|
46
|
+
"exports_count": N,
|
|
47
|
+
"export_pattern": "...",
|
|
48
|
+
"api_surface": ["..."],
|
|
49
|
+
"ccc_signals": {"top_files": [], "available": <bool>},
|
|
50
|
+
"strategy_used": "ast-grep|source-read",
|
|
51
|
+
"confidence": "T1|T1-low",
|
|
52
|
+
"warnings": []
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
`files_count` is the unit's file count the loading file gave (the `files_count` of its disqualification record), not the runner's `files_in_scope`, which leaves out every file no recipe reads.
|
|
57
|
+
|
|
58
|
+
## 4. Check the Records
|
|
59
|
+
|
|
60
|
+
Once every subagent has returned its path (a main-thread analysis writes its record the same way), check all the records in one call:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
uv run {checkUnitRecordsHelper} --dir "{run_dir}/unit-records"
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The script drops a wrapping markdown fence (a subagent sometimes writes one despite the contract), checks each record against the contract above and fills a missing or wrong-typed key with its empty value, so a degraded record still goes on. Its `records` are the per-unit payloads. Record each `problems` entry as the warning `{unit_name}: {problem}` and each `warnings` entry as it is, so they reach the envelope's `warnings`: one `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning '<the warning>'` per entry, a single quote in it written as a backtick. A unit with no file in the folder, or a file the script lists in `unreadable` (it held no JSON object), is analyzed again in the main thread (graceful degradation, §1), and the check runs once more. Record only the entries of the units this pass analyzed: a record an earlier pass checked was recorded then.
|
|
67
|
+
|
|
68
|
+
Return to the file that loaded this one with the checked `records` of these units.
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'generate-briefs.md'
|
|
3
3
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
4
|
-
schemaFile: '
|
|
4
|
+
schemaFile: 'assets/skill-brief-schema.md'
|
|
5
|
+
discoverFile: 'references/discover-additional-source.md'
|
|
5
6
|
advancedElicitationSkill: '/bmad-advanced-elicitation'
|
|
6
7
|
partyModeSkill: '/bmad-party-mode'
|
|
7
8
|
---
|
|
@@ -16,21 +17,29 @@ To present each qualifying unit as a recommendation with evidence-based rational
|
|
|
16
17
|
|
|
17
18
|
## Rules
|
|
18
19
|
|
|
19
|
-
- This is the primary user decision point
|
|
20
|
-
- Do not proceed without explicit confirmation for each unit
|
|
20
|
+
- This is the primary user decision point: every unit gets a decision before the run moves on, which a headless run takes by the §7 GATE default
|
|
21
21
|
- Present evidence for each recommendation, invite questions and pushback
|
|
22
22
|
|
|
23
23
|
## MANDATORY SEQUENCE
|
|
24
24
|
|
|
25
|
+
Every HARD HALT in this step names its exit code, `halt_reason` and phase. When `{headless_mode}` is true it first prints its envelope on stderr through the shared emitter (`{emitEnvelopeHelper}` and `{run_dir}` come from SKILL.md On Activation): stage `{run_dir}/halt.json` as `{"phase": "<phase>", "reason": "<the halt message>", "halt_reason": "<halt_reason>", "mode": "interactive", "report_path": "{outputFile as an absolute path}"}`, plus `"path"` when the halt names one, then run
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
and display the line it prints verbatim. Write the payload as valid JSON: in the halt message and `path`, replace each backslash with / and each double quote with a backtick. If the emitter exits non-zero or prints no line, display the halt message alone. An interactive HALT displays its message and emits nothing.
|
|
32
|
+
|
|
25
33
|
### 1. Load Context
|
|
26
34
|
|
|
27
35
|
Read {outputFile} completely to obtain:
|
|
28
|
-
- Qualifying units from Identified Units
|
|
36
|
+
- Qualifying units from Identified Units, each with its project path (the deferred ones are listed in the summary, not given a card)
|
|
29
37
|
- Export map data per unit
|
|
30
38
|
- Integration points and coupling analysis
|
|
31
39
|
- Stack skill candidates from frontmatter
|
|
32
40
|
- Existing skills from frontmatter
|
|
33
|
-
- `intent_hint` from frontmatter (
|
|
41
|
+
- `intent_hint` from frontmatter (the goal the user stated at init; empty when none)
|
|
42
|
+
- `refs` from frontmatter: a unit's ref is its project path's entry there (none without one)
|
|
34
43
|
|
|
35
44
|
Load {schemaFile} for reference on what skill-brief.yaml requires (so recommendations are actionable).
|
|
36
45
|
|
|
@@ -42,6 +51,7 @@ For each qualifying unit, prepare a recommendation card:
|
|
|
42
51
|
|
|
43
52
|
```
|
|
44
53
|
**Unit: {name}**
|
|
54
|
+
- Source: {its project path}{, at {its ref} when it has one}
|
|
45
55
|
- Path: {path}
|
|
46
56
|
- Language: {language}
|
|
47
57
|
- Boundary: {type} | Scope: {scope_type}
|
|
@@ -51,12 +61,12 @@ For each qualifying unit, prepare a recommendation card:
|
|
|
51
61
|
- Coupling: {tight/loose/indirect}
|
|
52
62
|
- Confidence: {high/medium/low}
|
|
53
63
|
- Stack Skill: {yes — grouped with {units} / no}
|
|
54
|
-
- Status: {new / already-skilled → recommend update-skill}
|
|
64
|
+
- Status: {new / briefed: a brief from an earlier analysis at {its path}, rewritten if you confirm the unit / already-skilled → recommend update-skill}
|
|
55
65
|
|
|
56
66
|
**Rationale:** {2-3 sentences explaining WHY this should be a skill, citing specific detection signals and file paths}
|
|
57
67
|
|
|
58
68
|
**Proposed Brief Fields:**
|
|
59
|
-
- name: {
|
|
69
|
+
- name: {the unit's name, as identify-units or map-and-detect derived it}
|
|
60
70
|
- scope.type: {full-library / specific-modules / public-api / component-library / reference-app / docs-only}
|
|
61
71
|
- scope.include: {suggested glob patterns}
|
|
62
72
|
- description: {suggested 1-3 sentence description, containing a literal `Use when` clause}
|
|
@@ -64,6 +74,8 @@ For each qualifying unit, prepare a recommendation card:
|
|
|
64
74
|
|
|
65
75
|
### 3. Present Recommendations
|
|
66
76
|
|
|
77
|
+
**Headless** (`{headless_mode}` true): no one answers the questions below. Take the §7 GATE default now (confirm every card as proposed and flag every stack skill candidate for create-stack-skill), record it as that GATE says, then continue at §6. No question of §3 to §5 is asked.
|
|
78
|
+
|
|
67
79
|
"**Recommendations for {project_name}**
|
|
68
80
|
|
|
69
81
|
I've analyzed {count} qualifying units. Here are my recommendations for skill creation:
|
|
@@ -78,97 +90,66 @@ Present each recommendation card, then after ALL cards:
|
|
|
78
90
|
- **Recommended for new skills:** {count}
|
|
79
91
|
- **Already-skilled (recommend update-skill):** {count}
|
|
80
92
|
- **Stack skill candidates:** {count}
|
|
93
|
+
- **Deferred (outside the stated goal, not analyzed):** {count, with their names}
|
|
81
94
|
|
|
82
95
|
**For each unit above, please indicate:**
|
|
83
|
-
- **Y
|
|
84
|
-
- **N
|
|
85
|
-
- **M
|
|
96
|
+
- **Y**: Confirm: generate skill-brief.yaml
|
|
97
|
+
- **N**: Reject: skip this unit
|
|
98
|
+
- **M**: Modify: adjust name, scope, or description before confirming
|
|
86
99
|
|
|
87
100
|
**Bulk shortcuts:**
|
|
88
|
-
- `all-Y
|
|
89
|
-
- `all-N
|
|
90
|
-
- Individual response list (e.g., `1:Y, 2:N, 3:M, ...`)
|
|
101
|
+
- `all-Y`: confirm every recommendation as-is
|
|
102
|
+
- `all-N`: skip every recommendation
|
|
103
|
+
- Individual response list (e.g., `1:Y, 2:N, 3:M, ...`): explicit per-unit decisions (use this when you want to mix Y/N/M or modify any unit)
|
|
91
104
|
|
|
92
105
|
**Questions?** Ask 'why?' about any recommendation and I'll explain my reasoning with specific evidence."
|
|
93
106
|
|
|
94
107
|
### 4. Process User Decisions
|
|
95
108
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
**IF Y (Confirm):**
|
|
99
|
-
- Add to confirmed_units list with proposed brief fields
|
|
100
|
-
|
|
101
|
-
**IF N (Reject):**
|
|
102
|
-
- Document rejection with user's reason (if provided)
|
|
103
|
-
- Remove from confirmed list
|
|
104
|
-
|
|
105
|
-
**IF M (Modify):**
|
|
106
|
-
- Ask what to modify (name, scope, description, scope.include patterns)
|
|
107
|
-
- Update the recommendation with user changes
|
|
108
|
-
- Confirm the modified version
|
|
109
|
-
|
|
110
|
-
**Continue until ALL units have a decision (Y/N/M).**
|
|
109
|
+
Record a decision for every unit before moving on: Y adds it to `confirmed_units` with its proposed brief fields; N records the user's reason; M asks what to change (name, scope type, include patterns, description), applies it and confirms the result.
|
|
111
110
|
|
|
112
111
|
### 5. Confirm Stack Skill Candidates
|
|
113
112
|
|
|
114
|
-
If stack skill candidates were flagged:
|
|
115
|
-
|
|
116
|
-
"**Stack Skill Candidates:**
|
|
117
|
-
|
|
118
|
-
The following unit groupings show strong co-integration patterns and may benefit from a consolidated stack skill via create-stack-skill:
|
|
119
|
-
|
|
120
|
-
{For each candidate: list units, detection signal, evidence}
|
|
121
|
-
|
|
122
|
-
Would you like to flag these for create-stack-skill? (Y/N per candidate)"
|
|
123
|
-
|
|
124
|
-
Document decisions.
|
|
113
|
+
If stack skill candidates were flagged, list them (units, detection signal, evidence): their units show strong co-integration patterns and may benefit from a consolidated stack skill via create-stack-skill. Ask "Flag these for create-stack-skill? (Y/N per candidate)" and record each decision.
|
|
125
114
|
|
|
126
|
-
### 6.
|
|
115
|
+
### 6. Append to Report
|
|
127
116
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
{List each confirmed unit with final name, scope type, and description}
|
|
131
|
-
|
|
132
|
-
**Rejected Units:** {count}
|
|
133
|
-
{List with reasons}
|
|
134
|
-
|
|
135
|
-
**Stack Skill Flags:** {count}
|
|
136
|
-
{List groupings flagged for create-stack-skill}
|
|
137
|
-
|
|
138
|
-
**This is your final confirmation before I generate skill-brief.yaml files.** All confirmed?"
|
|
139
|
-
|
|
140
|
-
Wait for explicit final confirmation.
|
|
141
|
-
|
|
142
|
-
### 7. Append to Report
|
|
143
|
-
|
|
144
|
-
Append the complete "## Recommendations" section to {outputFile}:
|
|
145
|
-
|
|
146
|
-
Replace `[Appended by recommend]` with:
|
|
117
|
+
Replace `[Appended by recommend]` in {outputFile} with:
|
|
147
118
|
- All recommendation cards (including rationale)
|
|
148
119
|
- User decisions per unit (confirmed/rejected/modified)
|
|
149
120
|
- Stack skill candidate decisions
|
|
150
|
-
- Final confirmation status
|
|
151
121
|
|
|
152
122
|
Update {outputFile} frontmatter:
|
|
153
123
|
```yaml
|
|
154
|
-
stepsCompleted: [append 'recommend' to existing array]
|
|
155
|
-
lastStep: 'recommend'
|
|
156
124
|
confirmed_units: [{list of confirmed unit names}]
|
|
157
125
|
stack_skill_candidates: [{updated list with user decisions}]
|
|
158
126
|
```
|
|
159
127
|
|
|
160
|
-
|
|
128
|
+
A later pass through this section (after [A], [P] or [D], or in a session that resumed this step) replaces what the earlier one wrote. The step is marked complete only when [C] leaves it, so a run cancelled at the §7 menu resumes at these recommendations.
|
|
129
|
+
|
|
130
|
+
### 7. Present MENU OPTIONS
|
|
131
|
+
|
|
132
|
+
Lead with the decisions, so the menu is chosen against the final list:
|
|
133
|
+
|
|
134
|
+
"**Confirmed for brief generation:** {count}: {each confirmed unit with its final name, scope type and description}
|
|
135
|
+
**Rejected:** {count}: {each with its reason}
|
|
136
|
+
**Flagged for create-stack-skill:** {count}: {each grouping}"
|
|
161
137
|
|
|
162
138
|
Display: "**Select an Option:** [A] Advanced Elicitation [P] Party Mode [D] Discover Additional Source [C] Continue to Brief Generation [X] Cancel and exit"
|
|
163
139
|
|
|
164
140
|
#### Menu Handling Logic:
|
|
165
141
|
|
|
166
|
-
- IF A: Invoke {advancedElicitationSkill},
|
|
167
|
-
- IF P: Invoke {partyModeSkill},
|
|
168
|
-
- IF D:
|
|
169
|
-
- IF C:
|
|
170
|
-
- IF X: HARD HALT
|
|
171
|
-
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#
|
|
142
|
+
- IF A: Invoke {advancedElicitationSkill}. For each unit what it surfaced changes, take the decision again as §4 says, redo §6, then redisplay this menu
|
|
143
|
+
- IF P: Invoke {partyModeSkill}, then handle what it surfaced as [A] does
|
|
144
|
+
- IF D: load, read the entire file, then execute {discoverFile} with the project path the user gives. It returns the new path's units with their export records and composite proposals. Present each proposal (accepted unless the user rejects it; an accepted one replaces its constituents as one unit and joins `confirmed_composites` in the frontmatter), build the cards of the new units (§2), take their decisions (§3 to §5), redo §6, then redisplay this menu
|
|
145
|
+
- IF C: update {outputFile} frontmatter (`stepsCompleted`: append `recommend`; `lastStep: 'recommend'`), then load, read the entire file, then execute {nextStepFile}
|
|
146
|
+
- IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `recommend:7`, with `unit_counts` reflecting the decisions made so far in its payload): "Cancelled at the recommendations."
|
|
147
|
+
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#7-present-menu-options)
|
|
148
|
+
|
|
149
|
+
**GATE [default: C]**: present the menu and wait for the user's choice. The default also answers every question of §3 to §5: confirm every card as proposed and flag every stack skill candidate. If `{headless_mode}`, §3 takes that default before any question and records it the moment it does: stage `{run_dir}/decision.json` as `{"gate": "recommend.recommendations", "default_action": "C", "taken_action": "C", "reason": "headless: auto-accept all recommendations and flag every stack skill candidate", "evidence": {"confirmed": [<each confirmed unit name>], "stack_skill_candidates": <the flagged candidate count>}}`, then run
|
|
172
150
|
|
|
173
|
-
|
|
151
|
+
```bash
|
|
152
|
+
uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
153
|
+
```
|
|
174
154
|
|
|
155
|
+
If the command fails, go on: only that entry is lost. At this menu a headless run continues with [C].
|