vinta-ai-workflows 0.7.0-alpha2 → 0.7.0-alpha21

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 (36) hide show
  1. package/CHANGELOG.md +1704 -3
  2. package/README.md +16 -0
  3. package/package.json +11 -9
  4. package/schemas/README.md +9 -2
  5. package/schemas/intervention.v1.schema.json +170 -0
  6. package/schemas/postmortem.v1.schema.json +268 -3
  7. package/schemas/prs-context-frontmatter.v1.schema.json +18 -7
  8. package/schemas/vinta-ai-workflows-config.v1.schema.json +12 -0
  9. package/schemas/workflow.v1.schema.json +388 -24
  10. package/skills/vinta-analyze-codebase/SKILL.md +1 -0
  11. package/skills/vinta-bootstrap-ai-tools/SKILL.md +18 -2
  12. package/skills/vinta-derive-skills/SKILL.md +5 -0
  13. package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh +0 -0
  14. package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +100 -50
  15. package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/resources/ai-models.yaml +9 -10
  16. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/SKILL.md +10 -2
  17. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/scripts/claude-worktree-write-guard.py +0 -0
  18. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/scripts/gen-claude-sandbox-settings.sh +0 -0
  19. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/scripts/gen-compose-worktree-override.sh +0 -0
  20. package/skills/vinta-derive-skills/resources/foundation-skills/prepare-worktree/scripts/sandbox-run.sh +0 -0
  21. package/skills/vinta-derive-skills/resources/plan-execution/README.md +11 -0
  22. package/skills/vinta-derive-skills/resources/plan-execution/partials/commit-strategy/stacked.md +18 -0
  23. package/skills/vinta-derive-skills/resources/plan-execution/partials/dispatched-agent.md +31 -0
  24. package/skills/vinta-derive-skills/resources/plan-execution/partials/implementer-prompt.md +2 -0
  25. package/skills/vinta-derive-skills/resources/plan-execution/partials/parallel-lanes.md +10 -3
  26. package/skills/vinta-derive-skills/resources/plan-execution/partials/pr-context.md +3 -1
  27. package/skills/vinta-derive-skills/resources/plan-execution/shell/amend-plan-template.md +3 -0
  28. package/skills/vinta-derive-skills/resources/plan-execution/shell/implement-phase-template.md +3 -0
  29. package/skills/vinta-derive-skills/resources/plan-execution/shell/implement-plan-template.md +7 -3
  30. package/skills/vinta-derive-skills/resources/plan-execution/shell/integrate-phase-template.md +2 -1
  31. package/skills/vinta-derive-skills/resources/plan-execution/shell/review-phase-template.md +3 -0
  32. package/skills/vinta-derive-skills/resources/prs-context-template.md +5 -4
  33. package/skills/vinta-install-ai-tools-setup/SKILL.md +28 -1
  34. package/skills/vinta-install-ai-tools-setup/resources/setup-ai-tools.mjs +0 -0
  35. package/skills/vinta-sync-ai-tools/SKILL.md +2 -1
  36. package/skills/vinta-update-project-skills/SKILL.md +1 -0
@@ -20,7 +20,7 @@ The plan's **Phased Rollout** section opens with an **Execution graph** table an
20
20
  - **A phase assigned to a reviewer, or a reviewer that also takes phases** → stop and ask. The two roles are disjoint precisely so that an agent reviewing its own work is unrepresentable.
21
21
  - **A reviewer below every phase on the plan** → stop and ask. A reviewer's tier is a floor too, so one below the cheapest phase would never be picked.
22
22
  - **No reviewer at all** → not an error. Reviews fall back to `agent_models.reviewer`, cold, one session per phase. Say so once in the pool report so nobody reads the roster and assumes otherwise.
