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
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'map-and-detect.md'
|
|
3
3
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
4
|
-
heuristicsFile: '
|
|
4
|
+
heuristicsFile: 'references/unit-detection-heuristics.md'
|
|
5
|
+
scanRootFile: 'references/scan-root.md'
|
|
5
6
|
disqualifyCandidatesProbeOrder:
|
|
6
7
|
- '{project-root}/_bmad/skf/shared/scripts/skf-disqualify-candidates.py'
|
|
7
8
|
- '{project-root}/src/shared/scripts/skf-disqualify-candidates.py'
|
|
9
|
+
skillInventoryProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
8
12
|
detectLanguageProbeOrder:
|
|
9
13
|
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
|
|
10
14
|
- '{project-root}/src/shared/scripts/skf-detect-language.py'
|
|
@@ -16,7 +20,7 @@ detectLanguageProbeOrder:
|
|
|
16
20
|
|
|
17
21
|
## STEP GOAL:
|
|
18
22
|
|
|
19
|
-
To classify each detected boundary from the project scan into discrete skillable units by applying detection heuristics, assigning boundary types and scope types,
|
|
23
|
+
To classify each detected boundary from the project scan into discrete skillable units by applying detection heuristics, assigning boundary types and scope types, filtering out disqualified candidates and, in an interactive run with a stated goal, deferring the units outside it before export mapping.
|
|
20
24
|
|
|
21
25
|
## Rules
|
|
22
26
|
|
|
@@ -26,174 +30,156 @@ To classify each detected boundary from the project scan into discrete skillable
|
|
|
26
30
|
|
|
27
31
|
## MANDATORY SEQUENCE
|
|
28
32
|
|
|
33
|
+
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
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
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.
|
|
40
|
+
|
|
29
41
|
### 1. Load Context
|
|
30
42
|
|
|
31
43
|
Read {outputFile} to obtain:
|
|
32
|
-
- Project Scan results (detected boundaries, manifests,
|
|
33
|
-
- `forge_tier` from frontmatter
|
|
34
|
-
|
|
44
|
+
- Project Scan results (detected boundaries, manifests, service configurations), grouped by project path
|
|
45
|
+
- `project_paths`, `scan_roots` (each project path's scan root: the folder every helper of this step reads), `refs`, `forge_tier`, `intent_hint`, `existing_skills` and `existing_briefs` from frontmatter
|
|
46
|
+
|
|
47
|
+
**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 `identify-units:1`, path `{path}`): "{path} could not be fetched: {the first stderr line}."
|
|
35
48
|
|
|
36
49
|
Load {heuristicsFile} for classification rules.
|
|
37
50
|
|
|
38
51
|
### 2. Apply Detection Heuristics
|
|
39
52
|
|
|
40
|
-
**Resolve `{disqualifyCandidatesHelper}`** from `{disqualifyCandidatesProbeOrder}`; first existing path wins.
|
|
53
|
+
**Resolve `{disqualifyCandidatesHelper}`** from `{disqualifyCandidatesProbeOrder}` and **`{skillInventoryHelper}`** from `{skillInventoryProbeOrder}`; first existing path wins for each. If one has no candidate, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `identify-units:2`): "`{the missing script}` is missing. Re-install SKF."
|
|
41
54
|
|
|
42
55
|
For each detected boundary from the scan, apply the classification rules from {heuristicsFile} (loaded in §1):
|
|
43
56
|
|
|
44
|
-
**Step A
|
|
45
|
-
|
|
46
|
-
**Step B — Classify boundary type** per its Boundary Classification section. (Composite is detected separately in §3b below — not during this initial per-boundary pass.)
|
|
47
|
-
|
|
48
|
-
**Step C — Assign scope type** from that same section for the boundary's type.
|
|
57
|
+
**Step A: Run the disqualification helper (script).** In one call per project path it lists each boundary's files itself, applies the deterministic subset of the rules from {heuristicsFile} (file count, LoC, generated files) and looks up the signal files and the boundary's own manifest. Its output is evidence that Step B judges, not a verdict.
|
|
49
58
|
|
|
50
|
-
|
|
59
|
+
Run it once per project path, the `{i}`-th entry of `project_paths[]`, over the boundaries found under it, with `{scan_root}` that path's scan root (never `{project-root}`, the forge workspace) and one entry per boundary, its path relative to the scan root (`.` for a boundary at the root), with forward slashes:
|
|
51
60
|
|
|
52
|
-
|
|
61
|
+
```bash
|
|
62
|
+
uv run {disqualifyCandidatesHelper} filter --boundaries - --source-root "{scan_root}" --tree-dir "{run_dir}/unit-trees/{i}" <<'SKF_BOUNDARIES'
|
|
63
|
+
[{"name": "<boundary folder name>", "path": "<boundary path>"}, ...]
|
|
64
|
+
SKF_BOUNDARIES
|
|
65
|
+
```
|
|
53
66
|
|
|
54
|
-
1.
|
|
55
|
-
```json
|
|
56
|
-
[
|
|
57
|
-
{"name": "<unit-name>",
|
|
58
|
-
"path": "<rel-from-analyzed-source-root (project_paths[0])>",
|
|
59
|
-
"files": ["<rel-path>", ...]},
|
|
60
|
-
...
|
|
61
|
-
]
|
|
62
|
-
```
|
|
63
|
-
2. **Invoke the script** via stdin:
|
|
64
|
-
```bash
|
|
65
|
-
uv run {disqualifyCandidatesHelper} filter --boundaries - --source-root {project_paths[0]}
|
|
66
|
-
```
|
|
67
|
-
piping the boundaries JSON on stdin. `--source-root` is the analyzed-source root (`project_paths[0]`) — the directory the boundaries/manifest scan ran against — not `{project-root}` (the forge workspace), which differs whenever the analyzed target lives outside the forge workspace. The script emits:
|
|
67
|
+
1. The script lists every boundary's files (what git lists under its path, so ignored build output and installed dependencies stay out), writes each list to the run folder and emits one record per boundary:
|
|
68
68
|
```json
|
|
69
69
|
{
|
|
70
|
-
"kept": [{"name": "...", "path": "...", "files_count": N, "loc_total": L
|
|
71
|
-
|
|
72
|
-
|
|
70
|
+
"kept": [{"name": "...", "path": "...", "files_count": N, "loc_total": L, "non_source_count": K,
|
|
71
|
+
"generated_files": [{"path": "...", "reason": "generated-code|auto-generated-tag", "match": "..."}],
|
|
72
|
+
"generated_ratio": R, "passes_with_generated": true,
|
|
73
|
+
"manifest": {"path": "...", "ecosystem": "npm", "name": "@acme/auth", "private": false},
|
|
74
|
+
"signals": {...}, "tree_file": "..."}, ...],
|
|
75
|
+
"dropped": [{"name": "...", "reason": "<too-few-files|too-low-loc|generated-code|auto-generated-tag>", "context": {...}, ...}, ...],
|
|
76
|
+
"stats": {"kept": N, "dropped": N, "mixed": N, "by_reason": {"<reason>": N, ...}}
|
|
73
77
|
}
|
|
74
78
|
```
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
**
|
|
78
|
-
- **Pure configuration** — only config files (e.g., `.json`/`.yaml`) with no executable logic
|
|
79
|
-
- **Test-only** — test utilities with no production code
|
|
80
|
-
- **Already skilled** — exists in `existing_skills` list (recommend `update-skill` instead)
|
|
79
|
+
A `dropped[]` record carries every `kept[]` field plus `reason` and `context`. Read `files_count` and `loc_total` (the boundary's own source files, counted as {heuristicsFile}'s Disqualification Rules say), `generated_files` and `generated_ratio` (the files Step B weighs), `passes_with_generated` (whether the size rules pass with those files counted too), `manifest` (the boundary's own manifest, null without one), `signals` (Step D) and `tree_file` (the boundary's file list, which §4 hands to the language helper).
|
|
80
|
+
2. A boundary path that is no folder under the scan root makes the script exit 1 and name it on stderr: correct that entry and run the call again.
|
|
81
|
+
3. **Stash the results** in workflow state, each record with its project path: `kept[]` is the candidate pool for the classification that follows, and `dropped[]` drives the Disqualification table.
|
|
81
82
|
|
|
82
|
-
|
|
83
|
+
**Step B: Judge what the script cannot.**
|
|
83
84
|
|
|
84
|
-
**
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
85
|
+
- **Mixed cases** (`stats.mixed` counts them): a kept boundary whose `generated_files` is not empty. Read the flagged paths and their `match`. Build output or a vendored copy beside the unit's own code leaves the unit standing, and its counts already leave those files out. Drop a mixed boundary only when its own code is no more than glue around the generated files, with reason `generated-code` and one line on why.
|
|
86
|
+
- **A drop the flagged files caused:** a boundary dropped as `generated-code`, `auto-generated-tag`, `too-few-files` or `too-low-loc` whose `generated_files` you judge to be its own code (a source folder named `build/` or `dist/`, a header its own tooling writes into code it maintains) goes back into `kept[]` when its `passes_with_generated` is true, with those files named in the notes. When it is false, the boundary stays dropped: even with those files it is too small.
|
|
87
|
+
- **LLM-judged disqualifications** (not in the script; apply on top of `kept[]`), removing a boundary that fails one from the working `kept` set and appending it to `dropped[]` with the reason:
|
|
88
|
+
- **Pure configuration**: only config files (e.g., `.json`/`.yaml`) with no executable logic
|
|
89
|
+
- **Test-only**: test utilities with no production code
|
|
89
90
|
|
|
90
|
-
|
|
91
|
-
|---|-----------|------|---------------|------------|---------|------------|--------|
|
|
92
|
-
| 1 | {name} | {path} | {type} | {scope} | {signal count: strong/moderate/weak} | {high/medium/low} | {new/already-skilled} |
|
|
91
|
+
Show every drop and every restore in §6 with its reason and evidence (the record's `context`, `generated_ratio` and first `generated_files` path), so the user can override it; a headless run keeps the judgment made here.
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
**Step C: Name each unit (script), then check it is not already skilled.** The helper that names every brief names the units too, so a unit's name here is the name its brief gets.
|
|
95
94
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
95
|
+
1. Name every unit in one call, by {heuristicsFile}'s Unit Names, one entry per kept boundary straight from its record: `target` is its `path` (its project path itself for a boundary at the root), and `manifest_name` and `private` are its `manifest.name` and `manifest.private` (null when `manifest` is null):
|
|
96
|
+
```bash
|
|
97
|
+
uv run {skillInventoryHelper} derive-name --from - <<'SKF_UNIT_NAMES'
|
|
98
|
+
[{"target": "<boundary path>", "manifest_name": <manifest.name>, "private": <manifest.private>}, ...]
|
|
99
|
+
SKF_UNIT_NAMES
|
|
100
|
+
```
|
|
101
|
+
Each `names[].name` is that unit's name from here on. Boundaries whose names would clash are already told apart by their parent folders (`clash` keeps the name they shared); give the entries `unnamed` and `duplicates` list a name of your own, from their folder.
|
|
102
|
+
2. **Already skilled:** a unit whose name is in `existing_skills` (a compiled skill) fails the last LLM-judged rule: remove it from the working `kept` set and append it to `dropped[]` with reason `already-skilled` (recommend `update-skill` instead). A unit whose name is in `existing_briefs` only has a brief from an earlier analysis: it stays a candidate with status `briefed` and its brief's path, and generate-briefs rewrites that brief only if the unit is confirmed.
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
**Step D: Tally detection signals** per the Detection Signals tables in {heuristicsFile}: cite the file each record's `signals` entry names (and `large_directory`), and judge the signals the helper does not report, as that file says.
|
|
102
105
|
|
|
103
|
-
|
|
106
|
+
**Step E: Classify boundary type** per its Boundary Classification section, and **assign the scope type** from that same section for the boundary's type. This pass classifies each boundary on its own: composite merges are proposed in map-and-detect, once the import graph exists.
|
|
104
107
|
|
|
105
|
-
|
|
108
|
+
### 3. Build Unit Classification Table
|
|
106
109
|
|
|
107
|
-
|
|
108
|
-
- Derive a composite name from the common namespace prefix or repo name
|
|
109
|
-
- List the constituents (boundary names and paths being merged)
|
|
110
|
-
- State the triggering heuristic and evidence
|
|
110
|
+
For each candidate that passes disqualification:
|
|
111
111
|
|
|
112
|
-
|
|
112
|
+
| # | Unit Name | Project Path | Path | Boundary Type | Scope Type | Files | Own Manifest | Signals | Confidence | Status |
|
|
113
|
+
|---|-----------|--------------|------|---------------|------------|-------|--------------|---------|------------|--------|
|
|
114
|
+
| 1 | {name} | {its project path} | {path} | {type} | {scope} | {files_count} | {manifest path, name and ecosystem, or --} | {signal count: strong/moderate/weak} | {high/medium/low} | {new/briefed/deferred} |
|
|
113
115
|
|
|
114
|
-
|
|
116
|
+
For disqualified candidates, note reason and evidence:
|
|
115
117
|
|
|
116
|
-
**
|
|
118
|
+
**Disqualified:**
|
|
119
|
+
| Path | Reason | Evidence |
|
|
120
|
+
|------|--------|----------|
|
|
121
|
+
| {path} | {disqualification reason} | {the record's `context`, or `generated_ratio` and the first `generated_files` path} |
|
|
117
122
|
|
|
118
123
|
### 4. Detect Primary Language Per Unit
|
|
119
124
|
|
|
120
|
-
For each qualifying unit
|
|
125
|
+
For each qualifying unit, detect the primary language deterministically via the shared helper, the single source of truth for the manifest→language rule table.
|
|
121
126
|
|
|
122
|
-
**Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins.
|
|
127
|
+
**Resolve `{detectLanguageHelper}`** from `{detectLanguageProbeOrder}`; first existing path wins. If neither exists, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `identify-units:4`): "`skf-detect-language.py` is missing. Re-install SKF."
|
|
123
128
|
|
|
124
|
-
For each unit,
|
|
129
|
+
For each unit, hand the helper the file list §2 wrote for it, its record's `tree_file`:
|
|
125
130
|
|
|
126
131
|
```bash
|
|
127
|
-
|
|
132
|
+
uv run {detectLanguageHelper} --tree-file "{the unit's tree_file}"
|
|
128
133
|
```
|
|
129
134
|
|
|
130
|
-
Read `.language` and `.confidence` for the unit. When confidence is low (the extension-frequency fallback fired
|
|
131
|
-
|
|
132
|
-
### 5. Present Classifications
|
|
133
|
-
|
|
134
|
-
"**Unit Identification Complete**
|
|
135
|
+
Pass no `--workspace-signal` here: a workspace root's language would answer for every unit of the workspace (a TypeScript package in a Cargo workspace would read as `rust`). The unit's folder is the tree's root for the helper, so the unit's own manifest decides, and a manifest in its docs, examples, tests or tools folder never does while another one exists. Read `.language` and `.confidence` for the unit. When `detected_languages` has more than one entry, `.language` is the helper's first guess: choose the language the unit documents from its own manifest (the record's `manifest`), or, without one, `.source_language` (the language most of its files are written in), and name the choice and the other languages in §6. When confidence is low (the extension-frequency fallback fired: no manifest matched), surface it in §6 so the user can override the guess.
|
|
135
136
|
|
|
136
|
-
|
|
137
|
+
### 5. Defer What the Goal Leaves Out
|
|
137
138
|
|
|
138
|
-
|
|
139
|
+
Interactive runs only, and only when `intent_hint` is not empty: mark each qualifying unit the stated goal clearly leaves out `deferred` in the Status column, with one line on why (for example "deferred: payments, outside the stated goal (authentication)"). Step 4 maps only the units that are not deferred, and the deferred ones stay in the classification table, so nothing is dropped without notice. A unit you are unsure about stays in. A headless run defers nothing: there `intent_hint` only ranks the step 5 recommendations.
|
|
139
140
|
|
|
140
|
-
|
|
141
|
-
{Disqualification table}
|
|
141
|
+
### 6. Present the Classifications and Confirm
|
|
142
142
|
|
|
143
|
-
|
|
144
|
-
{List with recommendation to run update-skill if source has changed}
|
|
143
|
+
Show the user the classification table, then:
|
|
145
144
|
|
|
146
|
-
|
|
145
|
+
- **Mixed cases** (`stats.mixed`): for each qualifying unit with generated files, its name, `generated_ratio`, the flagged folders or headers and why it stays; and each boundary §2 Step B restored, with the files that restored it
|
|
146
|
+
- **Disqualified candidates**, with the table above
|
|
147
|
+
- **Already-skilled units** (from `existing_skills`), each with a recommendation to run update-skill if its source changed
|
|
148
|
+
- **Deferred units**, when §5 deferred any, with how to restore them
|
|
149
|
+
- **Notes:** structure patterns observed, and ambiguous boundaries that need the user's call
|
|
147
150
|
|
|
148
|
-
|
|
151
|
+
Then display:
|
|
149
152
|
|
|
150
|
-
|
|
151
|
-
|---|----------------|--------------|-----------|----------|
|
|
152
|
-
| 1 | {name} | {list of constituent unit names} | {mutual hard dependency / shared integration surface} | {brief evidence} |
|
|
153
|
+
"Add, remove, reclassify or restore any unit? Tell me, or **Select:** [C] Continue to Export Mapping and Integration Detection | [X] Cancel and exit"
|
|
153
154
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
{END IF}
|
|
155
|
+
#### Menu Handling Logic:
|
|
157
156
|
|
|
158
|
-
|
|
159
|
-
-
|
|
160
|
-
-
|
|
157
|
+
- IF C: go to §7
|
|
158
|
+
- IF X: HARD HALT (exit code 6, `halt_reason: "user-cancelled"`, phase `identify-units:6`): "Cancelled at unit identification."
|
|
159
|
+
- IF Any other: adjust the classifications as directed (restoring a deferred unit sets its status back to new or briefed), show what changed, then [Redisplay Menu Options](#6-present-the-classifications-and-confirm)
|
|
161
160
|
|
|
162
|
-
|
|
163
|
-
{IF composites proposed:} Are the composite merge proposals correct? (Accept/reject each individually.)"
|
|
161
|
+
**GATE [default: C]**: present the menu and wait for the user's choice. If `{headless_mode}`: accept every classification and continue with [C], and record that decision the moment it is taken: stage `{run_dir}/decision.json` as `{"gate": "identify-units.classifications", "default_action": "C", "taken_action": "C", "reason": "headless: auto-accept unit classifications", "evidence": {"qualifying": <the qualifying unit count>, "dropped": <the dropped boundary count>}}`, then run
|
|
164
162
|
|
|
165
|
-
|
|
163
|
+
```bash
|
|
164
|
+
uv run {emitEnvelopeHelper} record --workflow skf-analyze-source --run-dir "{run_dir}" --decision < "{run_dir}/decision.json"
|
|
165
|
+
```
|
|
166
166
|
|
|
167
|
-
|
|
167
|
+
If the command fails, go on: only that entry is lost.
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
### 7. Append to Report and Continue
|
|
170
170
|
|
|
171
|
-
Replace the placeholder `[Appended by identify-units]` with:
|
|
172
|
-
- Classification table (qualifying units,
|
|
173
|
-
-
|
|
171
|
+
Replace the placeholder `[Appended by identify-units]` in {outputFile} with:
|
|
172
|
+
- Classification table (qualifying units, under their §2 Step C names, with their project paths, file counts, own manifests and statuses, deferred units included)
|
|
173
|
+
- Mixed cases and restored boundaries, with their evidence
|
|
174
174
|
- Disqualification table
|
|
175
175
|
- Already-skilled units list
|
|
176
|
-
- Language detection results
|
|
176
|
+
- Language detection results, and each unit's `tree_file`
|
|
177
177
|
- Any user adjustments noted
|
|
178
178
|
|
|
179
179
|
Update {outputFile} frontmatter:
|
|
180
180
|
```yaml
|
|
181
181
|
stepsCompleted: [append 'identify-units' to existing array]
|
|
182
182
|
lastStep: 'identify-units'
|
|
183
|
-
confirmed_composites: [{list of approved composite merge objects: {name, constituents[], heuristic}}]
|
|
184
183
|
```
|
|
185
184
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
### 7. Present MENU OPTIONS
|
|
189
|
-
|
|
190
|
-
Display: "**Select:** [C] Continue to Export Mapping and Integration Detection | [X] Cancel and exit"
|
|
191
|
-
|
|
192
|
-
#### Menu Handling Logic:
|
|
193
|
-
|
|
194
|
-
- IF C: Save classifications to {outputFile}, update frontmatter, then load, read entire file, then execute {nextStepFile}
|
|
195
|
-
- IF X: HARD HALT with exit code 6 (`user-cancelled`). Emit the error envelope on stderr with `halt_reason: "user-cancelled"` and counts/paths reflecting state at cancellation (shape in `references/headless-contract.md`)
|
|
196
|
-
- IF Any other: help user, then [Redisplay Menu Options](#7-present-menu-options)
|
|
197
|
-
|
|
198
|
-
**GATE [default: C]** — present the menu and wait for the user's choice. If `{headless_mode}`: accept all classifications and auto-proceed, log: "headless: auto-accept unit classifications".
|
|
199
|
-
|
|
185
|
+
Then load, read the entire file, then execute {nextStepFile}.
|
|
@@ -3,6 +3,9 @@ nextStepFile: 'scan-project.md'
|
|
|
3
3
|
continueFile: 'continue.md'
|
|
4
4
|
outputFile: '{forge_data_folder}/analyze-source-report-{project_name}.md'
|
|
5
5
|
templateFile: '{analysisReportTemplatePath}'
|
|
6
|
+
skillInventoryProbeOrder:
|
|
7
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-skill-inventory.py'
|
|
8
|
+
- '{project-root}/src/shared/scripts/skf-skill-inventory.py'
|
|
6
9
|
---
|
|
7
10
|
|
|
8
11
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -11,30 +14,45 @@ templateFile: '{analysisReportTemplatePath}'
|
|
|
11
14
|
|
|
12
15
|
## STEP GOAL:
|
|
13
16
|
|
|
14
|
-
To initialize the analyze-source workflow by loading configuration, detecting continuation state,
|
|
17
|
+
To initialize the analyze-source workflow by loading configuration, detecting continuation state, taking the target project path, the analysis goal and the scope from the invocation or one opening question, checking for existing skills, and creating the analysis report document.
|
|
15
18
|
|
|
16
19
|
## Rules
|
|
17
20
|
|
|
18
|
-
- Focus only on initialization
|
|
19
|
-
-
|
|
21
|
+
- Focus only on initialization: do not begin scanning or analysis
|
|
22
|
+
- Use what the invocation already says before asking anything, and ask at most one opening question
|
|
20
23
|
- Verify prerequisites before proceeding
|
|
21
24
|
|
|
22
25
|
## MANDATORY SEQUENCE
|
|
23
26
|
|
|
24
|
-
When `{headless_mode}` is true
|
|
27
|
+
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": "<auto when the invocation carries [auto], else interactive>"}`, plus `"path"` when the halt names one, then run
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv run {emitEnvelopeHelper} emit-halt --workflow skf-analyze-source --run-dir "{run_dir}" --target stderr < "{run_dir}/halt.json"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
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.
|
|
25
34
|
|
|
26
35
|
### 1. Check for Existing Report (Continuation Detection)
|
|
27
36
|
|
|
28
37
|
Look for {outputFile}.
|
|
29
38
|
|
|
30
|
-
**IF the file exists AND has `stepsCompleted` with entries:**
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
**IF the file exists AND has `stepsCompleted` with entries:** the report filename is keyed to `{project_name}` (the forge workspace), not the analyzed target, so the report may belong to another analysis or to one that already ended. Apply the first rule that holds:
|
|
40
|
+
|
|
41
|
+
1. **Finished:** `stepsCompleted` holds `generate-briefs` or `auto-scope`: that analysis already ended (with its briefs, or with none). Archive it (below), announce "**The previous analysis of this workspace is finished: archived as <name>; starting a fresh analysis.**", and continue to section 2. A finished report is never resumed, in headless mode either.
|
|
42
|
+
2. **Auto invocation or auto report:** this invocation carries the `[auto]` flag (e.g. `AN[auto]`), or the report's `mode` is `'auto'` (an `[auto]` run that was interrupted or ended at step 1a's coexistence gate with [M]erge or [S]kip). Auto mode is one pass that never resumes, so archive the unfinished report the same way, announce "**An `[auto]` analysis never resumes: archived the unfinished report as <name>; starting a fresh analysis.**", and continue to section 2.
|
|
43
|
+
3. **Unfinished:** establish the requested target and compare it to the report's. Take `project_paths[]` from the invocation as section 3 says (`--project-path`, comma-split, or a path the message names); when it gives none, ask section 3's opening question now (a headless run halts there instead), once: section 3 then asks nothing more. Read the report's frontmatter `project_paths`.
|
|
44
|
+
- **Same target:** compare the ref and hint flags this invocation passes with the report's frontmatter: `--target-ref` or `--target-refs`, resolved to each project path's ref as section 4 does, against `refs`, and `--scope-hint` and `--intent-hint` against `scope_hint` and `intent_hint`. A flag the invocation does not pass changes nothing.
|
|
45
|
+
- **The inputs match:** "**Found an unfinished analysis report. Resuming the previous session...**" Load, read entirely, then execute {continueFile}. **STOP HERE**: do not continue this sequence. Headless runs resume it too.
|
|
46
|
+
- **An input differs:** the later steps would read the report's old values, so archive it and announce "**The inputs changed: archived as <name>; starting a fresh analysis.**" In headless mode, also run `uv run {emitEnvelopeHelper} record --run-dir "{run_dir}" --warning 'inputs changed: the unfinished report was archived as <name>'`, a single quote in it written as a backtick (if it fails, go on). Then continue to section 2: section 3 keeps the path already set, and section 4 resolves the refs again.
|
|
47
|
+
- **Different target (stale collision):** archive it, announce "**Existing report belongs to a different target: archived as <name>; starting a fresh analysis.**", then continue to section 2 (section 3 keeps the path already set).
|
|
48
|
+
|
|
49
|
+
**To archive a report** (rules 1 and 2, changed inputs and a different target; a report that resumes stays where it is), rename it, never overwrite it:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
archive="{forge_data_folder}/analyze-source-report-{project_name}-$(date -u +%Y%m%d-%H%M%S).md" && mv -n "{outputFile}" "$archive" && printf '%s\n' "$archive"
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
and use the path it prints as `<name>`. If the rename fails, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `init:1`, path `{outputFile}`): "The earlier analysis report could not be archived: {the first stderr line}."
|
|
38
56
|
|
|
39
57
|
**IF the file does not exist OR stepsCompleted is empty:**
|
|
40
58
|
- Continue to section 2
|
|
@@ -43,7 +61,7 @@ Look for {outputFile}.
|
|
|
43
61
|
|
|
44
62
|
**Check forge-tier.yaml:**
|
|
45
63
|
- Look for `{sidecar_path}/forge-tier.yaml`
|
|
46
|
-
- **IF missing:** HARD HALT
|
|
64
|
+
- **IF missing:** HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `init:2`, path `{sidecar_path}/forge-tier.yaml`): "**Cannot proceed.** forge-tier.yaml not found at `{sidecar_path}/forge-tier.yaml`. Please run the setup workflow first to configure your forge tier (Quick/Forge/Forge+/Deep)."
|
|
47
65
|
- **IF found:** Read and note the forge tier value
|
|
48
66
|
|
|
49
67
|
**Apply tier override:** Read `{sidecar_path}/preferences.yaml`. If `tier_override` is set and is a valid tier value (Quick, Forge, Forge+, or Deep), use it instead of the detected tier.
|
|
@@ -56,9 +74,10 @@ Look for {outputFile}.
|
|
|
56
74
|
|
|
57
75
|
**IF `{auto_mode}` is true:**
|
|
58
76
|
|
|
59
|
-
1. **Resolve project path:** If `project_paths[]` is already populated (from §1 continuation detection or `--project-path` arg), use it. Otherwise, if `--project-path <path>` was passed at invocation, set `project_paths[]` from it (comma-split if multiple). If neither is available, HARD HALT
|
|
60
|
-
2. **Validate the path(s):** For each provided path/URL, check that it exists (local) or is accessible (remote). If any invalid: HARD HALT
|
|
61
|
-
3. **
|
|
77
|
+
1. **Resolve project path:** If `project_paths[]` is already populated (from §1 continuation detection or `--project-path` arg), use it. Otherwise, if `--project-path <path>` was passed at invocation, set `project_paths[]` from it (comma-split if multiple). If neither is available, HARD HALT (exit code 2, `halt_reason: "input-missing"`, phase `init:2b`): "**Auto mode requires `--project-path`: no project path available.**"
|
|
78
|
+
2. **Validate the path(s):** For each provided path/URL, check that it exists (local) or is accessible (remote). If any invalid: HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `init:2b`, path `{path}`): "**Path `{path}` doesn't appear to be valid.**"
|
|
79
|
+
3. **Take the hints:** `intent_hint` ← the `--intent-hint` value and `scope_hint` ← the `--scope-hint` value (empty when the flag is absent). Step 1a reads both, and so does the interactive chain it may fall back to.
|
|
80
|
+
4. **Create the analysis report** from {templateFile}. First build `existing_skills` and `existing_briefs` as section 5 does, without its messages: the step-by-step analysis an unclassified repository falls back to reads them. Populate frontmatter:
|
|
62
81
|
```yaml
|
|
63
82
|
stepsCompleted: ['init']
|
|
64
83
|
lastStep: 'init'
|
|
@@ -68,75 +87,52 @@ Look for {outputFile}.
|
|
|
68
87
|
project_name: '{project_name}'
|
|
69
88
|
project_paths: ['{provided_project_path}']
|
|
70
89
|
forge_tier: '{detected_tier}'
|
|
71
|
-
existing_skills: []
|
|
90
|
+
existing_skills: [{list of existing skill names}]
|
|
91
|
+
existing_briefs: [{name and path of each existing brief, as {name: '...', path: '...'}}]
|
|
92
|
+
intent_hint: '{intent_hint}'
|
|
93
|
+
scope_hint: '{scope_hint}'
|
|
72
94
|
confirmed_units: []
|
|
73
95
|
stack_skill_candidates: []
|
|
74
96
|
nextWorkflow: ''
|
|
75
97
|
mode: 'auto'
|
|
76
98
|
```
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
**IF `{auto_mode}` is not true:**
|
|
81
|
-
Continue to §3 as normal — the entire interactive flow below is unchanged.
|
|
82
|
-
|
|
83
|
-
### 3. Collect Project Path
|
|
99
|
+
5. "**Auto mode activated: bypassing interactive analysis.**"
|
|
100
|
+
6. **Route to auto-scope:** Load, read fully, then execute `references/step-auto-scope.md`. **STOP HERE**: do not continue to §3 or any subsequent section.
|
|
84
101
|
|
|
85
|
-
**
|
|
102
|
+
**IF `{auto_mode}` is not true:** continue to §3.
|
|
86
103
|
|
|
87
|
-
|
|
104
|
+
### 3. Opening Question
|
|
88
105
|
|
|
89
|
-
|
|
106
|
+
Read the invocation first: its flags (`--project-path`, comma-split for several paths; `--intent-hint`; `--scope-hint`) and, in an interactive run, its message, which may name a path or URL, the goal of the analysis, or folders and packages to focus on or skip ("analyze /work/mono, I only care about auth, skip vendor/"). A flag wins over the message. `project_paths[]` set by section 1 stays as it is.
|
|
90
107
|
|
|
91
|
-
|
|
92
|
-
-
|
|
93
|
-
- Multiple paths or URLs (comma-separated) for multi-repo analysis (e.g., integration/stack skills)
|
|
108
|
+
- `intent_hint`: the goal, in the user's words (a domain such as authentication, the consumers the skills serve, a constraint such as stable public APIs only).
|
|
109
|
+
- `scope_hint`: the folders or packages to focus on, and those to skip.
|
|
94
110
|
|
|
95
|
-
|
|
96
|
-
- `/path/to/project`
|
|
97
|
-
- `owner/repo, owner/repo2`
|
|
98
|
-
- `/path/to/project, https://github.com/owner/repo2`"
|
|
111
|
+
**Headless** (`{headless_mode}` true): ask nothing. With no path from a flag or section 1, HARD HALT (exit code 2, `halt_reason: "input-missing"`, phase `init:3`): "**No project path: headless mode requires `--project-path`.**" A hint no flag gave is empty: a headless run never reads one from the message.
|
|
99
112
|
|
|
100
|
-
|
|
113
|
+
**Interactive:** ask at most one question, and only for what is still missing:
|
|
101
114
|
|
|
102
|
-
**
|
|
103
|
-
-
|
|
104
|
-
- **
|
|
105
|
-
- Store as `project_paths[]` array in report frontmatter (single path stored as 1-element array for consistency)
|
|
106
|
-
- **IF `constituent_refs` was built from `--target-refs`:** Validate that every key in the map matches an entry in `project_paths[]`. If any key has no matching path, HALT: "constituent_refs key `{key}` does not match any entry in project_paths."
|
|
115
|
+
- **No path yet:** "**Which project should I analyze?** Give the root path(s) or URL(s), comma-separated for several repositories (`/path/to/project`, `owner/repo, owner/repo2`). Optionally add what you want out of it and anything to focus on or skip (for example: auth packages only, skip `vendor/`)."
|
|
116
|
+
- **A path, but no goal:** "**What should this analysis focus on, or keep out?** A domain, packages, folders to skip. Press Enter to analyze everything."
|
|
117
|
+
- **A path and a goal:** ask nothing.
|
|
107
118
|
|
|
108
|
-
|
|
119
|
+
Wait for the answer, then fill what is still missing from it: `project_paths[]`, `intent_hint` and `scope_hint`, each empty when the answer gives none. A value the invocation gave stays.
|
|
109
120
|
|
|
110
|
-
|
|
121
|
+
### 4. Validate the Inputs
|
|
111
122
|
|
|
112
|
-
|
|
123
|
+
**Paths:** for each entry of `project_paths[]`, check that it exists (local) or is accessible (remote). An invalid one: "Path `{path}` doesn't appear to be valid. Please correct it." and wait for the corrected path. In headless mode no one can correct it: HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `init:4`, path `{path}`) with that message.
|
|
113
124
|
|
|
114
|
-
|
|
115
|
-
- Skills for a specific domain (e.g., 'authentication and authorization')
|
|
116
|
-
- Target consumer agents (e.g., 'skills our backend team's AI assistants will call')
|
|
117
|
-
- Constraints (e.g., 'we only want stable public APIs, no internal modules')
|
|
125
|
+
**Ref pins:** `--target-ref <ref>` names one git tag or branch for every project path: `target_ref` ← it. `--target-refs <mapping>` names one per path, as comma-separated `path:ref` pairs (`owner/repo:v1.0.0,owner/repo2:main`), and every key must be an entry of `project_paths[]`, else HARD HALT (exit code 2, `halt_reason: "input-missing"`, phase `init:4`): "`--target-refs` key `{key}` does not match any entry in project_paths." The two are mutually exclusive: when both are passed, HARD HALT (exit code 2, `halt_reason: "input-missing"`, phase `init:4`): "`--target-refs` and `--target-ref` are mutually exclusive. Use `--target-refs` for one ref per path, or `--target-ref` for one ref for every path." Resolve each project path's **ref** once, here: its `--target-refs` entry, else `target_ref`, else none (the default ref: HEAD for a local path, the default branch for a remote one). `refs` ← each project path that has a ref, mapped to it (`{}` when none has one). Every later step reads a path's ref from `refs` alone: scan-project reads each path at its ref, and generate-briefs writes each unit's ref into its brief as `target_ref`.
|
|
118
126
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
Wait for user input. Store as workflow-context `intent_hint` (empty string if skipped).
|
|
122
|
-
|
|
123
|
-
### 4. Collect Optional Scope Hints
|
|
124
|
-
|
|
125
|
-
**Headless flag consumption:** If `--scope-hint <text>` was passed at invocation, set workflow-context `scope_hint` directly from the flag value, skip the prompt below, and proceed. If `{headless_mode}` is true and no `--scope-hint` was supplied, set `scope_hint = ""` (empty) and proceed without prompting.
|
|
126
|
-
|
|
127
|
-
"**Optional: Do you have scope hints to narrow the analysis?**
|
|
128
|
-
|
|
129
|
-
For example:
|
|
130
|
-
- Specific packages to focus on (e.g., `packages/auth`, `services/api`)
|
|
131
|
-
- Directories to exclude (e.g., `vendor/`, `node_modules/`, `dist/`)
|
|
132
|
-
|
|
133
|
-
Enter scope hints, or press Enter to analyze the entire project."
|
|
127
|
+
### 5. Check for Existing Skills
|
|
134
128
|
|
|
135
|
-
|
|
129
|
+
A unit is already skilled when a compiled skill carries its name. A brief alone does not make it one: an earlier analysis, archived in section 1, may have written it. **Resolve `{skillInventoryHelper}`** from `{skillInventoryProbeOrder}`; first existing path wins. If neither exists, HARD HALT (exit code 3, `halt_reason: "resolution-failure"`, phase `init:5`): "`skf-skill-inventory.py` is missing. Re-install SKF." List the compiled skills:
|
|
136
130
|
|
|
137
|
-
|
|
131
|
+
```bash
|
|
132
|
+
uv run {skillInventoryHelper} "{skills_output_folder}"
|
|
133
|
+
```
|
|
138
134
|
|
|
139
|
-
|
|
135
|
+
`existing_skills` ← the `name` of every `skills[]` entry whose `skf_skill` is true (none when it exits non-zero: no skills folder yet). A skill SKF did not generate is left out: update-skill, which an already-skilled unit is sent to, changes only the skills SKF generated. Then scan `{forge_data_folder}/*/skill-brief.yaml` (one level deep: each skill has its own subdirectory): `existing_briefs` ← `{name, path}` of each brief whose folder name is not in `existing_skills`.
|
|
140
136
|
|
|
141
137
|
**IF existing skills found:**
|
|
142
138
|
"**Existing skills detected:**
|
|
@@ -144,12 +140,15 @@ Scan `{forge_data_folder}/*/skill-brief.yaml` (one level deep — each skill has
|
|
|
144
140
|
|
|
145
141
|
These units will be flagged as 'already skilled' during analysis. If source changes are detected, I'll recommend running update-skill instead of generating new briefs."
|
|
146
142
|
|
|
147
|
-
**IF
|
|
143
|
+
**IF existing briefs found:**
|
|
144
|
+
"**Briefs with no compiled skill yet:** {list each name and path}. Their units are analyzed again; a brief is rewritten only when you confirm its unit."
|
|
145
|
+
|
|
146
|
+
**IF neither found:**
|
|
148
147
|
"**No existing skills found.** All identified units will be treated as new."
|
|
149
148
|
|
|
150
149
|
### 6. Create Analysis Report
|
|
151
150
|
|
|
152
|
-
Create {outputFile} from {templateFile}. If the write fails, HARD HALT
|
|
151
|
+
Create {outputFile} from {templateFile}. If the write fails, HARD HALT (exit code 4, `halt_reason: "write-failed"`, phase `init:6`, path `{outputFile}`): "The analysis report could not be written: {the error}."
|
|
153
152
|
|
|
154
153
|
**Populate frontmatter:**
|
|
155
154
|
```yaml
|
|
@@ -160,9 +159,11 @@ date: '{current_date}'
|
|
|
160
159
|
user_name: '{user_name}'
|
|
161
160
|
project_name: '{project_name}'
|
|
162
161
|
project_paths: ['{provided_project_path}']
|
|
163
|
-
|
|
162
|
+
target_ref: '{target_ref, or empty}'
|
|
163
|
+
refs: {each project path with a ref: its ref}
|
|
164
164
|
forge_tier: '{detected_tier}'
|
|
165
165
|
existing_skills: [{list of existing skill names}]
|
|
166
|
+
existing_briefs: [{name and path of each existing brief, as {name: '...', path: '...'}}]
|
|
166
167
|
intent_hint: '{intent_hint or empty string}'
|
|
167
168
|
scope_hint: '{scope_hint or empty string}'
|
|
168
169
|
confirmed_units: []
|
|
@@ -170,14 +171,15 @@ stack_skill_candidates: []
|
|
|
170
171
|
nextWorkflow: ''
|
|
171
172
|
```
|
|
172
173
|
|
|
173
|
-
|
|
174
|
+
`target_ref` stays for a path that discover-additional-source adds later, which takes it as its ref.
|
|
174
175
|
|
|
175
176
|
"**Initialization complete.**
|
|
176
177
|
|
|
177
|
-
**Project:** {
|
|
178
|
+
**Project:** {project_paths, each with its ref when it has one}
|
|
178
179
|
**Forge Tier:** {forge_tier}
|
|
179
180
|
**Existing Skills:** {count}
|
|
180
|
-
**
|
|
181
|
+
**Goal:** {intent_hint, or 'None: every unit is analyzed'}
|
|
182
|
+
**Scope Hints:** {scope_hint, or 'None: full project analysis'}
|
|
181
183
|
|
|
182
184
|
**Proceeding to project scan...**"
|
|
183
185
|
|