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
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
| Field | Type | Constraint | Description |
|
|
20
20
|
|--------------------|--------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
21
21
|
| source_type | string | `source` or `docs-only` | Default `source`. When `docs-only`: `source_repo` optional, `doc_urls` required |
|
|
22
|
-
| doc_urls | array | `{url, label}` objects
|
|
22
|
+
| doc_urls | array | `{url, label, source?}` objects | Documentation URLs for T3 content. Required when `source_type: "docs-only"`. Optional `source` provenance enum: `language-registry` (registry-guaranteed corpus) \| `readme-detection` \| `homepage` \| `pages-api` \| `docs-folder` |
|
|
23
23
|
| `scripts_intent` | string | `detect` / `none` / free-text | Describes whether scripts should be extracted. Values: `detect` (auto-detect from source — default when absent), `none` (skip scripts), or a free-text description of expected scripts (e.g., "CLI validation tools in bin/"). |
|
|
24
24
|
| `assets_intent` | string | `detect` / `none` / free-text | Describes whether assets should be extracted. Values: `detect` (auto-detect from source — default when absent), `none` (skip assets), or a free-text description of expected assets (e.g., "JSON schemas in schemas/"). |
|
|
25
25
|
| `target_version` | string | Semantic version (`X.Y.Z` or `X.Y.Z-prerelease`) | User-specified target version. When present, overrides auto-detection and becomes the skill's version. Recommended for docs-only skills where auto-detection is unavailable. |
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# DO NOT EDIT -- overwritten on every update.
|
|
2
2
|
#
|
|
3
3
|
# Workflow customization surface for skf-brief-skill.
|
|
4
|
+
# Team overrides: _bmad/custom/skf-brief-skill.toml (under {project-root})
|
|
5
|
+
# Personal overrides: _bmad/custom/skf-brief-skill.user.toml (under {project-root})
|
|
4
6
|
|
|
5
7
|
[workflow]
|
|
6
8
|
|
|
@@ -42,3 +44,15 @@ persistent_facts = [
|
|
|
42
44
|
description_voice_examples_path = ""
|
|
43
45
|
scope_templates_path = ""
|
|
44
46
|
brief_schema_path = ""
|
|
47
|
+
|
|
48
|
+
# Pipeline-integration hook invoked once the brief is written and the result
|
|
49
|
+
# contract is finalized (write-brief.md, step 5), before the workflow chains to
|
|
50
|
+
# the terminal health-check step. The command is called as:
|
|
51
|
+
# <on_complete> --result-path=<absolute_path_to_skill-brief.yaml>
|
|
52
|
+
# Useful for chaining into create-skill, Slack notifications, dashboard ingest,
|
|
53
|
+
# or CI hooks. Override wins. Failures are logged to workflow_warnings[] but
|
|
54
|
+
# never fail the workflow.
|
|
55
|
+
#
|
|
56
|
+
# Empty string = no-op (default).
|
|
57
|
+
|
|
58
|
+
on_complete = ""
|
|
@@ -10,24 +10,21 @@ detectWorkspacesProbeOrder:
|
|
|
10
10
|
detectLanguageProbeOrder:
|
|
11
11
|
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-language.py'
|
|
12
12
|
- '{project-root}/src/shared/scripts/skf-detect-language.py'
|
|
13
|
+
emitBriefEnvelopeProbeOrder:
|
|
14
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
15
|
+
- '{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
13
16
|
---
|
|
14
17
|
|
|
15
18
|
<!-- Config: communicate in {communication_language}. -->
|
|
16
19
|
|
|
17
20
|
# Step 2: Analyze Target
|
|
18
21
|
|
|
19
|
-
## STEP GOAL:
|
|
20
|
-
|
|
21
|
-
To analyze the target repository by resolving its location, reading its structure, detecting the primary language, and listing top-level modules and exports — providing the user with a factual foundation for scoping decisions.
|
|
22
|
-
|
|
23
22
|
## Rules
|
|
24
23
|
|
|
25
|
-
- Focus only on analysis — do not define scope yet (Step 03)
|
|
26
24
|
- Do not make scoping decisions or recommendations
|
|
27
25
|
- Do not hallucinate or guess about repository contents
|
|
28
|
-
- All user-facing output in `{communication_language}`
|
|
29
26
|
|
|
30
|
-
##
|
|
27
|
+
## Sequence
|
|
31
28
|
|
|
32
29
|
### 1. Resolve Target Location
|
|
33
30
|
|
|
@@ -56,15 +53,15 @@ To analyze the target repository by resolving its location, reading its structur
|
|
|
56
53
|
|
|
57
54
|
**On API failure (non-200 from `gh api`):**
|
|
58
55
|
|
|
59
|
-
Distinguish the failure class before reporting:
|
|
60
|
-
- Auto-run `gh auth status` and capture its output. If it reports an unauthenticated state or expired token: HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** GitHub CLI is not authenticated. `gh auth status` says: `{captured output}`. Run `gh auth login` and retry."
|
|
61
|
-
- If `gh auth status` reports authenticated but the call still failed (404/403): HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Cannot access repository at `{url}`. The CLI is authenticated but the API returned `{status}`. Check the URL and that the account has access to private repositories if applicable."
|
|
62
|
-
- If `gh auth status` itself fails to run (binary missing): HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** `gh` CLI not found on PATH. Install it from <https://cli.github.com> and re-run."
|
|
56
|
+
Distinguish the failure class before reporting. In headless mode, every branch below emits the error envelope per **step 5 §4b** with its stated `halt_reason` before the HALT (pass the resolved `{skill_name}`, or the `"unknown"` placeholder documented in §4b if it is not yet set):
|
|
57
|
+
- Auto-run `gh auth status` and capture its output. If it reports an unauthenticated state or expired token: emit the error envelope per **step 5 §4b** with `halt_reason: "gh-auth-failed"`, then HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** GitHub CLI is not authenticated. `gh auth status` says: `{captured output}`. Run `gh auth login` and retry."
|
|
58
|
+
- If `gh auth status` reports authenticated but the call still failed (404/403): emit the error envelope per **step 5 §4b** with `halt_reason: "target-inaccessible"`, then HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Cannot access repository at `{url}`. The CLI is authenticated but the API returned `{status}`. Check the URL and that the account has access to private repositories if applicable."
|
|
59
|
+
- If `gh auth status` itself fails to run (binary missing): emit the error envelope per **step 5 §4b** with `halt_reason: "gh-auth-failed"`, then HALT (exit code 3, `halt_reason: "gh-auth-failed"`) — "**Error:** `gh` CLI not found on PATH. Install it from <https://cli.github.com> and re-run."
|
|
63
60
|
|
|
64
61
|
**For local paths:**
|
|
65
62
|
- Verify the directory exists
|
|
66
63
|
- List the directory tree
|
|
67
|
-
- If path
|
|
64
|
+
- If the path does not exist: HALT (exit code 3, `halt_reason: "target-inaccessible"`) — "**Error:** Directory not found at {path}. Verify the path is correct." In headless mode, emit the error envelope per **step 5 §4b** with `halt_reason: "target-inaccessible"` before the HALT (pass the resolved `{skill_name}`, or the `"unknown"` placeholder documented in §4b if it is not yet set), matching the GitHub-target failure branches above so a missing local path surfaces the same `SKF_BRIEF_RESULT_JSON` failure class.
|
|
68
65
|
|
|
69
66
|
Display: "**Resolving target...**"
|
|
70
67
|
|
|
@@ -138,7 +135,9 @@ The script returns `{language, confidence, detection_source, fallback_to_extensi
|
|
|
138
135
|
**Confidence:** {confidence}
|
|
139
136
|
**Detection source:** {detection_source}"
|
|
140
137
|
|
|
141
|
-
If `
|
|
138
|
+
**Headless language override.** If `language_hint` was supplied as a headless argument, use it as the confirmed `{language}` (overriding the detected value) and carry it forward to §4 and step 03. The detector still runs so the "Detected language" line reflects what the source signals, but the explicit hint wins and the step 03 §4 low-confidence override does not fire. When `language_hint` is absent, carry the detected `{language}` forward.
|
|
139
|
+
|
|
140
|
+
If `confidence` is `low` (or `unknown` is returned for `language`) and no `language_hint` was supplied: flag for user override in step 03 §4.
|
|
142
141
|
|
|
143
142
|
### 4. List Top-Level Modules and Exports
|
|
144
143
|
|
|
@@ -288,13 +287,9 @@ Pause briefly for user input. If the user provides corrections or asks questions
|
|
|
288
287
|
|
|
289
288
|
- After analysis report is presented to user and any corrections addressed, load, read entire file, then execute {nextStepFile}
|
|
290
289
|
|
|
291
|
-
####
|
|
290
|
+
#### Execution rules:
|
|
292
291
|
|
|
293
292
|
- This is a soft auto-proceed step — present the pause prompt, wait briefly for user input
|
|
294
293
|
- If user provides corrections: address them, then proceed
|
|
295
294
|
- If no user input after a brief pause: proceed directly to step 03
|
|
296
295
|
|
|
297
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
298
|
-
|
|
299
|
-
ONLY WHEN the analysis is complete and the summary has been presented to the user will you load and read fully `scope-definition.md` to begin scope definition.
|
|
300
|
-
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'write-brief.md'
|
|
3
3
|
reviseStepFile: 'scope-definition.md'
|
|
4
|
-
briefSchemaFile: 'assets/skill-brief-schema.md'
|
|
5
4
|
advancedElicitationSkill: '/bmad-advanced-elicitation'
|
|
6
5
|
partyModeSkill: '/bmad-party-mode'
|
|
7
6
|
---
|
|
@@ -10,17 +9,11 @@ partyModeSkill: '/bmad-party-mode'
|
|
|
10
9
|
|
|
11
10
|
# Step 4: Confirm Brief
|
|
12
11
|
|
|
13
|
-
## STEP GOAL:
|
|
14
|
-
|
|
15
|
-
To present the complete skill brief in human-readable format, highlighting all fields that will be written to skill-brief.yaml, and obtain explicit user approval before writing.
|
|
16
|
-
|
|
17
12
|
## Rules
|
|
18
13
|
|
|
19
|
-
- Focus only on presenting and confirming — do not write files yet (Step 05)
|
|
20
14
|
- Do not proceed without explicit user approval (P2 confirmation gate)
|
|
21
|
-
- All user-facing output in `{communication_language}`
|
|
22
15
|
|
|
23
|
-
##
|
|
16
|
+
## Sequence
|
|
24
17
|
|
|
25
18
|
### 1. Assemble Complete Brief
|
|
26
19
|
|
|
@@ -163,15 +156,9 @@ Display: **Select an Option:** [R] Revise Scope [A] Advanced Elicitation [P] Par
|
|
|
163
156
|
- IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — step 5 has not run, no skill-brief.yaml file exists yet. `[X]` is interactive-only; the headless GATE never reaches this branch.
|
|
164
157
|
- IF Any other comments or queries: help user respond, apply any field adjustments, re-present brief if changed, then [Redisplay Menu Options](#5-present-menu-options)
|
|
165
158
|
|
|
166
|
-
####
|
|
159
|
+
#### Execution rules:
|
|
167
160
|
|
|
168
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
169
161
|
- **GATE [default: C]** — If `{headless_mode}`: auto-proceed with [C] Confirm, log: "headless: auto-confirm brief"
|
|
170
|
-
- ONLY proceed to write step when user selects 'C'
|
|
171
162
|
- After other menu items execution, return to this menu
|
|
172
163
|
- User can chat, request field changes, or ask questions — always respond and then redisplay menu
|
|
173
164
|
|
|
174
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
175
|
-
|
|
176
|
-
ONLY WHEN C is selected and the user has explicitly approved the brief will you load and read fully `write-brief.md` to write the skill-brief.yaml file.
|
|
177
|
-
|
|
@@ -4,31 +4,31 @@ The `.brief-draft.json` file at `{forge_data_folder}/{skill-name}/.brief-draft.j
|
|
|
4
4
|
|
|
5
5
|
**Headless mode skips this entire lifecycle** — the run completes in a single invocation, so no resume is meaningful and no checkpoint is written.
|
|
6
6
|
|
|
7
|
-
The two halves of the lifecycle (resume
|
|
7
|
+
The two halves of the lifecycle (resume after the target is confirmed in §3, write on §7 confirmation) form a pair. This file documents both so a single load covers them.
|
|
8
8
|
|
|
9
|
-
## Half 1 — Resume Check (loaded from §
|
|
9
|
+
## Half 1 — Resume Check (loaded from §3 after the target is confirmed)
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Keyed on the confirmed **target**, not the derived skill name, so the offer can fire right after §3 — before the returning user re-answers version (§3b), intent (§4), or scope (§5), which is exactly the state a draft restores. The caller (gather-intent §3) has already globbed `{forge_data_folder}/*/.brief-draft.json`, kept only drafts whose `target_repo` equals the confirmed target (or whose `doc_urls` contain it, for docs-only) with no `skill-brief.yaml` beside them, and selected the most-recently-modified survivor. Its directory basename is the candidate skill `name`. Present the resume prompt for that draft.
|
|
12
12
|
|
|
13
|
-
When
|
|
13
|
+
When a live draft is found, present:
|
|
14
14
|
|
|
15
15
|
```
|
|
16
16
|
**An in-progress draft for `{name}` was found** (last updated: {mtime}).
|
|
17
17
|
[Y] Resume from the saved draft (jump to §8 with prior answers restored)
|
|
18
|
-
[N] Start fresh (
|
|
18
|
+
[N] Start fresh (ignore this draft and keep gathering)
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
### `[Y]` — Resume
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
Restore the candidate `name` (the matched draft's directory basename), then load the JSON and restore the captured fields: `target_repo`, `source_type`, `source_authority`, `target_version`, `doc_urls`, `intent`, `scope_hint`, `description`, `forge_tier`, `tier_source`. Then jump directly to §8 — **skip §3b, §4, §5, §6, §7, and §7b** — so the version, intent, scope, and description the draft already holds are never re-gathered.
|
|
24
24
|
|
|
25
|
-
The skip rule for §7b is load-bearing: re-running §7b would overwrite the user's previously accepted `description` with a fresh candidate synthesized from the seed material. The restored `description` is authoritative.
|
|
25
|
+
The skip rule for §7b is load-bearing: re-running §7b would overwrite the user's previously accepted `description` with a fresh candidate synthesized from the seed material. The restored `description` is authoritative. §6 is skipped too, so the restored `name` is used as-is — it already cleared the collision and portfolio-similarity checks in the session that wrote the draft.
|
|
26
26
|
|
|
27
27
|
The user can still revise any field at step 4 §3 if a refinement is needed after the full brief is visible.
|
|
28
28
|
|
|
29
29
|
### `[N]` — Start fresh
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Leave the draft in place and continue forward to §3b — the normal gather flow (§3b version, §4 intent, §5 scope, §6 name) resumes, and the §6 collision / portfolio-similarity checks run in their usual place. Do not delete the draft here: the skill name has not been chosen yet, so there is nothing to key a deletion on. If the user lands on the same name, step 5's atomic write overwrites the stale draft; otherwise it stays a harmless orphan that the resume check offers again on a future run targeting the same repo.
|
|
32
32
|
|
|
33
33
|
## Half 2 — Checkpoint Write (loaded from §7 after summary confirmation)
|
|
34
34
|
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
nextStepFile: 'analyze-target.md'
|
|
3
3
|
ratifyTargetFile: 'confirm-brief.md'
|
|
4
4
|
forgeTierFile: '{sidecar_path}/forge-tier.yaml'
|
|
5
|
-
descriptionVoiceExamplesFile: 'assets/description-voice-examples.md'
|
|
6
5
|
headlessArgsFile: 'references/headless-args.md'
|
|
7
6
|
headlessSourceAuthorityDetectionFile: 'references/headless-source-authority-detection.md'
|
|
8
7
|
portfolioSimilarityCheckFile: 'references/portfolio-similarity-check.md'
|
|
@@ -22,10 +21,6 @@ emitBriefEnvelopeProbeOrder:
|
|
|
22
21
|
|
|
23
22
|
# Step 1: Gather Intent
|
|
24
23
|
|
|
25
|
-
## STEP GOAL:
|
|
26
|
-
|
|
27
|
-
To initialize the brief-skill workflow by discovering the forge tier configuration, then gathering the user's target repository, intent, and any upfront scope hints for skill creation.
|
|
28
|
-
|
|
29
24
|
## Rules
|
|
30
25
|
|
|
31
26
|
- Focus only on gathering intent — do not analyze the repo yet (Step 02)
|
|
@@ -33,7 +28,7 @@ To initialize the brief-skill workflow by discovering the forge tier configurati
|
|
|
33
28
|
- Open-ended discovery facilitation — collect target repo, user intent, scope hints, skill name
|
|
34
29
|
- All user-facing output in `{communication_language}`
|
|
35
30
|
|
|
36
|
-
##
|
|
31
|
+
## Sequence
|
|
37
32
|
|
|
38
33
|
### 1. Discover Forge Tier
|
|
39
34
|
|
|
@@ -61,6 +56,7 @@ Attempt to load `{forgeTierFile}`:
|
|
|
61
56
|
|
|
62
57
|
**If not found:**
|
|
63
58
|
- "**Cannot proceed.** forge-tier.yaml not found at `{forgeTierFile}`. Run the **setup** workflow first to configure your forge tier (Quick/Forge/Forge+/Deep)."
|
|
59
|
+
- In headless mode, emit the error envelope per **step 5 §4b** with `halt_reason: "forge-tier-missing"` (`skill_name` is not yet resolved here — use the `"unknown"` placeholder convention documented in §4b).
|
|
64
60
|
- HALT (exit code 3, `halt_reason: "forge-tier-missing"`) — do not proceed.
|
|
65
61
|
|
|
66
62
|
### 1b. Auto Mode Check
|
|
@@ -72,7 +68,7 @@ Attempt to load `{forgeTierFile}`:
|
|
|
72
68
|
1. **Load upstream brief path:** Read `brief_path` from the pipeline data context (passed by the forger from AN's `SKF_ANALYZE_RESULT_JSON` `brief_paths[]`). If `brief_path` is not available, HARD HALT with exit code 2 (`input-missing`): "**Auto mode requires `brief_path` in pipeline context — AN must run before BS[auto].**"
|
|
73
69
|
2. **Load source repo:** Read `source_repo` from the pipeline data context (the target repo URL or path, forwarded by the forger). If not available, attempt to extract it from the upstream brief at `brief_path`.
|
|
74
70
|
3. "**Auto mode activated — bypassing interactive brief workflow.**"
|
|
75
|
-
4. **Route to auto-brief:** Load, read fully, then execute `references/step-auto-brief.md
|
|
71
|
+
4. **Route to auto-brief:** Load, read fully, then execute `references/step-auto-brief.md`, and hand off there — do not fall through to §2 or any subsequent section of this file.
|
|
76
72
|
|
|
77
73
|
**IF `{auto_mode}` is NOT true:**
|
|
78
74
|
Continue to §2 as normal — the entire interactive flow below is unchanged.
|
|
@@ -85,12 +81,6 @@ Continue to §2 as normal — the entire interactive flow below is unchanged.
|
|
|
85
81
|
|
|
86
82
|
I'll help you define exactly what to skill and produce a `skill-brief.yaml` that drives the create-skill compilation workflow.
|
|
87
83
|
|
|
88
|
-
We'll work through this together:
|
|
89
|
-
1. **Now:** Understand what you want to skill and why
|
|
90
|
-
2. **Next:** Analyze the target repo structure
|
|
91
|
-
3. **Then:** Define scope boundaries
|
|
92
|
-
4. **Finally:** Confirm and write the brief
|
|
93
|
-
|
|
94
84
|
{If tier override was applied:}
|
|
95
85
|
**Your forge tier:** {override tier} (overridden from {original tier}) — {tier_gloss}
|
|
96
86
|
{Else:}
|
|
@@ -106,8 +96,12 @@ This section has four sub-flows. Execute exactly one branch — 3.1a *or* 3.2 *o
|
|
|
106
96
|
|
|
107
97
|
#### 3.1 Collect target
|
|
108
98
|
|
|
99
|
+
**Open-floor opening.** Lead with an open invitation so an expert can state everything in one breath rather than being walked through seven discrete prompts — costs almost nothing token-wise and sharply improves the conversational feel of this, the most question-heavy mode. A first-timer who pastes only a bare URL still gets the full guided sequence below, unchanged.
|
|
100
|
+
|
|
109
101
|
"**What repository or documentation do you want to create a skill for?**
|
|
110
102
|
|
|
103
|
+
Tell me everything you have — the repo or docs, what you want to skill and why, any scope or version thoughts. Or just paste a URL and we'll go from there.
|
|
104
|
+
|
|
111
105
|
Provide one of:
|
|
112
106
|
- A **GitHub URL** (e.g., `https://github.com/org/repo`)
|
|
113
107
|
- A **local path** (e.g., `/path/to/project`)
|
|
@@ -118,7 +112,7 @@ Or type `cancel` / `exit` / `[X]` to leave without writing anything.
|
|
|
118
112
|
|
|
119
113
|
**Target:**"
|
|
120
114
|
|
|
121
|
-
Wait for user response.
|
|
115
|
+
Wait for user response. **Parse the response for any of the fields the later sections collect** — `target_version` (§3b), intent (§4), scope hints (§5), source authority (§3.3), a proposed name (§6) — and pre-fill every field the user covered, holding them in workflow context. Sections §3b/§4/§5/§6/§7b then **acknowledge a pre-filled field instead of re-asking** ("I noted you're targeting v4.0.0"), and prompt only for the gaps. An expert who stated it all collapses to the §3.1 target branch plus the §7b description confirmation; a bare URL falls through to the full sequence. Then branch on the response for the target itself:
|
|
122
116
|
|
|
123
117
|
- Empty input, `cancel`, `exit`, `[X]`, `q`, or `:q` → Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — no files have been written yet by step 1. Headless mode never reaches this branch (the GATE in §8 short-circuits the interactive sub-flows).
|
|
124
118
|
- Path that resolves to an existing `skill-brief.yaml` (file path ending in `skill-brief.yaml` that exists, OR a directory containing a `skill-brief.yaml`) → §3.1a
|
|
@@ -218,6 +212,20 @@ Default to `"community"` if user does not specify or skips.
|
|
|
218
212
|
|
|
219
213
|
Confirm the target.
|
|
220
214
|
|
|
215
|
+
**Draft-resume check (interactive only).** Now that the target is confirmed — and *before* the version prompt (§3b), intent (§4), or scope (§5) spend the user's time — offer to resume an in-progress draft that already covers this exact target, so a returning user re-types nothing. Keying on the target (not the not-yet-derived skill name) is what lets the offer fire this early. When the flow is interactive:
|
|
216
|
+
|
|
217
|
+
1. **Cheap pre-filter** — list any draft file that mentions the confirmed target at all:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
grep -lF "{target}" "{forge_data_folder}"/*/.brief-draft.json 2>/dev/null
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
`{target}` is the repo URL, local path, or primary doc URL just entered. No output → no draft; skip straight to §3b.
|
|
224
|
+
|
|
225
|
+
2. **Confirm each candidate on the target *field*, not free text.** Read the candidate draft's JSON and keep it only if its `target_repo` equals the confirmed target (source targets) or the target appears in its `doc_urls` (docs-only) — this rejects a draft that merely mentions the URL in its `intent` or `description`. Drop any candidate that has a finished `skill-brief.yaml` in the same directory (that brief is done; step 5's overwrite gate owns it).
|
|
226
|
+
|
|
227
|
+
3. If one or more live drafts survive, load `{draftCheckpointFile}` and follow Half 1 (Resume Check) against the most-recently-modified survivor; its directory basename is the candidate skill name. On `[Y]` resume, Half 1 restores every gathered answer and jumps straight to §8 — **§3b, §4, §5, §6, §7, and §7b are all skipped**. Otherwise (headless, no surviving draft, or every match already has a finished brief beside it) skip the load and continue to §3b.
|
|
228
|
+
|
|
221
229
|
### 3b. Gather Target Version
|
|
222
230
|
|
|
223
231
|
This step only collects `target_version` and validates its shape with the regex below — auto-detection runs in step 2 and precedence/invariant resolution lands in step 5's writer script. The canonical precedence rules live in `references/version-resolution.md`; load it from step 2 / step 5 only when the relevant section needs it.
|
|
@@ -267,6 +275,8 @@ Take your time — the more context you share, the better the brief."
|
|
|
267
275
|
|
|
268
276
|
Wait for user response. Ask follow-up questions if intent is unclear.
|
|
269
277
|
|
|
278
|
+
**Capture, don't interrupt.** If the user volunteers an out-of-scope aside while answering — "the v3 API is totally different", "we're deprecating the auth module next quarter" — do not redirect the conversation to chase it. Silently note it as a candidate `scope.notes` line (carried forward into the brief's `scope.notes` at step 3) and continue the current prompt. These unprompted asides are often the most useful scoping signal; the cost of losing them when the conversation moves on is higher than the cost of one stored line.
|
|
279
|
+
|
|
270
280
|
### 5. Capture Scope Hints
|
|
271
281
|
|
|
272
282
|
If the user mentioned scope preferences in their intent response, acknowledge them:
|
|
@@ -314,7 +324,7 @@ Wait for confirmation or alternative.
|
|
|
314
324
|
|
|
315
325
|
**Portfolio-similarity check.** When the flow is interactive AND forge tier is `Deep` AND `tools.qmd` is true in `forge-tier.yaml`, load `{portfolioSimilarityCheckFile}` and follow the procedure there to catch semantic near-duplicates that exact-name collision misses. Otherwise (headless, or tier below Deep, or qmd unavailable) skip the load — the check does not run.
|
|
316
326
|
|
|
317
|
-
|
|
327
|
+
(The resume-a-draft offer for a returning user fires earlier, right after the target is confirmed in §3 — see the §3 "Draft-resume check" — so the intent, scope, and description a draft holds are spared *before* they get re-gathered here.)
|
|
318
328
|
|
|
319
329
|
### 7. Summarize Gathered Intent
|
|
320
330
|
|
|
@@ -334,7 +344,7 @@ Wait for confirmation or alternative.
|
|
|
334
344
|
|
|
335
345
|
Ready to analyze the target repository?"
|
|
336
346
|
|
|
337
|
-
**Draft checkpoint.** When the flow is interactive, load `{draftCheckpointFile}` (or reuse it if already loaded for the §
|
|
347
|
+
**Draft checkpoint.** When the flow is interactive, load `{draftCheckpointFile}` (or reuse it if already loaded for the §3 resume check) and follow Half 2 (Checkpoint Write) to persist the captured state atomically. Headless mode skips this — the run completes in a single invocation, no resume is meaningful.
|
|
338
348
|
|
|
339
349
|
### 7b. Synthesize Skill Description
|
|
340
350
|
|
|
@@ -377,9 +387,8 @@ Display: "**Select:** [C] Continue to Target Analysis · [X] Cancel and exit"
|
|
|
377
387
|
- IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). When `{headless_mode}` is true the GATE auto-proceeds and never reaches this branch — `[X]` is interactive-only. Cancellation here is non-destructive: no files have been written yet by step 1.
|
|
378
388
|
- IF Any other: Help user, then [Redisplay Menu Options](#8-present-menu-options)
|
|
379
389
|
|
|
380
|
-
####
|
|
390
|
+
#### Execution rules:
|
|
381
391
|
|
|
382
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
383
392
|
- **Resolve `{validateBriefInputsHelper}`** from `{validateBriefInputsProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
384
393
|
|
|
385
394
|
- **GATE [default: use args]** — If `{headless_mode}`, consume pre-supplied arguments and auto-proceed. The full argument set (required/optional, defaults, halt codes, enum values) is documented in `{headlessArgsFile}` — load it now if you need to look up a specific argument. Validation is delegated to `{validateBriefInputsHelper}`; the table is the canonical operator-facing documentation, the script enforces it.
|
|
@@ -410,9 +419,3 @@ Display: "**Select:** [C] Continue to Target Analysis · [X] Cancel and exit"
|
|
|
410
419
|
|
|
411
420
|
**Headless source-authority detection (derive route only — no `from_brief`).** After consuming `normalized`, if `source_authority` is absent AND `source_type=source` AND `target_repo` is a GitHub URL, load `{headlessSourceAuthorityDetectionFile}` and follow the procedure there. Otherwise (precondition unmet, value already supplied, docs-only, or local-path) skip the load — `community` is the implicit default for the unmet branches.
|
|
412
421
|
|
|
413
|
-
- ONLY proceed to next step when user selects 'C'
|
|
414
|
-
|
|
415
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
416
|
-
|
|
417
|
-
ONLY WHEN C is selected and target repository is confirmed will you load and read fully `analyze-target.md` to execute target analysis.
|
|
418
|
-
|
|
@@ -12,7 +12,7 @@ Loaded by step 1 §8 only when `{headless_mode}` is true. Canonical operator-fac
|
|
|
12
12
|
| `source_authority` | no | detected | `official` / `community` / `internal`. When absent and `target_repo` is a GitHub URL, step 1 §8 GATE probes `gh api user` and compares its login to the URL owner — match → `official`, otherwise → `community`. Local-path or `gh api user` failure → `community`. Forced to `community` when `source_type=docs-only` |
|
|
13
13
|
| `target_version` | no | — | Auto-detected in step 2 if absent. Full X.Y.Z semver required (HALT exit 2, `halt_reason: "input-invalid"` on partial forms like `1`, `1.2`, `v2`) |
|
|
14
14
|
| `scope_hint` | no | — | Free-text steering for §5 |
|
|
15
|
-
| `language_hint` | no | — | Overrides language detection
|
|
15
|
+
| `language_hint` | no | — | Overrides language detection — consumed at step 2 §3: the detector still runs for the informational Detected-language line, but the hint becomes the confirmed language and the step 3 §4 low-confidence override does not fire |
|
|
16
16
|
| `scope_type` | no | heuristic | `full-library` / `specific-modules` / `public-api` / `component-library` / `reference-app` / `docs-only`. When absent and `source_type=source`, step 3 §2c runs five signal-driven heuristics (component-registry presence, reference-app keywords, specific-module intent, narrow public API) and uses the first match; falls back to `full-library` only if no heuristic fires. `source_type=docs-only` always short-circuits to `docs-only` |
|
|
17
17
|
| `include` | no | — | Comma-separated globs (used by step 3 §3) |
|
|
18
18
|
| `exclude` | no | — | Comma-separated globs (used by step 3 §3) |
|
|
@@ -9,25 +9,4 @@ nextStepFile: 'shared/health-check.md'
|
|
|
9
9
|
|
|
10
10
|
# Step 6: Workflow Health Check
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
Chain to the shared workflow self-improvement health check at `{nextStepFile}`. This is the terminal step of brief-skill — after the shared health check completes, the workflow is fully done.
|
|
15
|
-
|
|
16
|
-
## Rules
|
|
17
|
-
|
|
18
|
-
- No user-facing reports, file writes, or result contracts in this step — those belong in step 5
|
|
19
|
-
- Delegate directly to `{nextStepFile}` with no additional commentary
|
|
20
|
-
- Do not attempt any other action between loading this step and executing `{nextStepFile}`
|
|
21
|
-
- All user-facing output in `{communication_language}`
|
|
22
|
-
|
|
23
|
-
## MANDATORY SEQUENCE
|
|
24
|
-
|
|
25
|
-
Load `{nextStepFile}`, read it fully, then execute it.
|
|
26
|
-
|
|
27
|
-
## Completion criteria
|
|
28
|
-
|
|
29
|
-
This is the terminal step of brief-skill. The workflow is complete when `{nextStepFile}` returns control — do not transition to any further step.
|
|
30
|
-
|
|
31
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
32
|
-
|
|
33
|
-
Step 06 is the terminal stage of brief-skill. After `{nextStepFile}` returns control, the brief-skill workflow is fully complete — do not re-enter step 5 or step 6, do not load any further step file, and do not loop back into the workflow.
|
|
12
|
+
This is the terminal step of brief-skill. Load `{nextStepFile}`, read it fully, then execute it — do nothing else here (no user-facing reports, file writes, or result contracts; those were step 5). After `{nextStepFile}` returns control, the brief-skill workflow is fully complete: do not re-enter step 5 or step 6, load any further step file, or loop back into the workflow.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# Invocation Contract — skf-brief-skill
|
|
2
|
+
|
|
3
|
+
Full argument set, gate map, exit codes, and headless result envelope for `skf-brief-skill`. Interactive callers can ignore this file; headless automators and pipeline integrators consult it. This is the canonical statement of the `from_brief` ratify contract — the source of truth for both the interactive (`gather-intent.md` §3.1a) and headless (step 1 §8 GATE) ratify paths.
|
|
4
|
+
|
|
5
|
+
## Invocation Contract
|
|
6
|
+
|
|
7
|
+
| Aspect | Detail |
|
|
8
|
+
|--------|--------|
|
|
9
|
+
| **Inputs** | `target_repo` [required], `skill_name` [required], `scope_hint` [optional], `language_hint` [optional], `target_version` [optional], `source_authority` [optional: official/community/internal, default community], `source_type` [optional: source/docs-only, default source], `doc_urls` [optional: list of `url[,label]` for source_type=docs-only or supplemental], `scope_type` [optional: full-library/specific-modules/public-api/component-library/reference-app/docs-only], `include` [optional: comma-separated globs], `exclude` [optional: comma-separated globs], `scripts_intent` [optional: detect/none/free-text, default detect], `assets_intent` [optional: detect/none/free-text, default detect], `intent` [optional: free-text used to derive description], `force` [optional: overwrite existing brief without prompting], `from_brief` [optional: path to a pre-authored `skill-brief.yaml` to *ratify* — when supplied it is the source of truth, `target_repo`/`skill_name` become optional/derived-from-brief, and the run mirrors the interactive §3.1a ratify path: schema-validate, skip analyze-target/scope-definition, write through the canonical writer in place], `[auto]` [optional: bracket modifier passed via pipeline context — when present, BS loads the upstream brief from `brief_path` in pipeline data, enriches it with doc detection, and writes through the canonical writer; requires `brief_path` from AN's `SKF_ANALYZE_RESULT_JSON`] |
|
|
10
|
+
| **Gates** | step 1: Input Gate [use args] | step 3: Confirm Gate [C] | step 4: Confirm Gate [C] |
|
|
11
|
+
| **Outputs** | `skill-brief.yaml` at `{forge_data_folder}/{skill-name}/skill-brief.yaml`; final `SKF_BRIEF_RESULT_JSON` line on stdout when `{headless_mode}` is true |
|
|
12
|
+
| **Headless** | All gates auto-resolve with heuristic-driven or default action when `{headless_mode}` is true; pre-supplied inputs consumed at the gates that would otherwise prompt; absent `source_authority` and `scope_type` are resolved by signal-driven detection (see `references/headless-args.md`); existing briefs are preserved unless `--force` was supplied (HALT with `overwrite-cancelled` otherwise); supplying `from_brief <path>` instead routes the step 1 GATE to the ratify path described in the `from_brief` Inputs cell (schema-validate, skip analyze/scope, write in place — no `--force` needed) rather than deriving a new brief |
|
|
13
|
+
| **Transient-failure retry** | This workflow does **not** auto-retry network or subprocess failures. A failed `gh` fetch (analyze-target.md §1, portfolio-similarity-check.md), QMD probe, or extraction script is logged and surfaced in the final result envelope as a warning, but the workflow continues with whatever signal it has. Headless pipelines that want retry semantics should wrap the invocation at their orchestrator level (e.g. CI re-runner on non-zero exit). Rationale: brief-skill is read-mostly with one terminal write (the YAML at step 5); a partial-signal retry has more failure modes than just re-running the whole workflow, which is cheap. |
|
|
14
|
+
| **Exit codes** | See "Exit Codes" below |
|
|
15
|
+
|
|
16
|
+
## Exit Codes
|
|
17
|
+
|
|
18
|
+
Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
|
|
19
|
+
|
|
20
|
+
| Code | Meaning | Raised by |
|
|
21
|
+
| ---- | -------------------- | ------------------------------------------------------------------------------------------ |
|
|
22
|
+
| 0 | success | step 6 (terminal) |
|
|
23
|
+
| 2 | input-missing / input-invalid | step 1 GATE — required headless arg absent (`target_repo`, `skill_name`, or `doc_urls` when `source_type=docs-only`) → `input-missing`; enum violation, malformed semver, non-kebab `skill_name`, or step 5 brief-context schema validation failure → `input-invalid` |
|
|
24
|
+
| 3 | resolution-failure | step 1 §1 (`forge-tier.yaml` missing); step 2 §1 (target inaccessible / `gh auth` fails) |
|
|
25
|
+
| 4 | write-failure | step 1 §1 pre-flight write probe (data folder unwritable: read-only mount, disk full, permissions denied); step 5 §4 (write to `{forge_data_folder}/{skill-name}/skill-brief.yaml` failed) |
|
|
26
|
+
| 5 | overwrite-cancelled | step 5 §2 (existing brief, `force` not supplied) |
|
|
27
|
+
| 6 | user-cancelled | any interactive menu in step 1/03/04 (user selected `[X]` Cancel and exit) |
|
|
28
|
+
|
|
29
|
+
## Result Contract (Headless)
|
|
30
|
+
|
|
31
|
+
When `{headless_mode}` is true, step 5 emits a single-line JSON envelope on **stdout** before chaining to step 6, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
SKF_BRIEF_RESULT_JSON: {"status":"success|error","brief_path":"…|null","skill_name":"…","version":"…|null","language":"…|null","scope_type":"…|null","exit_code":0,"halt_reason":null,"mode":"auto|null"}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`status` is `"success"` on the terminal happy path, `"error"` on any HALT. `halt_reason` is one of: `null` (success), `"input-missing"`, `"input-invalid"`, `"forge-tier-missing"`, `"target-inaccessible"`, `"gh-auth-failed"`, `"write-failed"`, `"overwrite-cancelled"`, `"user-cancelled"`. `exit_code` matches the table above. `mode` is `"auto"` when BS was invoked with the `[auto]` flag (pipeline auto-brief generation), `null` otherwise (interactive or headless-without-auto).
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
---
|
|
2
2
|
nextStepFile: 'confirm-brief.md'
|
|
3
|
-
scopeTemplatesFile: 'assets/scope-templates.md'
|
|
4
3
|
recommendScopeTypeProbeOrder:
|
|
5
4
|
- '{project-root}/_bmad/skf/shared/scripts/skf-recommend-scope-type.py'
|
|
6
5
|
- '{project-root}/src/shared/scripts/skf-recommend-scope-type.py'
|
|
@@ -12,19 +11,13 @@ partyModeSkill: '/bmad-party-mode'
|
|
|
12
11
|
|
|
13
12
|
# Step 3: Scope Definition
|
|
14
13
|
|
|
15
|
-
## STEP GOAL:
|
|
16
|
-
|
|
17
|
-
To collaboratively define the skill's inclusion and exclusion boundaries using the analysis findings from step 02, scope templates, and the user's intent from step 01.
|
|
18
|
-
|
|
19
14
|
## Rules
|
|
20
15
|
|
|
21
|
-
- Focus only on defining scope boundaries — do not write the brief yet (Step 05)
|
|
22
16
|
- Do not make scope decisions unilaterally — user drives all scope choices
|
|
23
17
|
- Produce: scope type, include patterns, exclude patterns
|
|
24
|
-
- All user-facing output in `{communication_language}`
|
|
25
18
|
- **Re-entry from step 4 [R] revise:** prior selections (`scope.type`, `scope.include`, `scope.exclude`, `scope.notes`, `scope.tier_a_include`, `scope.rationale`, `scripts_intent`, `assets_intent`, supplemental `doc_urls`) are preserved as the current state. Re-present them at each section as the existing answer; the user only re-confirms or overrides. Do not reset to the §2c template menu unless the user explicitly asks to start scope over. When `scope.rationale` is preserved and the user changes `chosen` (the scope type) on this pass, recompute `accepted_recommendation` (`chosen == recommended`) and refresh `reason` and `recorded` per the §2c capture rules — revise in place, do not append.
|
|
26
19
|
|
|
27
|
-
##
|
|
20
|
+
## Sequence
|
|
28
21
|
|
|
29
22
|
### 1. Present Scope Context
|
|
30
23
|
|
|
@@ -120,6 +113,8 @@ How broadly should this skill cover the library?
|
|
|
120
113
|
|
|
121
114
|
Press Enter to accept the recommendation, or pick a different letter."
|
|
122
115
|
|
|
116
|
+
**First-timer reassurance (interactive only, never-briefed user — the §4 first-timer rail fired in step 01).** Append one line so the harder scope-type call doesn't stall a first-timer: "The recommended type is almost always right — accept it and re-scope from step 4 if the analysis surprises you." Repeat users and headless skip this line.
|
|
117
|
+
|
|
123
118
|
Wait for user selection. Empty input or just Enter accepts the recommendation; any of the five letters overrides.
|
|
124
119
|
|
|
125
120
|
### 3. Define Boundaries Based on Selection
|
|
@@ -154,6 +149,8 @@ The analysis detected **{language}** with low confidence. Is this correct, or sh
|
|
|
154
149
|
|
|
155
150
|
Wait for confirmation or override.
|
|
156
151
|
|
|
152
|
+
**Headless:** `language_hint`, when supplied, already set the language at step 02 §3; otherwise accept the detected language and continue. This confirmation prompt is interactive-only, so a headless run never stalls here.
|
|
153
|
+
|
|
157
154
|
### 5. Summarize Scope Decisions
|
|
158
155
|
|
|
159
156
|
"**Scope Summary:**
|
|
@@ -199,9 +196,8 @@ Display: **Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Conti
|
|
|
199
196
|
- IF X: Treat as user-cancellation. Display `"Cancelled — no brief was written."` and HALT (exit code 6, `halt_reason: "user-cancelled"`). Cancellation here is non-destructive — no files have been written yet. `[X]` is interactive-only; the headless GATE never reaches this branch.
|
|
200
197
|
- IF Any other comments or queries: help user respond then [Redisplay Menu Options](#6-present-menu-options)
|
|
201
198
|
|
|
202
|
-
####
|
|
199
|
+
#### Execution rules:
|
|
203
200
|
|
|
204
|
-
- ALWAYS halt and wait for user input after presenting menu
|
|
205
201
|
- **GATE [default: C]** — If `{headless_mode}`: consume the headless inputs from step 1 in priority order:
|
|
206
202
|
- If `scope_type` was supplied, use it (must match one of the six valid types) and skip the §2c template menu.
|
|
207
203
|
- Otherwise auto-select via `{recommendScopeTypeHelper}` — invoke the script with the **same payload shape** documented in §2c but with `mode: "headless"` (presence-only matching for the component-registry rule, since `entry_files` may not be available without an interactive context). Use the returned `scope_type` and log `"headless: scope_type={value} from heuristic={matched_heuristic}"`. The script's docs-only short-circuit handles `source_type=docs-only` automatically.
|
|
@@ -209,11 +205,6 @@ Display: **Select an Option:** [A] Advanced Elicitation [P] Party Mode [C] Conti
|
|
|
209
205
|
- If `scripts_intent`/`assets_intent` were supplied, record them and skip §5b; otherwise default to `detect`.
|
|
210
206
|
- Set `scope.rationale`: `recommended`/`heuristic` from the script (or `recommended = scope_type` arg, `heuristic = "user-supplied-arg"` when `scope_type` was passed); `chosen = <resolved type>`; `accepted_recommendation = (no scope_type arg)`; `reason = "<script rationale>"` (auto path) or `"headless: scope_type supplied as argument"` (arg path); `recorded = {date}`. No prompt — headless never asks "why".
|
|
211
207
|
- Log: `"headless: scope_type={value} include={n} exclude={n} scripts_intent={value} assets_intent={value}"`.
|
|
212
|
-
- ONLY proceed to next step when user selects 'C'
|
|
213
208
|
- After other menu items execution, return to this menu
|
|
214
209
|
- User can chat or ask questions — always respond and then redisplay menu
|
|
215
210
|
|
|
216
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
217
|
-
|
|
218
|
-
ONLY WHEN C is selected and scope boundaries are confirmed will you load and read fully `confirm-brief.md` to present the complete brief for confirmation.
|
|
219
|
-
|
|
@@ -9,7 +9,12 @@ writeSkillBriefProbeOrder:
|
|
|
9
9
|
emitBriefEnvelopeProbeOrder:
|
|
10
10
|
- '{project-root}/_bmad/skf/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
11
11
|
- '{project-root}/src/shared/scripts/skf-emit-brief-result-envelope.py'
|
|
12
|
-
|
|
12
|
+
mergeDocUrlsProbeOrder:
|
|
13
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-merge-doc-urls.py'
|
|
14
|
+
- '{project-root}/src/shared/scripts/skf-merge-doc-urls.py'
|
|
15
|
+
detectDocsProbeOrder:
|
|
16
|
+
- '{project-root}/_bmad/skf/shared/scripts/skf-detect-docs.py'
|
|
17
|
+
- '{project-root}/src/shared/scripts/skf-detect-docs.py'
|
|
13
18
|
---
|
|
14
19
|
|
|
15
20
|
<!-- Config: communicate in {communication_language}. -->
|
|
@@ -69,10 +74,12 @@ Extract from the parsed brief:
|
|
|
69
74
|
|
|
70
75
|
### 2. Run Doc Detection
|
|
71
76
|
|
|
77
|
+
**Resolve `{detectDocsHelper}`** from `{detectDocsProbeOrder}`; first existing path wins. HALT if no candidate exists.
|
|
78
|
+
|
|
72
79
|
Invoke doc detection to discover documentation URLs for the source repo:
|
|
73
80
|
|
|
74
81
|
```bash
|
|
75
|
-
uv run
|
|
82
|
+
uv run {detectDocsHelper} --repo-url {source_repo}
|
|
76
83
|
```
|
|
77
84
|
|
|
78
85
|
`--repo-url` is always required (the script uses it for GitHub API calls). If a local clone is also available at `{local_clone_path}`, add `--local-path {local_clone_path}` to enable docs-folder scanning in addition to API-based detection.
|
|
@@ -97,8 +104,18 @@ For each detected doc entry, create a brief `doc_urls` entry:
|
|
|
97
104
|
- `"readme_link"` → `"README Link"`
|
|
98
105
|
- `"pages_api"` → `"GitHub Pages"`
|
|
99
106
|
- `"docs_folder"` → `"Docs Folder"`
|
|
107
|
+
- `source` ← coarse provenance derived from `detected_via` (per the `skill-brief.v1.json` `doc_urls[].source` enum): `homepageUrl` → `homepage`, `readme_link` → `readme-detection`, `pages_api` → `pages-api`, `docs_folder` → `docs-folder`. This marks the entry as opportunistically detected, distinct from a registry-guaranteed corpus.
|
|
108
|
+
|
|
109
|
+
**Merge via the canonical helper.** Resolve `{mergeDocUrlsHelper}` from `{mergeDocUrlsProbeOrder}` (first existing path wins; HALT if neither exists). Pass the upstream brief's `doc_urls` as `existing` and the entries just mapped above as `detected`:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
echo '{"scope_type": "{scope_type}", "existing": {upstream brief doc_urls JSON, [] if none}, "detected": {mapped detected entries JSON}}' \
|
|
113
|
+
| uv run {mergeDocUrlsHelper}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The helper returns `{"doc_urls": [...], "suppressed": [...]}`. It deduplicates by **normalized** URL (lowercase host, strip a trailing `/index.html` and any trailing `/`), so a seeded `…/book/` and a README's `…/book/index.html` collapse to one entry; existing/corpora-seeded entries always win and keep their `source: language-registry`, so the registry-vs-detected distinction survives the merge. For a **whole-language reference** (`scope_type == "full-library"` AND ≥1 `existing` entry has `source: language-registry`) it additionally suppresses README noise on a corpus host: non-corpus path segments (`/whatsnew/`, `/contribute`, `/wiki/`) and non-primary-locale duplicates of a kept page (`/ja/master/` when `/en/master/` is kept). Ordinary skills (any other `scope_type`, or no registry corpora) pass through with dedup only — no suppression. Use the returned `doc_urls` as the brief's merged list.
|
|
100
117
|
|
|
101
|
-
|
|
118
|
+
**Log suppressed entries.** When `suppressed` is non-empty, log one line per entry — `"info: suppressed {url} ({reason})"` — so the operator can see what the whole-language noise filter dropped (never drop silently). The N==0 DEGRADED case (a whole-language repo whose registry returned no corpora) carries no `language-registry` entry, so suppression stays inactive and its README docs are kept — this is intentional (there is no canonical corpus host to filter against).
|
|
102
119
|
|
|
103
120
|
### 4. Validate Enriched Brief
|
|
104
121
|
|
|
@@ -123,7 +140,7 @@ Assemble the enriched brief context as a flat JSON object following the write-br
|
|
|
123
140
|
"scope_rationale": null,
|
|
124
141
|
"scope_tier_a_include": null,
|
|
125
142
|
"scope_amendments": null,
|
|
126
|
-
"doc_urls": [{"url": "...", "label": "..."}],
|
|
143
|
+
"doc_urls": [{"url": "...", "label": "...", "source": "..."}],
|
|
127
144
|
"scripts_intent": "{scripts_intent or null}",
|
|
128
145
|
"assets_intent": "{assets_intent or null}",
|
|
129
146
|
"source_authority": "{source_authority or null}",
|
|
@@ -164,8 +181,4 @@ echo '{"status":"error","skill_name":"{skill_name or unknown}","halt_reason":"{r
|
|
|
164
181
|
|
|
165
182
|
### 7. Chain to Auto-Validate
|
|
166
183
|
|
|
167
|
-
Load, read fully, then execute {nextStepFile} to present the auto-brief validation gate, where the user can approve, edit, or reject the brief before the pipeline continues.
|
|
168
|
-
|
|
169
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
170
|
-
|
|
171
|
-
ONLY WHEN the enriched brief has been written and validated will you load and read fully {nextStepFile} to begin the auto-brief validation gate.
|
|
184
|
+
Load, read fully, then execute {nextStepFile} to present the auto-brief validation gate, where the user can approve, edit, or reject the brief before the pipeline continues. Do this only after the enriched brief has been written and validated.
|
|
@@ -75,11 +75,11 @@ Scope: {scope_type} ({N} include, {M} exclude patterns)
|
|
|
75
75
|
Docs: {doc_urls count} sources detected | "None detected"
|
|
76
76
|
Version: {version}
|
|
77
77
|
Forge Tier: {forge_tier}
|
|
78
|
-
|
|
78
|
+
Pipeline: forge-auto ({forge_tier} tier)
|
|
79
79
|
Description: "{description}"
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
Where `{N}` is the count of `scope_include` patterns and `{M}` is the count of `scope_exclude` patterns. If `doc_urls` is null or empty, display "None detected".
|
|
82
|
+
Where `{N}` is the count of `scope_include` patterns and `{M}` is the count of `scope_exclude` patterns. If `doc_urls` is null or empty, display "None detected". The `Pipeline` line names the auto pipeline and the resolved `{forge_tier}` — it carries no numeric quality target, which would be an unverified guarantee an automator might parse as fact.
|
|
83
83
|
|
|
84
84
|
### 3. Validation Gate
|
|
85
85
|
|
|
@@ -200,10 +200,6 @@ echo '{"status":"error","skill_name":"{skill_name or unknown}","halt_reason":"{r
|
|
|
200
200
|
|
|
201
201
|
### 8. Chain
|
|
202
202
|
|
|
203
|
-
Load, read fully, then execute the appropriate next step file
|
|
203
|
+
Load, read fully, then execute the appropriate next step file — only after the user has made their choice and the corresponding action has been taken (envelope emitted or context hydrated):
|
|
204
204
|
- [A]pprove or [E]dit (after final approve): {nextStepFile} (health-check.md)
|
|
205
205
|
- [R]eject: {rejectTargetFile} (confirm-brief.md)
|
|
206
|
-
|
|
207
|
-
## CRITICAL STEP COMPLETION NOTE
|
|
208
|
-
|
|
209
|
-
ONLY WHEN the user has made their choice (approve, edit-then-approve, or reject) and the appropriate action has been taken (envelope emitted or context hydrated) will you load and read fully the next step file.
|
|
@@ -29,7 +29,7 @@ The brief's `version` field is resolved from three candidate sources, in priorit
|
|
|
29
29
|
|
|
30
30
|
## Invariant
|
|
31
31
|
|
|
32
|
-
When `target_version` is set, the written brief
|
|
32
|
+
When `target_version` is set, the written brief must satisfy:
|
|
33
33
|
|
|
34
34
|
```
|
|
35
35
|
brief.target_version == brief.version
|