vinta-ai-workflows 0.1.7 → 0.2.0-alpha2

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 CHANGED
@@ -5,6 +5,195 @@ All notable changes to `vinta-ai-workflows` are documented in this file.
5
5
  The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/);
6
6
  the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.2.0] — YYYY-MM-DD
9
+
10
+ <!-- pre-release: 0.2.0-alpha2 on 2026-06-13 -->
11
+
12
+ ### Changed
13
+
14
+ - **Fixed bug on setup-ai-tools.mjs**: Sub agents were being generated
15
+ with an invalid description and were not being loaded by claude-code and
16
+ possibly other AI tools.
17
+
18
+ - **`implement-plan` template — stray main-checkout-write guard (only
19
+ when `run_options.use_worktree = true`).** A subagent told to work
20
+ inside the worktree can resolve an absolute path back to the **main
21
+ checkout** and silently edit files there; because worktrees have
22
+ independent working trees those edits never reach the phase commit —
23
+ they sit as uncommitted thrash in the main checkout and read as a
24
+ silent implementer/fixer failure. Layer 1 mechanical checks gain a new
25
+ item: after **every** implementer **and** fixer subagent returns, run
26
+ `git -C <main-checkout-path> status --short | grep -vE '^\?\?'`
27
+ (tracked modifications only); any output is a BLOCKER — recover intent
28
+ via `git -C <main-checkout-path> diff`, re-dispatch the agent with an
29
+ explicit worktree-path instruction if the change belongs there, then
30
+ `git -C <main-checkout-path> restore` so the main checkout returns
31
+ clean between phases. `<main-checkout-path>` is the repo root the skill
32
+ was invoked from, never `run_options.worktree_path`. Skipped entirely
33
+ when `use_worktree = false`. Mirrored in the per-phase Quick checklist
34
+ Layer 1 line and a new **Important rules** bullet.
35
+
36
+ <!-- pre-release: 0.2.0-alpha1 on 2026-06-12 -->
37
+
38
+ ### Added
39
+
40
+ - **Third-party dependency license policy captured at bootstrap, surfaced
41
+ to AI agents at implementation time.** `vinta-bootstrap-ai-tools` Step 0
42
+ group **C. Project conventions** gains question 7 — enforcement
43
+ (`block` (default) / `warn` / `off`), a confirm-and-edit prompt for the
44
+ forbidden SPDX list (seed: `GPL-2.0-only`, `GPL-3.0-only`,
45
+ `AGPL-3.0-only`, `SSPL-1.0`), per-package overrides, and free-form
46
+ notes. Captured in a new `policies.dependency_licenses` block of
47
+ `vinta-ai-workflows-config.v1.schema.json`. Consumers:
48
+ - `vinta-write-agents-md` renders a new **Dependency licenses** section
49
+ in `ai-tools/AGENTS.md` (enforcement mode + forbidden list + approved
50
+ overrides table + notes + pre-install check pointers like
51
+ `npm view <pkg> license`, PyPI metadata, etc.).
52
+ - `vinta-derive-skills` substitutes three new placeholders into the
53
+ `implement-plan` + `amend-plan` templates: `{{DEPENDENCY_LICENSE_BLOCK}}`
54
+ (top-level "Adding new third-party dependencies" section directly
55
+ before Working instructions — canonical body at
56
+ [vinta-derive-skills/resources/dependency-license-block.md](skills/vinta-derive-skills/resources/dependency-license-block.md)),
57
+ `{{DEPENDENCY_LICENSE_LAYER1_CHECK}}` (reviewer Layer 1 mechanical
58
+ check that greps the manifest diff for forbidden licenses), and
59
+ `{{DEPENDENCY_LICENSE_RULE_LINE}}` (an Important-rules bullet).
60
+ All three placeholders render the empty string when
61
+ `enforcement: off` or the config block is absent — projects that opt
62
+ out get no extra prose in their rendered skills. `enforcement: block`
63
+ refuses the install + asks the user to acknowledge before recording an
64
+ `allowed_overrides[]` entry and re-running; `warn` proceeds but flags
65
+ in the phase report. **Missing / `UNKNOWN` / undeclared license is
66
+ always handled as a stop-and-ask, regardless of enforcement mode** —
67
+ unknown ≠ permissive, so the subagent surfaces the gap (registry
68
+ lookup output, upstream URL) and asks the user to pick `skip the dep`
69
+ / `treat as forbidden` / `record an `allowed_overrides` entry with an
70
+ off-channel-confirmed SPDX`. Same behaviour reinforced in the Layer 1
71
+ reviewer check: undeclared license = BLOCKER, no enforcement-mode
72
+ downgrade.
73
+
74
+ - **New `policies.commit_strategy` field in `.vinta-ai-workflows.yaml`**
75
+ (`stacked-branches` | `modular-commits` | `ask`, default
76
+ `stacked-branches`). Drives how the rendered `implement-plan` skill
77
+ structures branches and commits across phases:
78
+ - `stacked-branches` — current behavior. One branch + one PR per
79
+ phase, stacked on top of each other.
80
+ - `modular-commits` — one branch + one PR for the whole plan; each
81
+ phase contributes multiple atomic commits (one per logical unit:
82
+ service, use-case wire-up, init/exports, serializer field,
83
+ refactor, fix). Tests travel in the same commit as the code they
84
+ test. The commit list becomes a table of contents for reviewers.
85
+ - `ask` — `implement-plan` prompts the user at Step 0 (alongside
86
+ `pause_between_phases` / `generate_inline_comments`) and caches the
87
+ resolved value in `TRACKING_{plan-id}.md` under
88
+ `run_options.commit_strategy_resolved`.
89
+ Additive on schema v1 — existing configs without the field default
90
+ to `stacked-branches` at read time (backward-compatible). Bootstrap
91
+ interview captures the answer in **C. Project conventions**.
92
+
93
+ - **New optional foundation skill: `prepare-worktree`** (copied verbatim
94
+ to `ai-tools/skills/prepare-worktree/SKILL.md` per project, opt-in via
95
+ the bootstrap **Optional foundation skills** interview, new
96
+ `prepare-worktree` question). Source:
97
+ [skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/SKILL.md](skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/SKILL.md).
98
+ Provisions a fully-runnable git worktree for parallel feature work so a
99
+ long-running plan (or experiment) can build, test, lint, migrate, and
100
+ hit databases without disturbing the main checkout — or other parallel
101
+ worktrees on the same machine. Walks the project's `.gitignore` +
102
+ package manifests + env templates + docker config and decides per
103
+ ignored path whether to **symlink** (read-only-ish reuse), **copy**
104
+ (defensive, when the feature mutates the path), or **fork** (state
105
+ that would corrupt main if shared — dev DB, test DB, docker-compose
106
+ project name). Reads the active plan to bias decisions: dep churn
107
+ flips dep dirs to copy/reinstall; migrations flip the dev DB to fork
108
+ and run them once; new env vars flip `.env` from symlink to copy +
109
+ mutate; compose changes flip the network strategy. Drops a per-worktree
110
+ summary YAML at `.vinta-ai-workflows/worktrees/<name>.yaml` + a
111
+ `WORKTREE.md` at the worktree root so teardown is mechanical (no
112
+ decision lives only in conversation memory). Bucket A (copy verbatim) —
113
+ body is project-agnostic; per-project variability lives in
114
+ `skills.prepare-worktree.*` config (worktree root, deps strategy,
115
+ compose-network strategy, test-DB strategy, summary dir).
116
+
117
+ - **`implement-plan` Step 0 question (c) — "Run phases in a worktree?"**.
118
+ New opt-in: when the user picks `Yes`, the orchestrator runs
119
+ `prepare-worktree` **once** at the start of the plan (new
120
+ **Provision worktree** step between Step 0 and Step 1), records
121
+ `worktree_path` / `worktree_branch` / `worktree_summary` in the
122
+ tracking file, and threads them into every phase's subagent prompt +
123
+ every `git` call in the **Branch + push** step. **One worktree per
124
+ plan run** — every phase branch stacks inside the same worktree; the
125
+ skill never provisions a second one mid-plan. Mid-plan resumes detect
126
+ the worktree from tracking and reuse it (asking only when the worktree
127
+ is missing). When `foundation_skills.prepare-worktree` is `disabled`,
128
+ the question is skipped and `run_options.use_worktree` is forced to
129
+ `false` with a one-line note pointing at `vinta-sync-ai-tools` to
130
+ enable later. Failure modes are explicit — prepare-worktree errors
131
+ never fall back silently to the main checkout; the user picks `Retry`
132
+ / `Run in main` / `Stop`.
133
+
134
+ - **`.vinta-ai-workflows.yaml` config additions for `prepare-worktree`**:
135
+ - `foundation_skills.prepare-worktree: enabled | disabled` — sticky
136
+ opt-in like every other foundation skill.
137
+ - `skills.prepare-worktree.worktree_root: string` (default
138
+ `.claude/worktrees` for claude-code-primary projects;
139
+ `../<repo>-wt-` sibling-dir layout otherwise) — where new worktrees
140
+ land. The skill resolves `<root>/<name>` per provisioning call.
141
+ - `skills.prepare-worktree.deps_strategy: symlink | copy | reinstall`
142
+ (default `symlink`) — default for dep dirs (`node_modules/`,
143
+ `vendor/`, `venv/`) when the active plan does NOT install new deps.
144
+ The skill auto-flips to `reinstall` when it detects dep churn in the
145
+ plan body.
146
+ - `skills.prepare-worktree.compose_network: per-worktree | shared-external | host`
147
+ (default `per-worktree`) — docker-compose networking strategy.
148
+ `shared-external` joins an externally-declared network so the
149
+ worktree can reach main's compose services (queues, caches, search
150
+ indexes that are expensive to spin twice).
151
+ - `skills.prepare-worktree.test_db_strategy: fork-on-schema-change | always-fork | share`
152
+ (default `fork-on-schema-change`) — when to fork the test DB per
153
+ worktree. `share` is only safe for solo work (parallel runs flake).
154
+ - `skills.prepare-worktree.summary_dir: string` (default
155
+ `.vinta-ai-workflows/worktrees`) — where per-worktree summary YAMLs
156
+ land. Covered by the umbrella `.vinta-ai-workflows/` gitignore.
157
+ - `run_options.implement-plan.use_worktree: boolean` (default
158
+ `false`) — suggested default shown for the Step 0 question (c)
159
+ above; per-run prompt always asks. Flipped to `true` at bootstrap
160
+ when the user opts in via the `prepare-worktree` follow-up.
161
+
162
+ - **Bootstrap interview — new `prepare-worktree` question** under
163
+ **Optional foundation skills**, plus four short follow-ups (worktree
164
+ root, default deps strategy, default test-DB strategy, and the
165
+ `implement-plan` default for question (c)). The **Optional foundation
166
+ skills** opener switched from "four skills" to "five skills"
167
+ accordingly. Outputs tree updated to list
168
+ `ai-tools/skills/prepare-worktree/SKILL.md` as an opt-in foundation
169
+ skill. The **Existing AI artifacts** disposition flow's
170
+ `foundation-shape` name list (which gates the
171
+ `Replace with Vinta foundation version` option) gained
172
+ `prepare-worktree`.
173
+
174
+ - **`vinta-derive-skills` — Always copy bucket** gains a row for
175
+ `prepare-worktree` (verbatim copy). The **Optional — ask the user**
176
+ bucket also gets a row covering the opt-in interview + the four
177
+ follow-ups; this is the same compose pattern as `add-one-off-script`
178
+ (verbatim copy, gated by ask-first). Foundation-shape lists in both
179
+ "Reconcile against existing skills" + Rules sections extended with
180
+ `prepare-worktree`.
181
+
182
+ ### Changed
183
+
184
+ - **`implement-plan` template**: the Step 0 opt-in questions block grew
185
+ from two questions to three (added (c) for worktree opt-in); a new
186
+ **Provision worktree** step sits between Step 0 and Step 1; the
187
+ per-phase prompt (`Prepare agent prompt` step) carries a worktree
188
+ block when `use_worktree = true`; the `Branch + push` step's branch
189
+ and push commands now prefix with `git -C <worktree_path>` when
190
+ applicable; tracking schema (`Update tracking file` step) gains
191
+ `run_options.worktree_path` / `worktree_branch` / `worktree_summary`;
192
+ Re-running mid-plan flow learned to detect + reuse the worktree;
193
+ Step 2 final report surfaces the teardown command (never auto-runs
194
+ it). Three new entries in the **Important rules** section codify the
195
+ one-worktree-per-plan-run invariant + the no-silent-fallback rule.
196
+
8
197
  ## [0.1.7] — 2026-06-01
