vinta-ai-workflows 0.2.0-alpha5 → 0.2.0-alpha7

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
@@ -7,10 +7,66 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [0.2.0] — YYYY-MM-DD
9
9
 
10
- ### Added
10
+ ### Changed
11
+
12
+ - **E2E tests are now opt-in in both `plan-feature` and `implement-plan`,
13
+ because they make the implementation run a LOT slower.** Previously, for
14
+ e2e-enabled projects, `plan-feature` *required* a happy-path Playwright spec on
15
+ every phase that reached the browser, and `implement-plan` ran those specs in
16
+ every phase's outer gate + review layers — browser boot, seeded data, and
17
+ screenshot capture on each phase. Now:
18
+ - `plan-feature` gained a Step 0 (group I) **E2E coverage** question that
19
+ **defaults to NO**. When not opted in, phases ship unit + integration tests
20
+ only and carry no e2e spec, `QA_USE_CASES.md`, or `pr-screenshots/`
21
+ references; e2e can still be added later per-flow via `add-e2e-test`.
22
+ - `implement-plan` gained a Step 0 question **(e) Run E2E tests this run?**
23
+ (`run_options.run_e2e`, **default off**). Even when a plan carries e2e specs,
24
+ the outer-gate e2e step, the Layer 1 verification note, the Layer 2
25
+ walkthrough check, and the implementer report field only run when the user
26
+ opts in for that run. The shared review/debug e2e gate follows the same
27
+ `run_options.run_e2e` flag, so standalone `systematic-debugging` /
28
+ `amend-plan` runs skip e2e unless it is set.
29
+ **Consumers**: re-sync to pick up the opt-in questions. E2E-disabled projects
30
+ are unaffected (the e2e regions strip out as before).
31
+
32
+
33
+ <!-- pre-release: 0.2.0-alpha7 on 2026-07-13 -->
34
+
35
+ ### Changed
36
+
37
+ - **`plan-feature` AI model tiers refreshed to the current model
38
+ generation.** `plan-feature/resources/ai-models.yaml` now cites the latest
39
+ IDs: tier 1 `gemini-2.5-flash-lite` → `gemini-3.1-flash-lite` and
40
+ `gpt-5-nano` → `gpt-5.6-luna`; tier 2 `claude-sonnet-4-6` → `claude-sonnet-5`
41
+ (incl. the Haiku step-up note) and `gemini-2.5-flash` → `gemini-3.5-flash`; tier 3
42
+ `claude-sonnet-4-6` → `claude-sonnet-5` and the retired `gemini-2.5-pro`
43
+ dropped in favor of `gemini-3-pro` and the retired `gpt-5` dropped in favor of
44
+ `gpt-5.6-terra`; tier 4 `claude-opus-4-7` → `claude-opus-4-8` and the retired
45
+ `o3` dropped in favor of `gpt-5.6-sol`. Tier *placement* is unchanged — only the
46
+ concrete IDs move. **Consumers**: re-sync to pick up the refreshed model
47
+ suggestions.
48
+
49
+ ### Fixed
50
+
51
+ - **`implement-plan` stacked-branches now opens each phase PR against its
52
+ parent phase, not the default branch.** The git branch topology was already
53
+ stacked correctly (each phase branches off the previous phase's branch), but
54
+ nothing told the orchestrator what to write into the prs-context `base`
55
+ field, so it defaulted to `<BASE_BRANCH>` and **every stacked PR targeted the
56
+ default branch** — collapsing the stack and showing each PR the cumulative
57
+ diff. The stacked commit-strategy partial now spells out the PR base per
58
+ phase (first phase → default branch; every subsequent phase → the previous
59
+ phase's branch), the shared `pr-context` write step no longer defaults `base`
60
+ blindly, and the `prs-context` template comment states the rule. Modular /
61
+ single-PR strategies are unaffected (one PR against the default branch).
62
+ **Consumers**: re-sync to pick up the corrected `base` resolution; existing
63
+ PRs opened against the wrong base must be re-targeted manually.
11
64
 
12
65
  <!-- pre-release: 0.2.0-alpha5 on 2026-07-13 -->
13
66
 
67
+ ### Added
68
+
69
+
14
70
  - **`handoff` foundation skill — session-continuation handoff docs between
15
71
  agents.** Write mode captures the current task (goal, verified-vs-unverified
16
72
  state, decisions + rejected alternatives, landmines, single concrete next
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinta-ai-workflows",
3
- "version": "0.2.0-alpha5",
3
+ "version": "0.2.0-alpha7",
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": {
@@ -123,8 +123,14 @@ The remaining per-shell placeholders:
123
123
  | `{{NEW_TEST_CMD_PATTERN}}` | derived | `pnpm --filter <pkg> test -- <new-test-path>` or `pytest path/to/new_test.py -x` |
124
124
  | `{{SCOPED_TEST_PATTERN}}` | derived | `pnpm test:patient`, `pytest tests/{unit,integration}/{app}/` |
125
125
  | `{{E2E_BLOCK}}` | populated only if e2e selected — see C below | block describing e2e command + screenshot copy |
126
- | `{{E2E_OUTER_GATE_LINE}}` | depends on e2e selected | ` c. **E2E:** ...` or empty |
127
- | `{{E2E_LAYER1_NOTE}}`, `{{E2E_LAYER2_CHECK}}`, `{{E2E_REPORT_FIELD}}`, `{{E2E_OUTER_GATE_CHECKLIST}}`, `{{UI_E2E_RULE_LINE}}` | depends on e2e selected | populated or empty strings |
126
+ | `{{E2E_OUTER_GATE_LINE}}` | depends on e2e selected | The outer-gate e2e step, **wrapped in a `run_options.run_e2e` runtime gate** so e2e is opt-in per run. Render as ` c. **E2E** (opt-in): {If \`run_options.run_e2e = true\`:} when this phase has an e2e spec, run the project's e2e suite for the touched app + copy screenshots into \`pr-screenshots/\`. {Else:} skip e2e this run (default — e2e makes the phase take a lot longer).` Empty when e2e not selected. |
127
+ | `{{E2E_LAYER1_NOTE}}`, `{{E2E_LAYER2_CHECK}}`, `{{E2E_REPORT_FIELD}}` | depends on e2e selected | Verification/report hooks for e2e, each **guarded by `{If run_options.run_e2e = true:}`** so they only apply when the run opted into e2e. `E2E_LAYER1_NOTE`: ` + the e2e suite when \`run_options.run_e2e = true\``. `E2E_LAYER2_CHECK`: a Layer-2 walkthrough item that checks the phase's named e2e spec exists + screenshots landed **only when `run_options.run_e2e = true`** (else it's a no-op). `E2E_REPORT_FIELD`: `- E2E: specs run + screenshot paths, or "skipped (run_options.run_e2e = false)".` Empty when e2e not selected. |
128
+ | `{{E2E_OUTER_GATE_CHECKLIST}}`, `{{UI_E2E_RULE_LINE}}` | depends on e2e selected | populated or empty. `E2E_OUTER_GATE_CHECKLIST`: a trailing checklist clause ` + the e2e suite when \`run_options.run_e2e = true\`` (leading ` + `) so the gate checklist only demands e2e on opted-in runs. `UI_E2E_RULE_LINE`: an important-rules bullet stating e2e is opt-in via `run_options.run_e2e` (default off, makes runs a lot slower) and only runs for phases carrying an e2e spec. |
129
+ | `{{E2E_RUN_OPTION_QUESTION}}` | depends on e2e selected | The Step 0 opt-in question **(e)** for `implement-plan`, e2e projects only (empty otherwise). Render as ``\n\n e. **Run E2E tests this run?** *"Some phases carry Playwright e2e specs. Running them each phase makes the implementation take a LOT longer (browser boot, seeded data, screenshot capture). Run them this time, or skip and rely on unit + integration coverage?"* Options: `Skip e2e (default) — faster`, `Run e2e — slower but exercises the browser flows`. Default = `Skip`. Records `run_options.run_e2e` (`true` only for the `Run e2e` answer).`` (starts with `\n\n`; vanishes cleanly for no-e2e projects) |
130
+ | `{{E2E_RUN_OPTION_CONFIRM}}` | depends on e2e selected | e2e projects: `` + `run_options.run_e2e` `` (leading ` + `). Empty otherwise. |
131
+ | `{{E2E_RUN_OPTION_TRAILER}}` | depends on e2e selected | e2e projects: ` E2E execution follows `run_options.run_e2e` (opt-in; off by default).` (leading space). Empty otherwise. |
132
+ | `{{E2E_RUN_OPTION_TRACKING}}` | depends on e2e selected | e2e projects: `` , `run_e2e` `` (leading `, `) — appends `run_e2e` to a run-options list (the tracking schema line + the implement-phase / review-phase pass-through lists). Empty otherwise. |
133
+ | `{{E2E_RUN_OPTION_RULE}}` | depends on e2e selected | e2e projects: ` `run_options.run_e2e` controls whether the e2e suites run in the outer gate + review layers ([Implement](#1a-implement) + [Review](#1b-review)) — off by default because e2e makes each phase a lot slower; on only when the user opts in at Step 0.` (leading space). Empty otherwise. |
128
134
  | `{{STACK_SPECIFIC_DEPLOY_BLOCK}}` | from matched stacks | `- Bots: \`pnpm bots:build\`, \`pnpm bots:deploy --env=dev-<handle>\`...` for Medplum, or empty |
129
135
  | `{{CODE_HOST}}` | Step 0 interview | `GitHub`, `GitLab`, `Bitbucket` |
130
136
  | `{{DEFAULT_BRANCH}}` | inventory.repo.default_branch | `main` or `master` |
@@ -98,6 +98,9 @@ Never flatten ten questions into one prose paragraph just because tool unavailab
98
98
  1. Metric / log / dashboard tells us it's working in prod?
99
99
  2. Audit logging requirements (whatever audit-trail app/module the project uses)?
100
100
  3. How measure producer adoption before downstream phases ship?
101
+ <!-- e2e:start -->
102
+ 4. **E2E coverage (opt-in)** — should this plan include happy-path Playwright e2e specs for its new UI flows? **Default: NO.** E2E specs make the *implementation* run take a lot longer (browser boot, seeded data, screenshot capture on every affected view, per phase). Opt in only when the flow is high-risk or explicitly QA-gated. When off, phases ship unit + integration tests only and carry no e2e requirement — e2e can still be added later, per-flow, via [add-e2e-test](../add-e2e-test/SKILL.md).
103
+ <!-- e2e:end -->
101
104
 
102
105
  ### J. Edge cases & failure modes
103
106
  1. Behavior when new field partially populated, malformed, oversized? Reject whole batch, drop offending entry?
@@ -202,11 +205,13 @@ When on, apply even when:
202
205
  Cross-cutting infra (shared types, migration, scaffolding) lands in a foundation phase before the use-case phases. Each subsequent use-case phase consumes that scaffolding.
203
206
 
204
207
  <!-- e2e:start -->
205
- ### Phases creating new UI flow need happy-path E2E
208
+ ### Phases creating a new UI flow ship happy-path E2E — only when e2e coverage was opted into
209
+
210
+ **Gated on the Step 0 group I "E2E coverage" answer, which defaults to NO.** When e2e coverage was **not** opted in (the default), skip this section entirely: phases ship unit + integration tests only, name no e2e spec, and add no `QA_USE_CASES.md` / `pr-screenshots/` machinery. E2E specs make the implementation run take a lot longer, so they are opt-in per plan, not automatic.
206
211
 
207
- Every phase that introduces or substantially changes a user-facing flow (new page, new modal, new wizard step, new gated action) **must** ship a Playwright e2e test covering at least the happy path in the same MR. Follow the [add-e2e-test](../add-e2e-test/SKILL.md) skill: pick the next free `PA###` / `PR###` id, update [QA_USE_CASES.md](QA_USE_CASES.md), add the page object + spec. **No `QA_USE_CASES.md` in the project yet?** Run [create-qa-use-cases](../create-qa-use-cases/SKILL.md) first to bootstrap the doc from this plan + spec — add-e2e-test appends, it doesn't create.
212
+ **When e2e coverage was opted in:** every phase that introduces or substantially changes a user-facing flow (new page, new modal, new wizard step, new gated action) ships a Playwright e2e test covering at least the happy path in the same MR. Follow the [add-e2e-test](../add-e2e-test/SKILL.md) skill: pick the next free `PA###` / `PR###` id, update [QA_USE_CASES.md](QA_USE_CASES.md), add the page object + spec. **No `QA_USE_CASES.md` in the project yet?** Run [create-qa-use-cases](../create-qa-use-cases/SKILL.md) first to bootstrap the doc from this plan + spec — add-e2e-test appends, it doesn't create.
208
213
 
209
- In the phase body, name the spec file path under **Tests → E2E**. If the phase is purely backend (API-only, bot, migration), skip — happy-path E2E only required when the phase reaches the browser.
214
+ In the phase body, name the spec file path under **Tests → E2E**. If the phase is purely backend (API-only, bot, migration), skip — happy-path E2E only applies when the phase reaches the browser.
210
215
 
211
216
  **Capture screenshots on every affected UI**: the e2e spec takes one screenshot per distinct rendered state (landing page, each modal/wizard step, success toast, final state) — not just the final state. Spec writes to Playwright's **default per-test output dir** via `testInfo.outputPath('<id>-<NN>-<view-slug>.png')` (zero-padded step number, kebab-case slug describing what's on screen). Never hard-code `pr-screenshots/` in the spec. After the suite runs, a copy step moves matching files from `test-results/**/` into `pr-screenshots/`. The `pr-screenshots/` directory is gitignored — author drags the files into the PR description in numeric order so reviewers see the journey, not just the destination. See [add-e2e-test](../add-e2e-test/SKILL.md) for the strict filename convention + spec example + copy command.
212
217
  <!-- e2e:end -->
@@ -235,7 +240,7 @@ Tests:
235
240
  - **Unit**: {file path} — {what it covers}.
236
241
  - **Integration**: {file path} — {what it covers, including edge cases user flagged in Step 0, AND flag-off test proving existing callers see no behavior change}.
237
242
  <!-- e2e:start -->
238
- - **E2E** (only when this phase reaches the browser): {e2e/tests/<app>/<id>-<slug>.spec.ts} — happy path covering the new flow. Spec writes screenshots to the Playwright default output dir via `testInfo.outputPath(...)`; post-run copy step moves them into `pr-screenshots/<id>-<step>.png`. Follow [add-e2e-test](../add-e2e-test/SKILL.md).
243
+ - **E2E** (only when e2e coverage was opted into at Step 0 AND this phase reaches the browser): {e2e/tests/<app>/<id>-<slug>.spec.ts} — happy path covering the new flow. Spec writes screenshots to the Playwright default output dir via `testInfo.outputPath(...)`; post-run copy step moves them into `pr-screenshots/<id>-<step>.png`. Follow [add-e2e-test](../add-e2e-test/SKILL.md).
239
244
  <!-- e2e:end -->
240
245
 
241
246
  **Suggested AI model**: {tier choice + why}. See "AI model selection".
@@ -402,7 +407,7 @@ When in doubt, model the plan after a recent example in `ai-plans/` — look for
402
407
  - [ ] **Phase granularity matches the Step 0 answer.** Default (one-use-case-per-phase): at least one phase per spec use-case, no phase implements two use-cases. If bundling was chosen: grouped phases stay MR-sized, one concern, independently mergeable. Cross-cutting scaffolding is its own foundation phase either way.
403
408
  - [ ] Each phase has Goal / Spec use-case / Feature flag (or explicit waiver) / Changes / Tests / Suggested AI model / Reusable skills / Acceptance.
404
409
  <!-- e2e:start -->
405
- - [ ] Every phase introducing a new UI flow has an **E2E happy-path test** in its Tests block, with screenshot output to `pr-screenshots/`.
410
+ - [ ] **If e2e coverage was opted into at Step 0:** every phase introducing a new UI flow has an **E2E happy-path test** in its Tests block, with screenshot output to `pr-screenshots/`. If it was not opted into (default), **no phase carries an e2e spec** and there is no `QA_USE_CASES.md` / `pr-screenshots/` reference.
406
411
  <!-- e2e:end -->
407
412
  - [ ] Feature flag declared in **Guiding Decisions** (key, scope, default, flip-on criterion) **unless** **Guiding Decisions** explicitly justifies "no flag — purely additive surface".
408
413
  - [ ] ≥1 test per gated phase asserts flag-off behavior unchanged.
@@ -11,7 +11,7 @@
11
11
  # Tier *placement* is human/LLM judgement — the job flags drift and proposes
12
12
  # edits, it does not blindly reassign tiers. See scripts/check-ai-models.mjs.
13
13
  schema_version: 1
14
- last_verified: 2026-06-22
14
+ last_verified: 2026-07-13
15
15
 
16
16
  # Drift is checked against a free, no-key community aggregator (models.dev,
17
17
  # vendor-keyed with release dates + pricing), cross-checked against LiteLLM's
@@ -37,10 +37,10 @@ tiers:
37
37
  anthropic:
38
38
  - id: claude-haiku-4-5
39
39
  openai:
40
- - id: gpt-5-nano
41
- note: fall back to gpt-5-mini if file has any branching logic
40
+ - id: gpt-5.6-luna
41
+ note: optimized for cost-sensitive workloads
42
42
  google:
43
- - id: gemini-2.5-flash-lite
43
+ - id: gemini-3.1-flash-lite
44
44
 
45
45
  - tier: 2
46
46
  label: standard pattern application
@@ -51,13 +51,13 @@ tiers:
51
51
  models:
52
52
  anthropic:
53
53
  - id: claude-haiku-4-5
54
- note: with iteration; step up to claude-sonnet-4-6 if phase touches >3 files
55
- - id: claude-sonnet-4-6
54
+ note: with iteration; step up to claude-sonnet-5 if phase touches >3 files
55
+ - id: claude-sonnet-5
56
56
  note: step-up target when phase touches >3 files
57
57
  openai:
58
58
  - id: gpt-5-mini
59
59
  google:
60
- - id: gemini-2.5-flash
60
+ - id: gemini-3.5-flash
61
61
 
62
62
  - tier: 3
63
63
  label: multi-file orchestration, business logic, SQL views
@@ -68,11 +68,10 @@ tiers:
68
68
  covering concurrency edges.
69
69
  models:
70
70
  anthropic:
71
- - id: claude-sonnet-4-6
71
+ - id: claude-sonnet-5
72
72
  openai:
73
- - id: gpt-5
73
+ - id: gpt-5.6-terra
74
74
  google:
75
- - id: gemini-2.5-pro
76
75
  - id: gemini-3-pro
77
76
  note: stronger code recall
78
77
 
@@ -84,15 +83,11 @@ tiers:
84
83
  tuning slow query against partitioned hot table, debugging heisenbug.
85
84
  models:
86
85
  anthropic:
87
- - id: claude-opus-4-7
86
+ - id: claude-opus-4-8
88
87
  note: "[1m] 1M-context variant for large codebases"
89
88
  openai:
90
- - id: gpt-5
91
- note: with extended thinking
92
- - id: o3
93
- note: pure reasoning
94
- - id: o4
95
- note: pure reasoning
89
+ - id: gpt-5.6-sol
90
+ note: Frontier model for complex professional work
96
91
  google:
97
92
  - id: gemini-3-pro
98
93
  note: with thinking
@@ -19,6 +19,11 @@ git -C <WORKROOT> checkout plan/{plan-id-kebab}/phase-{prev.id}
19
19
  git -C <WORKROOT> checkout -b plan/{plan-id-kebab}/phase-{phase.id}
20
20
  git -C <WORKROOT> push -u origin plan/{plan-id-kebab}/phase-{phase.id}
21
21
  ```
22
+
23
+ **PR base per phase** (the `base` field written into the prs-context frontmatter — this is what `gh pr create --base` / `glab mr create --target-branch` opens the PR against; getting it wrong makes every stacked PR target `<BASE_BRANCH>` instead of its parent phase):
24
+
25
+ - **First executed phase** → `base = <BASE_BRANCH>`.
26
+ - **Subsequent phases** → `base = plan/{plan-id-kebab}/phase-{prev.id}` (the previous phase's branch, **not** `<BASE_BRANCH>`). The PR must open against its parent phase so the diff shows only this phase's changes and the stack reviews cleanly.
22
27
  <!-- block-end: BRANCH_NAMING -->
23
28
 
24
29
  <!-- block-begin: PER_PHASE_COMMIT -->
@@ -39,7 +39,7 @@ Two project-level signals decide the actual behavior:
39
39
 
40
40
  When `generate_inline_comments = false`: skip this step. The file's `# Comments` block stays empty.
41
41
 
42
- 4. **Write the prs-context file** at {{PRS_CONTEXT_FILE_PATH}}, following [resources/prs-context-template.md](../../prs-context-template.md). Frontmatter: `plan_id`, `feature_name`, `phase_id`, `phase_title`, `branch`, `base`, `created_at`, `status: pending`, empty `pr_url`. Body sections: `# Title` (single-line PR title), `# Description` (Markdown body — uses the project's PR template structure from step 2 when one exists), `# Comments` (YAML list of `{file, start_line, end_line?, side, body}` — empty list when comments are off).
42
+ 4. **Write the prs-context file** at {{PRS_CONTEXT_FILE_PATH}}, following [resources/prs-context-template.md](../../prs-context-template.md). Frontmatter: `plan_id`, `feature_name`, `phase_id`, `phase_title`, `branch`, `base`, `created_at`, `status: pending`, empty `pr_url`. **`base` is the branch the PR opens against — resolve it per the commit strategy, never default it to `<BASE_BRANCH>` blindly:** for stacked branches only the first executed phase bases on `<BASE_BRANCH>`; every subsequent phase bases on the **previous phase's branch** (see the PR-base rule under the {{BRANCH_PUSH_HEADING}} step above). For a single plan-level PR (modular / one-PR strategies) `base = <BASE_BRANCH>`. Body sections: `# Title` (single-line PR title), `# Description` (Markdown body — uses the project's PR template structure from step 2 when one exists), `# Comments` (YAML list of `{file, start_line, end_line?, side, body}` — empty list when comments are off).
43
43
 
44
44
  5. **Confirm `.vinta-ai-workflows/prs-context/` is in `.gitignore`.** [vinta-install-ai-tools-setup](../../../vinta-install-ai-tools-setup/SKILL.md) runs the multi-vendor setup script which appends `.vinta-ai-workflows/prs-context/` on its first invocation. If an older bootstrap missed it, append it now.
45
45
 
@@ -53,12 +53,12 @@ Parse once, reuse for every phase:
53
53
  Skip this question entirely when `foundation_skills.prepare-worktree` is `disabled` in `.vinta-ai-workflows.yaml`: record `run_options.use_worktree = false`; surface a one-line note that worktree isolation is available if the team opts in via [vinta-sync-ai-tools](../../skills/vinta-sync-ai-tools/SKILL.md).
54
54
 
55
55
  d. **Full test suite each phase?** *"Each phase's outer gate always runs the repo-wide type/build gate. For tests, do you want the quick path (run only the scoped suite covering the apps/files that phase touched — faster phases) or the full repo test suite every phase (slower, but guards against regressions in untouched code)? New tests still pass individually in the inner loop either way."* Options: `Quick — scoped tests only each phase (default)`, `Full — run the whole test suite each phase`. Default = value of `run_options.implement-plan.full_test_suite` in `.vinta-ai-workflows.yaml` (`Quick`/false when unset). Records `run_options.full_test_suite` (`true` only for the `Full` answer).
56
-
56
+ {{E2E_RUN_OPTION_QUESTION}}
57
57
  PR opening itself is **not** asked here — it's governed by the project's PR creation policy captured at bootstrap (see `{{PR_POLICY_BLOCK}}` above). When that policy = "agents create PRs", the {{INTEGRATE_PHASE_DISPATCH}} step always opens the PR via [open-pr.sh](../open-pr-from-context/scripts/open-pr.sh) regardless of the comment opt-in.{{COMMIT_STRATEGY_STEP0_QUESTION}}
58
58
 
59
- 5. **Confirm with user before starting.** Show plan path, phase list (id + title + tier + cross-repo/flag-removal flags + e2e flag), phases this skill will execute vs defer, {{BRANCH_NAMING_PATTERN_SUMMARY}}, captured `run_options.pause_between_phases` + `run_options.generate_inline_comments` + `run_options.use_worktree` + `run_options.full_test_suite`{{COMMIT_STRATEGY_CONFIRM_NOTE}}{{PR_REMINDER_LINE}}.
59
+ 5. **Confirm with user before starting.** Show plan path, phase list (id + title + tier + cross-repo/flag-removal flags + e2e flag), phases this skill will execute vs defer, {{BRANCH_NAMING_PATTERN_SUMMARY}}, captured `run_options.pause_between_phases` + `run_options.generate_inline_comments` + `run_options.use_worktree` + `run_options.full_test_suite`{{E2E_RUN_OPTION_CONFIRM}}{{COMMIT_STRATEGY_CONFIRM_NOTE}}{{PR_REMINDER_LINE}}.
60
60
 
61
- Wait for "go". After that, the per-phase pause behavior follows `run_options.pause_between_phases`. Inline-comment drafting follows `run_options.generate_inline_comments`. Worktree isolation follows `run_options.use_worktree`. Outer-gate test scope follows `run_options.full_test_suite`.{{COMMIT_STRATEGY_STEP0_TRAILER}}
61
+ Wait for "go". After that, the per-phase pause behavior follows `run_options.pause_between_phases`. Inline-comment drafting follows `run_options.generate_inline_comments`. Worktree isolation follows `run_options.use_worktree`. Outer-gate test scope follows `run_options.full_test_suite`.{{E2E_RUN_OPTION_TRAILER}}{{COMMIT_STRATEGY_STEP0_TRAILER}}
62
62
 
63
63
  <!-- include: partials/worktree-seam.md#WORKROOT_RESOLUTION -->
64
64
 
@@ -70,13 +70,13 @@ For each phase that's `not is_cross_repo and not is_flag_removal`, in plan order
70
70
 
71
71
  ### 1a. Implement
72
72
 
73
- Invoke [implement-phase](../implement-phase/SKILL.md), passing the phase record, the plan-level decisions (**Goals + Non-goals**, **Guiding Decisions**, the relevant **Data Model Changes** subsection), the prior-phase tracking summaries, `run_options.full_test_suite`, and `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER`. It returns the implementer's report.
73
+ Invoke [implement-phase](../implement-phase/SKILL.md), passing the phase record, the plan-level decisions (**Goals + Non-goals**, **Guiding Decisions**, the relevant **Data Model Changes** subsection), the prior-phase tracking summaries, `run_options.full_test_suite`{{E2E_RUN_OPTION_TRACKING}}, and `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER`. It returns the implementer's report.
74
74
 
75
75
  **Model escalation.** implement-phase escalates one tier + retries once on a clear capability gap. After Tier 4 fails, it stops and hands back the failure — update tracking with `❌`, post the report to the user, ask how to proceed. Don't silently re-derive tier.
76
76
 
77
77
  ### 1b. Review
78
78
 
79
- Invoke [review-phase](../review-phase/SKILL.md) against the phase diff, passing the phase body to walk, `WORKROOT`, `main_checkout`, `run_options.full_test_suite`, and the `reviewer` / `fixer` agent types. It loops its three layers + fix loop until clean, then returns `PASS` (or the surfaced findings). Do not proceed to integrate while any layer is red.
79
+ Invoke [review-phase](../review-phase/SKILL.md) against the phase diff, passing the phase body to walk, `WORKROOT`, `main_checkout`, `run_options.full_test_suite`{{E2E_RUN_OPTION_TRACKING}}, and the `reviewer` / `fixer` agent types. It loops its three layers + fix loop until clean, then returns `PASS` (or the surfaced findings). Do not proceed to integrate while any layer is red.
80
80
 
81
81
  ### 1c. Integrate
82
82
 
@@ -86,7 +86,7 @@ Invoke {{INTEGRATE_PHASE_DISPATCH}}, passing `WORKROOT` / `BASE_BRANCH`, the `{{
86
86
 
87
87
  Tracking lives at `{{PLAN_DIR}}/TRACKING_{plan-id}.md`. Commit on the **current** phase's branch — deletion in [Step 2](#step-2--final-report).
88
88
 
89
- Schema: feature-name, plan path, started/last-updated dates, optional feature-flag info, **run options** (`pause_between_phases`, `generate_inline_comments`, `full_test_suite`, `use_worktree`, `worktree_path`, `worktree_branch`, `worktree_summary`, `sandbox_tier` — last four only when `use_worktree = true`), {{TRACKING_BRANCH_FIELD}}, completed-phases (with status, model{{TRACKING_PHASE_BRANCH_FIELD}}, e2e+screenshots if any, 5–15 line summary), current phase, remaining phases, deferred phases.
89
+ Schema: feature-name, plan path, started/last-updated dates, optional feature-flag info, **run options** (`pause_between_phases`, `generate_inline_comments`, `full_test_suite`{{E2E_RUN_OPTION_TRACKING}}, `use_worktree`, `worktree_path`, `worktree_branch`, `worktree_summary`, `sandbox_tier` — last four only when `use_worktree = true`), {{TRACKING_BRANCH_FIELD}}, completed-phases (with status, model{{TRACKING_PHASE_BRANCH_FIELD}}, e2e+screenshots if any, 5–15 line summary), current phase, remaining phases, deferred phases.
90
90
 
91
91
  The conductor writes this from the git diff + the agent's summary — not from the agent's narration.
92
92
 
@@ -162,7 +162,7 @@ After all executable phases complete:
162
162
  - **Feature flags = gates, not toggles for tests.**
163
163
  - **Never remove a feature flag from this skill.**
164
164
  - **Stop on Tier-4 failure.**
165
- - **Honor opt-in flags.** `run_options.pause_between_phases` controls the [Per-phase pause gate](#1f-per-phase-pause-gate-opt-in); `run_options.generate_inline_comments` controls whether {{INTEGRATE_PHASE_DISPATCH}} drafts inline comments (always writes the file when that step runs at all — empty comments when off); `run_options.use_worktree` controls whether the [Resolve WORKROOT step](#step-05--resolve-workroot) provisions a worktree and thus what `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER` resolve to; `run_options.full_test_suite` controls the outer-gate test scope ([Implement](#1a-implement) + [Review](#1b-review) Layer 1) — scoped suite by default, full repo suite when `true`.
165
+ - **Honor opt-in flags.** `run_options.pause_between_phases` controls the [Per-phase pause gate](#1f-per-phase-pause-gate-opt-in); `run_options.generate_inline_comments` controls whether {{INTEGRATE_PHASE_DISPATCH}} drafts inline comments (always writes the file when that step runs at all — empty comments when off); `run_options.use_worktree` controls whether the [Resolve WORKROOT step](#step-05--resolve-workroot) provisions a worktree and thus what `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER` resolve to; `run_options.full_test_suite` controls the outer-gate test scope ([Implement](#1a-implement) + [Review](#1b-review) Layer 1) — scoped suite by default, full repo suite when `true`.{{E2E_RUN_OPTION_RULE}}
166
166
  - **One worktree per plan run.** When `use_worktree = true`, provision once in the [Resolve WORKROOT step](#step-05--resolve-workroot) and reuse for every phase. Never spawn a second worktree mid-plan; never silently fall back to the main checkout on prepare-worktree failure (ask the user).
167
167
  - **Don't auto-tear-down the worktree.** Step 2 surfaces the teardown command; the user runs it when ready.
168
168
  - **`WORKROOT` is resolved once, used everywhere.** Every sub-skill takes `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER` as data — no step re-derives worktree state. OS-level prevention (sandbox wrap in implement-phase when `SANDBOX_TIER = enforced`) plus the review-phase stray-write backstop keep main-checkout writes out; see [worktree-seam](../implement-phase/SKILL.md#3-spawn-the-subagent).
@@ -6,7 +6,7 @@ feature_name: <FEATURE_NAME> # UPPERCASE_WITH_UNDERSCORES, matches p
6
6
  phase_id: <phase-id> # e.g. "1", "4a"
7
7
  phase_title: <phase title> # verbatim from the plan's Phased Rollout section
8
8
  branch: plan/<feature-kebab>/phase-<id> # branch the PR opens from
9
- base: <main | plan/<feature-kebab>/phase-<prev-id>> # target branch for the PR
9
+ base: <main | plan/<feature-kebab>/phase-<prev-id>> # PR target branch. Stacked: FIRST phase = default branch; every LATER phase = the PREVIOUS phase's branch (not the default branch). Modular / single-PR: default branch.
10
10
  created_at: <ISO 8601 timestamp>
11
11
  status: pending # `pending` until published; `published` after CLI run
12
12
  pr_url: # set by open-pr-from-context after publishing