vinta-ai-workflows 0.2.0-alpha4 → 0.2.0-alpha6

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,81 @@ 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
- <!-- pre-release: 0.2.0-alpha4 on 2026-07-08 -->
10
+ <!-- pre-release: 0.2.0-alpha6 on 2026-07-13 -->
11
+
12
+ ### Changed
13
+
14
+ - **`plan-feature` AI model tiers refreshed to the current model
15
+ generation.** `plan-feature/resources/ai-models.yaml` now cites the latest
16
+ IDs: tier 1 `gemini-2.5-flash-lite` → `gemini-3.1-flash-lite` and
17
+ `gpt-5-nano` → `gpt-5.6-luna`; tier 2 `claude-sonnet-4-6` → `claude-sonnet-5`
18
+ (incl. the Haiku step-up note) and `gemini-2.5-flash` → `gemini-3.5-flash`; tier 3
19
+ `claude-sonnet-4-6` → `claude-sonnet-5` and the retired `gemini-2.5-pro`
20
+ dropped in favor of `gemini-3-pro` and the retired `gpt-5` dropped in favor of
21
+ `gpt-5.6-terra`; tier 4 `claude-opus-4-7` → `claude-opus-4-8` and the retired
22
+ `o3` dropped in favor of `gpt-5.6-sol`. Tier *placement* is unchanged — only the
23
+ concrete IDs move. **Consumers**: re-sync to pick up the refreshed model
24
+ suggestions.
25
+
26
+ ### Fixed
27
+
28
+ - **`implement-plan` stacked-branches now opens each phase PR against its
29
+ parent phase, not the default branch.** The git branch topology was already
30
+ stacked correctly (each phase branches off the previous phase's branch), but
31
+ nothing told the orchestrator what to write into the prs-context `base`
32
+ field, so it defaulted to `<BASE_BRANCH>` and **every stacked PR targeted the
33
+ default branch** — collapsing the stack and showing each PR the cumulative
34
+ diff. The stacked commit-strategy partial now spells out the PR base per
35
+ phase (first phase → default branch; every subsequent phase → the previous
36
+ phase's branch), the shared `pr-context` write step no longer defaults `base`
37
+ blindly, and the `prs-context` template comment states the rule. Modular /
38
+ single-PR strategies are unaffected (one PR against the default branch).
39
+ **Consumers**: re-sync to pick up the corrected `base` resolution; existing
40
+ PRs opened against the wrong base must be re-targeted manually.
41
+
42
+ <!-- pre-release: 0.2.0-alpha5 on 2026-07-13 -->
11
43
 
12
44
  ### Added
13
45
 
46
+
47
+ - **`handoff` foundation skill — session-continuation handoff docs between
48
+ agents.** Write mode captures the current task (goal, verified-vs-unverified
49
+ state, decisions + rejected alternatives, landmines, single concrete next
50
+ step) into `.vinta-ai-workflows/handoffs/{date}-{slug}.md`, gathering state
51
+ from the repo — never from memory; resume mode reads a handoff, verifies its
52
+ claims against the repo before trusting them, and continues from the doc's
53
+ next step. Ships at
54
+ [skills/vinta-derive-skills/resources/foundation-skills/handoff/SKILL.md](skills/vinta-derive-skills/resources/foundation-skills/handoff/SKILL.md).
55
+ Wired as an **always-ship** bucket-A skill: new
56
+ `foundation_skills.handoff` enum entry (schema), derive-skills bucket-A
57
+ table + always-ships note, bootstrap always-copy-verbatim list + outputs
58
+ tree + Step 0.5 YAML (`handoff: enabled`), and both foundation-shape
59
+ replace lists. No bootstrap interview question — it always ships.
60
+
61
+ - **`handoff-to-client` foundation skill — API-change handoff docs for
62
+ API-only repos (opt-in, template-rendered).** Generates a self-contained
63
+ markdown document for the client teams consuming the repo's API: every
64
+ endpoint/operation added / changed / deprecated / removed on the current
65
+ branch vs the default branch, with request/response shapes derived from the
66
+ code (or a regenerated API spec), auth/error changes, breaking-change flags
67
+ judged from the strictest plausible client, one realistic example per
68
+ operation, and per-platform migration notes. Template at
69
+ [skills/vinta-derive-skills/resources/handoff-to-client-template.md](skills/vinta-derive-skills/resources/handoff-to-client-template.md)
70
+ (bucket B + C). New schema fields: `foundation_skills.handoff-to-client`
71
+ enum entry and the `skills.handoff-to-client` config block
72
+ (`client_platforms` — required non-empty array, `api_style`,
73
+ `api_spec_path`, `output_dir` — default
74
+ `.vinta-ai-workflows/client-handoffs`). New template placeholders
75
+ `{{API_STYLE}}`, `{{CLIENT_PLATFORMS_LIST}}`, `{{CLIENT_HANDOFF_DIR}}`,
76
+ `{{API_SPEC_BLOCK}}` documented in the derive-skills placeholder table.
77
+ Bootstrap gains **Optional foundation skills question 7** (asked only when
78
+ the inventory suggests an API-only repo) plus a four-part config follow-up;
79
+ Step 0.5 YAML, outputs tree, optional-bucket lists, and both
80
+ foundation-shape replace lists updated. **Consumers**: API-only projects
81
+ re-sync + answer the new interview question to enable it.
82
+
83
+ <!-- pre-release: 0.2.0-alpha4 on 2026-07-08 -->
84
+
14
85
  - **`implement-plan` outer-gate test scope is now configurable — and defaults
15
86
  to the quick path.** Each phase's outer gate still always runs the repo-wide
16
87
  type/build gate, but for tests it now runs **only the scoped suite** covering
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinta-ai-workflows",
3
- "version": "0.2.0-alpha4",
3
+ "version": "0.2.0-alpha6",
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": {
@@ -222,6 +222,16 @@
222
222
  "description": "Rewrite comments and doc blocks touched during the current task into Simple English — strip AI-slop vocabulary and negative framing, comment-only (no renames, no behavior change). Copy-verbatim foundation skill (bucket A), always shipped: the `review-phase` Layer 2 comment-hygiene check and fix loop depend on it. Set `disabled` only if a project deliberately opts out of the review flow's comment-hygiene step.",
223
223
  "type": "string",
224
224
  "enum": ["enabled", "disabled"]
225
+ },
226
+ "handoff": {
227
+ "description": "Write or consume a session-continuation handoff document under `.vinta-ai-workflows/handoffs/` so a fresh agent session (or a different agent / teammate) can resume in-flight work without re-deriving context. Copy-verbatim foundation skill (bucket A), always shipped — its body is fully project-agnostic. Set `disabled` only if a project deliberately opts out.",
228
+ "type": "string",
229
+ "enum": ["enabled", "disabled"]
230
+ },
231
+ "handoff-to-client": {
232
+ "description": "Generate a markdown API-change handoff document for client teams consuming an API-only repo — endpoints added/changed/deprecated/removed on the current branch vs the default branch, with request/response shapes, breaking-change flags, and per-platform migration notes. Template-rendered (bucket B) from `vinta-derive-skills/resources/handoff-to-client-template.md` and opt-in (bucket C) — only ships when the bootstrap interview confirms an API-only repo with separate client codebases. When `enabled`, project-level configuration lives under `skills.handoff-to-client` (client platforms, API style, spec path, output dir).",
233
+ "type": "string",
234
+ "enum": ["enabled", "disabled"]
225
235
  }
226
236
  }