9
198
 
10
199
  ### Added
@@ -35,6 +224,21 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
35
224
 
36
225
  ### Changed
37
226
 
227
+ - **`implement-plan` template rendered with new
228
+ `{{COMMIT_STRATEGY_*}}` placeholder family.** Branch naming, per-phase
229
+ push, subagent commit instructions, PR-open timing, tracking-file
230
+ branch field, and final-report branch summary now swap based on
231
+ `policies.commit_strategy`. Under `ask`, both code paths render in
232
+ the same body gated by `run_options.commit_strategy_resolved` —
233
+ mirrors the existing `pause_between_phases` /
234
+ `generate_inline_comments` opt-in pattern.
235
+ - **`amend-plan` refuses to run when
236
+ `policies.commit_strategy != stacked-branches`** and points users at
237
+ appending a new phase via `implement-plan` (or hand-crafting the
238
+ rebase). Modular-commits amendment support is tracked as a follow-up
239
+ — rewriting an arbitrary number of inline commits on a shared branch
240
+ is out of scope for this release.
241
+
38
242
  - **Replaced all `§N` shorthand cross-references with named section
39
243
  links across the repo.** `§1`, `§4.3`, `§1f`, `§A.3`, etc. were
40
244
  unreadable for humans (forced readers to flip back to the source doc
package/README.md CHANGED
@@ -124,6 +124,8 @@ git push -u origin plan/<feature-kebab>/phase-2
124
124
 
125
125
  Each phase's PR (or branch, depending on the project's PR policy captured at bootstrap) targets the previous phase's branch, not `main`. This keeps the diff per PR scoped to a single phase, makes review manageable, and lets the team merge phases sequentially as approvals land — earlier phases ship to production while later ones are still in review.
