aw-spec-cli 0.1.26 → 0.1.27

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.
Files changed (98) hide show
  1. package/assets/.agents/skills/appweaver/SKILL.md +7 -47
  2. package/assets/.appweaver/ORCH-DIALECT.md +13 -9
  3. package/assets/.appweaver/RULE-PARTITION.md +3 -3
  4. package/assets/.appweaver/STACK-PROFILES.md +188 -101
  5. package/assets/.appweaver/domain.json +1 -1
  6. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
  7. package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
  8. package/assets/.appweaver/orchestrator/README.md +120 -53
  9. package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
  10. package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
  11. package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
  12. package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +349 -0
  13. package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +381 -0
  14. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
  15. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
  16. package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
  17. package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
  18. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
  19. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +5 -5
  20. package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
  21. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +14 -14
  22. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
  23. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
  24. package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
  25. package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
  26. package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
  27. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +13 -13
  28. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
  29. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
  30. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
  31. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
  32. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
  33. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
  34. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +29 -28
  35. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +53 -53
  36. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
  37. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +3 -3
  38. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
  39. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
  40. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
  41. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
  42. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +2 -2
  43. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
  44. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
  45. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +284 -128
  46. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +224 -70
  47. package/assets/.appweaver/scripts/python/aw-foundation.py +809 -20
  48. package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
  49. package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
  50. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
  51. package/assets/.appweaver/scripts/python/aw-stack.py +195 -89
  52. package/assets/.appweaver/stack-profiles/angular.json +2 -1
  53. package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
  54. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +16 -3
  55. package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
  56. package/assets/.appweaver/stack-profiles/java-spring.json +12 -5
  57. package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
  58. package/assets/.appweaver/stack-profiles/node-express.json +8 -2
  59. package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
  60. package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
  61. package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
  62. package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
  63. package/assets/.appweaver/stacks.json +37 -1
  64. package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
  65. package/assets/.claude/skills/appweaver/SKILL.md +7 -46
  66. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
  67. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
  68. package/assets/foundations/foundation.spec.template.txt +73 -0
  69. package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +1 -1
  70. package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
  71. package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
  72. package/assets/guardrails/README.md +31 -17
  73. package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +5 -5
  74. package/assets/guardrails/{projects/dotnet-default-project → project-specific}/tech-rule-bindings.md +151 -114
  75. package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
  76. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
  77. package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
  78. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
  79. package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
  80. package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
  81. package/assets/guardrails/technology/nextjs/api-client.md +1 -1
  82. package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
  83. package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
  84. package/assets/guardrails/technology/nextjs/design-system.md +1 -1
  85. package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
  86. package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
  87. package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
  88. package/package.json +1 -1
  89. package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
  90. package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
  91. package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
  92. package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
  93. package/assets/.kilocode/agent.json +0 -28
  94. package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
  95. package/assets/.kilocode/workflows/appweaver.md +0 -55
  96. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
  97. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
  98. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/service/technical-requirements.md +0 -0
