bmad-module-skill-forge 1.9.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 +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/module-help.csv +2 -1
- 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-derive-assembly-shape.py +107 -0
- package/src/shared/scripts/skf-detect-docs.py +8 -3
- package/src/shared/scripts/skf-detect-language.py +5 -3
- 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 +1 -1
- package/src/shared/scripts/skf-shape-detect.py +576 -25
- package/src/shared/scripts/skf-validate-brief-schema.py +2 -5
- package/src/shared/scripts/skf-validate-pins.py +2 -2
- package/src/shared/scripts/skf-write-skill-brief.py +21 -5
- package/src/skf-analyze-source/SKILL.md +1 -1
- package/src/skf-analyze-source/assets/skill-brief-schema.md +1 -1
- package/src/skf-analyze-source/references/step-auto-scope.md +196 -44
- package/src/skf-analyze-source/references/step-shape-detect.md +20 -13
- package/src/skf-audit-skill/references/init.md +1 -1
- 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 +8 -2
- package/src/skf-brief-skill/references/scope-definition.md +2 -1
- package/src/skf-brief-skill/references/step-auto-brief.md +21 -4
- package/src/skf-brief-skill/references/step-auto-validate.md +2 -2
- 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 +1 -1
- package/src/skf-create-skill/assets/compile-assembly-rules.md +22 -0
- package/src/skf-create-skill/references/compile.md +4 -1
- 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-doc-rot.md +4 -4
- package/src/skf-create-skill/references/step-doc-sources.md +11 -2
- 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 +12 -7
- 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/references/coverage-check.md +10 -0
- package/src/skf-test-skill/references/init.md +1 -1
- package/src/skf-test-skill/references/source-access-protocol.md +13 -3
- package/src/skf-test-skill/scripts/compute-score.py +4 -3
- 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
- package/docs/deepwiki.md +0 -89
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-06-batch.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
briefFile: '{campaignWorkspacePath}/campaign-brief.yaml'
|
|
7
|
+
depsScript: 'scripts/campaign-deps.py'
|
|
8
|
+
kickoffTemplate: '{kickoffTemplatePath}'
|
|
9
|
+
kickoffScript: 'scripts/campaign-render-kickoff.py'
|
|
10
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
14
|
+
|
|
15
|
+
# Skill Loop
|
|
16
|
+
|
|
17
|
+
## STEP GOAL:
|
|
18
|
+
|
|
19
|
+
Iterate skills in `dependency_graph.execution_order`, processing each Tier A skill through the full pipeline while enforcing dependency gates. Write state after each skill completes to survive context death between skills.
|
|
20
|
+
|
|
21
|
+
## RULES
|
|
22
|
+
|
|
23
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
24
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
25
|
+
- Update `campaign.current_stage` to `4`.
|
|
26
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
27
|
+
- Write state after EACH skill completes (not just at end) — context death between skills must be survivable.
|
|
28
|
+
- The per-skill pipeline body (§5.2) runs inline, not in a delegated subagent: AN→BS→CS→TS are nested skill activations, and a subagent cannot spawn further subagents. This is a deliberate constraint, not an oversight — inline keeps the full pipeline reachable and preserves NFR-2 (every skill's state is written before the next begins).
|
|
29
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. Dependency gate blocks default to HALT (safest — never silently skip dependencies).
|
|
30
|
+
|
|
31
|
+
## TASKS
|
|
32
|
+
|
|
33
|
+
### §1 — Read + Validate State
|
|
34
|
+
|
|
35
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
36
|
+
|
|
37
|
+
### §2 — Read Brief
|
|
38
|
+
|
|
39
|
+
Load `{briefFile}`. Build a lookup map from `targets[].name` to `targets[].repo_url`. HALT (exit code 8, `missing-brief`) if the brief is missing or unreadable.
|
|
40
|
+
|
|
41
|
+
### §3 — Read Directive
|
|
42
|
+
|
|
43
|
+
If `campaign.directive_path` is set in state, load the file at that path and apply its contents as campaign-wide context for all skill processing, per the directive contract in `references/campaign-directive-spec.md`. If the file is not found, continue without error (directive is optional).
|
|
44
|
+
|
|
45
|
+
### §4 — Dependency Gate Check
|
|
46
|
+
|
|
47
|
+
For each skill in `dependency_graph.execution_order`, before processing:
|
|
48
|
+
|
|
49
|
+
1. Skip Tier B skills — they are processed in step-06 via batch mode.
|
|
50
|
+
2. Skip skills whose status is already `"completed"`, `"failed"`, or `"skipped"` (resume support).
|
|
51
|
+
3. Run `uv run {depsScript} --check --state-file {stateFile} --skill {skill_name}`.
|
|
52
|
+
4. If `ready: true` — proceed to §5 for this skill.
|
|
53
|
+
5. If `ready: false` — present the blocked skill and its unmet dependencies:
|
|
54
|
+
- `[S]kip` — mark skill as `"skipped"`, backup and write state, continue to next skill.
|
|
55
|
+
- `[F]orce` — re-run with `--force`, proceed to §5 despite unmet deps.
|
|
56
|
+
- `[H]alt` — stop the campaign loop. (Default in headless mode.)
|
|
57
|
+
6. **Deadlock detection:** after iterating through all remaining skills and finding none ready, present the same recovery menu as §4.5, scoped to the mutually-blocked set (this is the strictly harder situation, so it must not get worse UX than a single blocked skill):
|
|
58
|
+
- List the blocked skills and their unmet dependencies.
|
|
59
|
+
- `[F]orce one` — choose a skill to re-run with `--force` and resume the loop from it.
|
|
60
|
+
- `[S]kip one` — choose a skill to mark `"skipped"`, backup and write state, then re-evaluate readiness.
|
|
61
|
+
- `[H]alt` — stop the campaign loop with exit code 7 (`dependency-deadlock`). **Default in headless mode** (never silently force or skip a dependency). Log the chosen action to the decision log.
|
|
62
|
+
|
|
63
|
+
### §5 — Per-Skill Processing
|
|
64
|
+
|
|
65
|
+
For each ready Tier A skill:
|
|
66
|
+
|
|
67
|
+
1. **Activate** — set `status` to `"active"`, set `started_at` to current ISO-8601 with timezone. Backup and write state.
|
|
68
|
+
2. **Execute pipeline:**
|
|
69
|
+
- **Pre-apply** — apply known workarounds before generation by running the shared pre-apply helper against the skill's working directory:
|
|
70
|
+
```
|
|
71
|
+
uv run {project-root}/_bmad/skf/shared/scripts/skf-preapply.py --target-dir <skill-working-dir> --log-dir {campaignWorkspacePath}
|
|
72
|
+
```
|
|
73
|
+
(During development the helper lives at `src/shared/scripts/skf-preapply.py`.) Parse `applied[]` from the JSON output and capture the list of applied workarounds. Pre-apply is best-effort: if the helper is missing or exits non-zero, log a warning and proceed — it is not a gate.
|
|
74
|
+
- **Kickoff emit** — render the mechanical placeholders deterministically, then fill the three judgment slots. Run:
|
|
75
|
+
```
|
|
76
|
+
uv run {kickoffScript} --state-file {stateFile} --brief-file {briefFile} --skill {skill_name} --template {kickoffTemplate} --workarounds '<JSON list of applied workarounds from pre-apply>'
|
|
77
|
+
```
|
|
78
|
+
The script fills `{{campaign_name}}`, `{{current_stage}}`, `{{quality_gate_summary}}`, `{{skill_name}}`, `{{skill_tier}}`, `{{pin}}`, `{{commit_sha}}`, `{{repo_url}}`, `{{workarounds_list}}`, and `{{dependency_status_table}}` from state + brief. Then fill the three judgment slots that remain in the rendered output:
|
|
79
|
+
- `{{brief_summary}}` — a concise summary of this target's brief entry (name, repo_url, tier, pin, depends_on). The per-skill brief does NOT exist yet at kickoff — BS produces it during this pipeline run (see below), so do not read `brief_path`; summarize the campaign brief's target entry instead.
|
|
80
|
+
- `{{persistent_facts}}` — the campaign-wide persistent facts resolved in On Activation (literal sentences and loaded `file:` contents), as a bullet list, or "None" if empty. This is how house style/guardrails reach every skill's pipeline.
|
|
81
|
+
- `{{directive_content}}` — raw content of the file at `campaign.directive_path`, or "No directive configured" if unset/missing.
|
|
82
|
+
Present the completed kickoff message as the context for the skill's pipeline run.
|
|
83
|
+
- **AN → BS → CS → TS** — standard forge pipeline for this skill. When BS (Brief Synthesis) produces the skill's brief, set `skills[current].brief_path` to the brief path from the BS result envelope so the field the schema declares is populated and available for resume and reporting.
|
|
84
|
+
- **Doc-rot check** — grep feeder artifacts for corrections emitted during the pipeline run. Append any doc-rot findings to the skill's `workarounds_applied` array (prefixed with `[doc-rot]`) so they survive state write and are available for §6 propagation.
|
|
85
|
+
3. **Record results:**
|
|
86
|
+
- On success: set `status` to `"completed"`, set `completed_at` to current ISO-8601 with timezone, record `quality_score`. Backup and write state.
|
|
87
|
+
- On failure: set `status` to `"failed"`. Log the failure reason (the sub-skill's `halt_reason`/exit code, or "unparseable result envelope") to the decision log so `campaign status` and the report surface *why* a skill failed without the operator opening sub-skill logs. Backup and write state. Downstream skills whose `depends_on` does NOT include the failed skill continue processing normally; those that DO depend on it are blocked at §4's dependency gate.
|
|
88
|
+
|
|
89
|
+
### §6 — Propagate Findings
|
|
90
|
+
|
|
91
|
+
After each completed skill, propagate quality findings and doc-rot corrections to campaign-level tracking (`workarounds_applied`, `quality_score`).
|
|
92
|
+
|
|
93
|
+
### §7 — Loop Completion
|
|
94
|
+
|
|
95
|
+
When all Tier A skills in `execution_order` are processed (completed, failed, or skipped):
|
|
96
|
+
|
|
97
|
+
1. Set `campaign.current_stage` to `4`.
|
|
98
|
+
2. Set `campaign.last_updated` to current ISO-8601 with timezone.
|
|
99
|
+
3. Backup and write state.
|
|
100
|
+
|
|
101
|
+
## OUTPUT
|
|
102
|
+
|
|
103
|
+
Display per-skill summary: name, status, quality_score (if completed). Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-07-capstone.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
briefFile: '{campaignWorkspacePath}/campaign-brief.yaml'
|
|
7
|
+
batchFile: '{campaignWorkspacePath}/_batch-input.txt'
|
|
8
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
12
|
+
|
|
13
|
+
# Tier B Batch
|
|
14
|
+
|
|
15
|
+
## STEP GOAL:
|
|
16
|
+
|
|
17
|
+
Batch all Tier B skills through QS `--batch` mode, recording per-skill results in campaign state. Tier B skills use a faster, simpler path than the full Tier A pipeline — QS handles each target end-to-end in a single invocation.
|
|
18
|
+
|
|
19
|
+
## RULES
|
|
20
|
+
|
|
21
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
22
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
23
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
24
|
+
- Update `campaign.current_stage` to `5`.
|
|
25
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. QS `--batch` implies headless.
|
|
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 — Read Directive
|
|
34
|
+
|
|
35
|
+
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).
|
|
36
|
+
|
|
37
|
+
### §3 — Identify Tier B Skills
|
|
38
|
+
|
|
39
|
+
Filter `skills[]` for entries where `tier == "B"` and `status == "pending"`. Skip skills with status `"completed"`, `"failed"`, or `"skipped"` (resume support — a previous run may have partially completed the batch).
|
|
40
|
+
|
|
41
|
+
If no Tier B skills need processing, skip to §7 (Stage Completion) — the batch stage completes immediately when all Tier B skills are already handled.
|
|
42
|
+
|
|
43
|
+
### §4 — Generate Batch File
|
|
44
|
+
|
|
45
|
+
Load `{briefFile}` to look up `repo_url` for each Tier B skill (repo URLs are in the brief's `targets[]`, not in the state schema). HALT (exit code 8, `missing-brief`) if the brief is missing or unreadable.
|
|
46
|
+
|
|
47
|
+
Write a batch input file listing Tier B skills for QS `--batch` consumption. For each pending Tier B skill, include:
|
|
48
|
+
|
|
49
|
+
- Skill name (from `skills[].name`)
|
|
50
|
+
- Repository URL (from brief's `targets[].repo_url`, matched by name)
|
|
51
|
+
- Pin (from `skills[].pin`, or omit if null for latest)
|
|
52
|
+
|
|
53
|
+
Place the batch file at `{batchFile}`.
|
|
54
|
+
|
|
55
|
+
### §5 — Execute QS Batch
|
|
56
|
+
|
|
57
|
+
Set each pending Tier B skill to `status: "active"` and `started_at` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state.
|
|
58
|
+
|
|
59
|
+
Invoke QS in `--batch` mode with the generated batch file:
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
skf-quick-skill --batch {batchFile}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
QS `--batch` implies `--headless`. Capture per-skill results from the QS batch output — each target reports success/failure, skill path, and quality score.
|
|
66
|
+
|
|
67
|
+
### §6 — Record Results
|
|
68
|
+
|
|
69
|
+
For each Tier B skill in the batch:
|
|
70
|
+
|
|
71
|
+
1. If QS reports success:
|
|
72
|
+
- Set `status` to `"completed"`
|
|
73
|
+
- Set `completed_at` to current ISO-8601 with timezone
|
|
74
|
+
- Record `quality_score` from QS output
|
|
75
|
+
- Record `skill_path` from QS output
|
|
76
|
+
2. If QS reports failure:
|
|
77
|
+
- Set `status` to `"failed"`
|
|
78
|
+
|
|
79
|
+
After all updates: backup `{stateFile}` to `{backupFile}`, then write the updated state.
|
|
80
|
+
|
|
81
|
+
### §7 — Stage Completion
|
|
82
|
+
|
|
83
|
+
Set `campaign.current_stage` to `5`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state.
|
|
84
|
+
|
|
85
|
+
## OUTPUT
|
|
86
|
+
|
|
87
|
+
Display per-skill batch summary: name, status, quality_score (if completed). Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-08-verify.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
10
|
+
|
|
11
|
+
# Capstone
|
|
12
|
+
|
|
13
|
+
## STEP GOAL:
|
|
14
|
+
|
|
15
|
+
Compose a capstone stack skill from all completed individual skills using SS compose-mode. The capstone represents the final integrated view of all campaign skills — a single stack skill that documents how the constituent libraries connect.
|
|
16
|
+
|
|
17
|
+
## RULES
|
|
18
|
+
|
|
19
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
20
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
21
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
22
|
+
- Update `campaign.current_stage` to `6`.
|
|
23
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. SS compose-mode supports headless.
|
|
24
|
+
|
|
25
|
+
## TASKS
|
|
26
|
+
|
|
27
|
+
### §1 — Read + Validate State
|
|
28
|
+
|
|
29
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
30
|
+
|
|
31
|
+
### §2 — Collect Completed Skills
|
|
32
|
+
|
|
33
|
+
Gather all skills from `skills[]` with `status == "completed"` — this includes both Tier A skills (processed in step-05) and Tier B skills (processed in step-06). Extract their `skill_path` values.
|
|
34
|
+
|
|
35
|
+
If no completed skills exist, do NOT HALT — a campaign where everything failed is exactly when the operator most needs the downstream diagnostic report. Set `campaign.capstone` to `null`, warn ("No completed skills — skipping capstone composition; verification and the campaign report will still run so failures are explained"), log the skip to the decision log, and skip directly to §5 (Stage Completion) so the chain continues to verify → … → the report. step-10 (export) and step-11 (report) already handle the zero-completed case.
|
|
36
|
+
|
|
37
|
+
### §3 — Invoke SS Compose-Mode
|
|
38
|
+
|
|
39
|
+
Invoke `skf-create-stack-skill` in compose-mode with:
|
|
40
|
+
|
|
41
|
+
- The collected `skill_path` values as input skills
|
|
42
|
+
- `campaign.name` as the stack identifier
|
|
43
|
+
|
|
44
|
+
Capture the result: stack skill path and quality score from the SS result output (`SKF_STACK_RESULT_JSON`).
|
|
45
|
+
|
|
46
|
+
### §4 — Record Capstone Results
|
|
47
|
+
|
|
48
|
+
Persist the capstone outcome to `campaign.capstone` in the state (campaign-level summary; the composed skill itself lives at `skill_path`):
|
|
49
|
+
|
|
50
|
+
- `campaign.capstone.skill_path` — stack skill path (from SS result)
|
|
51
|
+
- `campaign.capstone.quality_score` — quality score (from SS result)
|
|
52
|
+
- `campaign.capstone.verified` — `null` for now; set by the verify stage (step-08) once the stack is checked
|
|
53
|
+
- `campaign.capstone.completed_at` — current ISO-8601 with timezone
|
|
54
|
+
|
|
55
|
+
The capstone is a derived artifact — it is **not** tracked as a skill entry in the `skills[]` array. Its campaign-level summary lives in `campaign.capstone`; the constituent skill list and any verbose detail are reported in the step output and are available to downstream steps (verify, refine).
|
|
56
|
+
|
|
57
|
+
### §5 — Stage Completion
|
|
58
|
+
|
|
59
|
+
Set `campaign.current_stage` to `6`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state (including `campaign.capstone` from §4).
|
|
60
|
+
|
|
61
|
+
## OUTPUT
|
|
62
|
+
|
|
63
|
+
Display capstone summary: stack skill name, path, quality score, and the list of constituent skills. Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-09-refine.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
10
|
+
|
|
11
|
+
# Verify
|
|
12
|
+
|
|
13
|
+
## STEP GOAL:
|
|
14
|
+
|
|
15
|
+
Invoke VS (skf-verify-stack) in headless mode against all completed campaign skills to produce a feasibility report. The report cross-references generated skills against the project's architecture document, providing coverage analysis and integration verdicts for operator review.
|
|
16
|
+
|
|
17
|
+
## RULES
|
|
18
|
+
|
|
19
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
20
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
21
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
22
|
+
- Update `campaign.current_stage` to `7`.
|
|
23
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. VS supports headless via `--headless`.
|
|
24
|
+
|
|
25
|
+
## TASKS
|
|
26
|
+
|
|
27
|
+
### §1 — Read + Validate State
|
|
28
|
+
|
|
29
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
30
|
+
|
|
31
|
+
### §2 — Read Directive
|
|
32
|
+
|
|
33
|
+
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).
|
|
34
|
+
|
|
35
|
+
### §3 — Locate Architecture Doc
|
|
36
|
+
|
|
37
|
+
Resolve the architecture document path, preferring the value persisted in state:
|
|
38
|
+
|
|
39
|
+
1. If `campaign.architecture_doc_path` is set in state and the file exists, use it directly.
|
|
40
|
+
2. Otherwise discover it: check `docs/architecture.md` at `{project-root}` (SKF convention), then `_bmad-output/planning-artifacts/architecture.md` (BMM convention).
|
|
41
|
+
3. If still not found and `{headless_mode}` is false: prompt the operator to provide the architecture doc path.
|
|
42
|
+
4. If still not found and `{headless_mode}` is true: skip VS invocation with a warning — do not HALT. Log that verification was skipped due to missing architecture doc (to the decision log) and proceed to §6.
|
|
43
|
+
|
|
44
|
+
Once resolved (steps 2–3), persist the path to `campaign.architecture_doc_path` so the refine stage and any resume reuse it without re-prompting. Then proceed to §4 with the resolved path.
|
|
45
|
+
|
|
46
|
+
### §4 — Invoke VS
|
|
47
|
+
|
|
48
|
+
Invoke `skf-verify-stack` with `--headless --architecture-doc <path>`, where `<path>` is the architecture doc discovered in §3.
|
|
49
|
+
|
|
50
|
+
VS discovers skills from its own configured `{skills_output_folder}` — the campaign does NOT pass individual skill paths. Capture the result envelope from stdout:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
SKF_VERIFY_STACK_RESULT_JSON: {"status":"…","report_path":"…","report_latest_path":"…","overall_verdict":"…","coverage_percentage":0,"recommendation_count":0,"exit_code":0,"halt_reason":null}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### §5 — Handle VS Outcome
|
|
57
|
+
|
|
58
|
+
**On success** (exit code 0): persist the summary to `campaign.verification` (detailed findings stay in the external report):
|
|
59
|
+
|
|
60
|
+
- `campaign.verification.report_path` — `report_latest_path` from the envelope
|
|
61
|
+
- `campaign.verification.overall_verdict` — one of `Verified`, `Plausible`, `Risky`, `Blocked`
|
|
62
|
+
- `campaign.verification.coverage_percentage` — from the envelope
|
|
63
|
+
- `campaign.verification.recommendation_count` — from the envelope
|
|
64
|
+
|
|
65
|
+
Also set `campaign.capstone.verified` to `true` when `overall_verdict == "Verified"`, otherwise `false` (only if a `campaign.capstone` entry exists from step-07).
|
|
66
|
+
|
|
67
|
+
**On VS failure** (non-zero exit): log the error (exit code and halt_reason from the envelope or stderr). Verification failure does NOT block the campaign — it produces diagnostic information for operator review. Leave `campaign.verification` unset (or null). Continue to §6 regardless of outcome.
|
|
68
|
+
|
|
69
|
+
### §6 — Stage Completion
|
|
70
|
+
|
|
71
|
+
Set `campaign.current_stage` to `7`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state (including `campaign.architecture_doc_path` from §3 and `campaign.verification` from §5).
|
|
72
|
+
|
|
73
|
+
## OUTPUT
|
|
74
|
+
|
|
75
|
+
Display verification summary: overall verdict (or "skipped" if architecture doc was not found), report path (if produced), and coverage percentage. Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-10-export.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
10
|
+
|
|
11
|
+
# Refine
|
|
12
|
+
|
|
13
|
+
## STEP GOAL:
|
|
14
|
+
|
|
15
|
+
Invoke RA (skf-refine-architecture) in headless mode with the project's architecture document and VS feasibility report to produce a refined architecture. RA identifies gaps, issues, and improvements based on the generated skills and applies them to the architecture document.
|
|
16
|
+
|
|
17
|
+
## RULES
|
|
18
|
+
|
|
19
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
20
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
21
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
22
|
+
- Update `campaign.current_stage` to `8`.
|
|
23
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. RA supports headless via `--headless`.
|
|
24
|
+
|
|
25
|
+
## TASKS
|
|
26
|
+
|
|
27
|
+
### §1 — Read + Validate State
|
|
28
|
+
|
|
29
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
30
|
+
|
|
31
|
+
### §2 — Read Directive
|
|
32
|
+
|
|
33
|
+
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).
|
|
34
|
+
|
|
35
|
+
### §3 — Locate Inputs
|
|
36
|
+
|
|
37
|
+
**Architecture doc:** Use the same resolution strategy as step-08:
|
|
38
|
+
|
|
39
|
+
1. If `campaign.architecture_doc_path` is set in state and the file exists, use it directly (step-08 normally persists it).
|
|
40
|
+
2. Otherwise check `docs/architecture.md` at `{project-root}`, then `_bmad-output/planning-artifacts/architecture.md`.
|
|
41
|
+
3. If still not found and `{headless_mode}` is false: prompt the operator.
|
|
42
|
+
4. If still not found and `{headless_mode}` is true: skip RA invocation with a warning — do not HALT. Log that refinement was skipped due to missing architecture doc (to the decision log) and proceed to §6.
|
|
43
|
+
|
|
44
|
+
Once resolved (steps 2–3), persist the path to `campaign.architecture_doc_path` if not already set, then proceed to §4 with the resolved path.
|
|
45
|
+
|
|
46
|
+
**VS feasibility report:** If chaining from step-08, the report path is available from the VS result envelope (`report_latest_path`). On resume, look for `feasibility-report-*-latest.md` in `{forge_data_folder}/`. If no report exists (VS may have failed or been skipped in step-08), proceed without it — RA's VS report input is optional.
|
|
47
|
+
|
|
48
|
+
### §4 — Invoke RA
|
|
49
|
+
|
|
50
|
+
Invoke `skf-refine-architecture` with:
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
skf-refine-architecture --headless --architecture-doc <arch_path> [--vs-report-path <report_path>] [--scope-skills <names>]
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
- `--architecture-doc`: the architecture doc discovered in §3 (required).
|
|
57
|
+
- `--vs-report-path`: the VS feasibility report path from §3 (omit if not found).
|
|
58
|
+
- `--scope-skills`: comma-separated names of completed campaign skills (from `skills[]` where `status == "completed"`). Optional but improves focus by limiting refinement scope to campaign-relevant skills.
|
|
59
|
+
|
|
60
|
+
Capture the result envelope from stdout:
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
SKF_REFINE_ARCHITECTURE_RESULT_JSON: {"status":"…","refined_path":"…","gap_count":0,"issue_count":0,"improvement_count":0,"exit_code":0,"halt_reason":null}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### §5 — Handle RA Outcome
|
|
67
|
+
|
|
68
|
+
**On success** (exit code 0): persist the summary to `campaign.refinement` (the refined document itself lives at `refined_path`):
|
|
69
|
+
|
|
70
|
+
- `campaign.refinement.refined_path` — from the envelope
|
|
71
|
+
- `campaign.refinement.gap_count` — from the envelope
|
|
72
|
+
- `campaign.refinement.issue_count` — from the envelope
|
|
73
|
+
- `campaign.refinement.improvement_count` — from the envelope
|
|
74
|
+
|
|
75
|
+
**On RA failure** (non-zero exit): log the error (exit code and halt_reason from the envelope or stderr). Refinement failure does NOT block the campaign — the campaign continues to export with whatever state exists. Leave `campaign.refinement` unset (or null). Continue to §6 regardless of outcome.
|
|
76
|
+
|
|
77
|
+
### §6 — Stage Completion
|
|
78
|
+
|
|
79
|
+
Set `campaign.current_stage` to `8`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state (including `campaign.refinement` from §5).
|
|
80
|
+
|
|
81
|
+
## OUTPUT
|
|
82
|
+
|
|
83
|
+
Display refinement summary: refined architecture path (or "skipped" if architecture doc was not found), gap count, issue count, and improvement count. Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'step-11-maintenance.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
10
|
+
|
|
11
|
+
# Export
|
|
12
|
+
|
|
13
|
+
## STEP GOAL:
|
|
14
|
+
|
|
15
|
+
Present all completed skills for operator review and gate the export behind explicit confirmation. This is the only campaign step that requires manual approval before proceeding — no files are written until the operator confirms.
|
|
16
|
+
|
|
17
|
+
## RULES
|
|
18
|
+
|
|
19
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
20
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
21
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
22
|
+
- Update `campaign.current_stage` to `9`.
|
|
23
|
+
- If `{headless_mode}` is true, auto-proceed past the write-gate with `[E]` and log: "headless: auto-proceed past export write-gate".
|
|
24
|
+
|
|
25
|
+
## TASKS
|
|
26
|
+
|
|
27
|
+
### §1 — Read + Validate State
|
|
28
|
+
|
|
29
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
30
|
+
|
|
31
|
+
### §2 — Read Directive
|
|
32
|
+
|
|
33
|
+
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).
|
|
34
|
+
|
|
35
|
+
### §3 — Collect Export Candidates
|
|
36
|
+
|
|
37
|
+
Gather all skills from `skills[]` with `status == "completed"`. These are the export candidates.
|
|
38
|
+
|
|
39
|
+
If no completed skills exist, display a warning and proceed directly to §6 (stage completion) — there is nothing to export.
|
|
40
|
+
|
|
41
|
+
Present a summary table of export candidates:
|
|
42
|
+
|
|
43
|
+
| # | Name | Tier | Quality Score | Skill Path |
|
|
44
|
+
|---|------|------|---------------|------------|
|
|
45
|
+
| 1 | {name} | {tier} | {quality_score} | {skill_path} |
|
|
46
|
+
| ... | ... | ... | ... | ... |
|
|
47
|
+
|
|
48
|
+
Display: "**{N} skill(s) ready for export.**"
|
|
49
|
+
|
|
50
|
+
### §4 — Write-Gate HALT
|
|
51
|
+
|
|
52
|
+
Present the export confirmation gate:
|
|
53
|
+
|
|
54
|
+
"**Export Gate — Confirm before writing files**
|
|
55
|
+
|
|
56
|
+
{N} completed skill(s) will be exported via `skf-export-skill`:
|
|
57
|
+
|
|
58
|
+
{summary table from §3}
|
|
59
|
+
|
|
60
|
+
- **[E]xport all** — invoke `skf-export-skill` for each completed skill
|
|
61
|
+
- **[C]ancel** — halt the campaign gracefully (no files written, resume later)
|
|
62
|
+
|
|
63
|
+
Choose [E] or [C]:"
|
|
64
|
+
|
|
65
|
+
**HALT and wait for operator input.**
|
|
66
|
+
|
|
67
|
+
**Headless mode:** auto-proceed with `[E]` and log: "headless: auto-proceed past export write-gate".
|
|
68
|
+
|
|
69
|
+
#### On `[C]ancel`:
|
|
70
|
+
|
|
71
|
+
Display: "Export cancelled by operator. Campaign halted gracefully — no files written. Resume later to retry export."
|
|
72
|
+
|
|
73
|
+
Log the cancellation to the decision log, then HALT with exit code 11 (`export-cancelled`). Do NOT mark the campaign as failed — this is a graceful, resumable halt; the operator may resume later.
|
|
74
|
+
|
|
75
|
+
#### On `[E]xport`:
|
|
76
|
+
|
|
77
|
+
Log the export decision to the decision log, then proceed to §5.
|
|
78
|
+
|
|
79
|
+
### §5 — Invoke EX
|
|
80
|
+
|
|
81
|
+
For each completed skill (from §3), invoke `skf-export-skill` in headless mode:
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
skf-export-skill {skill_name} --headless
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Capture the result envelope `SKF_EXPORT_RESULT_JSON` per skill.
|
|
88
|
+
|
|
89
|
+
**On per-skill EX success** (exit code 0): log the result and continue.
|
|
90
|
+
|
|
91
|
+
**On per-skill EX failure** (non-zero exit): log the error (exit code, envelope if available, or stderr). Continue with remaining skills — per-skill failure does not block remaining exports.
|
|
92
|
+
|
|
93
|
+
After all exports complete, display a summary:
|
|
94
|
+
|
|
95
|
+
"**Export Results:**
|
|
96
|
+
- Exported: {success_count} skill(s)
|
|
97
|
+
- Failed: {fail_count} skill(s)
|
|
98
|
+
{list of failed skills if any}"
|
|
99
|
+
|
|
100
|
+
### §6 — Stage Completion
|
|
101
|
+
|
|
102
|
+
Set `campaign.current_stage` to `9`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state.
|
|
103
|
+
|
|
104
|
+
## OUTPUT
|
|
105
|
+
|
|
106
|
+
Display export summary: skills exported count, failures count (if any), and per-skill results. Chain to `{nextStepFile}`.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
nextStepFile: 'health-check.md'
|
|
3
|
+
stateSchemaFile: 'assets/campaign-state-schema.json'
|
|
4
|
+
stateFile: '{campaignWorkspacePath}/_campaign-state.yaml'
|
|
5
|
+
backupFile: '{campaignWorkspacePath}/_campaign-state.yaml.bak'
|
|
6
|
+
reportFile: '{campaignWorkspacePath}/campaign-report.md'
|
|
7
|
+
reportScript: 'scripts/campaign-report.py'
|
|
8
|
+
reportTemplate: '{reportTemplatePath}'
|
|
9
|
+
validateScript: 'scripts/campaign-validate-state.py'
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
<!-- Config: communicate in {communication_language}. -->
|
|
13
|
+
|
|
14
|
+
# Maintenance
|
|
15
|
+
|
|
16
|
+
## STEP GOAL:
|
|
17
|
+
|
|
18
|
+
Generate a comprehensive campaign report from the accumulated state, emit the headless result envelope, and chain to the shared health check as the campaign's terminal step.
|
|
19
|
+
|
|
20
|
+
## RULES
|
|
21
|
+
|
|
22
|
+
- This step uses the **read-backup-modify-write** pattern.
|
|
23
|
+
- Validate state on load via `uv run {validateScript} --state-file {stateFile}`; HALT (exit 3) on non-zero.
|
|
24
|
+
- Update `campaign.last_updated` to current ISO-8601 with timezone on every write.
|
|
25
|
+
- Update `campaign.current_stage` to `10`.
|
|
26
|
+
- If `{headless_mode}` is true, auto-proceed through confirmation gates. Emit the headless envelope on stdout.
|
|
27
|
+
|
|
28
|
+
## TASKS
|
|
29
|
+
|
|
30
|
+
### §1 — Read + Validate State
|
|
31
|
+
|
|
32
|
+
Load `{stateFile}`. Run `uv run {validateScript} --state-file {stateFile}`; on non-zero, HALT (exit 3) with the script's `errors[]`.
|
|
33
|
+
|
|
34
|
+
### §2 — Generate Campaign Report
|
|
35
|
+
|
|
36
|
+
Invoke the campaign report script:
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
uv run {reportScript} \
|
|
40
|
+
--state-file {stateFile} \
|
|
41
|
+
--template-file {reportTemplate} \
|
|
42
|
+
--output-file {reportFile}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Capture the JSON result from stdout — it carries `skills_completed`, `skills_failed`, `quality_scores`, and `duration` already computed. Do not recompute these by hand in §3.
|
|
46
|
+
|
|
47
|
+
**On success** (exit code 0): log the report path and summary stats from the result JSON.
|
|
48
|
+
|
|
49
|
+
**On failure** (exit code 2): the campaign itself has already completed — do NOT discard it over a missing summary artifact. Display the error from stderr, log "report generation failed (degraded): {error}" to the decision log, set the envelope's `campaign_report_path` to `null`, and CONTINUE to §3. Surface `report-failure` only as a degraded signal in the envelope (`status:"error"`, `exit_code:10`), never as a hard halt that throws away a finished campaign.
|
|
50
|
+
|
|
51
|
+
Display: "**Campaign report generated:** `{reportFile}`" (or, on degrade, "**Campaign complete — report generation failed (see decision log); state is intact.**")
|
|
52
|
+
|
|
53
|
+
**Optional post-completion hook:** if `{onComplete}` (resolved in On Activation) is non-empty, invoke `{onComplete} --report-path={reportFile}`. Log the outcome to the decision log; a hook failure is recorded but never fails the campaign.
|
|
54
|
+
|
|
55
|
+
### §3 — Emit Headless Envelope
|
|
56
|
+
|
|
57
|
+
When `{headless_mode}` is true, emit the campaign result envelope on stdout, copying the counts, `quality_scores`, and `duration` straight from the §2 report-script result (do not recompute):
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
SKF_CAMPAIGN_RESULT_JSON: {"status":"success","skills_completed":N,"skills_failed":N,"quality_scores":{...},"campaign_report_path":"{reportFile}","decision_log":"{campaignWorkspacePath}/_campaign-decision-log.md","duration":"..."}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- `status`: "success" if the campaign completed normally (HARD HALTs emit the error variant per SKILL.md "Result Contract on HARD HALT")
|
|
64
|
+
- `skills_completed` / `skills_failed` / `quality_scores` / `duration`: from the §2 report-script result JSON
|
|
65
|
+
- `campaign_report_path`: `{reportFile}`
|
|
66
|
+
- `decision_log`: path to the append-only decision log
|
|
67
|
+
|
|
68
|
+
When not in headless mode, skip this section silently.
|
|
69
|
+
|
|
70
|
+
### §4 — Stage Completion
|
|
71
|
+
|
|
72
|
+
Set `campaign.current_stage` to `10`. Update `campaign.last_updated` to current ISO-8601 with timezone. Backup `{stateFile}` to `{backupFile}`, then write the updated state.
|
|
73
|
+
|
|
74
|
+
### §5 — Chain to Health Check
|
|
75
|
+
|
|
76
|
+
The operator's findings-routing consent (`campaign.health_findings_queue`) is applied by the terminal health-check step: `references/health-check.md` §1 reads it from state and carries it into the shared health check as the pre-decided opt-in (`"improvement"` → route non-bug findings to the shared improvement queue without re-prompting; `"local"` → local queue only). That is what makes the §2 setup consent prompt actionable rather than cosmetic — surface the active setting here for visibility.
|
|
77
|
+
|
|
78
|
+
Display: "**Campaign complete.** Report at `{reportFile}`. Findings routing: {campaign.health_findings_queue}. Chaining to health check..."
|
|
79
|
+
|
|
80
|
+
Chain to `{nextStepFile}` (shared/health-check.md).
|
|
81
|
+
|
|
82
|
+
## OUTPUT
|
|
83
|
+
|
|
84
|
+
Display campaign completion summary: skills completed, skills failed, report path, total duration. Chain to `{nextStepFile}`.
|