23
- - **A wave the roster cannot staff** → warn. Sort the wave's assigned tiers and the roster's tiers, compare one for one: a wave of two Tier 3 phases needs two members at Tier 3 or above, and a junior on the roster does not help because the floor forbids handing them one. Such a wave still runs — it serializes — so say so now rather than letting it look like a slow machine later.
23
+ - **A wave the roster cannot staff** → warn. Sort the wave's assigned tiers and the roster's tiers, compare one for one: a wave of two Tier 3 phases needs two members at Tier 3 or above, and a Tier 1 member on the roster does not help because the floor forbids handing them one. Such a wave still runs — it serializes — so say so now rather than letting it look like a slow machine later.
24
24
  - **A plan with no Crew table at all** is a legacy plan. Read each phase's `**Suggested AI model**:` tier instead and skip every check above.
25
25
  6. **Record the resolved graph and the roster** in `run.md` (see [Update tracking](#1d-update-tracking)) so a resume rebuilds the identical schedule and the identical staffing without re-asking anything.
26
26
 
@@ -124,9 +124,16 @@ The budget is an **integration-level** setting, not either phase's `max_fix_roun
124
124
 
125
125
  **Confirming a fix requires reading the files, not asking git.** `git add` clears a path's unmerged flag whether or not `<<<<<<<` is still sitting in it, so git cannot tell you whether the fixer actually resolved anything. Scan the conflicted paths for conflict markers before committing the merge. Skip this and a fixer that did nothing produces a merge commit full of markers that passes straight into the wave branch.
126
126
 
127
- ### One PR per phase, based on the phase's base
127
+ ### PRs: one per phase, plus what it takes to reach `<BASE_BRANCH>`
128
128
 
129
129
  The PR `base` written into the prs-context frontmatter is the phase's **computed `base_branch`** — `<BASE_BRANCH>`, a single dependency's branch, or the `integ-{P.id}` branch. Never `<BASE_BRANCH>` for a phase that has dependencies; a wrong base makes the PR diff include every upstream phase and the review is unusable.
130
+
131
+ Phase PRs are review units, and on their own they do not land the plan. Under a per-phase PR strategy the conductor also opens:
132
+
133
+ - **An integration PR per `integ-{P.id}` branch**, into `<BASE_BRANCH>`, just before `P`'s own PR. Without it `P`'s PR targets a branch nothing targets, and nothing stacked on `P` can reach `<BASE_BRANCH>`.
134
+ - **A plan PR at run end**, from the final `wave-{N}` branch into `<BASE_BRANCH>`. It is the only branch carrying the conflict resolutions made during wave merges, so it is merged last whichever way the plan lands. Its description lists every phase and integration PR in merge order.
135
+
136
+ The commit strategy's PR-open timing says which files to write and when.
130
137
  <!-- block-end: LANE_TOPOLOGY -->
131
138
 
132
139
  <!-- block-begin: LANE_SCHEDULER -->
@@ -169,7 +176,7 @@ while PENDING or RUNNING:
169
176
  `claim_agent(p)` is the staffing half of a dispatch, and it runs **before** the lane is taken. A lane is disk; who is holding it is what the phase costs and whether the result is any good.
170
177
 
171
178
  1. **The member the plan assigned, if they are free.** The common case, and the one the plan's cost estimate is written against.
172
- 2. **Otherwise the cheapest free member at or above that member's tier.** A wave should not serialize behind one agent when a qualified peer is idle. Reach for the *cheapest* qualified one, not the best available — covering for a peer must not quietly promote the phase to the top tier, or a busy wave silently runs every mid-tier phase on the senior's model.
179
+ 2. **Otherwise the cheapest free member at or above that member's tier.** A wave should not serialize behind one agent when a qualified peer is idle. Reach for the *cheapest* qualified one, not the best available — covering for a peer must not quietly promote the phase to the top tier, or a busy wave silently runs every Tier 2 phase on the Tier 4 member's model.
173
180
  3. **Otherwise nobody, and the phase waits** — even with a lane free. This is the one place staffing costs throughput, and it is deliberate: a phase run below its tier does not fail cleanly. It produces plausible code that fails review two rounds later, by which point nothing points back at the staffing decision.
174
181
 
175
182
  An implementer is held for the **whole phase**, not one turn of it: the fixer answering a review finding is the implementer continuing its own session, so handing the phase to someone else mid-flight would hand it to an agent with no session to continue. Release it when the phase settles.
@@ -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`. **`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).
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 a phase's PR bases on its dependency-derived `<phase.base_branch>` — `<BASE_BRANCH>` only for a phase with no dependencies (see the PR-base rule under the {{BRANCH_PUSH_HEADING}} step above); an integration PR (`kind: integration`) and the plan PR (`kind: plan`) base on `<BASE_BRANCH>`. 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. **Deslop the prose.** Run the `deslop-comments` skill ([deslop-comments](../deslop-comments/SKILL.md)) over the file you just wrote, passing {{PRS_CONTEXT_FILE_PATH}} as the explicit scope. `# Title`, the `# Description` body, and every `# Comments` `body` must read as Simple English: one idea per sentence, current behavior stated directly instead of "not X" framing, and no AI-slop vocabulary (`gate`, `guard`, `backstop`, `surface`, `leverage`, `plumb`, `canonical`, …). Keep precise domain terms, and keep the project's PR-template structure intact — section headings, `<!-- HTML comment -->` placeholders, and checklist lines stay exactly as step 2 wrote them. This pass rewrites prose only: it never touches the frontmatter, the section layout, or which file and lines a comment targets. Do it before `open-pr.sh` runs, since the published PR body and comments come straight from this file.
45
45
 
@@ -59,5 +59,7 @@ Two project-level signals decide the actual behavior:
59
59
 
60
60
  When policy = "branches only": **don't run the script.** File stays `status: pending`.
61
61
 
62
+ {If integrations.pr-review-canvas = enabled in `.vinta-ai-workflows.yaml`:} **Review canvas.** After exit `0` or `1`, the PR is up. Generate its review canvas with the `pr-review-canvas` skill ([pr-review-canvas](../pr-review-canvas/SKILL.md)). Pass the PR number from the end of `pr_url` (`…/pull/<n>` or `…/merge_requests/<n>`), as in `/pr-review-canvas <n>`. Run it again each time this step re-runs `open-pr.sh` on the same PR, for example after each phase under one plan-level PR. The tool updates the canvas incrementally. The skill posts the canvas as a PR comment unless the project's `pr-review.config.yml` turns sharing off. Add its local review URL and the comment link to the user update. A canvas that fails never fails the phase. Report the skill's error, and point at `pr-review doctor` when the error suggests setup. When the `pr-review-canvas` skill is not installed, say so once, point at `vinta-install-ai-tools-setup`, and skip.
63
+
62
64
  8. **Skill wrapper** — [open-pr-from-context](../open-pr-from-context/SKILL.md) is available for ad-hoc invocation (after the run, on a different machine, etc.). The orchestrator can call the script directly here; the skill is for humans.
63
65
  <!-- block-end: PR_CONTEXT -->
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: amend-plan
3
3
  description: Adjust an existing implementation plan in `{{PLAN_DIR}}/` after implementation has started or finished. Updates the plan file (revising existing phases or appending new ones), then for each affected phase that was already implemented adjusts its commits (`git commit --amend` or new commits) on the phase branch, force-pushes the rewritten branch, rebases every phase branch in the rewritten phase's dependency closure, force-pushes each, and refreshes the PR-context files. Use when the user says "amend the plan", "update phase N", "add a phase to plan X", "the spec changed, fix the plan", or "rewrite the implementation for phase N". NOT for one-off changes to a single file unrelated to a plan; use the regular implement skill for that. {{PR_POLICY_DESCRIPTION}}
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Amend Plan
@@ -9,6 +10,8 @@ Revise a plan in [`{{PLAN_DIR}}/`]({{PLAN_DIR}}/) after work has begun. Companio
9
10
 
10
11
  The flow is destructive (force-push). Every modification is gated on user confirmation. Default disposition for any ambiguous case is "stop and ask" — never force-push without an explicit per-branch `Confirm` from the user.{{COMMIT_STRATEGY_REFUSAL_BLOCK}}
11
12
 
13
+ <!-- include: partials/dispatched-agent.md#CONDUCTOR_ENTRY_GUARD -->
14
+
12
15
  ## Working assumptions
13
16
 
14
17
  - Repo: {{PROJECT_NAME}} ({{STACK_SUMMARY}}). Conventions: [AGENTS.md](../../../AGENTS.md).
@@ -1,12 +1,15 @@
1
1
  ---
2
2
  name: implement-phase
3
3
  description: Internal execution step of [implement-plan] / [amend-plan] — NOT a standalone entry point. Given one already-classified plan phase plus the resolved `WORKROOT` / `BASE_BRANCH` / `SANDBOX_TIER`, it composes a token-efficient implementer prompt, picks the model from the phase's own suggestion, and spawns exactly one implementer subagent, returning that agent's report. Do not invoke directly for ad-hoc edits or in response to a user's raw feature request; the conductor invokes it once per executable phase in {{PROJECT_NAME}}.
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Implement one phase
7
8
 
8
9
  Execution unit invoked by [implement-plan](../implement-plan/SKILL.md) (and by [amend-plan](../amend-plan/SKILL.md) for `amend-existing` rewrites). One phase in → one implementer report out. This skill does **not** review, branch, push, or open PRs — those are [review-phase](../review-phase/SKILL.md) and [integrate-phase](../integrate-phase/SKILL.md). It also does **not** decide whether a phase runs — the conductor already filtered cross-repo / flag-removal phases.
9
10
 
11
+ <!-- include: partials/dispatched-agent.md#CONDUCTOR_ENTRY_GUARD -->
12
+
10
13
  ## Inputs (passed by the conductor as data — this skill re-derives none of them)
11
14
 
12
15
  - `phase` record: `{ id, title, goal, body, spec_use_case, depends_on, wave, base_branch, crew_member, crew_tier, suggested_model_tier, reusable_skills, has_e2e, acceptance }`. `crew_member` / `crew_tier` come from the phase's `**Assigned to**:` line and the plan's **Crew** table; `suggested_model_tier` is the legacy path and is set only on a plan with no roster. Exactly one of the two is populated.
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: implement-plan
3
3
  description: Execute a phased implementation plan from `{{PLAN_DIR}}/` in {{PROJECT_NAME}} by orchestrating one subagent per phase (using whatever model the plan suggests and the runtime supports), running independent phases concurrently in their own worktree lanes when the plan's dependency graph allows it, pushing one branch per phase to {{CODE_HOST}}, and tracking progress. Use when the user says "implement the plan", "execute plan X", "start implementation", "run phase N of plan Y", "implement {feature} plan", or asks to drive a `*_IMPLEMENTATION_PLAN.md` file phase-by-phase. NOT for one-off changes, single-file edits, or work that doesn't have an existing plan. {{PR_POLICY_DESCRIPTION}}
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Implement Plan
@@ -17,6 +18,8 @@ The conductor itself owns only: plan parsing, the dependency graph, phase classi
17
18
 
18
19
  Execution counterpart to [plan-feature](../plan-feature/SKILL.md). Plan = contract; this skill = build pipeline.
19
20
 
21
+ <!-- include: partials/dispatched-agent.md#CONDUCTOR_ENTRY_GUARD -->
22
+
20
23
  ## Working assumptions
21
24
 
22
25
  - Repo: {{PROJECT_NAME}} ({{STACK_SUMMARY}}). Conventions: [AGENTS.md](../../../AGENTS.md).
@@ -178,9 +181,10 @@ After the scheduler loop exits — every executable phase is `done`, `failed`, o
178
181
 
179
182
  1. **Build the final wave branch** if the last completed wave has no branch yet, so one branch carries the whole plan.
180
183
  2. **Delete the `TRACKING_{plan-id}/` directory** (`git rm -r`) on that final wave branch, in one commit. The plan file stays.
181
- 3. Send the user a final summary: {{FINAL_REPORT_BRANCH_SUMMARY}}; the **wave branches** in order, and which phase branches merged into each; phases that **failed** and the dependents each one **blocked**; for UI-flow phases — list of `pr-screenshots/` files (if applicable); deferred phases (cross-repo + flag-removal); next steps for the human. When `run_options.use_worktree = true`: include **every lane's** path + branch + summary file path + teardown command (`git worktree remove <path>` + the per-engine drop-db / `docker compose -p <project> down -v` lines from that lane's `<worktree_summary>`), and the integration worktree's. Do NOT auto-run teardown — the user may still want a lane to debug review feedback or land follow-ups, and a failed phase's lane is the only place its state survives.
184
+ 3. **Open the plan PR** (per-phase PR strategies only — skip when the commit strategy already keeps one plan-level PR). Only when every phase is `done`: a plan with failed or blocked phases is not ready to land, so list the gap instead. Push the final wave branch, write `.vinta-ai-workflows/prs-context/{feature-kebab}/plan.md` with `kind: plan`, `branch: plan/{plan-id-kebab}/wave-{N}` (the final wave), `base: <BASE_BRANCH>`, and a `# Description` listing every phase and integration PR in merge order (wave by wave; plan order inside a wave; each integration PR right before its phase PR), with the two ways to land it — merge this PR alone, or merge the listed PRs in order and this one last — and the rule to use merge commits, not squash. Run `open-pr.sh` on it under the same PR policy as the phase PRs. This is the PR that lands the plan; a run that ends without it leaves the user to rebuild the merges by hand.
185
+ 4. Send the user a final summary: the **plan PR URL** first (or why it was not opened — failed phases, PR policy, missing deps); {{FINAL_REPORT_BRANCH_SUMMARY}}; the **wave branches** in order, and which phase branches merged into each; phases that **failed** and the dependents each one **blocked**; for UI-flow phases — list of `pr-screenshots/` files (if applicable); deferred phases (cross-repo + flag-removal); next steps for the human. When `run_options.use_worktree = true`: include **every lane's** path + branch + summary file path + teardown command (`git worktree remove <path>` + the per-engine drop-db / `docker compose -p <project> down -v` lines from that lane's `<worktree_summary>`), and the integration worktree's. Do NOT auto-run teardown — the user may still want a lane to debug review feedback or land follow-ups, and a failed phase's lane is the only place its state survives.
182
186
  {{FINAL_REPORT_PR_NOTE}}
