vinta-ai-workflows 0.7.0-alpha8 → 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 +472 -595
  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 +751 -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
@@ -79,6 +79,8 @@ For Python: read `pyproject.toml:[tool.poetry.scripts]` / `[project.scripts]` +
79
79
 
80
80
  For other languages: read `Makefile` + `justfile` + language-specific files (`Cargo.toml:[bin]`, etc).
81
81
 
82
+ Worktree provisioning: look for an existing script that sets up a git worktree, such as `bin/*worktree*` / `scripts/*worktree*` files, a `Makefile` / `justfile` target or `package.json` script with `worktree` in its name, or a `.gtrconfig` / `git gtr` setup. Record each one in `commands.worktree_candidates`, with a matching teardown when one exists. The bootstrap's `prepare-worktree` question offers them as the project's own provisioning command.
83
+
82
84
  Note: many repos have the test command in CI config but not surfaced as a top-level script. Read `.github/workflows/*.yml` / `.gitlab-ci.yml` / `.circleci/config.yml` / `Jenkinsfile` to confirm.
83
85
 
84
86
  ### 5. Monorepo shape
@@ -164,6 +166,7 @@ For each skill, also classify:
164
166
 
165
167
  - `vinta-managed` — directory name starts with `vinta-` (installed by `vinta-ai-workflows`; can be left alone or refreshed via that CLI).