227
237
  },
@@ -318,6 +328,38 @@
318
328
  }
319
329
  }
320
330
  },
331
+ "handoff-to-client": {
332
+ "description": "Configuration for the `handoff-to-client` foundation skill. Required when `foundation_skills.handoff-to-client` is `enabled`; ignored otherwise. Rendered into the skill body at derive time.",
333
+ "type": "object",
334
+ "required": ["client_platforms"],
335
+ "additionalProperties": false,
336
+ "properties": {
337
+ "client_platforms": {
338
+ "description": "Free-form list of the client codebases/platforms that consume this repo's API, as the team names them (e.g. `iOS (Swift)`, `Android (Kotlin)`, `web SPA (React)`, `partner integrations`). Rendered into the skill's audience line and per-operation migration-notes instruction. Must be non-empty — an API-only repo with no named consumers has no handoff audience.",
339
+ "type": "array",
340
+ "items": { "type": "string", "minLength": 1 },
341
+ "uniqueItems": true,
342
+ "minItems": 1
343
+ },
344
+ "api_style": {
345
+ "description": "The API paradigm, free-form (e.g. `REST`, `GraphQL`, `gRPC`, `REST + webhooks`). Drives how the rendered skill names operations (method+path vs query/mutation vs service/rpc).",
346
+ "type": "string",
347
+ "minLength": 1,
348
+ "default": "REST"
349
+ },
350
+ "api_spec_path": {
351
+ "description": "Repo-relative path to a machine-readable API spec (OpenAPI file, GraphQL schema, proto dir) plus, ideally, the command that regenerates it — e.g. `docs/openapi.yaml (regenerate: make openapi)`. When set, the rendered skill diffs the regenerated spec between base and branch as its primary change-enumeration source. Omit when no spec exists; the skill then works from route/serializer code alone.",
352
+ "type": "string",
353
+ "minLength": 1
354
+ },
355
+ "output_dir": {
356
+ "description": "Directory where generated client-handoff documents land, repo-relative.",
357
+ "type": "string",
358
+ "minLength": 1,
359
+ "default": ".vinta-ai-workflows/client-handoffs"
360
+ }
361
+ }
362
+ },
321
363
  "prepare-worktree": {
322
364
  "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.",
323
365
  "type": "object",
@@ -83,7 +83,7 @@ These bleed across sub-skills, so capture once now:
83
83
 
84
84
  ### D. Optional foundation skills
85
85
 
86
- Six skills are part of the foundation set but aren't always needed. Ask explicitly:
86
+ Seven skills are part of the foundation set but aren't always needed. Ask explicitly:
87
87
 
88
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. **This answer also governs `create-qa-use-cases` and the e2e content inside `plan-feature`**: on `No — skip`, set `foundation_skills.create-qa-use-cases: disabled` too — derive-skills won't ship `create-qa-use-cases` and strips `plan-feature`'s `<!-- e2e:start/end -->` regions so no-e2e projects carry zero Playwright / `QA_USE_CASES.md` / `pr-screenshots/` references. On either `Yes`, set both `add-e2e-test` and `create-qa-use-cases` to `enabled`.
89
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`.
@@ -114,7 +114,15 @@ Six skills are part of the foundation set but aren't always needed. Ask explicit
114
114
 
115
115
  6. **`thermo-nuclear-code-quality-review`** — does the team want an opt-in, deliberately harsh structural-maintainability audit available on demand (abstraction quality, giant files, spaghetti-condition growth), separate from the standard per-phase review? `AskUserQuestion` options: `Yes — enable`, `No — skip`. Recommend `Yes` for long-lived codebases where structural drift is a real cost, or teams that already run deep quality passes before merging large work. It ships as a user-invoked skill and is also the escalation target for the `review-phase` Layer 3 structural-simplification lens; it is never auto-run on every diff. No follow-up config — the body is project-agnostic.
116
116
 
117
- If the user answers "No" to any of the six, that skill won't ship. If the user answers "Yes" to `add-e2e-test` / `add-env-var` but doesn't have a template, derive-skills drafts one via interview. `systematic-debugging` is always template-rendered — no per-project drafting interview, just the MCP-server inventory above. `add-one-off-script` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/add-one-off-script/](../vinta-derive-skills/resources/foundation-skills/add-one-off-script/) — its body is project-agnostic; the per-project variability lives in the `skills.add-one-off-script.*` config block above and in env vars consumed at runtime. `prepare-worktree` is also copied verbatim from [vinta-derive-skills/resources/foundation-skills/prepare-worktree/](../vinta-derive-skills/resources/foundation-skills/prepare-worktree/) — same pattern: project-agnostic body, per-project defaults under `skills.prepare-worktree.*`. `thermo-nuclear-code-quality-review` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/](../vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/) with no follow-up config — its body is fully project-agnostic.
117
+ 7. **`handoff-to-client`** — is this an API-only repo whose consumers live in separate client codebases (mobile apps, SPAs, partner integrations) that need API changes documented for them? Ask **only when the inventory suggests an API-only shape** — backend framework with no co-located frontend app (no SPA package, no templates-rendered UI beyond an admin). `AskUserQuestion` options: `Yes — enable`, `No — skip`. Skip the question entirely (set `disabled`) for full-stack repos and monorepos that contain their own clients — there the API diff is visible to the client code in the same PR. When enabled, agents can generate a markdown API-change handoff document (endpoints added / changed / deprecated / removed vs the default branch, request/response shapes, breaking-change flags, per-platform migration notes) for client implementers who cannot read this repo.
118
+
119
+ **Follow-up only when `handoff-to-client` = Yes — client-handoff config.** Four short questions land under `skills.handoff-to-client.*`:
120
+ - **Client platforms.** Open prose → free-form string array, e.g. `iOS (Swift)`, `Android (Kotlin)`, `web SPA (React)`, `partner integrations`. Required, non-empty — this is the document's audience and drives the per-operation migration-notes sections.
121
+ - **API style.** `AskUserQuestion`: `REST`, `GraphQL`, `gRPC`, other (free-form). Auto-pick from the inventory when unambiguous (e.g. DRF routers → REST, graphene/strawberry → GraphQL); ask only when mixed.
122
+ - **API spec path.** Open prose. Repo-relative path to a machine-readable spec (OpenAPI file, GraphQL schema, proto dir) plus the command that regenerates it, if one exists (e.g. `docs/openapi.yaml (regenerate: make openapi)`). Cross-check the inventory for spec files the user forgot. Empty is fine — the rendered skill then enumerates changes from route/serializer code alone.
123
+ - **Output dir.** Default `.vinta-ai-workflows/client-handoffs`. Override if the team wants handoffs committed (e.g. `docs/api-changes/`) — note that the default lives under the gitignored `.vinta-ai-workflows/`, so docs there must be shared manually.
124
+
125
+ If the user answers "No" to any of the seven, that skill won't ship. If the user answers "Yes" to `add-e2e-test` / `add-env-var` but doesn't have a template, derive-skills drafts one via interview. `systematic-debugging` is always template-rendered — no per-project drafting interview, just the MCP-server inventory above. `add-one-off-script` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/add-one-off-script/](../vinta-derive-skills/resources/foundation-skills/add-one-off-script/) — its body is project-agnostic; the per-project variability lives in the `skills.add-one-off-script.*` config block above and in env vars consumed at runtime. `prepare-worktree` is also copied verbatim from [vinta-derive-skills/resources/foundation-skills/prepare-worktree/](../vinta-derive-skills/resources/foundation-skills/prepare-worktree/) — same pattern: project-agnostic body, per-project defaults under `skills.prepare-worktree.*`. `thermo-nuclear-code-quality-review` is copied verbatim from [vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/](../vinta-derive-skills/resources/foundation-skills/thermo-nuclear-code-quality-review/) with no follow-up config — its body is fully project-agnostic. `handoff-to-client` is always template-rendered from [vinta-derive-skills/resources/handoff-to-client-template.md](../vinta-derive-skills/resources/handoff-to-client-template.md) — no per-project drafting interview, just the client-handoff config follow-up above.
118
126
 
119
127
  ### E. Existing AI artifacts (per-artifact disposition)
120
128
 
@@ -134,7 +142,7 @@ For each artifact, read it (frontmatter + body), then ask the user via `AskUserQ
134
142
  - `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.
135
143
  - `Drop` — delete (rare; usually the user wants to migrate).
136
144
 
137
- Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `implement-phase`, `review-phase`, `integrate-phase`, `amend-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `deslop-comments`) get an extra option: `Replace with Vinta foundation version` — overwrites with the canonical foundation content, preserving the user's name. Useful when the existing version is stale. (`implement-phase` / `review-phase` / `integrate-phase` are the plan-execution sub-skills co-shipped with `implement-plan`; replace them as a unit.)
145
+ Foundation-shape skills (name matches `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `implement-phase`, `review-phase`, `integrate-phase`, `amend-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `deslop-comments`, `handoff`, `handoff-to-client`) get an extra option: `Replace with Vinta foundation version` — overwrites with the canonical foundation content, preserving the user's name. Useful when the existing version is stale. (`implement-phase` / `review-phase` / `integrate-phase` are the plan-execution sub-skills co-shipped with `implement-plan`; replace them as a unit.)
138
146
 
