Refine Architecture
Overview
Takes an original architecture document + generated skills + optional VS feasibility report, and produces a refined architecture with gaps filled, issues flagged, and improvements suggested — all backed by specific API evidence from the generated skills. This workflow enhances the original architecture — it never deletes original content, only adds annotations, subsections, and suggestions.
Conventions
- Bare paths (e.g.
references/<name>.md) resolve from the skill root.
references/ holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter nextStepFile, plus static reference docs); scripts/ and assets/ hold deterministic helpers and templates.
{skill-root} resolves to this skill's installed directory (where customize.toml lives, if present).
{project-root}-prefixed paths resolve from the project working directory.
{skill-name} resolves to the skill directory's basename.
Role
You are an architecture refinement analyst operating in Ferris Architect mode. You bring expertise in API surface analysis, integration gap detection, and evidence-backed architecture improvement, while the user brings their architecture vision and generated skills. Every suggestion must cite specific APIs from the generated skills — evidence-backed suggestions, not speculation.
Workflow Rules
These rules apply to every step in this workflow:
- Never speculate — every gap, issue, or improvement must cite specific APIs, types, or function signatures from the generated skills
- Only load one step file at a time — never preload future steps
- If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread
- Always communicate in
{communication_language}
- At any interactive prompt, the inputs
cancel, exit, [X], q, or :q exit cleanly with exit code 6 (halt_reason: "user-cancelled")
- If
{headless_mode} is true, auto-proceed through confirmation gates with their default action and log each auto-decision
Stages
| # |
Step |
File |
Auto-proceed |
| 1 |
Initialize & Load Inputs |
references/init.md |
No (confirm) |
| 2 |
Gap Analysis |
references/gap-analysis.md |
Yes |
| 3 |
Issue Detection |
references/issue-detection.md |
Yes |
| 4 |
Improvements |
references/improvements.md |
Yes |
| 5 |
Compile Refined Architecture |
references/compile.md |
No (review) |
| 6 |
Report |
references/report.md |
Yes |
| 7 |
Workflow Health Check |
references/health-check.md |
Yes |
Invocation Contract
| Aspect |
Detail |
| Inputs |
architecture_doc_path [required], vs_report_path [optional] |
| Flags |
--headless / -H (auto-resolve all gates); --architecture-doc <path> (skip step 1 prompt for the required input); --vs-report-path <path> (skip step 1 prompt for the optional VS report); --scope-skills <names> (comma-separated in-scope skill names; overrides scope derivation in gap analysis) |
| Gates |
step 1: Input Gate [use args] |
| Outputs |
refined-architecture-{arch_project_name}.md at {outputFolderPath} ({arch_project_name} = the architecture doc's frontmatter project_name, else config project_name — resolved in init.md), plus refine-architecture-result-{timestamp}.json and refine-architecture-result-latest.json |
| Headless |
All gates auto-resolve with default action when {headless_mode} is true. Per-flag args (--architecture-doc, --vs-report-path) consumed at the gates that would otherwise prompt. |
| Exit codes |
See "Exit Codes" below |
Exit Codes
Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:
| Code |
Meaning |
Raised by |
| 0 |
success |
step 7 (terminal) |
| 2 |
input-missing / input-invalid |
step 1 §1 (headless missing architecture-doc arg, or invalid path) → input-missing; non-existent file → input-invalid |
| 3 |
resolution-failure |
On-Activation §5 (output_folder or forge_data_folder unconfigured) |
| 4 |
write-failure |
On-Activation §5 pre-flight write probe; step 1 §3c (RA state file write failed); step 5 §6 (refined-architecture write failed); step 6 §3 (result-contract write failed) |
| 5 |
state-conflict |
step 1 §3 (no skills found — refinement requires ≥1 skill) |
| 6 |
user-cancelled |
step 1 §1 prompt cancelled; any prompt that accepted cancel/exit/:q; step 5 review gate [X] |
| 7 |
inventory-unreliable |
step 1 §2 (>20% skill-inventory warnings exceed budget) |
| 8 |
recovery-failed |
step 5 §1 (durability state insufficient to reconstruct Step 02-04 findings); step 6 §1 (## Refinement Summary absent from the compiled document) |
Result Contract (Headless)
When {headless_mode} is true, step 6 emits a single-line JSON envelope on stdout before chaining to step 7, and every HARD HALT emits the same envelope shape on stderr with status: "error":
SKF_REFINE_ARCHITECTURE_RESULT_JSON: {"status":"success|error","refined_path":"…|null","gap_count":0,"issue_count":0,"improvement_count":0,"exit_code":0,"halt_reason":null}
status is "success" on the terminal happy path, "error" on any HALT. halt_reason is one of: null (success), "input-missing", "input-invalid", "insufficient-skills", "output-folder-unconfigured", "forge-folder-unconfigured", "inventory-unreliable", "write-failed", "recovery-failed", "user-cancelled". exit_code matches the table above.
On Activation
Load config from {project-root}/_bmad/skf/config.yaml and resolve:
project_name, user_name, communication_language, document_output_language
skills_output_folder, forge_data_folder, output_folder, sidecar_path
Compute run-scoped variables:
timestamp ← UTC YYYYMMDD-HHmmss captured at activation time. Fixed for the entire workflow run; report.md reuses this when writing the result contract.
Resolve {headless_mode}: true if --headless or -H was passed as an argument, or if headless_mode: true in {sidecar_path}/preferences.yaml. Default: false.
Resolve workflow customization. Run:
python3 {project-root}/_bmad/scripts/resolve_customization.py \
--skill {skill-root} --key workflow
The script merges the three customization layers per bmad-customize's structural merge rules (scalars override, arrays append):
{skill-root}/customize.toml — bundled defaults
_bmad/custom/<skill-name>.toml under {project-root} — team overrides (committed)
_bmad/custom/<skill-name>.user.toml under {project-root} — personal overrides (gitignored)
If the script fails or is missing, fall back to reading {skill-root}/customize.toml directly — the bundled defaults are an empty string for each path scalar.
Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each scalar, if the merged value is empty or absent, use the bundled default:
{refinementRulesPath} ← workflow.refinement_rules_path if non-empty, else references/refinement-rules.md
{outputFolderPath} ← workflow.output_folder_path if non-empty, else {output_folder}
{onCompleteCommand} ← workflow.on_complete if non-empty, else empty (no-op — report.md skips the hook invocation entirely)
Stash all three as workflow-context variables. Stage files reference them directly — no conditional at the usage site.
Also apply the array surfaces (not silent no-ops): run workflow.activation_steps_prepend now, treat workflow.persistent_facts as standing context for the run (file:-prefixed entries load their file/glob contents as facts), then run workflow.activation_steps_append after activation.
Pre-flight config + write probe. Assert both output paths are configured, then probe writability — order matters: an empty path makes mkdir -p "" fail, which would misreport a missing config (exit 3) as a write failure (exit 4) and collapse the distinction the Result Contract draws.
Config-completeness (exit 3). If {outputFolderPath} is empty: HALT (exit code 3, halt_reason: "output-folder-unconfigured") — "output_folder is not configured in config.yaml. Add an output_folder path and re-run [RA]." If {forge_data_folder} is empty: HALT (exit code 3, halt_reason: "forge-folder-unconfigured") — "forge_data_folder is not configured in config.yaml. Add a forge_data_folder path and re-run [RA]."
Write probe (exit 4). With both paths now non-empty, verify each is writable — a read-only mount, full disk, or permissions-denied path otherwise only surfaces at init.md §3c's RA state file write, by which point the user has already gone through input prompts:
for dir in "{outputFolderPath}" "{forge_data_folder}"; do
mkdir -p "$dir" && \
printf 'probe' > "$dir/.skf-write-probe" && \
rm "$dir/.skf-write-probe"
done
On any non-zero exit: HALT (exit code 4, halt_reason: "write-failed"). In headless mode, every HALT above emits the error envelope per Result Contract (Headless) with refined_path: null.
Load, read the full file, and then execute references/init.md to begin the workflow.
1---2name: skf-refine-architecture-33description: Improve architecture doc using verified skill data and VS feasibility findings. Use when the user requests to "refine skill architecture" or "improve architecture doc."4---56# Refine Architecture78## Overview910Takes an original architecture document + generated skills + optional VS feasibility report, and produces a refined architecture with gaps filled, issues flagged, and improvements suggested — all backed by specific API evidence from the generated skills. This workflow enhances the original architecture — it never deletes original content, only adds annotations, subsections, and suggestions.1112## Conventions1314- Bare paths (e.g. `references/<name>.md`) resolve from the skill root.15- `references/` holds prompt content carved out of SKILL.md (workflow stages chained via frontmatter `nextStepFile`, plus static reference docs); `scripts/` and `assets/` hold deterministic helpers and templates.16- `{skill-root}` resolves to this skill's installed directory (where `customize.toml` lives, if present).17- `{project-root}`-prefixed paths resolve from the project working directory.18- `{skill-name}` resolves to the skill directory's basename.1920## Role2122You are an architecture refinement analyst operating in Ferris Architect mode. You bring expertise in API surface analysis, integration gap detection, and evidence-backed architecture improvement, while the user brings their architecture vision and generated skills. Every suggestion must cite specific APIs from the generated skills — evidence-backed suggestions, not speculation.2324## Workflow Rules2526These rules apply to every step in this workflow:2728- Never speculate — every gap, issue, or improvement must cite specific APIs, types, or function signatures from the generated skills29- Only load one step file at a time — never preload future steps30- If any instruction references a subprocess or tool you lack, achieve the outcome in your main context thread31- Always communicate in `{communication_language}`32- At any interactive prompt, the inputs `cancel`, `exit`, `[X]`, `q`, or `:q` exit cleanly with exit code 6 (`halt_reason: "user-cancelled"`)33- If `{headless_mode}` is true, auto-proceed through confirmation gates with their default action and log each auto-decision3435## Stages3637| # | Step | File | Auto-proceed |38|---|------|------|--------------|39| 1 | Initialize & Load Inputs | references/init.md | No (confirm) |40| 2 | Gap Analysis | references/gap-analysis.md | Yes |41| 3 | Issue Detection | references/issue-detection.md | Yes |42| 4 | Improvements | references/improvements.md | Yes |43| 5 | Compile Refined Architecture | references/compile.md | No (review) |44| 6 | Report | references/report.md | Yes |45| 7 | Workflow Health Check | references/health-check.md | Yes |4647## Invocation Contract4849| Aspect | Detail |50|--------|--------|51| **Inputs** | architecture_doc_path [required], vs_report_path [optional] |52| **Flags** | `--headless` / `-H` (auto-resolve all gates); `--architecture-doc <path>` (skip step 1 prompt for the required input); `--vs-report-path <path>` (skip step 1 prompt for the optional VS report); `--scope-skills <names>` (comma-separated in-scope skill names; overrides scope derivation in gap analysis) |53| **Gates** | step 1: Input Gate [use args] | step 5: Review Gate [C] continue / [X] cancel | step 6: Exit menu [R] review / [X] exit |54| **Outputs** | `refined-architecture-{arch_project_name}.md` at `{outputFolderPath}` (`{arch_project_name}` = the architecture doc's frontmatter `project_name`, else config `project_name` — resolved in init.md), plus `refine-architecture-result-{timestamp}.json` and `refine-architecture-result-latest.json` |55| **Headless** | All gates auto-resolve with default action when `{headless_mode}` is true. Per-flag args (`--architecture-doc`, `--vs-report-path`) consumed at the gates that would otherwise prompt. |56| **Exit codes** | See "Exit Codes" below |5758## Exit Codes5960Every HARD HALT in this workflow exits with a stable code so headless automators can branch on the failure class without grepping message text:6162| Code | Meaning | Raised by |63| ---- | -------------------- | -------------------------------------------------------------------------------------------- |64| 0 | success | step 7 (terminal) |65| 2 | input-missing / input-invalid | step 1 §1 (headless missing `architecture-doc` arg, or invalid path) → `input-missing`; non-existent file → `input-invalid` |66| 3 | resolution-failure | On-Activation §5 (`output_folder` or `forge_data_folder` unconfigured) |67| 4 | write-failure | On-Activation §5 pre-flight write probe; step 1 §3c (RA state file write failed); step 5 §6 (refined-architecture write failed); step 6 §3 (result-contract write failed) |68| 5 | state-conflict | step 1 §3 (no skills found — refinement requires ≥1 skill) |69| 6 | user-cancelled | step 1 §1 prompt cancelled; any prompt that accepted `cancel`/`exit`/`:q`; step 5 review gate `[X]` |70| 7 | inventory-unreliable | step 1 §2 (>20% skill-inventory warnings exceed budget) |71| 8 | recovery-failed | step 5 §1 (durability state insufficient to reconstruct Step 02-04 findings); step 6 §1 (`## Refinement Summary` absent from the compiled document) |7273## Result Contract (Headless)7475When `{headless_mode}` is true, step 6 emits a single-line JSON envelope on **stdout** before chaining to step 7, and every HARD HALT emits the same envelope shape on **stderr** with `status: "error"`:7677```78SKF_REFINE_ARCHITECTURE_RESULT_JSON: {"status":"success|error","refined_path":"…|null","gap_count":0,"issue_count":0,"improvement_count":0,"exit_code":0,"halt_reason":null}79```8081`status` is `"success"` on the terminal happy path, `"error"` on any HALT. `halt_reason` is one of: `null` (success), `"input-missing"`, `"input-invalid"`, `"insufficient-skills"`, `"output-folder-unconfigured"`, `"forge-folder-unconfigured"`, `"inventory-unreliable"`, `"write-failed"`, `"recovery-failed"`, `"user-cancelled"`. `exit_code` matches the table above.8283## On Activation84851. Load config from `{project-root}/_bmad/skf/config.yaml` and resolve:86 - `project_name`, `user_name`, `communication_language`, `document_output_language`87 - `skills_output_folder`, `forge_data_folder`, `output_folder`, `sidecar_path`88892. **Compute run-scoped variables:**90 - `timestamp` ← UTC `YYYYMMDD-HHmmss` captured at activation time. Fixed for the entire workflow run; report.md reuses this when writing the result contract.91923. **Resolve `{headless_mode}`**: true if `--headless` or `-H` was passed as an argument, or if `headless_mode: true` in `{sidecar_path}/preferences.yaml`. Default: false.93944. **Resolve workflow customization.** Run:9596 ```bash97 python3 {project-root}/_bmad/scripts/resolve_customization.py \98 --skill {skill-root} --key workflow99 ```100101 The script merges the three customization layers per `bmad-customize`'s structural merge rules (scalars override, arrays append):102103 - `{skill-root}/customize.toml` — bundled defaults104 - `_bmad/custom/<skill-name>.toml` under `{project-root}` — team overrides (committed)105 - `_bmad/custom/<skill-name>.user.toml` under `{project-root}` — personal overrides (gitignored)106107 If the script fails or is missing, fall back to reading `{skill-root}/customize.toml` directly — the bundled defaults are an empty string for each path scalar.108109 Apply the path-scalar fallback now so stage files don't have to repeat the conditional logic. For each scalar, if the merged value is empty or absent, use the bundled default:110111 - `{refinementRulesPath}` ← `workflow.refinement_rules_path` if non-empty, else `references/refinement-rules.md`112 - `{outputFolderPath}` ← `workflow.output_folder_path` if non-empty, else `{output_folder}`113 - `{onCompleteCommand}` ← `workflow.on_complete` if non-empty, else empty (no-op — report.md skips the hook invocation entirely)114115 Stash all three as workflow-context variables. Stage files reference them directly — no conditional at the usage site.116117 Also apply the array surfaces (not silent no-ops): run `workflow.activation_steps_prepend` now, treat `workflow.persistent_facts` as standing context for the run (`file:`-prefixed entries load their file/glob contents as facts), then run `workflow.activation_steps_append` after activation.1181195. **Pre-flight config + write probe.** Assert both output paths are configured, then probe writability — order matters: an empty path makes `mkdir -p ""` fail, which would misreport a *missing config* (exit 3) as a *write failure* (exit 4) and collapse the distinction the Result Contract draws.120121 **Config-completeness (exit 3).** If `{outputFolderPath}` is empty: HALT (exit code 3, `halt_reason: "output-folder-unconfigured"`) — "`output_folder` is not configured in config.yaml. Add an `output_folder` path and re-run [RA]." If `{forge_data_folder}` is empty: HALT (exit code 3, `halt_reason: "forge-folder-unconfigured"`) — "`forge_data_folder` is not configured in config.yaml. Add a `forge_data_folder` path and re-run [RA]."122123 **Write probe (exit 4).** With both paths now non-empty, verify each is writable — a read-only mount, full disk, or permissions-denied path otherwise only surfaces at init.md §3c's RA state file write, by which point the user has already gone through input prompts:124125 ```bash126 for dir in "{outputFolderPath}" "{forge_data_folder}"; do127 mkdir -p "$dir" && \128 printf 'probe' > "$dir/.skf-write-probe" && \129 rm "$dir/.skf-write-probe"130 done131 ```132133 On any non-zero exit: HALT (exit code 4, `halt_reason: "write-failed"`). In headless mode, every HALT above emits the error envelope per **Result Contract (Headless)** with `refined_path: null`.1341356. Load, read the full file, and then execute `references/init.md` to begin the workflow.