bmad-module-skill-forge 1.4.1 → 1.5.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 +0 -8
- package/docs/_data/pinned.yaml +1 -1
- package/docs/_internal/STABILITY.md +1 -1
- package/docs/architecture.md +2 -2
- package/docs/examples.md +1 -1
- package/docs/workflows.md +5 -5
- package/package.json +2 -2
- package/src/README.md +1 -1
- package/src/knowledge/ccc-bridge.md +12 -12
- package/src/knowledge/qmd-registry.md +5 -5
- package/src/shared/health-check.md +5 -5
- package/src/shared/references/description-guard-protocol.md +100 -0
- package/src/shared/references/output-contract-schema.md +1 -1
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -6
- package/src/shared/scripts/schemas/skf-setup-result-envelope.v1.json +9 -3
- package/src/shared/scripts/schemas/skf-update-result-envelope.v1.json +149 -0
- package/src/shared/scripts/schemas/skill-brief.v1.json +22 -2
- package/src/shared/scripts/skf-build-change-manifest.py +420 -0
- package/src/shared/scripts/skf-check-workspace-drift.py +321 -0
- package/src/shared/scripts/skf-compare-file-hashes.py +357 -0
- package/src/shared/scripts/skf-description-guard.py +359 -0
- package/src/shared/scripts/skf-detect-language.py +2 -2
- package/src/shared/scripts/skf-detect-scripts-assets.py +613 -0
- package/src/shared/scripts/skf-detect-tools.py +97 -8
- package/src/shared/scripts/skf-detect-workspaces.py +1 -1
- package/src/shared/scripts/skf-disqualify-candidates.py +576 -0
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +3 -3
- package/src/shared/scripts/skf-emit-result-envelope.py +93 -9
- package/src/shared/scripts/skf-enumerate-stack-skills.py +514 -0
- package/src/shared/scripts/skf-forge-tier-rw.py +11 -11
- package/src/shared/scripts/skf-hash-content.py +284 -0
- package/src/shared/scripts/skf-load-provenance.py +295 -0
- package/src/shared/scripts/skf-merge-ccc-exclusions.py +34 -4
- package/src/shared/scripts/skf-pair-intersect.py +250 -0
- package/src/shared/scripts/skf-provenance-gap-dispatch.py +433 -0
- package/src/shared/scripts/skf-qmd-classify-collections.py +42 -8
- package/src/shared/scripts/skf-recommend-scope-type.py +2 -2
- package/src/shared/scripts/skf-render-quick-metadata.py +2 -2
- package/src/shared/scripts/skf-resolve-authoritative-files.py +504 -0
- package/src/shared/scripts/skf-scan-manifests.py +738 -0
- package/src/shared/scripts/skf-scan-skill-md-structure.py +375 -0
- package/src/shared/scripts/skf-update-active-symlink.py +315 -0
- package/src/shared/scripts/skf-validate-brief-inputs.py +5 -5
- package/src/shared/scripts/skf-validate-brief-schema.py +348 -0
- package/src/shared/scripts/skf-write-skill-brief.py +61 -5
- package/src/skf-analyze-source/SKILL.md +69 -16
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +55 -0
- package/src/skf-analyze-source/{steps-c/step-01b-continue.md → references/continue.md} +12 -12
- package/src/skf-analyze-source/{steps-c/step-06-generate-briefs.md → references/generate-briefs.md} +29 -10
- package/src/skf-analyze-source/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-analyze-source/{steps-c/step-03-identify-units.md → references/identify-units.md} +44 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +27 -6
- package/src/skf-analyze-source/{steps-c/step-04-map-and-detect.md → references/map-and-detect.md} +52 -25
- package/src/skf-analyze-source/{steps-c/step-05-recommend.md → references/recommend.md} +15 -8
- package/src/skf-analyze-source/{steps-c/step-02-scan-project.md → references/scan-project.md} +12 -10
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -0
- package/src/skf-analyze-source/templates/analysis-report-template.md +6 -6
- package/src/skf-audit-skill/SKILL.md +66 -15
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -5
- package/src/skf-audit-skill/customize.toml +49 -0
- package/src/skf-audit-skill/{steps-c/step-07-health-check.md → references/health-check.md} +5 -3
- package/src/skf-audit-skill/{steps-c/step-01-init.md → references/init.md} +57 -19
- package/src/skf-audit-skill/{steps-c/step-02-re-index.md → references/re-index.md} +11 -11
- package/src/skf-audit-skill/{steps-c/step-06-report.md → references/report.md} +25 -7
- package/src/skf-audit-skill/{steps-c/step-04-semantic-diff.md → references/semantic-diff.md} +6 -6
- package/src/skf-audit-skill/{steps-c/step-05-severity-classify.md → references/severity-classify.md} +5 -5
- package/src/skf-audit-skill/references/severity-rules.md +2 -0
- package/src/skf-audit-skill/{steps-c/step-03-structural-diff.md → references/structural-diff.md} +29 -17
- package/src/skf-brief-skill/SKILL.md +48 -18
- package/src/skf-brief-skill/assets/description-voice-examples.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +32 -2
- package/src/skf-brief-skill/customize.toml +44 -0
- package/src/skf-brief-skill/{steps-c/step-02-analyze-target.md → references/analyze-target.md} +5 -5
- package/src/skf-brief-skill/{steps-c/step-04-confirm-brief.md → references/confirm-brief.md} +13 -10
- package/src/skf-brief-skill/references/draft-checkpoint.md +4 -4
- package/src/skf-brief-skill/{steps-c/step-01-gather-intent.md → references/gather-intent.md} +24 -24
- package/src/skf-brief-skill/references/headless-args.md +9 -9
- package/src/skf-brief-skill/references/headless-source-authority-detection.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-06-health-check.md → references/health-check.md} +4 -2
- package/src/skf-brief-skill/references/portfolio-similarity-check.md +2 -2
- package/src/skf-brief-skill/references/qmd-collection-registration.md +1 -1
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +19 -16
- package/src/skf-brief-skill/references/version-resolution.md +2 -2
- package/src/skf-brief-skill/{steps-c/step-05-write-brief.md → references/write-brief.md} +11 -10
- package/src/skf-create-skill/SKILL.md +25 -19
- package/src/skf-create-skill/assets/compile-assembly-rules.md +3 -3
- package/src/skf-create-skill/assets/skill-sections.md +5 -5
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +11 -11
- package/src/skf-create-skill/customize.toml +35 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +142 -0
- package/src/skf-create-skill/{steps-c/step-05-compile.md → references/compile.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-03d-component-extraction.md → references/component-extraction.md} +16 -16
- package/src/skf-create-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +4 -4
- package/src/skf-create-skill/{steps-c/step-04-enrich.md → references/enrich.md} +3 -3
- package/src/skf-create-skill/{steps-c/step-03-extract.md → references/extract.md} +52 -120
- package/src/skf-create-skill/references/extraction-patterns.md +8 -8
- package/src/skf-create-skill/{steps-c/step-07-generate-artifacts.md → references/generate-artifacts.md} +11 -11
- package/src/skf-create-skill/{steps-c/step-09-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-skill/{steps-c/step-01-load-brief.md → references/load-brief.md} +40 -32
- package/src/skf-create-skill/{steps-c/step-08-report.md → references/report.md} +8 -8
- package/src/skf-create-skill/references/source-resolution-protocols.md +6 -6
- package/src/skf-create-skill/{steps-c/sub/step-02b-ccc-discover.md → references/sub/ccc-discover.md} +5 -5
- package/src/skf-create-skill/{steps-c/sub/step-03c-fetch-docs.md → references/sub/fetch-docs.md} +28 -12
- package/src/skf-create-skill/{steps-c/sub/step-03b-fetch-temporal.md → references/sub/fetch-temporal.md} +81 -50
- package/src/skf-create-skill/{steps-c/step-06-validate.md → references/validate.md} +46 -26
- package/src/skf-create-stack-skill/SKILL.md +76 -17
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +102 -0
- package/src/skf-create-stack-skill/assets/stack-skill-template.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +46 -0
- package/src/skf-create-stack-skill/{steps-c/step-06-compile-stack.md → references/compile-stack.md} +6 -5
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +3 -1
- package/src/skf-create-stack-skill/{steps-c/step-05-detect-integrations.md → references/detect-integrations.md} +32 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +28 -28
- package/src/skf-create-stack-skill/{steps-c/step-07-generate-output.md → references/generate-output.md} +11 -85
- package/src/skf-create-stack-skill/{steps-c/step-10-health-check.md → references/health-check.md} +4 -2
- package/src/skf-create-stack-skill/{steps-c/step-01-init.md → references/init.md} +70 -4
- package/src/skf-create-stack-skill/references/integration-patterns.md +2 -0
- package/src/skf-create-stack-skill/references/manifest-patterns.md +2 -0
- package/src/skf-create-stack-skill/{steps-c/step-04-parallel-extract.md → references/parallel-extract.md} +40 -17
- package/src/skf-create-stack-skill/{steps-c/step-03-rank-and-confirm.md → references/rank-and-confirm.md} +5 -4
- package/src/skf-create-stack-skill/{steps-c/step-09-report.md → references/report.md} +3 -3
- package/src/skf-create-stack-skill/{steps-c/step-08-validate.md → references/validate.md} +6 -6
- package/src/skf-drop-skill/SKILL.md +84 -12
- package/src/skf-drop-skill/customize.toml +57 -0
- package/src/skf-drop-skill/{steps-c/step-02-execute.md → references/execute.md} +49 -34
- package/src/skf-drop-skill/{steps-c/step-04-health-check.md → references/health-check.md} +6 -4
- package/src/skf-drop-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-drop-skill/{steps-c/step-01-select.md → references/select.md} +63 -15
- package/src/skf-export-skill/SKILL.md +85 -16
- package/src/skf-export-skill/assets/managed-section-format.md +3 -3
- package/src/skf-export-skill/assets/snippet-format.md +2 -2
- package/src/skf-export-skill/customize.toml +49 -0
- package/src/skf-export-skill/{steps-c/step-03-generate-snippet.md → references/generate-snippet.md} +11 -11
- package/src/skf-export-skill/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-export-skill/{steps-c/step-01-load-skill.md → references/load-skill.md} +11 -49
- package/src/skf-export-skill/references/manifest-rebuild.md +68 -0
- package/src/skf-export-skill/references/multi-skill-mode.md +38 -0
- package/src/skf-export-skill/references/orphan-context-detection.md +75 -0
- package/src/skf-export-skill/references/orphan-row-detection.md +102 -0
- package/src/skf-export-skill/{steps-c/step-02-package.md → references/package.md} +7 -7
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +74 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +20 -8
- package/src/skf-export-skill/{steps-c/step-05-token-report.md → references/token-report.md} +5 -5
- package/src/skf-export-skill/{steps-c/step-04-update-context.md → references/update-context.md} +109 -113
- package/src/skf-quick-skill/SKILL.md +63 -123
- package/src/skf-quick-skill/customize.toml +44 -0
- package/src/skf-quick-skill/references/batch-mode.md +102 -0
- package/src/skf-quick-skill/{steps-c/step-04-compile.md → references/compile.md} +10 -10
- package/src/skf-quick-skill/{steps-c/step-02-ecosystem-check.md → references/ecosystem-check.md} +5 -5
- package/src/skf-quick-skill/{steps-c/step-06-finalize.md → references/finalize.md} +7 -7
- package/src/skf-quick-skill/{steps-c/step-07-health-check.md → references/health-check.md} +3 -3
- package/src/skf-quick-skill/{steps-c/step-03-quick-extract.md → references/quick-extract.md} +5 -5
- package/src/skf-quick-skill/references/registry-resolution.md +2 -0
- package/src/skf-quick-skill/{steps-c/step-01-resolve-target.md → references/resolve-target.md} +14 -10
- package/src/skf-quick-skill/{steps-c/step-05-write-and-validate.md → references/write-and-validate.md} +4 -4
- package/src/skf-refine-architecture/SKILL.md +86 -16
- package/src/skf-refine-architecture/customize.toml +49 -0
- package/src/skf-refine-architecture/{steps-c/step-05-compile.md → references/compile.md} +4 -4
- package/src/skf-refine-architecture/{steps-c/step-02-gap-analysis.md → references/gap-analysis.md} +5 -5
- package/src/skf-refine-architecture/{steps-c/step-07-health-check.md → references/health-check.md} +6 -4
- package/src/skf-refine-architecture/{steps-c/step-04-improvements.md → references/improvements.md} +5 -5
- package/src/skf-refine-architecture/references/init.md +144 -0
- package/src/skf-refine-architecture/{steps-c/step-03-issue-detection.md → references/issue-detection.md} +5 -5
- package/src/skf-refine-architecture/references/refinement-rules.md +2 -0
- package/src/skf-refine-architecture/{steps-c/step-06-report.md → references/report.md} +14 -5
- package/src/skf-rename-skill/SKILL.md +82 -12
- package/src/skf-rename-skill/customize.toml +52 -0
- package/src/skf-rename-skill/{steps-c/step-02-execute.md → references/execute.md} +94 -99
- package/src/skf-rename-skill/references/health-check.md +30 -0
- package/src/skf-rename-skill/references/rebuild-context.md +110 -0
- package/src/skf-rename-skill/{steps-c/step-03-report.md → references/report.md} +13 -5
- package/src/skf-rename-skill/{steps-c/step-01-select.md → references/select.md} +59 -20
- package/src/skf-setup/SKILL.md +35 -35
- package/src/skf-setup/customize.toml +33 -0
- package/src/skf-setup/{steps-c/step-03-auto-index.md → references/auto-index.md} +10 -18
- package/src/skf-setup/{steps-c/step-01b-ccc-index.md → references/ccc-index.md} +16 -31
- package/src/skf-setup/{steps-c/step-01-detect-and-tier.md → references/detect-and-tier.md} +23 -10
- package/src/skf-setup/{steps-c/step-05-health-check.md → references/health-check.md} +1 -1
- package/src/skf-setup/{steps-c/step-04-report.md → references/report.md} +21 -19
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-setup/{steps-c/step-02-write-config.md → references/write-config.md} +14 -13
- package/src/skf-test-skill/SKILL.md +77 -15
- package/src/skf-test-skill/customize.toml +54 -0
- package/src/skf-test-skill/{steps-c/step-04-coherence-check.md → references/coherence-check.md} +28 -71
- package/src/skf-test-skill/{steps-c/step-03-coverage-check.md → references/coverage-check.md} +16 -39
- package/src/skf-test-skill/{steps-c/step-02-detect-mode.md → references/detect-mode.md} +4 -26
- package/src/skf-test-skill/{steps-c/step-04b-external-validators.md → references/external-validators.md} +6 -28
- package/src/skf-test-skill/references/health-check.md +14 -0
- package/src/skf-test-skill/{steps-c/step-01-init.md → references/init.md} +21 -37
- package/src/skf-test-skill/references/migration-section-rules.md +4 -2
- package/src/skf-test-skill/{steps-c/step-06-report.md → references/report.md} +41 -51
- package/src/skf-test-skill/{steps-c/step-05-score.md → references/score.md} +26 -43
- package/src/skf-test-skill/references/scoring-rules.md +8 -6
- package/src/skf-test-skill/references/source-access-protocol.md +7 -5
- package/src/skf-test-skill/scripts/compute-score.py +88 -17
- package/src/skf-test-skill/templates/test-report-template.md +13 -13
- package/src/skf-update-skill/SKILL.md +23 -14
- package/src/skf-update-skill/customize.toml +44 -0
- package/src/skf-update-skill/{steps-c/step-02-detect-changes.md → references/detect-changes.md} +176 -68
- package/src/skf-update-skill/references/health-check.md +32 -0
- package/src/skf-update-skill/{steps-c/step-01-init.md → references/init.md} +56 -8
- package/src/skf-update-skill/references/manual-section-rules.md +4 -0
- package/src/skf-update-skill/references/merge-conflict-rules.md +4 -0
- package/src/skf-update-skill/{steps-c/step-04-merge.md → references/merge.md} +8 -8
- package/src/skf-update-skill/{steps-c/step-03-re-extract.md → references/re-extract.md} +53 -44
- package/src/skf-update-skill/references/remote-source-resolution.md +5 -1
- package/src/skf-update-skill/references/report.md +214 -0
- package/src/skf-update-skill/{steps-c/step-05-validate.md → references/validate.md} +5 -5
- package/src/skf-update-skill/{steps-c/step-06-write.md → references/write.md} +73 -51
- package/src/skf-verify-stack/SKILL.md +89 -17
- package/src/skf-verify-stack/assets/feasibility-report-template.md +4 -4
- package/src/skf-verify-stack/customize.toml +50 -0
- package/src/skf-verify-stack/references/coverage-patterns.md +2 -2
- package/src/skf-verify-stack/{steps-c/step-02-coverage.md → references/coverage.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-07-health-check.md → references/health-check.md} +7 -5
- package/src/skf-verify-stack/references/init.md +166 -0
- package/src/skf-verify-stack/references/integration-verification-rules.md +1 -1
- package/src/skf-verify-stack/{steps-c/step-03-integrations.md → references/integrations.md} +12 -12
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +22 -41
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +7 -7
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +8 -8
- package/tools/validate-docs-drift.js +1 -1
- package/src/skf-refine-architecture/steps-c/step-01-init.md +0 -136
- package/src/skf-rename-skill/steps-c/step-04-health-check.md +0 -22
- package/src/skf-test-skill/steps-c/step-07-health-check.md +0 -25
- package/src/skf-update-skill/steps-c/step-07-report.md +0 -148
- package/src/skf-update-skill/steps-c/step-08-health-check.md +0 -22
- package/src/skf-verify-stack/steps-c/step-01-init.md +0 -178
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.10"
|
|
3
|
-
# dependencies = []
|
|
3
|
+
# dependencies = ["pyyaml"]
|
|
4
4
|
# ///
|
|
5
5
|
"""SKF Detect Tools — Parallel tool detection + tier calculation for skf-setup.
|
|
6
6
|
|
|
7
|
-
Replaces the prose-driven tool-detection sequence in `src/skf-setup/
|
|
8
|
-
|
|
7
|
+
Replaces the prose-driven tool-detection sequence in `src/skf-setup/references/
|
|
8
|
+
detect-and-tier.md` §3-§8b with one Python invocation. Probes ast-grep,
|
|
9
9
|
gh, qmd, and ccc concurrently, applies the 4-rule tier decision table (see
|
|
10
10
|
`src/skf-setup/references/tier-rules.md`), evaluates --tier-override (with
|
|
11
11
|
sanity check) and --require-tier (with tool-prerequisite check independent of
|
|
12
12
|
the tier name), and emits one JSON document on stdout.
|
|
13
13
|
|
|
14
14
|
Schema documented in DETECT_OUTPUT_SCHEMA at the bottom of this docstring.
|
|
15
|
-
The output is consumed by step
|
|
16
|
-
and step
|
|
15
|
+
The output is consumed by step 1 prose, step 2 (forge-tier.yaml writer),
|
|
16
|
+
and step 4 (status report + envelope).
|
|
17
17
|
|
|
18
18
|
Tier rules (first match wins):
|
|
19
19
|
Deep = ast-grep + gh-cli + qmd (all healthy)
|
|
@@ -21,12 +21,12 @@ Tier rules (first match wins):
|
|
|
21
21
|
Forge = ast-grep
|
|
22
22
|
Quick = otherwise
|
|
23
23
|
|
|
24
|
-
CCC verification is two-step (matches step
|
|
24
|
+
CCC verification is two-step (matches step 1 §7):
|
|
25
25
|
Step A: `ccc --help` exits 0 AND output contains "CocoIndex Code" marker.
|
|
26
26
|
Rejects code2prompt-aliased-as-ccc and similar PATH shadowing.
|
|
27
27
|
Step B: `ccc doctor` succeeds (daemon healthy).
|
|
28
28
|
|
|
29
|
-
QMD verification is two-step (matches step
|
|
29
|
+
QMD verification is two-step (matches step 1 §5 post-PR-#248):
|
|
30
30
|
Step A: `qmd --version` exits 0 (binary identity, falls back to --help).
|
|
31
31
|
Step B: `qmd status` succeeds (daemon healthy).
|
|
32
32
|
qmd_status: "absent" | "daemon_stopped" | "healthy" — affects climb hint.
|
|
@@ -251,6 +251,50 @@ def tier_prerequisites_met(tier: str, tools: dict) -> tuple[bool, list[str]]:
|
|
|
251
251
|
return (len(missing) == 0, missing)
|
|
252
252
|
|
|
253
253
|
|
|
254
|
+
def read_prior_state(prior_state_path) -> dict:
|
|
255
|
+
"""Read forge-tier.yaml from a previous run, return prior tier / tools / detection_date.
|
|
256
|
+
|
|
257
|
+
Returns a flat dict (always present, keys always set) so callers don't
|
|
258
|
+
branch on missing-file vs empty-file vs malformed-file — the script owns
|
|
259
|
+
that classification. On any read failure or absent file, returns the
|
|
260
|
+
"first-run" shape (everything null/empty). The CCC freshness fields are
|
|
261
|
+
surfaced separately so the caller doesn't reparse YAML in prose.
|
|
262
|
+
"""
|
|
263
|
+
empty = {
|
|
264
|
+
"previous_tier": None,
|
|
265
|
+
"previous_detection_date": None,
|
|
266
|
+
"previous_tools": {},
|
|
267
|
+
"previous_ccc_index_status": None,
|
|
268
|
+
"previous_ccc_indexed_path": None,
|
|
269
|
+
"previous_ccc_last_indexed": None,
|
|
270
|
+
"previous_ccc_staleness_threshold_hours": None,
|
|
271
|
+
}
|
|
272
|
+
if not prior_state_path:
|
|
273
|
+
return empty
|
|
274
|
+
try:
|
|
275
|
+
import yaml # local import — only needed when --prior-state-from is used
|
|
276
|
+
from pathlib import Path as _P
|
|
277
|
+
p = _P(prior_state_path)
|
|
278
|
+
if not p.exists():
|
|
279
|
+
return empty
|
|
280
|
+
data = yaml.safe_load(p.read_text(encoding="utf-8")) or {}
|
|
281
|
+
except Exception:
|
|
282
|
+
return empty
|
|
283
|
+
|
|
284
|
+
tools_map = data.get("tools") if isinstance(data.get("tools"), dict) else {}
|
|
285
|
+
ccc_index = data.get("ccc_index") if isinstance(data.get("ccc_index"), dict) else {}
|
|
286
|
+
|
|
287
|
+
return {
|
|
288
|
+
"previous_tier": data.get("tier") if data.get("tier") in VALID_TIERS else None,
|
|
289
|
+
"previous_detection_date": data.get("tier_detected_at"),
|
|
290
|
+
"previous_tools": tools_map,
|
|
291
|
+
"previous_ccc_index_status": ccc_index.get("status"),
|
|
292
|
+
"previous_ccc_indexed_path": ccc_index.get("indexed_path"),
|
|
293
|
+
"previous_ccc_last_indexed": ccc_index.get("last_indexed"),
|
|
294
|
+
"previous_ccc_staleness_threshold_hours": ccc_index.get("staleness_threshold_hours"),
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
|
|
254
298
|
def detect(args: argparse.Namespace) -> dict:
|
|
255
299
|
tools: dict = {}
|
|
256
300
|
with ThreadPoolExecutor(max_workers=4) as ex:
|
|
@@ -302,6 +346,9 @@ def detect(args: argparse.Namespace) -> dict:
|
|
|
302
346
|
else:
|
|
303
347
|
require_satisfied = None
|
|
304
348
|
|
|
349
|
+
prior = read_prior_state(getattr(args, "prior_state_from", None))
|
|
350
|
+
deltas = compute_deltas(tools, prior, calculated)
|
|
351
|
+
|
|
305
352
|
return {
|
|
306
353
|
"tools": tools,
|
|
307
354
|
"tier": {
|
|
@@ -320,6 +367,38 @@ def detect(args: argparse.Namespace) -> dict:
|
|
|
320
367
|
"satisfied": require_satisfied,
|
|
321
368
|
"missing_tools": require_missing,
|
|
322
369
|
},
|
|
370
|
+
"prior": prior,
|
|
371
|
+
"deltas": deltas,
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
def compute_deltas(current_tools: dict, prior: dict, calculated_tier: str) -> dict:
|
|
376
|
+
"""Compute re-run deltas (tools added/removed, tier_changed, ccc_index_is_fresh).
|
|
377
|
+
|
|
378
|
+
Removes ~80 tokens of LLM-side set arithmetic + string compare from the
|
|
379
|
+
interactive banner branch in references/report.md. First-run convention
|
|
380
|
+
(prior.previous_tier is null): tools_added = currently-available tools,
|
|
381
|
+
tools_removed = [], tier_changed = false.
|
|
382
|
+
"""
|
|
383
|
+
tool_keys = ("ast_grep", "gh_cli", "qmd", "ccc")
|
|
384
|
+
cur_avail = {k: bool((current_tools.get(k) or {}).get("available")) for k in tool_keys}
|
|
385
|
+
|
|
386
|
+
prev_tools_raw = prior.get("previous_tools") or {}
|
|
387
|
+
if prev_tools_raw:
|
|
388
|
+
prev_avail = {k: bool(prev_tools_raw.get(k, False)) for k in tool_keys}
|
|
389
|
+
tools_added = sorted(k for k in tool_keys if cur_avail[k] and not prev_avail[k])
|
|
390
|
+
tools_removed = sorted(k for k in tool_keys if prev_avail[k] and not cur_avail[k])
|
|
391
|
+
else:
|
|
392
|
+
tools_added = sorted(k for k in tool_keys if cur_avail[k])
|
|
393
|
+
tools_removed = []
|
|
394
|
+
|
|
395
|
+
prior_tier = prior.get("previous_tier")
|
|
396
|
+
tier_changed = bool(prior_tier and prior_tier != calculated_tier)
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
"tools_added": tools_added,
|
|
400
|
+
"tools_removed": tools_removed,
|
|
401
|
+
"tier_changed": tier_changed,
|
|
323
402
|
}
|
|
324
403
|
|
|
325
404
|
|
|
@@ -332,7 +411,7 @@ def main() -> None:
|
|
|
332
411
|
"--tier-override",
|
|
333
412
|
default=None,
|
|
334
413
|
help="Force a specific tier (must be one of Quick, Forge, Forge+, Deep — case-sensitive)."
|
|
335
|
-
" Invalid values are flagged in the output rather than rejected, so step
|
|
414
|
+
" Invalid values are flagged in the output rather than rejected, so step 4 can"
|
|
336
415
|
" surface the warning to the user.",
|
|
337
416
|
)
|
|
338
417
|
parser.add_argument(
|
|
@@ -349,6 +428,16 @@ def main() -> None:
|
|
|
349
428
|
help="Environment variable name to check for security-scan availability"
|
|
350
429
|
" (informational only — does NOT affect tier). Default: SNYK_TOKEN.",
|
|
351
430
|
)
|
|
431
|
+
parser.add_argument(
|
|
432
|
+
"--prior-state-from",
|
|
433
|
+
default=None,
|
|
434
|
+
help="Optional path to a previous-run forge-tier.yaml. When provided,"
|
|
435
|
+
" the script reads it and surfaces previous_tier, previous_tools,"
|
|
436
|
+
" previous_detection_date, and previous_ccc_* fields under the 'prior'"
|
|
437
|
+
" key — removing YAML-parse responsibility from the step prompt."
|
|
438
|
+
" Missing file or unreadable YAML returns the first-run shape (all"
|
|
439
|
+
" null/empty) without erroring.",
|
|
440
|
+
)
|
|
352
441
|
args = parser.parse_args()
|
|
353
442
|
|
|
354
443
|
payload = detect(args)
|
|
@@ -8,7 +8,7 @@ Takes a JSON payload on stdin describing a target repo's file tree plus the
|
|
|
8
8
|
contents of a small set of root manifests, and returns whether a workspace
|
|
9
9
|
layout is present, which manifest kind drives it, and the list of resolved
|
|
10
10
|
workspaces. The helper does NO file I/O — the caller (typically
|
|
11
|
-
skf-brief-skill step
|
|
11
|
+
skf-brief-skill step 2 §1b) fetches files via `gh api` / local filesystem
|
|
12
12
|
and pipes the relevant content in.
|
|
13
13
|
|
|
14
14
|
Detection runs in priority order; the first matching detector wins:
|