bmad-module-skill-forge 1.8.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +1 -1
- package/README.md +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 +42 -3
- 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 +9 -3
- package/docs/why-skf.md +1 -1
- package/docs/workflows.md +73 -27
- package/package.json +2 -2
- package/src/module-help.csv +2 -1
- package/src/shared/_known-workarounds.yaml +155 -0
- package/src/shared/data/language-corpora.json +32 -0
- package/src/shared/references/pipeline-contracts.md +14 -2
- package/src/shared/scripts/schemas/skf-brief-result-envelope.v1.json +6 -1
- package/src/shared/scripts/schemas/skill-brief.v1.json +6 -1
- package/src/shared/scripts/skf-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +417 -0
- package/src/shared/scripts/skf-detect-language.py +5 -3
- package/src/shared/scripts/skf-emit-brief-result-envelope.py +12 -1
- package/src/shared/scripts/skf-emit-result-envelope.py +17 -0
- package/src/shared/scripts/skf-extract-public-api.py +53 -0
- package/src/shared/scripts/skf-language-corpora.py +100 -0
- package/src/shared/scripts/skf-merge-doc-urls.py +244 -0
- package/src/shared/scripts/skf-preapply.py +192 -0
- package/src/shared/scripts/skf-shape-detect.py +1114 -0
- package/src/shared/scripts/skf-validate-brief-schema.py +2 -5
- package/src/shared/scripts/skf-validate-pins.py +368 -0
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +26 -20
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/references/init.md +30 -0
- package/src/skf-analyze-source/references/step-auto-scope.md +677 -0
- package/src/skf-analyze-source/references/step-shape-detect.md +86 -0
- package/src/skf-audit-skill/SKILL.md +1 -0
- package/src/skf-audit-skill/assets/drift-report-template.md +6 -0
- package/src/skf-audit-skill/references/init.md +1 -1
- package/src/skf-audit-skill/references/report.md +4 -0
- package/src/skf-audit-skill/references/severity-classify.md +1 -1
- package/src/skf-audit-skill/references/step-doc-drift.md +147 -0
- package/src/skf-brief-skill/SKILL.md +7 -3
- package/src/skf-brief-skill/assets/skill-brief-schema.md +1 -1
- package/src/skf-brief-skill/references/analyze-target.md +7 -4
- package/src/skf-brief-skill/references/confirm-brief.md +0 -1
- package/src/skf-brief-skill/references/gather-intent.md +22 -2
- package/src/skf-brief-skill/references/scope-definition.md +2 -1
- package/src/skf-brief-skill/references/step-auto-brief.md +188 -0
- package/src/skf-brief-skill/references/step-auto-validate.md +209 -0
- package/src/skf-brief-skill/references/write-brief.md +2 -3
- package/src/skf-campaign/SKILL.md +190 -0
- package/src/skf-campaign/assets/campaign-state-schema.json +191 -0
- package/src/skf-campaign/customize.toml +73 -0
- package/src/skf-campaign/manifest.yaml +11 -0
- package/src/skf-campaign/references/campaign-directive-spec.md +121 -0
- package/src/skf-campaign/references/health-check.md +35 -0
- package/src/skf-campaign/references/step-01-setup.md +122 -0
- package/src/skf-campaign/references/step-02-strategy.md +97 -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 +87 -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 +114 -0
- package/src/skf-campaign/scripts/.gitkeep +0 -0
- package/src/skf-campaign/scripts/campaign-deps.py +235 -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-kickoff.py +158 -0
- package/src/skf-campaign/scripts/campaign-report.py +249 -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 +4 -1
- package/src/skf-create-skill/assets/compile-assembly-rules.md +22 -0
- package/src/skf-create-skill/assets/skill-sections.md +2 -0
- package/src/skf-create-skill/references/compile.md +5 -2
- package/src/skf-create-skill/references/extract.md +9 -1
- package/src/skf-create-skill/references/extraction-patterns.md +3 -1
- package/src/skf-create-skill/references/generate-artifacts.md +11 -2
- package/src/skf-create-skill/references/health-check.md +2 -2
- package/src/skf-create-skill/references/report.md +17 -1
- package/src/skf-create-skill/references/source-resolution-protocols.md +1 -1
- package/src/skf-create-skill/references/step-auto-shard.md +110 -0
- package/src/skf-create-skill/references/step-doc-rot.md +109 -0
- package/src/skf-create-skill/references/step-doc-sources.md +123 -0
- package/src/skf-create-skill/references/sub/fetch-docs.md +29 -0
- package/src/skf-create-skill/references/validate.md +12 -3
- package/src/skf-drop-skill/SKILL.md +2 -2
- package/src/skf-drop-skill/references/execute.md +20 -9
- package/src/skf-drop-skill/references/report.md +2 -0
- package/src/skf-drop-skill/references/select.md +7 -2
- package/src/skf-forger/SKILL.md +15 -4
- package/src/skf-refine-architecture/SKILL.md +2 -1
- package/src/skf-refine-architecture/references/compile.md +1 -1
- package/src/skf-refine-architecture/references/report.md +1 -1
- package/src/skf-rename-skill/SKILL.md +2 -2
- package/src/skf-rename-skill/references/execute.md +5 -4
- package/src/skf-rename-skill/references/rebuild-context.md +2 -2
- package/src/skf-rename-skill/references/select.md +3 -3
- package/src/skf-setup/SKILL.md +1 -1
- package/src/skf-setup/references/auto-index.md +3 -1
- package/src/skf-setup/references/detect-and-tier.md +4 -0
- package/src/skf-setup/references/report.md +4 -1
- package/src/skf-setup/references/tier-rules.md +1 -1
- package/src/skf-test-skill/SKILL.md +8 -7
- package/src/skf-test-skill/customize.toml +2 -1
- package/src/skf-test-skill/references/coverage-check.md +10 -0
- package/src/skf-test-skill/references/external-validators.md +1 -1
- package/src/skf-test-skill/references/init.md +16 -1
- package/src/skf-test-skill/references/report.md +5 -1
- package/src/skf-test-skill/references/score.md +95 -6
- package/src/skf-test-skill/references/source-access-protocol.md +13 -3
- package/src/skf-test-skill/references/step-hard-gate.md +73 -0
- package/src/skf-test-skill/scripts/compute-score.py +4 -3
- package/src/skf-test-skill/templates/test-report-template.md +1 -0
- package/src/skf-update-skill/customize.toml +0 -9
- package/src/skf-update-skill/references/detect-changes.md +33 -3
- package/src/skf-update-skill/references/health-check.md +2 -2
- package/src/skf-update-skill/references/init.md +1 -0
- package/src/skf-update-skill/references/re-extract.md +15 -1
- package/src/skf-verify-stack/references/report.md +1 -1
- package/tools/cli/lib/ui.js +3 -2
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"title": "campaign-state",
|
|
4
|
+
"description": "Schema for _campaign-state.yaml — single source of truth for campaign orchestration state",
|
|
5
|
+
"type": "object",
|
|
6
|
+
"required": ["campaign", "skills", "dependency_graph"],
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"campaign": {
|
|
10
|
+
"type": "object",
|
|
11
|
+
"required": ["name", "started_at", "last_updated", "current_stage", "quality_gate", "health_findings_queue"],
|
|
12
|
+
"additionalProperties": false,
|
|
13
|
+
"properties": {
|
|
14
|
+
"name": {
|
|
15
|
+
"type": "string"
|
|
16
|
+
},
|
|
17
|
+
"started_at": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"format": "date-time"
|
|
20
|
+
},
|
|
21
|
+
"last_updated": {
|
|
22
|
+
"type": "string",
|
|
23
|
+
"format": "date-time"
|
|
24
|
+
},
|
|
25
|
+
"current_stage": {
|
|
26
|
+
"type": "integer",
|
|
27
|
+
"minimum": 0,
|
|
28
|
+
"maximum": 10
|
|
29
|
+
},
|
|
30
|
+
"directive_path": {
|
|
31
|
+
"type": "string"
|
|
32
|
+
},
|
|
33
|
+
"quality_gate": {
|
|
34
|
+
"type": "object",
|
|
35
|
+
"required": ["hard", "soft_target", "soft_fallback"],
|
|
36
|
+
"additionalProperties": false,
|
|
37
|
+
"properties": {
|
|
38
|
+
"hard": {
|
|
39
|
+
"type": "string"
|
|
40
|
+
},
|
|
41
|
+
"soft_target": {
|
|
42
|
+
"type": "number"
|
|
43
|
+
},
|
|
44
|
+
"soft_fallback": {
|
|
45
|
+
"type": "number"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"health_findings_queue": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"enum": ["local", "improvement"]
|
|
52
|
+
},
|
|
53
|
+
"architecture_doc_path": {
|
|
54
|
+
"type": ["string", "null"],
|
|
55
|
+
"description": "Path to the architecture document consumed by the verify (Stage 7) and refine (Stage 8) stages. Sourced at setup; null when the campaign runs no verification."
|
|
56
|
+
},
|
|
57
|
+
"capstone": {
|
|
58
|
+
"type": ["object", "null"],
|
|
59
|
+
"additionalProperties": false,
|
|
60
|
+
"description": "Capstone (stack) outcome composed from all completed campaign skills (Tier A and Tier B). Campaign-level summary; the composed skill itself lives at skill_path.",
|
|
61
|
+
"properties": {
|
|
62
|
+
"skill_path": {
|
|
63
|
+
"type": ["string", "null"]
|
|
64
|
+
},
|
|
65
|
+
"quality_score": {
|
|
66
|
+
"type": ["number", "null"]
|
|
67
|
+
},
|
|
68
|
+
"verified": {
|
|
69
|
+
"type": ["boolean", "null"]
|
|
70
|
+
},
|
|
71
|
+
"completed_at": {
|
|
72
|
+
"type": ["string", "null"],
|
|
73
|
+
"format": "date-time"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"verification": {
|
|
78
|
+
"type": ["object", "null"],
|
|
79
|
+
"additionalProperties": false,
|
|
80
|
+
"description": "Stage 7 verify-stack summary. Detailed findings live in the external report at report_path.",
|
|
81
|
+
"properties": {
|
|
82
|
+
"report_path": {
|
|
83
|
+
"type": ["string", "null"]
|
|
84
|
+
},
|
|
85
|
+
"overall_verdict": {
|
|
86
|
+
"type": ["string", "null"],
|
|
87
|
+
"enum": ["Verified", "Plausible", "Risky", "Blocked", null]
|
|
88
|
+
},
|
|
89
|
+
"coverage_percentage": {
|
|
90
|
+
"type": ["number", "null"]
|
|
91
|
+
},
|
|
92
|
+
"recommendation_count": {
|
|
93
|
+
"type": ["integer", "null"]
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
"refinement": {
|
|
98
|
+
"type": ["object", "null"],
|
|
99
|
+
"additionalProperties": false,
|
|
100
|
+
"description": "Stage 8 refine-architecture summary. The refined document lives at refined_path.",
|
|
101
|
+
"properties": {
|
|
102
|
+
"refined_path": {
|
|
103
|
+
"type": ["string", "null"]
|
|
104
|
+
},
|
|
105
|
+
"gap_count": {
|
|
106
|
+
"type": ["integer", "null"]
|
|
107
|
+
},
|
|
108
|
+
"issue_count": {
|
|
109
|
+
"type": ["integer", "null"]
|
|
110
|
+
},
|
|
111
|
+
"improvement_count": {
|
|
112
|
+
"type": ["integer", "null"]
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"skills": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": {
|
|
121
|
+
"type": "object",
|
|
122
|
+
"required": ["name", "status", "tier"],
|
|
123
|
+
"additionalProperties": false,
|
|
124
|
+
"properties": {
|
|
125
|
+
"name": {
|
|
126
|
+
"type": "string"
|
|
127
|
+
},
|
|
128
|
+
"status": {
|
|
129
|
+
"type": "string",
|
|
130
|
+
"enum": ["pending", "active", "completed", "failed", "skipped"]
|
|
131
|
+
},
|
|
132
|
+
"depends_on": {
|
|
133
|
+
"type": "array",
|
|
134
|
+
"items": {
|
|
135
|
+
"type": "string"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"tier": {
|
|
139
|
+
"type": "string",
|
|
140
|
+
"enum": ["A", "B"]
|
|
141
|
+
},
|
|
142
|
+
"pin": {
|
|
143
|
+
"type": ["string", "null"]
|
|
144
|
+
},
|
|
145
|
+
"brief_path": {
|
|
146
|
+
"type": ["string", "null"]
|
|
147
|
+
},
|
|
148
|
+
"skill_path": {
|
|
149
|
+
"type": ["string", "null"]
|
|
150
|
+
},
|
|
151
|
+
"quality_score": {
|
|
152
|
+
"type": ["number", "null"]
|
|
153
|
+
},
|
|
154
|
+
"workarounds_applied": {
|
|
155
|
+
"type": "array",
|
|
156
|
+
"items": {
|
|
157
|
+
"type": "string"
|
|
158
|
+
}
|
|
159
|
+
},
|
|
160
|
+
"started_at": {
|
|
161
|
+
"type": ["string", "null"],
|
|
162
|
+
"format": "date-time"
|
|
163
|
+
},
|
|
164
|
+
"completed_at": {
|
|
165
|
+
"type": ["string", "null"],
|
|
166
|
+
"format": "date-time"
|
|
167
|
+
},
|
|
168
|
+
"commit_sha": {
|
|
169
|
+
"type": ["string", "null"]
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
},
|
|
174
|
+
"dependency_graph": {
|
|
175
|
+
"type": "object",
|
|
176
|
+
"required": ["execution_order", "circular_deps_detected"],
|
|
177
|
+
"additionalProperties": false,
|
|
178
|
+
"properties": {
|
|
179
|
+
"execution_order": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"items": {
|
|
182
|
+
"type": "string"
|
|
183
|
+
}
|
|
184
|
+
},
|
|
185
|
+
"circular_deps_detected": {
|
|
186
|
+
"type": "boolean"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# DO NOT EDIT -- overwritten on every update.
|
|
2
|
+
#
|
|
3
|
+
# Workflow customization surface for skf-campaign.
|
|
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 (config load, customization
|
|
12
|
+
# resolve). Overrides append. Use for org-wide pre-flight checks (auth,
|
|
13
|
+
# network, compliance) that must precede any orchestration 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 campaign
|
|
24
|
+
# (house style, naming conventions, quality guardrails). These are injected
|
|
25
|
+
# into every per-skill kickoff, so project-scoped house facts propagate to
|
|
26
|
+
# the whole campaign. Overrides append.
|
|
27
|
+
#
|
|
28
|
+
# Each entry is either:
|
|
29
|
+
# - a literal sentence, e.g. "All skills must cite their upstream source."
|
|
30
|
+
# - a file reference prefixed with `file:`, e.g.
|
|
31
|
+
# "file:{project-root}/docs/skill-style.md" (globs supported; file
|
|
32
|
+
# contents are loaded and treated as facts).
|
|
33
|
+
|
|
34
|
+
persistent_facts = [
|
|
35
|
+
"file:{project-root}/**/project-context.md",
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
# --- Workspace path ---
|
|
39
|
+
#
|
|
40
|
+
# Where the campaign keeps its state, backup, brief, batch input, archive,
|
|
41
|
+
# and decision log. Empty string = use the bundled default
|
|
42
|
+
# `{forge_data_folder}/_campaign`. Override to relocate campaign artifacts
|
|
43
|
+
# (e.g. a shared volume) without editing every step file. Resolved once in
|
|
44
|
+
# On Activation as {campaignWorkspacePath}.
|
|
45
|
+
|
|
46
|
+
campaign_workspace_path = ""
|
|
47
|
+
|
|
48
|
+
# --- Quality gate ---
|
|
49
|
+
#
|
|
50
|
+
# Campaign-wide quality bar applied to every skill. Scalars override the
|
|
51
|
+
# bundled defaults; the per-campaign brief and any directive `## Quality
|
|
52
|
+
# Overrides` still take precedence at runtime. Override here to change the
|
|
53
|
+
# org-wide default without forking the skill.
|
|
54
|
+
|
|
55
|
+
quality_gate_hard = "zero-critical-high"
|
|
56
|
+
quality_gate_soft_target = 90
|
|
57
|
+
quality_gate_soft_fallback = 80
|
|
58
|
+
|
|
59
|
+
# --- Optional template overrides ---
|
|
60
|
+
#
|
|
61
|
+
# Lift the canonical template paths so orgs can substitute house-style copies
|
|
62
|
+
# without forking the skill. Empty string = use the bundled default under
|
|
63
|
+
# `templates/`.
|
|
64
|
+
|
|
65
|
+
report_template_path = ""
|
|
66
|
+
kickoff_template_path = ""
|
|
67
|
+
brief_template_path = ""
|
|
68
|
+
|
|
69
|
+
# Optional post-completion hook. When non-empty, the workflow invokes:
|
|
70
|
+
# <on_complete> --report-path=<path-to-campaign-report.md>
|
|
71
|
+
# after the campaign report is finalized (step-11). Failures are logged to
|
|
72
|
+
# the decision log but never fail the campaign. Empty = no-op.
|
|
73
|
+
on_complete = ""
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
code: CA
|
|
2
|
+
name: skf-campaign
|
|
3
|
+
description: "Campaign orchestration — multi-library skill production with dependency tracking"
|
|
4
|
+
version: "2.0.0"
|
|
5
|
+
trigger: campaign
|
|
6
|
+
parent_module: skf
|
|
7
|
+
|
|
8
|
+
config:
|
|
9
|
+
state_file: "_campaign-state.yaml"
|
|
10
|
+
backup_file: "_campaign-state.yaml.bak"
|
|
11
|
+
directive_file: "_campaign-directive.md"
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
---
|
|
2
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
3
|
+
directiveFile: '_campaign-directive.md'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Campaign Directive Specification
|
|
7
|
+
|
|
8
|
+
This is the **canonical contract** for the campaign directive. SKILL.md and the
|
|
9
|
+
step files' "Read Directive" sections defer to it rather than re-specifying the
|
|
10
|
+
format — when a step loads `campaign.directive_path`, it applies the contents
|
|
11
|
+
per the sections below.
|
|
12
|
+
|
|
13
|
+
## Purpose
|
|
14
|
+
|
|
15
|
+
The campaign directive (`_campaign-directive.md`) is a file-based standing directive that provides campaign-wide policy persisting across context boundaries. It is:
|
|
16
|
+
|
|
17
|
+
- **Human-readable** — plain markdown, editable with any text editor
|
|
18
|
+
- **Auditable** — version-controllable alongside campaign artifacts
|
|
19
|
+
- **Context-boundary safe** — re-read from disk at each stage transition, with no dependency on LLM memory (NFR-2)
|
|
20
|
+
|
|
21
|
+
The directive allows the operator to adjust campaign-wide policy without editing the state file or relying on LLM memory.
|
|
22
|
+
|
|
23
|
+
## File Format
|
|
24
|
+
|
|
25
|
+
- **Encoding:** UTF-8 markdown
|
|
26
|
+
- **Frontmatter:** not required (plain content is sufficient)
|
|
27
|
+
- **Location:** the path specified by `campaign.directive_path` in the campaign state file
|
|
28
|
+
- **Default filename:** `_campaign-directive.md` (configured in `manifest.yaml` as `config.directive_file`)
|
|
29
|
+
|
|
30
|
+
## Recognized Sections
|
|
31
|
+
|
|
32
|
+
All sections are optional. The directive may contain any combination of these, or none at all.
|
|
33
|
+
|
|
34
|
+
### `## Quality Overrides`
|
|
35
|
+
|
|
36
|
+
Operator adjustments to quality gates for specific skills or the entire campaign.
|
|
37
|
+
|
|
38
|
+
Example:
|
|
39
|
+
```markdown
|
|
40
|
+
## Quality Overrides
|
|
41
|
+
|
|
42
|
+
- Accept 85% for library-x due to incomplete upstream docs
|
|
43
|
+
- Lower soft gate to 70% for experimental-sdk (early-stage repo)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### `## Skip List`
|
|
47
|
+
|
|
48
|
+
Skills to skip during processing, with rationale.
|
|
49
|
+
|
|
50
|
+
Example:
|
|
51
|
+
```markdown
|
|
52
|
+
## Skip List
|
|
53
|
+
|
|
54
|
+
- Skip library-y — upstream repo is in maintenance mode
|
|
55
|
+
- Skip legacy-tool — will be removed in next sprint
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `## Pipeline Flags`
|
|
59
|
+
|
|
60
|
+
Per-skill or campaign-wide pipeline modifiers.
|
|
61
|
+
|
|
62
|
+
Example:
|
|
63
|
+
```markdown
|
|
64
|
+
## Pipeline Flags
|
|
65
|
+
|
|
66
|
+
- Use `--pin main` for all unpinned skills
|
|
67
|
+
- Force forge-auto mode for large-repo-z
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### `## Notes`
|
|
71
|
+
|
|
72
|
+
Free-form operator context for the LLM agent processing the campaign.
|
|
73
|
+
|
|
74
|
+
Example:
|
|
75
|
+
```markdown
|
|
76
|
+
## Notes
|
|
77
|
+
|
|
78
|
+
Focus on documentation quality this run — the team is preparing for an external audit.
|
|
79
|
+
Prioritize skills that feed into the public API layer.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Unrecognized Sections
|
|
83
|
+
|
|
84
|
+
Any section heading not listed above is treated as general guidance. The LLM agent reads and applies judgment based on the content. This allows operators to add ad-hoc context without modifying the specification.
|
|
85
|
+
|
|
86
|
+
## Read Contract
|
|
87
|
+
|
|
88
|
+
The directive is read from the path stored in `campaign.directive_path` (in the campaign state file) at stage entry. Every step that loads state and performs actionable processing checks for and applies the directive.
|
|
89
|
+
|
|
90
|
+
Steps that read the directive:
|
|
91
|
+
- **step-02-strategy** — applies directive contents as campaign-wide context for strategy processing (e.g. `## Notes` visible while reviewing the computed order; the order itself is computed deterministically by `campaign-deps.py`)
|
|
92
|
+
- **step-05-skill-loop** — directive populates `{{directive_content}}` in kickoff template and provides campaign-wide context for all skill processing
|
|
93
|
+
- **step-06-batch** — operator may want skip/quality overrides for Tier B batch processing
|
|
94
|
+
- **step-08-verify** — operator may want to influence verification focus areas
|
|
95
|
+
- **step-09-refine** — operator may want to guide refinement priorities
|
|
96
|
+
- **step-10-export** — operator may want to exclude specific skills from export
|
|
97
|
+
|
|
98
|
+
Steps that do NOT read the directive:
|
|
99
|
+
- **step-01-setup** — creates the state file; `directive_path` is collected as input, not read
|
|
100
|
+
- **step-03-pins** — pin validation is deterministic (Python script); directive cannot influence gh API calls
|
|
101
|
+
- **step-04-provenance** — repo access verification is deterministic; directive cannot influence commit SHA recording
|
|
102
|
+
- **step-07-capstone** — SS compose-mode is mechanical aggregation; no operator policy applies
|
|
103
|
+
- **step-11-maintenance** — report generation is templated; health check is autonomous
|
|
104
|
+
- **step-resume** — routing step, not a processing step
|
|
105
|
+
|
|
106
|
+
## Absence Behavior
|
|
107
|
+
|
|
108
|
+
- If `campaign.directive_path` is not set in the state file: no error, proceed with defaults
|
|
109
|
+
- If `campaign.directive_path` is set but the file does not exist at that path: no error, proceed with defaults
|
|
110
|
+
- The directive is always optional — a campaign runs identically without one
|
|
111
|
+
|
|
112
|
+
## Modification Contract
|
|
113
|
+
|
|
114
|
+
The operator may edit the directive file at any time between stages. The next stage that reads the directive will pick up the updated version. There is no caching — the directive is always read fresh from disk at stage entry.
|
|
115
|
+
|
|
116
|
+
## Lifecycle
|
|
117
|
+
|
|
118
|
+
1. **Created:** before or during Stage 0 (setup) — the operator provides the file path, or it defaults to `_campaign-directive.md`
|
|
119
|
+
2. **Read:** at each stage entry by applicable steps (see Read Contract above)
|
|
120
|
+
3. **Modified:** at any time between stages by the operator
|
|
121
|
+
4. **Consumed:** by the LLM agent as campaign-wide context influencing processing decisions
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
# Note: `shared/health-check.md` resolves relative to the SKF module root
|
|
3
|
+
# ({project-root}/_bmad/skf/ when installed, {project-root}/src/ during
|
|
4
|
+
# development), NOT relative to this step file.
|
|
5
|
+
nextStepFile: 'shared/health-check.md'
|
|
6
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
10
|
+
|
|
11
|
+
# Workflow Health Check
|
|
12
|
+
|
|
13
|
+
## STEP GOAL:
|
|
14
|
+
|
|
15
|
+
Apply the operator's findings-routing consent, then chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of skf-campaign — after the shared health check completes, the workflow is fully done.
|
|
16
|
+
|
|
17
|
+
## Rules
|
|
18
|
+
|
|
19
|
+
- No user-facing reports, file writes, or result contracts in this step — those belong in step 11.
|
|
20
|
+
- The ONLY processing permitted here is reading the routing preference (below) and carrying it into `{nextStepFile}`; otherwise delegate directly with no additional commentary.
|
|
21
|
+
|
|
22
|
+
## MANDATORY SEQUENCE
|
|
23
|
+
|
|
24
|
+
### 1. Apply findings-routing consent
|
|
25
|
+
|
|
26
|
+
Read `campaign.health_findings_queue` from `{stateFile}` and carry it into the shared health check as the operator's **already-decided** routing consent (so the shared step does not re-prompt, satisfying its "explicit opt-in" requirement for non-bug findings):
|
|
27
|
+
|
|
28
|
+
- `"improvement"` — the operator opted in at setup: route this campaign's friction/gap findings to the shared improvement queue (the shared step's opt-in is pre-satisfied; do not re-prompt).
|
|
29
|
+
- `"local"` (default) — keep findings in the local queue only; do not submit to the shared queue.
|
|
30
|
+
|
|
31
|
+
If the state file is unreadable, default to `"local"` (never submit without consent).
|
|
32
|
+
|
|
33
|
+
### 2. Delegate
|
|
34
|
+
|
|
35
|
+
Load `{nextStepFile}`, read it fully, then execute it — applying the routing consent from step 1.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-02-strategy.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
briefFile: '{campaignWorkspacePath}/campaign-brief.yaml'
|
|
6
|
+
templateFile: '{briefTemplatePath}'
|
|
7
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
8
|
+
manifestScript: 'scripts/campaign-parse-manifest.py'
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
12
|
+
|
|
13
|
+
# Setup
|
|
14
|
+
|
|
15
|
+
## STEP GOAL:
|
|
16
|
+
|
|
17
|
+
Collect campaign inputs from the operator, create the initial `_campaign-state.yaml`, and generate `campaign-brief.yaml` so the campaign has a persistent starting point that survives context death.
|
|
18
|
+
|
|
19
|
+
This is the only step that creates the state file (it does not yet exist). All subsequent steps use **read-backup-modify-write** per the State Contract in SKILL.md.
|
|
20
|
+
|
|
21
|
+
## RULES
|
|
22
|
+
|
|
23
|
+
- This step creates the state file — there is no existing state to read or back up.
|
|
24
|
+
- Validate the written state with `uv run {validateScript} --state-file {stateFile}` before generating the brief. HALT (exit code 3, `invalid-state`) on non-zero, surfacing the script's `errors[]`.
|
|
25
|
+
- If `{headless_mode}` is true, draw inputs from `--brief`/`--manifest` (On Activation step 4) and auto-proceed through confirmation gates with the default action, logging each auto-decision to the decision log.
|
|
26
|
+
|
|
27
|
+
## TASKS
|
|
28
|
+
|
|
29
|
+
### §1 — Collect Inputs
|
|
30
|
+
|
|
31
|
+
Accept from the operator (or, in headless mode, from the `--brief`/`--manifest` source parsed in On Activation):
|
|
32
|
+
|
|
33
|
+
- `campaign_name` — string identifier for this campaign run
|
|
34
|
+
- Target libraries — each entry requires:
|
|
35
|
+
- `name` — skill name
|
|
36
|
+
- `repo_url` — source repository URL
|
|
37
|
+
- `tier` — `"A"` (full pipeline) or `"B"` (batch)
|
|
38
|
+
- `pin` — version pin (string) or `null` for latest
|
|
39
|
+
- `depends_on` — array of skill names this target depends on (may be empty)
|
|
40
|
+
- `directive_path` (optional) — path to a `_campaign-directive.md` file with operator directives (contract: `references/campaign-directive-spec.md`)
|
|
41
|
+
- `architecture_doc_path` (optional) — path to the architecture document the verify (Stage 7) and refine (Stage 8) stages consume. If omitted here, those stages discover it at runtime (`docs/architecture.md`, then `_bmad-output/planning-artifacts/architecture.md`). Capturing it now persists the choice across resume and avoids re-prompting.
|
|
42
|
+
|
|
43
|
+
When seeding from `--manifest`, parse it deterministically: `uv run {manifestScript} <manifest-file>`. If the result's `errors[]` is non-empty (exit 1), HALT listing the offending line numbers — never run a partial target set. When seeding from `--brief`, read the existing `campaign-brief.yaml` directly.
|
|
44
|
+
|
|
45
|
+
If no targets can be collected (empty interactive input or empty `--brief`/`--manifest`), HALT with guidance — a campaign needs at least one target.
|
|
46
|
+
|
|
47
|
+
### §2 — Health Queue Preference
|
|
48
|
+
|
|
49
|
+
Default to `"local"` (project-local findings queue). Present the opt-in prompt:
|
|
50
|
+
|
|
51
|
+
> Send anonymized quality findings to the shared improvement queue? [y/N]
|
|
52
|
+
|
|
53
|
+
- **y** — set `health_findings_queue` to `"improvement"`
|
|
54
|
+
- **N** (default) — keep `health_findings_queue` as `"local"`
|
|
55
|
+
|
|
56
|
+
In headless mode: auto-select `"local"` (N) and log the auto-decision.
|
|
57
|
+
|
|
58
|
+
### §3 — Build State Object
|
|
59
|
+
|
|
60
|
+
Construct `_campaign-state.yaml` in memory from collected inputs. Use the campaign-wide quality gate resolved in On Activation: `{qualityGateHard}` / `{qualityGateSoftTarget}` / `{qualityGateSoftFallback}`. Note: `repo_url` (collected in §1) is NOT part of the state schema — it belongs in the brief only (§5). The state schema enforces `additionalProperties: false`, so including it would fail validation.
|
|
61
|
+
|
|
62
|
+
```yaml
|
|
63
|
+
campaign:
|
|
64
|
+
name: "{campaign_name}"
|
|
65
|
+
started_at: "{current_iso8601_with_tz}"
|
|
66
|
+
last_updated: "{current_iso8601_with_tz}"
|
|
67
|
+
current_stage: 0
|
|
68
|
+
directive_path: "{directive_path or omit if not provided}"
|
|
69
|
+
architecture_doc_path: "{architecture_doc_path or omit if not provided}"
|
|
70
|
+
quality_gate:
|
|
71
|
+
hard: "{qualityGateHard}"
|
|
72
|
+
soft_target: {qualityGateSoftTarget}
|
|
73
|
+
soft_fallback: {qualityGateSoftFallback}
|
|
74
|
+
health_findings_queue: "{local or improvement}"
|
|
75
|
+
skills:
|
|
76
|
+
# One entry per target:
|
|
77
|
+
- name: "{target.name}"
|
|
78
|
+
status: "pending"
|
|
79
|
+
depends_on: [] # from target.depends_on
|
|
80
|
+
tier: "{target.tier}"
|
|
81
|
+
pin: null # from target.pin
|
|
82
|
+
brief_path: null # populated in step-05 once BS produces the skill's brief
|
|
83
|
+
skill_path: null
|
|
84
|
+
quality_score: null
|
|
85
|
+
workarounds_applied: []
|
|
86
|
+
started_at: null
|
|
87
|
+
completed_at: null
|
|
88
|
+
dependency_graph:
|
|
89
|
+
execution_order: [] # populated by step-02-strategy
|
|
90
|
+
circular_deps_detected: false
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### §4 — Write + Validate State
|
|
94
|
+
|
|
95
|
+
1. Ensure the directory `{campaignWorkspacePath}/` exists (create if missing).
|
|
96
|
+
2. Write the constructed state to `{stateFile}`. This is the initial creation — no `.bak` is needed for the first write; all subsequent steps use read-backup-modify-write.
|
|
97
|
+
3. Run `uv run {validateScript} --state-file {stateFile}`. On non-zero (invalid), **HALT** (exit 3) with the script's `errors[]` — do not proceed to brief generation with an invalid state file.
|
|
98
|
+
|
|
99
|
+
### §5 — Generate Brief
|
|
100
|
+
|
|
101
|
+
Populate `{templateFile}` with collected inputs and write to `{briefFile}`. Fill in:
|
|
102
|
+
|
|
103
|
+
- `campaign_name` — from collected input
|
|
104
|
+
- `created_at` — current ISO-8601 timestamp with timezone
|
|
105
|
+
- `targets` — array of target entries with `name`, `repo_url`, `tier`, `pin`, `depends_on`
|
|
106
|
+
- `quality_gate` — `{qualityGateHard}` / `{qualityGateSoftTarget}` / `{qualityGateSoftFallback}`
|
|
107
|
+
- `health_findings_queue` — from the §2 preference decision
|
|
108
|
+
- `architecture_doc_path` — from collected input, or empty string if not provided
|
|
109
|
+
- `notes` — operator-provided context, or empty string
|
|
110
|
+
|
|
111
|
+
The brief is a machine-readable snapshot enabling fresh-context resume (FR-35).
|
|
112
|
+
|
|
113
|
+
## OUTPUT
|
|
114
|
+
|
|
115
|
+
Confirm state file creation and brief generation. Display summary:
|
|
116
|
+
|
|
117
|
+
- Campaign name
|
|
118
|
+
- Number of targets
|
|
119
|
+
- Tier distribution (count of A vs B)
|
|
120
|
+
- Health queue setting
|
|
121
|
+
|
|
122
|
+
Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-03-pins.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
depsScript: 'scripts/campaign-deps.py'
|
|
7
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
11
|
+
|
|
12
|
+
# Strategy
|
|
13
|
+
|
|
14
|
+
## STEP GOAL:
|
|
15
|
+
|
|
16
|
+
Compute the execution order from dependency edges, detect circular dependencies, and present a human-readable strategy view to the operator so the campaign plan is visible before execution begins.
|
|
17
|
+
|
|
18
|
+
## RULES
|
|
19
|
+
|
|
20
|
+
- This step uses the **read-backup-modify-write** pattern (state file exists from step-01).
|
|
21
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
22
|
+
- Write `execution_order` and `circular_deps_detected` to `dependency_graph`.
|
|
23
|
+
- Update `campaign.current_stage` to `1`.
|
|
24
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
25
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates with the default action and log each auto-decision.
|
|
26
|
+
|
|
27
|
+
## TASKS
|
|
28
|
+
|
|
29
|
+
### §1 — Read + Validate State
|
|
30
|
+
|
|
31
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
32
|
+
|
|
33
|
+
### §2 — Backup State
|
|
34
|
+
|
|
35
|
+
Copy `{stateFile}` to `{backupFile}` before any modification.
|
|
36
|
+
|
|
37
|
+
### §3 — Read Directive
|
|
38
|
+
|
|
39
|
+
If `campaign.directive_path` is set in state, load the file at that path and apply its contents as campaign-wide context for this stage's processing, per the directive contract in `references/campaign-directive-spec.md`. If the file is not found, continue without error (directive is optional).
|
|
40
|
+
|
|
41
|
+
### §4 — Compute Execution Order
|
|
42
|
+
|
|
43
|
+
Run the deterministic topological sort — do not hand-compute it:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
uv run {depsScript} --compute --state-file {stateFile}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Parse the JSON output: `execution_order` (the ordered skill names — Kahn's sort with Tier A placed before Tier B within a dependency level), `circular_deps_detected` (bool), and `cycle_participants` (the unplaced skills when a cycle exists, else null). Exit code 1 from the script signals a cycle or a dangling dependency reference; exit code 2 signals a state/parse error — surface either and HALT.
|
|
50
|
+
|
|
51
|
+
### §5 — Handle Circular Dependencies
|
|
52
|
+
|
|
53
|
+
If `circular_deps_detected` is `true`, HALT (exit code 4, `circular-deps`) with a clear error listing `cycle_participants` and their mutual `depends_on` edges. Do NOT proceed — circular dependencies make execution order impossible.
|
|
54
|
+
|
|
55
|
+
### §6 — Write State
|
|
56
|
+
|
|
57
|
+
Set `dependency_graph.execution_order` to the computed order. Set `dependency_graph.circular_deps_detected` to the detection result. Set `campaign.current_stage` to `1`. Set `campaign.last_updated` to current ISO-8601 with timezone. Write to `{stateFile}`.
|
|
58
|
+
|
|
59
|
+
### §7 — Present Strategy View
|
|
60
|
+
|
|
61
|
+
Display a human-readable strategy summary to the operator (not written to a file — display only):
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
CAMPAIGN STRATEGY: {campaign_name}
|
|
65
|
+
|
|
66
|
+
EXECUTION ORDER:
|
|
67
|
+
1. {skill_name} [Tier {tier}] {pin or "latest"}
|
|
68
|
+
2. {skill_name} [Tier {tier}] {pin or "latest"} ← depends on: {dep1, dep2}
|
|
69
|
+
...
|
|
70
|
+
|
|
71
|
+
DEPENDENCY MAP:
|
|
72
|
+
{skill_a} → {skill_b}, {skill_c}
|
|
73
|
+
{skill_d} → (no dependencies)
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
QUALITY GATE:
|
|
77
|
+
Hard gate: {quality_gate.hard}
|
|
78
|
+
Soft target: {quality_gate.soft_target}%
|
|
79
|
+
Soft fallback: {quality_gate.soft_fallback}%
|
|
80
|
+
|
|
81
|
+
TIER DISTRIBUTION:
|
|
82
|
+
Tier A (full pipeline): {count}
|
|
83
|
+
Tier B (QS batch): {count}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### §8 — Plan Confirmation Gate
|
|
87
|
+
|
|
88
|
+
The strategy view is the last review surface before a potentially long, mostly-unattended run begins. Present a confirmation gate:
|
|
89
|
+
|
|
90
|
+
- `[P]roceed` — begin execution (chain to `{nextStepFile}`).
|
|
91
|
+
- `[C]ancel` — stop now with exit code 12 (`user-cancelled`); state is intact and resumable. To change targets, edit the campaign brief (`{campaignWorkspacePath}/campaign-brief.yaml`) or re-run `campaign` (overwrite), then start again.
|
|
92
|
+
|
|
93
|
+
**HALT and wait for operator input.** In headless mode, auto-proceed with `[P]` and log "headless: auto-proceed past plan-confirmation gate" to the decision log.
|
|
94
|
+
|
|
95
|
+
## OUTPUT
|
|
96
|
+
|
|
97
|
+
Confirm strategy computed, display the strategy view, and resolve the §8 gate. Chain to `{nextStepFile}`.
|