126
126
 
127
+ **Alternative: modular commits.** Teams that prefer one branch + one PR per plan can set `policies.commit_strategy: modular-commits` in `.vinta-ai-workflows.yaml`. Under that mode, every phase pushes its **atomic unit commits** (one per service, use-case wire-up, init export, serializer field, refactor, or bug fix — tests in the same commit as code) to a single `plan/<feature-kebab>` branch; the PR opens once after Phase 1 review and gets updated as later phases push. The third option, `commit_strategy: ask`, prompts `implement-plan` at Step 0 (alongside the existing `pause_between_phases` / `generate_inline_comments` opt-ins) and caches the answer in the tracking file. Default is `stacked-branches` — the model documented above. See [`schemas/vinta-ai-workflows-config.v1.schema.json`](schemas/vinta-ai-workflows-config.v1.schema.json) for the field definition.
128
+
127
129
  **Tracking file** — `ai-plans/TRACKING_<feature-kebab>.md`. The orchestrator writes it from `git diff` + the agent's report (not the agent's narration). Records: completed phases (status, model used, branch, base, e2e+screenshots when applicable, 5–15 line summary), current phase, remaining phases, deferred phases. Acts as the durable context handoff between phase prompts. Deleted on plan completion.
128
130
 
129
131
  **Phases the orchestrator never auto-executes:**
