@pilotspace/add 1.3.0 → 1.5.0
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/CHANGELOG.md +108 -0
- package/GETTING-STARTED.md +4 -0
- package/README.md +16 -3
- package/bin/cli.js +1 -6
- package/docs/09-the-loop.md +3 -1
- package/docs/14-foundation.md +11 -0
- package/docs/appendix-c-glossary.md +16 -0
- package/package.json +1 -1
- package/skill/add/SKILL.md +19 -2
- package/skill/add/advisor.md +75 -0
- package/skill/add/compact-foundation.md +53 -0
- package/skill/add/confidence.md +48 -0
- package/skill/add/design.md +92 -0
- package/skill/add/fold.md +4 -4
- package/skill/add/phases/0-ground.md +2 -0
- package/skill/add/phases/0-setup.md +51 -3
- package/skill/add/phases/1-specify.md +5 -1
- package/skill/add/phases/2-scenarios.md +2 -0
- package/skill/add/phases/3-contract.md +2 -0
- package/skill/add/phases/4-tests.md +2 -0
- package/skill/add/phases/5-build.md +2 -0
- package/skill/add/phases/6-verify.md +2 -0
- package/skill/add/phases/7-observe.md +7 -0
- package/skill/add/soul.md +77 -0
- package/skill/add/streams.md +44 -3
- package/tooling/add.py +403 -6
- package/tooling/templates/GLOSSARY.md.tmpl +4 -0
- package/tooling/templates/SOUL.md.tmpl +40 -0
- package/tooling/templates/TASK.md.tmpl +1 -1
- package/tooling/templates/kit.sample.css +53 -0
- package/tooling/templates/settings.sample.html +25 -0
- package/tooling/templates/tokens.sample.css +23 -0
- package/tooling/templates/udd-wireframe.md +118 -0
- package/tooling/templates/welcome.sample.html +25 -0
- package/tooling/templates/wireframe.sample.txt +27 -0
|
@@ -49,15 +49,41 @@ Ask only the live ones; skip what the request already answers. Rank your drafts
|
|
|
49
49
|
one notation every scope level shares — `⚠ <assumption> — lowest confidence because <why>; if wrong: <cost>` — and
|
|
50
50
|
tag thin or inferred answers `guessed`.
|
|
51
51
|
|
|
52
|
+
## 2c · Domain deep-dive — per-drive, across multiple turns (deepens §2b)
|
|
53
|
+
|
|
54
|
+
§2b gets a foundation from one question per lens; this step DEEPENS it across **multiple
|
|
55
|
+
turns**, one deep-dive per **drive** — naming all four, including the one §2b's lens list omitted:
|
|
56
|
+
|
|
57
|
+
| Drive | Deepen |
|
|
58
|
+
|-------|--------|
|
|
59
|
+
| **DDD** (domain) | core nouns → model: the entities, the invariants, the bounded edges |
|
|
60
|
+
| **SDD** (spec) | the milestone outcome → the behaviors and the explicit non-goals |
|
|
61
|
+
| **UDD** (users) | the primary user → the jobs, the surface, the one flow that must feel right |
|
|
62
|
+
| **TDD** (trust) | what "done & trusted" means: the risks to prove, the evidence that closes them |
|
|
63
|
+
|
|
64
|
+
Capture each surfaced decision as an **ADR** (architecture decision record) into `PROJECT.md`
|
|
65
|
+
**Key Decisions** as it lands — the Decisions lens becomes explicit ADR capture (the *why*, not just the *what*).
|
|
66
|
+
|
|
67
|
+
**Under `autonomy: auto` with full context, auto-complete all four drives in one pass** — draft
|
|
68
|
+
each without stopping to interview, still lowest-confidence-first, surfacing the top **flag**. Ask
|
|
69
|
+
only the live drives; skip what the request already answered. This deepens **drafting**, never the
|
|
70
|
+
gate: auto-complete NEVER skips the human baseline approval — the `lock` (§4) stays the one decision.
|
|
71
|
+
|
|
52
72
|
## 3 · Draft to the lock (both paths)
|
|
53
73
|
|
|
54
74
|
1. **Fill the living documentation** (it outlives all code): `.add/PROJECT.md` (the foundation — Domain · Spec/active
|
|
55
75
|
milestone · UI/UX · Key Decisions, one screen), `CONVENTIONS.md`, `GLOSSARY.md`, `MODEL_REGISTRY.md`,
|
|
56
76
|
`dependencies.allowlist`, and — for a UI project — `DESIGN.md` (the design source of truth: identity ·
|
|
57
|
-
principles · screens · the named-set foundation pointers + render recipe; delete it if there's no UI
|
|
77
|
+
principles · screens · the named-set foundation pointers + render recipe; delete it if there's no UI;
|
|
78
|
+
the design-definition loop that fills it — domain → components → wireframe → a captured screen confirmed before build — is `design.md`).
|
|
58
79
|
Brownfield: from the code. Greenfield: from the interview, gaps flagged `guessed`.
|
|
59
|
-
2. **
|
|
60
|
-
|
|
80
|
+
2. **Propose, then size it.** You just read the codebase (brownfield) or interviewed (greenfield) — so
|
|
81
|
+
don't silently draft. First float a **kickoff suggestion** for the first milestone the human reacts to:
|
|
82
|
+
a **goal** (one outcome sentence), a **flow** (the breadth-first task order that gets there), and
|
|
83
|
+
**scenarios** (concrete examples of what the user can DO once it ships). Keep it a lightweight react-to
|
|
84
|
+
sketch — a few bullets, NOT the frozen `MILESTONE.md` or per-task §2 suites. This is show-before-ask:
|
|
85
|
+
the human reacts (confirm / adjust / redirect); you do not auto-create. On their reaction, draft its
|
|
86
|
+
`MILESTONE.md` (read `scope.md`) — goal · scope · exit criteria · breadth-first tasks.
|
|
61
87
|
3. **Create the first task and draft its candidate specification bundle.** `new-task` is allowed pre-lock:
|
|
62
88
|
```bash
|
|
63
89
|
python3 .add/tooling/add.py new-task <slug> --title "<first feature>"
|
|
@@ -68,6 +94,28 @@ tag thin or inferred answers `guessed`.
|
|
|
68
94
|
4. **Write `.add/SETUP-REVIEW.md`** per `setup-review.md`: every decision you drafted (foundation, scope,
|
|
69
95
|
first contract), **lowest-confidence-first**, each tagged `guessed` | `evidence-grounded`.
|
|
70
96
|
|
|
97
|
+
## Run mode — how the build will be driven (propose parallel + auto; confirm to keep)
|
|
98
|
+
|
|
99
|
+
Before the lock, surface ONE more choice so the human is aware of how ADD will drive the build:
|
|
100
|
+
the **run mode**. Two settings compose it — the **autonomy** level (`add.py autonomy`, run.md: who owns
|
|
101
|
+
the verify gate) and **streams** (`add.py waves` + `streams.md`: whether independent tasks pipeline).
|
|
102
|
+
Show this table so the human sees the flow behavior of each, then PROPOSE the default:
|
|
103
|
+
|
|
104
|
+
| Run mode | Human gates that fire | Concurrency / flow behavior |
|
|
105
|
+
|----------|-----------------------|-----------------------------|
|
|
106
|
+
| **sequential · manual/conservative** | the contract freeze **and** every Verify, one task at a time | one task start-to-finish before the next; safest, slowest; the reviewer waits on each build |
|
|
107
|
+
| **parallel · auto** *(proposed default)* | the contract freeze **only** — Verify auto-PASSes on complete evidence (security/residue still escalate) | `add.py waves` schedules independent tasks into waves; builds overlap behind their frozen contracts while you review one bundle; the reviewer is never blocked on a build |
|
|
108
|
+
|
|
109
|
+
**Propose `parallel + auto` as the default, and ask the human to confirm-to-keep** (or downgrade in
|
|
110
|
+
one step — `add.py autonomy set conservative --project`, or just run tasks one at a time). This is a
|
|
111
|
+
confirm, never a silent flip. Record the chosen mode in **`PROJECT.md` Key Decisions** (e.g. "run mode:
|
|
112
|
+
parallel + auto (opt-out), confirmed by <name>") so every later session inherits it.
|
|
113
|
+
|
|
114
|
+
What the default does **not** change: the irreducible floor still holds — **one human approval per
|
|
115
|
+
contract** fires no matter the mode. `auto` + `parallel` change the *order and throttle* of the build
|
|
116
|
+
(which tasks run when, and who gates Verify), never *whether* the contract decision point fires. A
|
|
117
|
+
high-risk task still refuses `auto` and forces a lowered rung (run.md guard).
|
|
118
|
+
|
|
71
119
|
## 4 · The one human gate — the baseline approval
|
|
72
120
|
|
|
73
121
|
Open the report with the ARC (goal · done · plan) per `report-template.md`, then present
|
|
@@ -18,7 +18,9 @@ understand the feature — that is information, not an obstacle. Stop and ask.
|
|
|
18
18
|
**Identity is direction, not default (UDD).** For UI/design work, identity values — the brand
|
|
19
19
|
color, the core palette, the typeface — are human-owned. Surface them for discussion during
|
|
20
20
|
Diverge; never assume a brand value. The UDD token dialect checks a token's *shape*; its *value*
|
|
21
|
-
is the user's call (`udd-tokens.md`).
|
|
21
|
+
is the user's call (`udd-tokens.md`). For a UI feature with a screen, run the design-definition
|
|
22
|
+
loop in `design.md` — domain → research and reuse components → wireframe → a real captured screen
|
|
23
|
+
the human confirms before build — and carry the confirmed layout into the contract.
|
|
22
24
|
|
|
23
25
|
## Produce (in TASK.md §1)
|
|
24
26
|
|
|
@@ -63,6 +65,8 @@ Never: resolve an ambiguity by guessing.
|
|
|
63
65
|
"none material" that still names the single biggest risk (never a blank "none").
|
|
64
66
|
</exit_gate>
|
|
65
67
|
|
|
68
|
+
> **Advisor · Confidence** — for an unfamiliar domain, spawn a researcher (advisor.md); self-score the spec and let the lowest dimension aim your ⚠ flag (confidence.md).
|
|
69
|
+
|
|
66
70
|
## Next
|
|
67
71
|
|
|
68
72
|
`python3 .add/tooling/add.py advance` → read `phases/2-scenarios.md`.
|
|
@@ -40,6 +40,8 @@ Never: settle for a vague result ("then it works") — results must be specific
|
|
|
40
40
|
- [ ] Every rejection asserts what stays unchanged.
|
|
41
41
|
</exit_gate>
|
|
42
42
|
|
|
43
|
+
> **Advisor · Confidence** — delegate a wide scenario sweep when the surface is large (advisor.md); score Edge cases honestly — a missing case surfaces there first (confidence.md).
|
|
44
|
+
|
|
43
45
|
## Next
|
|
44
46
|
|
|
45
47
|
`python3 .add/tooling/add.py advance` → read `phases/3-contract.md`.
|
|
@@ -66,6 +66,8 @@ Never: change a frozen contract — a change reopens Specify.
|
|
|
66
66
|
- [ ] Every spec rejection has a contracted response.
|
|
67
67
|
</exit_gate>
|
|
68
68
|
|
|
69
|
+
> **Advisor · Confidence** — a second opinion on a risky shape is worth a spawn (advisor.md); a low self-score is your cue to lower autonomy before you freeze (confidence.md).
|
|
70
|
+
|
|
69
71
|
## Next
|
|
70
72
|
|
|
71
73
|
`python3 .add/tooling/add.py advance` → read `phases/4-tests.md`.
|
|
@@ -55,6 +55,8 @@ Never: implement the feature, or assert on internals.
|
|
|
55
55
|
- [ ] Coverage target recorded.
|
|
56
56
|
</exit_gate>
|
|
57
57
|
|
|
58
|
+
> **Advisor · Confidence** — spawn a test-author for a broad red suite (advisor.md); score Completeness — one test per scenario, every rejection covered (confidence.md).
|
|
59
|
+
|
|
58
60
|
## Next
|
|
59
61
|
|
|
60
62
|
`python3 .add/tooling/add.py advance` → read `phases/5-build.md`.
|
|
@@ -55,6 +55,8 @@ Never: change a test or the contract; use a package off the allow-list; or push
|
|
|
55
55
|
- [ ] Change small enough to review in full.
|
|
56
56
|
</exit_gate>
|
|
57
57
|
|
|
58
|
+
> **Advisor · Confidence** — delegate an independent, well-scoped batch (advisor.md); self-score before you present green, and refine while it is cheap (confidence.md).
|
|
59
|
+
|
|
58
60
|
## Next
|
|
59
61
|
|
|
60
62
|
`python3 .add/tooling/add.py advance` → read `phases/6-verify.md`.
|
|
@@ -82,6 +82,8 @@ before the ask — per that file's reconcile rule (verify is where a flag-vs-dig
|
|
|
82
82
|
(under `autonomy: auto` with no residue) the run auto-resolved as the accountable owner.
|
|
83
83
|
</exit_gate>
|
|
84
84
|
|
|
85
|
+
> **Advisor · Confidence** — the earned-green refute-read is the canonical adversarial spawn (advisor.md); score the verdict before you record the gate (confidence.md).
|
|
86
|
+
|
|
85
87
|
```bash
|
|
86
88
|
python3 .add/tooling/add.py gate PASS # marks the task done
|
|
87
89
|
# or: add.py gate RISK-ACCEPTED | add.py gate HARD-STOP (return to Build)
|
|
@@ -12,6 +12,11 @@ about the feature finally appears. Fill **§7** in TASK.md.
|
|
|
12
12
|
one is a signal), latency of the risky operation under load.
|
|
13
13
|
3. **Draft the next spec delta** — every defect, surprise, or new need becomes a
|
|
14
14
|
concrete change that re-enters the flow at Specify (a new task).
|
|
15
|
+
4. **Propose a voice delta** — you just worked a whole task alongside the human, so
|
|
16
|
+
notice where your voice diverged from theirs (their wordings + flow) and propose a
|
|
17
|
+
confirmable **voice delta** that tunes `SOUL.md`. Emit it `open`; the human confirms;
|
|
18
|
+
only then do you rewrite the routed SOUL.md section. Read `soul.md` for the grammar,
|
|
19
|
+
the routing, and the human-is-only-writer rule.
|
|
15
20
|
|
|
16
21
|
## AI prompt
|
|
17
22
|
|
|
@@ -34,6 +39,8 @@ Never: auto-roll-back — recommend; a human owns the production decision.
|
|
|
34
39
|
- [ ] A reviewed spec delta captured (becomes the next `new-task`).
|
|
35
40
|
</exit_gate>
|
|
36
41
|
|
|
42
|
+
> **Advisor · Confidence** — spawn a reviewer to mine the run for lessons (advisor.md); score Self-evaluation — did this loop teach the foundation? (confidence.md).
|
|
43
|
+
|
|
37
44
|
## Next
|
|
38
45
|
|
|
39
46
|
Loop. The artifacts you built are living documents the next cycle refines.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Self-improving the voice — how SOUL.md converges to the human
|
|
2
|
+
|
|
3
|
+
`SOUL.md` is the AI's voice (tone · communication style · trust). It ships as a **proposed starter**
|
|
4
|
+
and is **human-owned**; this doc is how it stops being write-once and starts converging to *this*
|
|
5
|
+
human. It mirrors `deltas.md` (emit) + `fold.md` (confirm → rewrite), but a confirmed voice delta is
|
|
6
|
+
consolidated into **SOUL.md**, not the foundation — because voice is not one of the five competencies.
|
|
7
|
+
|
|
8
|
+
You (the AI) **emit** voice deltas as `open`. Only the **human** confirms one, and only a confirmed
|
|
9
|
+
delta rewrites SOUL.md. **The human's confirm is the only writer** — you never self-approve a voice
|
|
10
|
+
rewrite (rewriting someone's voice is theirs to approve, like a foundation consolidation).
|
|
11
|
+
|
|
12
|
+
## What a voice delta is drawn from
|
|
13
|
+
|
|
14
|
+
A voice delta is grounded in how the human actually shows up **in session**:
|
|
15
|
+
- their **wordings** — the words they reach for, and the words they correct you on (they cross out a
|
|
16
|
+
bit of jargon and write the plain word over it);
|
|
17
|
+
- their **flow** — what they skip, what they double-check, where they want the summary before the detail.
|
|
18
|
+
|
|
19
|
+
NOT from their private **memory** files or anything outside the working session — SOUL learns from what
|
|
20
|
+
you observed together, never from reading a personal store.
|
|
21
|
+
|
|
22
|
+
## The grammar (mirrors deltas.md)
|
|
23
|
+
|
|
24
|
+
Each voice delta begins on its own tag line; the observation may wrap, and a required `(evidence: …)`
|
|
25
|
+
clause closes it:
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
- [VOICE · <status>] <observation about the voice> (evidence: <in-session pointer>)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
- `<status>` — `open` | `confirmed` | `declined`. A newly emitted delta is **`open`**.
|
|
32
|
+
- `<observation>` — what the voice should become ("lead with the decision, not the preamble").
|
|
33
|
+
- `(evidence: …)` — **required**, non-empty: a moment in the session (a correction, a re-ask, a
|
|
34
|
+
visible preference). No evidence → it is a guess about the human, not a delta. Drop it.
|
|
35
|
+
|
|
36
|
+
```
|
|
37
|
+
- [VOICE · open] the human strips hedging from my drafts — cut "I think / it seems" and state it plainly
|
|
38
|
+
(evidence: they rewrote two replies this session to remove the qualifier)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## The loop — observe → confirm → rewrite
|
|
42
|
+
|
|
43
|
+
1. **Emit** (OBSERVE) — at a task's observe phase (or on demand), propose 0–N voice deltas as `open`
|
|
44
|
+
from the session's wordings + flow. Surface them in the report; show-before-ask.
|
|
45
|
+
2. **Confirm** — the human accepts or declines each. **No SOUL.md write happens without this.**
|
|
46
|
+
3. **Rewrite** — on a confirmed delta, edit the routed SOUL.md section, then record the delta line
|
|
47
|
+
(status `confirmed`) at the **top** of the "Voice deltas" ledger (**newest-first**, append-only — a
|
|
48
|
+
declined delta flips to `declined` and stays in place, so "considered, chose not to" is auditable).
|
|
49
|
+
|
|
50
|
+
## Routing — every voice delta has a SOUL.md home
|
|
51
|
+
|
|
52
|
+
| the delta is about… | rewrite this SOUL.md section |
|
|
53
|
+
|---------------------|------------------------------|
|
|
54
|
+
| how I *sound* (warmth, directness, hedging) | **## Tone** |
|
|
55
|
+
| how I *structure* what I say (summary-first, show-before-ask, length) | **## Communication style** |
|
|
56
|
+
| what keeps the human's *trust* (gates, honesty, what I never do) | **## Trust** |
|
|
57
|
+
|
|
58
|
+
The rewrite is surgical: refine or append the bullet the delta names; never silently rewrite the rest
|
|
59
|
+
of the voice. Every confirmed delta also gets its line in **## Voice deltas** (newest-first).
|
|
60
|
+
|
|
61
|
+
## Reject codes (the AI is first check, the human the backstop)
|
|
62
|
+
|
|
63
|
+
<reject_codes>
|
|
64
|
+
- `unconfirmed_voice_rewrite` — a SOUL.md write was attempted without a recorded human confirm. The AI
|
|
65
|
+
proposes; it never self-approves. Stop and get the confirm. (The identity-owned floor.)
|
|
66
|
+
- `no_open_voice_deltas` — nothing is `open`. The loop is a no-op; do not touch SOUL.md.
|
|
67
|
+
- `unroutable_voice_delta` — the observation maps to no SOUL.md section (not tone/style/trust). Fix the
|
|
68
|
+
delta or widen the routing before writing.
|
|
69
|
+
</reject_codes>
|
|
70
|
+
|
|
71
|
+
## Where it plugs in
|
|
72
|
+
|
|
73
|
+
- **Emit**: `phases/7-observe.md` proposes voice deltas beside its competency/spec deltas.
|
|
74
|
+
- **Target**: `SOUL.md` (scaffolded by setup) — its "## Voice deltas" ledger holds the confirmed history.
|
|
75
|
+
- **Kin**: `deltas.md` (competency learnings → foundation) and `fold.md` (the same propose→confirm→write
|
|
76
|
+
discipline). This is the voice's version of that discipline; the engine stays judgment-free (no
|
|
77
|
+
`add.py` command writes the voice).
|
package/skill/add/streams.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
# Parallel streams — pipelining independent tasks
|
|
2
2
|
|
|
3
|
-
Load this
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Load this when a milestone has more than one task and you want to run them concurrently.
|
|
4
|
+
**Default:** when a project confirms `parallel + auto` as its run mode at setup
|
|
5
|
+
(`phases/0-setup.md` "Run mode"), parallel streaming is the project default — an **opt-out**, not
|
|
6
|
+
the opt-in it once was; downgrade in one step (`add.py autonomy set conservative --project`, or just
|
|
7
|
+
run tasks one at a time). A project that kept the conservative run mode still treats this rubric as
|
|
8
|
+
the opt-in escape hatch. Either way it changes nothing below.
|
|
6
9
|
|
|
7
10
|
It changes **no `add.py` code and no phase semantics**. It is a way *you, the
|
|
8
11
|
orchestrator*, drive several tasks at once by reading the dependency DAG that
|
|
@@ -35,6 +38,44 @@ Compute both from one `python3 .add/tooling/add.py status` — no new state:
|
|
|
35
38
|
└──────────────── a task gating PASS unblocks its dependents ──────────────┘
|
|
36
39
|
```
|
|
37
40
|
|
|
41
|
+
## The DAG strategy — let the engine schedule the waves (`add.py waves`)
|
|
42
|
+
|
|
43
|
+
Do **not** eyeball the READY-QUEUE by hand once a milestone has more than a couple of
|
|
44
|
+
tasks — the engine computes the whole schedule from the dependency DAG `status` already
|
|
45
|
+
holds. `add.py waves` (read-only, writes nothing) groups the active milestone's not-done
|
|
46
|
+
tasks into **topological waves**, names the **critical path**, and emits an advisory
|
|
47
|
+
**tier hint** — exactly the inputs you need to fan out effectively:
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
$ add.py waves
|
|
51
|
+
milestone: v13-onboarding-polish
|
|
52
|
+
wave 1: dag-scheduler, setup-suggest-milestone, setup-domain-deepdive, soul-artifact
|
|
53
|
+
wave 2: setup-run-mode (deps: dag-scheduler), soul-self-improve (deps: soul-artifact)
|
|
54
|
+
critical path: dag-scheduler → setup-run-mode (2 tasks)
|
|
55
|
+
tier hint: top → dag-scheduler, setup-run-mode; mid → the rest
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Read the schedule as a strategy, not a command:
|
|
59
|
+
|
|
60
|
+
- **Wave = a fan-out batch.** Every task in a wave has all its in-milestone deps already
|
|
61
|
+
PASS, so the whole wave is spawnable at once (one worker per task, `isolation="worktree"`).
|
|
62
|
+
Finish a wave, gate its tasks PASS, then `add.py waves` again — the next wave is unblocked.
|
|
63
|
+
- **Run the widest wave first.** It hides the most build latency under the human's review
|
|
64
|
+
latency (the honest frame above): more concurrent builds while the reviewer reads one bundle.
|
|
65
|
+
- **Spend your strongest model on the critical path.** The critical-path tasks gate the most
|
|
66
|
+
downstream work, so a wrong-but-plausible result there is the costliest — give them the
|
|
67
|
+
**top** tier (`run.md` tiers); off-path tasks take **mid**. The tier hint is exactly this rule,
|
|
68
|
+
applied to the graph. It is **advisory** — graph position is a proxy for scope difficulty, not a
|
|
69
|
+
gate; override it when you know a task is harder than its position suggests.
|
|
70
|
+
- **`--json`** (`{ milestone, waves, critical_path, critical_path_len, tiers, blocked }`) feeds a
|
|
71
|
+
runner that spawns the wave programmatically. `blocked` lists any task whose dep can never be
|
|
72
|
+
satisfied within this milestone (a cross-milestone dep) — surfaced, never silently dropped; a
|
|
73
|
+
`dependency_cycle` is refused with the offending members named (no schedule exists).
|
|
74
|
+
|
|
75
|
+
What `waves` does **not** change: the irreducible floor below still holds — one human approval
|
|
76
|
+
per contract, builds overlap but the review queue stays serial. `waves` decides *order and model*,
|
|
77
|
+
never *whether the human gate fires*.
|
|
78
|
+
|
|
38
79
|
## The autonomy level is the throttle (not a new flag)
|
|
39
80
|
|
|
40
81
|
How much concurrency you actually get is set by each task's `autonomy:` header
|