@wairon/cli 5.1.1-dev.108 → 5.1.1-dev.109
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/CONTRIBUTING.md +193 -0
- package/README.md +14 -11
- package/dist/cli/index.js +2694 -1819
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +130 -7
- package/dist/index.js +2235 -1397
- package/dist/index.js.map +1 -1
- package/docs/cli.md +74 -23
- package/docs/design/approval-baseline.md +257 -0
- package/docs/design/connecting-agent-entrypoint.md +167 -0
- package/docs/design/execution-budgets.md +199 -0
- package/docs/design/pack-scoping.md +581 -0
- package/docs/design/supervisor-doctrine.md +110 -0
- package/docs/extending-wairon.md +2 -2
- package/package.json +9 -3
- package/schemas/design-export-2.json +9 -1
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Execution budgets — the resource axis of the topology
|
|
2
|
+
|
|
3
|
+
> Status: **implemented**. Written against wairon 5.1.x. The measurements below
|
|
4
|
+
> come from three archived Claude Code sessions of this project's own
|
|
5
|
+
> development, read out of the session transcripts rather than estimated.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## The problem
|
|
10
|
+
|
|
11
|
+
The derived topology answered one question about each agent — *what does it own*
|
|
12
|
+
— and nothing about a second one that turns out to cost real money: *what does
|
|
13
|
+
its work cost to do*.
|
|
14
|
+
|
|
15
|
+
In a delegating workflow that gap has a specific, measurable shape. A Claude
|
|
16
|
+
Code subagent's `model` field defaults to `inherit`. An agent file that omits it
|
|
17
|
+
silently adopts the parent session's model. With a frontier-tier parent and no
|
|
18
|
+
agent files on disk at all, **1,860 of 2,176 subagent turns ran on the most
|
|
19
|
+
expensive tier** across the three sessions measured — not by anyone's decision,
|
|
20
|
+
but by a default nobody had reason to look at.
|
|
21
|
+
|
|
22
|
+
Two things are worth stating because they are commonly assumed and were both
|
|
23
|
+
wrong here:
|
|
24
|
+
|
|
25
|
+
- **Per-spawn startup duplication is not the problem.** Subagents do reload
|
|
26
|
+
CLAUDE.md and tool schemas from scratch — measured at 13.5k–32.5k tokens
|
|
27
|
+
against a main session's 44–46k. But the whole CLAUDE.md chain came to ~2,400
|
|
28
|
+
tokens: 8% of a subagent's startup and **0.2% of subagent spend**. Eliminating
|
|
29
|
+
it entirely would save ~2%.
|
|
30
|
+
- **Delegation was still correct.** Running the same work inline in a session
|
|
31
|
+
already averaging 271k context would have added a large context-carry
|
|
32
|
+
surcharge on every turn, and would have forced repeated compaction. The
|
|
33
|
+
problem was never *whether* to delegate; it was that every delegation was
|
|
34
|
+
constituted by default.
|
|
35
|
+
|
|
36
|
+
A default that expensive cannot be fixed by instruction text. A prompt asking an
|
|
37
|
+
orchestrator to choose models deliberately competes for attention with the task,
|
|
38
|
+
and loses — the sessions measured had exactly such a policy, stated by the
|
|
39
|
+
maintainer, and it lost 85% of the time. It has to be configuration.
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## The model
|
|
44
|
+
|
|
45
|
+
Four layers, tool-agnostic until the last. The split is what lets one derivation
|
|
46
|
+
serve a local Claude Code session, a hosted MCP client, and a tool that cannot
|
|
47
|
+
select models at all.
|
|
48
|
+
|
|
49
|
+
| Layer | File | Holds |
|
|
50
|
+
|-------|------|-------|
|
|
51
|
+
| **Execution profile** | `models/execution.ts`, `core/execution_profile.ts` | What the work *is like*: `breadth`, `writes`, `reasoningDepth`, `delegates`. Says nothing about models. |
|
|
52
|
+
| **Budget policy** | `core/budget_policy.ts` | What that *earns*: capability tier, effort, turn ceiling, tool class, delegation rights, MCP access. Named in tiers, never vendor models. |
|
|
53
|
+
| **Target emitter** | `exporters/claude.ts` | The per-tool *encoding*. Deliberately not generic. |
|
|
54
|
+
| **Brief** | `core/agent_resolver.ts` | The same budget, carried advisory to whoever spawns from it. |
|
|
55
|
+
|
|
56
|
+
### Derivation needs no spec authoring
|
|
57
|
+
|
|
58
|
+
Every input already exists on a resolved `AgentRecord`:
|
|
59
|
+
|
|
60
|
+
- `reasoningDepth` reads the **component stereotype**, which the vocabulary
|
|
61
|
+
already encodes. A Store, Index, Registry or Adapter is plumbing that its L3
|
|
62
|
+
contract and L5 narrative fully describe. An Orchestrator, Supervisor or
|
|
63
|
+
Specialist carries the decisions. Inventing a second classification alongside
|
|
64
|
+
the stereotype would have meant two things to keep in agreement.
|
|
65
|
+
- `breadth` reads owned-path spread and whether `readPaths` sweeps the tree.
|
|
66
|
+
- `writes` reads the **role**, not the path count — see the reversals below.
|
|
67
|
+
- `delegates` reads the template.
|
|
68
|
+
|
|
69
|
+
### Tiers, not model names
|
|
70
|
+
|
|
71
|
+
`ExecutionBudget.modelTier` is `small | standard | large | frontier`. Mapping a
|
|
72
|
+
tier onto a real model is the *consumer's* job, because only the consumer knows
|
|
73
|
+
what its host tool understands. The Claude Code exporter maps to model
|
|
74
|
+
**aliases** (`haiku`, `sonnet`, `opus`, `fable`) rather than pinned ids, so
|
|
75
|
+
generated files keep working across model releases.
|
|
76
|
+
|
|
77
|
+
### The dial
|
|
78
|
+
|
|
79
|
+
`execution.tier` defaults to `off`, and each step is a strict superset of the
|
|
80
|
+
constraints below it — raising it can only tighten a budget, never loosen one.
|
|
81
|
+
That property is what makes the dial safe to turn without auditing every agent.
|
|
82
|
+
|
|
83
|
+
`free` is defined as having *no* quality tradeoff, which is why it expresses no
|
|
84
|
+
model choice at all: picking a model is a quality decision. An absent
|
|
85
|
+
`modelTier` is not the same as a default one, and the exporter omits the field
|
|
86
|
+
rather than substituting.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Enforce versus advise
|
|
91
|
+
|
|
92
|
+
Both delivery paths carry the budget, and they are not equivalent:
|
|
93
|
+
|
|
94
|
+
- A **generated agent file** can *enforce*. Front-matter binds: `model`,
|
|
95
|
+
`effort`, `maxTurns`, `tools`, `mcpServers` are read by the host before the
|
|
96
|
+
agent runs.
|
|
97
|
+
- A **live brief** can only *advise*. The caller spawning from the brief is what
|
|
98
|
+
applies it.
|
|
99
|
+
|
|
100
|
+
That asymmetry is deliberate rather than a gap — a brief is consumed by tools
|
|
101
|
+
wairon does not control. It also matters practically: `materializeAgentFiles`
|
|
102
|
+
defaults to **off**, so the brief is the path most projects actually use, and a
|
|
103
|
+
budget that only reached generated files would have reached almost nobody.
|
|
104
|
+
|
|
105
|
+
The same line explains the hosted story. Budgets are declarative data and travel
|
|
106
|
+
fine over the hosted MCP surface as an advisory block on the brief. Front-matter,
|
|
107
|
+
hooks and settings are filesystem artifacts and only the local CLI can write
|
|
108
|
+
them. This is the same split hosted pack management already draws — declarative
|
|
109
|
+
over the API, code packs via filesystem — rather than a second rule.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Two things derivation deliberately never produces
|
|
114
|
+
|
|
115
|
+
### `frontier` is not an owner tier
|
|
116
|
+
|
|
117
|
+
Derivation caps deep reasoning at `large`, at every dial setting including
|
|
118
|
+
`aggressive`. `frontier` is reachable only by an explicit per-agent override.
|
|
119
|
+
|
|
120
|
+
The reasoning is that a frontier-capable model is a **sparring partner** for a
|
|
121
|
+
question the specs do not settle, not a way to operate a component day to day.
|
|
122
|
+
Given a tree that is already specced and decided, an owner that genuinely needs
|
|
123
|
+
frontier capability to function is usually a component doing too much — the same
|
|
124
|
+
smell `GOD_COMPONENT` reports, arrived at from a different direction. So it stays
|
|
125
|
+
a decision only the user can make, and `wairon execution show` surfaces every
|
|
126
|
+
agent pinned there.
|
|
127
|
+
|
|
128
|
+
### `orchestrate` is not derived either
|
|
129
|
+
|
|
130
|
+
The `orchestrate` tool class — the thin grant that withholds bulk-content tools
|
|
131
|
+
from a pure router — exists because a manager that can read files will read
|
|
132
|
+
them, and then it accumulates context exactly like a main session, which is the
|
|
133
|
+
whole thing delegation was supposed to avoid.
|
|
134
|
+
|
|
135
|
+
But **every agent in a wairon topology owns and authors something**. Domain
|
|
136
|
+
owners write the specs and source they own; even a chained-subproject owner
|
|
137
|
+
writes its mount spec. Stripping their write tools would not make them cheaper,
|
|
138
|
+
it would make them broken. The genuine pure router in this workflow is the
|
|
139
|
+
human's own main session, which is not a wairon agent at all.
|
|
140
|
+
|
|
141
|
+
So `orchestrate` stays in the vocabulary as an override-selectable class for a
|
|
142
|
+
manager someone defines by hand, and derivation never assigns it.
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Reversals worth recording
|
|
147
|
+
|
|
148
|
+
Both were found by generating into a real project rather than by reading the
|
|
149
|
+
code, and both are pinned by regression tests.
|
|
150
|
+
|
|
151
|
+
**`writes` was inferred from owned-path count.** An implementer whose source
|
|
152
|
+
path could not be inferred came out with zero owned paths, therefore
|
|
153
|
+
`writes: false`, therefore `tools: Read, Grep, Glob` — an implementer that
|
|
154
|
+
cannot implement, produced silently. `writes` is now a property of the role. A
|
|
155
|
+
missing path is a topology gap to fix, not a reason to demote an agent.
|
|
156
|
+
|
|
157
|
+
**Budget front-matter leaked into other targets.** `cursor`, `copilot` and
|
|
158
|
+
`codex` all reuse `ClaudeExporter` for the agent-file shape. Enabling budgets
|
|
159
|
+
therefore wrote `model`, `maxTurns` and `mcpServers` into files for tools that do
|
|
160
|
+
not implement Claude Code's subagent contract. Those keys would be ignored, which
|
|
161
|
+
is worse than absent: a budget sitting in the file reads as enforced when nothing
|
|
162
|
+
enforces it. The shape is still shared; the encoding is now per-tool, opt-in at
|
|
163
|
+
the exporter registry once a target's own fields are verified.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Deliberately out of scope
|
|
168
|
+
|
|
169
|
+
**Session-hygiene hooks and a context statusline.** Both would cut real tokens —
|
|
170
|
+
rewriting noisy commands so their output does not enter context verbatim, and
|
|
171
|
+
showing live context size instead of periodically re-measuring it. Neither
|
|
172
|
+
belongs here. They are identical for every project regardless of its spec tree,
|
|
173
|
+
so wairon would be deriving them from nothing, and wiring them means writing into
|
|
174
|
+
a hand-maintained `settings.json` with no marker-based reconcile available,
|
|
175
|
+
unlike every other file wairon generates. Generated skills are not a precedent:
|
|
176
|
+
those *are* wairon's domain.
|
|
177
|
+
|
|
178
|
+
**A conformance rule for frontier overrides.** `validate` gates the spec tree;
|
|
179
|
+
an override lives in project config, and `lint.allow` attaches to specs. The
|
|
180
|
+
finding actually wanted — "this component is doing too much" — is already
|
|
181
|
+
`GOD_COMPONENT`. The override warning lives in `wairon execution show`, where the
|
|
182
|
+
config it reports on lives.
|
|
183
|
+
|
|
184
|
+
---
|
|
185
|
+
|
|
186
|
+
## Open
|
|
187
|
+
|
|
188
|
+
- **Precedence between an agent file's `model:` and the
|
|
189
|
+
`CLAUDE_CODE_SUBAGENT_MODEL` environment variable is unverified.** The env var
|
|
190
|
+
short-circuits Claude Code's model-resolution chain when set to anything but
|
|
191
|
+
`inherit`; whether explicit front-matter still wins decides whether a global
|
|
192
|
+
floor and per-role pinning compose or conflict.
|
|
193
|
+
- **Whether `effort`, `maxTurns` and `mcpServers` in agent front-matter are
|
|
194
|
+
honoured** by a given Claude Code build. Documented, not yet measured.
|
|
195
|
+
- **Topology scale.** A large project generates 30–50 subsystem agents (and would
|
|
196
|
+
generate 1000+ with component implementers on). Because briefs resolve on
|
|
197
|
+
demand by id, nothing needs a materialized catalog — but agent *discovery*
|
|
198
|
+
still enumerates everything, which argues for scoping discovery to a domain.
|
|
199
|
+
Separate concern from budgets.
|