@@ -257,7 +259,7 @@ That's it. The sync skill walks every release between the project's recorded ver
257
259
 
258
260
  ### How it stays safe
259
261
 
260
- The single source of truth is `.vinta-ai-workflows.yaml` at the repo root (written at bootstrap, schema: [`schemas/vinta-ai-workflows-config.v1.schema.json`](schemas/vinta-ai-workflows-config.v1.schema.json)). It records every opt-in the project made — which foundation skills are `enabled`, which stacks are applied, which vendors are wired, which policies (PR creation, AI co-author, commit style) hold. `vinta-sync-ai-tools` reads this file and uses it to classify every upstream change into one of:
262
+ The single source of truth is `.vinta-ai-workflows.yaml` at the repo root (written at bootstrap, schema: [`schemas/vinta-ai-workflows-config.v1.schema.json`](schemas/vinta-ai-workflows-config.v1.schema.json)). It records every opt-in the project made — which foundation skills are `enabled`, which stacks are applied, which vendors are wired, which policies (PR creation, commit strategy, AI co-author, commit style) hold. `vinta-sync-ai-tools` reads this file and uses it to classify every upstream change into one of:
261
263
 
262
264
  | Bucket | Meaning | Default |
263
265
  |---|---|---|
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinta-ai-workflows",
3
- "version": "0.1.7",
3
+ "version": "0.2.0-alpha2",
4
4
  "description": "Bootstrap AI tooling (AGENTS.md, skills, sub-agents) across Claude Code, Codex, Cursor, and VS Code + GitHub Copilot.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -105,6 +105,12 @@
105
105
  "type": "string",
106
106
  "enum": ["conventional", "imperative", "other"]
107
107
  },
