aw-spec-cli 0.1.26 → 0.1.28

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 (137) 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 +11 -12
  4. package/assets/.appweaver/STACK-PROFILES.md +260 -108
  5. package/assets/.appweaver/domain.json +1 -1
  6. package/assets/.appweaver/interpreter/run-skill.py +28 -7
  7. package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
  8. package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
  9. package/assets/.appweaver/orchestrator/README.md +120 -53
  10. package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
  11. package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +17 -7
  12. package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
  13. package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
  14. package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +392 -0
  15. package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +548 -0
  16. package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
  17. package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
  18. package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
  19. package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +5 -4
  20. package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +3 -1
  21. package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
  22. package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
  23. package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +21 -13
  24. package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
  25. package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +28 -31
  26. package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
  27. package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
  28. package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
  29. package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +4 -1
  30. package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +6 -4
  31. package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
  32. package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
  33. package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +17 -16
  34. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +7 -1
  35. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +7 -1
  36. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
  37. package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
  38. package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
  39. package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
  40. package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
  41. package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
  42. package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
  43. package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +253 -44
  44. package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +72 -71
  45. package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
  46. package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +38 -14
  47. package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
  48. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
  49. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
  50. package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
  51. package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +3 -3
  52. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
  53. package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
  54. package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +371 -131
  55. package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +293 -76
  56. package/assets/.appweaver/scripts/python/aw-foundation.py +885 -20
  57. package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
  58. package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
  59. package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
  60. package/assets/.appweaver/scripts/python/aw-stack.py +676 -99
  61. package/assets/.appweaver/stack-profiles/angular.json +2 -1
  62. package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
  63. package/assets/.appweaver/stack-profiles/dotnet-webapi.json +18 -3
  64. package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
  65. package/assets/.appweaver/stack-profiles/java-spring.json +14 -5
  66. package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
  67. package/assets/.appweaver/stack-profiles/node-express.json +8 -2
  68. package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
  69. package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
  70. package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
  71. package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
  72. package/assets/.appweaver/stacks.json +40 -1
  73. package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
  74. package/assets/.appweaver/templates/delta-design-template.md +7 -5
  75. package/assets/.appweaver/templates/design-template.md +3 -0
  76. package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
  77. package/assets/.appweaver/templates/ui-design-template.md +6 -4
  78. package/assets/.claude/skills/appweaver/SKILL.md +7 -46
  79. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
  80. package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.lane.json +6 -0
  81. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
  82. package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.lane.json +6 -0
  83. package/assets/foundations/foundation.spec.template.txt +98 -0
  84. package/assets/foundations/java/Hexagonal/Hexagonal.lane.json +6 -0
  85. package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +8 -1
  86. package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
  87. package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
  88. package/assets/guardrails/README.md +31 -17
  89. package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +25 -13
  90. package/assets/guardrails/project-specific/tech-rule-bindings.md +296 -0
  91. package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
  92. package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
  93. package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
  94. package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
  95. package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
  96. package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
  97. package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
  98. package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
  99. package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
  100. package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
  101. package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
  102. package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
  103. package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
  104. package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
  105. package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
  106. package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
  107. package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
  108. package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
  109. package/assets/guardrails/technology/nextjs/api-client.md +1 -1
  110. package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
  111. package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
  112. package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
  113. package/assets/guardrails/technology/nextjs/client-security.md +1 -1
  114. package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
  115. package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
  116. package/assets/guardrails/technology/nextjs/design-system.md +1 -1
  117. package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
  118. package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
  119. package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
  120. package/assets/guardrails/technology/nextjs/i18n.md +1 -1
  121. package/assets/guardrails/technology/nextjs/observability.md +1 -1
  122. package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
  123. package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
  124. package/assets/guardrails/technology/nextjs/state-management.md +1 -1
  125. package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
  126. package/package.json +1 -1
  127. package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
  128. package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
  129. package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
  130. package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
  131. package/assets/.kilocode/agent.json +0 -28
  132. package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
  133. package/assets/.kilocode/workflows/appweaver.md +0 -55
  134. package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +0 -271
  135. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
  136. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
  137. /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/service/technical-requirements.md +0 -0
