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
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# /// script
|
|
3
|
+
# requires-python = ">=3.10"
|
|
4
|
+
# ///
|
|
5
|
+
"""Deterministic parse + validation of a forger pipeline invocation.
|
|
6
|
+
|
|
7
|
+
Pipeline Mode (references/pipeline-mode.md §1-2) turns a raw code sequence
|
|
8
|
+
(`BS CS[cocoindex] TS[min:80] EX`, `AN -> CS -> TS -> EX`, or a bare alias like
|
|
9
|
+
`forge-auto`) into a normalized run plan and a list of sequence anti-patterns.
|
|
10
|
+
Splitting the tokens, expanding aliases against a fixed table, classifying each
|
|
11
|
+
bracket argument, and detecting anti-patterns (duplicates, ordering, missing
|
|
12
|
+
prerequisites) is set/order plumbing with exactly one correct answer per input —
|
|
13
|
+
so it runs here, not in the prompt. The prompt keeps only the judgment the
|
|
14
|
+
script cannot make: interpreting the user's freeform request into a code
|
|
15
|
+
sequence, and deciding whether to proceed past a warned anti-pattern.
|
|
16
|
+
|
|
17
|
+
The alias-expansion and anti-pattern tables mirror
|
|
18
|
+
`src/shared/references/pipeline-contracts.md` (the human-readable contract);
|
|
19
|
+
this script is the executable form the forger consumes.
|
|
20
|
+
|
|
21
|
+
CLI usage:
|
|
22
|
+
uv run scripts/parse-pipeline.py 'BS CS TS EX' # positional
|
|
23
|
+
uv run scripts/parse-pipeline.py 'forge-auto' # bare alias
|
|
24
|
+
echo 'AN -> CS -> TS -> EX' | uv run scripts/parse-pipeline.py --stdin
|
|
25
|
+
|
|
26
|
+
Output (stdout, one object):
|
|
27
|
+
{
|
|
28
|
+
"raw": "<input>",
|
|
29
|
+
"alias": "forge" | null, # set when the input was a lone alias
|
|
30
|
+
"deprecated_alias": "deepwiki" | null,
|
|
31
|
+
"removed_alias": "onboard" | null,
|
|
32
|
+
"expanded": ["BS", "CS", "TS", "EX"], # normalized tokens (post-expansion)
|
|
33
|
+
"plan": [{"code","min","mode","target"}, ...],
|
|
34
|
+
"codes": ["BS", "CS", "TS", "EX"],
|
|
35
|
+
"unknown_codes": [],
|
|
36
|
+
"anti_patterns": [{"pattern","message","suggestion"}, ...],
|
|
37
|
+
"valid": <bool> # runnable: real codes, no unknowns, not removed
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
Exit codes:
|
|
41
|
+
0 — parsed, runnable (anti-patterns and a deprecated alias are warnings)
|
|
42
|
+
1 — no input provided (usage error)
|
|
43
|
+
2 — removed alias (e.g. `onboard`) — the forger HALTs
|
|
44
|
+
3 — nothing runnable (empty, or unknown codes) — the forger corrects course
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
from __future__ import annotations
|
|
48
|
+
|
|
49
|
+
import argparse
|
|
50
|
+
import json
|
|
51
|
+
import re
|
|
52
|
+
import sys
|
|
53
|
+
|
|
54
|
+
# Workflow codes that can appear in a pipeline. KI/WS are inline actions, not
|
|
55
|
+
# pipeline steps; `campaign` is a standalone workflow, not a pipeline code.
|
|
56
|
+
KNOWN_CODES = frozenset(
|
|
57
|
+
{"SF", "AN", "BS", "CS", "QS", "SS", "US", "AS", "VS", "RA", "TS", "EX", "RS", "DS"}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# Only these accept a `min:N` circuit-breaker override; on other codes a
|
|
61
|
+
# `min:N` bracket is ignored (recorded as `min: null`).
|
|
62
|
+
CIRCUIT_BREAKER_CODES = frozenset({"AN", "CS", "TS", "AS", "VS"})
|
|
63
|
+
|
|
64
|
+
# Alias table — mirrors pipeline-contracts.md. `forge-auto`'s TS[min:90] gate is
|
|
65
|
+
# non-default and is kept in lockstep with init.md §1b's forge-auto → 90 lookup.
|
|
66
|
+
ALIASES = {
|
|
67
|
+
"forge-auto": ["AN[auto]", "BS[auto]", "CS", "TS[min:90]", "EX"],
|
|
68
|
+
"forge": ["BS", "CS", "TS", "EX"],
|
|
69
|
+
"forge-quick": ["QS", "TS", "EX"],
|
|
70
|
+
"maintain": ["AS", "US", "TS", "EX"],
|
|
71
|
+
}
|
|
72
|
+
DEPRECATED_ALIASES = {"deepwiki": "forge-auto"} # renamed; still expands
|
|
73
|
+
REMOVED_ALIASES = {"onboard"} # no expansion — the forger HALTs
|
|
74
|
+
|
|
75
|
+
_TOKEN_RE = re.compile(r"^([A-Za-z]+)(?:\[([^\]]*)\])?$")
|
|
76
|
+
_ARROWS = re.compile(r"->|→|—>|»")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _tokenize(raw):
|
|
80
|
+
"""Split a raw sequence on whitespace and arrow separators."""
|
|
81
|
+
normalized = _ARROWS.sub(" ", raw)
|
|
82
|
+
return [t for t in normalized.split() if t]
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _classify_bracket(code, value):
|
|
86
|
+
"""Return (min, mode, target) for a bracket value on a given code."""
|
|
87
|
+
if value is None or value == "":
|
|
88
|
+
return None, None, None
|
|
89
|
+
m = re.fullmatch(r"min:(\d+)", value)
|
|
90
|
+
if m:
|
|
91
|
+
# min:N only applies to circuit-breaker codes; ignored elsewhere.
|
|
92
|
+
return (int(m.group(1)) if code in CIRCUIT_BREAKER_CODES else None), None, None
|
|
93
|
+
if value == "auto":
|
|
94
|
+
return None, "auto", None
|
|
95
|
+
return None, None, value
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def _detect_anti_patterns(codes):
|
|
99
|
+
"""Deterministic sequence checks — mirrors pipeline-contracts.md."""
|
|
100
|
+
found = []
|
|
101
|
+
|
|
102
|
+
# Duplicate codes.
|
|
103
|
+
seen = set()
|
|
104
|
+
dupes = []
|
|
105
|
+
for c in codes:
|
|
106
|
+
if c in seen and c not in dupes:
|
|
107
|
+
dupes.append(c)
|
|
108
|
+
seen.add(c)
|
|
109
|
+
if dupes:
|
|
110
|
+
found.append(
|
|
111
|
+
{
|
|
112
|
+
"pattern": "duplicate-codes",
|
|
113
|
+
"codes": dupes,
|
|
114
|
+
"message": f"same workflow appears more than once: {', '.join(dupes)}",
|
|
115
|
+
"suggestion": "remove the duplicate",
|
|
116
|
+
}
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# EX before TS (equivalently, TS after EX).
|
|
120
|
+
ex_idxs = [i for i, c in enumerate(codes) if c == "EX"]
|
|
121
|
+
ts_idxs = [i for i, c in enumerate(codes) if c == "TS"]
|
|
122
|
+
if ex_idxs and ts_idxs and min(ex_idxs) < max(ts_idxs):
|
|
123
|
+
found.append(
|
|
124
|
+
{
|
|
125
|
+
"pattern": "ex-before-ts",
|
|
126
|
+
"codes": ["EX", "TS"],
|
|
127
|
+
"message": "EX (export) runs before TS (test) — exporting an untested skill",
|
|
128
|
+
"suggestion": "move TS before EX",
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
# CS without BS or AN.
|
|
133
|
+
if "CS" in codes and "BS" not in codes and "AN" not in codes:
|
|
134
|
+
found.append(
|
|
135
|
+
{
|
|
136
|
+
"pattern": "cs-without-brief",
|
|
137
|
+
"codes": ["CS"],
|
|
138
|
+
"message": "CS (compile) has no preceding BS or AN — compiling without a brief",
|
|
139
|
+
"suggestion": "use QS for the quick path, or add AN/BS to produce a brief",
|
|
140
|
+
}
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# US without AS.
|
|
144
|
+
if "US" in codes and "AS" not in codes:
|
|
145
|
+
found.append(
|
|
146
|
+
{
|
|
147
|
+
"pattern": "us-without-audit",
|
|
148
|
+
"codes": ["US"],
|
|
149
|
+
"message": "US (update) has no preceding AS — updating without an audit",
|
|
150
|
+
"suggestion": "run AS first to detect what changed",
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
return found
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def parse_pipeline(raw):
|
|
158
|
+
"""Parse and validate a raw pipeline sequence. Deterministic."""
|
|
159
|
+
tokens = _tokenize(raw)
|
|
160
|
+
result = {
|
|
161
|
+
"raw": raw,
|
|
162
|
+
"alias": None,
|
|
163
|
+
"deprecated_alias": None,
|
|
164
|
+
"removed_alias": None,
|
|
165
|
+
"expanded": [],
|
|
166
|
+
"plan": [],
|
|
167
|
+
"codes": [],
|
|
168
|
+
"unknown_codes": [],
|
|
169
|
+
"anti_patterns": [],
|
|
170
|
+
"valid": False,
|
|
171
|
+
}
|
|
172
|
+
if not tokens:
|
|
173
|
+
return result
|
|
174
|
+
|
|
175
|
+
# Alias handling — only when the sequence is a lone alias token.
|
|
176
|
+
if len(tokens) == 1:
|
|
177
|
+
lone = tokens[0].lower()
|
|
178
|
+
if lone in REMOVED_ALIASES:
|
|
179
|
+
result["removed_alias"] = lone
|
|
180
|
+
return result
|
|
181
|
+
if lone in DEPRECATED_ALIASES:
|
|
182
|
+
result["deprecated_alias"] = lone
|
|
183
|
+
target = DEPRECATED_ALIASES[lone]
|
|
184
|
+
result["alias"] = target
|
|
185
|
+
tokens = list(ALIASES[target])
|
|
186
|
+
elif lone in ALIASES:
|
|
187
|
+
result["alias"] = lone
|
|
188
|
+
tokens = list(ALIASES[lone])
|
|
189
|
+
|
|
190
|
+
result["expanded"] = []
|
|
191
|
+
for tok in tokens:
|
|
192
|
+
m = _TOKEN_RE.match(tok)
|
|
193
|
+
if not m:
|
|
194
|
+
result["unknown_codes"].append(tok)
|
|
195
|
+
continue
|
|
196
|
+
code = m.group(1).upper()
|
|
197
|
+
value = m.group(2)
|
|
198
|
+
result["expanded"].append(
|
|
199
|
+
f"{code}[{value}]" if value not in (None, "") else code
|
|
200
|
+
)
|
|
201
|
+
if code not in KNOWN_CODES:
|
|
202
|
+
result["unknown_codes"].append(tok)
|
|
203
|
+
continue
|
|
204
|
+
min_n, mode, target = _classify_bracket(code, value)
|
|
205
|
+
result["codes"].append(code)
|
|
206
|
+
result["plan"].append(
|
|
207
|
+
{"code": code, "min": min_n, "mode": mode, "target": target}
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
result["anti_patterns"] = _detect_anti_patterns(result["codes"])
|
|
211
|
+
result["valid"] = bool(result["codes"]) and not result["unknown_codes"]
|
|
212
|
+
return result
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
# --- CLI --------------------------------------------------------------------
|
|
216
|
+
|
|
217
|
+
|
|
218
|
+
def _build_parser():
|
|
219
|
+
parser = argparse.ArgumentParser(
|
|
220
|
+
prog="parse-pipeline",
|
|
221
|
+
description=(
|
|
222
|
+
"Deterministic parse + validation of a forger pipeline invocation "
|
|
223
|
+
"(pipeline-mode.md §1-2): tokenize, expand aliases, classify bracket "
|
|
224
|
+
"arguments, and detect sequence anti-patterns, returning a normalized "
|
|
225
|
+
"run plan as JSON."
|
|
226
|
+
),
|
|
227
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
228
|
+
)
|
|
229
|
+
src = parser.add_mutually_exclusive_group()
|
|
230
|
+
src.add_argument(
|
|
231
|
+
"sequence",
|
|
232
|
+
nargs="?",
|
|
233
|
+
help="Raw pipeline sequence as a positional argument.",
|
|
234
|
+
)
|
|
235
|
+
src.add_argument(
|
|
236
|
+
"--stdin",
|
|
237
|
+
action="store_true",
|
|
238
|
+
help="Read the raw sequence from stdin.",
|
|
239
|
+
)
|
|
240
|
+
return parser
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def _resolve_input(args):
|
|
244
|
+
if args.stdin:
|
|
245
|
+
return sys.stdin.read()
|
|
246
|
+
if args.sequence is not None:
|
|
247
|
+
return args.sequence
|
|
248
|
+
return ""
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def main(argv=None):
|
|
252
|
+
parser = _build_parser()
|
|
253
|
+
args = parser.parse_args(argv)
|
|
254
|
+
raw = _resolve_input(args)
|
|
255
|
+
if not raw.strip():
|
|
256
|
+
parser.print_usage(file=sys.stderr)
|
|
257
|
+
print("error: no input provided (positional arg or --stdin)", file=sys.stderr)
|
|
258
|
+
return 1
|
|
259
|
+
|
|
260
|
+
result = parse_pipeline(raw)
|
|
261
|
+
print(json.dumps(result, indent=2))
|
|
262
|
+
if result["removed_alias"]:
|
|
263
|
+
return 2
|
|
264
|
+
if not result["valid"]:
|
|
265
|
+
return 3
|
|
266
|
+
return 0
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
if __name__ == "__main__":
|
|
270
|
+
raise SystemExit(main())
|
|
@@ -7,7 +7,7 @@ description: Fast skill from a package name or GitHub URL — no brief needed. U
|
|
|
7
7
|
|
|
8
8
|
## Overview
|
|
9
9
|
|
|
10
|
-
The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed.
|
|
10
|
+
The fastest path to a skill — accept a GitHub URL or package name, resolve to source, extract the public API surface, and produce a best-effort SKILL.md with context snippet and metadata. No brief needed. Output is always community-tier quality, regardless of which tools are available.
|
|
11
11
|
|
|
12
12
|
## Conventions
|
|
13
13
|
|
|
@@ -28,7 +28,7 @@ These rules apply to every step in this workflow:
|
|
|
28
28
|
- Never fabricate content — all data must come from source extraction or user input
|
|
29
29
|
- Only load one step file at a time — never preload future steps
|
|
30
30
|
- Always communicate in `{communication_language}`
|
|
31
|
-
- **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per
|
|
31
|
+
- **Universal cancel-line affordance** — at any interactive prompt the user may type `cancel`, `exit`, `:q`, or select the `[X] Cancel and exit` menu option (where surfaced) to leave cleanly. HARD HALT with **exit code 6 (user-cancelled)** and emit the error result contract per `references/halt-contract.md` with `error.code: "user-cancelled"`. In step 4 §6 the equivalent affordance is `[Q] Quit without writing` — same exit code, same envelope contract.
|
|
32
32
|
- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision
|
|
33
33
|
- If `{headless_mode}` is true, emit a single-line JSON progress event to **stderr** at each step's entry and exit so pipeline schedulers can stream live progress instead of post-mortem-parsing the result contract:
|
|
34
34
|
- entry: `{"step":N,"name":"<slug>","status":"start"}`
|
|
@@ -55,61 +55,14 @@ These rules apply to every step in this workflow:
|
|
|
55
55
|
|--------|--------|
|
|
56
56
|
| **Inputs** | target (GitHub URL or package name) [required for single-target mode], language_hint [optional], scope_hint [optional] |
|
|
57
57
|
| **Overrides** | `--description`, `--exports`, `--skip-snippet`, `--no-active-pointer`, `--batch <file>`, `--fail-fast` — see On Activation step 4 |
|
|
58
|
-
| **Gates** | step 1:
|
|
58
|
+
| **Gates** | step 1: target input, multi-language disambiguation [C/A]; step 2: ecosystem match [P/I/A] (if match); step 3: repo-shape [C/A] + zero-exports rescue [R/P/A]; step 4: review [C/E/S/Q]; step 5: overwrite [Y/N] |
|
|
59
59
|
| **Outputs** | SKILL.md, context-snippet.md, metadata.json, active pointer, result contract (timestamped + `-latest` copy). Snippet and active pointer can be skipped per overrides. |
|
|
60
60
|
| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true |
|
|
61
|
-
| **Exit codes** | See
|
|
61
|
+
| **Exit codes** | See `references/halt-contract.md` |
|
|
62
62
|
|
|
63
|
-
## Exit Codes
|
|
63
|
+
## Exit Codes & HARD HALT Contract
|
|
64
64
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
| Code | Meaning | Raised by |
|
|
68
|
-
| ---- | ---------------------- | ----------------------------------------------------------- |
|
|
69
|
-
| 0 | success | step 7 (terminal) |
|
|
70
|
-
| 3 | resolution-failure | step 1 §2c (prose input), step 1 §3 (registry chain failed) |
|
|
71
|
-
| 4 | write-failure | step 5 §2 (deliverable write failed) |
|
|
72
|
-
| 5 | overwrite-cancelled | step 5 §1 (user selected [N]) |
|
|
73
|
-
| 6 | user-cancelled | step 1 §1 ([X] Cancel and exit, or cancel-line affordance); step 2 §3 ([A] Abort at ecosystem-match gate); step 4 §6 (user selected [Q]) — originally `compile-cancelled`, generalised to cover any interactive gate |
|
|
74
|
-
| 7 | finalize-blocked | step 6 §1 (active-pointer flip refused — non-link in place) |
|
|
75
|
-
| 8 | ecosystem-redirect | step 2 §3 ([I] Install at ecosystem-match gate — user opted to install the existing official skill instead of compiling a custom community skill) |
|
|
76
|
-
|
|
77
|
-
Reserved: `validator-missing` may be promoted from advisory log to fatal exit code in a future revision.
|
|
78
|
-
|
|
79
|
-
## Result Contract on HARD HALT
|
|
80
|
-
|
|
81
|
-
In addition to the success-variant result contract written by step 6 §3, every HARD HALT must surface an **error variant** so headless automators don't silently break when `quick-skill-result-latest.json` is missing on failed runs.
|
|
82
|
-
|
|
83
|
-
**Always (every HARD HALT, regardless of phase)** — emit a single line on **stderr**:
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
SKF_QUICK_SKILL_RESULT_JSON: {"status":"error","exit_code":<N>,"phase":"<slug>","error":{"code":"<class>","message":"<short>"},"outputs":{},"summary":{},"skill_package":"<path-or-null>"}
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
One line, no pretty-print. Matches the prefix-and-envelope convention used by `skf-emit-result-envelope.py`.
|
|
90
|
-
|
|
91
|
-
**Additionally, when `{skill_package}` is known** (HALT at step 5 §1 onward) — write the same JSON object (without the `SKF_QUICK_SKILL_RESULT_JSON: ` prefix) to disk:
|
|
92
|
-
|
|
93
|
-
```
|
|
94
|
-
{skill_package}/quick-skill-result-{YYYYMMDD-HHmmss}.json
|
|
95
|
-
{skill_package}/quick-skill-result-latest.json (copy, not symlink)
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
so consumers that hardcode the `-latest.json` path see a deterministic file even on failed runs. HALTs at step 1/02/03/04 cannot write to disk because `{skill_package}` is computed only in step 5 §1; for those, the stderr envelope plus exit code is the contract.
|
|
99
|
-
|
|
100
|
-
**Schema:**
|
|
101
|
-
|
|
102
|
-
| Field | Type | Notes |
|
|
103
|
-
| --------------- | -------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
104
|
-
| `status` | string | always `"error"` for HARD HALTs |
|
|
105
|
-
| `exit_code` | integer | matches the Exit Codes table |
|
|
106
|
-
| `phase` | string | step slug where the HALT occurred (e.g. `resolve-target`, `compile`) |
|
|
107
|
-
| `error.code` | string | one of: `resolution-failure`, `write-failure`, `overwrite-cancelled`, `user-cancelled` (formerly `compile-cancelled`), `finalize-blocked`, `ecosystem-redirect` |
|
|
108
|
-
| `error.message` | string | the user-facing message that was displayed |
|
|
109
|
-
| `error.details` | any | optional — phase-specific context (e.g. the failed file path) |
|
|
110
|
-
| `outputs` | object | empty `{}` on early HALTs; partial when files were already written |
|
|
111
|
-
| `summary` | object | empty `{}` on early HALTs |
|
|
112
|
-
| `skill_package` | string \| null | absolute path when known, `null` when HALT preceded step 5 §1 |
|
|
65
|
+
See `references/halt-contract.md` for the exit-code map and the error-result envelope every HARD HALT emits (the `SKF_QUICK_SKILL_RESULT_JSON:` stderr line, the on-disk `-latest.json` write once `{skill_package}` is known, and the schema). Steps load it on their failure path so the wire format survives compaction.
|
|
113
66
|
|
|
114
67
|
## On Activation
|
|
115
68
|
|
|
@@ -139,8 +92,11 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
|
|
|
139
92
|
- `{skillTemplatePath}` ← `workflow.skill_template_path` if non-empty, else `assets/skill-template.md`
|
|
140
93
|
- `{registryResolutionPath}` ← `workflow.registry_resolution_path` if non-empty, else `references/registry-resolution.md`
|
|
141
94
|
- `{batchOutputPath}` ← `workflow.batch_output_path` if non-empty, else `{skills_output_folder}/_batch/`
|
|
95
|
+
- `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — step 6 §3 skips the hook invocation entirely)
|
|
142
96
|
|
|
143
|
-
Stash all
|
|
97
|
+
Stash all four as workflow-context variables. Stage files reference `{skillTemplatePath}` / `{registryResolutionPath}` / `{batchOutputPath}` / `{onCompleteCommand}` directly — no conditional at the usage site. Empty-string overrides cleanly fall through to the bundled default; non-empty values let orgs swap in house-style copies (custom template, registry chain, batch output dir) or wire in a post-completion hook (git-add, register, notify) without forking the skill.
|
|
98
|
+
|
|
99
|
+
**Apply the array surfaces** so the declared overrides are not silent no-ops: execute each entry in `workflow.activation_steps_prepend` in order now; treat every entry in `workflow.persistent_facts` as standing context for the whole run (`file:`-prefixed entries are paths or globs whose contents load as facts — the bundled default loads any `project-context.md`); then, after activation completes and before the first stage runs, execute each entry in `workflow.activation_steps_append` in order.
|
|
144
100
|
|
|
145
101
|
4. **Parse CLI overrides** — capture optional override flags into the workflow context as `{overrides}`. Each override is opt-in; when omitted, the workflow runs as today.
|
|
146
102
|
|
|
@@ -156,9 +112,3 @@ so consumers that hardcode the `-latest.json` path see a deterministic file even
|
|
|
156
112
|
5. **If `--batch` is set**, force `{headless_mode} = true` (log "headless: coerced by --batch" if it was false), then load and read `references/batch-mode.md` in full before proceeding. Follow its protocol to read the batch file, parse the target list, and drive the batch loop that wraps the step 1 → step 7 pipeline that follows.
|
|
157
113
|
|
|
158
114
|
6. Load, read the full file, and then execute `references/resolve-target.md` to begin the workflow. (In batch mode, control returns here for each subsequent target after step 7 completes; see `references/batch-mode.md`.)
|
|
159
|
-
|
|
160
|
-
## Batch Mode
|
|
161
|
-
|
|
162
|
-
When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single argument.
|
|
163
|
-
|
|
164
|
-
See `references/batch-mode.md` for the full protocol (input format, execution loop, summary contract, headless events, exit code).
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# DO NOT EDIT -- overwritten on every update.
|
|
2
2
|
#
|
|
3
3
|
# Workflow customization surface for skf-quick-skill.
|
|
4
|
+
# Team overrides: _bmad/custom/skf-quick-skill.toml (under {project-root})
|
|
5
|
+
# Personal overrides: _bmad/custom/skf-quick-skill.user.toml (under {project-root})
|
|
4
6
|
|
|
5
7
|
[workflow]
|
|
6
8
|
|
|
@@ -42,3 +44,10 @@ persistent_facts = [
|
|
|
42
44
|
skill_template_path = ""
|
|
43
45
|
registry_resolution_path = ""
|
|
44
46
|
batch_output_path = ""
|
|
47
|
+
|
|
48
|
+
# Optional post-completion hook. When non-empty, invoked with
|
|
49
|
+
# `--skill-package=<path>` after the result contract is finalized in step 6.
|
|
50
|
+
# Failures are logged but never fail the workflow. Use for git-add,
|
|
51
|
+
# skill-registry registration, or a notifier on the freshly compiled skill.
|
|
52
|
+
|
|
53
|
+
on_complete = ""
|
|
@@ -6,7 +6,7 @@ nextStepFile: 'resolve-target.md'
|
|
|
6
6
|
|
|
7
7
|
# Batch Mode
|
|
8
8
|
|
|
9
|
-
When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs
|
|
9
|
+
When `--batch <file>` is supplied, quick-skill processes a list of targets from a text file in sequence rather than a single target from arguments. Designed for unattended bulk runs — CI pipelines, mass-rebuilds, and batch meta-workflows.
|
|
10
10
|
|
|
11
11
|
## Input format
|
|
12
12
|
|
|
@@ -43,17 +43,19 @@ Per-line modifiers shadow the global `--description` / `--exports` / `--skip-sni
|
|
|
43
43
|
3. After step 7 completes (success or HARD HALT), record the per-target outcome (target, status, exit_code, skill_package, error.code) into the batch result list.
|
|
44
44
|
4. If `--fail-fast` is set and the target failed, exit the batch loop immediately. Otherwise continue with the next target.
|
|
45
45
|
|
|
46
|
-
Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per
|
|
46
|
+
Per-target output lands in `{skill_package}/` as today, with the per-target result contract at `{skill_package}/quick-skill-result-latest.json` (success or error variant per `references/halt-contract.md`).
|
|
47
47
|
|
|
48
48
|
## Batch summary contract
|
|
49
49
|
|
|
50
50
|
After the last target completes (or `--fail-fast` triggers an early exit), write the batch summary at:
|
|
51
51
|
|
|
52
52
|
```
|
|
53
|
-
{
|
|
54
|
-
{
|
|
53
|
+
{batchOutputPath}quick-skill-batch-{YYYYMMDD-HHmmss}.json
|
|
54
|
+
{batchOutputPath}quick-skill-batch-latest.json (copy, not symlink)
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
+
`{batchOutputPath}` is resolved at SKILL.md On Activation §3 from `workflow.batch_output_path` (bundled default `{skills_output_folder}/_batch/`, trailing slash included).
|
|
58
|
+
|
|
57
59
|
Schema:
|
|
58
60
|
|
|
59
61
|
```json
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'write-and-validate.md'
|
|
3
|
-
skillTemplateData: '
|
|
3
|
+
skillTemplateData: '{skillTemplatePath}'
|
|
4
4
|
quickMetadataRendererProbeOrder:
|
|
5
5
|
- '{project-root}/_bmad/skf/shared/scripts/skf-render-quick-metadata.py'
|
|
6
6
|
- '{project-root}/src/shared/scripts/skf-render-quick-metadata.py'
|
|
@@ -20,7 +20,7 @@ To assemble the best-effort SKILL.md document, context-snippet.md in Vercel-alig
|
|
|
20
20
|
- Follow template structure exactly from {skillTemplateData}
|
|
21
21
|
- Mark any sections with insufficient data as best-effort
|
|
22
22
|
|
|
23
|
-
##
|
|
23
|
+
## Steps
|
|
24
24
|
|
|
25
25
|
### 1. Load Skill Template
|
|
26
26
|
|
|
@@ -31,57 +31,28 @@ Load {skillTemplateData} to understand:
|
|
|
31
31
|
|
|
32
32
|
### 2. Assemble SKILL.md
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Populate the SKILL.md section structure from `{skillTemplateData}` § "SKILL.md Section Structure" (the frontmatter skeleton and the Required/Optional section list live there) using extraction_inventory. The rules below are the deltas the template does not encode:
|
|
35
35
|
|
|
36
|
-
**Frontmatter (
|
|
37
|
-
|
|
38
|
-
The SKILL.md MUST begin with YAML frontmatter:
|
|
39
|
-
|
|
40
|
-
```yaml
|
|
41
|
-
---
|
|
42
|
-
name: {skill_name}
|
|
43
|
-
description: >
|
|
44
|
-
{Trigger-optimized description from extraction_inventory.description.
|
|
45
|
-
1-1024 chars. Include what it does, when to use it, and what NOT to use it for.}
|
|
46
|
-
---
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
**Frontmatter rules:**
|
|
36
|
+
**Frontmatter rules (agentskills.io compliance):**
|
|
50
37
|
- `name`: lowercase alphanumeric + hyphens only, must match the skill output directory name. Prefer gerund form (`processing-pdfs`) for clarity.
|
|
51
|
-
- `description`: non-empty, max 1024 chars, optimized for agent discovery.
|
|
38
|
+
- `description`: non-empty, max 1024 chars, optimized for agent discovery. Use third-person voice ("Processes..." not "I can..." / "You can...") so it reads correctly in the agent's skill index.
|
|
52
39
|
- No other frontmatter fields — only `name` and `description` for community skills
|
|
53
40
|
|
|
54
|
-
**
|
|
55
|
-
- **Overview:** Package name, repository, language, source authority, generation date
|
|
41
|
+
**Per-section override wiring:**
|
|
56
42
|
- **Description:** From `{overrides.description}` if set (subject to the same length/voice checks as extracted descriptions); otherwise from extraction_inventory.description (README-derived)
|
|
57
43
|
- **Key Exports:** From `{overrides.exports}` if set (comma-separated names parsed and trimmed; empty items skipped); otherwise from extraction_inventory.exports — list each with name, type, brief description
|
|
58
|
-
- **Usage Patterns:** From extraction_inventory.usage_patterns (README examples)
|
|
59
44
|
|
|
60
|
-
**
|
|
61
|
-
- **Configuration:** If configuration options were found in source
|
|
62
|
-
- **Dependencies:** Key dependencies from manifest
|
|
63
|
-
- **Notes:** Caveats, limitations, extraction confidence level
|
|
64
|
-
- **Scripts & Assets Note** (if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
|
|
45
|
+
**Scripts & Assets Note** (add as an optional section if source contains `scripts/`, `bin/`, `assets/`, `templates/`, or `schemas/` directories): "This package may include scripts and assets. Run create-skill for full extraction with provenance tracking."
|
|
65
46
|
|
|
66
|
-
**If confidence is low
|
|
67
|
-
- Include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
|
|
47
|
+
**If confidence is low** — include a note: "This skill was generated with limited source data. Consider running create-skill for a more thorough compilation."
|
|
68
48
|
|
|
69
49
|
### 3. Generate Context Snippet
|
|
70
50
|
|
|
71
51
|
**If `{overrides.skip_snippet}` is true** — skip generation and note in the §5 preview: "context-snippet.md skipped per `--skip-snippet` override." Step-05 §2 will skip the corresponding write; step 5 §5 advisory snippet validation will report a "skipped" entry.
|
|
72
52
|
|
|
73
|
-
Otherwise,
|
|
53
|
+
Otherwise, produce context-snippet.md in the Vercel-aligned indexed format from `{skillTemplateData}` § "context-snippet.md Format" (~80-120 tokens).
|
|
74
54
|
|
|
75
|
-
|
|
76
|
-
[{skill_name} v{version}]|root: skills/{skill_name}/
|
|
77
|
-
|IMPORTANT: {skill_name} v{version} — read SKILL.md before writing {skill_name} code. Do NOT rely on training data.
|
|
78
|
-
|quick-start:{SKILL.md#usage-patterns}
|
|
79
|
-
|api: {top-5 exports with () for functions}
|
|
80
|
-
|key-types:{SKILL.md#key-exports} — {inline summary of most important type values}
|
|
81
|
-
|gotchas: {2-3 most critical pitfalls or breaking changes, inline}
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
The anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
|
|
55
|
+
The snippet anchors point to the QS template's actual headings — `#usage-patterns` (Usage Patterns) and `#key-exports` (Key Exports). The QS template has no `## Quick Start` / `## Key Types` headings (those are Deep-tier sections), so the Deep-tier anchors `#quick-start` / `#key-types` would dangle. If the assembled SKILL.md is missing the referenced heading, omit that line rather than emit a dangling anchor.
|
|
85
56
|
|
|
86
57
|
**If fewer than 5 exports:** Use all available exports.
|
|
87
58
|
**If no exports:** Omit the api line.
|
|
@@ -91,7 +62,7 @@ The anchors point to the QS template's actual headings — `#usage-patterns` (Us
|
|
|
91
62
|
|
|
92
63
|
Run the shared renderer against the assembled state. The helper applies the constants, echoes input-derived fields, computes export counts and the ISO 8601 UTC timestamp, and emits the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
|
|
93
64
|
|
|
94
|
-
**Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering
|
|
65
|
+
**Resolve `{quickMetadataRenderer}`** from `{quickMetadataRendererProbeOrder}`; first existing path wins. If no candidate exists, fall back to in-prompt rendering of the canonical envelope per `{skillTemplateData}` § "metadata.json Format".
|
|
95
66
|
|
|
96
67
|
**Probe `tool_versions.skf` first** (the helper expects it as input — the filesystem walk stays here because the helper does no I/O):
|
|
97
68
|
|
|
@@ -108,8 +79,6 @@ echo '{"name":"<name>","version":"<v>","description":"<desc>","language":"<lang>
|
|
|
108
79
|
|
|
109
80
|
The renderer emits the rendered metadata.json on stdout. Capture the output as `metadata` for the §5 preview and step 5 §2's deliverable write.
|
|
110
81
|
|
|
111
|
-
**Schema is canonical in the renderer.** When `{skillTemplateData}` adds a field, the renderer is updated to populate it (constants gain a row; input-derived fields gain a payload key). Do not hand-edit the rendered envelope here — the helper is the single source of truth for the population logic.
|
|
112
|
-
|
|
113
82
|
### 5. Present Compiled Output for Review
|
|
114
83
|
|
|
115
84
|
**If `{headless_mode}` is true** — skip the inline preview (no human reviewer reads it) and emit a one-line summary instead:
|
|
@@ -156,18 +125,12 @@ Display: **Select:** [C] Continue to Validation · [E] Edit description · [S] A
|
|
|
156
125
|
- **IF C** — Load, read entire file, then execute {nextStepFile}.
|
|
157
126
|
- **IF E** — Ask the user for a replacement description ("New description (1–1024 chars):"). Update SKILL.md frontmatter `description` and `metadata.json.description` in the in-memory compiled output, then re-render the §5 preview and redisplay this menu. Do not re-run extraction.
|
|
158
127
|
- **IF S** — Ask the user for an adjusted `scope_hint` ("New scope (e.g. `src/server/`, `packages/core/`):") and optionally a `language_hint`. Update the extraction context with the new hints, then load `quick-extract.md` to re-extract. The new extraction returns to §1 of this step on completion. Discards the prior compiled output.
|
|
159
|
-
- **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the
|
|
128
|
+
- **IF Q** — HARD HALT with **exit code 6 (user-cancelled)** per the exit-code map in `references/halt-contract.md`: "Compilation cancelled. No files written." Before exiting, emit the error result contract per `references/halt-contract.md` (`phase: "compile"`, `error.code: "user-cancelled"`, `skill_package: null`). Do not proceed to validation; do not write any artifacts.
|
|
160
129
|
- **IF Any other** — Help the user adjust the compiled output (treated as a free-form revision request), then redisplay the menu.
|
|
161
130
|
|
|
162
|
-
####
|
|
131
|
+
#### Gate:
|
|
163
132
|
|
|
164
|
-
-
|
|
133
|
+
- Halt and wait for user input after presenting the compiled output; only [C] (or a headless auto-approve) chains to `{nextStepFile}` for validation.
|
|
165
134
|
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Continue, log: "headless: auto-approve compiled output"
|
|
166
|
-
-
|
|
167
|
-
- [E] is local: re-renders the preview without re-running extraction
|
|
168
|
-
- [S] is the heavy option: it discards the compiled output and re-runs step 3 with new hints
|
|
169
|
-
|
|
170
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
171
|
-
|
|
172
|
-
ONLY WHEN the user reviews the compiled output and selects 'C' (or [Q] HALTs / [S] re-runs / [E] redisplays) will you load and read fully `{nextStepFile}` to execute validation.
|
|
135
|
+
- [E] re-renders the preview without re-running extraction; [S] discards the compiled output and re-runs step 3 with new hints.
|
|
173
136
|
|
|
@@ -12,11 +12,10 @@ To query the agentskills.io ecosystem for an existing official skill matching th
|
|
|
12
12
|
|
|
13
13
|
## Rules
|
|
14
14
|
|
|
15
|
-
- This check is advisory — never block the workflow on failure
|
|
16
15
|
- 5-second timeout on ecosystem queries; tool unavailability is a silent skip, not an error
|
|
17
16
|
- Do not begin extraction or compilation
|
|
18
17
|
|
|
19
|
-
##
|
|
18
|
+
## Steps
|
|
20
19
|
|
|
21
20
|
### 1. Query Ecosystem
|
|
22
21
|
|
|
@@ -54,34 +53,20 @@ An official skill already exists. You can:
|
|
|
54
53
|
**[I] Install** — Install the existing official skill instead (exits this workflow)
|
|
55
54
|
**[A] Abort** — Cancel compilation"
|
|
56
55
|
|
|
57
|
-
### 3. Handle Match Menu (
|
|
56
|
+
### 3. Handle Match Menu (only when a match was found)
|
|
58
57
|
|
|
59
58
|
#### Menu Handling Logic:
|
|
60
59
|
|
|
61
60
|
- IF P: Set `ecosystem_status: match-proceed`, then load, read entire file, then execute {nextStepFile}
|
|
62
|
-
- IF I: Display install instructions for the official skill, emit the HARD HALT envelope per
|
|
61
|
+
- IF I: Display install instructions for the official skill, emit the HARD HALT envelope per `references/halt-contract.md` (`phase: "ecosystem-check"`, `error.code: "ecosystem-redirect"`, `error.message: "User opted to install existing official skill instead of compiling a custom community skill."`, `skill_package: null`), exit with code 8 (ecosystem-redirect). Skill package is unknown at this phase — no on-disk result file is written.
|
|
63
62
|
- IF A: Display "Compilation cancelled.", emit the HARD HALT envelope (`phase: "ecosystem-check"`, `error.code: "user-cancelled"`, `error.message: "User aborted at ecosystem-match gate."`, `skill_package: null`), exit with code 6 (user-cancelled). Skill package is unknown at this phase — no on-disk result file is written.
|
|
64
63
|
- IF Any other: help user, then redisplay the match menu
|
|
65
64
|
|
|
66
|
-
####
|
|
65
|
+
#### Gate:
|
|
67
66
|
|
|
68
|
-
- ONLY display this menu when ecosystem_status is match
|
|
69
|
-
- ALWAYS halt and wait for user input when match is found
|
|
70
67
|
- **GATE [default: P]** — If `{headless_mode}` and match found: auto-proceed with [P] Proceed (compile custom skill anyway), log: "headless: ecosystem match found, auto-proceeding with custom compilation"
|
|
71
|
-
- For no-match and skip cases, auto-proceed without menu
|
|
72
68
|
|
|
73
69
|
### 4. Auto-Proceed (No Match or Skip)
|
|
74
70
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
- After no-match or skip determination, immediately load, read entire file, then execute {nextStepFile}
|
|
78
|
-
|
|
79
|
-
#### EXECUTION RULES:
|
|
80
|
-
|
|
81
|
-
- This is an auto-proceed path — no user interaction needed
|
|
82
|
-
- Proceed directly to extraction step
|
|
83
|
-
|
|
84
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
85
|
-
|
|
86
|
-
ONLY WHEN ecosystem check completes (match with user choice, no-match, or skip) will you load and read fully `{nextStepFile}` to proceed to source extraction.
|
|
71
|
+
For no-match and skip, load and execute {nextStepFile} to proceed to source extraction.
|
|
87
72
|
|