108
+ "commit_strategy": {
109
+ "description": "How `implement-plan` structures branches and commits across phases. `stacked-branches` (default — current behavior): one branch + one PR per phase, stacked on top of each other. `modular-commits`: one branch + one PR for the whole plan; each phase contributes multiple atomic commits (one per logical unit — service, use-case wire-up, init/exports, serializer field, refactor, fix). Tests travel in the same commit as the code they test. `ask`: `implement-plan` prompts the user at Step 0 (alongside `pause_between_phases` / `generate_inline_comments`) and caches the resolved value in `TRACKING_{plan-id}.md` under `run_options.commit_strategy_resolved`. Omitting the field is equivalent to `stacked-branches` (backward-compatible for configs written before this field existed).",
110
+ "type": "string",
111
+ "enum": ["stacked-branches", "modular-commits", "ask"],
112
+ "default": "stacked-branches"
113
+ },
108
114
  "stage_pattern": {
109
115
  "description": "Default `git add` pattern shown to subagents (no `git add -A`).",
110
116
  "type": "string"
@@ -112,6 +118,59 @@
112
118
  "anti_git_add_all_reason": {
113
119
  "description": "One-line reason `git add -A` is forbidden in this repo (e.g. secrets, build artifacts in tree).",
114
120
  "type": "string"
121
+ },
122
+ "dependency_licenses": {
123
+ "description": "Third-party dependency license policy. Captured at bootstrap; rendered into `ai-tools/AGENTS.md` (`## Dependency licenses` section) and the `implement-plan` / `amend-plan` skill bodies so the implementer / reviewer agents check a new dep's SPDX license against `forbidden_spdx` before running any install command (`npm add`, `pnpm add`, `pip install`, `poetry add`, `uv add`, `cargo add`, `go get`, etc.). When `enforcement: block`, the agent must refuse the install and surface the violation to the user; `warn` records the violation in the phase report but proceeds; `off` skips the check entirely.",
124
+ "type": "object",
125
+ "required": ["enforcement", "forbidden_spdx"],
126
+ "additionalProperties": false,
127
+ "properties": {
128
+ "enforcement": {
129
+ "description": "How the implementer / reviewer agents react when a new dep's license is in `forbidden_spdx`. `block` (default) — refuse install, ask user to confirm override before proceeding. `warn` — proceed but flag in the phase report. `off` — skip the check.",
130
+ "type": "string",
131
+ "enum": ["block", "warn", "off"],
132
+ "default": "block"
133
+ },
134
+ "forbidden_spdx": {
135
+ "description": "SPDX license identifiers (https://spdx.org/licenses/) the project refuses to take on as a third-party dep. Bootstrap proposes a default list (GPL-2.0-only, GPL-3.0-only, AGPL-3.0-only, SSPL-1.0) targeting viral copyleft licenses; the user confirms / edits before write. Empty array disables the check even when `enforcement` is `block` or `warn` (use `enforcement: off` instead for clarity).",
136
+ "type": "array",
137
+ "items": { "type": "string", "minLength": 1 },
138
+ "uniqueItems": true,
139
+ "default": ["GPL-2.0-only", "GPL-3.0-only", "AGPL-3.0-only", "SSPL-1.0"]
140
+ },
141
+ "allowed_overrides": {
142
+ "description": "Explicit per-package exceptions to `forbidden_spdx`. Each entry whitelists one package + license pair the team has accepted (legal review, dual-license clause, in-house carve-out). The implementer agent skips the block when the candidate package + license matches an entry; the reviewer agent treats the entry as load-bearing context (don't silently drop).",
143
+ "type": "array",
144
+ "items": {
145
+ "type": "object",
146
+ "required": ["package", "license", "reason"],
147
+ "additionalProperties": false,
148
+ "properties": {
149
+ "package": {
150
+ "description": "Package identifier as it appears in the manifest (npm name, PyPI distribution, Cargo crate, Go module path).",
151
+ "type": "string",
152
+ "minLength": 1
153
+ },
154
+ "license": {
155
+ "description": "SPDX identifier this override applies to. Must be present in `forbidden_spdx` for the override to mean anything.",
156
+ "type": "string",
157
+ "minLength": 1
158
+ },
159
+ "reason": {
160
+ "description": "One-line justification (e.g. 'legal review 2025-Q4', 'GPL exception clause covers our use', 'wraps a CLI invoked at build time only — not linked').",
161
+ "type": "string",
162
+ "minLength": 1
163
+ }
164
+ }
165
+ },
166
+ "uniqueItems": true,
167
+ "default": []
168
+ },
169
+ "notes": {
170
+ "description": "Free-form prose surfaced verbatim in the AGENTS.md `## Dependency licenses` section. Use for nuance the structured fields can't capture (e.g. 'LGPL is fine for dynamic linking but not for static linking — check the consuming module before adding', 'all viral-license deps go through @counsel before merge').",
171
+ "type": "string"
172
+ }
173
+ }
115
174
  }
116
175
  }
117
176
  },
@@ -144,6 +203,11 @@
144
203
  "description": "Root-cause-first debugging skill rendered from `vinta-derive-skills/resources/systematic-debugging-template.md`. When `enabled`, the per-project MCP tool selection lives in `skills.systematic-debugging.observability_mcp_tools`.",
145
204
  "type": "string",
146
205
  "enum": ["enabled", "disabled"]