@@ -1 +1 @@
1
- {"domain":""}
1
+ {"domain":"project-specific"}
@@ -62,13 +62,18 @@ def _indent(line):
62
62
 
63
63
 
64
64
  def _strip_comment(s):
65
- """Strip a trailing ' #...' comment that is outside quotes/flow."""
65
+ """Strip a trailing ' #...' comment that is outside quotes/flow. Inside double
66
+ quotes a backslash escapes the next character, so \\" does not end the string."""
66
67
  out, i, depth = [], 0, 0
67
68
  quote = None
68
69
  while i < len(s):
69
70
  c = s[i]
70
71
  if quote:
71
72
  out.append(c)
73
+ if quote == '"' and c == "\\" and i + 1 < len(s):
74
+ out.append(s[i + 1])
75
+ i += 2
76
+ continue
72
77
  if c == quote:
73
78
  quote = None
74
79
  elif c in ("'", '"'):
@@ -93,6 +98,9 @@ def _scalar(tok):
93
98
  if tok == "" or tok == "~" or tok.lower() == "null":
94
99
  return None
95
100
  if len(tok) >= 2 and tok[0] == tok[-1] and tok[0] in "'\"":
101
+ if tok[0] == '"':
102
+ # A double-quoted value reads \" as " and \\ as \, as YAML does.
103
+ return re.sub(r'\\(["\\])', r"\1", tok[1:-1])
96
104
  return tok[1:-1]
97
105
  low = tok.lower()
98
106
  if low == "true":
@@ -140,7 +148,9 @@ def _parse_flow(s):
140
148
  while pos[0] < len(s):
141
149
  ch = s[pos[0]]
142
150
  if quote:
143
- if ch == quote:
151
+ if quote == '"' and ch == "\\":
152
+ pos[0] += 1 # the escaped character never closes the quote
153
+ elif ch == quote:
144
154
  quote = None
145
155
  elif ch in "'\"":
146
156
  quote = ch
@@ -328,12 +338,23 @@ def _parse_block_scalar(lines, parent_indent, folded, chomp):
328
338
  trailing += 1
329
339
 
330
340
  if folded:
331
- text = ""
332
- for i, ln in enumerate(block):
333
- if i == 0:
334
- text = ln
341
+ # YAML folding: one line break between two lines becomes a space, a line break
342
+ # followed by k empty lines becomes k newlines, and the break before or after a
343
+ # more-indented line is kept as it is.
344
+ parts, prev, empties = [], None, 0
345
+ for ln in block:
346
+ if ln == "":
347
+ empties += 1
348
+ continue
349
+ if prev is None:
350
+ parts.append("\n" * empties)
351
+ elif prev[:1] not in " \t" and ln[:1] not in " \t":
352
+ parts.append("\n" * empties if empties else " ")
335
353
  else:
336
- text += ("\n" if (block[i - 1] == "" or ln == "") else " ") + ln
354
+ parts.append("\n" * (empties + 1))
355
+ parts.append(ln)
356
+ prev, empties = ln, 0
357
+ text = "".join(parts)
337
358
  else:
338
359
  text = "\n".join(block)
339
360
 
@@ -9,11 +9,27 @@ for that agent; the engine that consumes it is the *general* file in `.appweaver
9
9
  ```
10
10
  .appweaver/orchestrator/orchestrator.py ← general engine (reads a profile)
