vinta-ai-workflows 0.7.0-alpha35 → 0.7.0-alpha37
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 +406 -0
- package/package.json +1 -1
- package/schemas/postmortem.v1.schema.json +213 -2
- package/schemas/vinta-ai-workflows-config.v1.schema.json +212 -2
- package/schemas/workflow.v1.schema.json +211 -1
- package/skills/vinta-bootstrap-ai-tools/SKILL.md +30 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/django/notes.md +36 -1
- package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +29 -4
- package/skills/vinta-derive-skills/resources/plan-execution/README.md +9 -0
- package/skills/vinta-derive-skills/resources/plan-execution/partials/implementer-prompt.md +1 -0
- package/skills/vinta-derive-skills/resources/plan-execution/partials/maestro-live-run.md +40 -0
- package/skills/vinta-derive-skills/resources/plan-execution/partials/parallel-lanes.md +3 -1
- package/skills/vinta-derive-skills/resources/plan-execution/partials/review-loop.md +1 -1
- package/skills/vinta-derive-skills/resources/plan-execution/shell/amend-plan-template.md +8 -1
- package/skills/vinta-derive-skills/resources/write-unit-test-packs/stacks/django.md +4 -1
- package/skills/vinta-derive-skills/resources/write-unit-test-template.md +3 -0
- package/skills/vinta-install-ai-tools-setup/SKILL.md +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,8 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
7
7
|
|
|
8
8
|
## [0.7.0] — YYYY-MM-DD
|
|
9
9
|
|
|
10
|
+
<!-- pre-release: 0.7.0-alpha37 on 2026-10-20 -->
|
|
11
|
+
<!-- pre-release: 0.7.0-alpha36 on 2026-10-18 -->
|
|
10
12
|
<!-- pre-release: 0.7.0-alpha35 on 2026-10-16 -->
|
|
11
13
|
<!-- pre-release: 0.7.0-alpha34 on 2026-10-16 -->
|
|
12
14
|
<!-- pre-release: 0.7.0-alpha33 on 2026-10-16 -->
|
|
@@ -35,6 +37,215 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
35
37
|
|
|
36
38
|
### Added
|
|
37
39
|
|
|
40
|
+
- **`vinta-ai-maestro`: `post_merge`.** A workflow (or `maestro.post_merge`)
|
|
41
|
+
may declare a command that runs in the integration worktree after git
|
|
42
|
+
merges a branch by itself, with `{files}` set to the files both sides
|
|
43
|
+
changed (for example `py_compile` plus `ruff check --fix` and
|
|
44
|
+
`ruff format`). Its changes are committed on top of the merge. If it fails,
|
|
45
|
+
the merge stays as git made it and the merged tree's gates judge it. Each
|
|
46
|
+
run is journalled as `post_merge_result`.
|
|
47
|
+
- **`vinta-ai-maestro`: `ci_only` records CI checks deliberately left to
|
|
48
|
+
CI.** It lives in a plan or in `maestro.ci_only` in
|
|
49
|
+
`.vinta-ai-workflows.yaml`. Each entry is a CI command with the reason no
|
|
50
|
+
gate runs it. `doctor`'s CI-coverage check stops warning about those
|
|
51
|
+
commands and counts them as decisions.
|
|
52
|
+
- **`vinta-ai-maestro`: `queue_timeout_s`, and the pool queue in `status`.**
|
|
53
|
+
A gate's `timeout_s` counts only its command's runtime, and a regression
|
|
54
|
+
test now pins that down. The optional `queue_timeout_s` bounds the wait
|
|
55
|
+
for the gate's pools: a gate that waits too long fails with how long it
|
|
56
|
+
waited and who held the pool. `status` shows each pool's queue in order,
|
|
57
|
+
for example `test-suite: p3b (holds 4m) → p5b (waits 22m) → p5c (waits 3m)`.
|
|
58
|
+
- **`vinta-ai-maestro`: a gate can run differently in a lane with no scope
|
|
59
|
+
cache.** A command gate may declare `scope_cache` (for example
|
|
60
|
+
`apps/api/.testmondata`) and `cold_cmd`. When a cache file is missing, the
|
|
61
|
+
phase gate runs `cold_cmd` (default `cmd`) instead of a scoped form that
|
|
62
|
+
would run every test serially. `gate_started` now records which form ran
|
|
63
|
+
and why. The new `project.lane_seed` option copies such ignored caches into
|
|
64
|
+
a lane from its dependency's lane, the integration worktree or the main
|
|
65
|
+
checkout, journalled as `lane_seeded`. Both fields are also accepted in
|
|
66
|
+
`maestro.gates.<type>`.
|
|
67
|
+
- **`amend-plan` amends a live `vinta-ai-maestro` run instead of rewriting
|
|
68
|
+
its branches.** When a run of the plan is running, paused, interrupted or
|
|
69
|
+
failed, the skill asks whether to amend it, then edits the plan and the
|
|
70
|
+
run's own workflow copy (`vinta-ai-maestro workflow`, so earlier operator and
|
|
71
|
+
coordinator amendments survive), commits both on `plan/<workflow-id>/base`
|
|
72
|
+
and applies them with `vinta-ai-maestro amend`, which rebases the done
|
|
73
|
+
phases the change reaches. Before, the plan file changed and the run went on
|
|
74
|
+
building its snapshot. The skill also carries operator recipes for a live
|
|
75
|
+
run: switching harness or model, switching the account a harness runs as,
|
|
76
|
+
resuming with the same policy flags, and moving the base forward. New
|
|
77
|
+
partial `plan-execution/partials/maestro-live-run.md`; re-run
|
|
78
|
+
`vinta-derive-skills` to pick it up.
|
|
79
|
+
- **`vinta-ai-maestro`: a phase the review keeps rejecting moves up a crew
|
|
80
|
+
tier.** One run left a Tier 1 phase on its desk through 16 review rejections
|
|
81
|
+
over six hours until the coordinator moved it by hand. New
|
|
82
|
+
`defaults.escalate_after_rejections` (default `3`, `0` turns it off): when a
|
|
83
|
+
phase's review has failed to approve that many times on one desk, counted
|
|
84
|
+
across attempts, the scheduler amends the run. The phase moves to the
|
|
85
|
+
cheapest member of the next tier up and takes the new desk from its next
|
|
86
|
+
attempt. The amendment is journalled as `workflow_amended` with the new
|
|
87
|
+
author `scheduler`, a one-line `reason` and a new `rule` field
|
|
88
|
+
(`review_rejections`, the members, the tiers and the count). A phase already at the top tier stays
|
|
89
|
+
where it is. Amendments may now leave a member the run already had with no
|
|
90
|
+
phase, so moving a member's last phase is no longer refused.
|
|
91
|
+
- **`vinta-ai-maestro`: `purge` drops lane rescues whose work landed.** The
|
|
92
|
+
`refs/vinta-ai-maestro/wip/*` commits a recycled lane keeps of a phase's
|
|
93
|
+
uncommitted files piled up (~80 in one project). A purge now drops those of
|
|
94
|
+
the runs it purges whose phase is done and merged into a branch outside
|
|
95
|
+
`plan/` and `wt/`, and those of already-purged runs whose rescued files read
|
|
96
|
+
the same at `HEAD`. Every other rescue is kept, and `--dry-run` lists them.
|
|
97
|
+
- **`vinta-ai-maestro`: a `ui` left up across an upgrade says so.** It warns
|
|
98
|
+
once when the installed package's version no longer matches the one it
|
|
99
|
+
loaded, and `run` and `status` warn about a live `ui` serving another
|
|
100
|
+
release. A `ui` started days earlier used to keep serving pre-upgrade code
|
|
101
|
+
without a word.
|
|
102
|
+
- **`vinta-ai-maestro`: a resume remembers how the run was started.** Every
|
|
103
|
+
job records its `--permission`, `--system-one`, `--on-failure`, `--retries`,
|
|
104
|
+
`--retry-after`, `--no-coordinator`, `--host` and `--harness-profile` in
|
|
105
|
+
`runs/<id>/policy.json`, and `run --resume` (and the UI's Resume) reuses
|
|
106
|
+
them, saying which; a flag given on the command line still wins. Each resume
|
|
107
|
+
used to need all of them restated.
|
|
108
|
+
- **`vinta-ai-maestro`: harness profiles.** `--harness-profile <name>` on `run`
|
|
109
|
+
and `ui` picks a named binary and environment for one harness — a second
|
|
110
|
+
Claude account's `CLAUDE_CONFIG_DIR`, say — from the operator's
|
|
111
|
+
`~/.config/vinta-ai-maestro/profiles.yaml` (or `$VINTA_AI_MAESTRO_PROFILES`).
|
|
112
|
+
The run keeps the name, so a resume picks the same account.
|
|
113
|
+
- **`vinta-ai-maestro`: `propagate` works on a live run.** It refused one, so
|
|
114
|
+
a fix on a phase could not reach older `integ-*` branches until the run
|
|
115
|
+
ended, and their PRs stayed red. On a live run the run's job now makes the
|
|
116
|
+
merges, holding the integration worktree's queue, so none of the run's own
|
|
117
|
+
merges interleave with them.
|
|
118
|
+
- **`vinta-ai-maestro`: `sync-base <run>` brings a moved `base_branch` into a
|
|
119
|
+
running plan.** It merges the base (the remote's, when ahead) into
|
|
120
|
+
`plan/<id>/base`, then the plan branch into the lowest wave and each wave
|
|
121
|
+
into the one above. On a live run a wave's conflict goes to the run's
|
|
122
|
+
conflict fixer, gated as a phase merge is; the plan branch's own conflict,
|
|
123
|
+
and any conflict on a run that is not live, stops it with the branch as it
|
|
124
|
+
was. Both commands journal `branches_moved` on a live run.
|
|
125
|
+
- **`vinta-ai-maestro`: a list of what the run decided without you.** One
|
|
126
|
+
run answered 79 of its 125 questions unattended — review loops stopped,
|
|
127
|
+
agents' design questions given their first option, one of which added a
|
|
128
|
+
migration — and none of it was anywhere a person would look. Every question
|
|
129
|
+
a `--retry-after` timer or the run coordinator answered, and everything the
|
|
130
|
+
coordinator did on its own (steering, pauses, aborts, amendments, `exec`),
|
|
131
|
+
is now listed in:
|
|
132
|
+
- `status <run>` (*Decided without you*; `unattended` in `--json`), with an
|
|
133
|
+
agent question's header and the option it got;
|
|
134
|
+
- the run view's **Decided without you** panel (`GET /api/runs/:runId/unattended`);
|
|
135
|
+
- the plan PR's *Decided without a person* section;
|
|
136
|
+
- the post-mortem's new optional `unattended_decisions` finding
|
|
137
|
+
(`schemas/postmortem.v1.schema.json`, additive), which `plan-feature`
|
|
138
|
+
now reads: an agent question answered unattended is a decision the plan
|
|
139
|
+
left open.
|
|
140
|
+
- **`vinta-ai-maestro`: merge resolutions that undo a phase's deletion are
|
|
141
|
+
flagged.** One run's phase deleted an unused notification kind; the
|
|
142
|
+
conflict fixer kept "both sides" and every gate passed, so the deletion
|
|
143
|
+
never landed. After every merge in the integration worktree — a fixer's
|
|
144
|
+
resolution, or the `append_only` union driver, which re-adds lines one side
|
|
145
|
+
removed — the integrator counts lines one side deleted that the result
|
|
146
|
+
kept (codegen outputs excluded). Each is recorded as path, phase and line
|
|
147
|
+
count, never the lines: on the `node_conflict` journal row
|
|
148
|
+
(`reverted_deletions`), in the post-mortem's `wave_conflicts` and new
|
|
149
|
+
optional `unattended_decisions.reverted_deletions`
|
|
150
|
+
(`schemas/postmortem.v1.schema.json`, additive), and in the list of what
|
|
151
|
+
was decided without you (`status`, the run view, the plan PR body). It
|
|
152
|
+
flags; it does not block the merge. The conflict-fixer prompt now says a
|
|
153
|
+
phase's intent includes what it deleted.
|
|
154
|
+
- **`vinta-ai-maestro`: `--agent-answer-after` on `run` and `ui`.** How long an
|
|
155
|
+
agent's own question waits before it takes the recommended options. It
|
|
156
|
+
used to be `--retry-after`, so a one-minute retry interval answered design
|
|
157
|
+
questions in a minute. Unset, it is twice `--retry-after` and never under 30
|
|
158
|
+
minutes; set alone, agents' questions are answered while failures still
|
|
159
|
+
wait for a person.
|
|
160
|
+
- **`vinta-ai-maestro`: `doctor` checks the gates against CI.** It reads
|
|
161
|
+
`.github/workflows/*.yml` and warns about each `run:` command no gate runs,
|
|
162
|
+
or runs without a flag CI passes (`manage.py check` for CI's `check
|
|
163
|
+
--deploy`) — the reason every gate passed while CI failed on twenty review
|
|
164
|
+
PRs of one run. Matching is heuristic (tool and subcommand after `uv run`,
|
|
165
|
+
`npx`, `docker compose run`, …; `uses:` steps are not read) and it is always
|
|
166
|
+
a warning.
|
|
167
|
+
- **`vinta-ai-maestro`: project-wide custom gates.** `maestro.gates` in
|
|
168
|
+
`.vinta-ai-workflows.yaml` now takes ids of your own beside the four types —
|
|
169
|
+
`django-check: { cmd: uv run python manage.py check --fail-level WARNING }`,
|
|
170
|
+
`api-client-fresh: { cmd: make api_client && git diff --exit-code … }` —
|
|
171
|
+
with the fields a type takes (`cmd`, `scoped_cmd`, `requires`, `timeout_s`,
|
|
172
|
+
`tuning`). Every plan has each one under its id without declaring it, and
|
|
173
|
+
`maestro.defaults.gates` names it like a type, so a check CI runs is
|
|
174
|
+
declared once and keeps its own verdict instead of being chained onto
|
|
175
|
+
`typecheck` or repeated in every plan. A plan's gate of the same id replaces
|
|
176
|
+
it whole. `validate` refuses an id that is not lowercase kebab-case, the
|
|
177
|
+
reserved `codegen`, and a custom gate with no `cmd`. Previously any key but
|
|
178
|
+
a type failed with "Unrecognized keys". Additive in the config schema.
|
|
179
|
+
`plan-feature` and the Django stack notes now point CI-mirroring checks at
|
|
180
|
+
`maestro.gates.<id>`.
|
|
181
|
+
- **`vinta-ai-maestro`: codegen steps — generated files are regenerated, not
|
|
182
|
+
merged.** A workflow (or `maestro.codegen` in `.vinta-ai-workflows.yaml`)
|
|
183
|
+
declares `codegen.<id>`: a deterministic command, the files it writes
|
|
184
|
+
(`outputs`), the files they are a function of (`inputs`), and `after` for the
|
|
185
|
+
chain (schema, then client). The steps run in every lane before the gates
|
|
186
|
+
and their outputs are committed there; in the integration worktree a
|
|
187
|
+
conflict confined to their outputs is settled by taking either side and
|
|
188
|
+
running them, with no conflict fixer, and every merge is regenerated before
|
|
189
|
+
it is committed. A failing step is a red gate. `inputs` skip a step whose
|
|
190
|
+
inputs and outputs match a recorded run, a step that writes different
|
|
191
|
+
outputs from the same inputs is journalled `nondeterministic`, and a
|
|
192
|
+
`format: true` step formats only the files the phase changed. Agents are told
|
|
193
|
+
which files are generated and regenerate them mid-turn with
|
|
194
|
+
`vinta-ai-maestro codegen [<step>]`; `doctor --codegen` runs each step twice
|
|
195
|
+
to flag non-deterministic or stale output. Generated files caused most of one
|
|
196
|
+
run's 37 wave conflicts. `workflow.v1` and the config schema gain the
|
|
197
|
+
additive `codegen` field.
|
|
198
|
+
|
|
199
|
+
- **`vinta-ai-maestro`: append-only files merge as a union.** `append_only` (or
|
|
200
|
+
`maestro.append_only`) lists files phases only add entries to — DI
|
|
201
|
+
containers, URL routes, notification kinds, beat schedules — and merges in
|
|
202
|
+
the integration worktree use git's `union` driver for them, so two phases
|
|
203
|
+
each adding an entry no longer needs a fixer round. The merged tree is gated
|
|
204
|
+
as before. Additive in `workflow.v1` and the config schema.
|
|
205
|
+
|
|
206
|
+
- **`plan-feature`: emits codegen steps and append-only files** detected from the
|
|
207
|
+
project — the OpenAPI schema, generated API clients, route trees and
|
|
208
|
+
file-modifying pre-commit hooks as `codegen`; DI containers, URL routes and
|
|
209
|
+
beat schedules as `append_only` — preferring `maestro.codegen` /
|
|
210
|
+
`maestro.append_only` in the project file. `vinta-bootstrap-ai-tools` offers
|
|
211
|
+
to record them there once.
|
|
212
|
+
- **`vinta-ai-maestro`: take a phase over without failing it.** Moving a phase
|
|
213
|
+
to another agent took abort, amend and retry, and the retry restarted its
|
|
214
|
+
pipeline from the top — one phase went from review back to implementing.
|
|
215
|
+
`node interrupt <run> <phase>` stops the turn now and **holds** the phase,
|
|
216
|
+
lane, branch, commits and uncommitted work kept, until `resume`, `reassign`
|
|
217
|
+
or `step` releases it; the cut step runs again then. `node reassign <run>
|
|
218
|
+
<phase> --crew <member> | --harness <h> --model <m>` is interrupt, amend and
|
|
219
|
+
resume in one (`--after-turn` lets the turn finish): the phase carries on at
|
|
220
|
+
the same step, keeps its session when only the model changes, and otherwise
|
|
221
|
+
starts fresh with a handoff — the last report, the work in the lane, the red
|
|
222
|
+
gate. `node step <run> <phase> <state>` moves the pipeline by hand, never
|
|
223
|
+
into a final state. Journalled as `node_reassigned` and `node_operation`.
|
|
224
|
+
- **`vinta-ai-maestro`: `amend` accepts a held phase, or one waiting on a
|
|
225
|
+
question.** Its harness, model or crew member (`crew_changed`, a new
|
|
226
|
+
amendment kind) may change while it is parked, and it carries on at its
|
|
227
|
+
step. A brief, a gate list or a base still waits for the phase to stop.
|
|
228
|
+
- **`vinta-ai-maestro`: `switch-harness <run> --from --to --model` and
|
|
229
|
+
`defaults.harness_fallbacks`.** A live run moves off a harness — an account
|
|
230
|
+
out of credits — without a pause and resume: phases in flight are
|
|
231
|
+
reassigned at their step, later phases run on the new harness, and the
|
|
232
|
+
conflict fixer moves too. With `harness_fallbacks` the run does it by
|
|
233
|
+
itself when a harness parks on a quota refusal, the refused turn going
|
|
234
|
+
again at once on the fallback. Journalled `harness_switched`.
|
|
235
|
+
- **`vinta-ai-maestro`: `fixer interrupt|reassign <run>`.** End the conflict
|
|
236
|
+
fixer's running round as a round spent (what it left stays), or hand later
|
|
237
|
+
rounds to another harness and model. Journalled `fixer_operation`.
|
|
238
|
+
- **`vinta-ai-maestro`: one API for the operator and the coordinator, and every
|
|
239
|
+
act says why.** Every acting request takes a reason (`--reason` on every
|
|
240
|
+
verb, the `X-Maestro-Reason` header on the API), journalled with what it
|
|
241
|
+
explains; the coordinator is refused without one (`reason_required`). The
|
|
242
|
+
coordinator gains `interrupt`, `reassign`, `switch-harness`, `fixer`,
|
|
243
|
+
`resume` of its own holds, and `pause` of the run (`run_halt_requested`).
|
|
244
|
+
`run --coordinator-authority full` also lets it change the plan's shape —
|
|
245
|
+
phases, dependency edges, briefs, touch lists, deferrals — answer any
|
|
246
|
+
question you are not holding, `node step`, and stop the run. A check is
|
|
247
|
+
never weakened under either authority.
|
|
248
|
+
|
|
38
249
|
- **`vinta-ai-maestro`: integration is visible while it happens.** A phase in
|
|
39
250
|
`integrate` — a merge, a suite on the merged tree, a push, none with an
|
|
40
251
|
agent — showed `running` over a silent transcript, and one queued behind it
|
|
@@ -659,6 +870,97 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
659
870
|
|
|
660
871
|
### Changed
|
|
661
872
|
|
|
873
|
+
- **`vinta-ai-maestro`: the coordinator's wakes are more specific.**
|
|
874
|
+
- The `gate_cost` wake lists uncached minutes per phase and flags any
|
|
875
|
+
single run of 20 minutes or more as probably a cold lane. Runs of a
|
|
876
|
+
gate's `cold_cmd` no longer count toward the total.
|
|
877
|
+
- A failed attempt does not wake the coordinator when it already acted on
|
|
878
|
+
that phase during the attempt.
|
|
879
|
+
- A session that ends with shell calls that never returned is journalled
|
|
880
|
+
as `tool_calls_unfinished` and wakes the coordinator.
|
|
881
|
+
- `amend` lists the affected phases that are running or waiting, which pick
|
|
882
|
+
up the change only once they stop.
|
|
883
|
+
- **Bootstrap asks about maestro's test gate in lanes.** In the maestro
|
|
884
|
+
defaults (C.11), bootstrap now asks:
|
|
885
|
+
- whether a cache-based scoped run (`pytest --testmon`) should fall back to
|
|
886
|
+
the full parallel suite in a lane with no cache. This emits
|
|
887
|
+
`scope_cache`, `cold_cmd` and `project.lane_seed`, and proposes a
|
|
888
|
+
`test_changed` target that falls back when `.testmondata` is missing.
|
|
889
|
+
It also explains that `--testmon` with `-n` trades correctness for speed.
|
|
890
|
+
- whether a suite that reuses its database should get a fresh-database form
|
|
891
|
+
for the integration worktree. This emits `fresh_cmd` and
|
|
892
|
+
`tuning.allowed_flags: ['--create-db']`.
|
|
893
|
+
- for each CI check with no gate, whether to add a gate or record it under
|
|
894
|
+
`maestro.ci_only` with a reason.
|
|
895
|
+
- **Django stack notes** cover database reuse and testmon in lanes, keeping
|
|
896
|
+
the virtual environment out of a bind-mounted worktree
|
|
897
|
+
(`UV_PROJECT_ENVIRONMENT=/opt/venv`, `user: "${UID}:${GID}"`), registries
|
|
898
|
+
every phase appends to, and drf-spectacular `ENUM_NAME_OVERRIDES` for new
|
|
899
|
+
choice fields.
|
|
900
|
+
- **`plan-feature`** names the enum for same-named choice fields that two
|
|
901
|
+
phases expose, lists the usual append-only registries, and records CI
|
|
902
|
+
checks that cannot run locally under `ci_only`.
|
|
903
|
+
- **`plan-feature`: a rename of a shared symbol is an interface change.** A
|
|
904
|
+
phase that renames something a same-wave sibling also uses does it in the
|
|
905
|
+
foundation phase or keeps the old name as an alias until the wave lands.
|
|
906
|
+
One run had a phase call a helper its sibling renamed; each passed alone and
|
|
907
|
+
the merged wave failed the typecheck.
|
|
908
|
+
- **`plan-feature`: gates cover what CI runs.** The workflow rules now tell the
|
|
909
|
+
author to read the CI config and give every locally runnable CI job a gate,
|
|
910
|
+
naming the checks plans miss: a deploy check at warning level, a
|
|
911
|
+
migrations-complete check, a "generated client is up to date" check. The
|
|
912
|
+
Django stack notes suggest `manage.py check --deploy --fail-level WARNING`,
|
|
913
|
+
`makemigrations --check` and a regenerate-and-diff gate for the schema or
|
|
914
|
+
client. One run's regex-style routes passed every gate and failed CI.
|
|
915
|
+
- **`write-unit-test`: time-independent tests and deterministic generated
|
|
916
|
+
output.** Rule 8 now requires a frozen clock and an explicit timezone on any
|
|
917
|
+
test touching dates, and host-independent schema or client generation
|
|
918
|
+
(values from a locked package such as `tzdata`, sorted). The Django pack and
|
|
919
|
+
stack notes spell out `freezegun` / `time-machine` with
|
|
920
|
+
`override_settings(TIME_ZONE=...)` and `tzdata`-sourced timezone choices.
|
|
921
|
+
One run had a date test fail only near midnight UTC, and a timezone enum
|
|
922
|
+
differ by machine.
|
|
923
|
+
- **`vinta-bootstrap-ai-tools`: test-tool caches are ignored before lanes run.**
|
|
924
|
+
The maestro defaults step reads `.gitignore` for the selected runners'
|
|
925
|
+
caches and reports (`.testmondata*`, `junit/`, coverage outputs, …),
|
|
926
|
+
checks for the `check-added-large-files` pre-commit hook, which a committed
|
|
927
|
+
testmon database trips on every lane and merge commit, and offers to append
|
|
928
|
+
the missing entries.
|
|
929
|
+
- **`vinta-ai-maestro`: a review that stated no verdict is no longer reported
|
|
930
|
+
as a rejection.** One run recorded 22 attempts as `review verdict "fail"; 0
|
|
931
|
+
fix rounds spent`. None had rejected anything: each was a review turn that
|
|
932
|
+
ended before its reviewer answered (fixed in alpha33 and alpha34). The
|
|
933
|
+
pipeline still treats silence as `fail`, but the failure reason now says
|
|
934
|
+
`the review turn stated no verdict`, and the `review` fact carries
|
|
935
|
+
`stated: false`. The budget clause is renamed to `gate fix rounds spent`,
|
|
936
|
+
since a review's findings are fixed inside its own turn and never in a
|
|
937
|
+
separate fix round.
|
|
938
|
+
|
|
939
|
+
- **`vinta-ai-maestro`: two empty turns in a row park the phase instead of
|
|
940
|
+
burning its retries.** Right after one run moved its desks to codex, "codex
|
|
941
|
+
ended the turn without the agent doing anything" failed 20 attempts across 4
|
|
942
|
+
phases in about two minutes. When one harness ends two turns in a row
|
|
943
|
+
without the agent doing anything, across attempts, the phase now skips its
|
|
944
|
+
automatic retries and asks: the question says the harness is failing and
|
|
945
|
+
suggests `retry with` a member on another harness. `--retry-after` still
|
|
946
|
+
answers it, and backs off from the first question.
|
|
947
|
+
|
|
948
|
+
- **`vinta-ai-maestro`: a red gate on a merged base is re-run on retry.** One
|
|
949
|
+
run's base test gate failed once on a test that broke only near midnight.
|
|
950
|
+
Seven retries replayed the cached verdict, each reported as "failed during
|
|
951
|
+
setup, before any agent ran", and the unattended retry was withheld until an
|
|
952
|
+
operator ran `gate-cache invalidate`. The base gates now replay only a green
|
|
953
|
+
verdict and re-run a red one, and a red base gate no longer counts as a
|
|
954
|
+
setup failure, so `--retry-after` keeps retrying it with its usual backoff.
|
|
955
|
+
|
|
956
|
+
- **`vinta-ai-maestro`: a lane that will not recycle says why.** One run
|
|
957
|
+
failed 20 attempts with only "could not be recycled (worktree)" or
|
|
958
|
+
"(database)" in the journal and the daemon log. The failure now carries the
|
|
959
|
+
failing step's exit code and the tail of its stderr, the way a failed
|
|
960
|
+
`setup_cmd` already did, and a `reset_cmd`, `setup_cmd` or `prepare_cmd`
|
|
961
|
+
failing during a recycle reports that command's own error instead of
|
|
962
|
+
`LaneSetupError`. Command lines are still left out.
|
|
963
|
+
|
|
662
964
|
- **`vinta-ai-maestro`: the full suite runs before a PR, and on every merged
|
|
663
965
|
tree.** Under `gate_scope: scoped`, a phase's gates ran their scoped form
|
|
664
966
|
everywhere, so a PR could carry a suite only a scoped run had seen, and most
|
|
@@ -1031,6 +1333,110 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
1031
1333
|
|
|
1032
1334
|
### Fixed
|
|
1033
1335
|
|
|
1336
|
+
- **`vinta-ai-maestro`: a review chore can no longer leave the lane dirty.**
|
|
1337
|
+
Whatever a review leaves uncommitted, such as a mutation experiment's
|
|
1338
|
+
reverted migration or a generated file, is set aside under a
|
|
1339
|
+
`refs/vinta-ai-maestro/wip/` ref. The lane is then reset to `HEAD` before
|
|
1340
|
+
the gates run, and `review_left_lane_dirty` is journalled. The implementer
|
|
1341
|
+
and conflict-fixer prompts now say to run one test command at a time per
|
|
1342
|
+
lane, to check `docker ps` for leftover run containers, and to treat a
|
|
1343
|
+
single test file that runs past two minutes as a lock or hang.
|
|
1344
|
+
- **Plan-execution prompts and the review-canvas chore.** The implementer
|
|
1345
|
+
prompt adds the same shared-test-resource rules. The conflict fixer
|
|
1346
|
+
reports `ENVIRONMENT_STALE` (and changes no code) when the merged tree's
|
|
1347
|
+
failures are columns or tables no model defines, and syntax-checks the
|
|
1348
|
+
files git auto-merged. The reviewer leaves the worktree as it found it:
|
|
1349
|
+
mutation experiments run in a throwaway worktree. `plan-feature`'s review
|
|
1350
|
+
chore prompt says so too. Its review-canvas chore passes
|
|
1351
|
+
`--data-dir .pr-review` inside the lane, and setup ignores `.pr-review/`.
|
|
1352
|
+
- **`vinta-ai-maestro`: conflicts in generated files no longer fail a
|
|
1353
|
+
merge.** After each conflict-fixer round, codegen outputs that the round
|
|
1354
|
+
left conflicted, or staged with conflict markers, are settled again and
|
|
1355
|
+
regenerated, even when the fixer aborted and redid the merge. The fixer's
|
|
1356
|
+
prompt now matches: with codegen declared, generated files are the
|
|
1357
|
+
integrator's; with none declared, every conflicted file is the fixer's. An
|
|
1358
|
+
unresolved conflict over files that look generated suggests declaring a
|
|
1359
|
+
`codegen` step.
|
|
1360
|
+
- **`vinta-ai-maestro`: `exec` streams, accepts `--reason`, and can be
|
|
1361
|
+
cancelled.** The daemon used to read each answer whole before sending
|
|
1362
|
+
it, so an `exec` queued behind the integration worktree sent nothing, and
|
|
1363
|
+
the client said the run was "not live" while the command still ran later.
|
|
1364
|
+
The answer now streams. The client says who it is queued behind, and
|
|
1365
|
+
ending the client cancels the command, whether it is queued or running.
|
|
1366
|
+
`--reason` is journalled. `exec --detach`, `exec list <run>` and
|
|
1367
|
+
`exec cancel <run> <id>` are new. Every release of the integration
|
|
1368
|
+
worktree lets the next waiter in.
|
|
1369
|
+
- **`vinta-ai-maestro`: a paused phase no longer takes the integration
|
|
1370
|
+
worktree.** A paused node waiting in the integration queue keeps its place
|
|
1371
|
+
but is passed over, and is let in once it is resumed. This is journalled
|
|
1372
|
+
as `node_wait` with state `paused`. `status` shows a node as paused as soon
|
|
1373
|
+
as the pause is sent, not only once it takes effect.
|
|
1374
|
+
- **`vinta-ai-maestro`: a lane that cannot be recycled no longer fails the
|
|
1375
|
+
phase handed to it.** A recycle that fails (outside the `preserve` stage)
|
|
1376
|
+
takes that lane out of the run and provisions a fresh one, `<lane>-r<N>`,
|
|
1377
|
+
and the phase runs there with nothing charged. The old lane stays on disk
|
|
1378
|
+
and is journalled as `lane_unhealthy`, with any paths git could not remove
|
|
1379
|
+
and their owner's uid. `status` shows it.
|
|
1380
|
+
- **`vinta-ai-maestro`: a provider or network outage no longer fails
|
|
1381
|
+
phases.** A turn that ends on an infrastructure error (DNS or connection
|
|
1382
|
+
failures, `upstream-unavailable`, HTTP 5xx or 529, an expired or rejected
|
|
1383
|
+
login) parks the harness with backoff and re-runs the phase when the
|
|
1384
|
+
harness answers. Nothing is charged to its attempts, retries or
|
|
1385
|
+
"N failures in a row" count. A lapsed login is asked once per harness, not
|
|
1386
|
+
once per phase. Each outage is journalled as `outage_started` /
|
|
1387
|
+
`outage_ended`, and `status` shows a line for every open one. The
|
|
1388
|
+
coordinator's digest no longer lists error lines from before a phase's
|
|
1389
|
+
last session that ended well.
|
|
1390
|
+
- **`vinta-ai-maestro`: integration gates no longer run against a test
|
|
1391
|
+
database left by another branch.** A command gate may declare `fresh_cmd`
|
|
1392
|
+
(also in `maestro.gates.<type>`), the same check from a fresh database (for
|
|
1393
|
+
example `pytest --create-db`). In the integration worktree it runs instead
|
|
1394
|
+
of `cmd` in four cases: when the tree moved anywhere but forward since the
|
|
1395
|
+
gate last ran there, on the gate's first run there, once more after a red
|
|
1396
|
+
run whose output shows missing or extra columns or relations, and after a
|
|
1397
|
+
conflict fixer ends its turn on `ENVIRONMENT_STALE`. That last round is
|
|
1398
|
+
given back. Each fresh run is journalled as `integration_fresh_state`.
|
|
1399
|
+
- **`vinta-ai-maestro`: a killed gate no longer leaves its Docker container
|
|
1400
|
+
running.** A timed-out or cancelled gate, `with` command or `exec` also
|
|
1401
|
+
removes the one-off `docker compose run` containers its lane's compose
|
|
1402
|
+
project started since the command began, before the pools, lease or
|
|
1403
|
+
integration worktree it held are released. A sweep every five minutes
|
|
1404
|
+
removes one-off containers in lanes no phase or `exec` is using, journalled
|
|
1405
|
+
as `orphan_containers_stopped`. Without docker, nothing changes.
|
|
1406
|
+
- **`vinta-ai-maestro`: the integrator no longer stages untracked files into
|
|
1407
|
+
a merge resolution.** It stages tracked paths and the merge's own paths
|
|
1408
|
+
instead of `git add --all`, so a gate's leftovers in the integration
|
|
1409
|
+
worktree (a `.testmondata-wal`, say) stay out of the merge commit. A kept
|
|
1410
|
+
resolution that changes paths outside the merge, or whose commit is refused
|
|
1411
|
+
again, is dropped instead of replayed on every retry. A conflict fixer now
|
|
1412
|
+
stages any new file it creates itself, and its prompt says so.
|
|
1413
|
+
- **`vinta-ai-maestro`: an amendment reaches the conflict fixer.** The fixer
|
|
1414
|
+
is rebuilt from the amended crew when the plan is amended, so a run whose
|
|
1415
|
+
desks moved to another harness stops failing on "conflict fixer spawn
|
|
1416
|
+
refused" for the harness it left.
|
|
1417
|
+
- **`vinta-ai-maestro`: a conflict fixer stopped by its time limit keeps its
|
|
1418
|
+
work.** What the round had is kept under `refs/vinta-ai-maestro/abandoned/`
|
|
1419
|
+
(an interrupted round's too), and the retry's fixer is pointed at it to
|
|
1420
|
+
continue instead of redoing the resolution from scratch.
|
|
1421
|
+
- **`vinta-ai-maestro`: an amended harness reaches every phase it moved.** An
|
|
1422
|
+
amendment changed the harness only on phases still `pending`; a failed or
|
|
1423
|
+
blocked one waiting on a retry kept naming the old harness in `status` and
|
|
1424
|
+
the run view, and once the job loaded only the new harness's adapter the
|
|
1425
|
+
run view answered 500 `unknown harness`. Phases past `pending` now take the
|
|
1426
|
+
new harness without losing their status, and the run view leaves out the
|
|
1427
|
+
capacity of a harness the live run loaded no adapter for.
|
|
1428
|
+
- **`vinta-ai-maestro`: `land` decides "already in the base" by content.** A
|
|
1429
|
+
review PR is landed when merging it into the base would leave the base's
|
|
1430
|
+
tree unchanged. The ancestry test it used alone kept an `integ-*` PR open
|
|
1431
|
+
after its plan PR merged: three bookkeeping merges were not in `main`, though
|
|
1432
|
+
every branch they merged was. A draft plan PR is now named as one (GitHub
|
|
1433
|
+
will not merge a draft), and `land <run> --ready` marks it ready for review.
|
|
1434
|
+
- **`vinta-ai-maestro`: a hook that rewrites files no longer refuses the
|
|
1435
|
+
commit outright.** When a commit fails having left modified files behind — a
|
|
1436
|
+
`pre-commit` formatter or schema generator — they are staged and the commit
|
|
1437
|
+
is tried once more before the operator is asked, in lanes and in the
|
|
1438
|
+
integration worktree. One run had seven merge commits refused this way.
|
|
1439
|
+
|
|
1034
1440
|
- **`vinta-ai-maestro`: a claude-code turn the CLI calls "blocked" no longer
|
|
1035
1441
|
fails unless a tool was refused in it.** The CLI's own turn summary marks a
|
|
1036
1442
|
turn `blocked` whenever its last message names a next step for a person —
|
package/package.json
CHANGED