206
+ },
207
+ "prepare-worktree": {
208
+ "description": "Provision a fully-runnable git worktree for parallel feature work — symlinks dep dirs, copies env files, forks dev / test DBs, namespaces docker-compose project + network, drops a summary YAML for mechanical teardown. Copy-verbatim foundation skill (bucket A). When `enabled`, project-level defaults (worktree root, deps strategy, compose network strategy) live under `skills.prepare-worktree`. Consumed by `implement-plan` when its Step 0 question (c) opts in — the orchestrator runs `prepare-worktree` once at the start of a plan run and threads the worktree path through every subagent's prompt so phases all stack inside the same isolated checkout.",
209
+ "type": "string",
210
+ "enum": ["enabled", "disabled"]
147
211
  }
148
212
  }
149
213
  },
@@ -181,7 +245,12 @@
181
245
  "additionalProperties": false,
182
246
  "properties": {
183
247
  "pause_between_phases": { "type": "boolean", "default": false },
184
- "generate_inline_comments": { "type": "boolean", "default": false }
248
+ "generate_inline_comments": { "type": "boolean", "default": false },
249
+ "use_worktree": {
250
+ "description": "Default answer to Step 0 question (c) — whether `implement-plan` should provision an isolated git worktree (via `prepare-worktree`) and run every phase's subagent inside it. False = run in the current checkout. True = create one shared worktree at the start of the plan run; all phase branches stack inside it. Per-run prompt still asks; this is the suggested default shown.",
251
+ "type": "boolean",
252
+ "default": false
253
+ }
185
254
  }
186
255
  },
187
256
  "amend-plan": {
@@ -230,6 +299,42 @@
230
299
  }
231
300
  }
232
301
  },