139
147
  - **Sub-agents** (each under any vendor `agents/` dir):
140
148
  - `Migrate to ai-tools/agents/<name>.yaml` — converts vendor-specific format → canonical YAML; `setup-ai-tools.mjs` re-emits per-vendor copies.
@@ -254,6 +262,8 @@ foundation_skills:
254
262
  prepare-worktree: <Optional foundation skills → prepare-worktree answer → enabled | disabled>
255
263
  thermo-nuclear-code-quality-review: <Optional foundation skills → thermo-nuclear-code-quality-review answer → enabled | disabled>
256
264
  deslop-comments: enabled # always ships — review-phase Layer 2 comment-hygiene + fix loop depend on it
265
+ handoff: enabled # always ships — project-agnostic session-continuation handoff docs
266
+ handoff-to-client: <Optional foundation skills → handoff-to-client answer → enabled | disabled; only asked for API-only repos>
257
267
 
258
268
  foundation_agents:
259
269
  implementer: enabled
@@ -277,6 +287,13 @@ skills:
277
287
  systematic-debugging:
278
288
  observability_mcp_servers: <systematic-debugging follow-up — free-form array of MCP server identifiers, e.g. [sentry, datadog, our-internal-traces]>
279
289
 
290
+ # Only emit this block when foundation_skills.handoff-to-client = enabled.
291
+ handoff-to-client:
292
+ client_platforms: <handoff-to-client follow-up — free-form array, e.g. [iOS (Swift), Android (Kotlin), web SPA (React)]>
293
+ api_style: <handoff-to-client follow-up — REST | GraphQL | gRPC | free-form>
294
+ api_spec_path: <handoff-to-client follow-up — repo-relative spec path + regen command; omit when none>
295
+ output_dir: .vinta-ai-workflows/client-handoffs
296
+
280
297
  # Only emit this block when foundation_skills.prepare-worktree = enabled.
281
298
  prepare-worktree:
282
299
  worktree_root: <prepare-worktree follow-up — `.claude/worktrees` | `../<repo>-wt-`>
@@ -346,6 +363,7 @@ ai-tools/
346
363
  │ ├── create-spec/SKILL.md ← always (copied verbatim)
347
364
  │ ├── create-qa-use-cases/SKILL.md ← always (copied verbatim)
348
365
  │ ├── deslop-comments/SKILL.md ← always (copied verbatim; review-phase Layer 2 comment-hygiene + fix loop depend on it)
366
+ │ ├── handoff/SKILL.md ← always (copied verbatim; session-continuation handoff docs under .vinta-ai-workflows/handoffs/)
349
367
  │ ├── implement-plan/SKILL.md ← always (conductor; generated from template, project-specific)
350
368
  │ ├── implement-phase/SKILL.md ← always (plan-execution unit; co-shipped with implement-plan)
351
369
  │ ├── review-phase/SKILL.md ← always (plan-execution unit; shared by implement-plan / amend-plan / systematic-debugging)
@@ -354,6 +372,7 @@ ai-tools/
354
372
  │ ├── add-e2e-test/SKILL.md ← optional — only if user opts in
355
373
  │ ├── add-env-var/SKILL.md ← optional — only if user opts in
356
374
  │ ├── systematic-debugging/SKILL.md ← optional — only if user opts in (template-rendered)
375
+ │ ├── handoff-to-client/SKILL.md ← optional — only for API-only repos, if user opts in (template-rendered; config under skills.handoff-to-client.*)
357
376
  │ ├── add-one-off-script/ ← optional — only if user opts in (verbatim copy + bundled BaseOneOffScript + LocalRuntime templates)
358
377
  │ │ ├── SKILL.md
