Skip to content

Commit be04987

Browse files
committed
docs(.claude/ATT): add §16 Model Stylesheet + Mid-Task Switching
Maps to attractor-spec.md §8 model_stylesheet and adds Opus<>Sonnet switching semantics: - §16.1 Static per-phase defaults (plan/meta=opus, worker-skeleton-fill= sonnet, chairman=opus, PP-14=opus, etc.) - §16.2 Stylesheet syntax with CSS-like selectors + mandatory * fallback - §16.3 Mid-task escalation triggers (tool-call loop in council round 3+, MISSING_INVARIANT blocker, unsafe-block in skeleton-fill, etc.) - §16.4 De-escalation triggers (CONVERGE round 1 + 0 P0, diff<50, etc.) - §16.5 Wire format: workers do NOT self-switch; emit PROPOSAL on universal wire format (§1.3 coordination spec); orchestrator re-spawns with a NEW sentinel token (per LD-1 continuity) - §16.6 Cost-aware escalation budget - §16.7 Validation rules WAVE-030..035 - §16.8 Worked-example wave timeline
1 parent 918ba0d commit be04987

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

.claude/ATT/autoattended-orchestrator-spec.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,4 +1070,162 @@ next_action: proceed
10701070

10711071
---
10721072

1073+
## §16 Model Stylesheet + Mid-Task Switching
1074+
1075+
> Added 2026-05-18. Maps to `attractor-spec.md` §8 `model_stylesheet`
1076+
> (CSS-like selectors), adds our mid-task Opus↔Sonnet switching
1077+
> triggered by our stuck-protocol blockers and council-round counts.
1078+
1079+
### §16.1 Why have a stylesheet at all
1080+
1081+
| Phase / role | Cognitive load | Reasonable default |
1082+
|---|---|---|
1083+
| Plan authoring | high (architecture, cross-cutting) | **opus** + `reasoning=high` |
1084+
| Plan review (meta-agent) | high (judgment, taste) | **opus** + `reasoning=high` |
1085+
| PP-14 convergence-architect | high (creative-design exploration) | **opus** + `reasoning=high` |
1086+
| PP-16 preflight-drift-auditor | medium (git + grep against plan) | **sonnet** (escalate on drift > 100 lines) |
1087+
| PP-15 baton-handoff-auditor | medium (interface diffing) | **sonnet** |
1088+
| PP-13 brutally-honest-tester | medium (toolchain runner + AP1..AP9) | **sonnet** |
1089+
| Worker (skeleton-fill) | medium (mechanical fill of typed surface) | **sonnet** |
1090+
| Worker (greenfield code) | high (design + impl) | **opus** |
1091+
| Council round (per savant) | medium (review iteration) | **sonnet** |
1092+
| Chairman synthesis | high (cross-finding consolidation) | **opus** |
1093+
| Inbox drain (meta-agent) | low (typed-blocker routing) | **sonnet** (escalate on `BEHAVIOUR_QUESTION`) |
1094+
1095+
Static per-role defaults are step 1. Mid-task switching (§16.3) is
1096+
step 2.
1097+
1098+
### §16.2 Stylesheet syntax (attractor §8 compatible)
1099+
1100+
```yaml
1101+
model_stylesheet:
1102+
# CSS-like rules. First matching rule wins (per attractor §8).
1103+
rules:
1104+
- selector: "node[kind=plan]"
1105+
props: { model: opus, reasoning_effort: high }
1106+
- selector: "node[kind=meta_review]"
1107+
props: { model: opus, reasoning_effort: high }
1108+
- selector: "node[kind=savant][role=PP-14]"
1109+
props: { model: opus, reasoning_effort: high }
1110+
- selector: "node[kind=savant][phase=POST-IMPL]"
1111+
props: { model: sonnet }
1112+
- selector: "node[kind=savant][phase=PRE-SPAWN]"
1113+
props: { model: sonnet }
1114+
- selector: "node[kind=council_chairman]"
1115+
props: { model: opus }
1116+
- selector: "node[kind=worker][mode=skeleton-fill]"
1117+
props: { model: sonnet }
1118+
- selector: "node[kind=worker][mode=greenfield]"
1119+
props: { model: opus }
1120+
- selector: "*"
1121+
props: { model: sonnet } # final fallback
1122+
```
1123+
1124+
Selectors compose with `[attr=value]` pairs (attractor §8.2). The
1125+
fallback `*` rule is mandatory; absence is `WAVE-030` ERROR.
1126+
1127+
### §16.3 Mid-task escalation triggers
1128+
1129+
A worker (or savant) does NOT switch its own model — it writes a
1130+
typed signal to its `status.json` and the **orchestrator re-spawns**
1131+
with the requested model. Self-switching would break LD-1 sentinel
1132+
continuity.
1133+
1134+
| Trigger condition | Action | Escalate from → to |
1135+
|---|---|---|
1136+
| `outcome=RETRY` AND `notes contains "escalate-model:opus"` | re-spawn same agent_id with opus | sonnet → opus |
1137+
| Tool-call loop detected in council, `rounds >= 3` without CONVERGE | re-spawn the looping savant with opus + `reasoning=high` | sonnet → opus |
1138+
| Worker filed `MISSING_INVARIANT` blocker AND meta-agent answer is structural | re-spawn worker with opus | sonnet → opus |
1139+
| Worker filed `SPEC_SOURCE_MISMATCH` AND meta wrote an RFC | re-spawn worker with opus after RFC merge | sonnet → opus |
1140+
| Proof-of-read covers > 10 files | escalate at next re-spawn | sonnet → opus |
1141+
| `unsafe` block in skeleton-fill | escalate at next re-spawn | sonnet → opus |
1142+
| PP-16 drift surface > 100 lines | escalate the next preflight pass | sonnet → opus |
1143+
| PP-13 anti-pattern density > 3 per 100 lines of diff | escalate PP-13 for re-review pass | sonnet → opus |
1144+
1145+
### §16.4 Mid-task de-escalation triggers
1146+
1147+
The opposite direction — orchestrator can drop a re-spawn down from
1148+
opus to sonnet when the work turned out simpler than the stylesheet
1149+
default predicted:
1150+
1151+
| Trigger condition | Action | De-escalate from → to |
1152+
|---|---|---|
1153+
| Plan turned out to be a 2-bundle wave (not 12) | next round's worker default | opus → sonnet |
1154+
| Council CONVERGED in round 1 with zero P0 + ≤2 P1 | chairman synthesis | opus → sonnet |
1155+
| `outcome=SUCCESS` + tier-1 green + diff < 50 lines | next-wave default for this bundle | opus → sonnet |
1156+
| Meta-agent's inbox-drain answered only `AMBIGUITY` blockers in last 10 entries | next inbox drain | opus → sonnet |
1157+
1158+
### §16.5 Wire format for switching
1159+
1160+
The signal flows on the universal wire format
1161+
(`agent-coordination-mcp-spec.md §1.3`):
1162+
1163+
```markdown
1164+
## 2026-05-18T14:22 — PROPOSAL[P1]: escalate-model A4 → opus (sonnet, claude/wave-12)
1165+
1166+
**Author:** A4
1167+
**Kind:** PROPOSAL
1168+
**Severity:** P1
1169+
**Refs:** status.json#A4 wave-12
1170+
**Reason:** tool-call-loop:length=2:rounds=3 on customer.master sea-orm UPSERT
1171+
1172+
---
1173+
1174+
Requested: model=opus, reasoning_effort=high.
1175+
Suggested rationale: this is a stuck-protocol AMBIGUITY-class issue
1176+
(sea-orm vs Python idempotent UPSERT semantics) — judgment-heavy.
1177+
```
1178+
1179+
Orchestrator routes by `Kind=PROPOSAL` + `Severity=P1` + body
1180+
contains `escalate-model:`. Re-spawn happens in the next wave step.
1181+
1182+
### §16.6 Cost-aware ceiling
1183+
1184+
The stylesheet MUST declare a per-wave **escalation budget**:
1185+
1186+
```yaml
1187+
model_stylesheet:
1188+
budget:
1189+
max_opus_workers_per_wave: 3 # default 3
1190+
max_opus_savant_rounds_per_council: 2 # default 2
1191+
warn_if_exceeds: 0.8
1192+
```
1193+
1194+
If a wave's pending escalations would exceed the budget, the
1195+
orchestrator MUST either (a) serialize escalations across waves or
1196+
(b) ask the human via `wait.human` (attractor §6) before
1197+
escalating.
1198+
1199+
### §16.7 Validation rules
1200+
1201+
| Rule | Description | Severity |
1202+
|---|---|---|
1203+
| `WAVE-030 stylesheet-fallback` | `model_stylesheet.rules` MUST end with a `*` fallback. | ERROR |
1204+
| `WAVE-031 no-self-switching` | Workers / savants MUST NOT switch their own model mid-call. Use the `PROPOSAL`-wire signal (§16.5). | ERROR |
1205+
| `WAVE-032 sentinel-on-respawn` | Re-spawn under escalation MUST issue a NEW sentinel token (the previous worker's identity is closed). | ERROR |
1206+
| `WAVE-033 escalation-budget` | The wave's escalation total MUST NOT exceed `model_stylesheet.budget` without explicit human override. | WARNING |
1207+
| `WAVE-034 escalation-trace` | Every escalation re-spawn MUST leave a `PROPOSAL` entry on the wire format (§16.5) so the audit log shows when + why. | ERROR |
1208+
| `WAVE-035 de-escalation-gate` | De-escalation MUST be triggered only by §16.4 conditions; arbitrary downgrades are forbidden (cost-saving optimism). | ERROR |
1209+
1210+
### §16.8 Worked example: a wave that escalates then de-escalates
1211+
1212+
```
1213+
T+0 plan committed opus (per §16.1 default for plan)
1214+
T+1 PP-16 preflight runs sonnet (drift < 100 lines, default)
1215+
T+1 PP-16 emits skeleton sonnet (still PP-16)
1216+
T+2 council round 1 sonnet x4 (all savants default)
1217+
T+2 council CONVERGE opus (chairman synthesis default)
1218+
T+3 workers spawn (12 × A1..A12) sonnet (skeleton-fill default)
1219+
T+4 A4 hits sea-orm AMBIGUITY → PROPOSAL: escalate A4
1220+
T+4 meta-agent writes RFC opus (meta default)
1221+
T+5 A4 re-spawn opus (escalated, new sentinel)
1222+
T+6 A4 returns SUCCESS — (kept opus through this wave)
1223+
T+7 fan-in + tier-1 green —
1224+
T+8 next wave plans A4 again opus (sticky escalation for one wave)
1225+
T+9 A4 returns SUCCESS again —
1226+
T+10 wave 3 plans A4 sonnet (DE-ESCALATE per §16.4: 2 successes + diff < 50)
1227+
```
1228+
1229+
---
1230+
10731231
*End of `autoattended-orchestrator-spec.md`.*

0 commit comments

Comments
 (0)