302
+ "prepare-worktree": {
303
+ "description": "Configuration for the `prepare-worktree` foundation skill. Optional when `foundation_skills.prepare-worktree` is `enabled` — every field has a sensible default. Consumed by the skill at runtime to bias the per-worktree symlink-vs-copy-vs-fork decisions.",
304
+ "type": "object",
305
+ "additionalProperties": false,
306
+ "properties": {
307
+ "worktree_root": {
308
+ "description": "Where new worktrees land. Default `.claude/worktrees` when claude-code is the primary harness (matches the EnterWorktree convention); other harnesses default to `../<repo-name>-wt-` (sibling dirs of the main checkout). The skill resolves `<root>/<name>` per provisioning call.",
309
+ "type": "string",
310
+ "minLength": 1
311
+ },
312
+ "deps_strategy": {
313
+ "description": "Default strategy for dep dirs (`node_modules/`, `vendor/`, `venv/`) when the active plan does NOT install new deps. `symlink` reuses main's install (fast, safe for read-only); `copy` clones it (safe for pnpm-style relative-symlink stores, fails for yarn PnP); `reinstall` runs the package manager fresh in the worktree. The skill flips to `reinstall` automatically when it detects dep churn in the plan body.",
314
+ "type": "string",
315
+ "enum": ["symlink", "copy", "reinstall"],
316
+ "default": "symlink"
317
+ },
318
+ "compose_network": {
319
+ "description": "Default docker-compose networking strategy for the worktree. `per-worktree` spins a fresh isolated network (safest, doubles infra); `shared-external` joins an externally-declared network so the worktree can talk to main's compose services (queues, caches, search); `host` uses host networking when the project already does. Skill writes the chosen strategy into the worktree's `docker-compose.override.yml` (or equivalent) when `compose_change` is set.",
320
+ "type": "string",
321
+ "enum": ["per-worktree", "shared-external", "host"],
322
+ "default": "per-worktree"
323
+ },
324
+ "test_db_strategy": {
325
+ "description": "Default policy for the test DB. `always-fork` provisions a dedicated test DB per worktree (no flaky cross-worktree races at the cost of one extra DB per worktree); `fork-on-schema-change` only forks when the plan touches migrations; `share` keeps using the main checkout's test DB and accepts the race risk (only sensible for solo work).",
326
+ "type": "string",
327
+ "enum": ["always-fork", "fork-on-schema-change", "share"],
328
+ "default": "fork-on-schema-change"
329
+ },
330
+ "summary_dir": {
331
+ "description": "Where per-worktree summary YAMLs land. Default `.vinta-ai-workflows/worktrees` — covered by the umbrella gitignore added in 0.1.3. The skill writes `<summary_dir>/<name>.yaml` per provisioned worktree; teardown reads it.",
332
+ "type": "string",
333
+ "minLength": 1,
334
+ "default": ".vinta-ai-workflows/worktrees"
335
+ }
336
+ }
337
+ },
233
338
  "add-one-off-script": {
234
339
  "description": "Configuration for the `add-one-off-script` foundation skill. Optional when `foundation_skills.add-one-off-script` is `enabled` — sensible defaults apply when omitted.",
235
340
  "type": "object",
@@ -69,10 +69,21 @@ These bleed across sub-skills, so capture once now:
69
69
  4. **PR creation policy** — agents open PRs, or only push branches and humans open PRs?
70
70
  5. **Co-author trailer policy** — repo allows AI co-author trailers in commits, or strictly human-only?
71
71
  6. **Deploy targets** — Vercel, AWS, Kubernetes, Heroku, custom, none.
72
+ 7. **Third-party dependency license policy.** Should agents check the SPDX license of any new dep against a forbidden list before running `npm add` / `pnpm add` / `pip install` / `poetry add` / `uv add` / `cargo add` / `go get` (etc.)?
73
+ - **Enforcement.** `AskUserQuestion` options: `Block (recommended)` — refuse install + surface violation, ask user to confirm override before proceeding; `Warn` — proceed but flag in the phase report; `Off` — skip the check entirely.
74
+ - **Forbidden SPDX list.** Show the default seed (`GPL-2.0-only`, `GPL-3.0-only`, `AGPL-3.0-only`, `SSPL-1.0`) targeting viral copyleft licenses, then ask via open prose: *"Add or remove entries? Common additions: `LGPL-2.1-only`, `LGPL-3.0-only`, `BSL-1.1`, `EUPL-1.2`, `CC-BY-NC-*` (non-commercial)."* Skip when enforcement = `Off`.
75
+ - **Existing overrides (optional).** Open prose: *"Any packages already in the manifest with a forbidden license the team has accepted? Format: `<package> <SPDX-id> <one-line reason>`. Leave blank if none."* Each entry lands in `policies.dependency_licenses.allowed_overrides[]`. Skip when enforcement = `Off`.
76
+ - **Notes (optional).** Open prose: *"Any nuance the structured fields can't capture? (e.g. 'LGPL fine for dynamic linking only', 'viral-license deps go through @counsel before merge'.)"* Lands in `policies.dependency_licenses.notes`.
77
+ 8. **Commit strategy** — how `implement-plan` should structure branches + commits across phases. `AskUserQuestion` options:
78
+ - `Stacked branches (default) — one branch + one PR per phase, stacked on top of each other` — current behavior. Each phase ships one commit on its own branch; reviewers see one PR per phase.
79
+ - `Modular commits — one branch + one PR for the whole plan, atomic commit per logical unit` — each phase produces multiple commits (one per service / use-case wire-up / init / serializer field / refactor / fix). Tests travel in the same commit as the code they test. Reviewers read the commit list as a TOC.
80
+ - `Ask me each run` — `implement-plan` prompts at Step 0 (alongside `pause_between_phases` / `generate_inline_comments`) and caches the answer in `TRACKING_{plan-id}.md`.
81
+
82
+ Lands in `.vinta-ai-workflows.yaml` `policies.commit_strategy`. Drives the `implement-plan` template's branch / commit / PR-opening flow + the `amend-plan` skill's supported-strategies check.
72
83
 
73
84
  ### D. Optional foundation skills
74
85
 
75
- Four skills are part of the foundation set but aren't always needed. Ask explicitly:
86
+ Five skills are part of the foundation set but aren't always needed. Ask explicitly:
76
87
 
77
88
  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.
78
89
  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`.
@@ -84,6 +95,15 @@ Four skills are part of the foundation set but aren't always needed. Ask explici
84
95
  - **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}`.
85
96
  - **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.
86
97
 
98
+ 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.
99
+
100
+ **Follow-up only when `prepare-worktree` = Yes — worktree defaults.** Three short questions land under `skills.prepare-worktree.*`:
101
+ - **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.
102
+ - **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.
103
+ - **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).
104
+
105
+ **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.
106
+
87
107
  **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.
88
108
 
89
109
  **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:
@@ -92,7 +112,7 @@ Four skills are part of the foundation set but aren't always needed. Ask explici
92
112
  - 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.
93
113
  - 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.
94
114
 