183
- 4. Flag-removal phase deferred → end with `/schedule` offer for the dedicated flag-removal skill.
187
+ 5. Flag-removal phase deferred → end with `/schedule` offer for the dedicated flag-removal skill.
184
188
 
185
189
  ## Important rules
186
190
 
@@ -229,4 +233,4 @@ After the scheduler loop exits — every executable phase is `done`, `failed`, o
229
233
  - [ ] Wave branch built + `waves/wave-{N}.md` written when this phase completed its wave; merge conflicts resolved by a fixer, never by the conductor, and the outer gate re-run on the merged tree.
230
234
  - [ ] One-paragraph user update sent per phase completion (PR URL or pending-file path included; lane named; what the scheduler picked up next).
231
235
  - [ ] If `run_options.pause_between_phases = true`: stopped dispatching, let in-flight lanes drain, prompted user (`Continue` / `Pause` / `Stop`); honored answer. Else: next ready phase dispatched immediately.
232
- - [ ] On run end: final wave branch built; tracking directory deleted; final summary lists wave + phase branches{{FINAL_CHECKLIST_PR_NOTE}}, failed phases with the dependents they blocked, every lane's teardown command; any `status: pending` PR-context files listed with publish command; `/schedule` offer for flag-removal if applicable.
236
+ - [ ] On run end: final wave branch built; tracking directory deleted; plan PR opened (final wave branch → `<BASE_BRANCH>`, every phase + integration PR listed in merge order) when every phase is done and the strategy opens per-phase PRs; final summary leads with the plan PR URL and lists wave + phase branches{{FINAL_CHECKLIST_PR_NOTE}}, failed phases with the dependents they blocked, every lane's teardown command; any `status: pending` PR-context files listed with publish command; `/schedule` offer for flag-removal if applicable.
@@ -1,6 +1,7 @@
1
1
  ---
