bmad-module-skill-forge 1.9.0 → 2.0.1
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/.nvmrc +1 -1
- package/README.md +10 -5
- package/docs/_data/pinned.yaml +2 -2
- package/docs/agents.md +11 -2
- package/docs/architecture.md +5 -4
- package/docs/bmad-synergy.md +30 -7
- package/docs/campaign.md +172 -0
- package/docs/examples.md +7 -3
- package/docs/forge-auto.md +90 -0
- package/docs/getting-started.md +9 -0
- package/docs/how-it-works.md +6 -4
- package/docs/index.md +4 -3
- package/docs/skill-model.md +1 -1
- package/docs/troubleshooting.md +17 -1
- package/docs/verifying-a-skill.md +2 -2
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +64 -24
- package/package.json +2 -2
- package/src/knowledge/skill-lifecycle.md +1 -1
- package/src/module-help.csv +4 -3
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +6 -3
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- package/src/shared/scripts/skf-comention-pairs.py +350 -0
- package/src/shared/scripts/skf-count-tokens.py +222 -0
- package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +240 -4
- package/src/shared/scripts/skf-detect-language.py +82 -3
- package/src/shared/scripts/skf-detect-tools.py +105 -2
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-enumerate-stack-skills.py +111 -2
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- package/src/shared/scripts/skf-find-cycles.py +246 -0
- package/src/shared/scripts/skf-hash-content.py +487 -2
- package/src/shared/scripts/skf-language-corpora.py +100 -0
- package/src/shared/scripts/skf-manifest-ops.py +67 -1
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +1 -1
- package/src/shared/scripts/skf-rebuild-managed-sections.py +180 -0
- package/src/shared/scripts/skf-recommend-scope-type.py +1 -2
- package/src/shared/scripts/skf-render-metadata-stats.py +499 -0
- package/src/shared/scripts/skf-rewrite-skill-name.py +308 -0
- package/src/shared/scripts/skf-shape-detect.py +576 -25
- package/src/shared/scripts/skf-shard-body.py +461 -0
- package/src/shared/scripts/skf-skill-inventory.py +139 -3
- package/src/shared/scripts/skf-structural-diff.py +307 -67
- package/src/shared/scripts/skf-validate-brief-schema.py +41 -6
- package/src/shared/scripts/skf-validate-feasibility-report.py +234 -0
- package/src/shared/scripts/skf-validate-frontmatter.py +17 -12
- package/src/shared/scripts/skf-validate-output.py +443 -10
- package/src/shared/scripts/skf-validate-pins.py +3 -3
- package/src/shared/scripts/skf-verify-no-trace.py +214 -0
- package/src/shared/scripts/skf-verify-provenance-completeness.py +439 -0
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +17 -32
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/customize.toml +2 -0
- package/src/skf-analyze-source/references/auto-docs-only.md +116 -0
- package/src/skf-analyze-source/references/continue.md +8 -13
- package/src/skf-analyze-source/references/generate-briefs.md +28 -12
- package/src/skf-analyze-source/references/headless-contract.md +33 -0
- package/src/skf-analyze-source/references/health-check.md +1 -2
- package/src/skf-analyze-source/references/identify-units.md +25 -36
- package/src/skf-analyze-source/references/init.md +12 -25
- package/src/skf-analyze-source/references/map-and-detect.md +8 -20
- package/src/skf-analyze-source/references/recommend.md +4 -14
- package/src/skf-analyze-source/references/scan-project.md +3 -11
- package/src/skf-analyze-source/references/step-auto-scope.md +211 -197
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- package/src/skf-analyze-source/references/unit-detection-heuristics.md +2 -2
- package/src/skf-audit-skill/SKILL.md +9 -6
- package/src/skf-audit-skill/customize.toml +2 -0
- package/src/skf-audit-skill/references/init.md +58 -32
- package/src/skf-audit-skill/references/re-index.md +15 -34
- package/src/skf-audit-skill/references/report.md +11 -58
- package/src/skf-audit-skill/references/semantic-diff.md +4 -22
- package/src/skf-audit-skill/references/severity-classify.md +53 -87
- package/src/skf-audit-skill/references/step-doc-drift.md +49 -19
- package/src/skf-audit-skill/references/structural-diff.md +43 -68
- package/src/skf-brief-skill/SKILL.md +7 -36
- package/src/skf-brief-skill/assets/scope-templates.md +1 -1
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/customize.toml +14 -0
- package/src/skf-brief-skill/references/analyze-target.md +13 -18
- package/src/skf-brief-skill/references/confirm-brief.md +2 -15
- package/src/skf-brief-skill/references/draft-checkpoint.md +8 -8
- package/src/skf-brief-skill/references/gather-intent.md +27 -24
- package/src/skf-brief-skill/references/headless-args.md +1 -1
- package/src/skf-brief-skill/references/health-check.md +1 -22
- package/src/skf-brief-skill/references/invocation-contract.md +37 -0
- package/src/skf-brief-skill/references/scope-definition.md +6 -15
- package/src/skf-brief-skill/references/step-auto-brief.md +22 -9
- package/src/skf-brief-skill/references/step-auto-validate.md +3 -7
- package/src/skf-brief-skill/references/version-resolution.md +1 -1
- package/src/skf-brief-skill/references/write-brief.md +19 -13
- package/src/skf-campaign/SKILL.md +121 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +75 -0
- package/src/skf-campaign/manifest.yaml +15 -0
- package/src/skf-campaign/references/campaign-contracts.md +67 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +32 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +121 -0
- package/src/skf-campaign/references/step-02-strategy.md +102 -0
- package/src/skf-campaign/references/step-03-pins.md +56 -0
- package/src/skf-campaign/references/step-04-provenance.md +63 -0
- package/src/skf-campaign/references/step-05-skill-loop.md +103 -0
- package/src/skf-campaign/references/step-06-batch.md +88 -0
- package/src/skf-campaign/references/step-07-capstone.md +63 -0
- package/src/skf-campaign/references/step-08-verify.md +75 -0
- package/src/skf-campaign/references/step-09-refine.md +83 -0
- package/src/skf-campaign/references/step-10-export.md +106 -0
- package/src/skf-campaign/references/step-11-maintenance.md +84 -0
- package/src/skf-campaign/references/step-resume.md +115 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +244 -0
- package/src/skf-campaign/scripts/campaign-parse-manifest.py +119 -0
- package/src/skf-campaign/scripts/campaign-provenance.py +247 -0
- package/src/skf-campaign/scripts/campaign-render-batch.py +199 -0
- package/src/skf-campaign/scripts/campaign-render-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -0
- package/src/skf-campaign/scripts/campaign-status.py +162 -0
- package/src/skf-campaign/scripts/campaign-validate-pins.py +174 -0
- package/src/skf-campaign/scripts/campaign-validate-state.py +207 -0
- package/src/skf-campaign/templates/campaign-brief-template.yaml +34 -0
- package/src/skf-campaign/templates/campaign-report-template.md +54 -0
- package/src/skf-campaign/templates/kickoff-template.md +48 -0
- package/src/skf-create-skill/SKILL.md +15 -4
- package/src/skf-create-skill/assets/compile-assembly-rules.md +35 -34
- package/src/skf-create-skill/assets/skill-sections.md +9 -100
- package/src/skf-create-skill/assets/tessl-dismissal-rules.md +4 -13
- package/src/skf-create-skill/customize.toml +13 -0
- package/src/skf-create-skill/references/authoritative-files-protocol.md +7 -7
- package/src/skf-create-skill/references/compile.md +37 -47
- package/src/skf-create-skill/references/component-extraction.md +8 -35
- package/src/skf-create-skill/references/ecosystem-check.md +9 -25
- package/src/skf-create-skill/references/enrich.md +4 -17
- package/src/skf-create-skill/references/extract.md +20 -27
- package/src/skf-create-skill/references/extraction-patterns-tracing.md +1 -1
- package/src/skf-create-skill/references/extraction-patterns.md +10 -8
- package/src/skf-create-skill/references/generate-artifacts.md +20 -25
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/load-brief.md +16 -18
- package/src/skf-create-skill/references/report.md +27 -14
- package/src/skf-create-skill/references/source-resolution-protocols.md +4 -4
- package/src/skf-create-skill/references/step-auto-shard.md +52 -25
- package/src/skf-create-skill/references/step-doc-rot.md +33 -15
- package/src/skf-create-skill/references/step-doc-sources.md +13 -4
- package/src/skf-create-skill/references/sub/ccc-discover.md +2 -13
- package/src/skf-create-skill/references/sub/fetch-docs.md +33 -46
- package/src/skf-create-skill/references/sub/fetch-temporal.md +5 -20
- package/src/skf-create-skill/references/tier-degradation-rules.md +6 -8
- package/src/skf-create-skill/references/validate.md +69 -29
- package/src/skf-create-skill/scripts/scan-doc-rot.py +245 -0
- package/src/skf-create-stack-skill/SKILL.md +15 -9
- package/src/skf-create-stack-skill/assets/provenance-map-schema.md +1 -1
- package/src/skf-create-stack-skill/customize.toml +10 -0
- package/src/skf-create-stack-skill/references/compile-stack.md +7 -8
- package/src/skf-create-stack-skill/references/compose-mode-rules.md +2 -13
- package/src/skf-create-stack-skill/references/detect-integrations.md +49 -54
- package/src/skf-create-stack-skill/references/detect-manifests.md +37 -30
- package/src/skf-create-stack-skill/references/generate-output.md +24 -75
- package/src/skf-create-stack-skill/references/init.md +9 -81
- package/src/skf-create-stack-skill/references/manifest-patterns.md +5 -35
- package/src/skf-create-stack-skill/references/parallel-extract.md +12 -27
- package/src/skf-create-stack-skill/references/rank-and-confirm.md +6 -6
- package/src/skf-create-stack-skill/references/report.md +27 -62
- package/src/skf-create-stack-skill/references/validate.md +35 -31
- package/src/skf-drop-skill/SKILL.md +20 -23
- package/src/skf-drop-skill/customize.toml +10 -0
- package/src/skf-drop-skill/references/execute.md +67 -36
- package/src/skf-drop-skill/references/headless-contract.md +18 -0
- package/src/skf-drop-skill/references/health-check.md +1 -13
- package/src/skf-drop-skill/references/report.md +44 -10
- package/src/skf-drop-skill/references/select.md +93 -48
- package/src/skf-drop-skill/scripts/dir-sizes.py +116 -0
- package/src/skf-export-skill/SKILL.md +17 -14
- package/src/skf-export-skill/assets/managed-section-format.md +2 -5
- package/src/skf-export-skill/customize.toml +10 -6
- package/src/skf-export-skill/references/generate-snippet.md +21 -35
- package/src/skf-export-skill/references/load-skill.md +44 -42
- package/src/skf-export-skill/references/multi-skill-mode.md +1 -1
- package/src/skf-export-skill/references/orphan-context-detection.md +11 -3
- package/src/skf-export-skill/references/package.md +27 -33
- package/src/skf-export-skill/references/preflight-snippet-root-probe.md +24 -5
- package/src/skf-export-skill/references/result-envelope.md +28 -0
- package/src/skf-export-skill/references/summary.md +11 -5
- package/src/skf-export-skill/references/token-report.md +42 -24
- package/src/skf-export-skill/references/update-context.md +32 -33
- package/src/skf-forger/SKILL.md +32 -39
- package/src/skf-forger/references/pipeline-mode.md +34 -0
- package/src/skf-forger/scripts/parse-pipeline.py +270 -0
- package/src/skf-quick-skill/SKILL.md +10 -60
- package/src/skf-quick-skill/customize.toml +9 -0
- package/src/skf-quick-skill/references/batch-mode.md +6 -4
- package/src/skf-quick-skill/references/compile.md +15 -52
- package/src/skf-quick-skill/references/ecosystem-check.md +5 -20
- package/src/skf-quick-skill/references/finalize.md +12 -6
- package/src/skf-quick-skill/references/halt-contract.md +54 -0
- package/src/skf-quick-skill/references/health-check.md +3 -4
- package/src/skf-quick-skill/references/quick-extract.md +7 -18
- package/src/skf-quick-skill/references/registry-resolution.md +1 -23
- package/src/skf-quick-skill/references/resolve-target.md +27 -34
- package/src/skf-quick-skill/references/write-and-validate.md +10 -25
- package/src/skf-refine-architecture/SKILL.md +16 -8
- package/src/skf-refine-architecture/customize.toml +9 -0
- package/src/skf-refine-architecture/references/compile.md +10 -8
- package/src/skf-refine-architecture/references/gap-analysis.md +21 -50
- package/src/skf-refine-architecture/references/health-check.md +1 -1
- package/src/skf-refine-architecture/references/improvements.md +9 -25
- package/src/skf-refine-architecture/references/init.md +9 -16
- package/src/skf-refine-architecture/references/issue-detection.md +10 -25
- package/src/skf-refine-architecture/references/refinement-rules.md +4 -16
- package/src/skf-refine-architecture/references/report.md +14 -11
- package/src/skf-rename-skill/SKILL.md +11 -21
- package/src/skf-rename-skill/customize.toml +10 -0
- package/src/skf-rename-skill/references/execute.md +112 -82
- package/src/skf-rename-skill/references/exit-codes.md +12 -0
- package/src/skf-rename-skill/references/report.md +16 -8
- package/src/skf-rename-skill/references/select.md +69 -42
- package/src/skf-rename-skill/scripts/skf-validate-rename-name.py +161 -0
- package/src/skf-setup/SKILL.md +21 -13
- package/src/skf-setup/customize.toml +10 -0
- package/src/skf-setup/references/auto-index.md +11 -10
- package/src/skf-setup/references/ccc-index.md +14 -15
- package/src/skf-setup/references/detect-and-tier.md +10 -8
- package/src/skf-setup/references/report.md +26 -32
- package/src/skf-setup/references/tier-rules.md +2 -32
- package/src/skf-setup/references/write-config.md +9 -10
- package/src/skf-test-skill/SKILL.md +10 -8
- package/src/skf-test-skill/customize.toml +2 -0
- package/src/skf-test-skill/references/coherence-check.md +19 -31
- package/src/skf-test-skill/references/coverage-check.md +111 -67
- package/src/skf-test-skill/references/detect-mode.md +10 -41
- package/src/skf-test-skill/references/external-validators.md +11 -19
- package/src/skf-test-skill/references/init.md +39 -21
- package/src/skf-test-skill/references/migration-section-rules.md +4 -4
- package/src/skf-test-skill/references/report.md +60 -40
- package/src/skf-test-skill/references/score.md +32 -64
- package/src/skf-test-skill/references/scoring-rules.md +6 -62
- package/src/skf-test-skill/references/source-access-protocol.md +15 -5
- package/src/skf-test-skill/references/step-hard-gate.md +1 -3
- package/src/skf-test-skill/scripts/aggregate-coherence.py +276 -0
- package/src/skf-test-skill/scripts/check-metadata-coherence.py +359 -0
- package/src/skf-test-skill/scripts/combine-external-scores.py +190 -0
- package/src/skf-test-skill/scripts/compute-score.py +135 -4
- package/src/skf-test-skill/scripts/reconcile-coverage.py +327 -0
- package/src/skf-test-skill/scripts/validate-inventory.py +251 -0
- package/src/skf-test-skill/scripts/verify-declared-numerator.py +192 -0
- package/src/skf-update-skill/SKILL.md +17 -5
- package/src/skf-update-skill/customize.toml +11 -6
- package/src/skf-update-skill/references/detect-changes.md +48 -36
- package/src/skf-update-skill/references/health-check.md +5 -11
- package/src/skf-update-skill/references/init.md +40 -32
- package/src/skf-update-skill/references/manual-section-rules.md +1 -2
- package/src/skf-update-skill/references/merge-conflict-rules.md +1 -52
- package/src/skf-update-skill/references/merge.md +13 -57
- package/src/skf-update-skill/references/re-extract.md +27 -25
- package/src/skf-update-skill/references/report.md +14 -7
- package/src/skf-update-skill/references/validate.md +32 -30
- package/src/skf-update-skill/references/write.md +86 -51
- package/src/skf-update-skill/scripts/skf-new-file-diff.py +167 -0
- package/src/skf-verify-stack/SKILL.md +11 -21
- package/src/skf-verify-stack/customize.toml +12 -3
- package/src/skf-verify-stack/references/coverage-patterns.md +1 -29
- package/src/skf-verify-stack/references/coverage.md +21 -10
- package/src/skf-verify-stack/references/exit-codes.md +14 -0
- package/src/skf-verify-stack/references/health-check.md +1 -1
- package/src/skf-verify-stack/references/init.md +20 -25
- package/src/skf-verify-stack/references/integration-verification-rules.md +10 -19
- package/src/skf-verify-stack/references/integrations.md +44 -49
- package/src/skf-verify-stack/references/report.md +28 -34
- package/src/skf-verify-stack/references/requirements.md +3 -3
- package/src/skf-verify-stack/references/synthesize.md +36 -39
- package/src/skf-verify-stack/scripts/skf-coverage-tally.py +196 -0
- package/src/skf-verify-stack/scripts/skf-report-delta.py +256 -0
- package/src/skf-verify-stack/scripts/skf-verdict-rollup.py +258 -0
- package/tools/cli/lib/ui.js +3 -2
- package/docs/deepwiki.md +0 -89
- package/src/skf-rename-skill/references/rebuild-context.md +0 -110
|
@@ -6,6 +6,12 @@ nextStepFile: '../enrich.md'
|
|
|
6
6
|
atomicWriteProbeOrder:
|
|
7
7
|
- '{project-root}/_bmad/skf/shared/scripts/skf-atomic-write.py'
|
|
8
8
|
- '{project-root}/src/shared/scripts/skf-atomic-write.py'
|
|
9
|
+
# Resolve `{deriveAssemblyShapeHelper}` the same way — used in §1 to decide
|
|
10
|
+
# whether this is a whole-language reference (registry-corpora prose retained
|
|
11
|
+
# as a Language Guide) or a standard skill (unchanged behaviour).
|
|
12
|
+
deriveAssemblyShapeProbeOrder:
|
|
13
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-derive-assembly-shape.py'
|
|
14
|
+
- '{project-root}/src/shared/scripts/skf-derive-assembly-shape.py'
|
|
9
15
|
---
|
|
10
16
|
|
|
11
17
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -33,6 +39,14 @@ Evaluate the following conditions. **If the condition fails, skip silently to se
|
|
|
33
39
|
|
|
34
40
|
No tier gate — if `doc_urls` are present, this step runs at Quick, Forge, and Deep tiers alike.
|
|
35
41
|
|
|
42
|
+
**Determine assembly shape (whole-language gate).** Resolve `{deriveAssemblyShapeHelper}` from `{deriveAssemblyShapeProbeOrder}` (first existing path wins) and run it on the brief:
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
uv run {deriveAssemblyShapeHelper} {brief_path}
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If the result's `assembly_shape` is `whole-language-reference` (the brief carries ≥1 `doc_urls` entry with `source: language-registry` — a compiler/interpreter repo enriched with the language's canonical prose), set the in-context flag `whole_language_reference: true`. This changes ONLY how the registry-sourced corpora are handled below (§4a): their prose is retained as a **Language Guide** rather than shredded into per-export items. For every other brief the flag is false and this step behaves exactly as before — no change to ordinary skills.
|
|
49
|
+
|
|
36
50
|
### 2. Security Notice
|
|
37
51
|
|
|
38
52
|
Display an informational notice (not a gate — the user already approved these URLs in the brief):
|
|
@@ -72,7 +86,7 @@ Subpage discovery is triggered if **either** of the following independent trigge
|
|
|
72
86
|
|
|
73
87
|
The URL matches the path criteria above (ends in `/`, bare domain, or 1 segment) AND the fetched content is under **2000 words**. Short content on root-like URLs almost certainly indicates a navigation hub or landing page, even if it contains introductory code examples that would prevent Trigger 1 from firing. This handles modern doc sites (Mintlify, Docusaurus, GitBook) that include hero sections with code snippets on their root pages.
|
|
74
88
|
|
|
75
|
-
If neither trigger fires, keep the page content as-is and do
|
|
89
|
+
If neither trigger fires, keep the page content as-is and do not trigger subpage discovery.
|
|
76
90
|
|
|
77
91
|
**If a root URL with minimal content is detected:**
|
|
78
92
|
|
|
@@ -122,6 +136,19 @@ Parse the successfully fetched markdown for:
|
|
|
122
136
|
|
|
123
137
|
**No hallucination:** If information cannot be found in the fetched content, exclude it. Do not infer or fabricate API details.
|
|
124
138
|
|
|
139
|
+
**Whole-language references — retain prose, do not shred (`whole_language_reference: true`):** For a whole-language reference the registry-sourced corpora (the guide/Book, the standard/library docs) ARE the product, not the compiler's internal exports. Reducing that prose to per-export signature items and then discarding it under the §5 "T3 never overrides T1" rule (the compiler's AST already owns names like `Vec`, `Option`, `HashMap`) would gut exactly the content the skill exists to teach. So for these briefs, skip §4a below for the registry corpora.
|
|
140
|
+
|
|
141
|
+
### 4a. Retain the Language Guide (whole-language references only)
|
|
142
|
+
|
|
143
|
+
**Skip this section entirely unless `whole_language_reference: true`.** When it is true, for each `doc_urls` entry whose `source` is `language-registry`:
|
|
144
|
+
|
|
145
|
+
- Do not reduce its fetched markdown to per-export items. Instead retain the cleaned prose as a Language-Guide entry `{url, label, prose}`, where `prose` is the substantive body (narrative, idioms, usage examples, conceptual reference) lightly trimmed of navigation/boilerplate, each block cited `[EXT:{url}]`.
|
|
146
|
+
- Collect these into a `language_guide[]` context artifact, in `doc_urls` order.
|
|
147
|
+
|
|
148
|
+
This artifact is a **distinct** carrier — it is not merged into the extraction inventory and is not subject to the §5 conflict rule, so the canonical prose survives intact into step 5 (compile), which foregrounds it as the skill's Language Guide. Non-registry docs (README-detected, homepage, Pages, docs-folder) still flow through §4's normal per-export extraction and the §5 merge unchanged.
|
|
149
|
+
|
|
150
|
+
**If a registry corpus could not be fetched** (network failure), record it in `language_guide[]` as `{url, label, prose: null}` and warn — step 5 surfaces the gap rather than emitting a thin guide silently.
|
|
151
|
+
|
|
125
152
|
### 5. Build Doc-Fetch Inventory
|
|
126
153
|
|
|
127
154
|
**Mode determines merge behavior:**
|
|
@@ -129,7 +156,9 @@ Parse the successfully fetched markdown for:
|
|
|
129
156
|
- **`source_type: "docs-only"`** — The doc-fetch inventory IS the extraction inventory. It replaces the empty inventory from step 3, since there was no source code to extract from.
|
|
130
157
|
- **`source_type: "source"` (supplemental mode)** — Merge T3 items into the existing extraction inventory from step 3.
|
|
131
158
|
|
|
132
|
-
**Conflict rule:** T3 items
|
|
159
|
+
**Conflict rule:** T3 items never override existing T1, T1-low, or T2 items for the same export. When an export already has a higher-confidence entry, the T3 item is discarded — T3 has the lowest priority.
|
|
160
|
+
|
|
161
|
+
**Language-Guide carve-out:** the `language_guide[]` artifact from §4a (whole-language references) is not part of the export inventory and is therefore not subject to this conflict rule — it carries no export key, so it cannot collide with a T1 compiler export and can never be pruned. It is passed separately into step 5, which renders it as the foregrounded Language Guide section. Only the per-export T3 items participate in the T1/T2/T3 merge.
|
|
133
162
|
|
|
134
163
|
**Edge case — T1-zero supplemental mode:** If T1 extraction produced zero results and `doc_urls` are present in supplemental mode, T3 items should be used as the primary inventory since no T1 data exists to conflict with.
|
|
135
164
|
|
|
@@ -173,48 +202,6 @@ Display:
|
|
|
173
202
|
|
|
174
203
|
Proceeding to enrichment..."
|
|
175
204
|
|
|
176
|
-
### 7.
|
|
177
|
-
|
|
178
|
-
**Auto-proceed step — no user interaction.**
|
|
179
|
-
|
|
180
|
-
After documentation fetch is complete (or skipped for any reason), immediately load, read entire file, then execute `{nextStepFile}`.
|
|
181
|
-
|
|
182
|
-
#### EXECUTION RULES:
|
|
183
|
-
|
|
184
|
-
- This is an auto-proceed step with no user choices
|
|
185
|
-
- No `doc_urls` in brief: skip directly to next step with no output
|
|
186
|
-
- No web fetching available: skip with warning then auto-proceed
|
|
187
|
-
- All URLs failed: skip with warning then auto-proceed
|
|
188
|
-
- Successful fetch: display report then auto-proceed
|
|
189
|
-
- All failures degrade gracefully — skip and auto-proceed
|
|
190
|
-
|
|
191
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
192
|
-
|
|
193
|
-
ONLY WHEN documentation is fetched and T3 items are merged into the extraction inventory (or the step is skipped due to no `doc_urls`, no web tools, or fetch failures) will you proceed to load `{nextStepFile}` for enrichment.
|
|
194
|
-
|
|
195
|
-
---
|
|
196
|
-
|
|
197
|
-
## SYSTEM SUCCESS/FAILURE METRICS
|
|
198
|
-
|
|
199
|
-
### SUCCESS:
|
|
200
|
-
|
|
201
|
-
- No `doc_urls` in brief: skipped silently, auto-proceeded
|
|
202
|
-
- `doc_urls` present: each URL fetched using whatever web tool is available
|
|
203
|
-
- Root URLs with minimal content: subpage discovery attempted, relevant subpages fetched
|
|
204
|
-
- Individual fetch failures handled gracefully (skip and continue)
|
|
205
|
-
- All extracted content cited as T3 with `[EXT:{url}]` provenance
|
|
206
|
-
- Existing T1/T1-low/T2 items never overridden by T3 data
|
|
207
|
-
- Docs-only mode: doc-fetch inventory correctly replaces empty extraction inventory
|
|
208
|
-
- Supplemental mode: T3 items merged into existing inventory respecting conflict rule
|
|
209
|
-
- Auto-proceeded to step 4
|
|
210
|
-
|
|
211
|
-
### SYSTEM FAILURE:
|
|
212
|
-
|
|
213
|
-
- Halting the workflow because web fetching is unavailable or a URL fails
|
|
214
|
-
- Including fetched content without `[EXT:{url}]` citations
|
|
215
|
-
- Overriding existing higher-confidence extractions (T1, T1-low, T2) with T3 data
|
|
216
|
-
- Hardcoding a specific fetching tool instead of being tool-agnostic
|
|
217
|
-
- Hallucinating API details not found in the fetched content
|
|
218
|
-
- Beginning compilation in this step (that is step 5)
|
|
205
|
+
### 7. Auto-Proceed
|
|
219
206
|
|
|
220
|
-
|
|
207
|
+
No user interaction. After the fetch completes or is skipped for any reason, load `{nextStepFile}`, read it fully, then execute it.
|
|
@@ -123,7 +123,7 @@ Per-call rationale:
|
|
|
123
123
|
rm -f "$ERR_FILE"
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
Failed individual fetches get a one-line placeholder; the loop continues with remaining tags. If a rate limit (HTTP 429) is hit, stop the release loop, keep the partial `releases.md` file in place (do
|
|
126
|
+
Failed individual fetches get a one-line placeholder; the loop continues with remaining tags. If a rate limit (HTTP 429) is hit, stop the release loop, keep the partial `releases.md` file in place (do not delete it), and log: "Release fetch stopped at tag {N}/{total} due to rate limiting — partial releases.md retained."
|
|
127
127
|
|
|
128
128
|
**Why sequential here when the rest is parallel:** the append-per-release pattern guarantees that a mid-loop abort (rate limit, network drop, user interrupt) leaves a partial but well-formed `releases.md` with every release fetched so far. Parallel writers appending to the same file would need file locking and per-writer ordering — the simpler sequential loop is robust for free, and 10 release fetches contribute only ~5-10s of the total wall-clock.
|
|
129
129
|
|
|
@@ -197,7 +197,7 @@ else
|
|
|
197
197
|
fi
|
|
198
198
|
```
|
|
199
199
|
|
|
200
|
-
**Rollback rule:** if the `qmd collection add` step fails (non-zero exit, network error, parse error)
|
|
200
|
+
**Rollback rule:** if the `qmd collection add` step fails (non-zero exit, network error, parse error) after the prior `remove` succeeded, remove the canonical registry entry in `forge-tier.yaml` to match QMD's actual state. A dangling registry entry that points at a non-existent QMD collection poisons subsequent cache-hit checks in §2. Emit a warning in evidence-report and skip the embed — enrichment degrades to no-QMD for this run.
|
|
201
201
|
|
|
202
202
|
**Scope the embed:** Always pass `--collection {skill-name}-temporal` to `qmd embed`. An unscoped `qmd embed` re-embeds every collection in the QMD store, which can take minutes per run in batch mode and generates wasteful GPU/API cost. If the installed `qmd` CLI does not accept `--collection` (older upstream versions), gate the embed behind a per-skill check: if a previous `{skill-name}-temporal` entry already exists in `qmd_collections` and its `created_at` is within 24 hours, skip the embed entirely and warn "qmd embed skipped — upstream qmd lacks --collection scope; re-embedding all collections would be wasteful in batch mode". Log the skip in the evidence report.
|
|
203
203
|
|
|
@@ -231,7 +231,7 @@ rm -rf {project-root}/_bmad-output/{skill-name}-temporal/
|
|
|
231
231
|
|
|
232
232
|
**Error handling:**
|
|
233
233
|
|
|
234
|
-
- If QMD indexing fails: log the error, note that temporal enrichment will be unavailable. Do
|
|
234
|
+
- If QMD indexing fails: log the error, note that temporal enrichment will be unavailable. Do not fail the workflow.
|
|
235
235
|
- If registry update fails: log the error, continue. The collection may exist in QMD even if the registry entry failed.
|
|
236
236
|
- If cleanup fails: log a warning and continue.
|
|
237
237
|
|
|
@@ -239,22 +239,7 @@ Display brief confirmation:
|
|
|
239
239
|
|
|
240
240
|
"**Temporal context indexed.** Collection `{skill-name}-temporal` created ({file_count} files: {list files}). Proceeding to enrichment..."
|
|
241
241
|
|
|
242
|
-
### 5.
|
|
242
|
+
### 5. Auto-Proceed
|
|
243
243
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
After temporal context is fetched and indexed (or skipped for any reason), immediately load, read entire file, then execute `{nextStepFile}`.
|
|
247
|
-
|
|
248
|
-
#### EXECUTION RULES:
|
|
249
|
-
|
|
250
|
-
- This is an auto-proceed step with no user choices
|
|
251
|
-
- Quick/Forge/Forge+ tiers skip directly to next step with no output
|
|
252
|
-
- Non-GitHub sources skip directly to next step with no output
|
|
253
|
-
- Cached collections (< 7 days old) skip with brief cache-hit message
|
|
254
|
-
- Deep tier with fresh fetch displays brief confirmation then auto-proceeds
|
|
255
|
-
- All failures degrade gracefully — skip and auto-proceed
|
|
256
|
-
|
|
257
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
258
|
-
|
|
259
|
-
ONLY WHEN temporal context is indexed into QMD (or the step is skipped due to eligibility, cache, or failure) will you proceed to load `{nextStepFile}` for documentation fetch.
|
|
244
|
+
No user interaction. After temporal context is fetched and indexed (or skipped for any reason — non-Deep tier, non-GitHub source, cache hit, or any failure), load `{nextStepFile}`, read it fully, then execute it.
|
|
260
245
|
|
|
@@ -8,7 +8,7 @@ When `source_repo` is a remote URL (GitHub URL or owner/repo format) and the tie
|
|
|
8
8
|
|
|
9
9
|
**Workspace-first clone strategy (preferred):**
|
|
10
10
|
|
|
11
|
-
1. Check `git` availability (`git --version`). `git` is effectively guaranteed at Deep tier (via `gh` dependency) but
|
|
11
|
+
1. Check `git` availability (`git --version`). `git` is effectively guaranteed at Deep tier (via `gh` dependency) but not guaranteed at Forge tier.
|
|
12
12
|
2. If `git` is available: check for an existing workspace checkout at `{workspace_root}/repos/{host}/{owner}/{repo}/`. If found, `git fetch` to update. If not found, clone into the workspace path with `--depth 1 --single-branch`. See `source-resolution-protocols.md` for the full workspace resolution algorithm.
|
|
13
13
|
3. The workspace uses a full checkout (no sparse-checkout). Brief `include_patterns` and `exclude_patterns` are applied as file-level filters at extraction time, not at the git level. This allows a single workspace checkout to serve multiple briefs with different scope filters.
|
|
14
14
|
4. For update-skill: `changed_files_from_manifest` scoping is applied as file-level filters at extraction time on the full workspace checkout.
|
|
@@ -18,21 +18,19 @@ When `source_repo` is a remote URL (GitHub URL or owner/repo format) and the tie
|
|
|
18
18
|
|
|
19
19
|
**Fallback (clone fails or `git` unavailable):**
|
|
20
20
|
|
|
21
|
-
- The extraction step
|
|
22
|
-
- **create-skill:**
|
|
23
|
-
- **update-skill:**
|
|
21
|
+
- The extraction step warns the user explicitly before degrading — a silent drop from AST (T1) to source reading (T1-low) would leave them trusting a lower-confidence result without knowing it changed
|
|
22
|
+
- **create-skill:** the warning includes actionable guidance — clone locally and update `source_repo` in the brief to the local path
|
|
23
|
+
- **update-skill:** the warning includes actionable guidance — clone locally, re-run [CS] Create Skill with the local path to regenerate provenance data, then re-run the update
|
|
24
24
|
- Extraction proceeds using Quick tier strategy (source reading via gh_bridge — resolved as `gh api` commands or direct file I/O; see `knowledge/tool-resolution.md`)
|
|
25
25
|
- All results labeled T1-low with `[SRC:...]` citations
|
|
26
26
|
- The degradation reason is recorded in the evidence report
|
|
27
27
|
|
|
28
|
-
Silent degradation is **forbidden**. The user must always know when AST extraction was skipped and why.
|
|
29
|
-
|
|
30
28
|
## AST Tool Unavailable at Forge/Deep Tier
|
|
31
29
|
|
|
32
30
|
When the tier is Forge or Deep but ast-grep is not functional:
|
|
33
31
|
|
|
34
|
-
- The extraction step
|
|
35
|
-
-
|
|
32
|
+
- The extraction step warns the user explicitly before degrading
|
|
33
|
+
- The warning includes actionable guidance: run [SF] Setup Forge to detect tools
|
|
36
34
|
- Extraction proceeds using Quick tier strategy
|
|
37
35
|
- All results labeled T1-low
|
|
38
36
|
- The degradation reason is recorded in the evidence report
|
|
@@ -17,6 +17,27 @@ atomicWriteProbeOrder:
|
|
|
17
17
|
descriptionGuardProbeOrder:
|
|
18
18
|
- '{project-root}/_bmad/skf/shared/scripts/skf-description-guard.py'
|
|
19
19
|
- '{project-root}/src/shared/scripts/skf-description-guard.py'
|
|
20
|
+
# Resolve `{frontmatterValidator}` by probing `{frontmatterValidatorProbeOrder}`
|
|
21
|
+
# in order (installed SKF module path first, src/ dev-checkout fallback); first
|
|
22
|
+
# existing path wins. §0's post-restore re-validation hook uses it; an installed
|
|
23
|
+
# module has no src/ tree, so a bare src/ path would silently fail the hook.
|
|
24
|
+
frontmatterValidatorProbeOrder:
|
|
25
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-validate-frontmatter.py'
|
|
26
|
+
- '{project-root}/src/shared/scripts/skf-validate-frontmatter.py'
|
|
27
|
+
# Resolve `{shardBodyHelper}` by probing `{shardBodyProbeOrder}` in order
|
|
28
|
+
# (installed SKF module path first, src/ dev-checkout fallback); first existing
|
|
29
|
+
# path wins. §4 uses it as the deterministic selective splitter and reads its
|
|
30
|
+
# `tier1_preserved` field instead of counting Tier-1 headings pre/post by hand.
|
|
31
|
+
shardBodyProbeOrder:
|
|
32
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-shard-body.py'
|
|
33
|
+
- '{project-root}/src/shared/scripts/skf-shard-body.py'
|
|
34
|
+
# Resolve `{renderMetadataStatsHelper}` by probing `{renderMetadataStatsProbeOrder}`
|
|
35
|
+
# in order (installed SKF module path first, src/ dev-checkout fallback); first
|
|
36
|
+
# existing path wins. §7 uses it in --check mode to re-derive the metadata
|
|
37
|
+
# `stats` / `confidence_distribution` instead of re-doing the arithmetic by hand.
|
|
38
|
+
renderMetadataStatsProbeOrder:
|
|
39
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-render-metadata-stats.py'
|
|
40
|
+
- '{project-root}/src/shared/scripts/skf-render-metadata-stats.py'
|
|
20
41
|
---
|
|
21
42
|
|
|
22
43
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -43,7 +64,7 @@ To validate the compiled SKILL.md content against the agentskills.io specificati
|
|
|
43
64
|
|
|
44
65
|
Load `{descriptionGuardProtocol}` for the full prose explanation of the four-phase guard (why it exists, what counts as divergence, why token-stream comparison is the right shape). The deterministic phases are executed via `{descriptionGuardHelper}` — the calling sections (§2 and §4) invoke the helper at the capture and verify-restore points.
|
|
45
66
|
|
|
46
|
-
**This skill's post-restore re-validation hook:** after `{descriptionGuardHelper}` reports `restored: true`, run `uv run {
|
|
67
|
+
**This skill's post-restore re-validation hook:** after `{descriptionGuardHelper}` reports `restored: true`, resolve `{frontmatterValidator}` from `{frontmatterValidatorProbeOrder}` (first existing path wins), run `uv run {frontmatterValidator} <staging-skill-dir>/SKILL.md` and capture `schema_revalidation_result` in context. If the validator exits non-zero OR reports failure for the `description` field, flip the Schema result back to `FAIL` in the evidence report (overriding any prior PASS/WARN from §2), record `description_guard_revalidation: FAIL` with the validator's diagnostic message, and continue — do not halt (step 9 health-check and result contract still need to run so the failure is surfaced through the normal artifact path).
|
|
47
68
|
|
|
48
69
|
### 1. Check Tool Availability
|
|
49
70
|
|
|
@@ -104,14 +125,14 @@ If `restored: true` in the verify-restore output, apply §0's post-restore re-va
|
|
|
104
125
|
|
|
105
126
|
**If skill-check was available:** Skip — already validated in step 2.
|
|
106
127
|
|
|
107
|
-
**If skill-check
|
|
128
|
+
**If skill-check not available (fallback):** Perform manual frontmatter compliance check:
|
|
108
129
|
|
|
109
130
|
- [ ] Frontmatter present — file starts with `---` and has closing `---`
|
|
110
131
|
- [ ] `name` field — present, non-empty, lowercase alphanumeric + hyphens only, 1-64 chars
|
|
111
132
|
- [ ] `name` matches skill output directory name
|
|
112
133
|
- [ ] `description` field — present, non-empty, 1-1024 characters
|
|
113
134
|
- [ ] No unknown fields — only `name`, `description`, `license`, `compatibility`, `metadata`, `allowed-tools` permitted
|
|
114
|
-
- [ ] `version` and `author` are
|
|
135
|
+
- [ ] `version` and `author` are not in frontmatter (they belong in metadata.json)
|
|
115
136
|
|
|
116
137
|
If fails: auto-fix (deterministic), re-validate once, record result. If passes: record "Frontmatter: PASS".
|
|
117
138
|
|
|
@@ -137,13 +158,21 @@ If `restored: true` in the verify-restore output, apply §0's post-restore re-va
|
|
|
137
158
|
|
|
138
159
|
**Mandatory approach — selective split:** Identify Tier 2 sections by their `## Full` heading prefix (e.g., `## Full API Reference`, `## Full Type Definitions`, `## Full Integration Patterns`). Extract ONLY those sections to `references/`, starting with the largest. Keep ALL Tier 1 content and any smaller sections inline. Inline passive context achieves 100% task accuracy vs 79% for on-demand retrieval (per Vercel research).
|
|
139
160
|
|
|
140
|
-
|
|
161
|
+
This selective split is deterministic — run `{shardBodyHelper}` (the same splitter step 5b auto-shard uses) rather than counting and extracting by hand. **Resolve `{shardBodyHelper}`** from `{shardBodyProbeOrder}`; first existing path wins.
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
uv run {shardBodyHelper} <staging-skill-dir>/SKILL.md --budget 400
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
It extracts the largest `## Full` sections to `references/` until the body fits, rewrites each as a cross-reference blockquote through the atomic-write helper, and reports `sections_extracted`, `body_lines_after`, `tier1_preserved`, `xref_ok`, and `under_budget`.
|
|
168
|
+
|
|
169
|
+
**Do not run `npx skill-check split-body --write` before selective extraction.** It extracts every `##` section top-to-bottom, destroying the Tier 1 inline content the two-tier design depends on — a last resort used only after selective split has been attempted and proven insufficient.
|
|
141
170
|
|
|
142
|
-
**If selective split alone does not bring body under the limit** (
|
|
171
|
+
**If selective split alone does not bring body under the limit** (the splitter reports `under_budget: false` — rare, typically only when Tier 1 itself exceeds 300 lines): reduce Tier 1 Key API Summary and Architecture at a Glance sections to fit within limits. Do not fall back to automated `split-body --write` to solve a Tier 1 sizing problem.
|
|
143
172
|
|
|
144
|
-
**Tier 1 preservation check:** After
|
|
173
|
+
**Tier 1 preservation check:** After any split operation, verify that all of the following Tier 1 sections remain inline in SKILL.md (not moved to references/): Overview, Quick Start, Common Workflows, Key API Summary, Migration & Deprecation Warnings (if present), Key Types, Architecture at a Glance, CLI (if present), Scripts & Assets (if present), Manual Sections. If any was moved to references/, restore it immediately and re-split targeting only Tier 2 sections.
|
|
145
174
|
|
|
146
|
-
**Post-split Tier-1 count check (mandatory):**
|
|
175
|
+
**Post-split Tier-1 count check (mandatory):** do not recount Tier-1 headings by hand — consume the splitter's `tier1_preserved` field. `{shardBodyHelper}` compares the Tier-1 headings inline before extraction against those inline afterward and reports `tier1_preserved` (with any pulled headings in `tier1_missing`). Read it from the invocation above, or re-check any split's result with `uv run {shardBodyHelper} <staging-skill-dir>/SKILL.md --dry-run`. **HALT** if `tier1_preserved` is false with: "Split reduced Tier-1 section count (missing {tier1_missing}). Tier-1 sections must remain inline. Restoring from staging backup and aborting body split — manual review required." Do not proceed past §4 — Tier-1 preservation is a hard invariant and a `tier1_preserved: false` result means the splitter pulled an inline section into references/ regardless of the section-list check above (e.g., heading-text variation, capitalization, or the splitter's own heuristics).
|
|
147
176
|
|
|
148
177
|
**Anchor validation and remediation:** After any split, verify that context-snippet section anchors (`#quick-start`, `#key-types`) still resolve to headings in SKILL.md. If an anchor no longer resolves (section was split out), restore that section to SKILL.md inline content — the context-snippet must always reference sections that exist in the main file.
|
|
149
178
|
|
|
@@ -182,8 +211,8 @@ Parse output for: `description_score`, `content_score`, `review_score`, `validat
|
|
|
182
211
|
**Apply dismissal rules** in this order:
|
|
183
212
|
|
|
184
213
|
1. **Check score thresholds** against the "Score Thresholds" table in `{tesslDismissalData}`. Most importantly:
|
|
185
|
-
- If tessl's output contains a `findings[]` entry with rule ID `description_field` (the deterministic angle-bracket / XML-tag validator): follow the **recover-then-halt** path defined by the `description-xml-tags-guarded-upstream` rule in `{tesslDismissalData}`. Re-apply step 5 §2a's `<`/`>` → `{`/`}` substitution in place on the staging SKILL.md frontmatter `description`, re-sync the in-context copy, and re-run `npx -y tessl skill review <staging-skill-dir>` once. **Re-run gate:** treat the `description_field` finding being **absent** from the re-run as the only successful recovery outcome. If the finding persists on the re-run — whether the re-substitution improved the description or not — that counts as recovery failure: halt with the original `description-xml-tags-guarded-upstream` failure message from `{tesslDismissalData}`, do
|
|
186
|
-
- If the LLM-judge `description_score` is below 100 **but no `description_field` finding is present** (the deterministic validator PASSED): this is a soft discoverability signal (jargon density, trigger-term phrasing) from the judge's sub-scores, not a sanitizer bypass. Record `description_judge_score: {n}% (deterministic description_field validator PASSED)` as a warning in the evidence report and continue — do
|
|
214
|
+
- If tessl's output contains a `findings[]` entry with rule ID `description_field` (the deterministic angle-bracket / XML-tag validator): follow the **recover-then-halt** path defined by the `description-xml-tags-guarded-upstream` rule in `{tesslDismissalData}`. Re-apply step 5 §2a's `<`/`>` → `{`/`}` substitution in place on the staging SKILL.md frontmatter `description`, re-sync the in-context copy, and re-run `npx -y tessl skill review <staging-skill-dir>` once. **Re-run gate:** treat the `description_field` finding being **absent** from the re-run as the only successful recovery outcome. If the finding persists on the re-run — whether the re-substitution improved the description or not — that counts as recovery failure: halt with the original `description-xml-tags-guarded-upstream` failure message from `{tesslDismissalData}`, do not proceed to §6b, and do not downgrade the recovery to a warning. On successful recovery (finding cleared), log `description-recovery: applied ({count} substitutions)` in the evidence report under "Dismissed tessl suggestions" and continue suggestion iteration against the rerun's `judge_suggestions[]`.
|
|
215
|
+
- If the LLM-judge `description_score` is below 100 **but no `description_field` finding is present** (the deterministic validator PASSED): this is a soft discoverability signal (jargon density, trigger-term phrasing) from the judge's sub-scores, not a sanitizer bypass. Record `description_judge_score: {n}% (deterministic description_field validator PASSED)` as a warning in the evidence report and continue — do not trigger the recover-then-halt path and do not halt.
|
|
187
216
|
- If `review_score < 60` or `content_score < 60`: record warnings in the evidence report, continue.
|
|
188
217
|
2. **Iterate `judge_suggestions[]`.** For each suggestion:
|
|
189
218
|
- Cross-reference against the rules in `{tesslDismissalData}` in order.
|
|
@@ -199,7 +228,9 @@ tessl installs automatically via `npx`. A missing tool is not an error — grace
|
|
|
199
228
|
|
|
200
229
|
**If §6 produced no novel suggestions (all dismissed via `{tesslDismissalData}`) OR tessl was unavailable:** Skip this gate — auto-proceed.
|
|
201
230
|
|
|
202
|
-
**If §6 produced novel suggestions
|
|
231
|
+
**GATE [default: S]** — If `{headless_mode}` is true AND §6 produced novel suggestions: auto-select [S] Skip (a headless run has no human to triage novel suggestions), record `"tessl suggestions: {N} novel suggestion(s) auto-skipped (headless)"` in the evidence report under "Dismissed tessl suggestions", log `"headless: auto-skip {N} novel tessl suggestion(s)"`, and append `{step: "validate", gate: "tessl-suggestions", decision: "S", value: "{N} novel auto-skipped", rationale: "headless mode — no human to triage novel tessl suggestions", timestamp: {ISO}}` to the in-context `headless_decisions[]` list and, the moment it lands, append the same object as a JSON line to the durable audit sink `{sidecar_path}/auto-decisions.jsonl` (the on-landing append established at step 1 §3). §8 below reconciles the sink into the evidence-report `## Auto-Decisions` table — this is the last gate to fire; the earlier gates' rows are already in the sink and were rendered into the staged report at step 5 §7. This is the one consequential auto-decision that drops human-relevant feedback, so it must leave an audit row rather than vanishing. Then auto-proceed to §7 — do not present the menu below.
|
|
232
|
+
|
|
233
|
+
**If §6 produced novel suggestions** (ones not matched by any dismissal rule) AND `{headless_mode}` is false, present them to the user:
|
|
203
234
|
|
|
204
235
|
"**Content quality review: {score}%**
|
|
205
236
|
|
|
@@ -225,14 +256,21 @@ tessl suggestions (novel — not matched by `{tesslDismissalData}`):
|
|
|
225
256
|
|
|
226
257
|
### 7. Validate metadata.json
|
|
227
258
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
-
|
|
233
|
-
|
|
259
|
+
**Re-derive the computed fields with `{renderMetadataStatsHelper}` in check mode** rather than re-doing the arithmetic by hand. Resolve `{renderMetadataStatsHelper}` from `{renderMetadataStatsProbeOrder}` (first existing path wins; HALT if neither resolves), then run it against the staged provenance-map and metadata.json:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
uv run {renderMetadataStatsHelper} <staging-skill-dir>/provenance-map.json \
|
|
263
|
+
--check <staging-skill-dir>/metadata.json
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
The helper re-bins `entries[]` by `signature_source`, recomputes `exports_documented`, `exports_total`, and `public_api_coverage` / `total_coverage` (null when the denominator is 0), and cross-checks `stats.scripts_count` / `stats.assets_count` against the `scripts[]` / `assets[]` array lengths and the provenance-map `file_entries` counts. It takes the judgment values (`exports_public_api`, `exports_internal`, `effective_denominator`) from `metadata.json` itself and infers the shape from `scope_type` / `skill_type` (pass `--shape` to override). Parse the emitted JSON (rely on the JSON, not the exit code):
|
|
234
267
|
|
|
235
|
-
|
|
268
|
+
- **`coherence.ok: true`** — the computed fields are internally consistent; record "Metadata: PASS".
|
|
269
|
+
- **`coherence.ok: false`** — each `violations[]` entry is `{field, expected, actual}` where `expected` is the correct value. **Auto-fix each computed-value violation** (`field` starting `stats.` or `confidence_distribution.`) by setting that field in `metadata.json` to `expected` (write via `python3 {atomicWriteHelper} write --target <staging-skill-dir>/metadata.json`), leaving every other stats field — e.g. `stats.notes` on a reference app — untouched. Record "Metadata: auto-fixed {N} computed-value discrepanc(y|ies)" listing the fields. These are computed values, so the helper is authoritative — a `confidence_distribution` violation is the per-entry mis-binning compile.md §4 describes (T2 annotations + T3 doc items counted on top of the per-export tiers); the helper's per-entry counts replace them. Carve-outs are handled by `--shape`: a **stack** distribution sums to the constituent count and a **reference-app** distribution to the per-citation count, so those are consistent states, not violations. A `provenance.file_entries.*` violation is not a computed metadata field — it means the provenance-map `file_entries` and metadata counts disagree; record it as a warning for manual reconciliation rather than auto-editing the count.
|
|
270
|
+
|
|
271
|
+
Then verify the two fields the helper does not own (genuine constants/contract):
|
|
272
|
+
- `spec_version` is `"1.3"`.
|
|
273
|
+
- `scope_type` is present and equals the brief's `scope.type` verbatim.
|
|
236
274
|
|
|
237
275
|
### 8. Update Evidence Report
|
|
238
276
|
|
|
@@ -263,6 +301,18 @@ Add validation results to evidence-report content in context:
|
|
|
263
301
|
- {warnings, security results, tessl scores and suggestions — or "skipped"}
|
|
264
302
|
```
|
|
265
303
|
|
|
304
|
+
**Auto-Decisions table (reconcile from the durable sink — idempotent):** all gates have now fired — every one appended its row to the on-disk sink `{sidecar_path}/auto-decisions.jsonl` as it landed (including §6b's tessl-suggestions row), step 5 §7 rendered the step 1–3d rows into the staged `<staging-skill-dir>/evidence-report.md`, and steps 7–9 add none. Reconcile: read the sink's JSON lines (the authoritative durable record — it survives any compaction of the in-context buffer), union them with both the `## Auto-Decisions` rows already in `<staging-skill-dir>/evidence-report.md` and the in-context `headless_decisions[]` buffer, keyed on `step`+`gate` so no decision is duplicated or dropped, and re-render the section from that union. Because the rows are recovered from the sink rather than from the possibly-compacted buffer, the audit table stays complete on a long headless run. Emit one row per entry:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
## Auto-Decisions
|
|
308
|
+
|
|
309
|
+
| Step | Gate | Decision | Rationale | Timestamp |
|
|
310
|
+
|------|------|----------|-----------|-----------|
|
|
311
|
+
| {step} | {gate} | {decision}{value?} | {rationale} | {timestamp} |
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
If the sink, the on-disk rows, and `headless_decisions[]` are all empty, keep the single line step 5 §7 emitted: `No auto-decisions — workflow ran interactively (or all gates had no match to auto-resolve).` This keeps the section always present so reviewers can tell "zero auto-decisions" apart from "section missing", and keeps the row count equal to `summary.auto_decision_count`.
|
|
315
|
+
|
|
266
316
|
**Description Guard population:** if the §0 protocol fired during §2 (`skill-check --fix`) or §4 (`split-body`), fill the four Description Guard fields from context:
|
|
267
317
|
|
|
268
318
|
- `Restored: true` when `description_guard_restored == true`, otherwise `false`.
|
|
@@ -272,17 +322,7 @@ Add validation results to evidence-report content in context:
|
|
|
272
322
|
|
|
273
323
|
When `Restored: false`, the three follow-up fields are all `—` — this is the clean-run expected state.
|
|
274
324
|
|
|
275
|
-
### 9.
|
|
276
|
-
|
|
277
|
-
**Conditional interaction step.** If tessl produced suggestions, section 6b halts for user input. Otherwise, auto-proceed.
|
|
278
|
-
|
|
279
|
-
After validation completes (including any user decisions from section 6b), immediately load, read entire file, then execute `{nextStepFile}`.
|
|
280
|
-
|
|
281
|
-
- Tool unavailability is a skip, not a halt
|
|
282
|
-
- Validation failures are warnings — proceed to artifact generation
|
|
283
|
-
- tessl gate only triggers when suggestions exist — no gate for clean reviews or unavailable tools
|
|
284
|
-
|
|
285
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
325
|
+
### 9. Auto-Proceed
|
|
286
326
|
|
|
287
|
-
|
|
327
|
+
Conditional interaction: §6b halts for user input only when tessl produced novel suggestions; otherwise the step auto-proceeds. After validation completes (including any §6b decisions), load `{nextStepFile}`, read it fully, then execute it. Tool unavailability and validation failures are skips and warnings, never halts.
|
|
288
328
|
|