11
11
  .appweaver/orchestrator/adapters/*.py ← shared SDK adapters (one per SDK, not per agent)
12
- .claude/agent.json ← Claude Code profile (claude -p / claude-agent-sdk)
13
- .agents/agent.json ← Antigravity profile (agy -p / google-antigravity)
14
- .kilocode/agent.json ← Kilo Code profile (delegates to claude)
12
+ .claude/agent.json ← Claude Code profile (claude -p / claude-agent-sdk)
13
+ .agents/agent.json ← Antigravity profile (agy -p / google-antigravity)
14
+ .kilo/agent.json ← Kilo Code profile (kilo run / claude-agent-sdk)
15
+ .cursor/agent.json ← Cursor profile (cursor-agent -p)
16
+ .copilot/agent.json ← GitHub Copilot profile (copilot -p)
17
+ .devin/agent.json ← Devin profile (devin -p)
18
+ .cline/agent.json ← Cline profile (cline)
19
+ .roo/agent.json ← Roo Code profile (roo --print)
20
+ .opencode/agent.json ← opencode profile (opencode run)
21
+ .factory/agent.json ← Factory Droid profile (droid exec)
22
+ .augment/agent.json ← Augment profile (auggie --print)
23
+ .continue/agent.json ← Continue profile (cn -p)
24
+ .kiro/agent.json ← Kiro profile (kiro-cli chat)
25
+ .codex/agent.json ← OpenAI Codex profile (codex exec)
26
+ .gemini/agent.json ← Gemini CLI profile (gemini -p)
27
+ .amp/agent.json ← Amp profile (amp -x)
15
28
  ```
16
29
 
30
+ Only the first three have an `sdk` block; the rest support the `agent` and
31
+ `spawn` strategies.
32
+
17
33
  The launcher passes its profile with `--agent-profile <path>` (which implies
18
34
  `--transport real`).
19
35
 
@@ -60,7 +76,7 @@ options). Adapters are keyed by SDK, not by agent:
60
76
  `adapters/google_antigravity.py` maps the neutral permission modes onto
61
77
  Antigravity policies and drives `Agent` / `LocalAgentConfig` (used by
62
78
  `.agents`), while `adapters/claude_agent_sdk.py` drives `query` /
63
- `ClaudeAgentOptions` (shared by `.claude` and `.kilocode`, whose SDK is the
79
+ `ClaudeAgentOptions` (shared by `.claude` and `.kilo`, whose SDK is the
64
80
  same) — none of which the engine knows about; it only follows the profile's
65
81
  `sdk.adapter` pointer.
66
82
 
@@ -87,11 +103,23 @@ When `system` is `"prepend"`, the system block is folded into the prompt
87
103
  ## Adding a new agent
88
104
 
89
105
  1. Drop an `agent.json` at that agent's root (`.<agent>/agent.json`) describing its CLI.
90
- 2. Add a launcher in that agent's native format that calls
91
- `orchestrator.py … --agent-profile .<agent>/agent.json`.
92
- 3. For the `sdk`/`sdk-apply` strategies, add an `sdk` block and point
106
+ 2. Add the agent's row to the profile table in `.appweaver/orchestrator/LAUNCHER.md`.
107
+ The launchers in folders several agents read (`.claude/skills/`, `.agents/skills/`)
108
+ name no agent; an agent loading one of them finds its profile in that table.
109
+ 3. Add a launcher in that agent's native format that points at `LAUNCHER.md` and
110
+ names `.<agent>/agent.json` as the agent's profile — `.cursor/commands/appweaver.md`
111
+ is the shortest example.
112
+ 4. For the `sdk`/`sdk-apply` strategies, add an `sdk` block and point
93
113
  `sdk.adapter` at the matching adapter in `.appweaver/orchestrator/adapters/`
94
114
  — or drop a new adapter there first if that SDK has none yet.
95
-
96
- No engine change required. Verify with `--dry-run` (prints the exact command
97
- without executing).
115
+ 5. Add the agent's folder (and its launcher folder, if different) to `KIT_AGENT_DIRS`
116
+ in `.appweaver/scripts/python/aw-inventory.py`, so a brownfield inventory does not
117
+ read the kit's files as the project's own. When the launcher sits in a folder the
118
+ project also uses (as `.github/` holds its CI), add the launcher's exact path to
119
+ `KIT_AGENT_FILES` instead.
120
+
121
+ No engine change required. Verify with `--dry-run` on `_smoke.orch.yaml`
122
+ (`--non-interactive --strategy spawn --agent-profile .<agent>/agent.json --dry-run`):
123
+ it prints the exact command the profile builds for every model step — the
124
+ read-only `agent_query`, `agent_author` and `agent_review`, and the `agent_generate`
125
+ edit step — without executing any of them.
@@ -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.
@@ -130,6 +130,9 @@ workflow:
130
130
  # the context's CANONICAL model — the aggregate root,
131
131
  # its entities and its invariants live here, not in the
132
132
  # spec and not in this plan.
133
+ - { path: .appweaver/memory/constitution.technical.md, optional: true }
134
+ # the lane's ratified technology base, the same one
135
+ # the master plan is authored under — no domain.
133
136
  - { path: "{{cr_dir}}/delta-slice-analyze-report.md", optional: true }
134
137
  # WHAT THE LAST GATE FOUND, when this change
135
138
  # has already been through analyze-slice-delta.
@@ -191,7 +194,9 @@ workflow:
191
194
  lane" with every addition or change to this feature's published surface, as field
192
195
  shapes. That table is the only part of this document the frontend delta plan may
193
196
  bind against; a contract the UI needs and this document never states becomes a
194
- client-side workaround. "None" when the surface is unchanged.
197
+ client-side workaround. "None" when the surface is unchanged. Each row carries the
198
+ endpoint's operation id: a changed endpoint keeps the one the master plan gives
199
+ it, and a new endpoint gets one unique across the service.
195
200
  - Stay technology-agnostic (no code) and keep the master's form: behaviour as
196
201
  signatures + pre/post/invariant/raises, contracts as field shapes.
197
202
  - TWO CASES — decide from the delta-spec in context:
@@ -208,11 +213,12 @@ workflow:
208
213
 
209
214
  # ══════════ THE LANE SWAP — the frontend's rules replace the backend's ═══════
210
215
  # The delta twin of the swap `plan` performs before its own master frontend sections.
211
- # Sticky standards only accumulate, and the caller loaded BOTH lanes' rule sets before
212
- # including this module, so without this the service delta plan is authored with the UI
213
- # rules in its envelope and the experience delta plan with the service rules. `replace`
214
- # resets to the workflow's declared seed and loads `## /aw-spec-plan-ui`, so the backend
215
- # delta above kept the service set and everything below this line is the frontend's.
216
+ # The caller loads only the service lane's rules (`## /aw-spec-plan-backend`, when that
217
+ # lane is declared) before including this module, and sticky standards only accumulate,
218
+ # so without this the experience delta plan would be authored with the service rules in
219
+ # its envelope. `replace` resets to the workflow's declared seed and loads
220
+ # `## /aw-spec-plan-frontend`, so the backend delta above is authored under the service
221
+ # set and everything below this line under the frontend's.
216
222
  #
217
223
  # Conditioned on the same flag as the lane it precedes: a change with no frontend half
218
224
  # authors nothing here and must not have its envelope swapped out from under the
@@ -221,7 +227,7 @@ workflow:
221
227
  condition: "{{fe_existing}} == true"
222
228
  action: include
223
229
  module: .appweaver/orchestrator/modules/tech-select.orch.yaml
224
- with: { command: aw-spec-plan-ui, replace: "true" }
230
+ with: { command: aw-spec-plan-frontend, replace: "true" }
225
231
 
226
232
  # ═════════════════════ FRONTEND LANE — the experience delta plan ═════════════
227
233
  - id: ctx_frontend_delta
@@ -292,6 +298,10 @@ workflow:
292
298
  and introduce no server-side behaviour or persistence assumption. What the
293
299
  experience needs and the surface does not offer goes under "Contract deltas
294
300
  needed", raised back to the service lane — never worked around in the client.
301
+ - A BINDING ROW'S ELEMENT LEADS WITH ITS OPERATION ID — `OperationId` · `VERB
302
+ /route` — copied exactly from the service delta's table or, for an endpoint the
303
+ change does not touch, the master backend plan. Implement looks the endpoint up by
304
+ it in the service's exported API document.
295
305
  - UX- IS THIS DOCUMENT'S TO REALISE. The service plan excludes the spec's Experience
296
306
  Standards by contract, so a UX- item in the delta-spec that reaches neither plan
297
307
  is a dropped requirement.
@@ -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