bmad-module-skill-forge 1.4.1 → 1.5.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/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 +147 -16
- 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-manifest-ops.py +22 -6
- 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} +48 -14
- package/src/skf-analyze-source/{steps-c/step-01-init.md → references/init.md} +32 -9
- 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} +16 -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} +63 -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} +35 -17
- package/src/skf-brief-skill/SKILL.md +49 -19
- 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} +27 -15
- 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} +35 -29
- 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 +2 -2
- package/src/skf-brief-skill/{steps-c/step-03-scope-definition.md → references/scope-definition.md} +27 -20
- 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} +29 -16
- 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 +10 -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} +48 -28
- 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} +37 -11
- package/src/skf-create-stack-skill/{steps-c/step-02-detect-manifests.md → references/detect-manifests.md} +32 -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} +44 -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 +79 -0
- package/src/skf-export-skill/{steps-c/step-06-summary.md → references/summary.md} +23 -11
- 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} +37 -73
- 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} +13 -9
- 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 +170 -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} +18 -14
- package/src/skf-verify-stack/{steps-c/step-06-report.md → references/report.md} +27 -42
- package/src/skf-verify-stack/{steps-c/step-04-requirements.md → references/requirements.md} +13 -9
- package/src/skf-verify-stack/{steps-c/step-05-synthesize.md → references/synthesize.md} +14 -10
- 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
|
@@ -2,13 +2,21 @@
|
|
|
2
2
|
briefSchemaFile: 'assets/skill-brief-schema.md'
|
|
3
3
|
versionResolutionFile: 'references/version-resolution.md'
|
|
4
4
|
qmdRegistrationFile: 'references/qmd-collection-registration.md'
|
|
5
|
-
nextStepFile: '
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
5
|
+
nextStepFile: 'health-check.md'
|
|
6
|
+
writeSkillBriefProbeOrder:
|
|
7
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-write-skill-brief.py'
|
|
8
|
+
- '{project-root}/src/shared/scripts/skf-write-skill-brief.py'
|
|
9
|
+
emitBriefEnvelopeProbeOrder:
|
|
10
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
11
|
+
- '{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
12
|
+
forgeTierRwProbeOrder:
|
|
13
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-forge-tier-rw.py'
|
|
14
|
+
- '{project-root}/src/shared/scripts/skf-forge-tier-rw.py'
|
|
9
15
|
forgeTierFile: '{sidecar_path}/forge-tier.yaml'
|
|
10
16
|
---
|
|
11
17
|
|
|
18
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
19
|
+
|
|
12
20
|
# Step 5: Write Brief
|
|
13
21
|
|
|
14
22
|
## STEP GOAL:
|
|
@@ -26,11 +34,11 @@ To generate the complete skill-brief.yaml from the approved brief data and write
|
|
|
26
34
|
|
|
27
35
|
## MANDATORY SEQUENCE
|
|
28
36
|
|
|
29
|
-
**CRITICAL:** Follow this sequence exactly. Do not skip, reorder, or improvise unless user explicitly requests a change.
|
|
30
|
-
|
|
31
37
|
### 1. Reference the Schema (LLM context only)
|
|
32
38
|
|
|
33
|
-
|
|
39
|
+
**Resolve `{writeSkillBriefHelper}`** from `{writeSkillBriefProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
40
|
+
|
|
41
|
+
`{briefSchemaPath}` and `{versionResolutionFile}` document the brief contract for human readers. The deterministic enforcement of that contract lives in `{writeSkillBriefHelper}` and its JSON Schema artifact at `src/shared/scripts/schemas/skill-brief.v1.json`. Load `{briefSchemaPath}` only if you need to explain a specific field to the user during inline adjustments — otherwise skip the read; the script is the source of truth.
|
|
34
42
|
|
|
35
43
|
### 2. Resolve Output Path
|
|
36
44
|
|
|
@@ -52,7 +60,7 @@ If the file exists, present:
|
|
|
52
60
|
Overwrite it with the brief you just approved? [Y/N]"
|
|
53
61
|
|
|
54
62
|
- **[Y]** Overwrite — proceed to §3.
|
|
55
|
-
- **[N]** Cancel — emit a single-line stderr log `brief-skill: overwrite-cancelled at {path}` and HALT with exit code 5 (do not chain to step
|
|
63
|
+
- **[N]** Cancel — emit a single-line stderr log `brief-skill: overwrite-cancelled at {path}` and HALT with exit code 5 (do not chain to step 6; the run produced no new artifact).
|
|
56
64
|
|
|
57
65
|
**Headless (`{headless_mode}` is true):**
|
|
58
66
|
|
|
@@ -83,6 +91,7 @@ Assemble the brief context as a **flat** JSON object — every approved value is
|
|
|
83
91
|
"scope_include": ["{approved include patterns}"],
|
|
84
92
|
"scope_exclude": ["{approved exclude patterns}"],
|
|
85
93
|
"scope_notes": "{approved scope notes or empty string}",
|
|
94
|
+
"scope_rationale": null | {"recommended":"...","chosen":"...","accepted_recommendation":true|false,"heuristic":"...","reason":"...","recorded":"YYYY-MM-DD"},
|
|
86
95
|
"doc_urls": null | [{"url": "...", "label": "..."}],
|
|
87
96
|
"scripts_intent": null | "{detect|none|free-text}",
|
|
88
97
|
"assets_intent": null | "{detect|none|free-text}",
|
|
@@ -93,7 +102,7 @@ Assemble the brief context as a **flat** JSON object — every approved value is
|
|
|
93
102
|
Pipe it into the writer script with the `--from-flat` flag:
|
|
94
103
|
|
|
95
104
|
```bash
|
|
96
|
-
echo '<context-json>' | uv run {
|
|
105
|
+
echo '<context-json>' | uv run {writeSkillBriefHelper} write --target {resolved-target-path} --from-flat
|
|
97
106
|
```
|
|
98
107
|
|
|
99
108
|
The script translates flat → nested internally, drops the null optional fields, and runs the same schema validation and atomic write as before — pass every key always, the writer decides what reaches the YAML.
|
|
@@ -116,38 +125,42 @@ The script:
|
|
|
116
125
|
|
|
117
126
|
**On success:** capture `brief_path` and `version` from the response envelope — both are needed for §4b and §6.
|
|
118
127
|
|
|
119
|
-
**Draft cleanup.** After a successful write, remove `{forge_data_folder}/{skill-name}/.brief-draft.json` if it exists (`rm -f` — silent on absent). The draft was a step
|
|
128
|
+
**Draft cleanup.** After a successful write, remove `{forge_data_folder}/{skill-name}/.brief-draft.json` if it exists (`rm -f` — silent on absent). The draft was a step 1 §7 checkpoint covering the in-flight workflow window; once the brief is written it is no longer meaningful. In headless mode this rm is a no-op (drafts are only written interactively).
|
|
120
129
|
|
|
121
130
|
### 4b. Headless Result Envelope (Canonical)
|
|
122
131
|
|
|
123
|
-
|
|
132
|
+
**Resolve `{emitBriefEnvelopeHelper}`** from `{emitBriefEnvelopeProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
133
|
+
|
|
134
|
+
This section is the canonical envelope-emission reference for the workflow. Every headless emission — the success terminal here and every HARD HALT in step 1/02/05 — uses this contract. Remote sites point here instead of restating it.
|
|
124
135
|
|
|
125
136
|
**Success (this call site only — emitted from §3 directly):**
|
|
126
137
|
|
|
127
138
|
```bash
|
|
128
139
|
echo '{"status":"success","brief_path":"<from §3 response>","skill_name":"<name>","version":"<from §3 response>","language":"<language>","scope_type":"<scope.type>","halt_reason":null}' | \
|
|
129
|
-
uv run {
|
|
140
|
+
uv run {emitBriefEnvelopeHelper} emit
|
|
130
141
|
```
|
|
131
142
|
|
|
132
143
|
**Error (used by every HARD HALT site):**
|
|
133
144
|
|
|
134
145
|
```bash
|
|
135
146
|
echo '{"status":"error","skill_name":"<name>","halt_reason":"<reason>"}' | \
|
|
136
|
-
uv run {
|
|
147
|
+
uv run {emitBriefEnvelopeHelper} emit --target stderr
|
|
137
148
|
```
|
|
138
149
|
|
|
139
|
-
When the HALT fires before `skill_name` has been resolved (step
|
|
150
|
+
When the HALT fires before `skill_name` has been resolved (step 1 §1 pre-flight write probe, step 1 §8 input-missing on a malformed args bundle), pass the partially-gathered value or the literal `"unknown"` — the script accepts any non-empty string at this position.
|
|
140
151
|
|
|
141
152
|
The script derives `exit_code` deterministically from `halt_reason` (null→0, input-missing/input-invalid→2, forge-tier-missing/target-inaccessible/gh-auth-failed→3, write-failed→4, overwrite-cancelled→5, user-cancelled→6 [interactive-only — headless never raises this]), validates against `src/shared/scripts/schemas/skf-brief-result-envelope.v1.json`, and prints the prefixed `SKF_BRIEF_RESULT_JSON: {…}` line.
|
|
142
153
|
|
|
143
|
-
The script enforces the success/error halt_reason invariant (success requires null halt_reason; error requires non-null). The `user-cancelled` halt_reason is accepted for completeness (interactive `[X]` Cancel sites in step
|
|
154
|
+
The script enforces the success/error halt_reason invariant (success requires null halt_reason; error requires non-null). The `user-cancelled` halt_reason is accepted for completeness (interactive `[X]` Cancel sites in step 1/03/04) but never appears on the headless code path.
|
|
144
155
|
|
|
145
|
-
Invocation sites (each pointed at this block, not duplicated): step
|
|
156
|
+
Invocation sites (each pointed at this block, not duplicated): step 1 §1 (write-failed pre-resolution), step 1 §8 (input-missing/input-invalid GATE), step 5 §2b (overwrite-cancelled), step 5 §3 (input-invalid/write-failed from script). Step-01 §1 forge-tier-missing and step 2 §1 (target-inaccessible/gh-auth-failed) currently HALT without emitting an envelope — pre-existing gaps tracked separately, not addressed by this canonicalization.
|
|
146
157
|
|
|
147
158
|
When `{headless_mode}` is false, skip this section silently — no envelope is emitted.
|
|
148
159
|
|
|
149
160
|
### 5. QMD Collection Registration (Deep Tier Only)
|
|
150
161
|
|
|
162
|
+
**Resolve `{forgeTierRwHelper}`** from `{forgeTierRwProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
163
|
+
|
|
151
164
|
**IF forge tier is Deep AND QMD tool is available:** load `{qmdRegistrationFile}` and follow the procedure there to index the brief into a QMD collection and update the forge-tier registry.
|
|
152
165
|
|
|
153
166
|
**IF forge tier is NOT Deep OR QMD is not available:** skip this section silently — do not load `{qmdRegistrationFile}`. No messaging.
|
|
@@ -9,6 +9,14 @@ description: Compile a skill from a brief. Supports --batch for multiple briefs.
|
|
|
9
9
|
|
|
10
10
|
Compiles a verified agent skill from a skill-brief.yaml and source code, producing an agentskills.io-compliant SKILL.md with provenance map, evidence report, and progressive disclosure references. The workflow is mostly autonomous with three interaction points — after ecosystem check (if match found), after source extraction (to confirm findings), and after content quality review (when tessl produces suggestions). Steps adapt behavior based on forge tier (Quick/Forge/Forge+/Deep). Zero hallucination tolerance: every instruction in the output must trace to source code with a confidence tier citation.
|
|
11
11
|
|
|
12
|
+
## Conventions
|
|
13
|
+
|
|
14
|
+
- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.
|
|
15
|
+
- `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.
|
|
16
|
+
- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).
|
|
17
|
+
- `{project-root}`-prefixed paths resolve from the project working directory.
|
|
18
|
+
- `{skill-name}` resolves to the skill directory's basename.
|
|
19
|
+
|
|
12
20
|
## Role
|
|
13
21
|
|
|
14
22
|
You are operating in Ferris Architect mode — a skill compilation engine performing structural extraction and assembly. Apply zero hallucination tolerance: uncitable content is excluded, not guessed.
|
|
@@ -18,8 +26,6 @@ You are operating in Ferris Architect mode — a skill compilation engine perfor
|
|
|
18
26
|
These rules apply to every step in this workflow:
|
|
19
27
|
|
|
20
28
|
- Never include content in SKILL.md that cannot be cited to source code
|
|
21
|
-
- Read each step file completely before taking any action
|
|
22
|
-
- Follow the mandatory sequence in each step exactly — do not skip, reorder, or optimize
|
|
23
29
|
- Only load one step file at a time — never preload future steps
|
|
24
30
|
- Always communicate in `{communication_language}`
|
|
25
31
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
@@ -28,28 +34,28 @@ These rules apply to every step in this workflow:
|
|
|
28
34
|
|
|
29
35
|
| # | Step | File | Auto-proceed |
|
|
30
36
|
|---|------|------|--------------|
|
|
31
|
-
| 1 | Load Brief |
|
|
32
|
-
| 2 | Ecosystem Check |
|
|
33
|
-
| 2b | CCC Discover |
|
|
34
|
-
| 3 | Extract |
|
|
35
|
-
| 3b | Fetch Temporal |
|
|
36
|
-
| 3c | Fetch Docs |
|
|
37
|
-
| 3d | Component Extraction |
|
|
38
|
-
| 4 | Enrich |
|
|
39
|
-
| 5 | Compile |
|
|
40
|
-
| 6 | Validate |
|
|
41
|
-
| 7 | Generate Artifacts |
|
|
42
|
-
| 8 | Report |
|
|
43
|
-
| 9 | Workflow Health Check |
|
|
44
|
-
|
|
45
|
-
*Sub-steps under `
|
|
37
|
+
| 1 | Load Brief | references/load-brief.md | Yes |
|
|
38
|
+
| 2 | Ecosystem Check | references/ecosystem-check.md | Conditional |
|
|
39
|
+
| 2b | CCC Discover | references/sub/ccc-discover.md | Yes |
|
|
40
|
+
| 3 | Extract | references/extract.md | No (confirm) |
|
|
41
|
+
| 3b | Fetch Temporal | references/sub/fetch-temporal.md | Yes |
|
|
42
|
+
| 3c | Fetch Docs | references/sub/fetch-docs.md | Yes |
|
|
43
|
+
| 3d | Component Extraction | references/component-extraction.md | Conditional |
|
|
44
|
+
| 4 | Enrich | references/enrich.md | Yes |
|
|
45
|
+
| 5 | Compile | references/compile.md | Yes |
|
|
46
|
+
| 6 | Validate | references/validate.md | Conditional |
|
|
47
|
+
| 7 | Generate Artifacts | references/generate-artifacts.md | Yes |
|
|
48
|
+
| 8 | Report | references/report.md | Yes |
|
|
49
|
+
| 9 | Workflow Health Check | references/health-check.md | Yes |
|
|
50
|
+
|
|
51
|
+
*Sub-steps under `references/sub/` are conditional branches (CCC discovery, temporal/doc enrichment) kept out of the top-level step count so main-line steps 1–9 drive the workflow. Step 3d (Component Extraction) stays top-level as an alternative main step that replaces the standard extraction path when `scope.type: "component-library"`.*
|
|
46
52
|
|
|
47
53
|
## Invocation Contract
|
|
48
54
|
|
|
49
55
|
| Aspect | Detail |
|
|
50
56
|
|--------|--------|
|
|
51
57
|
| **Inputs** | brief_path (path to skill-brief.yaml) [required], --batch [optional] |
|
|
52
|
-
| **Gates** | step
|
|
58
|
+
| **Gates** | step 2: Choice Gate [P] (if match) | step 3: Review Gate [C] |
|
|
53
59
|
| **Outputs** | SKILL.md, context-snippet.md, metadata.json, provenance-map.json, evidence-report.md, references/ |
|
|
54
60
|
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
|
|
55
61
|
|
|
@@ -60,4 +66,4 @@ These rules apply to every step in this workflow:
|
|
|
60
66
|
|
|
61
67
|
2. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in preferences.yaml. Default: false.
|
|
62
68
|
|
|
63
|
-
3. Load, read the full file, and then execute
|
|
69
|
+
3. Load, read the full file, and then execute `references/load-brief.md` to begin the workflow.
|
|
@@ -21,7 +21,7 @@ description: >
|
|
|
21
21
|
- Uppercase placeholders are also acceptable: `NAME`, `COMPONENT_ID`.
|
|
22
22
|
- For code-ish fragments, use curly braces in place of angle brackets inside the backticks: `` `Meta{typeof X}` ``, `` `Array{T}` ``.
|
|
23
23
|
|
|
24
|
-
Authors should not rely on remembering this — step
|
|
24
|
+
Authors should not rely on remembering this — step 5 §2a enforces it via a pre-write sanitization pass that unconditionally replaces every `<` with `{` and every `>` with `}` in the frontmatter `description`. See step 5 §2a for the rule and `assets/tessl-dismissal-rules.md` (`description-xml-tags-guarded-upstream`) for the recovery path if a downstream tool rewrites the description after §2a has run.
|
|
25
25
|
- Only `name` and `description` in frontmatter — `version` and `author` go in metadata.json
|
|
26
26
|
- No other frontmatter fields for standard skills (only `name`, `description`, `license`, `compatibility`, `metadata`, `allowed-tools` are permitted by spec)
|
|
27
27
|
|
|
@@ -62,7 +62,7 @@ These sections form the essential standalone body. Target: **under 300 lines tot
|
|
|
62
62
|
- Provenance citation per function
|
|
63
63
|
|
|
64
64
|
**Section 4b — Migration & Deprecation Warnings (~10 lines, Deep tier only):**
|
|
65
|
-
- Only populated when step
|
|
65
|
+
- Only populated when step 4 enrichment produced **T2-future** annotations (deprecation warnings, breaking changes, planned renames)
|
|
66
66
|
- List each warning as a single-line bullet: function name, what changed or will change, source citation
|
|
67
67
|
- Max 10 lines — just the actionable warnings, not full context
|
|
68
68
|
- Link to Tier 2 Full API Reference for details: "See Full API Reference for migration details."
|
|
@@ -158,7 +158,7 @@ Replace the function table with a Component Catalog organized by category:
|
|
|
158
158
|
**Total components:** {unique count} | {Per variant: **With {name}:** {count}}
|
|
159
159
|
```
|
|
160
160
|
|
|
161
|
-
Source: `component_catalog[]` from step
|
|
161
|
+
Source: `component_catalog[]` from step 3d. Group by `category` field. Provenance: cite the registry file.
|
|
162
162
|
|
|
163
163
|
**Section 5 (Key Types) — Props-focused override:**
|
|
164
164
|
|
|
@@ -76,7 +76,7 @@ When `scope.type: "component-library"`, these section formats replace their stan
|
|
|
76
76
|
**Total components:** {unique_count} | **With {variant1}:** {count1} | **With {variant2}:** {count2}
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
-
- Source: `component_catalog[]` from step
|
|
79
|
+
- Source: `component_catalog[]` from step 3d extraction
|
|
80
80
|
- Group by `category` field from registry
|
|
81
81
|
- Show top 3-5 component names per category
|
|
82
82
|
- Cite registry file: `[SRC:{registry_file}:L1]`
|
|
@@ -224,7 +224,7 @@ Indexed pipe-delimited format for CLAUDE.md managed section (~80-120 tokens per
|
|
|
224
224
|
"total_coverage": 0.0,
|
|
225
225
|
"scripts_count": 0,
|
|
226
226
|
"assets_count": 0
|
|
227
|
-
// "effective_denominator": 0 // optional — emitted for stratified-scope monorepo packages; test-skill uses this as the coverage denominator when present. See
|
|
227
|
+
// "effective_denominator": 0 // optional — emitted for stratified-scope monorepo packages; test-skill uses this as the coverage denominator when present. See compile.md §4 emit rules.
|
|
228
228
|
},
|
|
229
229
|
// scripts[] and assets[] — include ONLY when inventories are non-empty; omit entirely otherwise
|
|
230
230
|
// "scripts": [{ "file": "scripts/{name}", "purpose": "{description}", "source_file": "{source-path}", "confidence": "T1-low" }],
|
|
@@ -329,12 +329,12 @@ Each reference file includes:
|
|
|
329
329
|
|---|---|---|---|---|
|
|
330
330
|
| `"script"` | `scripts_inventory` | yes → `scripts/` | `"file-copy"` | Runnable scripts (CLI tools, validation scripts, etc.) bundled into the skill for execution. |
|
|
331
331
|
| `"asset"` | `assets_inventory` | yes → `assets/` | `"file-copy"` | Data files (templates, JSON schemas, config fixtures) bundled for reference. |
|
|
332
|
-
| `"doc"` | `promoted_docs` (from step
|
|
332
|
+
| `"doc"` | `promoted_docs` (from step 3 §2a) | **no** | `"promoted-authoritative"` | Authoritative AI documentation files (`llms.txt`, `AGENTS.md`, etc.) promoted into scope by the Discovered Authoritative Files Protocol. The source file is tracked for drift detection but not bundled into the skill — its content influences compile-time decisions (description, Quick Start) and is watched for upstream changes. |
|
|
333
333
|
|
|
334
334
|
When `file_type: "doc"`:
|
|
335
335
|
|
|
336
336
|
- `source_file` is the relative path from the source root to the authoritative doc.
|
|
337
|
-
- `content_hash` is computed at promotion time (step
|
|
337
|
+
- `content_hash` is computed at promotion time (step 3 §2a) and persisted here so update-skill Category D can detect drift via hash comparison.
|
|
338
338
|
- `file_name` convention: use the source-relative path prefixed with `docs/authoritative/` to namespace doc entries away from script/asset filenames in tools that iterate `file_entries[]` by `file_name`. Example: `docs/authoritative/apps/docs/public/llms.txt`. Step-07 does not write this path — it is a synthetic namespace used only within the provenance map.
|
|
339
339
|
- `confidence` is `"T1-low"` (the promotion decision is source-level but the content was not AST-parsed).
|
|
340
340
|
|
|
@@ -392,4 +392,4 @@ t2_future_count: {N}
|
|
|
392
392
|
|
|
393
393
|
**Frontmatter — pinned detection contract:** the `t2_future_count` field is the authoritative forward-looking-annotation count for downstream gate checks (e.g. skf-test-skill §2b migration-section rule). Emit **always**, even when 0 — omission is indistinguishable from "no T2-future data" and silently flips the gate into Case 2/3 for a Case-1 skill. `generated` and `forge_tier` mirror the narrative header for consumers that read only the frontmatter. Downstream gate rules MUST parse `t2_future_count` from frontmatter, not grep prose — prose drift (heading renames, alternate phrasings like "forward-looking annotations") silently breaks the detection.
|
|
394
394
|
|
|
395
|
-
**Description Guard slot:** populated by step
|
|
395
|
+
**Description Guard slot:** populated by step 6 §0 (create-skill) and §0 (update-skill) when the guard protocol fires. `Restored: true` indicates that an external tool (typically `skill-check --fix` or `split-body`) rewrote the frontmatter `description` and the guard restored the pre-tool value. When `Restored: false`, leave `Triggering tool`, `Original description preserved`, and `Notes` as `—`. When `Restored: true`, fill all four fields: tool name, whether the original was successfully written back, and a one-sentence note describing what the tool had changed (e.g., "replaced with generic summary", "truncated at 80 chars", "angle-bracket tokens re-introduced"). Downstream test-skill assertions can grep for `Restored: true` to detect unintended tool rewrites without parsing free-form warning prose.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
This file is the **single source of truth** for tessl review findings that Skill Forge expects and must dismiss. Step-06 §6 loads this file, parses the `tessl skill review` JSON output, and cross-references each finding against the rules below. Matches are dismissed with their rationale logged to the evidence report; non-matches surface to the user via §6b.
|
|
4
4
|
|
|
5
|
-
**Why this file exists:** Previously, expected tessl behavior was enumerated as prose in step
|
|
5
|
+
**Why this file exists:** Previously, expected tessl behavior was enumerated as prose in step 6 itself. Each time tessl evolved a scorer or added a new rule, step 6 had to be manually patched and the prose re-read by every execution. This file moves the expected behavior into a structured list with stable rule IDs, rationales, and match criteria — one place to update when tessl changes, one place to audit what SKF expects.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -13,10 +13,10 @@ When parsing tessl output, check these fields against the thresholds below. Viol
|
|
|
13
13
|
| Field | Threshold | Severity on violation | Rationale |
|
|
14
14
|
|---|---|---|---|
|
|
15
15
|
| `review_score` (overall) | `>= 60` | warn | Two-tier SKF skills trade some conciseness score for progressive disclosure. 60 is the floor below which something is genuinely wrong. |
|
|
16
|
-
| `description_score` | `== 100` | **error — recover, then halt** | step
|
|
16
|
+
| `description_score` | `== 100` | **error — recover, then halt** | step 5 §2a unconditionally replaces `<` with `{` and `>` with `}` in the frontmatter description before validation. A score below 100 indicates the sanitizer was bypassed (downstream tool rewrote the description) or a novel tessl rule. Attempt recovery per rule `description-xml-tags-guarded-upstream` (re-apply the §2a substitution in place on the staging SKILL.md frontmatter and re-run tessl). Halt only if recovery fails. |
|
|
17
17
|
| `content_score` | `>= 60` | warn | Two-tier design deliberately duplicates key API data across Tier 1 and Tier 2. Conciseness scorer penalizes this. 60 is the acceptable floor. |
|
|
18
18
|
|
|
19
|
-
If `description_score < 100`, **attempt recovery first** per rule `description-xml-tags-guarded-upstream` below: re-apply step
|
|
19
|
+
If `description_score < 100`, **attempt recovery first** per rule `description-xml-tags-guarded-upstream` below: re-apply step 5 §2a's `<` → `{` / `>` → `}` substitution in place on the staging SKILL.md frontmatter `description`, then re-run `npx -y tessl skill review <staging-skill-dir>` once. If the re-run produces `description_score == 100`, log `description-recovery: applied ({count} substitutions)` in the evidence report and proceed to normal suggestion handling. If recovery fails, halt with: "Description sanitization recovery failed — step 5 §2a's `<`/`>` → `{`/`}` replacement did not resolve the tessl finding. Investigate the staging SKILL.md frontmatter for non-angle-bracket content that tessl is still rejecting, and patch §2a accordingly. Do not edit the description manually." Do NOT proceed to §6b user prompt on an unrecovered failure.
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
@@ -39,7 +39,7 @@ Each rule below describes a tessl suggestion that Skill Forge expects and dismis
|
|
|
39
39
|
- **Match criteria (all of):**
|
|
40
40
|
- Suggestion text mentions `Full API Reference` OR a `## Full ...` section heading
|
|
41
41
|
- Suggestion text contains one of: `move`, `relocate`, `extract`, `split out`, `separate file`, `external file`
|
|
42
|
-
- **Rationale:** The two-tier design (Tier 1 inline + Tier 2 inline) keeps Tier 2 sections inline by default. `skill-check split-body` relocates Tier 2 to `references/` only when the body exceeds size limits — see step
|
|
42
|
+
- **Rationale:** The two-tier design (Tier 1 inline + Tier 2 inline) keeps Tier 2 sections inline by default. `skill-check split-body` relocates Tier 2 to `references/` only when the body exceeds size limits — see step 6 §4. Preemptive relocation destroys the standalone SKILL.md that the cited 100% task accuracy (vs. 79% for on-demand retrieval) depends on.
|
|
43
43
|
- **Action:** dismiss.
|
|
44
44
|
|
|
45
45
|
### Rule: `consolidate-duplicate-parameters`
|
|
@@ -48,7 +48,7 @@ Each rule below describes a tessl suggestion that Skill Forge expects and dismis
|
|
|
48
48
|
- **Match criteria (any of):**
|
|
49
49
|
- Suggestion mentions `duplicate parameter`, `redundant parameter`, `consolidate parameter`
|
|
50
50
|
- Suggestion mentions both `Key API` / `Key API Summary` AND `Full API Reference` and suggests merging them
|
|
51
|
-
- **Rationale:** Tier 1 Key API Summary intentionally lists only key parameters for standalone discoverability. Tier 2 Full API Reference provides complete parameter tables, types, defaults, and edge cases. This is progressive disclosure, not duplication. Consolidating would force agents to scroll to Tier 2 for the most common function calls, defeating Tier 1's purpose and breaking the split-body Tier 1 preservation contract in step
|
|
51
|
+
- **Rationale:** Tier 1 Key API Summary intentionally lists only key parameters for standalone discoverability. Tier 2 Full API Reference provides complete parameter tables, types, defaults, and edge cases. This is progressive disclosure, not duplication. Consolidating would force agents to scroll to Tier 2 for the most common function calls, defeating Tier 1's purpose and breaking the split-body Tier 1 preservation contract in step 6 §4.
|
|
52
52
|
- **Action:** dismiss.
|
|
53
53
|
|
|
54
54
|
### Rule: `conciseness-redundancy-between-tiers`
|
|
@@ -66,14 +66,14 @@ Each rule below describes a tessl suggestion that Skill Forge expects and dismis
|
|
|
66
66
|
- **Scorer:** `description_field` (deterministic validator)
|
|
67
67
|
- **Match criteria (any of):**
|
|
68
68
|
- Finding rule ID is `description_field` AND message mentions `XML tag`, `must not contain`, or angle-bracket-related text
|
|
69
|
-
- **Expected occurrence:** zero. step
|
|
70
|
-
- **Action:** **Attempt recovery, then halt if recovery fails.** This is not a dismissal — the finding represents a real sanitizer bypass that step
|
|
69
|
+
- **Expected occurrence:** zero. step 5 §2a unconditionally replaces `<` with `{` and `>` with `}` in the frontmatter description before SKILL.md is written.
|
|
70
|
+
- **Action:** **Attempt recovery, then halt if recovery fails.** This is not a dismissal — the finding represents a real sanitizer bypass that step 6 must resolve before proceeding.
|
|
71
71
|
1. **Re-apply §2a in place.** Read the current `description` from the on-disk staging SKILL.md frontmatter, replace every `<` with `{` and every `>` with `}`, and write the result back to the frontmatter. Re-sync the in-context copy to match. Count the substitutions; if zero, the description is already clean and the tessl finding points at something other than angle brackets — skip to the halt branch below.
|
|
72
72
|
2. **Re-run tessl once.** Execute `npx -y tessl skill review <staging-skill-dir>` a second time and re-parse the JSON output.
|
|
73
73
|
3. **On success** (`description_score == 100`): log `description-recovery: applied ({count} substitutions)` in the evidence report under "Dismissed tessl suggestions", then continue §6 with the recovered review result (proceed to normal suggestion handling against the rules below). The rerun's `judge_suggestions[]` replaces the original.
|
|
74
|
-
4. **On failure** (`description_score` still < 100 after re-sanitization): halt with: "Description sanitization recovery failed — step
|
|
74
|
+
4. **On failure** (`description_score` still < 100 after re-sanitization): halt with: "Description sanitization recovery failed — step 5 §2a's `<`/`>` → `{`/`}` replacement did not resolve the tessl finding. Investigate the staging SKILL.md frontmatter for non-angle-bracket content that tessl is still rejecting, and patch §2a accordingly. Do not edit the description manually."
|
|
75
75
|
|
|
76
|
-
The recovery path makes the skill shippable when a downstream tool (`skill-check --fix`, `split-body`, or a future validator) re-introduces angle brackets into the description after §2a has run. The Description Guard Protocol in step
|
|
76
|
+
The recovery path makes the skill shippable when a downstream tool (`skill-check --fix`, `split-body`, or a future validator) re-introduces angle brackets into the description after §2a has run. The Description Guard Protocol in step 6 §0 is the first line of defense against such rewrites; this rule is the second line, active when the guard also missed.
|
|
77
77
|
|
|
78
78
|
---
|
|
79
79
|
|
|
@@ -97,6 +97,6 @@ When tessl introduces new rules, changes scorer behavior, or SKF design decision
|
|
|
97
97
|
1. **Add a new rule section** above with `Rule:`, `Scorer:`, `Match criteria`, `Rationale`, `Action`.
|
|
98
98
|
2. **Link the rationale** to the concrete SKF design principle it protects (two-tier design, MANUAL markers, sanitization, split-body preservation, etc.). A rationale without a design-principle link is a smell.
|
|
99
99
|
3. **Keep score thresholds above current production floors.** Do not lower them to suppress real regressions.
|
|
100
|
-
4. **Never embed dismissal logic in step files.** If step
|
|
100
|
+
4. **Never embed dismissal logic in step files.** If step 6 needs updated behavior, update this file first and reference it from step 6.
|
|
101
101
|
|
|
102
|
-
This file is load-bearing: step
|
|
102
|
+
This file is load-bearing: step 6 §6 has no other source of truth for expected tessl behavior.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-create-skill.
|
|
4
|
+
|
|
5
|
+
[workflow]
|
|
6
|
+
|
|
7
|
+
# --- Configurable below. Overrides merge per BMad structural rules: ---
|
|
8
|
+
# scalars: override wins • arrays (persistent_facts, activation_steps_*): append
|
|
9
|
+
# arrays-of-tables with `code`/`id`: replace matching items, append new ones.
|
|
10
|
+
|
|
11
|
+
# Steps to run before the standard activation (uv probe, config load).
|
|
12
|
+
# Overrides append. Use for org-wide pre-flight checks (auth, network,
|
|
13
|
+
# compliance) that must precede any skill compilation work.
|
|
14
|
+
|
|
15
|
+
activation_steps_prepend = []
|
|
16
|
+
|
|
17
|
+
# Steps to run after activation but before the first stage executes.
|
|
18
|
+
# Overrides append. Use for context loads or banner customization that
|
|
19
|
+
# should run once activation completes successfully.
|
|
20
|
+
|
|
21
|
+
activation_steps_append = []
|
|
22
|
+
|
|
23
|
+
# Persistent facts the workflow keeps in mind for the whole run
|
|
24
|
+
# (extraction style, compilation guardrails, tessl review preferences).
|
|
25
|
+
# Overrides append.
|
|
26
|
+
#
|
|
27
|
+
# Each entry is either:
|
|
28
|
+
# - a literal sentence, e.g. "Skills must declare PEP 723 inline metadata."
|
|
29
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
30
|
+
# "file:{project-root}/docs/create-policy.md" (globs supported; file
|
|
31
|
+
# contents are loaded and treated as facts).
|
|
32
|
+
|
|
33
|
+
persistent_facts = [
|
|
34
|
+
"file:{project-root}/**/project-context.md",
|
|
35
|
+
]
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# Authoritative Files Protocol
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Carved from `extract.md §2a`. Loaded on demand when step 3's `### 2a. Discovered Authoritative Files Protocol` sub-step runs.
|
|
6
|
+
|
|
7
|
+
**Skip this protocol entirely if `source_type: "docs-only"`** — there is no source tree to scan.
|
|
8
|
+
|
|
9
|
+
Before resolving source access for extraction, scan the source tree for **authoritative AI documentation files** that the brief's scope filters excluded. Project authors increasingly add files specifically written to steer AI assistants (`llms.txt`, `AGENTS.md`, `.cursorrules`, etc.), and these files often contain the **canonical** install command, quick-start, or architecture summary — information that nowhere else in the source tree provides. A brief authored from a scan of `src/**` will frequently exclude these files without the author realizing they exist.
|
|
10
|
+
|
|
11
|
+
This protocol detects such files, prompts the user, and records the decision in the brief so future runs (re-create, update, audit) honor it.
|
|
12
|
+
|
|
13
|
+
**Heuristic scan list (handled by the helper — listed here for reference):** case-insensitive basename match, any directory depth, on `llms.txt`, `llms-full.txt`, `AGENTS.md`, `CLAUDE.md`, `GEMINI.md`, `COPILOT.md`, `.cursorrules`, `.windsurfrules`, `.clinerules`.
|
|
14
|
+
|
|
15
|
+
## Procedure
|
|
16
|
+
|
|
17
|
+
1. **Resolve, scan, classify, and load previews in one call.** The helper handles the source-tree walk (pruning `node_modules`, `dist`, `.git`, etc.), case-insensitive basename matching, scope-filter diff (with `**`-recursive-glob support), amendment reconciliation (most-recent action wins), preview load (first 20 lines), and SHA-256 hashing:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
uv run {resolveAuthoritativeFilesHelper} resolve \
|
|
21
|
+
--source-root {source_root} \
|
|
22
|
+
--brief {forge_data_folder}/{skill_name}/skill-brief.yaml \
|
|
23
|
+
[--preview-lines 20]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
The helper emits one envelope with three buckets:
|
|
27
|
+
|
|
28
|
+
```json
|
|
29
|
+
{
|
|
30
|
+
"status": "no-candidates" | "candidates-found",
|
|
31
|
+
"summary": {
|
|
32
|
+
"candidates_total": N, "already_in_scope_count": N,
|
|
33
|
+
"pre_decided_count": N, "unresolved_count": N
|
|
34
|
+
},
|
|
35
|
+
"already_in_scope": [
|
|
36
|
+
{"path": "...", "heuristic": "...", "size_bytes": N,
|
|
37
|
+
"line_count": N, "content_hash": "sha256:..."}
|
|
38
|
+
],
|
|
39
|
+
"pre_decided": [
|
|
40
|
+
{"path": "...", "heuristic": "...",
|
|
41
|
+
"prior_action": "promoted"|"skipped",
|
|
42
|
+
"should_add_to_promoted_docs": <bool>,
|
|
43
|
+
"size_bytes": N|null, "line_count": N|null,
|
|
44
|
+
"content_hash": "sha256:..."|null}
|
|
45
|
+
],
|
|
46
|
+
"unresolved": [
|
|
47
|
+
{"path": "...", "heuristic": "...", "size_bytes": N,
|
|
48
|
+
"line_count": N, "content_hash": "sha256:...",
|
|
49
|
+
"preview": "<first N lines>",
|
|
50
|
+
"excluded_by_pattern": "<glob>"|"not matched by any scope.include"}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
2. **Apply the helper's classification:**
|
|
56
|
+
|
|
57
|
+
- **`already_in_scope[]`** — file is in scope and not skipped. **Remove the path from §2's filtered file list** and append the record to in-context `promoted_docs[]`. No prompt — authoritative docs must never reach §4 code extraction even when scope.include matches.
|
|
58
|
+
- **`pre_decided[]` with `prior_action: "promoted"`** — amendment says promoted; **append to `promoted_docs[]`** using the helper-supplied hash/size/lines. Deterministic replay path.
|
|
59
|
+
- **`pre_decided[]` with `prior_action: "skipped"`** — user previously declined. Do nothing. Move on.
|
|
60
|
+
- **`unresolved[]`** — proceed to step 3 below (user prompt).
|
|
61
|
+
|
|
62
|
+
3. **Prompt.** Present each `unresolved[]` candidate to the user. Use the helper's `preview`, `size_bytes`, `line_count`, and `excluded_by_pattern` fields verbatim — they replace what the LLM previously had to compute itself:
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
**Discovered authoritative file excluded by brief scope**
|
|
66
|
+
|
|
67
|
+
Path: {relative_path_from_source_root}
|
|
68
|
+
Size: {line_count} lines, {bytes} bytes
|
|
69
|
+
Matched heuristic: {basename}
|
|
70
|
+
Excluded by pattern: {matching_exclude_pattern or "not matched by any scope.include"}
|
|
71
|
+
|
|
72
|
+
First 20 lines:
|
|
73
|
+
{inline preview}
|
|
74
|
+
|
|
75
|
+
This file is typically authored for AI assistants and may contain canonical usage information not present elsewhere in the source. How should extraction handle it?
|
|
76
|
+
|
|
77
|
+
[P] Promote — include in this extraction run AND amend brief for future runs
|
|
78
|
+
[S] Skip — honor the brief exclusion AND record skip in amendments (no re-prompt)
|
|
79
|
+
[U] Update — halt this run and return to skf-brief-skill to refine scope
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
4. **Headless mode (`{headless_mode}` is true):** auto-select `[S] Skip` for every candidate. Record amendment entries with `action: "skipped"` and `reason: "headless: no user to prompt"`. A non-interactive run must never silently promote files into scope — the decision requires a human.
|
|
83
|
+
|
|
84
|
+
5. **Apply decision:**
|
|
85
|
+
|
|
86
|
+
- **[P] Promote:**
|
|
87
|
+
1. **Do NOT add the path to the filtered file list from §2.** Authoritative documentation files are not code — they must not go through the AST extraction pipeline in §4, which would silently produce no exports (ghost entries). Instead, add the path to a new in-context list `promoted_docs[]` with `{path, heuristic, size_bytes, line_count, content_hash}`. Compute the SHA-256 content hash of the file now.
|
|
88
|
+
2. Append to `brief.scope.include`: add the exact `candidate.path` as a literal glob (no wildcards — the amendment targets this specific file). This write ensures that a re-run of `skf-create-skill` against the amended brief sees the path in scope and skips re-prompting.
|
|
89
|
+
3. Append to `brief.scope.amendments[]` a new entry with `action: "promoted"`, `path: candidate.path`, `reason: {user-provided one-sentence reason or auto-generated "authoritative AI docs — matched heuristic {basename}"}`, `heuristic: {basename}`, `date: {today ISO}`, `workflow: "skf-create-skill"`.
|
|
90
|
+
4. **Write the amended brief back to disk immediately** at `{forge_data_folder}/{skill_name}/skill-brief.yaml`. Immediate write (not deferred to step 7) ensures a crashed run still leaves the amendment recorded. Preserve all other brief fields and formatting. **Use atomic write + backup:** before writing, copy the original brief to `{forge_data_folder}/{skill_name}/skill-brief.yaml.bak` (overwriting any prior `.bak` — the most recent pre-amendment snapshot is the useful one). Then pipe the amended YAML through the shared atomic writer so a crash mid-write cannot corrupt the brief:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
# 1. Backup
|
|
94
|
+
cp {forge_data_folder}/{skill_name}/skill-brief.yaml \
|
|
95
|
+
{forge_data_folder}/{skill_name}/skill-brief.yaml.bak
|
|
96
|
+
|
|
97
|
+
# 2. Atomic write (stdin → tmp → fsync → rename)
|
|
98
|
+
cat <<'AMENDED_YAML' | python3 {atomicWriteHelper} write \
|
|
99
|
+
--target {forge_data_folder}/{skill_name}/skill-brief.yaml
|
|
100
|
+
{amended brief YAML}
|
|
101
|
+
AMENDED_YAML
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The helper stages into `{brief}.skf-tmp`, fsyncs, then `os.replace()`s — readers never see a half-written brief.
|
|
105
|
+
5. Display: "**Promoted `{path}`** — tracked as documentation file, amendment recorded."
|
|
106
|
+
|
|
107
|
+
- **[S] Skip:**
|
|
108
|
+
1. Do NOT modify `scope.include` or `scope.exclude`.
|
|
109
|
+
2. Append to `brief.scope.amendments[]` a new entry with `action: "skipped"`, `path: candidate.path`, `reason: {user-provided reason or auto-generated "user declined promotion at create-skill §2a"}`, `heuristic: {basename}`, `date: {today ISO}`, `workflow: "skf-create-skill"`.
|
|
110
|
+
3. **Write the amended brief back to disk** so future runs do not re-prompt. Use the same backup-then-atomic-write pattern as the [P] Promote path (copy to `skill-brief.yaml.bak` first, then pipe through `skf-atomic-write.py write --target {brief_path}`).
|
|
111
|
+
4. Display: "**Skipped `{path}`** — decision recorded in amendments."
|
|
112
|
+
|
|
113
|
+
- **[U] Update:**
|
|
114
|
+
1. Halt the workflow immediately.
|
|
115
|
+
2. Display: "**Halting create-skill.** Re-run `skf-brief-skill` to refine the scope filters for `{skill_name}`, then re-run `skf-create-skill`. Decisions for previously prompted candidates were already persisted to the brief; the current candidate was not written."
|
|
116
|
+
3. Exit with status `halted-for-brief-refinement`.
|
|
117
|
+
|
|
118
|
+
6. **Summary.** After all candidates are resolved (or none were found), display a one-line summary:
|
|
119
|
+
|
|
120
|
+
- `"Authoritative files scan: {N} candidates, {P} promoted, {S} skipped, {A} pre-decided from amendments."`
|
|
121
|
+
- If N = 0: `"Authoritative files scan: no candidates."`
|
|
122
|
+
|
|
123
|
+
**Record for evidence report:** `authoritative_files_scan: {candidates: N, promoted: P, skipped: S, pre_decided: A, decisions: [{path, action, heuristic, reason}]}` — step 7 includes this in `evidence-report.md`.
|
|
124
|
+
|
|
125
|
+
## How promoted docs reach the provenance map
|
|
126
|
+
|
|
127
|
+
Promoted docs do NOT flow through §4 code extraction. Instead:
|
|
128
|
+
|
|
129
|
+
1. §2a populates the in-context `promoted_docs[]` list with content hashes.
|
|
130
|
+
2. **Step-05 §6** (provenance-map assembly) reads `promoted_docs[]` and emits one `file_entries[]` entry per promoted doc with `file_type: "doc"`, `extraction_method: "promoted-authoritative"`, `confidence: "T1-low"`, and the pre-computed `content_hash`.
|
|
131
|
+
3. **Step-07 §2** does NOT copy doc files into the skill package (unlike scripts and assets). The source file remains at its original path; only the provenance map tracks it. Future audit and update workflows compare against this tracking entry via content hash — no file copy is required because the intent is drift detection on the *source*, not bundling documentation into the skill output.
|
|
132
|
+
|
|
133
|
+
**Re-running `skf-create-skill`** reads the amended brief. Files with `action: "promoted"` amendments already appear in `scope.include`, but §2a still runs — it detects the file is in scope AND has an existing amendment, and takes the "pre-decided" silent path. The `promoted_docs[]` list is rebuilt on each run by scanning amendments with `action: "promoted"` (this is the deterministic replay path).
|
|
134
|
+
|
|
135
|
+
## Downstream workflow consumption
|
|
136
|
+
|
|
137
|
+
Zero code changes required in consumer workflows:
|
|
138
|
+
|
|
139
|
+
- **`skf-update-skill`** reads `provenance-map.json`. Promoted docs appear as `file_entries[]` entries. Update-skill Category D (script/asset file changes) iterates `file_entries` and compares content hashes — this works identically for `file_type: "doc"` entries, giving drift detection for free.
|
|
140
|
+
- **`skf-audit-skill`** (after the bounded re-index fix) scans files from `provenance-map.json`. The re-index builds its list from `entries[].source_file ∪ file_entries[].source_file`, so promoted doc paths are naturally included in the audit scan.
|
|
141
|
+
|
|
142
|
+
The brief is the single source of truth for authored scope intent. The provenance map is the single source of truth for extracted state. `scope.amendments[]` is the bridge that records when those two intentionally diverged. `promoted_docs[]` is the in-memory handoff from §2a to step 5 §6; it is not persisted — the persisted form is the `file_entries[]` list in provenance-map.json.
|