vinta-ai-workflows 0.1.7
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 +830 -0
- package/LICENSE +21 -0
- package/README.md +547 -0
- package/package.json +27 -0
- package/schemas/README.md +84 -0
- package/schemas/mcp-preflight-cache.v1.schema.json +50 -0
- package/schemas/prs-context-comments.v1.schema.json +51 -0
- package/schemas/prs-context-frontmatter.v1.schema.json +77 -0
- package/schemas/sub-agent.v1.schema.json +105 -0
- package/schemas/vinta-ai-workflows-config.v1.schema.json +283 -0
- package/skills/vinta-analyze-codebase/SKILL.md +325 -0
- package/skills/vinta-bootstrap-ai-tools/SKILL.md +375 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/README.md +50 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/django/notes.md +52 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/medplum/notes.md +45 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/nextjs-app-router/notes.md +35 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/python-package/notes.md +31 -0
- package/skills/vinta-bootstrap-ai-tools/resources/stacks/typescript-monorepo/notes.md +32 -0
- package/skills/vinta-derive-skills/SKILL.md +200 -0
- package/skills/vinta-derive-skills/resources/amend-plan-template.md +355 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/SKILL.md +292 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.py +602 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/add-one-off-script/resources/one_off_script_base.ts +624 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-qa-use-cases/SKILL.md +232 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/create-spec/SKILL.md +235 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/SKILL.md +78 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/open-pr-from-context/scripts/open-pr.sh +357 -0
- package/skills/vinta-derive-skills/resources/foundation-skills/plan-feature/SKILL.md +418 -0
- package/skills/vinta-derive-skills/resources/implement-plan-template.md +375 -0
- package/skills/vinta-derive-skills/resources/prs-context-template.md +91 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-mcp-tools.md +125 -0
- package/skills/vinta-derive-skills/resources/systematic-debugging-template.md +167 -0
- package/skills/vinta-derive-subagents/SKILL.md +192 -0
- package/skills/vinta-install-ai-tools-setup/SKILL.md +138 -0
- package/skills/vinta-install-ai-tools-setup/resources/setup-ai-tools.mjs +392 -0
- package/skills/vinta-migrate-plans-specs/SKILL.md +229 -0
- package/skills/vinta-sync-ai-tools/SKILL.md +184 -0
- package/skills/vinta-update-project-skills/SKILL.md +178 -0
- package/skills/vinta-write-agents-md/SKILL.md +192 -0
- package/vinta-ai-workflows.mjs +316 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plan-feature
|
|
3
|
+
description: Author a phased implementation plan for a new feature following the repo's `ai-plans/` conventions. Use when the user asks to "plan", "design", "scope", or "break down" a feature, write an implementation plan / IMPLEMENTATION_PLAN.md, or turn a spec/idea into a phased roadmap. Always interrogates the requester before drafting.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plan Feature
|
|
7
|
+
|
|
8
|
+
Plans live in `ai-plans/` as `YYYY-MM-DD-FEATURE_NAME_IMPLEMENTATION_PLAN.md` (uppercase + underscores). `..._SPEC.md` sibling exists → **read first**. Plan translates spec into phased delivery, doesn't re-derive requirements. No spec? Point at [create-spec](../create-spec/SKILL.md) first; plan without spec = plausible-sounding but unverified. Spec/plan pair share `YYYY-MM-DD-FEATURE_NAME` prefix.
|
|
9
|
+
|
|
10
|
+
## Step 0 — Interrogate before drafting (NON-NEGOTIABLE)
|
|
11
|
+
|
|
12
|
+
**Never assume requester want.** *"Plan bookmarks feature"* hide ≥dozen decisions cheaper to surface now than unwind in Phase 4.
|
|
13
|
+
|
|
14
|
+
Ask below in **batched, numbered groups**. Skip only when SPEC.md or prior conversation **explicitly** answers — never because guess. Can guess but not 100% sure → ask + state default ("default: per-user; confirm or override").
|
|
15
|
+
|
|
16
|
+
Drop irrelevant groups; don't drop questions inside relevant group:
|
|
17
|
+
|
|
18
|
+
### Use `AskUserQuestion` for finite-choice questions
|
|
19
|
+
|
|
20
|
+
Every question in groups B–J with discrete answer set — yes/no, named option, finite enum — **must** go through `AskUserQuestion` tool, not free-form prose. Why:
|
|
21
|
+
|
|
22
|
+
- User picks; no retyping context.
|
|
23
|
+
- Multiple related questions ride one `AskUserQuestion` call (tool accepts list of questions, each own option set). Batch per group: one call for the **Data model & storage** group, one for the **API surface** group, etc.
|
|
24
|
+
- Short option label per choice; rationale ("default: per-user — confirm or override") goes in question header, not option labels.
|
|
25
|
+
|
|
26
|
+
Plain prose (no tool) **only** when answer genuinely open-ended: "walk me through user journey", "what success look like in your words", "what deadline driver". Group A mostly prose; B–J mostly closed-choice.
|
|
27
|
+
|
|
28
|
+
### Iterative asking when no `AskUserQuestion` (or question open-ended)
|
|
29
|
+
|
|
30
|
+
Two cases force iterative single-question mode:
|
|
31
|
+
|
|
32
|
+
1. **`AskUserQuestion` genuinely unavailable** (harness errored on call, not deferred). Try once — confirm actually missing, not schema-deferred.
|
|
33
|
+
2. **Question genuinely open-ended** (no finite option set — narrative, journey, free-form motivation, deadline date).
|
|
34
|
+
|
|
35
|
+
Both cases: **ask one question at a time, wait for answer, then ask next.** Don't dump 5 open questions in one paragraph — user reads three, answers two, third gets lost. Iterate:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
> Q1: Who is the primary actor for this flow?
|
|
39
|
+
[wait for answer]
|
|
40
|
+
> Q2: Walk me through what they do today when they hit this problem.
|
|
41
|
+
[wait for answer]
|
|
42
|
+
> Q3: …
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Closed-choice questions in same group still ride single `AskUserQuestion` call — only open-ended ones split into one-per-message. Mixing in one group fine: send closed-choice batch via tool, then iterate open ones in plain prose after.
|
|
46
|
+
|
|
47
|
+
Never flatten ten questions into one prose paragraph just because tool unavailable. Iteration = fallback, not consolidation.
|
|
48
|
+
|
|
49
|
+
### A. Problem & users
|
|
50
|
+
1. Problem this solves, for whom (tenant admins, internal ops, external integrations, end-users via UI)?
|
|
51
|
+
2. Success looks like — what behavior or metric changes?
|
|
52
|
+
3. Workflows requester *thinks* in scope but actually belong to follow-up?
|
|
53
|
+
4. Who else cares about this landing? Anyone need looping in on contract?
|
|
54
|
+
|
|
55
|
+
### B. Scope & non-goals
|
|
56
|
+
1. **Explicitly out of scope** for v1? Force non-goals list — where most plans drift.
|
|
57
|
+
2. v1.x / v2 already implied? Name it so we don't bake assumptions into v1's data model.
|
|
58
|
+
|
|
59
|
+
### C. Data model & storage
|
|
60
|
+
1. New table, new column on existing, JSONB blob, side table, no persistence?
|
|
61
|
+
2. Touching an existing table on a hot path (high-volume, frequently joined, partitioned)? Adding a column there has very different costs than a side table.
|
|
62
|
+
3. Multi-tenancy: per-tenant, per-user-per-tenant, tenant-shared?
|
|
63
|
+
4. Partitioning: do related tables partition by `tenant_id`? Should this one (for partition-wise joins)?
|
|
64
|
+
5. Cardinality: rough upper bound rows per tenant?
|
|
65
|
+
6. Soft FK vs hard FK to partitioned tables — cleanup story on delete?
|
|
66
|
+
7. Indexing: which predicates need index-friendly?
|
|
67
|
+
|
|
68
|
+
### D. API surface
|
|
69
|
+
1. REST (internal versioned API), Public GraphQL, internal-only, or several?
|
|
70
|
+
2. Auth: internal session/JWT, public API token (`Authorization: Bearer ...`), service-to-service?
|
|
71
|
+
3. Bulk-upsert? Endpoints fed by integrations should be bulk-upsert.
|
|
72
|
+
4. Client SDKs or external consumers locking in contract?
|
|
73
|
+
|
|
74
|
+
### E. Producers & consumers (cross-repo)
|
|
75
|
+
1. Data flowing in from an upstream producer / integration repo? Which third-party providers feed it?
|
|
76
|
+
2. Downstream system reading new data — warehouse / lake, analytics, exports?
|
|
77
|
+
3. Deploy ordering between repos — what gets deployed first; what breaks if order flips?
|
|
78
|
+
|
|
79
|
+
### F. Backwards compatibility & semantics
|
|
80
|
+
1. Existing clients/integrations — does omitting new field mean "don't change" vs "clear"? (omit-vs-empty-list = recurring bug source)
|
|
81
|
+
2. Existing rules / records expected to keep behaving same when new field defaults to null/empty? Confirm explicitly.
|
|
82
|
+
3. Replace vs merge semantics on writes?
|
|
83
|
+
4. Case-sensitivity, normalization (trim, lowercase), dedupe — at which layer?
|
|
84
|
+
|
|
85
|
+
### G. Concurrency, transactions, idempotency
|
|
86
|
+
1. Race conditions (concurrent batch edits, parallel workers / serverless invocations on the same row)?
|
|
87
|
+
2. Atomic-batch semantics: all-or-nothing, best-effort?
|
|
88
|
+
3. Upsert needs `last_updated_at` guard so we don't overwrite newer state?
|
|
89
|
+
|
|
90
|
+
### H. Rollout & risk
|
|
91
|
+
1. **Feature flag** — declared in the project's feature-flag module (substitute the actual path during planning). **Default YES** when feature touches existing flows (changes shape of existing endpoint, alters query path on hot table, modifies routing/matching, mutates data on existing rows, adds branching to use case with callers). Confirm flag key + scope (per-tenant vs per-request, by whatever names the project's flag API uses). Skip only when **purely additive new surface** (brand-new endpoint, table, admin page no existing code reads/writes) — even then, ask before dropping.
|
|
92
|
+
2. Backfill needed? Idempotent? Resumable?
|
|
93
|
+
3. Migration safety: locks, rewrites, query-plan regressions on hot tables?
|
|
94
|
+
4. Rollback plan: revert migration, flag-off, hot-patch?
|
|
95
|
+
|
|
96
|
+
### I. Observability & validation
|
|
97
|
+
1. Metric / log / dashboard tells us it's working in prod?
|
|
98
|
+
2. Audit logging requirements (whatever audit-trail app/module the project uses)?
|
|
99
|
+
3. How measure producer adoption before downstream phases ship?
|
|
100
|
+
|
|
101
|
+
### J. Edge cases & failure modes
|
|
102
|
+
1. Behavior when new field partially populated, malformed, oversized? Reject whole batch, drop offending entry?
|
|
103
|
+
2. Cycle / depth / cardinality limits — where (serializer vs use case vs DB constraint)?
|
|
104
|
+
3. Acceptable to silently truncate vs reject loudly?
|
|
105
|
+
|
|
106
|
+
### Clarity loop — keep asking until done
|
|
107
|
+
|
|
108
|
+
Don't treat Step 0 as one-pass. After each round of answers, **scan for new gaps**: contradictions, follow-ups the answer surfaces, decisions that depend on something earlier left vague. Open another batch of questions for those. Repeat.
|
|
109
|
+
|
|
110
|
+
Loop exit conditions (all required):
|
|
111
|
+
- Every group A–J either fully answered or explicitly waived.
|
|
112
|
+
- Every answer's downstream questions also asked + answered.
|
|
113
|
+
- No "we'll figure that out later" — that's **Open Questions** material; either it has a recommended default + owner, or it gets resolved now.
|
|
114
|
+
- You can write each Phase's Goal + Acceptance line right now without inventing.
|
|
115
|
+
|
|
116
|
+
If any condition fails → another `AskUserQuestion` round. Don't shortcut to drafting.
|
|
117
|
+
|
|
118
|
+
After answers stabilize: **read back decisions** as one-paragraph summary. Then issue one final `AskUserQuestion` with single question — *"Anything I got wrong before I draft?"* — options `Looks good`, `Some corrections (I'll list)`, `More to clarify`, `Stop, rethink`. `More to clarify` → another loop iteration. Only draft when user picks `Looks good`.
|
|
119
|
+
|
|
120
|
+
Pushback *"just write the plan"*: write it but **mark every assumption explicitly** in "Guiding Decisions" table.
|
|
121
|
+
|
|
122
|
+
## Plan structure
|
|
123
|
+
|
|
124
|
+
```markdown
|
|
125
|
+
# {Feature Name} — Implementation Plan
|
|
126
|
+
|
|
127
|
+
## 1. Goals
|
|
128
|
+
- 2-5 numbered concrete goals (the contract).
|
|
129
|
+
- Then "Non-goals:" bulleted list. **Always include non-goals.**
|
|
130
|
+
|
|
131
|
+
## 2. Guiding Decisions
|
|
132
|
+
| Decision | Resolution |
|
|
133
|
+
|---|---|
|
|
134
|
+
| **Storage shape** | … with the *why*, not just the what. |
|
|
135
|
+
| **Match semantics** | … |
|
|
136
|
+
| ... | ... |
|
|
137
|
+
|
|
138
|
+
## 3. Data Model Changes
|
|
139
|
+
### 3.1 New {Model}
|
|
140
|
+
Code block with model. Reference @app/path/to/file.py for files
|
|
141
|
+
that need editing. Note exports in __init__.py.
|
|
142
|
+
|
|
143
|
+
### 3.2 {Existing model}.{new_field}
|
|
144
|
+
...
|
|
145
|
+
|
|
146
|
+
### 3.3 Type plumbing
|
|
147
|
+
TypedDicts, dataclasses, NewType updates.
|
|
148
|
+
|
|
149
|
+
## 4. API Design (omit if no API surface)
|
|
150
|
+
### 4.1 {Endpoint group}
|
|
151
|
+
Method / path / payload / response shape / errors.
|
|
152
|
+
|
|
153
|
+
## 5. Phased Rollout
|
|
154
|
+
See "Phase structure" below.
|
|
155
|
+
|
|
156
|
+
## 6. Risk & Rollout Notes
|
|
157
|
+
Feature flag (key, scope, default, flip-on criterion, removal path),
|
|
158
|
+
locks, query-plan regressions, partition setup, view recreation,
|
|
159
|
+
backfill story, rollback story.
|
|
160
|
+
|
|
161
|
+
## 7. Open Questions
|
|
162
|
+
Decisions left to product/eng leadership, with recommended default.
|
|
163
|
+
|
|
164
|
+
## 8. Touch List
|
|
165
|
+
Files to be created / edited / cross-repo, grouped by phase.
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Don't invent new top-level sections. Skip non-applicable (e.g. omit "API Design" for pure data-pipeline) but keep numbering consecutive.
|
|
169
|
+
|
|
170
|
+
## Phase structure
|
|
171
|
+
|
|
172
|
+
### Naming: numbers + letters, consistently
|
|
173
|
+
|
|
174
|
+
- **Top-level**: `Phase 1`, `Phase 2`, …
|
|
175
|
+
- **Sub-phases (concern too big for one MR)**: `Phase 2a`, `Phase 2b`, `Phase 2c`. Use when one logical phase produces >300 LoC PR.
|
|
176
|
+
- **Parallel-track (different repo, different team, runs alongside)**: `Phase 1b`. Letter signals "different lane, same time", not "comes after".
|
|
177
|
+
- **Foundation phase**: `Phase 0` for pure scaffolding (new app skeleton, no behavior change). Optional.
|
|
178
|
+
- Consistent inside one plan: don't mix `Phase 2.1` with `Phase 3a`.
|
|
179
|
+
|
|
180
|
+
### Each phase MR-sized
|
|
181
|
+
|
|
182
|
+
Reviewer reads diff in 30 minutes:
|
|
183
|
+
|
|
184
|
+
- **Target**: ~100–300 LoC (tests included).
|
|
185
|
+
- **One concern per phase.** "Add field + write migration + wire into 4 use cases + update 3 SQL views" = four phases.
|
|
186
|
+
- **Independently mergeable.** Phase N merged + Phase N+1 stalled → system still working. No half-finished features behind flag with no flag-on path.
|
|
187
|
+
- **Own tests.** Every phase ships unit/integration tests. No "tests come in Phase 8."
|
|
188
|
+
- **Acceptance criterion.** Each phase ends with one-line "Acceptance:" — literally testable.
|
|
189
|
+
|
|
190
|
+
### One use-case per phase (mandatory)
|
|
191
|
+
|
|
192
|
+
Every spec use-case (entries under **Decisions → Use-cases** in the SPEC) gets **its own phase**. Never bundle two use-cases in one phase even when the diff is tiny. Bundling = larger PR + reviewer needs context for both flows + rollback drags both. Cost of an extra phase = one PR header. Cost of a bundled regression = hotfix + split-after-the-fact.
|
|
193
|
+
|
|
194
|
+
Apply even when:
|
|
195
|
+
- Two use-cases share the same endpoint — split anyway, the second phase is "wire use-case 2 into the existing endpoint." Reviewer reads ≤50 LoC.
|
|
196
|
+
- Use-cases are CRUD on same entity — Create / Read / Update / Delete are four phases, not one.
|
|
197
|
+
- "It's just one extra branch" — that branch hides edge cases. Separate phase forces explicit acceptance + tests for that branch.
|
|
198
|
+
|
|
199
|
+
Cross-cutting infra (shared types, migration, scaffolding) lands in a foundation phase before the use-case phases. Each subsequent use-case phase consumes that scaffolding.
|
|
200
|
+
|
|
201
|
+
### Phases creating new UI flow need happy-path E2E
|
|
202
|
+
|
|
203
|
+
Every phase that introduces or substantially changes a user-facing flow (new page, new modal, new wizard step, new gated action) **must** ship a Playwright e2e test covering at least the happy path in the same MR. Follow the [add-e2e-test](../add-e2e-test/SKILL.md) skill: pick the next free `PA###` / `PR###` id, update [QA_USE_CASES.md](QA_USE_CASES.md), add the page object + spec. **No `QA_USE_CASES.md` in the project yet?** Run [create-qa-use-cases](../create-qa-use-cases/SKILL.md) first to bootstrap the doc from this plan + spec — add-e2e-test appends, it doesn't create.
|
|
204
|
+
|
|
205
|
+
In the phase body, name the spec file path under **Tests → E2E**. If the phase is purely backend (API-only, bot, migration), skip — happy-path E2E only required when the phase reaches the browser.
|
|
206
|
+
|
|
207
|
+
**Capture screenshots on every affected UI**: the e2e spec takes one screenshot per distinct rendered state (landing page, each modal/wizard step, success toast, final state) — not just the final state. Spec writes to Playwright's **default per-test output dir** via `testInfo.outputPath('<id>-<NN>-<view-slug>.png')` (zero-padded step number, kebab-case slug describing what's on screen). Never hard-code `pr-screenshots/` in the spec. After the suite runs, a copy step moves matching files from `test-results/**/` into `pr-screenshots/`. The `pr-screenshots/` directory is gitignored — author drags the files into the PR description in numeric order so reviewers see the journey, not just the destination. See [add-e2e-test](../add-e2e-test/SKILL.md) for the strict filename convention + spec example + copy command.
|
|
208
|
+
|
|
209
|
+
Doesn't fit → split: `Phase 4a — Static validation`, `Phase 4b — Resolution engine`, `Phase 4c — Apply engine`, `Phase 4d — View wiring`.
|
|
210
|
+
|
|
211
|
+
### Phase template
|
|
212
|
+
|
|
213
|
+
```markdown
|
|
214
|
+
### Phase N{a} — {Crisp imperative title, ≤8 words}
|
|
215
|
+
|
|
216
|
+
**Goal**: one sentence on user-visible (or producer-visible) outcome.
|
|
217
|
+
"Ship value: none on its own" → say so explicitly + justify why scaffolding needed.
|
|
218
|
+
|
|
219
|
+
**Feature flag**: `{flag-key}` — {gated path; what runs when off vs on}.
|
|
220
|
+
Omit only if phase is purely scaffolding (no reachable behavior) or **Guiding Decisions** explicitly marks "no flag — purely additive surface".
|
|
221
|
+
|
|
222
|
+
Changes:
|
|
223
|
+
1. {File or module}: {what changes, what stays}.
|
|
224
|
+
2. {Next thing}.
|
|
225
|
+
3. ...
|
|
226
|
+
|
|
227
|
+
Spec use-case: {SPEC **Decisions → Use-cases** id/name this phase implements, or "shared scaffolding — no use-case yet"}.
|
|
228
|
+
|
|
229
|
+
Tests:
|
|
230
|
+
- **Unit**: {file path} — {what it covers}.
|
|
231
|
+
- **Integration**: {file path} — {what it covers, including edge cases user flagged in Step 0, AND flag-off test proving existing callers see no behavior change}.
|
|
232
|
+
- **E2E** (only when this phase reaches the browser): {e2e/tests/<app>/<id>-<slug>.spec.ts} — happy path covering the new flow. Spec writes screenshots to the Playwright default output dir via `testInfo.outputPath(...)`; post-run copy step moves them into `pr-screenshots/<id>-<step>.png`. Follow [add-e2e-test](../add-e2e-test/SKILL.md).
|
|
233
|
+
|
|
234
|
+
**Suggested AI model**: {tier choice + why}. See "AI model selection".
|
|
235
|
+
|
|
236
|
+
**Reusable skills**: {invoke `Skill(name)` — see "Project skills"}.
|
|
237
|
+
|
|
238
|
+
Acceptance: {one literal statement true after merge + deploy of this phase, only this phase}.
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Gate behavior changes behind feature flag by default
|
|
242
|
+
|
|
243
|
+
Feature touches **any existing flow** — existing callers hit new branches, new fields, new constraints, new query plans, differently-shaped responses → **plan for flag from Phase 1**. Default *flag on*, not off; ask in the Step 0 **Rollout & risk** group to confirm but don't silently drop.
|
|
244
|
+
|
|
245
|
+
In plan:
|
|
246
|
+
|
|
247
|
+
1. Declare flag in **Guiding Decisions**: key, scope (per-request vs per-tenant, using the project's flag API names), default (`false`), flip-on criterion ("after Phase 5 ships + reprocess job runs clean for 48h on staging").
|
|
248
|
+
2. Show flag definition site (the project's feature-flag module) in **Touch List**.
|
|
249
|
+
3. Every phase reachable from existing caller: name flag, describe what executes when **off** (must be pre-feature behavior, byte-for-byte where possible) vs **on**.
|
|
250
|
+
4. Data model change unconditional (column existing can't be gated)? Make sure *reads + writes* of column gated; off-flag tenant has zero observable change. Test asserts.
|
|
251
|
+
5. Phase N+1 (or **Risk & Rollout Notes** entry) for **flag rollout**: enable for one internal tenant → soak → staging → cohort → globally.
|
|
252
|
+
6. **Always end with dedicated final phase to remove flag.** Name `Phase N — Remove the {flag-key} feature flag`. **Mandatory** when flag declared — flag debt = real debt.
|
|
253
|
+
|
|
254
|
+
Legitimate skips:
|
|
255
|
+
|
|
256
|
+
- **Purely additive new surface**: brand-new endpoint at new path, brand-new table, brand-new admin page no existing code reads/writes. Borderline-additive (new app + new endpoints alongside existing surfaces): err on the side of adding the flag — would have needed one if it had touched an existing shared table.
|
|
257
|
+
- **Pure refactor with no behavior change**, provable via tests + diff review. Refactors don't need flags; features do.
|
|
258
|
+
|
|
259
|
+
Unsure? Treat as not additive + add flag. Cost of unused flag = one PR. Cost of non-flagged regression = hotfix + postmortem.
|
|
260
|
+
|
|
261
|
+
### Mandatory final phase: remove flag
|
|
262
|
+
|
|
263
|
+
Flag declared → **last phase must be dedicated removal phase**. Don't roll into Phase N's "and also clean up flag"; give own number so survives scope cuts + shows up in tracking.
|
|
264
|
+
|
|
265
|
+
Gated on real-world signal, not phase number — can't merge until flag on 100% long enough. Mark clearly so doesn't get rushed.
|
|
266
|
+
|
|
267
|
+
```markdown
|
|
268
|
+
### Phase N — Remove the `{flag-key}` feature flag
|
|
269
|
+
|
|
270
|
+
**Goal**: delete flag + dead off-branch so feature becomes unconditional. **Prerequisite**: flag has been on for 100% of tenants in production for at least {soak window — typically 2 weeks, or one full end-of-month/quarter cycle if feature touches reporting}, with no rollback or incident attributed.
|
|
271
|
+
|
|
272
|
+
**Feature flag**: removed in this phase.
|
|
273
|
+
|
|
274
|
+
Changes:
|
|
275
|
+
1. Delete flag declaration in the project's feature-flag module.
|
|
276
|
+
2. Every site calling the flag's check methods (`is_enabled(...)` / per-tenant variant, by whatever names the project uses): inline on-branch + delete off-branch. Touch list:
|
|
277
|
+
- {file 1}
|
|
278
|
+
- {file 2}
|
|
279
|
+
- …
|
|
280
|
+
3. Delete tests exercising flag-off path (added in earlier phases for backwards compatibility).
|
|
281
|
+
4. Flag controlled gated paths in tests via fixtures or parametrization → simplify to single (formerly on-flag) branch.
|
|
282
|
+
5. Search for stale references: `grep -r "{flag-key}"` + `grep -r "{FLAG_CONSTANT}"` should return zero.
|
|
283
|
+
|
|
284
|
+
Tests:
|
|
285
|
+
- Existing test suite passes unchanged on on-branch.
|
|
286
|
+
- Remove flag-parametrized tests no longer make sense.
|
|
287
|
+
|
|
288
|
+
**Suggested AI model**: Tier 1 — `claude-haiku-4-5` / `gpt-5-nano` / `gemini-2.5-flash-lite`. Mechanical deletion + inlining; cheap models excel.
|
|
289
|
+
|
|
290
|
+
**Reusable skills**: none — pure cleanup.
|
|
291
|
+
|
|
292
|
+
Acceptance: `grep -r "{flag-key}" app/ tests/` returns nothing, feature behaves identically to flag-on state, full test suite green.
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
Place as separate, numbered, last-in-list entry inside **Phased Rollout**. Also in **Touch List** under its own phase. **Required**.
|
|
296
|
+
|
|
297
|
+
### Order phases for slowest-moving dependency first
|
|
298
|
+
|
|
299
|
+
Common mistake: leave cross-repo producer wiring for last, then discover the upstream repo's deploy cadence is two weeks. Order so slowest path starts in Phase 1 (e.g. *"accept field, validate, drop on floor"*) + fast in-repo work fills in behind. Typical sequencing: `Phase 1` (API stub) → `Phase 1b` (cross-repo producer, parallel) → `Phase 2`+ (in-repo persistence).
|
|
300
|
+
|
|
301
|
+
### Never give time estimates
|
|
302
|
+
|
|
303
|
+
**Don't** write "~2 days" / "1 sprint" / "ETA: …". Time estimates for AI-implemented work pointless + become targets LLM optimizes against. **LoC sizing (`~150 LoC`) fine** — reviewability signal, not time.
|
|
304
|
+
|
|
305
|
+
## AI model selection per phase
|
|
306
|
+
|
|
307
|
+
For each phase, suggest **cheapest/fastest model likely to one-shot work**. Iterating with cheap model usually beats burning Opus tokens on CRUD scaffold.
|
|
308
|
+
|
|
309
|
+
### Tier 1 — cheapest/fastest (boilerplate, exact-precedent edits)
|
|
310
|
+
**Use for**: single migration adding column or index, exporting from `__init__.py`, registering admin, scaffolding empty Django app, thin serializer mirroring existing pattern verbatim.
|
|
311
|
+
|
|
312
|
+
- Anthropic: `claude-haiku-4-5`
|
|
313
|
+
- OpenAI: `gpt-5-nano` (fall back to `gpt-5-mini` if file has any branching logic)
|
|
314
|
+
- Google: `gemini-2.5-flash-lite`
|
|
315
|
+
|
|
316
|
+
### Tier 2 — standard pattern application
|
|
317
|
+
**Use for**: repository methods, DRF serializer with non-trivial validation, ViewSet wiring with filterset, pytest unit/integration tests against established fixtures, simple HStore/ArrayField additions.
|
|
318
|
+
|
|
319
|
+
- Anthropic: `claude-haiku-4-5` (with iteration), step up to `claude-sonnet-4-6` if phase touches >3 files
|
|
320
|
+
- OpenAI: `gpt-5-mini`
|
|
321
|
+
- Google: `gemini-2.5-flash`
|
|
322
|
+
|
|
323
|
+
### Tier 3 — multi-file orchestration, business logic, SQL views
|
|
324
|
+
**Use for**: use case coordinating across repositories with non-trivial branching, new `vw_*` view + non-managed model + migration, serializer with cross-field validation affecting use-case behavior, integration tests covering concurrency edges.
|
|
325
|
+
|
|
326
|
+
- Anthropic: `claude-sonnet-4-6`
|
|
327
|
+
- OpenAI: `gpt-5`
|
|
328
|
+
- Google: `gemini-2.5-pro` (or `gemini-3-pro` for stronger code recall)
|
|
329
|
+
|
|
330
|
+
### Tier 4 — architectural / novel / hard
|
|
331
|
+
**Use for**: cycle detection in user-mutable trees, transactional batch protocols with deferred constraints, partitioned-to-partitioned FK design, perf tuning slow query against partitioned hot table, debugging heisenbug.
|
|
332
|
+
|
|
333
|
+
- Anthropic: `claude-opus-4-7` (`[1m]` 1M-context for large codebases)
|
|
334
|
+
- OpenAI: `gpt-5` with extended thinking, or `o3` / `o4` for pure reasoning
|
|
335
|
+
- Google: `gemini-3-pro` with thinking
|
|
336
|
+
|
|
337
|
+
### Writing the suggestion
|
|
338
|
+
|
|
339
|
+
> **Suggested AI model**: Tier 1 — `claude-haiku-4-5` / `gpt-5-nano` / `gemini-2.5-flash-lite`. Single-field migration + model export, exact precedent in `@<app>/<module>/models/<file>.py`.
|
|
340
|
+
|
|
341
|
+
When one tier doesn't fit:
|
|
342
|
+
|
|
343
|
+
> **Suggested AI model**: Tier 2 for repository + serializer (Haiku 4.5 / GPT-5 mini / Gemini Flash); step up to Tier 3 (`claude-sonnet-4-6`) for integration test spanning upsert → routing → reprocess.
|
|
344
|
+
|
|
345
|
+
**Default to cheapest tier that plausibly works, not safest.** Cheap models failing fast beats expensive succeeding slowly.
|
|
346
|
+
|
|
347
|
+
## Project skills to leverage
|
|
348
|
+
|
|
349
|
+
Skills under the project's `ai-tools/skills/` directory encode hard-won conventions. **Reference by name in each relevant phase** so implementer invokes via `Skill(name)` instead of re-deriving.
|
|
350
|
+
|
|
351
|
+
| Skill | Invoke when phase… |
|
|
352
|
+
|---|---|
|
|
353
|
+
| `create-model` | adds new Django model / database table |
|
|
354
|
+
| `create-postgres-view` | adds or modifies `vw_*` (or MV, function, type) |
|
|
355
|
+
| `create-postgres-function` | adds or modifies `CREATE FUNCTION` / `upsert_ct_*` / `ft_*` / aggregate |
|
|
356
|
+
| `create-cloud-function` | scaffolds new serverless function |
|
|
357
|
+
| `create-data-export` | adds async CSV/Excel export |
|
|
358
|
+
| `create-data-import` | adds CSV import |
|
|
359
|
+
| `graphql-public-query` | adds a query/mutation under the project's public GraphQL module |
|
|
360
|
+
| `write-tests` | writes pytest unit/integration tests following fixture catalog + snapshot conventions |
|
|
361
|
+
|
|
362
|
+
In phase:
|
|
363
|
+
|
|
364
|
+
> **Reusable skills**: `create-postgres-view` (for the relevant `vw_*.sql` change); `write-tests` (for the integration test under the project's integration-tests dir).
|
|
365
|
+
|
|
366
|
+
No clean skill match? Omit line — don't fabricate.
|
|
367
|
+
|
|
368
|
+
## File references
|
|
369
|
+
|
|
370
|
+
`@path/to/file.py` for files relative to repo root when *naming* file inside plan body or discovery questions. Project convention; agent harness resolves.
|
|
371
|
+
|
|
372
|
+
For inline links in narrative prose, GitHub-flavored markdown links work + preferred for line-range deep-links:
|
|
373
|
+
|
|
374
|
+
```markdown
|
|
375
|
+
See `upsert_records` in [records.py:92-96](../<app>/<module>/models/records.py#L92-L96).
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
Don't mix styles within one sentence. In **Touch List**, use `@path` for new files + `[name](relative-path)` for edited files when want line numbers.
|
|
379
|
+
|
|
380
|
+
## What to avoid
|
|
381
|
+
|
|
382
|
+
- **No `§N` shorthand for section references — anywhere in the plan body.** Use section names: `Goals + Non-goals`, `Guiding Decisions`, `Data Model Changes`, `API Design`, `Phased Rollout`, `Risk & Rollout Notes`, `Open Questions`, `Touch List`. Readers shouldn't have to count headings to follow a cross-reference, and section numbering shifts when the spec/plan evolves. Same rule applies to citing SPEC sections (`Use-cases`, `Acceptance scenarios`, etc.) — name them.
|
|
383
|
+
- **No time estimates.** Use LoC sizing.
|
|
384
|
+
- **No vibes-based guarantees** ("should be straightforward", "trivial", "easy lift").
|
|
385
|
+
- **No skipped non-goals section.**
|
|
386
|
+
- **No phase that breaks build if merged alone.** Each independently mergeable AND independently reversible.
|
|
387
|
+
- **No phase requiring manual `kubectl` / SSH / "remember to run X"** without Risk & Rollout Notes checklist.
|
|
388
|
+
- **No assuming user wants what they asked for.** Watch for "wait, also…" + update plan.
|
|
389
|
+
|
|
390
|
+
## Worked references
|
|
391
|
+
|
|
392
|
+
When in doubt, model the plan after a recent example in `ai-plans/` — look for ones that:
|
|
393
|
+
|
|
394
|
+
- wire a cross-repo producer (`Phase 1b` parallel to in-repo phases) with an "API contract first, persist later" rollout;
|
|
395
|
+
- split a large mutation phase into `4a/4b/4c/4d` sub-phases;
|
|
396
|
+
- stay small + sharply scoped by following an existing precedent on the same entity;
|
|
397
|
+
- use a feature-flagged staged rollout across many small phases.
|
|
398
|
+
|
|
399
|
+
## Checklist
|
|
400
|
+
|
|
401
|
+
- [ ] Step 0 questions answered (or explicitly waived); decisions echoed back.
|
|
402
|
+
- [ ] Filename: `ai-plans/{TODAY}-{FEATURE_NAME}_IMPLEMENTATION_PLAN.md`.
|
|
403
|
+
- [ ] **Goals + Non-goals** section present.
|
|
404
|
+
- [ ] **Guiding Decisions** table — each row has *why*.
|
|
405
|
+
- [ ] Phases MR-sized (~100–300 LoC) + independently mergeable.
|
|
406
|
+
- [ ] Phase numbering uses numbers + letters consistently.
|
|
407
|
+
- [ ] **At least one phase per spec use-case** (entries under SPEC **Decisions → Use-cases**). No phase implements two use-cases. Cross-cutting scaffolding is its own foundation phase.
|
|
408
|
+
- [ ] Each phase has Goal / Spec use-case / Feature flag (or explicit waiver) / Changes / Tests / Suggested AI model / Reusable skills / Acceptance.
|
|
409
|
+
- [ ] Every phase introducing a new UI flow has an **E2E happy-path test** in its Tests block, with screenshot output to `pr-screenshots/`.
|
|
410
|
+
- [ ] Feature flag declared in **Guiding Decisions** (key, scope, default, flip-on criterion) **unless** **Guiding Decisions** explicitly justifies "no flag — purely additive surface".
|
|
411
|
+
- [ ] ≥1 test per gated phase asserts flag-off behavior unchanged.
|
|
412
|
+
- [ ] If flag declared, **final entry under Phased Rollout is dedicated flag-removal phase** with prerequisite (soak window), full deletion touch list, `grep` acceptance check.
|
|
413
|
+
- [ ] No time estimates anywhere.
|
|
414
|
+
- [ ] Cross-repo phases labeled `Phase Nb`, deploy ordering called out.
|
|
415
|
+
- [ ] Risk & Rollout Notes covers locks, partitions, backfills, rollback.
|
|
416
|
+
- [ ] Open Questions lists what couldn't resolve, with recommended default.
|
|
417
|
+
- [ ] Touch List groups files by phase.
|
|
418
|
+
- [ ] All file references use `@path/to/file.py` or `[name](relative-path#Lline)`.
|