95
- If the user answers "No" to any of the four, 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.
115
+ If the user answers "No" to any of the five, 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.*`.
96
116
 
97
117
  ### E. Existing AI artifacts (per-artifact disposition)
98
118
 
@@ -112,7 +132,7 @@ For each artifact, read it (frontmatter + body), then ask the user via `AskUserQ
112
132
  - `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.
113
133
  - `Drop` — delete (rare; usually the user wants to migrate).
114
134
 
115
- Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`) 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.
135
+ Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`) 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.
116
136
 
117
137
  - **Sub-agents** (each under any vendor `agents/` dir):
118
138
  - `Migrate to ai-tools/agents/<name>.yaml` — converts vendor-specific format → canonical YAML; `setup-ai-tools.mjs` re-emits per-vendor copies.
@@ -199,10 +219,22 @@ commands:
199
219
 
200
220
  policies:
201
221
  pr_creation: <Project conventions → PR creation policy>
222
+ commit_strategy: <Project conventions → Commit strategy> # stacked-branches | modular-commits | ask
202
223
  ai_coauthor: <Project conventions → Co-author trailer policy>
203
224
  commit_style: <conventional | imperative | other>
204
225
  stage_pattern: <derived>
205
226
  anti_git_add_all_reason: <derived>
227
+ # Only emit `dependency_licenses` when enforcement != Off (the `off` value is
228
+ # supported by the schema but the agent never needs the rest of the block
229
+ # when there is no check to run — keep the config slim).
230
+ dependency_licenses:
231
+ enforcement: <Project conventions → license policy enforcement → block | warn | off>
232
+ forbidden_spdx: <license policy forbidden list — array of SPDX IDs the user confirmed at bootstrap>
233
+ allowed_overrides: # empty array when the user listed no exceptions
234
+ - package: <name>
235
+ license: <SPDX ID — must appear in forbidden_spdx>
236
+ reason: <one-line justification>
237
+ notes: <free-form prose, omit when blank>
206
238
 
207
239
  vendors: <Scope → Vendor coverage list>
208
240
 
@@ -217,6 +249,7 @@ foundation_skills:
217
249
  add-env-var: <Optional foundation skills → add-env-var answer → enabled | disabled>
218
250
  systematic-debugging: <Optional foundation skills → systematic-debugging answer → enabled | disabled>
219
251
  add-one-off-script: <Optional foundation skills → add-one-off-script answer → enabled | disabled>
252
+ prepare-worktree: <Optional foundation skills → prepare-worktree answer → enabled | disabled>
220
253
 
221
254
  foundation_agents:
222
255
  implementer: enabled
@@ -230,6 +263,7 @@ run_options:
230
263
  implement-plan:
231
264
  pause_between_phases: false
232
265
  generate_inline_comments: false
266
+ use_worktree: <Optional foundation skills → prepare-worktree follow-up → default for Step 0 question (c); false unless team opted in>
233
267
  amend-plan:
234
268
  blast_radius_signal_threshold: 2
235
269
 
@@ -238,6 +272,14 @@ skills:
238
272
  systematic-debugging:
239
273
  observability_mcp_servers: <systematic-debugging follow-up — free-form array of MCP server identifiers, e.g. [sentry, datadog, our-internal-traces]>
240
274
 
275
+ # Only emit this block when foundation_skills.prepare-worktree = enabled.
276
+ prepare-worktree:
277
+ worktree_root: <prepare-worktree follow-up — `.claude/worktrees` | `../<repo>-wt-`>
278
+ deps_strategy: <prepare-worktree follow-up — symlink | copy | reinstall>
279
+ compose_network: per-worktree
280
+ test_db_strategy: <prepare-worktree follow-up — fork-on-schema-change | always-fork | share>
281
+ summary_dir: .vinta-ai-workflows/worktrees
282
+
241
283
  # Only emit this block when foundation_skills.add-one-off-script = enabled.
242
284
  add-one-off-script:
243
285
  scripts_dir: <add-one-off-script follow-up — default `scripts/one_off`>
@@ -308,6 +350,7 @@ ai-tools/
308
350
  │ │ └── resources/
309
351
  │ │ ├── one_off_script_base.py
310
352
  │ │ └── one_off_script_base.ts
353
+ │ ├── prepare-worktree/SKILL.md ← optional — only if user opts in (verbatim copy; project-agnostic body, defaults under skills.prepare-worktree.*)
311
354
  │ ├── 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)
312
355
  │ ├── 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)
313
356
  │ └── <stack-specific skills>/SKILL.md ← only if user supplied templates
@@ -338,7 +381,7 @@ Foundation skills break into three buckets — see [vinta-derive-skills](../vint
338
381
 
339
382
  - **Always copy verbatim**: `plan-feature`, `create-spec`, `create-qa-use-cases`. Bundled with the bootstrap skill set; project-agnostic enough to ship as-is (with light path scrubs).
340
383
  - **Always generate**: `implement-plan`, `amend-plan`. Bodies have too much project-specific content (test commands, branch convention, PR + co-author policy, agent dispatch) — generated from parameterized templates using interview answers + inventory.
341
- - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`. 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.
384
+ - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`, `prepare-worktree`. 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, and (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; if no → don't ship.
342
385
 
343
386
  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.
344
387