359
378
  │ │ └── resources/
@@ -389,9 +408,9 @@ Plus the symlinks + per-vendor generated files, set up by the install step.
389
408
 
390
409
  Foundation skills break into three buckets — see [vinta-derive-skills](../vinta-derive-skills/SKILL.md) for the full mechanics:
391
410
 
392
- - **Always copy verbatim**: `plan-feature`, `create-spec`, `create-qa-use-cases`, `deslop-comments`. Bundled with the bootstrap skill set; project-agnostic enough to ship as-is (with light path scrubs). `deslop-comments` always ships because `review-phase`'s Layer 2 comment-hygiene check + fix loop dispatch it.
411
+ - **Always copy verbatim**: `plan-feature`, `create-spec`, `create-qa-use-cases`, `deslop-comments`, `handoff`. Bundled with the bootstrap skill set; project-agnostic enough to ship as-is (with light path scrubs). `deslop-comments` always ships because `review-phase`'s Layer 2 comment-hygiene check + fix loop dispatch it. `handoff` always ships because its session-continuation body is fully project-agnostic.
393
412
  - **Always generate**: the plan-execution unit — `implement-plan` (conductor) + its co-shipped sub-skills `implement-phase` / `review-phase` / `integrate-phase`, plus `amend-plan` (conductor). Bodies have too much project-specific content (test commands, branch convention, PR + co-author policy, agent dispatch) — generated from parameterized templates + shared partials using interview answers + inventory. The sub-skills are not independently opt-in; they always ship with the conductors.
394
- - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`. 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. `thermo-nuclear-code-quality-review`: if yes → copy the bundled SKILL.md verbatim (no follow-up config); if no → don't ship.
413
+ - **Optional, ask first**: `add-e2e-test`, `add-env-var`, `systematic-debugging`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `handoff-to-client`. Skipped by default; orchestrator asks via `AskUserQuestion` whether the project has the relevant flow at all. `add-e2e-test` / `add-env-var`: if yes + user has a template → copy + adapt; if yes + no template → draft from scratch via interview; if no → don't ship. `systematic-debugging`: if yes → render the bundled template plus the per-tool MCP catalogue blocks for the observability tools selected in its follow-up; if no → don't ship. `add-one-off-script`: if yes → copy the bundled SKILL.md verbatim plus the language-specific `BaseOneOffScript` template (`one_off_script_base.py` / `one_off_script_base.ts`) chosen via its follow-up; if no → don't ship. `prepare-worktree`: if yes → copy the bundled SKILL.md verbatim, populate `skills.prepare-worktree.*` defaults from its follow-ups, 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. `thermo-nuclear-code-quality-review`: if yes → copy the bundled SKILL.md verbatim (no follow-up config); if no → don't ship. `handoff-to-client`: asked only for API-only repos; if yes → render the bundled template using `skills.handoff-to-client.*` (client platforms, API style, spec path, output dir) from its follow-ups; if no → don't ship.
395
414
 
396
415
  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.
397
416
 
@@ -26,7 +26,7 @@ Before drafting any new SKILL.md, walk through every entry in `existing_ai_artif
26
26
  - **Migrate to `ai-tools/skills/<name>/`** — `git mv` the existing skill folder (with all its resources) into the canonical layout. After move, scan the body for hard-coded vendor paths that no longer apply (`.cursor/skills/...` self-references, etc.) and rewrite to the new path. `setup-ai-tools.mjs` will re-link to the chosen vendors.
27
27
  - **Keep in current vendor path, don't touch** — leave it where it is; AGENTS.md may reference it; downstream skill setup won't manage it. **Don't ship a foundation duplicate that would shadow it.**
28
28
  - **Drop** — log removal; don't emit anything.
29
- - **Replace with Vinta foundation version** (foundation-shape only — `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `deslop-comments`) — proceed with the bucket A / B / C flow below for that name. The user has explicitly opted into overwriting their version.
29
+ - **Replace with Vinta foundation version** (foundation-shape only — `plan-feature`, `create-spec`, `create-qa-use-cases`, `implement-plan`, `add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `deslop-comments`, `handoff`, `handoff-to-client`) — proceed with the bucket A / B / C flow below for that name. The user has explicitly opted into overwriting their version.
30
30
  - **`vinta-managed`** (any skill whose dir starts with `vinta-`) — leave alone. These come from the `vinta-ai-workflows` CLI; `vinta-derive-skills` doesn't manage them.
31
31
 
32
32
  For each name in the foundation set: only emit it (verbatim copy / generate from template / interview-draft) when no existing skill of that name is being migrated or kept. If the user said `Migrate` or `Keep` for an existing `plan-feature/SKILL.md`, **do not overwrite**.
@@ -48,6 +48,7 @@ These are project-agnostic enough to ship as-is. Copy from this skill's [resourc
48
48
  | `create-qa-use-cases` | [resources/foundation-skills/create-qa-use-cases/SKILL.md](resources/foundation-skills/create-qa-use-cases/SKILL.md) | Bootstrap a project's `QA_USE_CASES.md` from the active spec/plan. **E2E-gated** — ship only when `foundation_skills.add-e2e-test` is `enabled`; QA use-cases exist to seed e2e specs, so a no-e2e project has no use for it. |
49
49
  | `open-pr-from-context` | [resources/foundation-skills/open-pr-from-context/](resources/foundation-skills/open-pr-from-context/) | Thin SKILL.md wrapper around [scripts/open-pr.sh](resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh) — bash script that publishes one `.vinta-ai-workflows/prs-context/{feature}/{phase}.md` file as a real PR + inline comments via the project's PR CLI (`gh` / `glab`). Used by `implement-plan` (when CLI + `yq`/`jq` are available) and standalone (to publish a `pending` file later). |
50
50
  | `deslop-comments` | [resources/foundation-skills/deslop-comments/SKILL.md](resources/foundation-skills/deslop-comments/SKILL.md) | Rewrite comments + doc blocks touched during a task into Simple English — strip AI-slop vocabulary and negative framing; comment-only, no renames or behavior change. **Always ships** — the `review-phase` Layer 2 comment-hygiene check + fix loop dispatch it, so it must exist in the target. Also user-invokable standalone ("deslop these comments"). |
