vinta-ai-workflows 0.7.0-alpha9 → 0.7.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.
Files changed (67) hide show
  1. package/CHANGELOG.md +473 -621
  2. package/README.md +33 -19
  3. package/package.json +4 -1
  4. package/schemas/README.md +11 -3
  5. package/schemas/ai-models.v1.schema.json +5 -0
  6. package/schemas/interview-answers.v1.schema.json +122 -0
  7. package/schemas/interview-round.v1.schema.json +346 -0
  8. package/schemas/plan-review.v1.schema.json +342 -0
  9. package/schemas/postmortem.v1.schema.json +848 -3
  10. package/schemas/prs-context-comments.v1.schema.json +1 -1
  11. package/schemas/prs-context-frontmatter.v1.schema.json +18 -7
  12. package/schemas/vinta-ai-workflows-config.v1.schema.json +677 -18
  13. package/schemas/workflow.v1.schema.json +616 -26
  14. package/skills/vinta-analyze-codebase/SKILL.md +5 -0
  15. package/skills/vinta-bootstrap-ai-tools/SKILL.md +154 -31
  16. package/skills/vinta-bootstrap-ai-tools/resources/stacks/README.md +1 -1
  17. package/skills/vinta-bootstrap-ai-tools/resources/stacks/django/notes.md +36 -1
  18. package/skills/vinta-bootstrap-ai-tools/resources/worktree-command/README.md +85 -0
  19. package/skills/vinta-bootstrap-ai-tools/resources/worktree-command/lib-template.sh +160 -0
  20. package/skills/vinta-bootstrap-ai-tools/resources/worktree-command/prepare-template.sh +250 -0
  21. package/skills/vinta-bootstrap-ai-tools/resources/worktree-command/teardown-template.sh +96 -0
  22. package/skills/vinta-derive-skills/SKILL.md +23 -15
  23. package/skills/vinta-derive-skills/resources/dependency-license-block.md +8 -9
  24. package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/SKILL.md +1 -1
  25. package/skills/vinta-derive-skills/resources/foundation-skills/create-qa-use-cases/SKILL.md +3 -3
  26. package/skills/vinta-derive-skills/resources/foundation-skills/create-spec/SKILL.md +21 -2
  27. package/skills/vinta-derive-skills/resources/foundation-skills/handoff/SKILL.md +3 -3
  28. package/skills/vinta-derive-skills/resources/foundation-skills/interview-ui/SKILL.md +121 -0
  29. package/skills/vinta-derive-skills/resources/foundation-skills/interview-ui/resources/examples/docs/D4-concurrency.md +28 -0
  30. package/skills/vinta-derive-skills/resources/foundation-skills/interview-ui/resources/examples/round-01.json +60 -0
  31. package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/SKILL.md +1 -1
  32. package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh +34 -7
  33. package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +363 -142
  34. package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/resources/ai-models.yaml +19 -13
  35. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/SKILL.md +39 -21
  36. package/skills/vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/SKILL.md +8 -6
  37. package/skills/vinta-derive-skills/resources/foundation-skills/thermo-nuclear-review-loop/SKILL.md +181 -0
  38. package/skills/vinta-derive-skills/resources/plan-execution/README.md +40 -7
  39. package/skills/vinta-derive-skills/resources/plan-execution/partials/agent-models.md +14 -35
  40. package/skills/vinta-derive-skills/resources/plan-execution/partials/commit-strategy/stacked.md +21 -0
  41. package/skills/vinta-derive-skills/resources/plan-execution/partials/dispatched-agent.md +31 -0
  42. package/skills/vinta-derive-skills/resources/plan-execution/partials/implementer-prompt.md +67 -6
  43. package/skills/vinta-derive-skills/resources/plan-execution/partials/maestro-live-run.md +44 -0
  44. package/skills/vinta-derive-skills/resources/plan-execution/partials/model-pick.md +9 -3
  45. package/skills/vinta-derive-skills/resources/plan-execution/partials/parallel-lanes.md +95 -50
  46. package/skills/vinta-derive-skills/resources/plan-execution/partials/pr-context.md +4 -2
  47. package/skills/vinta-derive-skills/resources/plan-execution/partials/relay-questions.md +13 -0
  48. package/skills/vinta-derive-skills/resources/plan-execution/partials/review-loop.md +81 -0
  49. package/skills/vinta-derive-skills/resources/plan-execution/partials/worktree-seam.md +86 -17
  50. package/skills/vinta-derive-skills/resources/plan-execution/shell/amend-plan-template.md +35 -16
  51. package/skills/vinta-derive-skills/resources/plan-execution/shell/implement-phase-template.md +12 -1
  52. package/skills/vinta-derive-skills/resources/plan-execution/shell/implement-plan-template.md +49 -33
  53. package/skills/vinta-derive-skills/resources/plan-execution/shell/integrate-phase-template.md +2 -1
  54. package/skills/vinta-derive-skills/resources/plan-execution/shell/review-phase-template.md +19 -27
  55. package/skills/vinta-derive-skills/resources/prs-context-template.md +5 -4
  56. package/skills/vinta-derive-skills/resources/systematic-debugging-mcp-tools.md +1 -1
  57. package/skills/vinta-derive-skills/resources/systematic-debugging-template.md +8 -8
  58. package/skills/vinta-derive-skills/resources/write-unit-test-packs/stacks/django.md +4 -1
  59. package/skills/vinta-derive-skills/resources/write-unit-test-template.md +3 -0
  60. package/skills/vinta-derive-subagents/SKILL.md +25 -9
  61. package/skills/vinta-install-ai-tools-setup/SKILL.md +29 -2
  62. package/skills/vinta-migrate-plans-specs/SKILL.md +7 -7
  63. package/skills/vinta-sync-ai-tools/SKILL.md +19 -2
  64. package/skills/vinta-update-project-skills/SKILL.md +1 -0
  65. package/skills/vinta-write-agents-md/SKILL.md +10 -6
  66. package/skills/vinta-write-agents-md/resources/asking-the-human.md +56 -0
  67. package/skills/vinta-derive-skills/resources/plan-execution/partials/review-layers.md +0 -101
package/CHANGELOG.md CHANGED
@@ -5,635 +5,489 @@ All notable changes to `vinta-ai-workflows` are documented in this file.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
6
6
  the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
- ## [0.7.0] — YYYY-MM-DD
9
-
10
- <!-- pre-release: 0.7.0-alpha9 on 2026-09-14 -->
11
- <!-- pre-release: 0.7.0-alpha8 on 2026-09-14 -->
12
- <!-- pre-release: 0.7.0-alpha7 on 2026-09-14 -->
13
- <!-- pre-release: 0.7.0-alpha6 on 2026-09-13 -->
14
- <!-- pre-release: 0.7.0-alpha5 on 2026-09-13 -->
15
- <!-- pre-release: 0.7.0-alpha4 on 2026-09-13 -->
16
- <!-- pre-release: 0.7.0-alpha3 on 2026-09-12 -->
17
- <!-- pre-release: 0.7.0-alpha2 on 2026-09-12 -->
18
- <!-- pre-release: 0.7.0-alpha1 on 2026-09-11 -->
8
+ ## [0.7.0] — 2026-11-03
9
+
10
+ <!-- Graduates the 0.7.0-alpha1 … 0.7.0-alpha39 series (2026-09-11 to
11
+ 2026-10-24). This section is the net change since 0.6.1. The
12
+ alpha-by-alpha record is in the GitHub pre-releases and in this file's
13
+ git history before the release commit. -->
19
14
 
20
15
  ### Added
21
16
 