2
2
  name: {{INTEGRATE_PHASE_NAME}}
3
3
  description: Internal integration step of [implement-plan] — NOT a standalone entry point. Pushes one reviewed phase along {{PROJECT_NAME}}'s commit strategy and opens (or updates) its PR through the prs-context file + bundled open-pr.sh — the only PR-creation path. The conductor passes the resolved `WORKROOT` / `BASE_BRANCH` and the PR / inline-comment policy; do not invoke directly to push arbitrary work.
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Integrate one phase
@@ -28,4 +29,4 @@ Invoked by [implement-plan](../implement-plan/SKILL.md) after [review-phase](../
28
29
 
29
30
  ## Output
30
31
 
31
- Return to the conductor: the branch pushed, and the PR-context file path with its `status` (`published` + `pr_url` when `open-pr.sh` ran; `pending` otherwise) plus the publish command when `pending`.
32
+ Return to the conductor: the branch pushed (plus the `integ-` branch when one was pushed), and each PR-context file path written — the integration file first when there is one — with its `status` (`published` + `pr_url` when `open-pr.sh` ran; `pending` otherwise) plus the publish command when `pending`.
@@ -1,12 +1,15 @@
1
1
  ---
2
2
  name: review-phase
3
3
  description: Internal review gate of [implement-plan] / [amend-plan] / [systematic-debugging] — NOT a standalone entry point. Runs the mandatory three-layer review (mechanical checks, plan-compliance walkthrough, independent reviewer subagent) plus the fix loop against one phase's diff in {{PROJECT_NAME}}, spawning an independent reviewer, sending findings back to the phase's own implementer to fix, and looping until all three layers are clean. The invoking conductor passes the diff, the phase body to walk against, and the resolved `WORKROOT`; do not invoke directly to "review my code" — use the project's standard code-review path for that.
4
+ disable-model-invocation: true
4
5
  ---
5
6
 
6
7
  # Review one phase
7
8
 
8
9
  The single review implementation shared by every plan-execution conductor: [implement-plan](../implement-plan/SKILL.md) (after an implementer runs), [amend-plan](../amend-plan/SKILL.md) (after a rewrite), and [systematic-debugging](../systematic-debugging/SKILL.md) (against the fix diff). Read-only orchestration: this skill **never edits code** — every issue becomes a fix-up subagent task.
9
10
 
11
+ <!-- include: partials/dispatched-agent.md#CONDUCTOR_ENTRY_GUARD -->
12
+
10
13
  ## Inputs (passed by the conductor)
11
14
 
12
15
  - The phase diff (on the current branch inside `WORKROOT`).
@@ -3,10 +3,11 @@
3
3
  schema_version: 1 # see schemas/prs-context-frontmatter.v1.schema.json
4
4
  plan_id: <plan-id> # filename feature portion, kebab-case
5
5
  feature_name: <FEATURE_NAME> # UPPERCASE_WITH_UNDERSCORES, matches plan/spec
6
- phase_id: <phase-id> # e.g. "1", "4a"
7
- phase_title: <phase title> # verbatim from the plan's Phased Rollout section
8
- branch: plan/<feature-kebab>/phase-<id> # branch the PR opens from
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.
6
+ kind: phase # phase (default) | integration (a phase's integ- branch) | plan (the PR that lands the whole plan)
7
+ phase_id: <phase-id> # e.g. "1", "4a". Omit for kind: plan
8
+ phase_title: <phase title> # verbatim from the plan's Phased Rollout section. Omit for kind: plan
9
+ branch: plan/<feature-kebab>/phase-<id> # branch the PR opens from (integ-<id> for integration; final wave-<N> for a stacked plan PR)
10
+ base: <main | plan/<feature-kebab>/phase-<dep-id> | plan/<feature-kebab>/integ-<id>> # PR target branch. Stacked phase: its dependency-derived base (default branch only with no dependencies). Integration, plan, modular / single-PR: default branch.
10
11
  created_at: <ISO 8601 timestamp>
11
12
  status: pending # `pending` until published; `published` after CLI run
12
13
  pr_url: # set by open-pr-from-context after publishing
@@ -101,10 +101,37 @@ For each vendor in the user's selection:
101
101
 
102
102
  Any mismatches → re-run the script. If still wrong → inspect the script's output for warnings (it warns when a target path exists as a non-symlink real file).
103
103
 
104
+ ### 7b. Install integration skills
105
+
106
+ Read `integrations` from `.vinta-ai-workflows.yaml`. Skip this step when nothing there is `enabled`. Run it **after** step 6: the vendor skill paths must already be symlinks into `ai-tools/skills/`, or the tool would create real vendor directories that block those symlinks.
107
+
108
+ **`pr-review-canvas` = enabled:**
109
+
110
+ 1. Check for the CLI with `pr-review --version`. If it is missing, print the install command and skip the rest of this integration. **Do not install it yourself.** It is a global, machine-level tool, like `gh`:
111
+
112
+ ```bash
113
+ npm install -g @vintasoftware/pr-review-canvas
114
+ ```
115
+
116
+ Tell the user to install it, then re-run this step (or run `pr-review install-skill --claude-dir ai-tools/skills --codex-dir ai-tools/skills` themselves).
117
+ 2. Install the skill into the canonical directory:
118
+
119
+ ```bash
120
+ pr-review install-skill --claude-dir ai-tools/skills --codex-dir ai-tools/skills --json
121
+ ```
122
+
123
+ Both flags point at `ai-tools/skills/`, so the tool writes one copy, `ai-tools/skills/pr-review-canvas/`. Every vendor then reaches that copy through its symlink. The tool also adds `.pr-review/settings.yml` to `.gitignore`.
124
+ 3. **Never edit `ai-tools/skills/pr-review-canvas/SKILL.md`.** The tool stamps a body hash into its frontmatter, and `pr-review doctor` and `pr-review serve` flag a modified copy as stale. To refresh the skill, run `pr-review upgrade`, not this flow.
125
+ 4. Run `pr-review doctor`. Its `skill` check must pass, and it reads the copy through `.agents/skills/`, which step 6 always links. Show any other failed checks to the user with the hints the tool prints, most often `gh auth login` / `glab auth login` or a missing `origin` remote. These do not block the bootstrap.
126
+ 5. Do not write `pr-review.config.yml`. Every key in it is optional, and the defaults are correct. Mention that the team can copy the tool's example config to change sharing or mark high-risk paths.
127
+
128
+ On `SKILL_DIR_EXISTS` (exit 1), a hand-made `ai-tools/skills/pr-review-canvas/` without the tool's marker is in the way. Show it to the user and ask before re-running with `--force`. `--force` replaces that directory.
129
+
104
130
  ### 8. Commit
105
131
 
106
132
  Stage:
107
- - `ai-tools/` (canonical sources + script)
133
+ - `ai-tools/` (canonical sources + script, plus any integration skill from step 7b)
134
+ - `.gitignore` (when step 7b's `pr-review install-skill` added `.pr-review/settings.yml`)
108
135
  - `package.json` (script alias + yaml dep)
109
136
  - `pnpm-lock.yaml` / `package-lock.json` / `yarn.lock` (after install)
110
137
  - `AGENTS.md` (regular file at the repo root)
@@ -109,7 +109,7 @@ For each `affects-project` and `opt-in-offer` and `config-schema-change` entry,
109
109
 
110
110
  `tooling` changes batch under one prompt: `Apply all tooling changes?` — they're typically idempotent and small.
111
111
 
112
- `opt-in-offer` `Skip` writes the corresponding entry to `foundation_skills` (or wherever it lives) as `disabled` so the next sync respects the choice.
112
+ `opt-in-offer` `Skip` writes the corresponding entry to `foundation_skills` (or `integrations`, or wherever it lives) as `disabled` so the next sync respects the choice.
113
113
 
114
114
  Don't batch `affects-project` decisions. Each is a separate decision so the user can keep their hand-tuned wording for one skill while accepting another.
115
115
 
@@ -124,6 +124,7 @@ In order:
124
124
  - Bump `schema_version` if the major changed.
125
125
 
126
126
  2. **`opt-in-offer` accepts** — flip the corresponding entry to `enabled` in the config; copy / render the artifact (foundation skill, agent, etc.).
127
+ - **An integration** (`integrations.<name>` in the config, such as `pr-review-canvas`) has no bundled artifact to copy. Flip it to `enabled`, then run [vinta-install-ai-tools-setup](../vinta-install-ai-tools-setup/SKILL.md)'s **Install integration skills** step, which uses the tool's own CLI. The plan-execution skills and `plan-feature` read the flag at runtime, so nothing needs re-deriving. Offer it only when its preconditions hold. For `pr-review-canvas`, that means `project.code_host` is `github` / `gitlab` and `policies.pr_creation` is `agents-create`. `Skip` writes `disabled` under `integrations`.
127
128
 
128
129
  3. **`affects-project` accepts** — re-render the relevant template (for `implement-plan` / `amend-plan`) or re-copy the foundation skill body (for verbatim ones — delegated to [vinta-update-project-skills](../vinta-update-project-skills/SKILL.md)). Use the values in `.vinta-ai-workflows.yaml` as the substitution source. Validate every `{{PLACEHOLDER}}` is resolved.
129
130
 
@@ -65,6 +65,7 @@ For each project skill, decide its bucket:
65
65
  | `verbatim` | The skill name matches a directory under `vinta-derive-skills/resources/foundation-skills/` (e.g. `plan-feature`, `create-spec`, `create-qa-use-cases`). | Diff against source. |
66
66
  | `templated` | The skill name is `implement-plan` (or any other future templated skill listed under `vinta-derive-skills/resources/*-template.md`). | **Don't diff.** Surface as "regenerate via [vinta-derive-skills](../vinta-derive-skills/SKILL.md)". |
67
67
  | `stack-derived` | The skill maps to a stack-template prompt under `vinta-bootstrap-ai-tools/resources/stacks/<stack>/notes.md`. | Same as `templated` — surface, don't diff. |
68
+ | `integration` | The skill dir carries an external tool's ownership marker, such as `.pr-review-install` for `pr-review-canvas`. | **Never diff or edit** — the tool stamps a content hash and treats any edit as stale. Surface as "refresh with the tool's own updater" (`pr-review upgrade` for `pr-review-canvas`). |
68
69
  | `user-authored` | None of the above. | Skip silently. |
69
70
 
70
71
  For `templated` and `stack-derived`, in-place diffing is misleading because the project version contains interpolated values (commands, branch names, etc.) that won't appear in the template. The right refresh path for those is to re-run [vinta-derive-skills](../vinta-derive-skills/SKILL.md) so the user can re-supply the inputs.