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.
- package/assets/.agents/skills/appweaver/SKILL.md +7 -47
- package/assets/.appweaver/ORCH-DIALECT.md +13 -9
- package/assets/.appweaver/RULE-PARTITION.md +11 -12
- package/assets/.appweaver/STACK-PROFILES.md +260 -108
- package/assets/.appweaver/domain.json +1 -1
- package/assets/.appweaver/interpreter/run-skill.py +28 -7
- package/assets/.appweaver/orchestrator/AGENT-PROFILE.md +38 -10
- package/assets/.appweaver/orchestrator/LAUNCHER.md +88 -0
- package/assets/.appweaver/orchestrator/README.md +120 -53
- package/assets/.appweaver/orchestrator/adapters/claude_agent_sdk.py +1 -1
- package/assets/.appweaver/orchestrator/modules/delta-plan.orch.yaml +17 -7
- package/assets/.appweaver/orchestrator/modules/domain-select.orch.yaml +6 -4
- package/assets/.appweaver/orchestrator/modules/foundation-lane.orch.yaml +237 -0
- package/assets/.appweaver/orchestrator/modules/foundation-pack.orch.yaml +392 -0
- package/assets/.appweaver/orchestrator/modules/foundation-spec.orch.yaml +548 -0
- package/assets/.appweaver/orchestrator/modules/lane-gate.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/modules/tech-select.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/orchestrator.py +162 -63
- package/assets/.appweaver/orchestrator/rev-templates/delta-design-template.skeleton.md +5 -4
- package/assets/.appweaver/orchestrator/rev-templates/design-template.skeleton.md +3 -1
- package/assets/.appweaver/orchestrator/rev-templates/domain-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-requirements.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/domain-rule-bindings.skeleton.md +21 -13
- package/assets/.appweaver/orchestrator/rev-templates/frontend-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/tech-rule-bindings.skeleton.md +28 -31
- package/assets/.appweaver/orchestrator/rev-templates/technical-constitution.skeleton.md +2 -2
- package/assets/.appweaver/orchestrator/rev-templates/technical-rule-file.skeleton.md +1 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-constitution.skeleton.md +3 -3
- package/assets/.appweaver/orchestrator/rev-templates/ui-delta-design-template.skeleton.md +4 -1
- package/assets/.appweaver/orchestrator/rev-templates/ui-design-template.skeleton.md +6 -4
- package/assets/.appweaver/orchestrator/workflows/_smoke.orch.yaml +41 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-add-component.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-adopt.orch.yaml +17 -16
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan-delta.orch.yaml +7 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-plan.orch.yaml +7 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice-delta.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-analyze-slice.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-build.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-characterize.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-constitution.orch.yaml +61 -12
- package/assets/.appweaver/orchestrator/workflows/aw-spec-deploy.orch.yaml +1 -1
- package/assets/.appweaver/orchestrator/workflows/aw-spec-foundation.orch.yaml +172 -293
- package/assets/.appweaver/orchestrator/workflows/aw-spec-implement.orch.yaml +253 -44
- package/assets/.appweaver/orchestrator/workflows/aw-spec-onboard.orch.yaml +72 -71
- package/assets/.appweaver/orchestrator/workflows/aw-spec-parity.orch.yaml +2 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-plan.orch.yaml +38 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-run.orch.yaml +4 -4
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-bounded-context.orch.yaml +26 -2
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-domain.orch.yaml +21 -15
- package/assets/.appweaver/orchestrator/workflows/aw-spec-select-stack.orch.yaml +14 -14
- package/assets/.appweaver/orchestrator/workflows/aw-spec-specify.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-model.orch.yaml +3 -3
- package/assets/.appweaver/orchestrator/workflows/aw-spec-ui-prototype.orch.yaml +6 -6
- package/assets/.appweaver/scripts/bash/aw-spec-actions.sh +371 -131
- package/assets/.appweaver/scripts/powershell/aw-spec-actions.ps1 +293 -76
- package/assets/.appweaver/scripts/python/aw-foundation.py +885 -20
- package/assets/.appweaver/scripts/python/aw-inventory.py +28 -21
- package/assets/.appweaver/scripts/python/aw-plan-coverage.py +2 -2
- package/assets/.appweaver/scripts/python/aw-rev-constitution.py +6 -6
- package/assets/.appweaver/scripts/python/aw-stack.py +676 -99
- package/assets/.appweaver/stack-profiles/angular.json +2 -1
- package/assets/.appweaver/stack-profiles/blazor-wasm.json +2 -1
- package/assets/.appweaver/stack-profiles/dotnet-webapi.json +18 -3
- package/assets/.appweaver/stack-profiles/go-chi.json +6 -1
- package/assets/.appweaver/stack-profiles/java-spring.json +14 -5
- package/assets/.appweaver/stack-profiles/nextjs.json +2 -1
- package/assets/.appweaver/stack-profiles/node-express.json +8 -2
- package/assets/.appweaver/stack-profiles/python-fastapi.json +9 -2
- package/assets/.appweaver/stack-profiles/react-vite.json +2 -1
- package/assets/.appweaver/stack-profiles/sveltekit.json +2 -1
- package/assets/.appweaver/stack-profiles/vue-vite.json +2 -1
- package/assets/.appweaver/stacks.json +40 -1
- package/assets/.appweaver/templates/constitution-ui-template.md +2 -2
- package/assets/.appweaver/templates/delta-design-template.md +7 -5
- package/assets/.appweaver/templates/design-template.md +3 -0
- package/assets/.appweaver/templates/ui-delta-design-template.md +1 -1
- package/assets/.appweaver/templates/ui-design-template.md +6 -4
- package/assets/.claude/skills/appweaver/SKILL.md +7 -46
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.Reference.rules.json +31 -0
- package/assets/foundations/dotnet/ModularMonolith/ModularMonolith.lane.json +6 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.Reference.rules.json +16 -0
- package/assets/foundations/dotnet/VerticalSlice/VerticalSlice.lane.json +6 -0
- package/assets/foundations/foundation.spec.template.txt +98 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.lane.json +6 -0
- package/assets/foundations/java/Hexagonal/Hexagonal.pack.txt +8 -1
- package/assets/foundations/java/Hexagonal/unpack-foundation.sh +4 -5
- package/assets/foundations/node/NextAppRouter/NextAppRouter.spec.txt +68 -0
- package/assets/guardrails/README.md +31 -17
- package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain-rule-bindings.md +25 -13
- package/assets/guardrails/project-specific/tech-rule-bindings.md +296 -0
- package/assets/guardrails/technology/dotnet-webapi/PACKAGING.md +58 -4
- package/assets/guardrails/technology/dotnet-webapi/api-versioning.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/auditing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/authorization.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/clean-architecture.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/coding-standards.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/cqrs.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/data-classification.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/dependency-policy.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/eventing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/folder-structure.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/framework-api-map.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/modular-monolith.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/persistence.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/testing.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/vertical-slices.md +1 -1
- package/assets/guardrails/technology/dotnet-webapi/zero-trust.md +1 -1
- package/assets/guardrails/technology/nextjs/accessibility-implementation.md +1 -1
- package/assets/guardrails/technology/nextjs/api-client.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.dotnet-webapi.md +1 -1
- package/assets/guardrails/technology/nextjs/api-integration.java-spring.md +1 -1
- package/assets/guardrails/technology/nextjs/auth-session.md +1 -1
- package/assets/guardrails/technology/nextjs/client-security.md +1 -1
- package/assets/guardrails/technology/nextjs/component-architecture.md +1 -1
- package/assets/guardrails/technology/nextjs/component-conventions.md +2 -2
- package/assets/guardrails/technology/nextjs/design-system.md +1 -1
- package/assets/guardrails/technology/nextjs/error-handling.md +1 -1
- package/assets/guardrails/technology/nextjs/forms-and-validation.md +1 -1
- package/assets/guardrails/technology/nextjs/frontend-testing.md +1 -1
- package/assets/guardrails/technology/nextjs/i18n.md +1 -1
- package/assets/guardrails/technology/nextjs/observability.md +1 -1
- package/assets/guardrails/technology/nextjs/performance-budgets.md +1 -1
- package/assets/guardrails/technology/nextjs/routing-navigation.md +1 -1
- package/assets/guardrails/technology/nextjs/state-management.md +1 -1
- package/assets/guardrails/technology/nextjs/ui-constitution.md +3 -3
- package/package.json +1 -1
- package/assets/.agents/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.appweaver/orchestrator/.smoke-out/smoke.md +0 -6
- package/assets/.appweaver/orchestrator/workflows/aw-spec-demo.orch.yaml +0 -100
- package/assets/.claude/skills/appweaver-demo/SKILL.md +0 -59
- package/assets/.kilocode/agent.json +0 -28
- package/assets/.kilocode/workflows/appweaver-demo.md +0 -59
- package/assets/.kilocode/workflows/appweaver.md +0 -55
- package/assets/guardrails/projects/dotnet-default-project/tech-rule-bindings.md +0 -271
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/domain/domain-requirements.md +0 -0
- /package/assets/guardrails/{projects/dotnet-default-project → project-specific}/frontend/ui-requirements.md +0 -0
- /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 ==
|
|
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
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
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
|
-
|
|
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
|
|
13
|
-
.agents/agent.json ← Antigravity profile
|
|
14
|
-
.
|
|
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 `.
|
|
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
|
|
91
|
-
|
|
92
|
-
|
|
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
|
-
|
|
97
|
-
|
|
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`, `.
|
|
24
|
-
that agent shares it — no per-skill duplication.
|
|
25
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
38
|
-
.
|
|
39
|
-
.
|
|
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 |
|
|
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
|
|
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/
|
|
85
|
-
python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/
|
|
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/
|
|
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/
|
|
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 (
|
|
100
|
-
python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/
|
|
101
|
-
--agent-profile .
|
|
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
|
|
105
|
-
executing
|
|
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/
|
|
157
|
-
--checkpoint .appweaver/orchestrator/.
|
|
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:
|
|
170
|
-
`
|
|
171
|
-
|
|
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
|
|
233
|
+
## The agents
|
|
199
234
|
|
|
200
|
-
| Agent |
|
|
201
|
-
|
|
202
|
-
| Claude Code | `.claude/` | `claude -p`
|
|
203
|
-
| Antigravity | `.agents/` | `
|
|
204
|
-
| Kilo Code | `.
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
290
|
-
|
|
291
|
-
|
|
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) —
|
|
294
|
-
python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/
|
|
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/.
|
|
362
|
+
--checkpoint .appweaver/orchestrator/.state/smoke.state.json --json
|
|
297
363
|
|
|
298
|
-
# agent (Strategy 4) —
|
|
299
|
-
python3 .appweaver/orchestrator/orchestrator.py .appweaver/orchestrator/workflows/
|
|
300
|
-
--strategy agent --checkpoint .appweaver/orchestrator/.
|
|
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 .
|
|
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
|
-
#
|
|
212
|
-
#
|
|
213
|
-
#
|
|
214
|
-
# resets to the workflow's declared seed and loads
|
|
215
|
-
#
|
|
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-
|
|
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
|
|
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
|
-
|
|
54
|
-
|
|
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
|
|
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
|