51
+ | `handoff` | [resources/foundation-skills/handoff/SKILL.md](resources/foundation-skills/handoff/SKILL.md) | Write or consume a session-continuation handoff doc under `.vinta-ai-workflows/handoffs/` — goal, current state, decisions + rationale, landmines, next step — so a fresh agent session (or a teammate) resumes in-flight work without re-deriving context. **Always ships** — fully project-agnostic; standalone (no cross-links into the always-on trio). |
51
52
  | `prepare-worktree` | [resources/foundation-skills/prepare-worktree/](resources/foundation-skills/prepare-worktree/) | Provision a runnable, isolated git worktree for parallel feature work — symlink dep dirs (or copy / reinstall when the plan churns deps), copy + mutate env files, fork dev + test DBs when migrations are in scope, namespace docker-compose project + network, OS-sandbox the worktree so main-checkout writes are blocked (bundled [scripts/sandbox-run.sh](resources/foundation-skills/prepare-worktree/scripts/sandbox-run.sh) — `sandbox-exec` / `bwrap`), write a teardown-ready summary YAML. Used by `implement-plan` when Step 0 question (c) opts in; standalone for ad-hoc isolation. Opt-in (bucket A + ask-first via the bootstrap's **Optional foundation skills** interview). |
52
53
  | `thermo-nuclear-code-quality-review` | [resources/foundation-skills/thermo-nuclear-code-quality-review/SKILL.md](resources/foundation-skills/thermo-nuclear-code-quality-review/SKILL.md) | Opt-in deep structural-maintainability audit of a diff — abstraction quality, giant files, spaghetti-condition growth — harsher than the standard per-phase review; hunts for "code-judo" reframes that collapse branches / helpers / layers rather than polishing them. Read-only; hands each fix to the `fixer` agent. Invoked deliberately by the user, or escalated from the `review-phase` Layer 3 structural-simplification lens. Opt-in (bucket A + ask-first via the bootstrap's **Optional foundation skills** interview). |
53
54
 
@@ -56,7 +57,7 @@ These reference each other:
56
57
  - `plan-feature` reads spec; dispatches `create-qa-use-cases` when the doc is missing (e2e-enabled projects only — see below).
57
58
  - `implement-plan` (bucket B below) writes per-phase PR-context files following [resources/prs-context-template.md](resources/prs-context-template.md), then invokes `open-pr-from-context` when a PR CLI is detected.
58
59
 
59
- The **always-on unit** is `plan-feature` + `create-spec` + `open-pr-from-context` — copy all three or none. `deslop-comments` also always ships (independently — it doesn't cross-reference the trio), because the `review-phase` Layer 2 comment-hygiene check + fix loop dispatch it; a target missing it would leave that review step dangling. `create-qa-use-cases` joins the unit **only when `foundation_skills.add-e2e-test` is `enabled`**; when add-e2e-test is disabled (or absent), don't ship it and set `foundation_skills.create-qa-use-cases: disabled` in `.vinta-ai-workflows.yaml` to match.
60
+ The **always-on unit** is `plan-feature` + `create-spec` + `open-pr-from-context` — copy all three or none. `deslop-comments` also always ships (independently — it doesn't cross-reference the trio), because the `review-phase` Layer 2 comment-hygiene check + fix loop dispatch it; a target missing it would leave that review step dangling. `handoff` also always ships independently — its body is fully project-agnostic and nothing else depends on it. `create-qa-use-cases` joins the unit **only when `foundation_skills.add-e2e-test` is `enabled`**; when add-e2e-test is disabled (or absent), don't ship it and set `foundation_skills.create-qa-use-cases: disabled` in `.vinta-ai-workflows.yaml` to match.
60
61
 
61
62
  **E2E stripping in `plan-feature`.** `plan-feature` ships verbatim but carries e2e-only regions delimited by `<!-- e2e:start -->` / `<!-- e2e:end -->` lines. When copying it, run an e2e pass:
62
63
 
@@ -82,6 +83,8 @@ The five are a **co-shipped unit**: `implement-plan` is always generated, so `im
82
83
 
83
84
  - **`systematic-debugging`** — root-cause-first debugging flow with project-specific reproduction commands and enforced observability MCP evidence-gathering. From [resources/systematic-debugging-template.md](resources/systematic-debugging-template.md) plus the **MCP-agnostic** evidence-categories block at [resources/systematic-debugging-mcp-tools.md](resources/systematic-debugging-mcp-tools.md) — the rendered SKILL.md instructs the agent to list available MCP tools at runtime and map them to evidence categories (error tracking, traces, logs, metrics, alerts, deploys, dashboards), instead of hardcoding tool names that go stale. **Opt-in** — only generated when `foundation_skills.systematic-debugging` is `enabled` in `.vinta-ai-workflows.yaml`. The free-form list of MCP server identifiers rendered into the body comes from `skills.systematic-debugging.observability_mcp_servers` in the same config. It reuses `review-phase` for its Phase 4 review gate (an `invoke [review-phase]` reference — always resolvable because the plan-execution unit is always shipped).
84
85
 
86
+ - **`handoff-to-client`** — generate a markdown API-change handoff document for the client teams consuming an API-only repo: endpoints/operations added / changed / deprecated / removed on the current branch vs the default branch, with request/response shapes, breaking-change flags, and per-platform migration notes. From [resources/handoff-to-client-template.md](resources/handoff-to-client-template.md). **Opt-in** — only generated when `foundation_skills.handoff-to-client` is `enabled` in `.vinta-ai-workflows.yaml` (the bootstrap interview asks only when the repo looks API-only with separate client codebases). The rendered body bakes in `skills.handoff-to-client.*` config: client platforms, API style, optional API spec path, output dir. Standalone — no cross-links into the plan-execution unit.
87
+
85
88
  Every plan-execution shell + `systematic-debugging` consumes the placeholder set below — render each by substituting from the inventory + Step 0 interview answers. `systematic-debugging` reuses the same set plus two extra placeholders (`{{OBSERVABILITY_MCP_BLOCK}}`, `{{OBSERVABILITY_MCP_LIST}}`) rendered from the catalogue.
86
89
 
87
90
  #### Rendering the plan-execution unit
@@ -137,6 +140,10 @@ The remaining per-shell placeholders:
137
140
  | `{{INTEGRATE_PHASE_LINK}}` | derived from `policies.commit_strategy` | Path used by `amend-plan`'s PR-template cross-reference. `../integrate-phase/SKILL.md` for `stacked` / `modular`; `../integrate-phase-stacked/SKILL.md` for `ask` (amend-plan only runs under the stacked topology). |
138
141
  | `{{OBSERVABILITY_MCP_BLOCK}}` | rendered from [resources/systematic-debugging-mcp-tools.md](resources/systematic-debugging-mcp-tools.md) | the verbatim "Phase 0 evidence categories" block — same content for every project. When `skills.systematic-debugging.observability_mcp_servers` is empty, renders the no-tools fallback paragraph instead. The block is MCP-agnostic on purpose: tool names are discovered at runtime, not baked at generation time. |
139
142
  | `{{OBSERVABILITY_MCP_LIST}}` | derived from `skills.systematic-debugging.observability_mcp_servers` | comma-separated MCP server identifiers as the user named them at bootstrap (e.g. `sentry, datadog, our-internal-traces`). Renders `none configured` when empty. |
143
+ | `{{API_STYLE}}` | `skills.handoff-to-client.api_style` (handoff-to-client only) | `REST`, `GraphQL`, `gRPC`, `REST + webhooks` |
144
+ | `{{CLIENT_PLATFORMS_LIST}}` | `skills.handoff-to-client.client_platforms` (handoff-to-client only) | comma-separated, e.g. `iOS (Swift), Android (Kotlin), web SPA (React)` |
145
+ | `{{CLIENT_HANDOFF_DIR}}` | `skills.handoff-to-client.output_dir` (handoff-to-client only) | `.vinta-ai-workflows/client-handoffs` (default) |
146
+ | `{{API_SPEC_BLOCK}}` | derived from `skills.handoff-to-client.api_spec_path` (handoff-to-client only) | when set: a paragraph instructing the agent to regenerate/read the spec at that path on both base and branch and diff the two as the primary change-enumeration source (cross-checking against the code diff). When absent: a one-line note that no machine-readable spec exists, so shapes come from route/serializer code alone. |
140
147
  | `{{DEPENDENCY_LICENSE_BLOCK}}` | derived from `policies.dependency_licenses` | Top-level `## Adding new third-party dependencies` section. Empty string when `enforcement: off` or the block is absent. When `block` / `warn`: short paragraph naming the enforcement mode + the forbidden SPDX list + the pre-install check (`npm view <pkg> license`, PyPI metadata, etc.) + a one-line pointer to the **Dependency licenses** section in [AGENTS.md](AGENTS.md) for the full table including `allowed_overrides` and `notes`. See [resources/dependency-license-block.md](resources/dependency-license-block.md) for the canonical body. |
141
148
  | `{{DEPENDENCY_LICENSE_LAYER1_CHECK}}` | derived from `policies.dependency_licenses` | Layer 1 review checklist item. Empty string when `enforcement: off`. When `block` / `warn`: `6. **Dependency license scan**: \`git diff package.json pyproject.toml ...\` (project-relevant manifests) — for every added dep look up its SPDX license (\`npm view <pkg> license\`, PyPI metadata, repo \`LICENSE\`). A license in \`policies.dependency_licenses.forbidden_spdx\` and not in \`allowed_overrides\` is a BLOCKER (when \`block\`) or a SHOULD-FIX (when \`warn\`). A missing / \`UNKNOWN\` / undeclared license is **always a BLOCKER** regardless of enforcement mode — there is no override to silently bless undisclosed terms.` |
142
149
  | `{{DEPENDENCY_LICENSE_RULE_LINE}}` | derived from `policies.dependency_licenses` | Important-rules bullet. Empty string when `enforcement: off`. When `block`: `- **License check before any new dep.** Refuse \`npm add\` / \`pnpm add\` / \`pip install\` / \`poetry add\` / \`uv add\` / \`cargo add\` / \`go get\` when the package's SPDX license is in the forbidden list — see AGENTS.md **Dependency licenses**. User can grant a one-off override after acknowledging the violation; record the override in \`policies.dependency_licenses.allowed_overrides\` before re-running.` When `warn`: same line but `Proceed but record the violation in the phase report` instead of `Refuse`. |
@@ -207,6 +214,7 @@ Render each template (expand includes → substitute placeholders → write), pr
207
214
  - `ai-tools/skills/integrate-phase/SKILL.md` (from `plan-execution/shell/integrate-phase-template.md`) — **or**, under `ask`, `ai-tools/skills/integrate-phase-stacked/SKILL.md` + `ai-tools/skills/integrate-phase-modular/SKILL.md` (same template rendered twice)
208
215
  - `ai-tools/skills/amend-plan/SKILL.md` (from `plan-execution/shell/amend-plan-template.md`)
209
216
  - `ai-tools/skills/systematic-debugging/SKILL.md` (from `systematic-debugging-template.md`) — only when `foundation_skills.systematic-debugging: enabled`
217
+ - `ai-tools/skills/handoff-to-client/SKILL.md` (from `handoff-to-client-template.md`) — only when `foundation_skills.handoff-to-client: enabled`
210
218
 
211
219
  The first five are the **plan-execution unit** — render them together (they share partials + placeholders + cross-links); a change to one partial ripples to every shell that includes it.
212
220
 
@@ -284,7 +292,7 @@ Length: 100–300 lines. Shorter = under-specified. Longer = should probably spl
284
292
  - **Don't ship copy-pasted source-project SKILL.md files unchanged.** Run search-and-replace for source project names / paths / commands before saving.
285
293
  - **Foundation set is a unit.** Always copy `plan-feature` + `create-spec` + `open-pr-from-context` together — they reference each other. `create-qa-use-cases` joins only when `add-e2e-test` is enabled; when it's not, strip `plan-feature`'s e2e regions (the `<!-- e2e:start/end -->` pass) so no cross-link dangles.
286
294
  - **The plan-execution unit is generated, not copied.** `implement-plan` + `implement-phase` + `review-phase` + `integrate-phase` + `amend-plan` all have too much project-specific content for verbatim shipping. They are separate files but a **co-shipped unit** — never emit the conductors without the three sub-skills; a conductor whose `[implement-phase]` / `[review-phase]` / integrate link dangles is a broken skill.
287
- - **Optional skills (`add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`) are gated by user answer.** Don't ship them by default.
295
+ - **Optional skills (`add-e2e-test`, `add-env-var`, `add-one-off-script`, `prepare-worktree`, `thermo-nuclear-code-quality-review`, `handoff-to-client`) are gated by user answer.** Don't ship them by default. `handoff-to-client` is additionally template-rendered (bucket B) — its config lives under `skills.handoff-to-client.*`.
288
296
  - **Each skill solves one job.** Two unrelated checklists → split.
289
297
  - **Reference real files in the target.** Skill links must point to existing paths.
290
298
  - **Skills auto-load by description.** Specific triggers, specific outcomes.
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: handoff
3
+ description: Write or consume a session-continuation handoff document under `.vinta-ai-workflows/handoffs/` so a fresh agent session (or a different agent / teammate) can resume in-flight work without re-deriving context. Use when the user says "hand this off", "write a handoff", "wrap this up for another agent", "prepare a handoff doc", or — in resume mode — "pick up from the handoff", "resume from handoff", or points at a handoff file. Captures goal, current state, decisions with rationale, files touched, verification status, and the exact next step.
4
+ ---
5
+
6
+ # Handoff
7
+
8
+ Context dies with the session. A handoff document is the bridge: everything a fresh agent needs to continue the work, written down while the outgoing agent still knows it. The reader has none of your conversation history — write for someone who knows the codebase conventions but nothing about this task.
9
+
10
+ Two modes. Pick by what the user asked for:
11
+
12
+ - **Write mode** — capture the current task into a handoff doc. Trigger: "hand this off", "wrap up for another agent", "write a handoff before we stop".
13
+ - **Resume mode** — start from an existing handoff doc. Trigger: "resume from the handoff", "pick up where the last session left off", or the user pastes/points at a handoff file.
14
+
15
+ ## Write mode
16
+
17
+ ### 1. Gather real state — never from memory alone
18
+
19
+ Collect each of these from the repo, not from what you recall doing:
20
+
21
+ 1. `git status --short` + `git diff --stat` — uncommitted work.
22
+ 2. `git log --oneline <default-branch>..HEAD` — commits this task produced (skip if on the default branch).
23
+ 3. Current branch name and its upstream/base.
24
+ 4. Any in-flight plan or tracking artifacts: `ai-plans/*_IMPLEMENTATION_PLAN.md`, `TRACKING_*.md`, `.vinta-ai-workflows/prs-context/` files with `status: pending`.
25
+ 5. Open PRs for this branch, if a PR CLI is available (`gh pr view` / `glab mr view`).
26
+ 6. Test / lint / build status: what was last run, and did it pass? If you don't know, say "not verified" — do not guess.
27
+
28
+ ### 2. Write the document
29
+
30
+ Path: `.vinta-ai-workflows/handoffs/{YYYY-MM-DD}-{task-slug}.md` (e.g. `2026-07-11-fix-invoice-rounding.md`). Create the directory if missing. If a handoff for the same task slug already exists, supersede it: write the new file with today's date and add a `supersedes:` line pointing at the old one — never silently overwrite.
31
+
32
+ Structure:
33
+
34
+ ```markdown
35
+ # Handoff: {one-line task title}
36
+
37
+ - **Date:** {YYYY-MM-DD}
38
+ - **Branch:** {branch} (base: {base-branch})
39
+ - **Status:** {in-progress | blocked | ready-for-review}
40
+ - **Supersedes:** {path to previous handoff, or omit}
41
+
42
+ ## Goal
43
+ What the task is trying to achieve and why — the original ask, plus any scope changes agreed with the user since.
44
+
45
+ ## Current state
46
+ What is DONE and verified, what is done but NOT verified, what is not started.
47
+ Cite commits (`abc1234`) and files. Include the exact uncommitted-work summary
48
+ from `git status` if anything is uncommitted.
49
+
50
+ ## Decisions made
51
+ Each decision the next agent must not accidentally relitigate:
52
+ - **{decision}** — {rationale}. Alternatives considered: {…, and why rejected}.
53
+
54
+ ## Landmines
55
+ Gotchas discovered the hard way: flaky tests, misleading names, code that looks
56
+ wrong but is correct (and why), env quirks, anything you'd warn a teammate about.
57
+
58
+ ## Next step
59
+ The SINGLE most important next action, concrete enough to start immediately
60
+ (file, command, expected outcome). Then the rest of the remaining work as an
61
+ ordered list.
62
+
63
+ ## Verification
64
+ How to confirm the finished work is correct: commands to run, flows to exercise,
65
+ what "passing" looks like.
66
+ ```
67
+
68
+ ### 3. Quality gate before saving
69
+
70
+ - Every claim of "done" is backed by a commit hash or a passing command you actually ran this session. Anything else is labeled "not verified".
71
+ - No references to "the conversation", "as discussed above", or "earlier" — the reader has no conversation.
72
+ - A stranger could execute **Next step** without asking a question.
73
+
74
+ ### 4. Tell the user where it landed
75
+
76
+ Report the file path. Note that `.vinta-ai-workflows/` is typically gitignored — if the handoff must reach another machine or teammate, they should share the file explicitly or commit it deliberately.
77
+
78
+ ## Resume mode
79
+
80
+ 1. **Read the handoff doc** in full. If the user didn't name one, list `.vinta-ai-workflows/handoffs/` and pick the most recent that isn't superseded; confirm the pick with the user if more than one task is plausible.
81
+ 2. **Verify its claims against the repo before trusting them.** The repo may have moved since the handoff was written:
82
+ - Named branch exists and you're on it (or switch after confirming with the user).
83
+ - Cited commits exist (`git log`), cited files exist, `git status` matches the described uncommitted state.
84
+ - Re-run the cheapest verification command from the **Verification** section to confirm the "done" claims still hold.
85
+ 3. **On mismatch, stop and reconcile** — tell the user what the handoff claims vs. what the repo shows. Never continue from stale premises.
86
+ 4. **Adopt the decisions.** Treat **Decisions made** as settled unless the user reopens one; do not re-explore rejected alternatives.
87
+ 5. **Continue from Next step.** When the work later stops again unfinished, write a fresh handoff (write mode) superseding this one.
88
+
89
+ ## Pitfalls
90
+
91
+ - **Writing the handoff from memory.** The doc says "tests pass" but they were never run after the last edit. Gather state from the repo (step 1) — every time.
92
+ - **Recording what happened instead of what's next.** A chronological diary of the session is not a handoff. The reader needs current state + next action, not the journey.
93
+ - **Omitting rejected alternatives.** The next agent re-derives the rejected approach, spends an hour, and hits the same wall. One line per rejection prevents this.
94
+ - **Vague next step.** "Continue the refactor" is useless. "Extract the retry logic in `client.py` into `retry.py`, then make `test_client.py` pass again" is a handoff.
95
+ - **Resume mode trusting the doc blindly.** Handoffs go stale — a teammate may have pushed to the branch since. Verify (resume step 2) before building on it.
96
+
97
+ ## Verification
98
+
99
+ - Write mode: the file exists at the reported path, follows the structure above, and contains no unverified "done" claims.
100
+ - Resume mode: repo state matched the doc (or mismatches were surfaced), and work continued from the doc's **Next step** — not from a fresh re-derivation.
@@ -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
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: handoff-to-client
3
+ description: Generate a markdown API-change handoff document for the client teams consuming {{PROJECT_NAME}}'s {{API_STYLE}} API ({{CLIENT_PLATFORMS_LIST}}). Documents every endpoint/operation added, changed, deprecated, or removed on the current branch relative to `{{DEFAULT_BRANCH}}` — request/response shapes, auth, errors, breaking-change flags, and per-platform migration notes — so client implementers can adopt the changes without reading this repo's source. Use when the user says "write the client handoff", "document the API changes for the clients", "hand off to the frontend/mobile team", or before merging an API-changing branch.
4
+ ---
5
+
6
+ # Handoff to client
7
+
8
+ {{PROJECT_NAME}} ({{STACK_SUMMARY}}) is an API-only repo — its consumers live in separate codebases: {{CLIENT_PLATFORMS_LIST}}. Client implementers cannot read this repo's diff; this skill turns an API-changing branch into a self-contained markdown document they implement against.
9
+
10
+ The document is a contract description, not a changelog: every change carries enough shape detail (fields, types, nullability, examples) that a client engineer can code against it without opening this repo.
11
+
12
+ ## Step 0 — Resolve the scope
13
+
14
+ Default scope is the **current branch vs `{{DEFAULT_BRANCH}}`**:
15
+
16
+ ```
17
+ git fetch origin {{DEFAULT_BRANCH}}
18
+ git diff origin/{{DEFAULT_BRANCH}}...HEAD --stat
19
+ ```
20
+
21
+ Overrides, when the user asks: an explicit commit range (`<from>..<to>`), a merged PR, or a whole feature plan (enumerate the plan's phase branches/commits from its tracking file and union their diffs). State the resolved scope in the output doc's header.
22
+
23
+ If the resolved diff touches no API surface at all, say so and stop — do not fabricate a document.
24
+
25
+ ## Step 1 — Enumerate the API surface changes
26
+
27
+ Work from the diff, never from memory:
28
+
29
+ 1. List changed files in the scope and keep the API-relevant ones: route/URL declarations, controllers/views/resolvers, serializers/schemas/DTOs, auth/permission code, error handlers, API versioning config.
30
+ 2. For each, read the changed hunks and map them to concrete operations (method + path for REST; query/mutation/subscription for GraphQL; service/rpc for gRPC).
31
+ 3. Classify every operation touched: **added**, **changed**, **deprecated**, or **removed**.
32
+ 4. For each **changed** operation, diff the request and response shapes field by field: added fields, removed fields, type changes, nullability changes, renamed fields, default changes, new/changed validation rules, pagination or filtering changes.
33
+ 5. Flag **breaking** vs **non-breaking**. Breaking = anything an existing client call could fail or misbehave on: removed/renamed field or endpoint, narrowed type, newly-required request field, changed status code or error shape, auth/permission tightening. Additive-and-optional is non-breaking.
34
+
35
+ {{API_SPEC_BLOCK}}
36
+
37
+ Also sweep for non-endpoint contract changes clients still feel: auth flows (token lifetimes, scopes, header names), rate limits, webhooks/event payloads, websocket messages, file-upload conventions, and deprecation timelines.
38
+
39
+ ## Step 2 — Write the document
40
+
41
+ Path: `{{CLIENT_HANDOFF_DIR}}/{YYYY-MM-DD}-{branch-or-feature-slug}.md`. Create the directory if missing.
42
+
43
+ ```markdown
44
+ # API changes: {feature / branch title}
45
+
46
+ - **Date:** {YYYY-MM-DD}
47
+ - **Scope:** {branch} vs {{DEFAULT_BRANCH}} ({short-sha range})
48
+ - **Audience:** {{CLIENT_PLATFORMS_LIST}}
49
+ - **Breaking changes:** {count, or "none"}
50
+
51
+ ## Summary
52
+ 2–5 sentences: what shipped and why clients care. Lead with breaking changes.
53
+
54
+ ## Breaking changes ← omit section if none; never bury these
55
+ Per change: what breaks, which operations, what the client must do, and the
56
+ deadline/version after which the old behavior disappears.
57
+
58
+ ## {Operation-by-operation sections, grouped added / changed / deprecated / removed}
59
+
60
+ ### {METHOD /path} or {operationName}
61
+ - **Status:** added | changed | deprecated | removed — {breaking? yes/no}
62
+ - **Auth:** {scheme, required scopes/permissions}
63
+ - **Request:** field table or annotated example — name, type, required?,
64
+ constraints, default. For *changed*: call out exactly what differs from before.
65
+ - **Response:** per status code — annotated example JSON with field meanings,
66
+ nullability, enum values spelled out.
67
+ - **Errors:** status codes + error body shape + when each fires.
68
+ - **Example:** one complete request/response pair with realistic (fake) data.
69
+ - **Client migration notes:** what each platform ({{CLIENT_PLATFORMS_LIST}})
70
+ concretely changes — omit platforms unaffected by this operation.
71
+
72
+ ## Other contract changes
73
+ Auth flow / rate limits / webhooks / versioning changes from the Step 1 sweep.
74
+
75
+ ## Rollout
76
+ Is the change live, behind a flag, or awaiting deploy? Environment availability
77
+ (staging first?), and the sequencing clients must respect.
78
+ ```
79
+
80
+ Rules for the body:
81
+
82
+ - **Examples over prose.** Every operation gets at least one realistic request/response example. Use plausible fake data — never real user data, tokens, or secrets copied from fixtures or logs.
83
+ - **Shape from code, not intent.** Derive field names, types, and nullability from the serializer/schema/resolver code in the diff (or the regenerated spec), not from the plan document or commit messages.
84
+ - **Self-contained.** No links into this repo's source as the primary explanation; the audience may not have repo access. Citing paths as *provenance* is fine.
85
+ - **Neutral tone for migration notes.** Describe what the client must handle; don't prescribe their internal architecture.
86
+
87
+ ## Step 3 — Verify before handing off
88
+
89
+ 1. Re-read each documented operation against the actual code one final time — signatures drift during writing.
90
+ 2. Grep the diff for API-relevant files you did NOT document and confirm each is genuinely client-invisible (internal refactor, tests, comments).
91
+ 3. Confirm every **breaking** flag: would an unmodified existing client call still succeed? If unsure, mark it breaking — false alarms are cheaper than silent breakage.
92
+ 4. Exercise at least one added/changed endpoint against a locally running instance when feasible, and paste the real (redacted) response into the doc's example.
93
+ 5. Report the doc path to the user, flag the breaking-change count, and remind them `{{CLIENT_HANDOFF_DIR}}` may be gitignored — share or commit the file deliberately so it actually reaches the client teams.
94
+
95
+ ## Pitfalls
96
+
97
+ - **Documenting the plan instead of the code.** Plans drift during implementation; the diff is the truth. Always derive shapes from what actually merged into the branch.
98
+ - **Missing error-shape changes.** Clients parse error bodies too. A changed error envelope breaks clients just as hard as a changed success payload.
99
+ - **"Non-breaking" by wishful thinking.** A field that changed from `string` to `string | null` breaks any client that never null-checks. Judge breakage from the strictest plausible client, not the friendliest.
100
+ - **Serializer-level changes hidden behind unchanged routes.** A diff can change a response shape without touching any route file — sweep serializers/schemas/DTOs even when the route list looks untouched.
101
+ - **Stale doc after review fixes.** If review feedback changes the API after the handoff was written, regenerate the doc — a superseded handoff to clients is worse than none.
102
+
103
+ ## Verification
104
+
105
+ - The doc exists under `{{CLIENT_HANDOFF_DIR}}/`, is scoped-and-dated, and every API-relevant file in the diff is either documented or consciously excluded.
106
+ - Every breaking change appears in the **Breaking changes** section, not only in its per-operation entry.
107
+ - A client engineer with zero access to this repo could implement every documented change from the doc alone.
@@ -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
 
@@ -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