166
168
  - `foundation-shape` — name matches the Vinta foundation set (`plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `implement-phase`, `review-phase`, `integrate-phase`, `amend-plan`, `add-e2e-test`, `add-env-var`, `write-unit-test`). `implement-phase` / `review-phase` / `integrate-phase` are the plan-execution sub-skills co-shipped with `implement-plan`.
169
+ - `integration` — installed by an external tool that the bootstrap's **Integrations** group knows about. The directory carries that tool's marker, such as `pr-review-canvas/` with a `.pr-review-install` file (installed by `pr-review install-skill`). The tool owns it. Record it, and also record `pr-review.config.yml` at the repo root when present, so the bootstrap can default the integration question to `Yes`.
167
170
  - `project-custom` — anything else; written by the team.
168
171
 
169
172
  **Sub-agents** — list every agent file with its name + description:
@@ -275,6 +278,8 @@ commands:
275
278
  lint: <e.g. pnpm lint>
276
279
  format: <e.g. pnpm format>
277
280
  typecheck: <e.g. pnpm build (tsc) — or null if no separate command>
281
+ worktree_candidates: # existing worktree-provisioning scripts; [] when none
282
+ - { prepare: <e.g. ./bin/new-worktree>, teardown: <e.g. ./bin/rm-worktree — or null>, signal: <path of the script / Makefile / package.json> }
278
283
 
279
284
  tests:
280
285
  unit_framework: vitest | jest | pytest | ...
@@ -23,10 +23,11 @@ This orchestrator runs six sub-skills in order. Each is its own SKILL.md so it c
23
23
  2. [vinta-write-agents-md](../vinta-write-agents-md/SKILL.md) — synthesize the root `AGENTS.md` from the inventory + a focused interview for what the analysis can't see.
24
24
  3. [vinta-derive-subagents](../vinta-derive-subagents/SKILL.md) — author `ai-tools/agents/*.yaml`. Always emits the foundation trio (`implementer`, `reviewer`, `fixer`); adds stack-specific specialists when the user supplies a template for a matched stack.
25
25
  4. [vinta-derive-skills](../vinta-derive-skills/SKILL.md) — author `ai-tools/skills/*/SKILL.md`. Always copies the project-agnostic foundation set (`plan-feature`, `create-spec`, `create-qa-use-cases`) verbatim from its bundled resources. Generates `implement-plan` from a parameterized template using project specifics. Asks the user whether the optional `add-e2e-test` and `add-env-var` skills are needed. Asks for stack-specific templates per matched stack.
26
- 5. [vinta-install-ai-tools-setup](../vinta-install-ai-tools-setup/SKILL.md) — copy the canonical `setup-ai-tools.mjs` into `ai-tools/scripts/`, wire the package script alias, run setup, verify all vendor paths resolve.
26
+ - *Optional, after step 4:* [Generate the worktree command](#optional-step--generate-the-worktree-command) — only when the `prepare-worktree` answer was `generate a provisioning script`. Writes `prepare.sh` / `teardown.sh` into the project from bundled templates.
27
+ 5. [vinta-install-ai-tools-setup](../vinta-install-ai-tools-setup/SKILL.md) — copy the canonical `setup-ai-tools.mjs` into `ai-tools/scripts/`, wire the package script alias, run setup, verify all vendor paths resolve. Then install the skills of any enabled integration (D.2) through that tool's own CLI.
27
28
  6. [vinta-migrate-plans-specs](../vinta-migrate-plans-specs/SKILL.md) — find any pre-existing implementation plans / feature specs scattered across the repo (`docs/`, `specs/`, `plans/`, root markdown, etc.) and propose moving them to the canonical layout `ai-plans/YYYY-MM-DD-{FEATURE_NAME}_{PLAN|SPEC}.md`. Read-only by default; every rename is gated on per-file user approval. Skipped automatically when the analysis finds no candidates.
28
29
 
29
- Each sub-skill returns a short status report. Don't run the next sub-skill until the previous finished cleanly. If a sub-skill fails or surfaces ambiguity, surface that to the user and resolve before continuing.
30
+ Each sub-skill returns a short status report. Don't run the next sub-skill until the previous finished cleanly. If a sub-skill fails or surfaces ambiguity, resolve it with the user before continuing — as an `AskUserQuestion` with concrete options (e.g. `Retry <sub-skill> (Recommended)`, `Skip it, continue`, `Stop`), never as a prose question at the end of the status report.
30
31
 
31
32
  ### Sibling skill — `create-qa-use-cases`
32
33
 
@@ -47,7 +48,7 @@ If the repo already has an `AGENTS.md` (at the root, or at the legacy `ai-tools/
47
48
 
48
49
  ## Interview (Step 0 — before any sub-skill runs)
49
50
 
50
- Use `AskUserQuestion` for finite-choice questions; iterate plain prose for open-ended ones. Same convention as [plan-feature](../plan-feature/SKILL.md) and [create-spec](../create-spec/SKILL.md).
51
+ Every question goes through `AskUserQuestion` — the harness's structured question tool, which renders clickable options plus a free-text field. On harnesses other than Claude Code, use the equivalent tool listed in [asking-the-human](../vinta-write-agents-md/resources/asking-the-human.md), and follow its shape rules: 2–4 options, recommended first with ` (Recommended)`, no "Other" option, up to 4 questions per call (3 on Codex). For open-ended questions, offer the candidates the analysis found (detected commands, paths, environments, branch names) as options; the free-text field covers the rest. Plain prose only when there is no candidate at all, one question per message.
51
52
 
52
53
  ### A. Scope
53
54
 
@@ -93,11 +94,36 @@ These bleed across sub-skills, so capture once now:
93
94
 
94
95
  **Additional conventions (optional).** Open prose: *"Any recurring test conventions the four fields above don't capture? (e.g. 'co-locate tests as `*.test.ts` next to source', 'name tests `should_<behavior>_when_<condition>`', 'mock HTTP with our recorded-cassette helper'.)"* On an existing project, seed this from the extras `vinta-analyze-codebase` surfaced and let the user trim. Each entry lands in `skills.write-unit-test.additional_conventions[]`. Leave empty when there's nothing project-specific — the universal rules + framework pack already cover the essentials.
95
96
 
96
- 10. **Agent model tiers (optional).** The plan-execution family picks the **implementer** model per phase from the plan itself, but the **reviewer**, **fixer**, and the mechanical steps (**worktree prep**, **opening the PR / integrate**) have no model input unless the project sets one. Offer to pin each to a **tier** (1–4) into the same table `plan-feature` uses — `ai-tools/skills/plan-feature/resources/ai-models.yaml` — so review runs on a capable model while cheap mechanical work runs on a cheap one. `AskUserQuestion`: `Use recommended defaults (reviewer 3, fixer 2, worktree prep 1, integrate 1)`, `Customize each`, `Leave unset — every spawn uses the runtime default`. On `Customize each`, ask a per-role tier (1–4) for `reviewer` / `fixer` / `worktree_prep` / `integrate`. Land the chosen tiers in `.vinta-ai-workflows.yaml` `agent_models`; omit any role the user leaves unset (unset → runtime default). Recommend the defaults for most teams; recommend `Leave unset` only when the runtime exposes a single model anyway. Note `worktree_prep` is a no-op unless `prepare-worktree` is enabled, and setting `worktree_prep` / `integrate` makes `implement-plan` delegate those steps to a cheap subagent instead of running them inline.
97
+ 10. **Agent model tiers (optional).** The plan-execution family picks the **implementer** model per phase from the plan itself, and `review-phase` runs its reviewer one tier above the implementer, so neither is asked here. The merge-conflict **fixer** and the mechanical steps (**worktree prep**, **opening the PR / integrate**) have no model input unless the project sets one. Offer to pin each to a **tier** (1–4) into the same table `plan-feature` uses — `ai-tools/skills/plan-feature/resources/ai-models.yaml` — so cheap mechanical work runs on a cheap model. `AskUserQuestion`: `Use recommended defaults (fixer 2, worktree prep 1, integrate 1)`, `Customize each`, `Leave unset — every spawn uses the runtime default`. On `Customize each`, ask a per-role tier (1–4) for `fixer` / `worktree_prep` / `integrate`. Never ask for or emit `reviewer`: `agent_models.reviewer` is deprecated and ignored. Land the chosen tiers in `.vinta-ai-workflows.yaml` `agent_models`; omit any role the user leaves unset (unset → runtime default). Recommend the defaults for most teams; recommend `Leave unset` only when the runtime exposes a single model anyway. Note `worktree_prep` is a no-op unless `prepare-worktree` is enabled, and setting `worktree_prep` / `integrate` makes `implement-plan` delegate those steps to a cheap subagent instead of running them inline.
98
+
99
+ 11. **`vinta-ai-maestro` defaults (optional).** Every plan `plan-feature` writes ships a `.workflow.json` that [vinta-ai-maestro](https://github.com/vintasoftware/vinta-ai-workflows/tree/main/packages/vinta-ai-maestro) executes, and most of what is in it repeats from plan to plan: which gates every phase runs, the pool the test suite contends for, the review and comment-hygiene chores. A `maestro:` section here holds those once, and each plan states only what is different. `AskUserQuestion` (header `Maestro`): `Set project defaults (Recommended)`, `Skip — plans carry everything themselves`. Recommend skipping only when the team does not run maestro.
100
+
101
+ On `Set project defaults`, capture:
102
+ - **Gates every phase runs.** Multi-select `AskUserQuestion` over the types the commands above give a command for: `typecheck` (from `commands.build`), `lint`, `test` (from `commands.test_unit`), and `e2e` only when `add-e2e-test` is enabled. → `maestro.defaults.gates`.
103
+ - **A different command for maestro.** `AskUserQuestion` per selected type: `Same as commands.* (Recommended)`, `Different for maestro (I'll give it)`. Teams pick a different one when lanes need a flag the inner loop does not, e.g. `pytest --reuse-db -n auto`. → `maestro.gates.<type>.cmd`. `implement-plan` keeps running `commands.*`.
104
+ - **Scoped gates.** Only when `test` (or `lint`) is selected: should a phase's gate run narrowed to the files the phase changed until its review approves, with the full command run after the review and on every merged tree? `AskUserQuestion`: `Yes — scoped until review, full after (Recommended)`, `No — full command every time`. On `Yes`, propose a template with `{changed_files}` for the detected runner (`vitest related {changed_files} --run`, `jest --findRelatedTests {changed_files}`, `pytest --testmon {changed_files}`, `ruff check {changed_files}`) and confirm it. It lands in `commands.test_unit_scoped` / `commands.lint_scoped`, where `implement-plan` reads it too. `No` sets `maestro.defaults.gate_scope: full`.
105
+ - **Cold lanes.** Only when the scoped template narrows by a cache, as `pytest --testmon` does with `.testmondata`. A lane has no cache until a run builds one, and a testmon run without one runs **every** test, serially: one observed run spent 30–40 minutes per phase gate that way. Say so, and that `--testmon` together with `-n` (xdist) trades correctness for speed — testmon cannot see which tests a worker ran, so the project's scoped line normally runs without `-n`. `AskUserQuestion` (header `Cold lanes`): `Run the full suite in parallel until a lane has a cache (Recommended)`, `Keep the scoped command — it handles a missing cache itself`. On the first, emit `maestro.gates.test.scope_cache` (the cache path, relative to the repo, e.g. `apps/api/.testmondata`), `maestro.gates.test.cold_cmd` (the parallel full suite, e.g. `make test`), and `maestro.project.lane_seed` with the same paths, so a lane is handed a copy from its dependency's lane. When the scoped line is a task-runner target (`make test_changed`), also propose the fallback in the target itself, so `implement-plan` and a person get it too:
106
+
107
+ ```make
108
+ test_changed:
109
+ @if [ ! -f .testmondata ]; then $(MAKE) test; else <the testmon command>; fi
110
+ ```
111
+
112
+ Show it as a proposed edit and apply it only on the user's yes.
113
+ - **Fresh database in the integration worktree.** Only when the test command keeps its database between runs (`--reuse-db`, `--keepdb`, a fixture that skips migrations on an existing schema). Maestro's integration worktree runs merges for different branches one after another, and a reused database applies each tree's migrations on top of the last tree's — one observed run had three merges fail on columns and tables that belonged to another branch. `AskUserQuestion` (header `Fresh DB`): `Recreate the database there when the tree changes (Recommended)`, `Keep reusing it`. On the first, propose the fresh form of the command (`--create-db` in place of `--reuse-db`, or `make test_reset test`), confirm it, and emit it as `maestro.gates.test.fresh_cmd`, plus `tuning.allowed_flags: ['--create-db']` when the flag form fits, so the run coordinator can add the flag without being refused for rewriting the command. Then name the migration files from the inventory as globs (`apps/*/migrations/*.py`, `db/migrate/*.rb`, `prisma/migrations/**`) and emit them as `maestro.gates.test.fresh_when`: a phase that rewrites or renames one of its own migrations moves the tree forward and still leaves a reused database recording the old one, and these globs are what tell maestro so. Offer them as candidates in the same confirmation rather than as a second question.
114
+ - **When the full suite runs.** Only on `Yes` above. `AskUserQuestion`: `After each review and on every merged tree (Recommended)`, `Only on merged trees`, `Only on merged waves`. The first is the default and emits nothing. `Only on merged trees` skips the per-phase full run after review (`maestro.defaults.verify_gates: scoped`), for a suite too slow to run once per phase. `Only on merged waves` also leaves multi-dependency bases unchecked (`verify_gates: scoped` and `base_gates: off`).
115
+ - **A test-suite pool.** `AskUserQuestion`: `One suite at a time (Recommended for DB-backed suites)`, `Two at a time`, `No limit`. A limit emits `maestro.resources.test-suite` (`kind: semaphore`, `capacity` 1 or 2, `scope: host`) and `maestro.gates.test.requires: [test-suite]`. `scope: host` makes the limit hold across every maestro run on the machine, not just within one: two runs on one laptop, each with a one-suite limit, otherwise run two suites at once — the contention the limit exists to prevent. Then offer the runner's command patterns as the pool's `match` (`pytest*`, `uv run pytest*`, `pnpm test*`), which makes agents take the lease before running tests by hand.
116
+ - **Files git does not carry.** A maestro lane is a worktree and has only what git tracks. Read `.gitignore` for entries with a tracked `*.example` / `*.sample` / `*.template` sibling, the compose file's `env_file:` lines, and the gitignored settings module the framework imports (`DJANGO_SETTINGS_MODULE`'s local module, typically). Propose the list in a multi-select `AskUserQuestion` (header `Env files`), each path pre-selected; the user confirms or drops entries. → `maestro.project.env_files`. Every hook, gate and `manage.py` call in a lane depends on these, and a plan that omits them fails in ways that look like code problems. Nothing found → omit the key and say so.
117
+
118
+ - **Test-tool caches git must not carry.** Gates in a lane write cache and report files into the worktree, and an agent's `git add -A` there commits whatever is not ignored. Read `.gitignore` for the outputs of the runners and gates selected above: `.testmondata*` (pytest-testmon's SQLite database, plus its `-shm` / `-wal` siblings — tens of MB), `.pytest_cache/`, `junit/` or `junit*.xml`, `coverage/`, `.coverage`, `.coverage.*`, `htmlcov/`, `coverage.xml`, `.nyc_output/`, `.vitest/` and `.jest-cache/` where those runners are in use. Then read `.pre-commit-config.yaml` (or the project's hook runner) for `check-added-large-files`: that hook checks staged files, so a testmon database that is not ignored fails every lane commit and every maestro merge commit (`project.hooks: run`), and looks like a hook problem rather than a missing ignore rule. Propose the missing entries in a multi-select `AskUserQuestion` (header `Cache ignores`), each pre-selected, with `Add the selected entries (Recommended)` meaning append them to `.gitignore` under a `# test-tool caches` comment. When one is already tracked, say so: ignoring it does not untrack it, and the human runs `git rm --cached <path>` themselves. Nothing missing → say so and add nothing.
119
+ - **CI checks.** Read the CI config (`.github/workflows/*.yml`, `.gitlab-ci.yml`) for each check it runs — tests, lint, type check, `makemigrations --check --dry-run`, `check --deploy --fail-level WARNING`, a "generated client is current" diff — and compare with the gates chosen above. For each check no gate runs, `AskUserQuestion` (header `CI check`): `Add it as a project gate (Recommended)`, `Leave it to CI — it needs CI (I'll say why)`. A gate lands as `maestro.gates.<id>.cmd` with its id added to `maestro.defaults.gates`. A check left to CI lands under `maestro.ci_only` with its command and the reason, which `vinta-ai-maestro doctor` reports as a decision rather than warning about it on every run. Never drop one silently: an unrecorded gap is a warning in every run's log that people learn to skip.
120
+ - **Generated files and append-only registries.** Read the project for generators — an API schema command (`spectacular`, an `openapi.json` dump), a generated client (`openapi-ts`, `orval`, `openapi-generator`, `graphql-codegen`; `*.gen.ts`), a route tree (`routeTree.gen.ts`) — and for file-modifying hooks in `.pre-commit-config.yaml` / `lefthook.yml` / `lint-staged` (a schema hook, `ruff format`, `prettier --write`). Propose each as a codegen step in a multi-select `AskUserQuestion` (header `Codegen`), pre-selected, showing its command, inputs and outputs; a formatter is `format: true` with `{changed_files}` in its command. → `maestro.codegen`. Then propose append-only registries — DI containers, URL route lists, notification-kind registries, beat schedules — in a second multi-select (header `Registries`). → `maestro.append_only`. Nothing found → omit both keys and say so.
121
+
122
+ Everything here is a default under every plan. A plan's own `.workflow.json` overrides any of it, and a commit to this file on a running plan's branch (`plan/<workflow-id>/base`) is applied to that run.
97
123
 
98
124
  ### D. Optional foundation skills
99
125
 
100
- Seven skills are part of the foundation set but aren't always needed. Ask explicitly:
126
+ Eight skills are part of the foundation set but aren't always needed. Ask explicitly:
101
127
 
102
128
  1. **`add-e2e-test`** — does the project have e2e tests (Playwright / Cypress / similar) or plan to add them? `AskUserQuestion` options: `Yes — already has them`, `Yes — planning to add`, `No — skip`. If yes, [vinta-derive-skills](../vinta-derive-skills/SKILL.md)'s **Optional — ask the user** bucket follows up to ask whether the user has a template or wants to draft from scratch. **This answer also governs `create-qa-use-cases` and the e2e content inside `plan-feature`**: on `No — skip`, set `foundation_skills.create-qa-use-cases: disabled` too — derive-skills won't ship `create-qa-use-cases` and strips `plan-feature`'s `<!-- e2e:start/end -->` regions so no-e2e projects carry zero Playwright / `QA_USE_CASES.md` / `pr-screenshots/` references. On either `Yes`, set both `add-e2e-test` and `create-qa-use-cases` to `enabled`.
103
129
  2. **`add-env-var`** — does the project have a non-trivial env-var propagation flow (multiple files / build configs / CI updates per new var) or a single `.env` file is enough? `AskUserQuestion` options: `Yes — non-trivial flow`, `No — single .env is enough`. Skip if `No`.
@@ -109,11 +135,22 @@ Seven skills are part of the foundation set but aren't always needed. Ask explic
109
135
  - **Primary language.** `AskUserQuestion`: `Python`, `TypeScript`. Auto-pick from `inventory.frameworks` when one language clearly dominates; ask only when polyglot. Drives which `BaseOneOffScript` template gets staged at `<scripts_dir>/_base.{py,ts}`.
110
136
  - **S3 bucket + prefix.** Open prose. Empty bucket disables S3 upload (filesystem copy stays authoritative). The skill also reads the `ONE_OFF_S3_BUCKET` / `ONE_OFF_S3_PREFIX` env vars at runtime, so leaving the config blank is fine if the team prefers env-only.
111
137
 
112
- 5. **`prepare-worktree`** — does the team want to run long-running plans / experiments inside an isolated git worktree (its own runnable copy of the app, with its own dev + test DB, env files, docker-compose project name) instead of swapping branches in the main checkout? `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for any project with long migrations, multi-day plans, or teams where parallel concurrent work in the same checkout is common (one dev shipping a feature while another runs a migration; an agent driving `implement-plan` for hours while the human keeps coding on `main`). Skip for solo projects where branch-switching in place is unproblematic.
138
+ 5. **`prepare-worktree`** — does the team want to run long-running plans / experiments inside an isolated git worktree (its own runnable copy of the app, with its own dev + test DB, env files, docker-compose project name) instead of swapping branches in the main checkout? `AskUserQuestion` options: `Yes — enable the skill`, `Yes — we provision with our own script/command`, `Yes — generate a provisioning script for this project`, `No — skip`. The second option is for teams that already have a provisioning script, and the third writes one for them. Both make provisioning deterministic and LLM-free: `implement-plan` runs the command instead of the skill (see the follow-ups below). Recommend the third for teams that want worktrees but have no script, when runs are frequent or parallel: the provisioning decisions are made once at bootstrap instead of by a model on every lane. Recommend it over the skill when inventory found an existing worktree script (`commands.worktree_candidates`): a `bin/*worktree*` / `scripts/*worktree*` file, or a Makefile / `justfile` / `package.json` target with `worktree` in its name. Recommend `Yes` for any project with long migrations, multi-day plans, or teams where parallel concurrent work in the same checkout is common (one dev shipping a feature while another runs a migration; an agent driving `implement-plan` for hours while the human keeps coding on `main`). Skip for solo projects where branch-switching in place is unproblematic.
113
139
 
114
- **Follow-up only when `prepare-worktree` = Yes — worktree defaults.** Three short questions land under `skills.prepare-worktree.*`:
140
+ **Follow-up only when `prepare-worktree` = own script/command.** The skill does not ship (`foundation_skills.prepare-worktree: disabled`). Worktrees stay available, because `implement-plan` treats a configured command as the provisioner.
141
+ - **Prepare command.** `AskUserQuestion` (header `Worktree cmd`): one option per `commands.worktree_candidates` entry, as its invocation (`./bin/new-worktree`, `make worktree`, …); free text for any other. Prose only when nothing was found. Lands in `commands.worktree_prepare`. Show the user the contract their script must honor. It runs from the repo root with `VINTA_WORKTREE_NAME`, `VINTA_WORKTREE_PATH`, `VINTA_WORKTREE_BRANCH`, `VINTA_WORKTREE_BASE_REF`, `VINTA_WORKTREE_KIND`, `VINTA_MAIN_CHECKOUT`, `VINTA_PLAN_PATH` and `VINTA_WORKTREE_SUMMARY` set. It must create a runnable worktree at that path on that new branch, and exit non-zero on failure. Writing the summary YAML is optional. The full text is the `commands.worktree_prepare` description in the config schema. If their existing script takes positional arguments instead, offer a wrapper invocation (`./bin/new-worktree "$VINTA_WORKTREE_NAME" "$VINTA_WORKTREE_PATH"`) as the candidate.
142
+ - **Teardown command.** `AskUserQuestion` (header `Teardown`): the candidates found, plus `No teardown command — just git worktree remove`. Note on that option that any DB, volume or cache the prepare command creates would be left behind. Lands in `commands.worktree_teardown`; omit the key on `No`.
143
+ - **Worktree root.** Same question as in the skill follow-up below. Lands in `skills.prepare-worktree.worktree_root`; the conductor uses it to build `VINTA_WORKTREE_PATH`. The deps / test-DB strategy questions are skill-only, so skip them.
144
+ - The `implement-plan` worktree default and the parallel-execution follow-ups below apply as they do for the skill.
145
+
146
+ **Follow-up only when `prepare-worktree` = generate a provisioning script.** The skill does not ship (`foundation_skills.prepare-worktree: disabled`). The scripts are written by the optional [Generate the worktree command](#optional-step--generate-the-worktree-command) step after derive-skills; here, capture only what Step 0.5 needs:
147
+ - **Script directory.** `AskUserQuestion` (header `Script dir`): `scripts/worktree (Recommended)`, `bin/worktree`, plus any existing scripts directory the inventory found. Free text covers other paths. Step 0.5 emits `commands.worktree_prepare: <dir>/prepare.sh` and `commands.worktree_teardown: <dir>/teardown.sh`.
148
+ - **Worktree root.** Same question as in the skill follow-up below; lands in `skills.prepare-worktree.worktree_root`.
149
+ - The `implement-plan` worktree default and the parallel-execution follow-ups below apply as they do for the skill.
150
+
151
+ **Follow-up only when `prepare-worktree` = Yes — enable the skill — worktree defaults.** Three short questions land under `skills.prepare-worktree.*`:
115
152
  - **Worktree root.** `AskUserQuestion`: `.claude/worktrees` (claude-code convention; the runtime's `EnterWorktree` puts them there), `../<repo-name>-wt-` (sibling dirs of the main checkout — survives across runtimes; relative-path tooling that walks up still works). Auto-pick the first when claude-code is the only selected vendor; ask when multiple vendors are in the **Scope** group's vendor coverage answer.
116
- - **Default deps strategy when the plan does NOT install new deps.** `AskUserQuestion`: `symlink` (fastest, reuses main's `node_modules` / `vendor/` / `venv/`), `copy` (defensive; safe for pnpm + npm + cargo + go; risky for yarn PnP + venv), `reinstall` (slowest, always correct). Recommend `symlink` for pnpm / npm / cargo / go projects; `reinstall` for poetry / yarn PnP.
153
+ - **Default deps strategy.** Every worktree gets its own dependency dirs and never symlinks main's. `AskUserQuestion`: `copy` (copy-on-write clone of main's `node_modules` / `vendor/` — fast and close to free on disk on APFS / btrfs / XFS; right for npm / pnpm / cargo / go / bundler), `reinstall` (run the package manager fresh in the worktree — slower, but always correct). Recommend `copy`, except `reinstall` for poetry / uv / venv / yarn PnP projects, whose trees store absolute paths into the main checkout. The skill reinstalls virtualenvs and yarn PnP regardless of this default.
117
154
  - **Default test-DB strategy.** `AskUserQuestion`: `fork-on-schema-change` (default — only forks when the plan body shows migrations), `always-fork` (defensive — every worktree gets its own test DB regardless), `share` (only safe for solo work; flaky cross-worktree test runs are the cost).
118
155
 
119
156
  **Follow-up — `implement-plan` default for worktree opt-in.** `AskUserQuestion`: should the `implement-plan` Step 0 question (c) — "run phases in a worktree?" — default to `Yes` or `No`? Lands in `run_options.implement-plan.use_worktree`. Recommend `No` for solo projects + short plans; `Yes` for teams that already use worktrees as part of their workflow.
@@ -122,9 +159,9 @@ Seven skills are part of the foundation set but aren't always needed. Ask explic
122
159
  - **Default for Step 0 question (e)?** `AskUserQuestion`: when a plan's dependency graph says several phases are independent, should `implement-plan` implement them **concurrently** (one worktree lane each) by default, or one at a time? Lands in `run_options.implement-plan.parallel_phases`. **Recommend `Yes` (the schema default)** — it is the whole reason the plan carries a dependency graph. Recommend `No` when review capacity is the team's bottleneck (a fan of simultaneous PRs helps nobody), when the repo has a merge queue that serializes anyway, or when developer machines are too small to run several app copies.
123
160
  - **Lane cap.** `AskUserQuestion`: `2`, `3` (default), `4`, `6`. Lands in `run_options.implement-plan.max_parallel_lanes`. Each lane is a full runnable checkout — deps, forked dev + test DBs, its own compose project. Size it to the machine, not to the plan; the runtime caps it again at the widest wave.
124
161
 
125
- Both are skipped, and `parallel_phases` is emitted as `false`, when `prepare-worktree` = No — parallel execution has a hard worktree requirement and `implement-plan` refuses rather than degrading.
162
+ Both are skipped, and `parallel_phases` is emitted as `false`, when `prepare-worktree` = No (neither the skill nor a command) — parallel execution has a hard worktree requirement and `implement-plan` refuses rather than degrading.
126
163
 
127
- **Follow-up only when `systematic-debugging` = Yes — observability MCP server inventory.** Open prose, not multi-select. Ask the user to name every MCP server already wired up that exposes observability data, in whatever shorthand the team uses (`sentry`, `datadog`, `our-internal-traces`, `grafana-prod`, etc.). The intent is not to pick from a fixed catalogue — that goes stale fast — but to give the systematic-debugging agent a starter list of servers to introspect at Phase 0. Cross-check the answers against any MCP servers actually configured in the project's AI tooling (`.mcp.json`, `~/.claude/mcp_servers.json`, `.codex/mcp.json`, etc.) — if a server is configured but the user didn't mention it, ask whether it carries observability data. The selection lands in `skills.systematic-debugging.observability_mcp_servers` of `.vinta-ai-workflows.yaml` (free-form string array). Empty array is allowed but warn the user that Phase 0 collapses to "local logs only" and production-only bugs without telemetry become a guess factory. The agent will discover specific tool names + categories (error tracking, traces, logs, metrics, alerts, deploys, dashboards) from the live MCP tool list at runtime — see [vinta-derive-skills/resources/systematic-debugging-mcp-tools.md](../vinta-derive-skills/resources/systematic-debugging-mcp-tools.md) for the evidence categories baked into the rendered SKILL.md.
164
+ **Follow-up only when `systematic-debugging` = Yes — observability MCP server inventory.** First read the MCP servers actually configured in the project's AI tooling (`.mcp.json`, `~/.claude/mcp_servers.json`, `.codex/mcp.json`, etc.). Then ask a multi-select `AskUserQuestion` (header `MCP servers`): *"Which of these MCP servers expose observability data (errors, traces, logs, metrics)?"*, one option per configured server (up to 4; split into further calls when there are more). The free-text field takes any server not listed, in whatever shorthand the team uses (`sentry`, `datadog`, `our-internal-traces`, `grafana-prod`, etc.). When nothing is configured, ask the same thing in prose. The intent is not to pick from a fixed catalogue — that goes stale fast — but to give the systematic-debugging agent a starter list of servers to introspect at Phase 0. The selection lands in `skills.systematic-debugging.observability_mcp_servers` of `.vinta-ai-workflows.yaml` (free-form string array). Empty array is allowed but warn the user that Phase 0 collapses to "local logs only" and production-only bugs without telemetry become a guess factory. The agent will discover specific tool names + categories (error tracking, traces, logs, metrics, alerts, deploys, dashboards) from the live MCP tool list at runtime — see [vinta-derive-skills/resources/systematic-debugging-mcp-tools.md](../vinta-derive-skills/resources/systematic-debugging-mcp-tools.md) for the evidence categories baked into the rendered SKILL.md.
128
165
 
129
166
  **Cache scaffolding.** Preflight state lives at `.vinta-ai-workflows/cache.yaml` ([`mcp-preflight-cache.v1`](../../schemas/mcp-preflight-cache.v1.schema.json)). The bootstrap orchestrator must:
130
167
 
@@ -132,9 +169,11 @@ Seven skills are part of the foundation set but aren't always needed. Ask explic
132
169
  - Do **not** seed the cache file at bootstrap. The first debug run preflights all configured servers and writes the file then. An empty / missing `.vinta-ai-workflows/cache.yaml` is a valid initial state.
133
170
  - Mention to the user how to refresh: delete the file to re-preflight everything, or edit one entry's `status` to `dirty` to refresh that one server. Token rotated → cache will catch the auth error on the next call and flip the entry to `dirty` automatically.
134
171
 
135
- 6. **`thermo-nuclear-code-quality-review`** — does the team want an opt-in, deliberately harsh structural-maintainability audit available on demand (abstraction quality, giant files, spaghetti-condition growth), separate from the standard per-phase review? `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for long-lived codebases where structural drift is a real cost, or teams that already run deep quality passes before merging large work. It ships as a user-invoked skill and is also the escalation target for the `review-phase` Layer 3 structural-simplification lens; it is never auto-run on every diff. No follow-up config — the body is project-agnostic.
172
+ 6. **`thermo-nuclear-code-quality-review`** — does the team want an opt-in, deliberately harsh structural-maintainability audit available on demand (abstraction quality, giant files, spaghetti-condition growth), separate from the standard per-phase review? `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for long-lived codebases where structural drift is a real cost, or teams that already run deep quality passes before merging large work. It ships as a user-invoked skill, a deeper pass on top of the structural lens the per-phase review loop already applies; it is never auto-run on every diff. No follow-up config — the body is project-agnostic.
173
+
174
+ 7. **`interview-ui`** — does the team want spec interviews (and, later, other decision-heavy interviews) to run as a full-screen browser form instead of a chat exchange? One decision per screen, with the context the agent already knows, Markdown/Mermaid explainers, and each option's consequences in view; the in-page chat is for questions to the agent, not decisions. `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for teams where product or non-engineering stakeholders answer the spec interview, or whenever specs carry state machines and trade-offs that are hard to weigh in chat. Skip for solo engineers who prefer staying in the terminal. The page is served by `vinta-ai-maestro interview` (Node ≥ 22; `npx vinta-ai-maestro`, or a devDependency) and needs a browser on the machine running the agent. No follow-up config — the body is project-agnostic; `create-spec` asks per interview whether to use the browser or chat.
136
175
 
137
- 7. **`handoff-to-client`** — is this an API-only repo whose consumers live in separate client codebases (mobile apps, SPAs, partner integrations) that need API changes documented for them? Ask **only when the inventory suggests an API-only shape** — backend framework with no co-located frontend app (no SPA package, no templates-rendered UI beyond an admin). `AskUserQuestion` options: `Yes — enable`, `No — skip`. Skip the question entirely (set `disabled`) for full-stack repos and monorepos that contain their own clients — there the API diff is visible to the client code in the same PR. When enabled, agents can generate a markdown API-change handoff document (endpoints added / changed / deprecated / removed vs the default branch, request/response shapes, breaking-change flags, per-platform migration notes) for client implementers who cannot read this repo.
176
+ 8. **`handoff-to-client`** — is this an API-only repo whose consumers live in separate client codebases (mobile apps, SPAs, partner integrations) that need API changes documented for them? Ask **only when the inventory suggests an API-only shape** — backend framework with no co-located frontend app (no SPA package, no templates-rendered UI beyond an admin). `AskUserQuestion` options: `Yes — enable`, `No — skip`. Skip the question entirely (set `disabled`) for full-stack repos and monorepos that contain their own clients — there the API diff is visible to the client code in the same PR. When enabled, agents can generate a markdown API-change handoff document (endpoints added / changed / deprecated / removed vs the default branch, request/response shapes, breaking-change flags, per-platform migration notes) for client implementers who cannot read this repo.
138
177
 
139
178
  **Follow-up only when `handoff-to-client` = Yes — client-handoff config.** Four short questions land under `skills.handoff-to-client.*`:
140
179
  - **Client platforms.** Open prose → free-form string array, e.g. `iOS (Swift)`, `Android (Kotlin)`, `web SPA (React)`, `partner integrations`. Required, non-empty — this is the document's audience and drives the per-operation migration-notes sections.
@@ -142,7 +181,17 @@ Seven skills are part of the foundation set but aren't always needed. Ask explic
142
181
  - **API spec path.** Open prose. Repo-relative path to a machine-readable spec (OpenAPI file, GraphQL schema, proto dir) plus the command that regenerates it, if one exists (e.g. `docs/openapi.yaml (regenerate: make openapi)`). Cross-check the inventory for spec files the user forgot. Empty is fine — the rendered skill then enumerates changes from route/serializer code alone.
143
182
  - **Output dir.** Default `.vinta-ai-workflows/client-handoffs`. Override if the team wants handoffs committed (e.g. `docs/api-changes/`) — note that the default lives under the gitignored `.vinta-ai-workflows/`, so docs there must be shared manually.
144
183
 
145
- If the user answers "No" to any of the seven, that skill won't ship. If the user answers "Yes" to `add-e2e-test` / `add-env-var` but doesn't have a template, derive-skills drafts one via interview. `systematic-debugging` is always template-rendered — no per-project drafting interview, just the MCP-server inventory above. `add-one-off-script` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/add-one-off-script/](../vinta-derive-skills/resources/foundation-skills/add-one-off-script/) — its body is project-agnostic; the per-project variability lives in the `skills.add-one-off-script.*` config block above and in env vars consumed at runtime. `prepare-worktree` is also copied verbatim from [vinta-derive-skills/resources/foundation-skills/prepare-worktree/](../vinta-derive-skills/resources/foundation-skills/prepare-worktree/) — same pattern: project-agnostic body, per-project defaults under `skills.prepare-worktree.*`. `thermo-nuclear-code-quality-review` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/](../vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/) with no follow-up config — its body is fully project-agnostic. `handoff-to-client` is always template-rendered from [vinta-derive-skills/resources/handoff-to-client-template.md](../vinta-derive-skills/resources/handoff-to-client-template.md) — no per-project drafting interview, just the client-handoff config follow-up above.
184
+ If the user answers "No" to any of the eight, that skill won't ship. If the user answers "Yes" to `add-e2e-test` / `add-env-var` but doesn't have a template, derive-skills drafts one via interview. `systematic-debugging` is always template-rendered — no per-project drafting interview, just the MCP-server inventory above. `add-one-off-script` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/add-one-off-script/](../vinta-derive-skills/resources/foundation-skills/add-one-off-script/) — its body is project-agnostic; the per-project variability lives in the `skills.add-one-off-script.*` config block above and in env vars consumed at runtime. `prepare-worktree` is also copied verbatim from [vinta-derive-skills/resources/foundation-skills/prepare-worktree/](../vinta-derive-skills/resources/foundation-skills/prepare-worktree/) — same pattern: project-agnostic body, per-project defaults under `skills.prepare-worktree.*`. `thermo-nuclear-code-quality-review` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/](../vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/) with no follow-up config — its body is fully project-agnostic. `interview-ui` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/interview-ui/](../vinta-derive-skills/resources/foundation-skills/interview-ui/) as a whole directory (SKILL.md + `resources/examples/`) with no follow-up config; the server and the page are `vinta-ai-maestro interview`'s, not bundled. `handoff-to-client` is always template-rendered from [vinta-derive-skills/resources/handoff-to-client-template.md](../vinta-derive-skills/resources/handoff-to-client-template.md) — no per-project drafting interview, just the client-handoff config follow-up above.
185
+
186
+ ### D.2 Integrations (external tools)
187
+
188
+ Integrations are external tools that ship their own skill. They are not foundation skills: this package bundles none of their content. When one is enabled, the tool's own CLI installs its skill, and this flow only wires that skill in. Ask once per integration:
189
+
190
+ 1. **`pr-review-canvas`** ([PR Review Canvas](https://github.com/vintasoftware/pr-review-canvas), CLI `pr-review`). Should agents generate a review canvas for every PR they open? A canvas is the PR's diff grouped by topic, with attention points for the reviewer. It is shared as a PR comment and read in a local review app (`pr-review serve`). Ask **only when** `project.code_host` is `github` or `gitlab` **and** the `pr_creation` policy (C.4) is `agents-create`. Otherwise set `disabled` without asking: the tool supports only those two hosts, and with `branches-only` no agent opens a PR to attach a canvas to. `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for teams that review agent-written PRs, where a large multi-phase diff is the normal case. Default to `Yes` when [vinta-analyze-codebase](../vinta-analyze-codebase/SKILL.md) already found the tool in use: a `pr-review-canvas` skill classified `integration`, or a `pr-review.config.yml`.
191
+
192
+ Mention the requirements in the question: Node.js 22+, a logged-in `gh` or `glab`, and Claude Code or Codex as the agent. Do **not** install the CLI. Like `open-pr.sh`'s `yq` / `jq` / `gh`, it is a machine-level dependency the user installs. [vinta-install-ai-tools-setup](../vinta-install-ai-tools-setup/SKILL.md) checks for it and prints `npm install -g @vintasoftware/pr-review-canvas` when it is missing.
193
+
194
+ No follow-up config. The tool's own settings (sharing on/off, high-risk paths, prompt overrides) live in its `pr-review.config.yml` at the repo root, and the tool owns that file.
146
195
 
147
196
  ### E. Existing AI artifacts (per-artifact disposition)
148
197
 
@@ -162,7 +211,9 @@ For each artifact, read it (frontmatter + body), then ask the user via `AskUserQ
162
211
  - `Keep in current vendor path, don't touch` — leaves it where it is. AGENTS.md may reference it; downstream skill setup won't manage it.
163
212
  - `Drop` — delete (rare; usually the user wants to migrate).
164
213
 
165
- Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `implement-phase`, `review-phase`, `integrate-phase`, `amend-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `deslop-comments`, `handoff`, `handoff-to-client`, `write-unit-test`) get an extra option: `Replace with Vinta foundation version` — overwrites with the canonical foundation content, preserving the user's name. Useful when the existing version is stale. (`implement-phase` / `review-phase` / `integrate-phase` are the plan-execution sub-skills co-shipped with `implement-plan`; replace them as a unit.)
214
+ **Integration-owned skills** (name matches an integration under D.2 — today `pr-review-canvas`) get no question. Leave them where they are. Their tool owns them through its own marker file (`.pr-review-install`), and its `doctor` / `upgrade` commands manage them. When the integration is `enabled` and the existing copy sits in a real `.claude/skills/` or `.agents/skills/` directory rather than in `ai-tools/skills/`, tell the user once. [vinta-install-ai-tools-setup](../vinta-install-ai-tools-setup/SKILL.md) installs a fresh copy into `ai-tools/skills/`, so the old copy becomes redundant once the vendor directory is a symlink.
215
+
216
+ Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `implement-phase`, `review-phase`, `integrate-phase`, `amend-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `interview-ui`, `thermo-nuclear-review-loop`, `deslop-comments`, `handoff`, `handoff-to-client`, `write-unit-test`) get an extra option: `Replace with Vinta foundation version` — overwrites with the canonical foundation content, preserving the user's name. Useful when the existing version is stale. (`implement-phase` / `review-phase` / `integrate-phase` are the plan-execution sub-skills co-shipped with `implement-plan`; replace them as a unit.)
166
217
 
167
218
  - **Sub-agents** (each under any vendor `agents/` dir):
168
219
  - `Migrate to ai-tools/agents/<name>.yaml` — converts vendor-specific format → canonical YAML; `setup-ai-tools.mjs` re-emits per-vendor copies.
@@ -204,9 +255,9 @@ Rules:
204
255
  - When in doubt, reference DESIGN.md — do not invent new values
205
256
  ```
206
257
 
207
- Globs may need tuning for the project's actual UI file extensions (Svelte-only projects, RN `.tsx`, etc.). Ask the user once if the analysis surfaced a UI framework not covered by the default glob list; otherwise ship the defaults.
258
+ Globs may need tuning for the project's actual UI file extensions (Svelte-only projects, RN `.tsx`, etc.). When the analysis surfaced a UI framework not covered by the default glob list, ask once via `AskUserQuestion`: `Add <framework> globs (Recommended)` (name the globs you'd add), `Ship the defaults`. Otherwise ship the defaults.
208
259
 
209
- After Step 0: read back the captured decisions (including every per-artifact disposition), confirm via `AskUserQuestion` (`Looks good`, `Some corrections (I'll list)`, `Stop, rethink`).
260
+ After Step 0: read back the captured decisions (including every per-artifact disposition), confirm via `AskUserQuestion` (`Looks good (Recommended)`, `Some corrections (I'll list)`, `Stop, rethink`).
210
261
 
211
262
  The dispositions become inputs to:
212
263
 
@@ -220,7 +271,7 @@ Captured interview state lands in **one** YAML file at the repo root: `.vinta-ai
220
271
 
221
272
  This file is the **only** source of truth for project-wide settings. Every downstream sub-skill (4 → 6 below) reads from it instead of receiving values via in-conversation state. Every meta-skill ([vinta-sync-ai-tools](../vinta-sync-ai-tools/SKILL.md), [vinta-update-project-skills](../vinta-update-project-skills/SKILL.md)) reads + rewrites it.
222
273
 
223
- Write the file now (before any sub-skill runs). Populate from the interview groups **Scope**, **Stack detection**, **Project conventions**, **Optional foundation skills**, and **Existing AI artifacts**:
274
+ Write the file now (before any sub-skill runs). Populate from the interview groups **Scope**, **Stack detection**, **Project conventions**, **Optional foundation skills**, **Integrations**, and **Existing AI artifacts**:
224
275
 
225
276
  ```yaml
226
277
  # yaml-language-server: $schema=./node_modules/vinta-ai-workflows/schemas/vinta-ai-workflows-config.v1.schema.json
@@ -243,9 +294,13 @@ commands:
243
294
  format: <derived>
244
295
  build: <derived>
245
296
  test_unit: <Project conventions → Test framework(s)>
246
- test_unit_scoped: <derived from monorepo shape>
297
+ test_unit_scoped: <C.11 scoped-gates template with {changed_files} when confirmed; else derived from monorepo shape>
298
+ lint_scoped: <C.11 scoped lint template; omit unless confirmed>
247
299
  test_unit_new_pattern: <derived>
248
300
  e2e: <only when foundation_skills.add-e2e-test = enabled>
301
+ # Only when the prepare-worktree answer was "own script/command" or "generate".
302
+ worktree_prepare: <own-command follow-up → prepare command | generate follow-up → <script dir>/prepare.sh>
303
+ worktree_teardown: <own-command follow-up → teardown command, omitted on "No teardown command" | generate follow-up → <script dir>/teardown.sh>
249
304
 
250
305
  policies:
251
306
  pr_creation: <Project conventions → PR creation policy>
@@ -279,9 +334,11 @@ foundation_skills:
279
334
  add-env-var: <Optional foundation skills → add-env-var answer → enabled | disabled>
280
335
  systematic-debugging: <Optional foundation skills → systematic-debugging answer → enabled | disabled>
281
336
  add-one-off-script: <Optional foundation skills → add-one-off-script answer → enabled | disabled>
282
- prepare-worktree: <Optional foundation skills → prepare-worktree answer → enabled | disabled>
337
+ prepare-worktree: <Optional foundation skills → prepare-worktree answer → enabled | disabled; disabled for "own script/command" and "generate">
283
338
  thermo-nuclear-code-quality-review: <Optional foundation skills → thermo-nuclear-code-quality-review answer → enabled | disabled>
284
- deslop-comments: enabled # always ships — review-phase Layer 2 comment-hygiene + fix loop and the integrate-phase PR-context prose pass depend on it
339
+ interview-ui: <Optional foundation skills → interview-ui answer → enabled | disabled>
340
+ thermo-nuclear-review-loop: enabled # always ships — review-phase runs it over every phase, and so does the review chore of every maestro workflow plan-feature writes
341
+ deslop-comments: enabled # always ships — the integrate-phase / amend-plan PR-context prose pass and maestro's deslop chore depend on it
285
342
  handoff: enabled # always ships — project-agnostic session-continuation handoff docs
286
343
  handoff-to-client: <Optional foundation skills → handoff-to-client answer → enabled | disabled; only asked for API-only repos>
287
344
  write-unit-test: <enabled when a unit-test framework was detected (Project conventions → Test framework(s)); disabled when none found — default-on, not an opt-in>
@@ -291,13 +348,15 @@ foundation_agents:
291
348
  reviewer: enabled
292
349
  fixer: enabled
293
350
 
351
+ integrations:
352
+ pr-review-canvas: <Integrations → pr-review-canvas answer → enabled | disabled; disabled without asking when code_host ∉ {github, gitlab} or pr_creation = branches-only>
353
+
294
354
  # Only emit the roles the user chose in the "Agent model tiers" question (C.10).
295
355
  # Omit the whole block on "Leave unset"; omit any individual role left unset.
296
356
  # Each value is a tier (1–4) into ai-tools/skills/plan-feature/resources/ai-models.yaml.
297
357
  agent_models:
298
- reviewer: <C.10 → reviewer tier, default 3>
299
358
  fixer: <C.10 → fixer tier, default 2>
300
- worktree_prep: <C.10 → worktree_prep tier, default 1; omit when prepare-worktree disabled>
359
+ worktree_prep: <C.10 → worktree_prep tier, default 1; omit when prepare-worktree disabled (including the own-command case — a command runs inline)>
301
360
  integrate: <C.10 → integrate tier, default 1>
302
361
 
303
362
  stacks: <Stack detection → matched stacks>
@@ -309,11 +368,52 @@ run_options:
309
368
  generate_inline_comments: false
310
369
  full_test_suite: false # default: each phase's outer gate runs scoped tests only; set true to run the full suite every phase
311
370
  use_worktree: <Optional foundation skills → prepare-worktree follow-up → default for Step 0 question (c); false unless team opted in>
312
- parallel_phases: <Optional foundation skills → parallel-execution follow-up → default for Step 0 question (e); true when prepare-worktree is enabled and the team didn't opt out, false otherwise>
371
+ parallel_phases: <Optional foundation skills → parallel-execution follow-up → default for Step 0 question (e); true when worktrees are available (skill enabled or own command) and the team didn't opt out, false otherwise>
313
372
  max_parallel_lanes: <parallel-execution follow-up → lane cap, default 3; omit when parallel_phases is false>
314
373
  amend-plan:
315
374
  blast_radius_signal_threshold: 2
316
375
 
376
+ # Only emit on C.11 → "Set project defaults". Omit the whole block on "Skip".
377
+ # Defaults UNDER every plan's .workflow.json: the plan wins wherever it says
378
+ # something. Emit only the keys the user answered; nothing here repeats a
379
+ # value maestro would derive from `commands` on its own.
380
+ maestro:
381
+ defaults:
382
+ gates: <C.11 → gates every phase runs, e.g. [typecheck, lint, test]>
383
+ gate_scope: <C.11 → omit for "scoped" (the default); `full` on "No — full command every time">
384
+ verify_gates: <C.11 → omit (the default, `full`); `scoped` on "Only on merged trees" or "Only on merged waves">
385
+ base_gates: <C.11 → omit (the default, `full`); `off` on "Only on merged waves">
386
+ gates:
387
+ test:
388
+ cmd: <C.11 → maestro-only test command; omit to use commands.test_unit>
389
+ fresh_cmd: <C.11 "Fresh database in the integration worktree" → the same command from a fresh test database, e.g. pytest --create-db -n auto; omit when the suite keeps no database between runs>
390
+ fresh_when: <C.11 "Fresh database in the integration worktree" → globs of the migration files, e.g. ['apps/*/migrations/*.py']; only alongside fresh_cmd>
391
+ tuning:
392
+ allowed_flags: <C.11 → ['--create-db'] alongside fresh_cmd, so the coordinator may add it; omit otherwise>
393
+ cold_cmd: <C.11 "Cold lanes" → what runs while a lane has no scope cache, e.g. the parallel full suite; omit when the scoped template needs no cache>
394
+ scope_cache: <C.11 "Cold lanes" → the cache files the scoped template narrows by, e.g. [apps/api/.testmondata]; omit otherwise>
395
+ requires: [test-suite] # only with a test-suite pool
396
+ resources:
397
+ test-suite: # only on a pool limit
398
+ capacity: <1 | 2>
399
+ kind: semaphore
400
+ scope: host
401
+ match: <C.11 → runner command patterns, e.g. ['pytest*', 'uv run pytest*']>
402
+ codegen: # C.11 → generators and file-modifying hooks; omit when none
403
+ <step-id>:
404
+ cmd: <the generator command, e.g. uv run python manage.py spectacular --file schema.yml>
405
+ inputs: <globs it reads, e.g. ['**/serializers.py', '**/views.py']; omit to run every time>
406
+ outputs: <globs it writes, e.g. [schema.yml]>
407
+ after: <steps that run first, e.g. [schema]; omit when none>
408
+ format: <true for a formatter whose cmd takes {changed_files}; omit otherwise>
409
+ append_only: <C.11 → registries phases only append to, e.g. [app/containers.py, app/urls.py]; omit when none>
410
+ ci_only: # C.11 "CI checks" → each CI command deliberately left to CI; omit when every one has a gate
411
+ - command: <the CI command as CI runs it>
412
+ reason: <why no gate runs it: credentials, a deploy, a hosted service>
413
+ project:
414
+ env_files: <C.11 → gitignored files every lane needs its own copy of, e.g. [.env, .env.docker, app/settings/local.py]; omit when none>
415
+ lane_seed: <C.11 "Cold lanes" → the same scope-cache paths, so a new lane gets a copy; omit otherwise>
416
+
317
417
  skills:
318
418
  # Only emit this block when foundation_skills.systematic-debugging = enabled.
319
419
  systematic-debugging:
@@ -337,10 +437,11 @@ skills:
337
437
  db_isolation: <C.9 → transaction-rollback | truncate | recreate | framework-default>
338
438
  additional_conventions: <C.9 → free-form array of extra conventions inferred/supplied; [] when none>
339
439
 
340
- # Only emit this block when foundation_skills.prepare-worktree = enabled.
440
+ # Only emit this block when foundation_skills.prepare-worktree = enabled, or when
441
+ # commands.worktree_prepare is set — then emit worktree_root + summary_dir only.
341
442
  prepare-worktree:
342
443
  worktree_root: <prepare-worktree follow-up — `.claude/worktrees` | `../<repo>-wt-`>
343
- deps_strategy: <prepare-worktree follow-up — symlink | copy | reinstall>
444
+ deps_strategy: <prepare-worktree follow-up — copy | reinstall>
344
445
  compose_network: per-worktree
345
446
  test_db_strategy: <prepare-worktree follow-up — fork-on-schema-change | always-fork | share>
346
447
  summary_dir: .vinta-ai-workflows/worktrees
@@ -364,6 +465,14 @@ Validate the file against the schema before writing — if any required field is
364
465
 
365
466
  Existing-project case: `.vinta-ai-workflows.yaml` already present → that's a re-bootstrap. Show the existing config, ask via `AskUserQuestion`: `Keep existing config and refresh sub-skills only`, `Re-interview and overwrite`, `Stop`. The `Refresh sub-skills only` path is the common case for older projects whose config was written by an earlier `vinta-bootstrap-ai-tools`.
366
467
 
468
+ ## Optional step — Generate the worktree command
469
+
470
+ Runs after [vinta-derive-skills](../vinta-derive-skills/SKILL.md) (step 4) and before the install step, **only** when the `prepare-worktree` answer (D.5) was `Yes — generate a provisioning script for this project`. Skip it silently otherwise.
471
+
472
+ It writes `<script dir>/lib.sh`, `prepare.sh` and `teardown.sh` into the project, plus `gen-compose-worktree-override.sh` when the project uses docker compose. The source is the bundled templates in [resources/worktree-command/](resources/worktree-command/). The templates carry the `commands.worktree_prepare` contract, already tested: env resolution, `--dry-run`, sanity checks, `git worktree add`, rollback of a half-made worktree, compose isolation, the full summary YAML, and a teardown that refuses dirty worktrees and never runs `down -v`. This step fills only the **PROJECT STEPS** regions with this project's dependency, env, database and service handling, decided from the inventory, plus a few structured questions.
473
+
474
+ Follow [resources/worktree-command/README.md](resources/worktree-command/README.md): read before write in the chosen directory, render the placeholders, fill the regions, then verify (`bash -n`, a `--dry-run`, and an optional real smoke test the user opts into). It returns a status report like every sub-skill. On failure, the README's fix question can fall back to the `prepare-worktree` skill, which also updates `.vinta-ai-workflows.yaml`.
475
+
367
476
  ## Stack templates — detection only, content is user-supplied
368
477
 
369
478
  [`resources/stacks/<stack>/notes.md`](resources/stacks/) defines **detection signals** + lists the **categories of skills + sub-agents that typically belong** to each stack. **It does NOT ship ready-made skill / agent content.** The team's specific skill library lives wherever the team keeps it (a shared repo, a personal `~/skills/` dir, a published package, a private gist) — the bootstrap orchestrator asks the user to point at it when a stack matches.
@@ -411,7 +520,8 @@ ai-tools/
411
520
  │ ├── plan-feature/SKILL.md ← always (copied verbatim from derive-skills resources)
412
521
  │ ├── create-spec/SKILL.md ← always (copied verbatim)
413
522
  │ ├── create-qa-use-cases/SKILL.md ← always (copied verbatim)
414
- │ ├── deslop-comments/SKILL.md ← always (copied verbatim; review-phase Layer 2 comment-hygiene + fix loop and the integrate-phase PR-context prose pass depend on it)
523
+ │ ├── thermo-nuclear-review-loop/SKILL.md ← always (copied verbatim; the review chore of every maestro workflow plan-feature writes runs it)
524
+ │ ├── deslop-comments/SKILL.md ← always (copied verbatim; the integrate-phase / amend-plan PR-context prose pass and maestro's deslop chore depend on it)
415
525
  │ ├── handoff/SKILL.md ← always (copied verbatim; session-continuation handoff docs under .vinta-ai-workflows/handoffs/)
416
526
  │ ├── implement-plan/SKILL.md ← always (conductor; generated from template, project-specific)
417
527
  │ ├── implement-phase/SKILL.md ← always (plan-execution unit; co-shipped with implement-plan)
@@ -433,7 +543,12 @@ ai-tools/
433
543
  │ │ ├── one_off_script_base.py
434
544
  │ │ └── one_off_script_base.ts
435
545
  │ ├── prepare-worktree/SKILL.md ← optional — only if user opts in (verbatim copy; project-agnostic body, defaults under skills.prepare-worktree.*)
436
- │ ├── thermo-nuclear-code-quality-review/SKILL.md ← optional — only if user opts in (verbatim copy; deep structural-maintainability audit, escalation target for review-phase Layer 3)
546
+ │ ├── thermo-nuclear-code-quality-review/SKILL.md ← optional — only if user opts in (verbatim copy; deliberate deep structural-maintainability audit, run on request)
547
+ │ ├── interview-ui/ ← optional — only if user opts in (verbatim copy of the whole dir; browser form for decision-heavy interviews, used by create-spec Step 0; the page is served by `vinta-ai-maestro interview`)
548
+ │ │ ├── SKILL.md
549
+ │ │ └── resources/
550
+ │ │ └── examples/ ← sample round + explainer doc
551
+ │ ├── pr-review-canvas/ ← integration — only when integrations.pr-review-canvas = enabled and `pr-review` is installed. Written by `pr-review install-skill`, never by this flow; owned through its `.pr-review-install` marker, refreshed by `pr-review upgrade`
437
552
  │ ├── run-one-off-script-django/ ← optional sister skill — only when stack matches + user supplies template (authors Jupyter notebook / mgmt command runner + JupyterRuntime / DjangoMgmtRuntime adapter in the per-script folder)
438
553
  │ ├── run-one-off-script-medplum/ ← optional sister skill — only when stack matches + user supplies template (authors Medplum bot + MedplumBotRuntime adapter in the per-script folder)
439
554
  │ └── <stack-specific skills>/SKILL.md ← only if user supplied templates
@@ -446,6 +561,12 @@ ai-tools/
446
561
  └── scripts/
447
562
  └── setup-ai-tools.mjs ← copied from install-ai-tools-setup resources
448
563
 
564
+ <script dir>/ ← only when D.5 = generate (default scripts/worktree/); the project owns these
565
+ ├── prepare.sh ← commands.worktree_prepare
566
+ ├── teardown.sh ← commands.worktree_teardown
567
+ ├── lib.sh ← shared plumbing, sourced by both
568
+ └── gen-compose-worktree-override.sh ← only when the project uses docker compose
569
+
449
570
  DESIGN.md ← preserved at repo root if pre-existing (never overwritten)
450
571
  .cursor/rules/design.mdc ← only when DESIGN.md exists, user opted Wire it in,
451
572
  and `cursor` ∈ vendors (Cursor Project Rules, Option A
@@ -462,9 +583,9 @@ Plus the symlinks + per-vendor generated files, set up by the install step. The
462
583
 
463
584
  Foundation skills break into three buckets — see [vinta-derive-skills](../vinta-derive-skills/SKILL.md) for the full mechanics:
464
585
 
465
- - **Always copy verbatim**: `plan-feature`, `create-spec`, `create-qa-use-cases`, `deslop-comments`, `handoff`. Bundled with the bootstrap skill set; project-agnostic enough to ship as-is (with light path scrubs). `deslop-comments` always ships because `review-phase`'s Layer 2 comment-hygiene check + fix loop dispatch it, and `integrate-phase` / `amend-plan` run it over the PR-context file. `handoff` always ships because its session-continuation body is fully project-agnostic.
586
+ - **Always copy verbatim**: `plan-feature`, `create-spec`, `create-qa-use-cases`, `thermo-nuclear-review-loop`, `deslop-comments`, `handoff`. Bundled with the bootstrap skill set; project-agnostic enough to ship as-is (with light path scrubs). `deslop-comments` always ships because `integrate-phase` / `amend-plan` run it over the PR-context file and maestro's `deslop` chore runs it on every phase. `thermo-nuclear-review-loop` always ships because it is the per-phase review on both execution paths: `review-phase` runs it with the conductor as host, and the `review` chore of every `vinta-ai-maestro` workflow `plan-feature` writes runs it on a phase once its gates are green. `handoff` always ships because its session-continuation body is fully project-agnostic.
466
587
  - **Always generate**: the plan-execution unit — `implement-plan` (conductor) + its co-shipped sub-skills `implement-phase` / `review-phase` / `integrate-phase`, plus `amend-plan` (conductor). Bodies have too much project-specific content (test commands, branch convention, PR + co-author policy, agent dispatch) — generated from parameterized templates + shared partials using interview answers + inventory. The sub-skills are not independently opt-in; they always ship with the conductors. `write-unit-test` is also template-rendered but **conditionally generated** — it ships whenever a unit-test framework was detected (not an opt-in question, not ask-first): the rendered body bakes in the project's test command + captured `skills.write-unit-test.*` conventions, and the verbatim packs land in its `resources/packs/` — one runner pack for the detected test framework plus a stack pack per matched stack (Django / FastAPI / Flask / Medplum / React / Next.js / TanStack Start / React Router / Prisma / pure-package), so framework-specific advice only ships when that framework is present. A few stack packs also apply a one-time project-setup step at derive time (e.g. Medplum wires the two FHIR-indexing Vitest setup files — `test.globalSetup.ts` + `test.setup.ts` — into the Vitest config so `MockClient` search filtering works) — a project mutation done once, not per test.
467
- - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `handoff-to-client`. Skipped by default; orchestrator asks via `AskUserQuestion` whether the project has the relevant flow at all. `add-e2e-test` / `add-env-var`: if yes + user has a template → copy + adapt; if yes + no template → draft from scratch via interview; if no → don't ship. `systematic-debugging`: if yes → render the bundled template plus the per-tool MCP catalogue blocks for the observability tools selected in its follow-up; if no → don't ship. `add-one-off-script`: if yes → copy the bundled SKILL.md verbatim plus the language-specific `BaseOneOffScript` template (`one_off_script_base.py` / `one_off_script_base.ts`) chosen via its follow-up; if no → don't ship. `prepare-worktree`: if yes → copy the bundled SKILL.md verbatim, populate `skills.prepare-worktree.*` defaults from its follow-ups, (when the user opted in via the worktree-default follow-up) flip `run_options.implement-plan.use_worktree` to `true` so `implement-plan`'s Step 0 question (c) defaults to yes, and emit `run_options.implement-plan.parallel_phases` + `max_parallel_lanes` from the parallel-execution follow-up; if no → don't ship, and emit `parallel_phases: false` (parallel execution cannot run without worktrees). `thermo-nuclear-code-quality-review`: if yes → copy the bundled SKILL.md verbatim (no follow-up config); if no → don't ship. `handoff-to-client`: asked only for API-only repos; if yes → render the bundled template using `skills.handoff-to-client.*` (client platforms, API style, spec path, output dir) from its follow-ups; if no → don't ship.
588
+ - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `interview-ui`, `handoff-to-client`. Skipped by default; orchestrator asks via `AskUserQuestion` whether the project has the relevant flow at all. `add-e2e-test` / `add-env-var`: if yes + user has a template → copy + adapt; if yes + no template → draft from scratch via interview; if no → don't ship. `systematic-debugging`: if yes → render the bundled template plus the per-tool MCP catalogue blocks for the observability tools selected in its follow-up; if no → don't ship. `add-one-off-script`: if yes → copy the bundled SKILL.md verbatim plus the language-specific `BaseOneOffScript` template (`one_off_script_base.py` / `one_off_script_base.ts`) chosen via its follow-up; if no → don't ship. `prepare-worktree`: if yes → copy the bundled SKILL.md verbatim, populate `skills.prepare-worktree.*` defaults from its follow-ups, (when the user opted in via the worktree-default follow-up) flip `run_options.implement-plan.use_worktree` to `true` so `implement-plan`'s Step 0 question (c) defaults to yes, and emit `run_options.implement-plan.parallel_phases` + `max_parallel_lanes` from the parallel-execution follow-up; if own script/command → don't ship, and emit `commands.worktree_prepare` / `commands.worktree_teardown`; if generate → don't ship, emit the same keys pointing at `<script dir>/prepare.sh` / `teardown.sh`, and run the [Generate the worktree command](#optional-step--generate-the-worktree-command) step after derive-skills; if no → don't ship, and emit `parallel_phases: false` (parallel execution cannot run without worktrees). `thermo-nuclear-code-quality-review`: if yes → copy the bundled SKILL.md verbatim (no follow-up config); if no → don't ship. `handoff-to-client`: asked only for API-only repos; if yes → render the bundled template using `skills.handoff-to-client.*` (client platforms, API style, spec path, output dir) from its follow-ups; if no → don't ship.
468
589
 
469
590
  Stack-specific skills + agents land in the target only when the user provides templates for them. If they don't have templates yet, the orchestrator records the detected stacks + skill categories as a TODO list the user can address later via [vinta-derive-skills](../vinta-derive-skills/SKILL.md) / [vinta-derive-subagents](../vinta-derive-subagents/SKILL.md) standalone runs.
470
591
 
@@ -472,7 +593,8 @@ Stack-specific skills + agents land in the target only when the user provides te
472
593
 
473
594
  - **Read before write.** Always check what's in the target repo first. Don't clobber existing AGENTS.md / skills / agents without an explicit confirmation in Step 0.
474
595
  - **Stack templates are starting points, not finals.** Each copied skill / agent must be reviewed against the actual project (interview the user about specifics) and edited where the template's assumptions don't fit.
475
- - **Don't fabricate conventions.** If `vinta-analyze-codebase` doesn't find a thing, ask the user. Don't write "Use bulk_create instead of loop+save" into AGENTS.md just because Django was detected — confirm the team actually follows it.
596
+ - **Every stop for input is a structured question.** See [asking-the-human](../vinta-write-agents-md/resources/asking-the-human.md). A prose question at the end of a long report is the failure mode — the user has to hunt for it and type the answer.
597
+ - **Don't fabricate conventions.** If `vinta-analyze-codebase` doesn't find a thing, ask the user (`AskUserQuestion`, offering what you did find as candidates). Don't write "Use bulk_create instead of loop+save" into AGENTS.md just because Django was detected — confirm the team actually follows it.
476
598
  - **Foundation skills are universal.** Every project gets `add-env-var`, `add-e2e-test`, `plan-feature`, `implement-plan`, `create-spec`, `create-qa-use-cases`. The bodies need light per-project edits (test commands, branch conventions) — `vinta-derive-skills` handles that.
477
599
  - **Foundation agents are universal.** `implementer` / `reviewer` / `fixer` always. Stack specialists (`deploy-author` for Medplum, `migration-author` for Django) only when the stack matches.
478
600
  - **Don't run install-ai-tools-setup until AGENTS.md + agents YAMLs + skills exist.** The setup script reads these files; running it on an empty `ai-tools/` produces nothing useful.
@@ -496,6 +618,7 @@ After all sub-skills finish:
496
618
  3. Each selected vendor's directory has the expected files: `.claude/agents/*.md`, `.cursor/agents/*.md`, `.github/agents/*.agent.md`, `.codex/agents/*.toml`.
497
619
  4. Spot-check one skill, one agent: open SKILL.md / `<agent>.yaml` and confirm content describes THIS project (not a copy-pasted template with `<placeholder>` strings).
498
620
  5. If the project uses Claude Code: in a new session, ask Claude to invoke one of the project-specific skills. Confirm it loads + the body looks right.
499
- 6. If [vinta-migrate-plans-specs](../vinta-migrate-plans-specs/SKILL.md) ran: `ls ai-plans/` lists the migrated docs in canonical `YYYY-MM-DD-{FEATURE_NAME}_{PLAN|SPEC}.md` form. `git status` shows the renames staged (or already committed). No plan/spec markdown left orphaned in `docs/`, `specs/`, or repo root unless the user explicitly skipped them.
621
+ 6. If the worktree command was generated: `bash -n` passes on `<script dir>/*.sh`, `<script dir>/prepare.sh vinta-smoke --dry-run` prints a plausible plan, and `.vinta-ai-workflows.yaml` points `commands.worktree_prepare` / `commands.worktree_teardown` at the generated files.
622
+ 7. If [vinta-migrate-plans-specs](../vinta-migrate-plans-specs/SKILL.md) ran: `ls ai-plans/` lists the migrated docs in canonical `YYYY-MM-DD-{FEATURE_NAME}_{PLAN|SPEC}.md` form. `git status` shows the renames staged (or already committed). No plan/spec markdown left orphaned in `docs/`, `specs/`, or repo root unless the user explicitly skipped them.
500
623
 
501
624
  End the run with a one-paragraph summary: what was created, what was skipped (per `--only`), what manual edits the user should review.
@@ -3,7 +3,7 @@
3
3
  Each subdirectory here defines a **stack** — a set of detection signals + a description of what kinds of skills + sub-agents typically belong to that stack. The bootstrap flow uses these to:
4
4
 
5
5
  1. Detect (via [vinta-analyze-codebase](../../../vinta-analyze-codebase/SKILL.md)) which stacks the target project matches.
6
- 2. Ask the user "I detected stack X; do you have skill / sub-agent templates for it? Point me at them" — bootstrap doesn't ship pre-baked content.
6
+ 2. Ask the user via `AskUserQuestion` "I detected stack X; do you have skill / sub-agent templates for it?" (`Yes — I'll give the path` with the path typed into the free-text field, `No — record as gap`) — bootstrap doesn't ship pre-baked content.
7
7
  3. Copy + adapt the user-provided templates into the target's `ai-tools/skills/` and `ai-tools/agents/`.
8
8
 
9
9
  This keeps the bootstrap skill **infrastructure only**. Specific skill content (e.g. "how to add a Medplum bot") lives wherever the user keeps their personal / team skill library, not here.
@@ -25,7 +25,7 @@ If no multi-tenancy signals → single-tenant Django; the team's templates may s
25
25
  - **Create-postgres-function** (if the project ships custom `CREATE FUNCTION` / aggregates) — versioned function migrations.
26
26
  - **Create-data-import / create-data-export** — async import/export commands feeding integrations.
27
27
  - **GraphQL-public-query** (if the project uses Strawberry or Graphene) — public-API mutation/query patterns.
28
- - **REST-endpoint** (if the project uses Django REST Framework or django-ninja) - REST API endpoint patterns.
28
+ - **REST-endpoint** (if the project uses Django REST Framework or django-ninja) - REST API endpoint patterns. With drf-spectacular, ask whether the team's endpoint template requires every new `choices` field the API exposes to add its `ENUM_NAME_OVERRIDES` entry in the same change. Parallel phases that each add a `status` field with different choices otherwise collide on the generated enum name (`StatusEnum`), and the collision only shows at integration, in the schema test.
29
29
  - **Run-one-off-script-django** — sister to the universal `add-one-off-script` foundation skill. Authors the *runner* artefact in the per-script folder (Jupyter notebook in `notebooks/` is the typical Vinta default; a thin `BaseCommand` under `<app>/management/commands/<name>.py` is the alternative for headless / cron / CI invocation) and ships the matching `Runtime` adapter at `<scripts_dir>/_runtime_django.py` (`JupyterRuntime` and/or `DjangoMgmtRuntime`). Adapter responsibilities: hook `BaseCommand.handle()` into `BaseOneOffScript.execute()`; respect `python manage.py <name> --apply` / `--resume` / `--status` / `--restore` flags; load Django settings + DB connection before the engine starts iterating; for the Jupyter variant, swap signal handlers for kernel-interrupt and skip the PID-file lease (notebook = single instance by construction). README in the per-script folder spells out `python manage.py shell < script.py`, `jupyter lab notebooks/<name>/runner.ipynb`, and `python manage.py <name> --apply` as the three legitimate entry points.
30
30
 
31
31
  ## Agent categories typically needed
@@ -45,6 +45,41 @@ If no multi-tenancy signals → single-tenant Django; the team's templates may s
45
45
  - One-off script invocation surface (Jupyter notebook in `notebooks/<name>/`, Django management command, both) — drives the `run-one-off-script-django` skill's runner artefact + which `Runtime` adapter ships
46
46
  - Notebook directory path (`notebooks/`, `<project>/notebooks/`) — only when Jupyter is selected as a runner surface
47
47
 
48
+ ## Gates that should mirror CI
49
+
50
+ Ask which of these CI runs, and suggest each one it runs as a gate, so a phase cannot pass every gate and still fail CI. Declare each once, project-wide, as a custom gate under `maestro.gates.<id>` in `.vinta-ai-workflows.yaml` (e.g. `django-check: { cmd: ... }`, `api-client-fresh: { cmd: ... }`) and add its id to `maestro.defaults.gates` — every plan then runs it as its own gate, with its own verdict. Don't chain these onto the `typecheck` / `test` lines in `commands`: one verdict for several unrelated checks tells a fixer nothing about which one failed.
51
+
52
+ - **Deploy check at warning level** — `python manage.py check --deploy --fail-level WARNING` (with the CI settings module). Catches what `check` alone passes: URL patterns Django warns about (e.g. a `path()` route that looks like a regex), security settings, model warnings. One observed run added regex-style routes that passed every gate and failed this check in CI.
53
+ - **Migrations complete** — `python manage.py makemigrations --check --dry-run`.
54
+ - **Generated client / schema up to date** — when the project generates an OpenAPI/GraphQL schema or a typed frontend client from the Django API (drf-spectacular, Strawberry, django-ninja + an openapi codegen), a gate that regenerates it and fails on a diff (`<generate command> && git diff --exit-code <schema/client paths>`).
55
+
56
+ Placeholders to ask about: the settings module CI runs checks with, and the schema/client generate command and its output paths.
57
+
58
+ ## Test commands in lanes
59
+
60
+ Ask how the suite runs, because maestro runs it in many worktrees at once, one merged tree after another in its integration worktree:
61
+
62
+ - **Database reuse.** With `pytest --reuse-db` (or `--keepdb`), a database a test run left behind applies forward migrations and never removes ones the current tree lacks. The integration worktree switches branches between merges, so its test gate needs a fresh-database form (`--create-db`, `make test_reset test`) — bootstrap emits it as `maestro.gates.test.fresh_cmd`.
63
+ - **Scoped runs with testmon.** `pytest --testmon` without a `.testmondata` runs every test, serially. A `test_changed` target should fall back to the full parallel run when the file is missing, and bootstrap declares the cache as `scope_cache` / `lane_seed`. `--testmon` with `-n` trades correctness for speed: testmon cannot attribute what an xdist worker ran.
64
+ - **One run at a time per lane.** A DB-backed suite shares its lane's test databases with any other run in that lane. Ask about the test-suite pool, and tell agents to check `docker ps` for a leftover `<lane>-api-run-*` container before starting another run.
65
+
66
+ Placeholders to ask about: the fresh-database form of the test command, the testmon cache path, the full parallel command.
67
+
68
+ ## The dev container and the worktree
69
+
70
+ When `docker-compose.yml` bind-mounts the repository into the dev container, anything the container writes into the mount belongs to the container's user — root by default — and a lane whose `apps/api/.venv` is root-owned cannot be cleaned or recycled from the host (one observed phase failed six times on such a lane). Ask whether the compose file already keeps these out of the mount, and suggest, as changes the team makes to its own compose file:
71
+
72
+ - the virtual environment outside the mounted tree: `UV_PROJECT_ENVIRONMENT=/opt/venv` (uv), or a named volume over the `.venv` path;
73
+ - the dev service running as the host user: `user: "${UID}:${GID}"`, with `UID`/`GID` exported in the project's env file.
74
+
75
+ ## Registries every phase appends to
76
+
77
+ URL route lists (`routes.py`), DI containers (`containers.py`), task packages (`tasks/__init__.py`) and drf-spectacular's `ENUM_NAME_OVERRIDES` are edited by nearly every phase of a plan, and they cause most of its merge work — including auto-merges git accepts that leave two list openers or a duplicated import. Ask which the project has, and suggest either a registry per feature module (`routes/<feature>.py` gathered by a loader, tasks found by autodiscovery), or listing them under `maestro.append_only` so maestro merges them with git's union driver. Either way the merged tree is gated.
78
+
79
+ ## Test determinism
80
+
81
+ Tests that touch dates freeze the clock and set the timezone explicitly (`freezegun` / `time-machine` + `override_settings(TIME_ZONE=...)`), and schema generation reads no host state — timezone choices come from a pinned `tzdata`, not the OS tz database. Ask whether the project already has `freezegun`/`time-machine` and `tzdata` in its dev/lock dependencies; the `write-unit-test` Django pack assumes them.
82
+
48
83
  ## When this stack doesn't apply cleanly
49
84
 
50
85
  - Django REST framework but no DB (read-only API on top of an external service) → most of these skills don't apply.