22
- - **A project declares what makes a lane runnable.** `project.env_files` copies
23
- ignored configuration into each worktree, `project.setup_cmd` runs an
24
- idempotent setup hook on provisioning and recycle, and the fixed
25
- `project.commands` vocabulary tells implementers, reviewers and fixers the
26
- project's real lint, typecheck, test and migration entry points.
27
-
28
- - **Compose-backed lanes are isolated past `COMPOSE_PROJECT_NAME`.** The daemon
29
- now generates an out-of-tree Compose override per lane, strips fixed host
30
- ports, re-pins fixed and external volumes, and carries the complete lane
31
- environment into agent and takeover processes as well as gates. Explicitly
32
- published services receive probed per-lane ports recorded in the teardown
33
- summary.
34
-
35
- - **Shared services get one namespace per lane.** `project.services` models a
36
- fixed index or lane-derived name inside one Redis, RabbitMQ, object-storage,
37
- or similar server, with project-owned create/reset commands and capacity
38
- validation before provisioning creates templates or worktrees.
39
-
40
- - **Agents can take the semaphore a workflow declares.**
41
- `vinta-ai-maestro with <resource> -- <cmd>` waits on the run's existing
42
- `ResourcePools`, runs the heavy inner-loop command, and releases on exit.
43
- Renewable leases expire when their client disappears, are visible in the
44
- live journal, and are surfaced in implementer, reviewer and fixer prompts.
45
-
46
- - **A failed phase retries itself, and then asks.** `--on-failure` defaults to
47
- `retry`: one cold re-attempt (`--retries <n>`, 0–5), and then the node parks
48
- on a question — retry, retry with another member of the crew, or stop. The
49
- failures this system produces are overwhelmingly environmental and are gone by
50
- the second attempt; the ones that survive it are the ones worth a person.
51
- `ask` skips the automatic attempt. `stop` is the old behaviour and remains the
52
- right choice for CI, because everything else eventually **waits**.
53
-
54
- A failure that survives its retries says so: the reason carries
55
- `(after N attempts)`, which no event otherwise records.
56
-
57
- - **A failed phase can be retried by hand.** A **Retry phase** button, and
58
- `POST /api/runs/:runId/nodes/:nodeId/retry`. It returns the node to the ready
59
- set and unblocks the subtree its failure blocked — a phase that died of
60
- something environmental holds up work that was never broken. It needs the run
61
- to still be in flight, which with the new default it usually is; a run that
62
- has genuinely ended is re-run, not retried, and says so rather than doing
63
- nothing.
64
-
65
- - **The monitor can go and look.** It was given a digest and nothing else, and
66
- read exactly as thin as that sounds — it could say a phase had failed and
67
- never say what the phase had written. It is briefed as a technical project
68
- manager now, with the map: the plan document, each phase's brief, each lane's
69
- worktree path, each branch and its base, and where the journal and transcripts
70
- live. It has a shell and its working directory is the repository, so it can
71
- read the diff before drawing a conclusion. The digest stays as the index —
72
- bounded, cheap, enough to know which phase is worth a closer look.
73
-
74
- - **The monitor conversation is kept.** It lived in component state, so a reload
75
- threw away every question and every answer — a worse record than the run it
76
- describes. It is written to the transcript store under a reserved node id and
77
- read back on load, so it outlives the tab, the daemon and the run.
78
-
79
- - **Panels expand.** Anything holding content that is only nominally
80
- summarisable — an agent's transcript, a gate log, the monitor conversation,
81
- the steering box — takes the full container width and about a screen of
82
- height on demand. The height travels as a CSS variable, because the element
83
- that has to grow is a scroller several components below the panel.
84
-
85
- - **A run has a spokesperson you can ask.** `serve` grows a **Monitor** panel on
86
- the run view: one agent that reads the journal and answers in prose — what is
87
- blocked, why a phase failed, what it would take to move on. It runs on the
88
- dearest tier on the crew, because it is read by a person deciding what to do
89
- about a failing run, and it is asked a handful of times rather than hundreds.
90
-
91
- Three things it deliberately is not.
92
-
93
- **It is not in the permission path.** The obvious thought, once an agent has
94
- been refused something, is to put a smarter agent in front of the refusals —
95
- but a phase makes hundreds of tool calls (one node in one real run made 179)
96
- and a model turn before each is latency and cost spent on questions like "may
97
- I run ruff", which should never have been questions. Permissions are settled
98
- structurally, once per spawn, for free.
99
-
100
- **It does not read the transcripts.** Piping every agent's output into a
101
- second agent would make the monitor the most expensive thing in the run and
102
- tie its cost to the work rather than to the questions. It reads a bounded
103
- digest — statuses, failure reasons, pending questions, the last few refusals
104
- with their sentences, one trimmed last word per phase — so a one-hour run and
105
- a one-day run cost about the same to ask about.
106
-
107
- **It has no authority.** It can explain a §9.1 pause; it cannot answer one.
108
- An agent that could quietly approve its colleagues' work would turn a
109
- checkpoint into a formality, and the checkpoint is the point.
110
-
111
- It answers about **finished runs too**, which is when "why did this fail" is
112
- usually asked, and it needs no lane: it writes nothing.
113
-
114
- - **`serve` reads `--permission`.** The flag has been accepted and ignored since
115
- it existed. It decides how the monitor is spawned, so it is read now.
116
-
117
- - **A plan staffs a team, instead of picking a model per phase.** Choosing a tier
118
- phase by phase answers "what runs this one" ten times and never adds it up, so the
119
- two questions that decide what a feature costs go unasked: how many agents does
120
- this need at once, and is any of them too junior for what it was handed.
121
- - `plan-feature` opens **Phased Rollout** with a **Crew** table — one row per
122
- agent, carrying its tier and the phases it takes — and every phase carries an
123
- **`**Assigned to**:`** line naming one of them. It replaces
124
- `**Suggested AI model**:`; a plan that still has the old line keeps working, and
125
- the executor reads the tier straight off it.
126
- - The **Execution graph** table gains an **Agent** column and an **Idle** note.
127
- Reading across a row says who is working that wave; reading down a column says
128
- who is not. A wave that will serialize because the roster cannot staff it is now
129
- stated in the plan rather than discovered as a slow run.
130
- - **Every member has to earn their place**, by concurrency (a wave genuinely needs
131
- that many hands *at or above* those phases' tiers) or by cheapness (they take
132
- work a dearer member would otherwise do). The roster is therefore **not** capped
133
- at the widest wave — a junior who runs the migration and the flag deletion is
134
- worth having in a graph that never runs two phases at once — but the lane pool
135
- still is, because lanes are bought with concurrency and crew are not.
136
- - **Reviewers are a role on the crew, and implementers and reviewers are
137
- disjoint.** A member has `role: implementer` or `role: reviewer`; a phase cannot
138
- be assigned to a reviewer and a reviewer never writes code, so an agent reading
139
- its own diff is not something a plan can express. A phase is read by the
140
- cheapest reviewer at or above its tier. A roster with no reviewer still runs and
141
- falls back to `agent_models.reviewer`, cold, one session per phase.
142
- - **A reviewer reads the lane it is reviewing**, with the phase's changes still
143
- uncommitted in it, and has no worktree of its own. That is what puts review
144
- before the commit: a finding is fixed in the working tree rather than
145
- recorded as a mistake on the branch plus a correction after it. The cost is
146
- that a reviewer's directory follows the work, so its session carries only
147
- between reviews that land in the same lane.
148
- - **A crew member is an agent that lives for the whole run.** Each one keeps its
149
- own worktree and its own session across every phase it takes, so the agent that
150
- takes Phase 4 still knows what it learned about the codebase in Phase 1 —
151
- which is most of what a cold agent's first turn of a phase is spent
152
- rediscovering.
153
- - This works because the *directory* stops moving. Lanes used to be anonymous
154
- slots handed out by a free list, so a member landed somewhere different each
155
- phase and its context described paths it was not standing in. Pinning each
156
- member to one worktree leaves a far smaller question — which files changed —
157
- and `git diff --name-only` answers it exactly.
158
- - A cross-phase continuation therefore gets the new phase's **full brief** (it
159
- is new work, not a delta) behind a re-orientation: same agent, same directory,
160
- everything you learned still holds; the tree is on a different branch; these
161
- files differ; and — the sentence that matters most — whether the previous
162
- phase's own work is in this tree at all.
163
- - A delta that cannot be computed is reported as **unknown**, never as empty.
164
- "Nothing changed" is the one wording that would stop an agent re-reading.
165
- - Two things still start cold: a member whose previous phase **failed**, because
166
- its session is the context that failed with it, and the final fix round.
167
- - The cost, stated plainly: **one worktree and one set of forked databases per
168
- implementer**, so `resources.lane.capacity` is now the implementer count
169
- rather than the widest wave, and adding a cheaper implementer is a trade of
170
- disk against money rather than free.
171
- - The workflow document gained a top-level **`crew`** block and **`nodes[].crew`**.
172
- A staffed node carries no `model` — the member has one — and a document that is
173
- half-staffed, names a member nobody declared, assigns a phase to a reviewer,
174
- declares an implementer nobody is assigned to, or staffs a reviewer below every
175
- phase on the plan is refused before the run starts.
176
- - `vinta-ai-maestro` claims an agent **before** the lane, prefers the member the plan
177
- named, covers with the **cheapest** qualified free peer when they are busy, and
178
- **waits rather than handing a phase below its tier** — even with a lane free. A
179
- lane is disk; a phase run by too junior an agent does not fail cleanly, it fails
180
- review two rounds later with nothing pointing back at the staffing. A reviewer is
181
- claimed per review turn rather than per phase — it has one session ledger and
182
- two concurrent reviews would collide over it — so one reviewer on a three-lane
183
- plan is a queue at the review step and not a serialised run.
184
- - The run view reports who actually worked against who the plan said would.
185
- `substituted` is the figure to read beside a cost that overran: every
186
- substitution ran at or above the budgeted tier, so a run can be entirely green
187
- and still have been staffed dearer than planned.
188
-
189
- - **`implement-plan` runs independent phases in parallel.** The plan now carries a
190
- dependency graph and the conductor schedules against it: a phase starts as soon as
191
- every phase it depends on is green and a worktree lane is free, instead of waiting
192
- for its turn in plan order. A chain-shaped plan behaves exactly as before —
193
- sequential execution is the one-lane case of the same scheduler.
194
- - `plan-feature` gives every phase a **`**Depends on**:`** line naming the artifact
195
- it needs from each upstream phase, and opens **Phased Rollout** with an
196
- **Execution graph** table derived from those lines. It also checks same-wave
197
- phases against the **Touch List** for file overlap and tells you to add an edge
198
- when two phases would fight over the same file.
199
- - New shared partial `plan-execution/partials/parallel-lanes.md` carries the graph
200
- parse, the worktree lane pool, the dependency-derived branch topology, the
201
- dispatch loop, the tracking-directory schema, and the sibling-lane write guard.
202
- - `prepare-worktree` documents provisioning a **pool** of lanes for one plan and
203
- records a `reset_cmd` per forked DB so a lane can be reused across phases without
204
- carrying the previous phase's migrations into the next one's test run.
205
- - Two new config fields: `run_options.implement-plan.parallel_phases` (default
206
- `true`) and `run_options.implement-plan.max_parallel_lanes` (default `3`), asked
207
- at bootstrap alongside the existing `prepare-worktree` follow-ups.
208
-
209
- - **`plan-feature` emits an executable `ai-plans/<feature-kebab>.workflow.json`
210
- beside every plan.** The markdown stays the document humans review; the JSON is
211
- the same phase graph in the form an orchestrator runs — one node per phase, one
212
- `depends_on` entry per `**Depends on**:` clause carrying both the upstream phase
213
- and the artifact it provides, plus the phase's Touch List, gates, capacity pools
214
- and model tier. Validated by
215
- [`schemas/workflow.v1.schema.json`](schemas/workflow.v1.schema.json), which the
216
- emitted file references from its `$schema` key so editors validate it as it is
217
- written. **Unconditional** — no config field, no bootstrap question, no opt-in:
218
- a project with no orchestrator carries a file nothing reads, and a project that
219
- adopts one later finds its plans already executable.
220
-
221
- - **Review findings go back to the phase's own implementer, not to a fresh fixer.**
222
- The agent that wrote the code still holds the phase brief, the plan's bounds, the
223
- dependency context and its own reasoning; a fresh fixer held a quoted finding and
224
- had to rediscover the rest — slower, dearer, and likelier to "fix" a symptom by
225
- undoing something the phase chose deliberately. The fix message is now a delta —
226
- the findings, nothing else — because re-sending the brief invites a
227
- re-implementation rather than a fix.
228
-
229
- Three rules keep that from costing what it buys. **The reviewer is never the
230
- implementer**: continuing the reviewer across rounds is fine, but the review must
231
- come from an agent that did not write the code. **The last round before giving up
232
- goes to a fresh fixer, always** — reuse means the agent that wrote the bug is
233
- fixing it, which is usually the point and occasionally exactly wrong, because that
234
- assumption *was* the bug. And where a runtime cannot continue a finished
235
- sub-agent, the old cold hand-off still happens and is recorded as one, so a slow
236
- phase can be read later without guessing.
237
-
238
- One consequence worth knowing: a continued implementer fixes at its own crew
239
- member's tier, so `agent_models.fixer` now governs only the cold cases. A project
17
+ - **`vinta-ai-maestro`: a `plan-feature` plan runs itself, phases in parallel,
18
+ with you steering from a terminal or a browser.** A new workspace package,
19
+ `packages/vinta-ai-maestro/`, published as its own npm package under the same
20
+ version number as `vinta-ai-workflows` and run with `npx vinta-ai-maestro`
21
+ (Node ≥ 22). It is not part of the `vinta-ai-workflows` tarball: what reaches
22
+ the skills package is the generated schemas below and the skill changes that
23
+ produce and consume them. [SPEC.md](packages/vinta-ai-maestro/SPEC.md) is the
24
+ authority and the package README is the operator's manual.
25
+ - **A run.** `run <workflow.json>` starts the plan's `.workflow.json` as a
26
+ background job and returns; closing the terminal changes nothing
27
+ (`--foreground` keeps it in the process, for CI). The run works on a plan
28
+ branch, `plan/<workflow-id>/base`, cut from `base_branch`. Each phase gets a
29
+ crew member, a lane — a git worktree with its own copy of the dependency
30
+ dirs, forked `dev` / `test` databases, an isolated compose project, a
31
+ namespace in each shared service, the declared `env_files` and a
32
+ `setup_cmd` — and the `standard-phase` pipeline: implement, gates, review,
33
+ polish chores, verify, integrate (merge, gates on the merged tree, push,
34
+ PR), `after_pr` chores. A phase with one dependency branches from it, one
35
+ with several from an `integ-<id>` merge; each wave merges into
36
+ `plan/<id>/wave-<N>`, and the last wave opens the plan PR, the one PR that
37
+ lands the plan. `run --resume <run-id>` picks a paused, interrupted or
38
+ failed run back up with the policy it was started with. Policy flags:
39
+ `--on-failure retry|ask|stop` (default `retry`: one cold attempt, then a
40
+ question), `--retries`, `--retry-after <15m>` (an unanswered failure
41
+ question answers itself, backing off when attempts fail fast),
42
+ `--agent-answer-after` (how long an agent's own question waits before the
43
+ recommended options are taken), `--permission ask|auto|full|judged`
44
+ (default `auto`), `--harness-profile <name>` (a named binary and
45
+ environment — a second account, say — from
46
+ `~/.config/vinta-ai-maestro/profiles.yaml`), `--system-one <config.json>`,
47
+ `--no-coordinator` and `--coordinator-authority full`.
48
+ - **Harnesses.** claude-code, codex (`codex app-server`, codex-cli ≥ 0.147.0)
49
+ and opencode, behind one adapter contract: spawn, resume, inject a message
50
+ into a running turn, wait for background work, compact. A quota, rate-limit
51
+ or concurrency refusal parks the harness, not the phase, until the reset
52
+ time the vendor stated; `defaults.model_fallbacks` and
53
+ `defaults.harness_fallbacks` move the refused spawn to a fallback instead;
54
+ a provider outage re-runs the phase when the harness answers, charging
55
+ nothing to its attempts; a logged-out CLI asks you to log in. Sessions
56
+ start one at a time per harness, and the ceiling a run discovers is kept
57
+ for the next one.
58
+ - **The crew.** A plan staffs a team, the Crew table `plan-feature` writes:
59
+ one member per agent with a tier, a model and a harness, and every phase
60
+ assigned to one of them. A member keeps its worktree and its session across
61
+ the phases it takes, so what it learned in phase 1 is still there in
62
+ phase 4. A busy member is covered by the cheapest qualified free peer or by
63
+ a spare in its image (`defaults.max_spare_crew`, default 2); a phase is
64
+ never handed below its tier (`defaults.substitution`, default
65
+ `up_one_tier`); a phase its review keeps rejecting moves up a tier
66
+ (`defaults.escalate_after_rejections`, default 3); a merge conflict goes to
67
+ the most senior member who wrote one of its sides.
68
+ - **Gates.** A gate is a shell command, by type (`test`, `lint`, `typecheck`,
69
+ `e2e`, taking the project's `commands.*`) or by a project-wide id
70
+ (`maestro.gates.<id>`), or a judge question put to a System One classifier.
71
+ Phase gates run a `scoped_cmd` (`{changed_files}` / `{touches}`) until the
72
+ review approves; `verify` then runs the full `cmd` on the phase branch, and
73
+ the full suite runs on every merged base and wave (`verify_gates`,
74
+ `base_gates`, `wave_gates`, all full by default). Results are cached per
75
+ gate, command and tree. `fresh_cmd` and `fresh_when` run a gate from a
76
+ fresh test database when the tree moved under it; `cold_cmd` and
77
+ `scope_cache` cover a lane with no test cache; `timeout_s`,
78
+ `queue_timeout_s` and `tuning.allowed_flags` bound and retune a gate.
79
+ Resource pools (`resources`, `scope: run | host`) serialise the heavy ones
80
+ across lanes, and across every maestro run on the machine. Agents run a
81
+ gate with `vinta-ai-maestro gate <id>` and take a pool with
82
+ `vinta-ai-maestro with <resource> -- <cmd>`; on claude-code a `PreToolUse`
83
+ gate guard refuses the bare command, and `--permission judged` asks a
84
+ classifier about each shell call. `codegen` steps regenerate generated
85
+ files rather than merging them, `append_only` files merge as a union,
86
+ `post_merge` runs a formatter over what git merged, and `ci_only` records
87
+ the CI checks deliberately left to CI.
88
+ - **Review and chores.** Once a phase's gates are green, the implementer's
89
+ own session runs the `review` chore, `thermo-nuclear-review-loop`: one
90
+ reviewer sub-agent, each finding verified and fixed or rejected with
91
+ counter-evidence, until the reviewer explicitly approves. A phase's
92
+ decisions — answered questions, operator context, rejected findings — are
93
+ kept and carried into every later prompt, so nothing is asked twice.
94
+ `deslop` and the project's other `after_review` chores run before verify;
95
+ `after_pr` chores (a review canvas, say) run once the PR is open. A chore
96
+ reporting `Status: FAILURE` is recorded as failed. `max_fix_rounds` is
97
+ unset by default, which means no limit; set it to be asked.
98
+ - **Integration.** A conflict goes to a conflict fixer in the integration
99
+ worktree, with a time limit per round and its resolution gated by the union
100
+ of both phases' gates; what a round left is kept under
101
+ `refs/vinta-ai-maestro/` across attempts. A resolution that undoes a
102
+ phase's deletion is flagged. A merge git or a hook refuses goes to you.
103
+ Every phase and integration PR carries a **Landing** section pointing at
104
+ the plan PR; `land <run>` says how a finished run lands and closes the PRs
105
+ whose work is already in the base; `propagate <run> <phase>` carries a late
106
+ fix into every `integ-` and `wave-` branch; `sync-base <run>` brings a moved
107
+ `base_branch` into a live plan.
108
+ - **Steering.** `status`, `logs [-f]`, `logs --failures <gate-log>`, `pause`,
109
+ `stop`, `node context|redirect|pause|resume|abort|retry|fresh|answer`,
110
+ `node interrupt|reassign|step` (take a phase over at its step without
111
+ failing it), `switch-harness`, `fixer interrupt|reassign`, `workflow`,
112
+ `amend` (a live run takes an edited workflow, rebasing the done phases the
113
+ change reaches), `exec <run> <lane|integration> -- <cmd>` (a command with
114
+ the lane's environment, holding the integration worktree while it runs),
115
+ `gate-cache invalidate`, `purge [--lanes --branches]` (never the only copy
116
+ of work), `doctor` (every check a run depends on, from disk and servers to
117
+ env files, compose `-T`, gate scope and the CI jobs no gate covers),
118
+ `validate`, `simulate` and `judge calibrate`. Every acting request takes a
119
+ reason, journalled with what it explains.
120
+ - **The run coordinator.** One agent per run, woken when a phase fails, an
121
+ attempt errors, a phase waits on the integration worktree or a gate crosses
122
+ its cost threshold, at most 24 times a run. It reads the journal and the
123
+ repository and acts through the same API as you: steer, pause, retry,
124
+ answer the questions a timer could answer, amend the live run, run a
125
+ command. It may change how the run executes, never what it builds, and
126
+ never weakens a check. Everything decided without you — by it or by a
127
+ timer — is listed in `status`, the run view, the plan PR and the
128
+ post-mortem.
129
+ - **The browser UI.** `ui` serves every run in the project and hosts none,
130
+ so closing it interrupts nothing. A run view with the plan graph, the
131
+ roster, the integration worktree's record, resource pools, sessions and
132
+ cost, what was decided without you, a notifications inbox and the
133
+ coordinator as a sidebar; a phase view with the transcript rendered the way
134
+ the harnesses render it, the phase's running processes and gates, its
135
+ changes as a diff, its integration timeline, its PR, and steering as a chat
136
+ input; an analytics page while the run goes and the post-mortem as a report
137
+ after; a Logs view over the daemon's own log; a workflow editor that saves
138
+ only what you changed; Pause, Stop, Retry and Resume. Every page fits a
139
+ phone, in light and dark.
140
+ - **The record.** Everything lands under `.vinta-ai-maestro/` (gitignored):
141
+ the run's journal, each phase's transcript with the role that wrote each
142
+ line, gate logs, the daemon's own log (`logs/daemon.ndjson`, identifiers
143
+ only, enforced), and once the run ends a post-mortem (`postmortem.v1`):
144
+ dependencies declared but unused or discovered at gate time, conflicts,
145
+ the critical path, idle capacity, gate costs, failure causes, crew
146
+ substitutions, failed chores and unattended decisions. `plan-feature` reads
147
+ it before planning the next feature in the same repository.
148
+ - **Security.** The daemon binds loopback and every API request carries a
149
+ token. Agents hold a token of their own that reaches only their leases,
150
+ gates and hooks; the coordinator has one of its own; a run's job keeps its
151
+ token in a `0600` file that `ui` never prints. Nothing in the journal or
152
+ the log holds repository contents, and every token is redacted from both.
153
+ The only API key the package ever uses is the one a `--system-one`
154
+ classifier config names; the harnesses run on your logged-in CLIs.
155
+ - **Platforms.** macOS, Linux and Windows, each in CI.
156
+
157
+ - **`vinta-design-system` and `vinta-dag-editor`**, two more workspace
158
+ packages maestro's UI is built on: oklch tokens in three layers, six
159
+ run-status tones (waiting is amber and failure is red, never the same hue),
160
+ shadcn/ui components on Tailwind CSS v4 and a light/dark/system theme; and
161
+ the framework-agnostic Web Component that draws and edits plan DAGs —
162
+ arrowed edges, dependencies drawn by dragging, phase ids on the cards, a
163
+ details strip, keyboard zoom, full screen. They publish on their own cadence
164
+ as dependencies of `vinta-ai-maestro`; nothing in either reaches
165
+ `npx vinta-ai-workflows install`.
166
+
167
+ - **Plan review: a page for a plan before it runs, and a chat with the agent
168
+ that wrote it.** `vinta-ai-maestro review open <workflow.json>` serves the
169
+ plan's graph with every phase's real prompts, the plan's markdown, a phase ×
170
+ gate matrix, the projected schedule and what `validate` reports. You comment
171
+ on the plan, a phase, a prompt or a gate and send the batch; the agent answers
172
+ through `review wait` and `review reply`, edits the plan, and **Approve plan**
173
+ ends the loop. The review is committed beside the plan as
174
+ `ai-plans/<id>.review.json` (`plan-review.v1`, see
175
+ [packages/vinta-ai-maestro/SPEC.md § 19](packages/vinta-ai-maestro/SPEC.md)).
176
+ When maestro is installed, `plan-feature` runs `validate --json` on every
177
+ workflow it writes and asks whether to review on the page, in chat, or later.
178
+
179
+ - **The browser interview.** A decision-heavy interview — `create-spec`'s
180
+ Step 0 first — can run as a full-screen browser form instead of a chat
181
+ exchange: one decision per screen with the context the agent already knows,
182
+ Markdown, Mermaid or HTML explainers, option cards that state each option's
183
+ consequences with the recommended default marked, and a question panel for
184
+ asking the agent. Round-based and file-based, so it works the same under
185
+ every harness: the agent writes
186
+ `.vinta-ai-workflows/interviews/<slug>/rounds/round-NN.json`
187
+ (`interview-round.v1`), blocks on `vinta-ai-maestro interview wait`, and
188
+ resumes when the page submits `answers/round-NN.json`
189
+ (`interview-answers.v1`). The page is maestro's
190
+ (`interview start|wait|status|stop --dir <dir>`,
191
+ [SPEC.md § 20](packages/vinta-ai-maestro/SPEC.md)), rendered with the design
192
+ system; the server binds loopback, carries a token in the printed URL,
193
+ serves documents only from the interview's `docs/` and accepts a round's
194
+ answers once. Opt in with the new `interview-ui` foundation skill (bootstrap
195
+ **Optional foundation skills** question 7, `foundation_skills.interview-ui`
196
+ in the config schema); it ships `SKILL.md` and an example round, and needs
197
+ `vinta-ai-maestro` runnable from the project (`npx --no-install
198
+ vinta-ai-maestro` when it is a devDependency, `npx vinta-ai-maestro`
199
+ otherwise). `create-spec` asks once per interview whether to decide in the
200
+ browser or in chat; projects without the skill see no change.
201
+
202
+ - **`thermo-nuclear-review-loop` foundation skill.** A review-and-fix loop
203
+ over a change: the agent running it spawns one reviewer sub-agent, checks
204
+ each finding against the code, fixes the justified ones and answers the rest,
205
+ until the reviewer explicitly approves under a strict code-quality standard.
206
+ Questions only a person can settle — unreachable scenarios, requirement
207
+ ambiguity, destructive operations — go to them instead of being assumed.
208
+ Always shipped (`foundation_skills.thermo-nuclear-review-loop`), because
209
+ `review-phase` runs it and every maestro workflow names it in its `review`
210
+ chore; also invokable on its own.
211
+
212
+ - **`plan-feature` emits an executable workflow and staffs a crew.**
213
+ `ai-plans/YYYY-MM-DD-<feature-kebab>.workflow.json` lands beside every plan,
214
+ unconditionally — a project with no orchestrator carries a file nothing
215
+ reads, and one that adopts maestro later finds its plans already executable.
216
+ It is the same phase graph in the form a run loads: one node per phase,
217
+ `depends_on` from each phase's `**Depends on**:` line, its Touch List, gates,
218
+ pools and crew member, validated by `workflow.v1`. The plan opens **Phased
219
+ Rollout** with a **Crew** table and an **Execution graph** table, and every
220
+ phase carries `**Assigned to**:` and `**Depends on**:` lines; they replace
221
+ `**Suggested AI model**:`, which old plans may keep. The skill asks what a
222
+ phase lane needs its own copy of and writes the workflow's `project` block,
223
+ emits the codegen steps and append-only files it detects in the project,
224
+ writes the crew's model fallbacks, puts a contract test for any interface two
225
+ parallel phases share into the foundation phase, and reads the post-mortems
226
+ of earlier runs before drawing the next graph.
227
+
228
+ - **`implement-plan` runs independent phases in parallel** on the skills path
229
+ too, with no maestro. The plan carries a dependency graph and the conductor
230
+ schedules against it: a phase starts as soon as every phase it depends on is
231
+ green and a worktree lane is free. A chain-shaped plan behaves exactly as
232
+ before. Lanes are a pool of worktrees, branches base on their dependencies
233
+ (`integ-<id>` for several, `plan/<id>/wave-<N>` per wave), tracking is a
234
+ directory with one file per phase so wave merges never conflict on it, a
235
+ sibling-lane write guard covers the pool, and `modular-commits` keeps its
236
+ atomic units on lane branches. Two new config fields:
237
+ `run_options.implement-plan.parallel_phases` (default `true`) and
238
+ `max_parallel_lanes` (default `3`). The skill refuses rather than degrading
239
+ when parallel execution is asked for and worktrees are unavailable.
240
+
241
+ - **Provision worktrees with your own script instead of the `prepare-worktree`
242
+ skill.** Set `commands.worktree_prepare` (and optionally
243
+ `commands.worktree_teardown`) in `.vinta-ai-workflows.yaml`; `implement-plan`
244
+ and maestro run that command for every lane and the integration worktree,
245
+ with `VINTA_WORKTREE_NAME`, `_PATH`, `_BRANCH`, `_BASE_REF`, `_KIND`,
246
+ `VINTA_MAIN_CHECKOUT`, `VINTA_PLAN_PATH` and `VINTA_WORKTREE_SUMMARY` set,
247
+ and check the result with git rather than trusting the exit code. The
248
+ bootstrap offers existing worktree scripts `vinta-analyze-codebase` found,
249
+ and can write the scripts for you — `prepare.sh`, `teardown.sh` and `lib.sh`
250
+ under `scripts/worktree/`, from templates that carry the contract, dry runs,
251
+ rollback, compose isolation and a teardown that refuses a dirty worktree.
252
+
253
+ - **Agents stop for input with clickable questions instead of prose.** Every
254
+ skill and sub-agent asks through the harness's structured question tool
255
+ (Claude Code's `AskUserQuestion`, OpenCode's `question`, Codex's
256
+ `request_user_input`, Cursor's `AskQuestion`, Copilot's `askQuestions`,
257
+ Gemini CLI's `ask_user`): 2–4 options with descriptions, the recommended one
258
+ first. `AGENTS.md` gains an **Asking the human** section, copied verbatim
259
+ from
260
+ [`vinta-write-agents-md/resources/asking-the-human.md`](skills/vinta-write-agents-md/resources/asking-the-human.md).
261
+ Sub-agents, which cannot ask, return `status: NEEDS_INPUT` with the question
262
+ in the tool's shape, and the new `plan-execution/partials/relay-questions.md`
263
+ turns it into a question, records the answer and continues the same agent.
264
+ Every prose stop point across the plan-execution unit, the foundation skills
265
+ and the bootstrap skills became such a question. `vinta-sync-ai-tools` adds
266
+ a one-time migration for existing projects.
267
+
268
+ - **PR Review Canvas integration (`integrations.pr-review-canvas`).** The
269
+ bootstrap offers [PR Review Canvas](https://github.com/vintasoftware/pr-review-canvas)
270
+ as its first *integration*: an external tool that installs its own skill,
271
+ nothing of which is bundled here. A new optional top-level `integrations`
272
+ object in the config schema records the opt-in (interview group D.2, asked
273
+ when `code_host` is GitHub or GitLab and `pr_creation` is `agents-create`).
274
+ When enabled, `vinta-install-ai-tools-setup` runs `pr-review install-skill`
275
+ (the CLI is never auto-installed; the install command is printed), the
276
+ `integrate-phase` PR step runs `/pr-review-canvas <n>` after `open-pr.sh`
277
+ publishes, and `plan-feature` adds an `after_pr` `review-canvas` chore to the
278
+ workflow it writes. The analysis, derive and update skills treat an
279
+ integration-owned skill as the tool's and never edit it.
280
+
281
+ - **Model fallbacks for models that run out of quota.** `ai-models.yaml`
282
+ entries take `fallback:` (the shipped table sets
283
+ `claude-fable-5-1 → claude-opus-5-5` and `gpt-6-astra → gpt-5.6-sol`),
284
+ `ai-models.v1.schema.json` gains the optional field, the nightly
285
+ `check-ai-models` job checks fallback ids for staleness, `plan-feature`
286
+ writes the map into each workflow's `defaults.model_fallbacks`, and the
287
+ plan-execution skills follow the same rule when maestro is not running them.
288
+
289
+ - **Five generated JSON Schemas, and the schemas are checked.**
290
+ [`workflow.v1`](schemas/workflow.v1.schema.json) (the executable plan),
291
+ [`postmortem.v1`](schemas/postmortem.v1.schema.json),
292
+ [`plan-review.v1`](schemas/plan-review.v1.schema.json),
293
+ [`interview-round.v1`](schemas/interview-round.v1.schema.json) and
294
+ [`interview-answers.v1`](schemas/interview-answers.v1.schema.json) are
295
+ generated from zod sources in `vinta-ai-maestro` and byte-compared in its
296
+ tests; see [`schemas/README.md`](schemas/README.md). `npm run
297
+ validate-schemas` (part of `npm test`) compiles every schema under `schemas/`
298
+ with Ajv in strict Draft 2020-12 mode and checks the fixtures in
299
+ `tests/schema-fixtures/`: `valid/` must pass, `invalid/` must fail.
300
+
301
+ - **Config schema (`vinta-ai-workflows-config.v1`), all additive.** A `maestro`
302
+ section holding what every plan used to repeat — gates by type and by id,
303
+ resources (with `scope`), chores, `defaults` (gates, harness, pipeline,
304
+ `gate_scope`, `verify_gates`, `base_gates`, `wave_gates`,
305
+ `pull_requests: phase | plan`, `max_spare_crew`, `substitution`,
306
+ `escalate_after_rejections`, `model_fallbacks`, `harness_fallbacks`), the
307
+ `project` block (databases, services, `env_files`, `setup_cmd`,
308
+ `prepare_cmd`, `reset_cmd`, `recycle_keep`, `hooks`, `lane_seed`), `codegen`,
309
+ `append_only`, `ci_only` and `post_merge` — which maestro layers each plan
310
+ over (`commands.*`, then `maestro.*`, then the plan, then the run's own
311
+ amendments). Also `integrations`, `foundation_skills.interview-ui`,
312
+ `foundation_skills.thermo-nuclear-review-loop`, `commands.worktree_prepare`
313
+ / `worktree_teardown`, `commands.worktree_candidates`, `commands.lint_scoped`
314
+ and `run_options.implement-plan.parallel_phases` / `max_parallel_lanes`. The
315
+ bootstrap interview asks for each (maestro defaults are group C.11, with
316
+ follow-ups on `env_files`, the test gate in lanes, a fresh-database form,
317
+ when the full suite runs, CI checks with no gate, and test-tool caches
318
+ missing from `.gitignore`), and `vinta-sync-ai-tools` offers them to
319
+ existing projects. `prs-context-frontmatter.v1` gains an optional `kind`
320
+ (`phase | integration | plan`).
321
+
322
+ ### Changed
323
+
324
+ - **`plan-feature`: plans have fewer, longer phases.** The phase size ceiling
325
+ rises from 1500 to 4000 LoC, tests included, and the sub-phase trigger moves
326
+ to that same ceiling; the Step 0 **Phase granularity** default flips to
327
+ bundling closely-related use-cases into one phase, with one use-case per
328
+ phase as the opt-in answer. A phase of a few hundred lines has to justify
329
+ standing alone. A plan drawn before the change is still valid as written.
330
+ The skill also tells the author to read the CI config and give every locally
331
+ runnable CI job a gate (and to record the rest under `ci_only`), treats two
332
+ parallel phases adding migrations to the same app as file overlap, treats a
333
+ rename of a shared symbol as an interface change, names the enum for
334
+ same-named choice fields two phases expose, lists the usual append-only
335
+ registries, tells authors to declare the gitignored files a lane needs under
336
+ `project.env_files`, and states that `gates: []` means *none*. Its AI model
337
+ tiers cite the latest OpenAI, Anthropic and Google releases
338
+ (`claude-sonnet-5-5`, `gpt-6.1-sol`, `gemini-3.1-pro-preview`); tier
339
+ placement is unchanged. Re-derive the skill to pick these up.
340
+
341
+ - **`implement-plan` and its sub-skills follow what maestro learned from real
342
+ runs.** Implementers commit when a gate stays red and report `FAILURE`
343
+ naming the gate; an uncommitted file does not exist as far as the run is
344
+ concerned. They run every command in the foreground, never hand-edit a
345
+ generated file, and list every gate they ran and its result; the conductor
346
+ reviews only a `SUCCESS` report whose gates are all green. Every spawn of a
347
+ phase carries the decisions already made in it, and a resumed implementer
348
+ checks the branch for committed work first. Every merged tree runs the full
349
+ gate, whatever the `full_test_suite` answer is, and the Quick test scope
350
+ means scoped tests until the review approves and the full suite once before
351
+ integration. The merge fixer keeps what a side deleted, stages by name,
352
+ verifies narrowly, and confirms a resolution by scanning the files for
353
+ markers, never by asking git; a merge refused by a hook or by git goes to
354
+ the human. A member moved to its next phase is told first that its objective
355
+ changed; a continuation that fails is retried cold with the full brief; an
356
+ outage or an expired login asks `Wait and retry` / `Switch model` / `Stop
357
+ the run` rather than escalating the tier. Lanes are recycled fully between
358
+ phases, leftovers saved to a `refs/wip/` ref first. A dispatched phase agent
359
+ does the work itself: every composed implementer prompt and a guard at the
360
+ top of each conductor refuse to hand a phase to a sub-agent. The plan PR is
361
+ the one PR that lands the plan, and every phase and integration PR says so.
362
+ Re-derive the skills to pick this up; plans and tracking directories written
363
+ before the change still work.
364
+
365
+ - **`review-phase` runs the thermo-nuclear review loop.** Each phase is
366
+ reviewed by `thermo-nuclear-review-loop`, hosted by the conductor because a
367
+ sub-agent cannot spawn sub-agents of its own: one reviewer one tier above the
368
+ phase's implementer (a Tier 4 phase is reviewed at Tier 4), each round of
369
+ findings handed to the phase's own implementer, which verifies, fixes or
370
+ rejects with counter-evidence and commits the round. A reviewer pass with no
371
+ verdict is continued once and never counts as approval; a finding re-raised
372
+ without new evidence is rejected on the spot; after 3 rejecting passes a
373
+ fresh implementer one tier up takes over; after 20 passes that still return
374
+ blockers the conductor asks whether to continue, stop the phase unapproved,
375
+ **Accept as is** (integrated with its open blockers recorded) or amend the
376
+ plan. After approval the implementer runs `deslop-comments` over the
377
+ comments the phase added.
378
+
379
+ - **`amend-plan` cascades along the dependency graph, and amends a live
380
+ maestro run.** A rewrite touches the amended phase's dependent closure
381
+ instead of "every phase with a higher number", rebases in topological order,
382
+ rebuilds `integ-` bases first, refuses to run while a phase is in flight, and
383
+ gains a `dependency-change` amendment kind. When a maestro run of the plan is
384
+ running, paused, interrupted or failed, the skill asks whether to amend it,
385
+ edits the plan and the run's own workflow copy, commits both on the plan
386
+ branch and applies them with `vinta-ai-maestro amend`; it also carries the
387
+ operator recipes for a live run (`switch-harness`, `node reassign`, `node
388
+ interrupt`, `--harness-profile`, `propagate`, `sync-base`).
389
+
390
+ - **`prepare-worktree`: worktrees get their own copy of the dependency dirs,
391
+ never a symlink.** A symlinked `node_modules` / `vendor/` / `venv/` sent
392
+ writes back into the main checkout and made parallel worktrees race on one
393
+ tree. The skill copies every dependency dir with a copy-on-write clone
394
+ (`cp -ac` on macOS, `cp -a --reflink=auto` on Linux) and reinstalls
395
+ virtualenvs and yarn PnP; `skills.prepare-worktree.deps_strategy` now
396
+ defaults to `copy`. The skill also documents provisioning a pool of lanes for
397
+ one plan with a `reset_cmd` per forked database, and its summary's `|`
398
+ alternatives are closed sets read by machine. **Consumers:** re-sync to pick
399
+ up the new body; worktrees that already exist keep their links until they
400
+ are re-provisioned.
401
+
402
+ - **`create-spec` offers a browser surface for its Step 0 interview** when
403
+ `ai-tools/skills/interview-ui/` exists (see **The browser interview** above).
404
+ The question bank, clarity loop, read-back and exit conditions are
405
+ unchanged.
406
+
407
+ - **`write-unit-test`: time-independent tests and deterministic generated
408
+ output.** Rule 8 requires a frozen clock and an explicit timezone on any test
409
+ touching dates, and host-independent schema or client generation. The Django
410
+ pack and stack notes spell out `freezegun` / `time-machine` with
411
+ `override_settings(TIME_ZONE=...)` and `tzdata`-sourced timezone choices.
412
+
413
+ - **Django stack notes** cover database reuse and testmon in lanes, keeping
414
+ the virtual environment out of a bind-mounted worktree, registries every
415
+ phase appends to, drf-spectacular `ENUM_NAME_OVERRIDES` for new choice
416
+ fields, and the CI-mirroring checks a plan's gates should carry
417
+ (`manage.py check --deploy --fail-level WARNING`, `makemigrations --check`,
418
+ a regenerate-and-diff gate for a schema or client).
419
+
420
+ - **The bootstrap and sync skills.** `vinta-bootstrap-ai-tools` asks the new
421
+ questions listed under **Config schema** above, no longer offers `symlink`
422
+ for dependency dirs, and no longer asks for a reviewer tier; the **Optional
423
+ foundation skills** group grows to eight questions (`interview-ui` is 7,
424
+ `handoff-to-client` moves to 8). `vinta-analyze-codebase` records existing
425
+ worktree scripts and integration-owned skills. `vinta-sync-ai-tools` carries
426
+ the asking-the-human migration, offers the PR Review Canvas integration to
427
+ existing projects as an `opt-in-offer`, and re-renders the plan-execution
428
+ skills together. Every generated skill now carries
429
+ `disable-model-invocation: true`.
430
+
431
+ - **`agent_models.fixer` now sets only the merge-conflict fixer's tier.** The
432
+ phase's own implementer fixes review findings at its own tier, so a project
240
433
  that set `fixer` cheap to save money is saving it on fewer rounds.
241
434
 
242
- - **The workflow schema gained `defaults.max_session_turns`.** Optional, default
243
- 12. An orchestrator that reuses one agent session across a phase's implement
244
- and fix turns needs a ceiling on how long that session may grow before the next
245
- turn starts cold; without one a long phase eventually dies on a context-window
246
- error that reads as a broken harness. `plan-feature` omits the field — it is a
247
- safety limit, not something a plan tunes — and its field table says so.
248
-
249
- - **`plan-feature` asks about the project's databases and emits the workflow's
250
- `project` block.** The block records what a phase lane must **fork** to be a
251
- working checkout — the `dev` and `test` databases, and the project's own
252
- migrate command, which runs once per template database rather than once per
253
- lane. Without it every lane got a git worktree and nothing else, so two phases
254
- running concurrently pointed their test gate at the same rows. Asked at
255
- emission time with one `AskUserQuestion` call ("what does a phase lane need its
256
- own copy of", "how is that database delivered"); the rest — the migrate
257
- command, the database names, the env var names — is read out of the project's
258
- settings and task runner rather than asked.
259
-
260
- Two rules the skill is explicit about, because both are easy to get wrong:
261
- **sharing is the absence of a declaration** (there is no `share` value, and a
262
- lane that reads the main checkout's database has nothing to describe), and
263
- **each role names its own database** (a lane's fork is named from `name` and
264
- the lane, not the role, so `dev` and `test` sharing one `name` collapse to one
265
- forked database). Everything `prepare-worktree` discovers per worktree —
266
- `reset_cmd`, compose project names, volume forks, seed commands, env-file
267
- strategy — stays out of the block by design.
268
-
269
- - **New schema
270
- [`postmortem.v1.schema.json`](schemas/postmortem.v1.schema.json)** — the
271
- structured plan post-mortem an orchestrator writes at
272
- `.vinta-ai-maestro/runs/<run-id>/postmortem.json` once a run has ended: dependencies
273
- that were declared but never used, dependencies discovered at gate time,
274
- same-wave phases that actually conflicted, and phases whose real duration
275
- diverged from their wave placement. `plan-feature` reads it before drawing the
276
- next feature's Execution graph, which is what stops a plan from repeating a
277
- defect the last run already paid for. Like
278
- [`workflow.v1.schema.json`](schemas/workflow.v1.schema.json) it is
279
- **generated** from a zod source rather than hand-written — see
280
- [`schemas/README.md`](schemas/README.md).
435
+ ### Deprecated
281
436
 
282
- ### Changed
437
+ - **`agent_models.reviewer` is ignored.** The review runs one tier above the
438
+ phase's implementer, so no configured tier is read. The key stays in the v1
439
+ config schema so existing configs still validate; drop it at your next edit.
283
440
 
284
- - **Phase branches base on their dependencies, not on the previous phase.** A phase
285
- with no dependencies cuts from the default branch; one with a single dependency
286
- cuts from that phase's branch; one with several cuts from a
287
- `plan/{plan-id}/integ-{phase-id}` branch that merges them. Each wave is then merged
288
- into a `plan/{plan-id}/wave-{N}` integration branch, which is what a resume anchors
289
- on and what the final report points at. The PR `base` follows the same value —
290
- a stacked plan produces exactly the stack it did before.
291
- - **Tracking is a directory, not a file.** `{{PLAN_DIR}}/TRACKING_{plan-id}/` holds
292
- `run.md` (conductor-owned), one `phase-{id}.md` per phase (written only by the lane
293
- that ran it, committed on that phase's own branch), and `waves/wave-{N}.md`. No two
294
- branches write the same path, so wave merges no longer conflict on tracking. A run
295
- started under the old single-file layout is migrated on resume.
296
- - **An implementer is told about its dependencies only.** Prior-phase context passed
297
- into a phase prompt is now that phase's transitive dependency closure rather than
298
- "everything finished so far" — a sibling lane's work is not in the phase's base
299
- branch, and describing it as done made the implementer code against files it could
300
- not see.
301
- - **The stray-write guard covers sibling lanes.** The sandbox denies the whole
302
- worktree pool root and allows back only the running lane; the review-phase backstop
303
- checks the main checkout and every sibling workroot after each implementer and
304
- fixer. A write into a lane that is mid-implementation is worse than a stray
305
- main-checkout write.
306
- - **`amend-plan` cascades along the dependency graph.** A rewrite touches the
307
- amended phase's dependent closure instead of "every phase with a higher number",
308
- rebases in topological order, rebuilds `integ-` bases before rebasing a
309
- multi-dependency phase onto them, and refuses to run while any phase is still in
310
- flight. It gained a `dependency-change` amendment kind for edits to a
311
- `**Depends on**:` line.
312
- - **`implement-plan` refuses rather than degrading** when parallel execution is asked
313
- for but worktrees are unavailable — several agents cannot share one working tree,
314
- and silently falling back to sequential would discard the schedule the user
315
- approved.
316
- - **`modular-commits` supports parallel runs**: lanes commit their atomic units on
317
- `plan/{plan-id}/lane-{phase-id}` branches, merged `--no-ff` into the single plan
318
- branch at each wave boundary, so the unit commits survive.
441
+ - **`skills.prepare-worktree.deps_strategy: symlink`** stays in the schema
442
+ enum so existing configs validate, but is deprecated and read as `copy`.
443
+ Change it to `copy` (or `reinstall`) in `.vinta-ai-workflows.yaml` to stop
444
+ the interview default from being re-emitted.
445
+
446
+ ### Removed
447
+
448
+ - **The three-layer phase review.** `review-phase` no longer runs the
449
+ mechanical checks (including the review-time secret scan, dependency-license
450
+ check and co-author trailer check), the plan-compliance walkthrough
451
+ (including the comment-hygiene check), the crew reviewer, or a separate
452
+ fixer per finding; the thermo-nuclear review loop replaces them. The
453
+ implementer's own install-time license check and co-author rules are
454
+ unchanged.
455
+
456
+ - **Reviewers on the plan.** `plan-feature`'s Crew table has no `Role` column
457
+ and no reviewer rows, and phases have no `**Review models**:` line.
458
+ **Migration:** plans written with them still run; `implement-plan` ignores
459
+ them.
319
460
 
320
461
  ### Fixed
321
462
 
322
- - **`serve --host 0.0.0.0` prints a URL another machine can open.** Binding
323
- every interface made the server report the wildcard back, so the line printed
324
- for the operator to open — and share — was `http://0.0.0.0:<port>`, which
325
- resolves for nobody. The bind is unchanged; the printed host is now this
326
- machine's LAN address. The daemon still warns, because the token in that URL
327
- is the only thing between the run and anyone who can reach the port.
328
-
329
- - **An agent can run a shell command.** `auto` mapped to the vendor's
330
- `acceptEdits`, which accepts file *edits* and nothing else — a shell command
331
- still goes to a permission prompt, and in `-p` there is nobody to answer one.
332
- A run of eight phases died of it: the agents wrote their code and were then
333
- refused `ruff`, `pytest`, `git add` and `docker compose`, **69 denials across
334
- two lanes**, every gate failing on work that was never allowed to be checked.
335
- `auto` now allows `Bash` in the policy file it already writes.
336
-
337
- What that costs is worth stating plainly: **`Bash` was never confined to the
338
- lane.** The deny list covers the file-editing tools and a shell redirection
339
- walks through it, so allowing the shell allows commands on the machine.
340
- `auto` has always promised exactly this in words — "the agent works unattended
341
- inside its lane" — and this is the first version where the words are true.
342
- `ask` still does not allow it: that mode exists for a human at the browser,
343
- and the prompt is its purpose.
344
-
345
- - **A refusal says why, in the words the harness used.** `permission_denied`
346
- carried a decision token and deliberately dropped the sentence beside it, on
347
- §11 grounds. Then a run failed with forty-five denials reading
348
- `reason: "other"`, and finding out what that meant cost an afternoon and a
349
- rebuilt reproduction — the sentence said "this Bash command contains multiple
350
- operations; the following parts require approval". §11 keeps repository
351
- *contents* out of the record; a refusal's own explanation is not contents, and
352
- the `tool_use` row above it already carries the path and the command verbatim.
353
- Withholding it protected nothing and hid the one fact worth having.
354
-
355
- - **`serve` opens a run that has already finished.** The API resolved a run from
356
- the in-memory registry *and* the journal and required both, so a daemon
357
- started with nothing running listed the operator's history — the list reads
358
- the journal — and then answered 404 for every run in it, under a message
359
- saying the daemon was not running. Reads now need only the journal, which is
360
- where a run's whole record lives and which outlives the daemon by design
361
- (§5.3). Steering a finished run is still refused, with `409` rather than
362
- `404`: the run exists, and saying it does not sends the operator hunting for a
363
- typo instead of reading the status in front of them.
364
-
365
- - **Four places the UI asked the operator to work around it.** The transcript
366
- opened at the *oldest* row it held, so a live agent's newest line — the one
367
- the panel was opened to read — sat below the fold and every arriving entry
368
- pushed it further down; it now opens at the newest and stays there, but only
369
- while the operator is already at the bottom, because scrolling up is reading.
370
- The `git diff` command overflowed its panel, uncopyable without selecting
371
- blind, and now wraps. The shell's bounded column went from 1280px to 1600px:
372
- 1280 is a reading measure, and the Nodes table's columns are ids, lane names
373
- and branch names, none of which can be abbreviated without losing what
374
- identifies them. And the notification interval said "Remind every 5 min"
375
- without ever saying what it would remind anyone about — it repeats the
376
- notification for a phase that stopped to ask the operator something, until
377
- they answer, which is what the options say now.
378
-
379
- - **A killed terminal releases its directory on Windows.** Two PTY tests failed
380
- teardown with `EBUSY: rmdir`: killing a process there is not synchronous with
381
- releasing what it held, so the conpty and its background child are gone as far
382
- as the test is concerned while the OS still has the working directory open.
383
-
384
- - **A failed phase can be retried instead of ending the run.** `run` takes
385
- `--on-failure <stop|ask>`. `stop` is the default and is what every run has
386
- always done — the phase fails, its dependents block, the run finishes. `ask`
387
- parks the node on a question instead: retry, retry with another member of the
388
- crew, or stop.
389
-
390
- It exists because the failures worth retrying are overwhelmingly
391
- environmental — a permission wall, a grant nobody made, a gate whose service
392
- was not up — and the only recovery was to start the whole plan again, running
393
- every phase that had already succeeded a second time. Only pass `ask` when
394
- somebody is watching: the run waits, which is exactly why it is not the
395
- default.
396
-
397
- The alternatives offered are **members of the crew, not models**. A staffed
398
- run has no free-floating models in it — a phase is taken by a member, and the
399
- tier floor that decides who may take it is the assigned member's own — so a
400
- model is something the plan cannot express and nobody could be found to hold.
401
- A member below the phase's tier is never offered: an operator answering a
402
- question is not a reason to hand a phase to somebody the plan judged too
403
- junior for it.
404
-
405
- The retry starts **cold**, and everything the node held goes back before it
406
- waits (§6.1) — an operator at lunch must not be holding a lane another phase
407
- could use.
408
-
409
- - **A refusal nobody was asked about is now said out loud.** The adapter knew
410
- about `permission_request`, a question waiting for an answer, and nothing
411
- else. The refusal an operator actually hits is not a question: a read outside
412
- the working directory is decided by the CLI and announced as
413
- `permission_denied`, with no request to reply to. That frame was dropped at
414
- the first `switch` — no event, no journal row, no transcript line. The new
415
- `permission_denied` event carries the decision token (`workingDir`, `mode`)
416
- and never the vendor's prose, which names the file being read (§11).
417
-
418
- - **A turn that ended blocked is no longer a turn that succeeded.** The CLI
419
- says `status_category: "blocked"` one frame before reporting
420
- `is_error: false`, and both are true from its side: it was asked for
421
- something it could not do and said so. Taking the second at its word is how a
422
- phase passed having written no code and then failed two steps later under
423
- another name. A session that reported an error no longer ends `ok` — which
424
- also makes a reviewer fail closed, since its verdict is read back out of a
425
- transcript whose session did not end cleanly.
426
-
427
- - **An agent still could not write in its own lane.** The entry below passed
428
- claude-code `--permission-mode auto`, which matched our own vocabulary for
429
- "works unattended" and is not what the vendor means by the word: `auto` still
430
- routes a write to a permission prompt, and in `-p` there is nobody to answer
431
- one. Run against the CLI, a `Write` to the agent's *own working directory*
432
- comes back denied with no reason attached — the same dead end, wearing the
433
- word that made it look closed. `acceptEdits` is the mode under which that
434
- write succeeds, and is what `auto` now maps to. The test covering this
435
- asserted the word rather than the behaviour, so it pinned the bug in place.
436
-
437
- - **A phase can read the operator's checkout.** A lane is a worktree cut from a
438
- branch, so anything uncommitted — a plan written this morning, a spec that
439
- never leaves the operator's machine — is present where they are and absent
440
- from every lane. Reaching for it was refused before the model saw a byte, with
441
- a message that reads like a prompt awaiting an answer ("Claude requested
442
- permissions to read from …, but you haven't granted it yet") when in fact
443
- nothing is asking: the CLI denies it outright, emits no permission request,
444
- and the session then ends *successfully*, having written nothing.
445
-
446
- The repository root is now granted to every claude-code agent for **reading**.
447
- Granting a directory also grants writing in it, and the lane sits inside the
448
- directory being granted, so the grant is paired with a deny list that keeps
449
- the lane the only writable place under it — the operator's source and every
450
- sibling lane stay refused. That list names the *siblings* at each level down
451
- to the lane rather than the root itself, because the vendor resolves deny
452
- before allow with no carve-out: `deny: <repo>/**` plus `allow: <lane>/**`
453
- refuses the lane too. Each of those facts was established by running the CLI.
454
-
455
- **This covers the file-editing tools and not `Bash`.** A shell redirection was
456
- never confined to the working directory and is not confined now; that boundary
457
- is the OS's, and the vendor's sandbox that enforces it also switches off the
458
- network a phase needs to install anything.
459
-
460
- codex needed nothing: under `--approve-for-me` it already reads anywhere on
461
- disk, which was confirmed the same way.
462
-
463
- - **An agent can write in its own lane.** Every adapter declared
464
- `permissionControl: true` and passed no policy at all: claude-code was spawned
465
- as `-p --output-format stream-json …` with no `--permission-mode`, and codex as
466
- `exec --json` with no sandbox and no approval flag, under a comment saying it
467
- took both on the command line. So a headless run asked before its first write,
468
- emitted a `permission_request`, rendered it in the transcript — and nothing
469
- anywhere answered. The phase failed reporting a permission system it could not
470
- see, having written nothing.
471
-
472
- `run` and `serve` now take `--permission <ask|auto|full>`, defaulting to
473
- `auto`. **The operator sets it, never the workflow document**: the document is
474
- committed and shared, and a file in a repository should not be able to tell
475
- someone else's machine to run agents without approvals.
476
-
477
- Both CLIs refuse combinations that looked reasonable, and both were found by
478
- running them rather than reading them: codex rejects `--sandbox` alongside
479
- `--approve-for-me`, and `codex exec resume` accepts neither — passing the
480
- fresh-spawn policy there turned a `stale_session` refusal, which the scheduler
481
- retries cold, into a `fatal` one that fails the node.
482
-
483
- This reverses a documented decision. The README said the daemon passed no
484
- permission flags and that a committed `.claude/settings.json` was what made a
485
- run able to write; that is now the narrowing layer on top of a mode, not the
486
- only thing standing between an agent and a blocked lane.
487
- - **`purge --lanes --branches` clears what a failed run leaves behind.** A run's
488
- lane worktrees are not under `runs/`, so no purge ever reached them: three
489
- failed attempts at one plan left twelve worktrees, twelve summaries, and a set
490
- of `plan/<id>/phase-*` branches still checked out — which is what makes the
491
- *next* run of that plan impossible, since git refuses to check out a branch a
492
- second worktree holds.
493
-
494
- One rule decides both: **never delete the only copy of work.** A phase can
495
- leave work committed on its branch or uncommitted in its worktree, and both
496
- count — so a branch carrying commits no other branch has is kept, a lane with
497
- a dirty tree is kept, and each is listed with the command to remove it by
498
- hand. Untracked files count as work: a phase that wrote three new modules and
499
- never committed them is exactly the case worth protecting.
500
-
501
- Emptiness is measured as "carries no commit another branch does not already
502
- have", not as "merged into HEAD". The latter is relative to wherever the
503
- operator is standing, so on a feature branch — the checkout this is most often
504
- run from — every empty phase branch looked unmerged and nothing was ever
505
- cleaned up.
506
-
507
- `--dry-run` and `--yes` work as they already did, and a worktree that will not
508
- go is named rather than counted.
509
-
510
- - **`doctor` now catches, before a lane exists, the failures that used to take a
511
- run each.** Four consecutive runs of one plan failed four different ways, and
512
- every one of them was knowable at minute zero from the workflow and the repo.
513
- - **Every `prompt_ref` and `plan_context_ref` is resolved against
514
- `base_branch`**, with `git cat-file -e`, which reads the branch's tree and
515
- so cannot be satisfied by a working-tree copy — the working tree being
516
- exactly what a lane will not have. It distinguishes the three cases, because
517
- they have three different fixes: never committed, **staged but never
518
- committed** (`git add` alone does not put a file in a branch), and committed
519
- on a different branch. The last offers both routes out — merge it, or point
520
- `base_branch` at the branch that has it — since only the operator knows
521
- which they want.
522
- - **Phase branches held by another worktree** are reported with the directory
523
- to remove. Lane directories are named per run and phase branches per
524
- workflow, so a failed run leaves worktrees holding the branch names the next
525
- run will try to cut, and git refuses to check out a branch twice. Nothing
526
- cleans those up: `purge` deletes run state under `.vinta-ai-maestro/runs/`,
527
- and lane worktrees are not there. `doctor` does not delete them either — a
528
- failed lane's worktree is the only place its state survives — but it now
529
- names each one and the exact command.
530
-
531
- - **A failed node records why.** `node_status` carried `{"status":"failed"}` and
532
- nothing else, so two runs failing for two unrelated reasons produced identical
533
- journal rows and the cause survived only in the operator's terminal. The
534
- reason is now persisted — **sanitized**, not raw: errors the package builds
535
- itself are identifiers by construction and are kept verbatim, and anything
536
- else is reduced to its kind, the rule `recycleStage` already followed. The
537
- journal is durable and API-served, and an exception message from a dependency
538
- is exactly how repository content gets into one. Blocked dependents record
539
- which node blocked them.
540
-
541
- - **Two diagnostics that named the symptom and hid the cause.** Both came out of
542
- one real run, and neither was a wrong answer — just an unusable one.
543
- - **A phase whose plan is not committed** failed with `prompt_ref "…" names no
544
- readable file`, against a path that was spelled correctly. A lane is a fresh
545
- worktree of the base branch, so a plan sitting untracked in the operator's
546
- checkout is in the one place the run cannot look. The message now names the
547
- directory it resolved against and says why a plan is often not in it.
548
- - **A lane summary the daemon could not accept** reported `summary unreadable`
549
- and advised deleting the lane — which takes its forked databases with it,
550
- over what turned out to be two wrong fields. `doctor` now names the fields
551
- and what was expected, and offers repair before deletion. A file that does
552
- not parse at all still reports as unreadable, because there is no field to
553
- name. Neither message carries the offending *value*: a summary holds
554
- database names and connection variables, and the value that failed
555
- validation is the likeliest thing in it to be one.
556
-
557
- `prepare-worktree` gained the rule that would have prevented the summary in
558
- the first place — its `|` alternatives are closed sets read by machine, `null`
559
- is how you say "none", and a strategy outside the set should be the closest
560
- one plus a `note:` rather than a fourth word.
561
-
562
- - **`npx vinta-ai-maestro` now runs.** The published package pointed its `bin` at
563
- `src/cli/bin.ts` and relied on Node stripping the types at startup — which Node
564
- refuses to do anywhere under `node_modules`, unconditionally and with no flag to
565
- override. So the CLI worked from a checkout and died on first run once installed,
566
- with `ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING`.
567
-
568
- `packages/vinta-ai-maestro` now builds: `tsc` emits `dist/` with
569
- `rewriteRelativeImportExtensions` (the source imports `.ts` specifiers, which
570
- emitted JS cannot keep), vite writes the daemon's UI into `dist/ui`, and the
571
- shebang is rewritten from the source's `--experimental-transform-types` form to
572
- a plain `#!/usr/bin/env node` — a compiled entry point has no types left to
573
- transform, and should not ask Node for a flag it is free to retire. `prepack`
574
- runs the build, so a tarball can never be cut from a stale `dist/`.
575
-
576
- Three packaging faults surfaced with it, each of which broke an install on its
577
- own:
578
- - **The UI was never in the tarball.** `serve` resolves its static root as
579
- `dist/ui` and refuses to read outside it, so it would have booted and answered
580
- every page with "build the UI first". The build now asserts `dist/ui/index.html`
581
- exists rather than trusting a vite config that writes outside its own root.
582
- - **`tailwindcss` and `tw-animate-css` were imported but never declared.** They
583
- resolved only through pnpm's `.bin` shim setting `NODE_PATH`; building by any
584
- other path failed to resolve them. Both are now devDependencies.
585
- - **Everything the UI imports was a runtime dependency.** React, xterm,
586
- lucide-react and the three workspace packages are bundled into `dist/ui` by
587
- vite and cannot be loaded at runtime — yet a consumer installed all of them,
588
- and two carried `workspace:*` specifiers that no registry understands. Moved to
589
- devDependencies; the published package now declares six runtime dependencies
590
- instead of fourteen.
591
-
592
- CI packs the tarball, installs it into a throwaway project and runs the binary
593
- from `node_modules`. Every previous check ran from a checkout, which is the one
594
- place this class of bug cannot appear.
595
-
596
- - **Lane provisioning serializes `git worktree add`, not only the database
597
- template.** `prepare-worktree` previously named one serialization point; there
598
- are two. Git rewrites `.git/worktrees/` metadata on every add, and concurrent
599
- adds against one repository clobber each other's entries — a reproducible
600
- corruption, not a theoretical race. Worktrees are added one at a time; the
601
- expensive per-lane work (dependency linking, database cloning, summary
602
- writing) still overlaps around it.
603
-
604
- - **The conflict-fixer round budget is an integration-level setting, not a
605
- phase's `max_fix_rounds`.** `parallel-lanes.md` now says so, and defaults it to
606
- two. A merge conflict belongs to a *pair* of phases, so deriving the budget
607
- from one of them made the answer depend on which phase happened to merge
608
- second.
609
-
610
- - **A resolved merge conflict is confirmed by scanning the files, never by asking
611
- git.** `git add` clears a path's unmerged flag whether or not `<<<<<<<` is
612
- still sitting in it, so git's index cannot answer "did the fixer actually fix
613
- it". `parallel-lanes.md` now requires scanning the conflicted paths for
614
- conflict markers before the merge is committed. Without it, a fixer that did
615
- nothing produces a merge commit full of markers that passes into the wave
616
- branch unnoticed.
617
-
618
- > The repository also gained `packages/vinta-ai-maestro/`, the workspace package
619
- > that executes these workflows. It is published as its own npm package,
620
- > `vinta-ai-maestro`, carrying the same version as `vinta-ai-workflows`, and is
621
- > run with `npx vinta-ai-maestro`. It is not part of the `vinta-ai-workflows`
622
- > tarball — the root `files` whitelist excludes `packages/`, so nothing in it is
623
- > installed by `npx vinta-ai-workflows install`. What ships from that work into
624
- > the skills package is the two generated schemas above and the skill changes
625
- > that produce and consume them.
626
- >
627
- > Its browser UI is now built on `packages/design-system/` (`vinta-design-system`),
628
- > a second workspace package: oklch tokens in three layers mirroring
629
- > `vinta-schedule-design-system`, six run-status **tones** (`idle`, `active`,
630
- > `wait`, `attention`, `ok`, `error` — waiting is amber and failure is red, never
631
- > the same hue), shadcn/ui components on Tailwind CSS v4, a small layout kit, and
632
- > a light/dark/system theme. The run graph and the pipeline editor are re-skinned
633
- > through their own custom properties, so the canvas and the badges beside it
634
- > share one palette. It and `vinta-dag-editor` publish on their own cadence
635
- > (`0.1.0`) as dependencies of `vinta-ai-maestro`; nothing in either reaches
636
- > `npx vinta-ai-workflows install`.
463
+ - **`open-pr.sh` posts inline comments on macOS and reports why a comment
464
+ failed.** Four bugs in the `open-pr-from-context` script, all seen while
465
+ publishing a stacked plan from a Mac: a GNU-only `sed` idiom that BSD `sed`
466
+ rejected, so trailing blank lines were never trimmed; a lowercase
467
+ `side: right` that GitHub answered with "422 Validation Failed", now
468
+ upper-cased; `gh api` and `glab api` stderr thrown away, so a failed comment
469
+ gave no reason; and a multi-line `awk -v` that BSD `awk` rejected when
470
+ adding to a `## Publish log` section. Projects that patched their own copy
471
+ can re-sync with `vinta-sync-ai-tools`.
472
+
473
+ - **`check-ai-models` no longer mistakes sibling models for snapshots of a
474
+ cited id.** The matcher used substrings, so `claude-sonnet-5` matched
475
+ `claude-sonnet-5-5` and hid the newer release, and `gemini-3-pro` matched
476
+ `gemini-3-pro-image` so a retired model still looked available. It accepts
477
+ only exact ids, dated or `-vN` snapshot suffixes, and provider prefixes.
478
+
479
+ - **`implement-plan`'s final report no longer suggests `docker compose down -v`
480
+ to tear down a lane.** `down -v` also deletes the compose volumes a worktree
481
+ deliberately shares with the main checkout. The report prints the sequence
482
+ `prepare-worktree` documents: `docker compose -p <project> down`, then
483
+ `docker volume rm` for each forked volume, then removal of the generated
484
+ compose override.
485
+
486
+ - **`prepare-worktree` serialises `git worktree add`, not only the database
487
+ template.** Git rewrites `.git/worktrees/` metadata on every add, and
488
+ concurrent adds against one repository clobber each other's entries.
489
+ Worktrees are added one at a time; the per-lane work around them still
490
+ overlaps.
637
491
 
638
492
  ## [0.6.1] — 2026-08-17
639
493
 
@@ -996,7 +850,6 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
996
850
  **Consumers**: re-sync to pick up the opt-in questions. E2E-disabled projects
997
851
  are unaffected (the e2e regions strip out as before).
998
852
 
999
-
1000
853
  <!-- pre-release: 0.2.0-alpha6 on 2026-07-13 -->
1001
854
 
1002
855
  ### Changed
@@ -1033,7 +886,6 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
1033
886
 
1034
887
  ### Added
1035
888
 
1036
-
1037
889
  - **`handoff` foundation skill — session-continuation handoff docs between
1038
890
  agents.** Write mode captures the current task (goal, verified-vs-unverified
1039
891
  state, decisions + rejected alternatives, landmines, single concrete next