@@ -0,0 +1,88 @@
1
+ # AppWeaver launcher
2
+
3
+ Every agent's `/appweaver` command points here. These instructions are the same for
4
+ every agent; the launcher you came from only says which agent you are, or — in a
5
+ folder that several agents read — tells you to find yourself in the profile table.
6
+
7
+ Runs one converted `aw-spec-*` workflow on the shared, agent-agnostic engine. All orchestration and **all context management live in the workflow YAML + engine** (`.appweaver/orchestrator/orchestrator.py`): the interpreter assembles the COMPLETE payload (system + user) for every request; you never author generation context yourself. You run the interpreter, fulfill each request it hands you, and relay every human-facing interaction to the user.
8
+
9
+ Usage: `/appweaver <skill> [strategy] [input…]` — e.g. `/appweaver select-stack`, `/appweaver specify spawn Build an order API`, `/appweaver analyze-slice`.
10
+
11
+ - **Engine + workflows (common, shared by all agents):** `.appweaver/orchestrator/orchestrator.py`, `.appweaver/orchestrator/workflows/aw-spec-<skill>.orch.yaml`, shared modules in `.appweaver/orchestrator/modules/`, shared scripts in `.appweaver/scripts/`
12
+ - **Working directory:** run every command from the workspace root (the folder that contains `.appweaver/`).
13
+
14
+ ## Profile table
15
+
16
+ Find the row for the agent you are. Its profile is your transport profile: the CLI that `spawn` launches and the SDK that `sdk` / `sdk-apply` import. Read the profile's `note` before using it — it states that agent's limits (model name format, isolation, what must be installed and signed in).
17
+
18
+ | You are | Profile | `spawn` runs | `sdk` / `sdk-apply` |
19
+ |---|---|---|---|
20
+ | Claude Code | `.claude/agent.json` | `claude -p` | ✓ |
21
+ | Antigravity | `.agents/agent.json` | `agy` | ✓ |
22
+ | Kilo Code | `.kilo/agent.json` | `kilo run` | ✓ (Claude Agent SDK — needs Claude access) |
23
+ | Cursor | `.cursor/agent.json` | `cursor-agent -p` | — |
24
+ | GitHub Copilot | `.copilot/agent.json` | `copilot -p` | — |
25
+ | Devin Desktop / Devin CLI (formerly Windsurf) | `.devin/agent.json` | `devin -p` | — |
26
+ | Cline | `.cline/agent.json` | `cline` | — |
27
+ | Roo Code | `.roo/agent.json` | `roo --print` | — |
28
+ | opencode | `.opencode/agent.json` | `opencode run` | — |
29
+ | Factory Droid | `.factory/agent.json` | `droid exec` | — |
30
+ | Augment | `.augment/agent.json` | `auggie --print` | — |
31
+ | Continue | `.continue/agent.json` | `cn -p` | — |
32
+ | Kiro | `.kiro/agent.json` | `kiro-cli chat` | — |
33
+ | OpenAI Codex | `.codex/agent.json` | `codex exec` | — |
34
+ | Gemini CLI | `.gemini/agent.json` | `gemini -p` | — |
35
+ | Amp | `.amp/agent.json` | `amp -x` | — |
36
+ | any other agent | — | — | — |
37
+
38
+ ## Strategies
39
+
40
+ - **`agent`** (default) — YOU fulfill each generation through the checkpoint channel. Works for every agent and needs no profile.
41
+ - **`spawn`** — each generation runs in a fresh process of your agent's CLI, as your profile describes. Needs your row's profile and that CLI on PATH.
42
+ - **`sdk`** — an isolated SDK session generates and applies. Needs a profile with an `sdk` block.
43
+ - **`sdk-apply`** — an isolated SDK session generates read-only; YOU apply its output (pending kind `apply`). Needs a profile with an `sdk` block.
44
+
45
+ If the user names a strategy your row does not support — or you have no row and they name anything but `agent` — say so and stop.
46
+
47
+ ## Execution Steps
48
+
49
+ 1. **Parse Arguments** (`<skill> [strategy] [input…]`):
50
+ - `skill` (required): the aw-spec skill name, e.g. `select-stack`, `foundation`, `specify`, `design`, `implement`, `build`. Resolve the workflow file `.appweaver/orchestrator/workflows/aw-spec-<skill>.orch.yaml`. If it does not exist, list the available `aw-spec-*.orch.yaml` files in that folder and stop.
51
+ - `strategy` (optional, one of `agent`, `spawn`, `sdk`, `sdk-apply`; default `agent`): if the first word after the skill is one of these, it is the strategy. Always pass `--strategy <strategy>`.
52
+ - Everything after the strategy is the user input: pass it as `--input "<text>"` (omit when empty).
53
+ - `--agent-profile <your profile>` is required for `spawn`, `sdk`, and `sdk-apply` (`agent` needs no profile). If the SDK package isn't installed, add `--sdk-install`.
54
+ - **Always** pass `--checkpoint .appweaver/orchestrator/.state/<skill>.state.json` — for EVERY strategy. Converted skills contain interactive steps (questions, selections, hooks); the checkpoint is how they reach you and the user. Strategies only govern who generates.
55
+ - `spawn` may also add `--model <name>` (in the form your profile's `note` gives) and `--isolation bare|fresh` (only where your profile defines isolation args); `sdk`/`sdk-apply` accept `--model <name>`.
56
+
57
+ 2. **Run the Interpreter** in the terminal:
58
+ ```bash
59
+ python3 .appweaver/orchestrator/orchestrator.py \
60
+ .appweaver/orchestrator/workflows/aw-spec-<skill>.orch.yaml \
61
+ --strategy <strategy> \
62
+ --checkpoint .appweaver/orchestrator/.state/<skill>.state.json \
63
+ [--agent-profile <your profile>] # spawn, sdk, sdk-apply \
64
+ [--input "<user input>"] \
65
+ --json
66
+ ```
67
+
68
+ 3. **Handle the Suspend/Resume Loop** — the exit code tells you what happened:
69
+ - `0` — done. Go to step 4.
70
+ - `1` — stopped by a gate. Go to step 4.
71
+ - `2` — **suspended, NOT an error.** The interpreter is waiting for you. Do not debug, retry with other flags, or edit the workflow, engine, or state files. Read the printed `pending` JSON and dispatch on `pending.kind`; fulfill it, write the response to `pending.response_path`, then re-run the SAME command. Repeat until exit `0` or `1`.
72
+
73
+ Dispatch on `pending.kind`:
74
+ - **`ask`** — ask the USER the `prompt` with the listed `options` (use your question tool; without one, post the prompt and options in chat as a numbered list, say that more than one may be picked when `multi` is true, and END YOUR TURN — never answer it yourself). When the user answers, write the chosen answer as PLAIN TEXT to `response_path` (comma-separated values when `multi` is true).
75
+ - **`select`** — ask the USER to pick ONE of `options` (use your question tool; without one, post the options in chat as a numbered list and END YOUR TURN). When the user answers, write the chosen value as plain text to `response_path`.
76
+ - **`hook`** — run each MANDATORY hook in `hooks` in this conversation; optional hooks are at your discretion. Each hook names a slash command (`slash`) from an extension (`extension`); if your agent does not have that command, read `.appweaver/extensions/<extension>/commands/<slash without the leading />.md` and follow it. Then write `done` to `response_path`.
77
+ - **`author`** — read `system_path` + `user_path` and treat them as your ONLY standards and context. Author the COMPLETE content of the file named in `target` and write it — content ONLY, no commentary, no code fence — to `response_path`. Do NOT write the target file yourself; the interpreter does that.
78
+ - **`agent_generate`** — read `system_path` + `user_path`; perform the task YOURSELF with the listed `tools` within `permission_mode`; write your full final reply — ending with the required ```json fence — to `response_path`. `tools` uses Claude Code tool names (`Read`, `Write`, `Edit`, `Bash`, `Glob`, `Grep`); if yours differ, use your own equivalents.
79
+ - **`agent_query` / `agent_review`** — same as above but READ-ONLY (do not modify files); the reply must end with the required ```json fence.
80
+ - **`apply`** — an isolated generation already decided the changes: read `artifact_path` and write its file contents EXACTLY to the paths it names, then write the confirmation ```json fence to `response_path`.
81
+ - If `pending.note` is present, your previous response was rejected — follow the note and rewrite `response_path`.
82
+
83
+ 4. **Report**:
84
+ Report the final JSON (`status`, `outputs`, and any `reason`) to the user. On `stopped`, relay the gate message verbatim — it tells the user what to fix or run first.
85
+
86
+ ## Adding an agent
87
+
88
+ Add its profile (see `AGENT-PROFILE.md`), add its row to the profile table above, and give it a launcher in its own native format that points here and names that profile.
@@ -20,38 +20,68 @@ This engine is now the **only** pipeline that ships. The earlier declarative tie
20
20
  ## General vs. agent-specific (file layout)
21
21
 
22
22
  The transport **profile lives once at each agent's root** (`.claude/agent.json`,
23
- `.agents/agent.json`, `.kilocode/agent.json`), so every orchestrator skill for
24
- that agent shares it — no per-skill duplication. Only the thin launcher is
25
- per-skill.
23
+ `.agents/agent.json`, `.kilo/agent.json`, …), so every orchestrator skill for
24
+ that agent shares it — no per-skill duplication. The `/appweaver` instructions
25
+ live once too, in `LAUNCHER.md`; each agent's launcher is a thin pointer to it.
26
+ A launcher in a folder only one agent reads names that agent's profile; a
27
+ launcher in a folder several agents read (`.claude/skills/`, `.agents/skills/`)
28
+ names none, and the agent finds its row in `LAUNCHER.md`'s profile table.
26
29
 
27
30
  ```
28
31
  .appweaver/orchestrator/ ← GENERAL (shared by all agents)
29
32
  orchestrator.py engine (profile-driven; no agent hardcoded)
30
- workflows/aw-spec-demo.orch.yaml demo workflow (run: /appweaver demo)
33
+ LAUNCHER.md the /appweaver instructions + profile table (every launcher points here)
34
+ workflows/_smoke.orch.yaml CI smoke: every construct, mock, writes only to .smoke-out/
31
35
  AGENT-PROFILE.md the transport-profile schema
32
36
  README.md
33
37
 
34
38
  .claude/agent.json ← Claude Code profile (all its skills share this)
35
- .claude/skills/appweaver-demo/SKILL.md ← Claude Code launcher
39
+ .claude/skills/appweaver/SKILL.md ← launcher (shared folder: Copilot, Cursor, Kilo read it too)
36
40
  .agents/agent.json ← Antigravity profile
37
- .agents/skills/appweaver-demo/SKILL.md ← Antigravity launcher
38
- .kilocode/agent.json ← Kilo Code profile
39
- .kilocode/workflows/appweaver-demo.md ← Kilo Code launcher
41
+ .agents/skills/appweaver/SKILL.md ← launcher (shared folder: Codex, Gemini CLI, Amp, Devin, Copilot, Cursor, Kilo read it too)
42
+ .kilo/agent.json ← Kilo Code profile
43
+ .kilo/agents/appweaver-{edit,read}.md ← Kilo agents a spawned step runs as
44
+ .kilo/commands/appweaver.md ← Kilo Code launcher
45
+ .cursor/agent.json ← Cursor profile
46
+ .cursor/commands/appweaver.md ← Cursor launcher
47
+ .copilot/agent.json ← GitHub Copilot profile
48
+ .github/prompts/appweaver.prompt.md ← GitHub Copilot launcher
49
+ .devin/agent.json ← Devin profile (Devin Desktop, formerly Windsurf)
50
+ .devin/workflows/appweaver.md ← Devin launcher
51
+ .cline/agent.json ← Cline profile (not in .clinerules/: every file there is a rule)
52
+ .clinerules/workflows/appweaver.md ← Cline launcher (/appweaver.md)
53
+ .roo/agent.json ← Roo Code profile
54
+ .roo/commands/appweaver.md ← Roo Code launcher
55
+ .opencode/agent.json ← opencode profile
56
+ .opencode/agents/appweaver-{edit,read}.md ← opencode agents a spawned step runs as
57
+ .opencode/commands/appweaver.md ← opencode launcher
58
+ .factory/agent.json ← Factory Droid profile
59
+ .factory/commands/appweaver.md ← Factory Droid launcher
60
+ .augment/agent.json ← Augment profile
61
+ .augment/commands/appweaver.md ← Augment launcher
62
+ .continue/agent.json ← Continue profile
63
+ .continue/prompts/appweaver.md ← Continue launcher (invokable prompt)
64
+ .kiro/agent.json ← Kiro profile
65
+ .kiro/skills/appweaver/SKILL.md ← Kiro launcher
66
+ .codex/agent.json ← OpenAI Codex profile (launcher: .agents/skills/)
67
+ .gemini/agent.json ← Gemini CLI profile (launcher: .agents/skills/)
68
+ .amp/agent.json ← Amp profile (launcher: .agents/skills/)
69
+ .amp/settings-{edit,read}.json ← Amp permission sets a spawned step runs with
40
70
  ```
41
71
 
42
72
  ## Your diagram → this code
43
73
 
44
74
  | Diagram box | Where it lives |
45
75
  |---|---|
46
- | Agent skill launches the runtime | the per-agent launcher runs `orchestrator.py … --agent-profile <profile>` |
76
+ | Agent skill launches the runtime | the per-agent launcher points at `LAUNCHER.md`, which runs `orchestrator.py … --agent-profile <profile>` |
47
77
  | Python Workflow / Interpreter Runtime | `orchestrator.py` — `Orchestrator.run()` |
48
78
  | **Builds Complete Context** | `build_context` → `_assemble_system()` + `_assemble_user()` |
49
- | **Invoke (fresh generation)** | `agent_generate` → `_run_fresh()` → the profile's CLI |
79
+ | **Invoke (fresh generation)** | `agent_generate` → `_run_fresh()` → the profile's CLI (every code step in `workflows/aw-spec-implement.orch.yaml`; `_smoke`'s `gen_file` is the minimal one) |
50
80
  | Agent uses tools (Edit, Bash…) | tools/approval flags from the profile |
51
81
  | **Return structured result** | trailing ```` ```json {…} ```` block → `_extract_json()` → bound via `outputs:` |
52
82
  | Interpreter continues next step | `_run_steps()` / `_run_loop()` |
53
- | **Review the current output** | `agent_review` → a second fresh, read-only generation |
54
- | …continues | the `revise` loop in `workflows/aw-spec-demo.orch.yaml` |
83
+ | **Review the current output** | `agent_review` → a second fresh, read-only generation (`_smoke`'s `review_file` reviews what `gen_file` reported) |
84
+ | …continues | a `loop` (`while:` + `break`) around `agent_generate` → `agent_review` — the review→revise cycle |
55
85
 
56
86
  ## Why this overrides the launching agent's own context (your R6)
57
87
 
@@ -78,31 +108,37 @@ see below.)
78
108
  ## Run it
79
109
 
80
110
  Safe (default) — **no model calls**. Prints the exact payloads the fresh agent
81
- would receive (proof of isolation), simulates the writes, runs the whole loop:
111
+ would receive (proof of isolation), simulates the writes, runs the whole
112
+ workflow — including the `agent_generate` edit step and the `agent_review` of
113
+ what it wrote. `_smoke` has one `ask`, so it runs with `--non-interactive`:
82
114
 
83
115
  ```bash
84
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml # mock
85
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml --show-full
116
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml --non-interactive # mock
117
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml --non-interactive --show-full
86
118
  ```
87
119
 
88
120
  For real — pass an agent profile (implies `--transport real`):
89
121
 
90
122
  ```bash
91
123
  # Claude Code
92
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
93
- --agent-profile .claude/agent.json --isolation bare --model opus
124
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
125
+ --non-interactive --agent-profile .claude/agent.json --isolation bare --model opus
94
126
 
95
127
  # Antigravity (Gemini)
96
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
97
- --agent-profile .agents/agent.json --isolation fresh --model gemini-2.5-pro
128
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
129
+ --non-interactive --agent-profile .agents/agent.json --isolation fresh --model gemini-2.5-pro
98
130
 
99
- # Kilo Code (delegates generation to claude -p)
100
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
101
- --agent-profile .kilocode/agent.json --isolation fresh --model opus
131
+ # Kilo Code (kilo run; --model takes Kilo's provider/model form)
132
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
133
+ --non-interactive --agent-profile .kilo/agent.json --model <provider>/<model>
102
134
  ```
103
135
 
104
- Add `--dry-run` to print the exact command a profile would run **without
105
- executing it**. Output lands in `.appweaver/orchestrator/.demo-out/` (safe to delete).
136
+ Add `--dry-run` to print the exact command a profile would run for every model
137
+ step **without executing any of them**: each step then takes its mock result, so
138
+ the run carries on to the next. A dry run never writes an `agent_author` target
139
+ (a later `required_files` gate counts it as present) and never caches a result
140
+ in the checkpoint. Output lands in `.appweaver/orchestrator/.smoke-out/`
141
+ (gitignored, safe to delete).
106
142
 
107
143
  ## Execution strategies — `--strategy`, per-step `strategy:`
108
144
 
@@ -153,8 +189,8 @@ If spawning a second agent instance is impossible or unwanted, `--checkpoint`
153
189
  ports run-skill.py's **suspend/resume** method into this engine:
154
190
 
155
191
  ```bash
156
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
157
- --checkpoint .appweaver/orchestrator/.demo-out/demo.state.json --json
192
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
193
+ --checkpoint .appweaver/orchestrator/.state/smoke.state.json --json
158
194
  ```
159
195
 
160
196
  At each `agent_generate` / `agent_review` the interpreter writes the fully
@@ -166,10 +202,9 @@ the Bash call. The agent fulfills the request **in its own conversation**
166
202
  required ```` ```json ```` fence — to `<state>.response.md`, and re-runs the
167
203
  same command. Completed steps replay from the cache, so the run continues
168
204
  exactly where it suspended; on a terminal end the state file and sidecars are
169
- deleted. Launcher: the `appweaver-demo` skill/workflow handles this via its
170
- `sdk-apply` / `agent` strategies (step 3, the suspend/resume loop). The same
171
- loop works for any agent that can run bash and read/write files — including
172
- Kilo Code, natively, with no `claude` CLI.
205
+ deleted. Launcher: `LAUNCHER.md` step 3 (the suspend/resume loop), which every
206
+ agent's `/appweaver` follows. The same loop works for any agent that can run
207
+ bash and read/write files — it needs no profile and no extra CLI.
173
208
 
174
209
  **The trade-off, stated plainly:** the interpreter keeps 100% ownership of
175
210
  what goes *into* each payload, but the request executes inside the invoking
@@ -195,16 +230,39 @@ documented in `.appweaver/ORCH-DIALECT.md`.
195
230
  | Extra auth / CLI needed | yes (`claude`/`gemini` + key for `--bare`) | none |
196
231
  | Permission prompts / HITL | none (headless) | the agent's native ones |
197
232
 
198
- ## The three agents
233
+ ## The agents
199
234
 
200
- | Agent | Folder | Fresh-generation CLI | System block | Tools | Isolation |
201
- |---|---|---|---|---|---|
202
- | Claude Code | `.claude/` | `claude -p` | `--system-prompt` | `--tools` | `--bare` (needs `ANTHROPIC_API_KEY`) / `--setting-sources ""` |
203
- | Antigravity | `.agents/` | `gemini -p` | folded into prompt (no system flag) | `--approval-mode` | best-effort (no `--bare` equivalent) |
204
- | Kilo Code | `.kilocode/` | `claude -p` (no native headless CLI) | `--system-prompt` | `--tools` | `--bare` / `--setting-sources ""` |
205
-
206
- Adding a fourth agent = drop an `agent.json` + a launcher in its folder; no
207
- engine change. See `AGENT-PROFILE.md` for the schema.
235
+ | Agent | Profile | Fresh-generation CLI | Edit steps | Read-only steps |
236
+ |---|---|---|---|---|
237
+ | Claude Code | `.claude/` | `claude -p` (prompt on stdin) | `--tools <list> --permission-mode acceptEdits` | `--tools "" --permission-mode default` |
238
+ | Antigravity | `.agents/` | `agy -p` | `--mode accept-edits` | `--mode plan` |
239
+ | Kilo Code | `.kilo/` | `kilo run` (prompt on stdin) | `--agent appweaver-edit` | `--agent appweaver-read` |
240
+ | Cursor | `.cursor/` | `cursor-agent -p` | `--force` | `--mode ask` |
241
+ | GitHub Copilot | `.copilot/` | `copilot -p` | `--allow-all-tools` | no flag |
242
+ | Devin (formerly Windsurf) | `.devin/` | `devin -p` | `--permission-mode dangerous` | no flag (Devin's default `normal` mode) |
243
+ | Cline | `.cline/` | `cline` | act mode, `--auto-approve true` | `--plan` |
244
+ | Roo Code | `.roo/` | `roo --print` | `--mode code` | `--mode ask` |
245
+ | opencode | `.opencode/` | `opencode run --auto` | `--agent appweaver-edit` | `--agent appweaver-read` |
246
+ | Factory Droid | `.factory/` | `droid exec -o json` (prompt on stdin) | `--auto high` | no flag (read-only by default) |
247
+ | Augment | `.augment/` | `auggie --quiet --print` | no flag | `--ask` |
248
+ | Continue | `.continue/` | `cn --silent -p` | `--auto` | `--readonly` |
249
+ | Kiro | `.kiro/` | `kiro-cli chat --no-interactive` (prompt on stdin) | `--trust-all-tools` | `--trust-tools=read,grep` |
250
+ | OpenAI Codex | `.codex/` | `codex exec` (prompt on stdin) | `--sandbox workspace-write` | `--sandbox read-only` |
251
+ | Gemini CLI | `.gemini/` | `gemini -o json -p` | `--approval-mode auto_edit` | `--approval-mode plan` |
252
+ | Amp | `.amp/` | `amp -x` (prompt on stdin) | `--settings-file .amp/settings-edit.json` | `--settings-file .amp/settings-read.json` |
253
+
254
+ Only Claude Code takes the system block as a flag (`--system-prompt`), limits
255
+ tools per step (`--tools`) and isolates a generation (`--bare`, which needs
256
+ `ANTHROPIC_API_KEY`, or `--setting-sources ""`). Every other profile folds the
257
+ system block into the prompt, and its isolation is best-effort: the agent's own
258
+ rules files still load. Only Claude Code, Antigravity and Kilo Code have an
259
+ `sdk` block. Each profile's `note` gives that agent's limits.
260
+
261
+ Adding an agent = drop an `agent.json` + a thin launcher in its folder that
262
+ points at `LAUNCHER.md`, add the agent's row to `LAUNCHER.md`'s profile
263
+ table, and add its folder to the inventory's `KIT_AGENT_DIRS`
264
+ (`.appweaver/scripts/python/aw-inventory.py`); no engine change. See
265
+ `AGENT-PROFILE.md` for the schema and the full steps.
208
266
 
209
267
  ## Invoking from an agent (the top of your diagram)
210
268
 
@@ -213,7 +271,7 @@ agent's *only* job is to run the orchestrator and relay the JSON. It **never
213
271
  generates**; its conversation **never** enters a model request.
214
272
 
215
273
  ```
216
- User → /appweaver-demo → (agent runs) orchestrator.py --agent-profile <its profile>
274
+ User → /appweaver <skill> → (agent runs) orchestrator.py --agent-profile <its profile>
217
275
  → interpreter builds context → spawns a fresh CLI per step (isolated)
218
276
  → interpreter reviews + continues → agent reports final JSON
219
277
  ```
@@ -240,8 +298,13 @@ the context leak this design removes, and one reason that tier was retired.
240
298
  - `loop` (`while:` + `max_iterations:`) with `break` (+ `condition:`) — the
241
299
  review→revise cycle.
242
300
 
301
+ `_smoke.orch.yaml` runs one `agent_generate` (`gen_file`) and one
302
+ `agent_review` (`review_file`) of what it wrote, gated on `files[]` being
303
+ non-empty and on `pass`; with no model, the mock writes `SmokeGenerated.cs`
304
+ under `.smoke-out/` and the review passes when the reported files exist.
305
+
243
306
  The engine now implements the FULL dialect the `aw-spec-*` conversions need on
244
- top of these demo actions: `execute_script`, `verify_context`,
307
+ top of these actions: `execute_script`, `verify_context`,
245
308
  `load_standards` (sticky system prefix), `agent_author` (interpreter-owned
246
309
  `output_target`, read-only generation), `agent_query` (generic structured
247
310
  JSON), `ask`/`user_select` (HITL via checkpoint), `dispatch_hooks`, `include`
@@ -282,19 +345,23 @@ at the top of this file).
282
345
  HITL — IS now ported; see `.appweaver/ORCH-DIALECT.md`.)
283
346
 
284
347
 
285
- # spawn (Strategy 3) — demo skill
286
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
287
- --strategy spawn --agent-profile .claude/agent.json --isolation bare --json
348
+ ## Each strategy on `_smoke`
288
349
 
289
- # sdk (Strategy 1) — demo skill
290
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
291
- --strategy sdk --agent-profile .claude/agent.json --model opus --json
350
+ ```bash
351
+ # spawn (Strategy 3)
352
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
353
+ --non-interactive --strategy spawn --agent-profile .claude/agent.json --isolation bare --json
354
+
355
+ # sdk (Strategy 1)
356
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
357
+ --non-interactive --strategy sdk --agent-profile .claude/agent.json --model opus --json
292
358
 
293
- # sdk-apply (Strategy 2) — demo skill, then follow the suspend/resume loop
294
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
359
+ # sdk-apply (Strategy 2) — then follow the suspend/resume loop
360
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
295
361
  --strategy sdk-apply --agent-profile .claude/agent.json \
296
- --checkpoint .appweaver/orchestrator/.demo-out/demo.state.json --json
362
+ --checkpoint .appweaver/orchestrator/.state/smoke.state.json --json
297
363
 
298
- # agent (Strategy 4) — demo skill, then follow the suspend/resume loop
299
- python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml \
300
- --strategy agent --checkpoint .appweaver/orchestrator/.demo-out/demo.state.json --json
364
+ # agent (Strategy 4) — then follow the suspend/resume loop
365
+ python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/_smoke.orch.yaml \
366
+ --strategy agent --checkpoint .appweaver/orchestrator/.state/smoke.state.json --json
367
+ ```
@@ -1,6 +1,6 @@
1
1
  """claude-agent-sdk adapter — a shared SDK adapter, loaded by the
2
2
  aw-orchestrator engine when an agent profile's `sdk.adapter` points here
3
- (both .claude/agent.json and .kilocode/agent.json do). Adapters live in this
3
+ (both .claude/agent.json and .kilo/agent.json do). Adapters live in this
4
4
  library keyed by SDK, not by agent: everything claude-agent-sdk-specific is
5
5
  HERE, the engine ships no SDK code of its own, and each profile declares
6
6
  which adapter drives its SDK.
@@ -45,13 +45,15 @@ workflow:
45
45
  - { name: dg_rulemap_exists, from: "$.rulemap_exists" }
46
46
  - { name: dg_candidates, from: "$.candidates" }
47
47
 
48
- # 2. Domain gate — only when the domain/domain-rule-bindings is missing.
48
+ # 2. Domain gate — only when the project or its domain-rule-bindings.md is missing.
49
49
  - id: gate
50
50
  action: ask
51
51
  condition: "{{dg_rulemap_exists}} == false"
52
52
  prompt: >
53
- Domain is not set or its rule files are missing (domain '{{domain}}').
54
- Continue with technical standards only, or exit to run /appweaver select-domain?
53
+ No domain rule map found for project '{{domain}}': .appweaver/domain.json must name a
54
+ folder under guardrails/ that holds domain-rule-bindings.md (project-specific by default;
55
+ /appweaver select-domain lists the folders that qualify). Continue with technical
56
+ standards only, or exit to fix it?
55
57
  options: ["continue", "exit"]
56
58
  answer_var: dg_gate
57
59
  - id: gate_stop
@@ -60,7 +62,7 @@ workflow:
60
62
  require_value: dg_gate
61
63
  equals: "continue"
62
64
  on_mismatch: stop
63
- on_mismatch_message: "Exited — run /appweaver select-domain (or fix the domain folder) and re-run."
65
+ on_mismatch_message: "Exited — run /appweaver select-domain, or set \"domain\" in .appweaver/domain.json to a folder under guardrails/ that holds domain-rule-bindings.md (project-specific by default), then re-run."
64
66
 
65
67
  # 3. Selection box — only when a rule map with candidates exists.
66
68
  - id: select_mode
@@ -0,0 +1,237 @@
1
+ # =============================================================================
2
+ # foundation-lane (orchestrator) — scaffold ONE declared lane
3
+ #
4
+ # Included by aw-spec-foundation once per lane kind — backend first, then frontend — with
5
+ # that lane's fields passed through `with:`. It answers "what is this lane built from?"
6
+ # and hands off:
7
+ #
8
+ # 1. Can the lane take a foundation — does it run its commands inside its lane root folder
9
+ # and keep its tests there? If not, it is reported and passed over. Then: does it
10
+ # already hold files? If so, ask to overwrite them; "no" skips the lane and nothing
11
+ # else is asked. Each lane is asked on its own.
12
+ # 2. List what fits the lane: every pack and spec under foundations/<ecosystem>/ whose
13
+ # `# kind:` / `# profiles:` header admits this lane, then [manual spec] and [skip].
14
+ # 3. Pick one. A fast-path name (`/appweaver foundation VerticalSlice App`) preselects
15
+ # its entry in whichever lane lists it.
16
+ # 4. pack -> foundation-pack (unpack the verified bundle, as before)
17
+ # spec | manual spec -> foundation-spec (an agent builds the project from the spec)
18
+ # skip -> nothing is written.
19
+ #
20
+ # Every refusal in here and in the two route modules RETURNS rather than stops, so the
21
+ # caller always reaches the next lane; the reason is in fl_status, which the caller
22
+ # reports per lane at the end of the run.
23
+ #
24
+ # Inputs (via include `with:`):
25
+ # fl_kind, fl_lane_id, fl_profile, fl_title, fl_language, fl_ecosystem,
26
+ # fl_source_path, fl_test_path, fl_workdir, fl_build
27
+ # Shared with the caller: USER_INPUT (the fast path) and `app` (asked once per run, the
28
+ # first time a lane needs it, and reused by the next lane).
29
+ # Produces: fl_status, fl_route, fl_name, fl_spec_path, fl_files, and fl_overwrite ("yes"
30
+ # when the lane already had files and the operator agreed to overwrite them), which the
31
+ # two route modules read.
32
+ # =============================================================================
33
+
34
+ name: foundation-lane
35
+ dialect: aw-spec.orchestrator/v1
36
+
37
+ scripts:
38
+ actions:
39
+ sh: .appweaver/scripts/bash/aw-spec-actions.sh
40
+ ps1: .appweaver/scripts/powershell/aw-spec-actions.ps1
41
+
42
+ workflow:
43
+
44
+ # 0. Vars are shared across the two includes; start this lane clean.
45
+ - id: fl_reset
46
+ action: set
47
+ vars:
48
+ fl_status: "not scaffolded"
49
+ fl_route: ""
50
+ fl_name: ""
51
+ fl_spec_file: ""
52
+ fl_spec_path: ""
53
+ fl_files: ""
54
+ fl_has_files: ""
55
+ fl_files_summary: ""
56
+ fl_self_contained: ""
57
+ fl_shape_reason: ""
58
+ fl_overwrite_answer: ""
59
+ fl_overwrite: ""
60
+ fl_overwrite_note: ""
61
+ fl_go: "true"
62
+ fl_spec_route: ""
63
+
64
+ - id: fl_has_root
65
+ action: verify_context
66
+ require_non_empty: fl_source_path
67
+ on_empty: return
68
+ message_var: fl_status
69
+ on_empty_message: "not scaffolded — lane `{{fl_lane_id}}` declares no lane root folder in .appweaver/stacks.json; re-run /appweaver select-stack and give it its lane root folder"
70
+
71
+ # 1. Does the lane already hold files? Any file in its lane root folder or test path counts,
72
+ # whatever stack wrote it, and so do its build files where its commands run when that
73
+ # is outside the lane (a .NET solution at the repo root). Asked BEFORE the pick list,
74
+ # so "no" skips this lane with nothing else asked and the run moves on to the next one.
75
+ # The first option is the non-interactive default, so an unattended run never
76
+ # overwrites. The answer key carries the lane kind, so a scripted run answers each lane
77
+ # on its own: --answer fl_overwrite_backend=yes --answer fl_overwrite_frontend=no.
78
+ - id: fl_files_check
79
+ action: execute_script
80
+ script: { ref: actions }
81
+ subcommand: foundation-lane-files
82
+ args: ["--source", "{{fl_source_path}}", "--test", "{{fl_test_path}}", "--workdir", "{{fl_workdir}}", "--profile", "{{fl_profile}}"]
83
+ outputs:
84
+ - { name: fl_has_files, from: "$.has_files" }
85
+ - { name: fl_files_summary, from: "$.summary" }
86
+ - { name: fl_self_contained, from: "$.self_contained" }
87
+ - { name: fl_shape_reason, from: "$.shape_reason" }
88
+
89
+ # A foundation is a complete project that lands INSIDE the lane root folder — build files,
90
+ # source and tests — so the lane has to run its commands there and keep its tests there.
91
+ # A lane declared the classic way (code in src/, solution and tests/ at the repo root)
92
+ # suits existing code but would get a project its own build cannot find; it is reported
93
+ # here, before anything is asked, and the run moves on to the next lane.
94
+ - id: fl_shape_gate
95
+ action: verify_context
96
+ require_true: fl_self_contained
97
+ on_false: return
98
+ message_var: fl_status
99
+ on_false_message: "not scaffolded — {{fl_shape_reason}}"
100
+
101
+ - id: fl_ask_overwrite
102
+ action: ask
103
+ condition: "{{fl_has_files}} == true"
104
+ prompt: >
105
+ {{fl_kind}} lane `{{fl_lane_id}}` ({{fl_profile}}) already has files — {{fl_files_summary}}.
106
+ Scaffolding it writes into these folders and replaces files with the same path; files
107
+ with other names stay, and nothing is deleted. Overwrite?
108
+ options: ["no — skip this lane", "yes — overwrite"]
109
+ answer_key: "fl_overwrite_{{fl_kind}}"
110
+ answer_var: fl_overwrite_answer
111
+
112
+ # The answer is free text from the launcher: the full option and a bare `yes` both count.
113
+ - id: fl_overwrite_option
114
+ action: set
115
+ condition: "{{fl_overwrite_answer}} == yes — overwrite"
116
+ vars: { fl_overwrite: "yes" }
117
+
118
+ - id: fl_overwrite_short
119
+ action: set
120
+ condition: "{{fl_overwrite_answer}} == yes"
121
+ vars: { fl_overwrite: "yes" }
122
+
123
+ - id: fl_overwrite_gate
124
+ action: verify_context
125
+ condition: "{{fl_has_files}} == true"
126
+ require_value: fl_overwrite
127
+ equals: "yes"
128
+ on_mismatch: return
129
+ message_var: fl_status
130
+ on_mismatch_message: "skipped — the lane already has files ({{fl_files_summary}}) and overwriting them was declined"
131
+
132
+ - id: fl_overwrite_noted
133
+ action: set
134
+ condition: "{{fl_overwrite}} == yes"
135
+ vars: { fl_overwrite_note: " It already has files, and you chose to overwrite them." }
136
+
137
+ # 2. What fits this lane.
138
+ - id: fl_list
139
+ action: execute_script
140
+ script: { ref: actions }
141
+ subcommand: foundation-list
142
+ args: ["--kind", "{{fl_kind}}", "--profile", "{{fl_profile}}", "--ecosystem", "{{fl_ecosystem}}", "--lane-id", "{{fl_lane_id}}", "--args", "{{USER_INPUT}}"]
143
+ outputs:
144
+ - { name: fl_options, from: "$.options" }
145
+ - { name: fl_count, from: "$.count" }
146
+ - { name: fl_all, from: "$.all_foundations" }
147
+ - { name: fl_preselect, from: "$.preselect_option" }
148
+
149
+ # 3. Pick. There are always at least two options ([manual spec] and [skip]), so this
150
+ # always asks unless the fast path named an entry this lane offers.
151
+ - id: fl_pick
152
+ action: user_select
153
+ prompt: >
154
+ {{fl_kind}} lane `{{fl_lane_id}}` — {{fl_title}} at {{fl_source_path}}.{{fl_overwrite_note}}
155
+ What should it be scaffolded from? A [pack] is a verified project unpacked as-is; a
156
+ [spec] describes a project the agent builds into the lane; [manual spec] lets you give
157
+ that description yourself; [skip] leaves the lane untouched.
158
+ ({{fl_count}} of the foundations shipped fit this lane; all of them: {{fl_all}})
159
+ options_from_variable: fl_options
160
+ preselect_from: fl_preselect
161
+ outputs:
162
+ - { name: fl_selection, from: selection }
163
+
164
+ - id: fl_choice
165
+ action: execute_script
166
+ script: { ref: actions }
167
+ subcommand: foundation-choice
168
+ args: ["--selection", "{{fl_selection}}", "--kind", "{{fl_kind}}", "--profile", "{{fl_profile}}", "--ecosystem", "{{fl_ecosystem}}"]
169
+ outputs:
170
+ - { name: fl_choice_ok, from: "$.ok" }
171
+ - { name: fl_route, from: "$.route" }
172
+ - { name: fl_name, from: "$.name" }
173
+ - { name: fl_spec_file, from: "$.file" }
174
+ - { name: fl_choice_msg, from: "$.reason" }
175
+
176
+ - id: fl_choice_gate
177
+ action: verify_context
178
+ require_true: fl_choice_ok
179
+ on_false: return
180
+ message_var: fl_status
181
+ on_false_message: "not scaffolded — {{fl_choice_msg}}"
182
+
183
+ - id: fl_skip
184
+ action: set
185
+ condition: "{{fl_route}} == skip"
186
+ vars: { fl_go: "" }
187
+
188
+ - id: fl_skip_gate
189
+ action: verify_context
190
+ require_true: fl_go
191
+ on_false: return
192
+ message_var: fl_status
193
+ on_false_message: "skipped — left as it is, by choice"
194
+
195
+ # 4. The project name — asked once per run, the first time a lane needs it, unless the
196
+ # fast path gave it. The next lane reuses it.
197
+ - id: fl_ask_app
198
+ action: ask
199
+ condition: "{{app}} == "
200
+ prompt: >
201
+ Enter the project (application) name, e.g. AppWeaver.Health. A pack renames its
202
+ sentinel to it; a spec build names the project after it, in the form the stack uses.
203
+ It is asked once and used for every lane in this run.
204
+ answer_var: app_typed
205
+
206
+ - id: fl_app_from_typed
207
+ action: set
208
+ condition: "{{app}} == "
209
+ vars: { app: "{{app_typed}}" }
210
+
211
+ - id: fl_app_gate
212
+ action: verify_context
213
+ require_non_empty: app
214
+ on_empty: return
215
+ message_var: fl_status
216
+ on_empty_message: "not scaffolded — no project name was given"
217
+
218
+ # 5. Hand off. The engine has no OR, so the two spec routes set one flag.
219
+ - id: fl_route_spec
220
+ action: set
221
+ condition: "{{fl_route}} == spec"
222
+ vars: { fl_spec_route: "true" }
223
+
224
+ - id: fl_route_manual
225
+ action: set
226
+ condition: "{{fl_route}} == manual"
227
+ vars: { fl_spec_route: "true" }
228
+
229
+ - id: pack
230
+ action: include
231
+ condition: "{{fl_route}} == pack"
232
+ module: .appweaver/orchestrator/modules/foundation-pack.orch.yaml
233
+
234
+ - id: spec
235
+ action: include
236
+ condition: "{{fl_spec_route}} == true"
237
+ module: .appweaver/orchestrator/modules/foundation-spec.orch.yaml