@avesta-hq/prevention 0.5.0 → 0.6.0-pre.11
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/.avesta/docs/user-story-map/GROUP-0-LEARNINGS.md +292 -0
- package/.avesta/docs/user-story-map/brand.yml +105 -0
- package/.avesta/docs/user-story-map/fonts/Nohemi-Bold.woff2 +0 -0
- package/.avesta/docs/user-story-map/fonts/Nohemi-Medium.woff2 +0 -0
- package/.avesta/docs/user-story-map/fonts/Nohemi-Regular.woff2 +0 -0
- package/.avesta/docs/user-story-map/fonts/Nohemi-SemiBold.woff2 +0 -0
- package/.avesta/docs/user-story-map/personas/arjun.md +58 -0
- package/.avesta/docs/user-story-map/personas/priya.md +75 -0
- package/.avesta/docs/user-story-map/personas/ravi.md +66 -0
- package/.avesta/docs/user-story-map/story-map.html +1422 -0
- package/.avesta/docs/user-story-map/story-map.yml +346 -0
- package/.claude/agents/avesta-acceptance-stage.md +3 -2
- package/.claude/agents/avesta-acceptance-writer.md +3 -3
- package/.claude/agents/avesta-bug-fixer.md +3 -2
- package/.claude/agents/avesta-commit-stage.md +3 -2
- package/.claude/agents/avesta-committer.md +3 -2
- package/.claude/agents/avesta-dependency-reviewer.md +4 -4
- package/.claude/agents/avesta-detection-assessor.md +20 -0
- package/.claude/agents/avesta-dora-init.md +3 -2
- package/.claude/agents/avesta-dora-reporter.md +3 -2
- package/.claude/agents/avesta-driver-builder.md +3 -2
- package/.claude/agents/avesta-dsl-builder.md +3 -3
- package/.claude/agents/avesta-enhancer.md +3 -2
- package/.claude/agents/avesta-green.md +3 -2
- package/.claude/agents/avesta-init.md +3 -2
- package/.claude/agents/avesta-layer-worker.md +3 -2
- package/.claude/agents/avesta-layer.md +3 -2
- package/.claude/agents/avesta-mutation-tester.md +4 -4
- package/.claude/agents/avesta-planner.md +3 -3
- package/.claude/agents/avesta-red.md +3 -2
- package/.claude/agents/avesta-refactorer.md +3 -2
- package/.claude/agents/avesta-release-stage.md +3 -2
- package/.claude/agents/avesta-reviewer.md +4 -4
- package/.claude/agents/avesta-scaffolder.md +4 -4
- package/.claude/agents/avesta-shaper.md +18 -0
- package/.claude/agents/avesta-shipper.md +3 -2
- package/.claude/agents/avesta-spiker.md +3 -2
- package/.claude/agents/avesta-tech-debt-assessor.md +3 -2
- package/.claude/agents/avesta-visionary.md +2 -2
- package/.claude/commands/avesta-acceptance-stage.md +7 -3
- package/.claude/commands/avesta-acceptance-test.md +7 -3
- package/.claude/commands/avesta-bug-fix.md +7 -3
- package/.claude/commands/avesta-code-review.md +7 -3
- package/.claude/commands/avesta-commit-stage.md +7 -3
- package/.claude/commands/avesta-commit.md +7 -3
- package/.claude/commands/avesta-dependency-review.md +7 -3
- package/.claude/commands/avesta-dora-init.md +7 -3
- package/.claude/commands/avesta-dora-report.md +7 -3
- package/.claude/commands/avesta-driver.md +7 -3
- package/.claude/commands/avesta-dsl.md +7 -3
- package/.claude/commands/avesta-enhance.md +7 -3
- package/.claude/commands/avesta-green.md +7 -3
- package/.claude/commands/avesta-init.md +7 -3
- package/.claude/commands/avesta-layer.md +4 -23
- package/.claude/commands/avesta-mutation-testing.md +7 -3
- package/.claude/commands/avesta-plan.md +7 -3
- package/.claude/commands/avesta-red.md +7 -3
- package/.claude/commands/avesta-refactor.md +7 -3
- package/.claude/commands/avesta-release-stage.md +7 -3
- package/.claude/commands/avesta-scaffold.md +7 -3
- package/.claude/commands/avesta-shape.md +12 -0
- package/.claude/commands/avesta-ship.md +7 -3
- package/.claude/commands/avesta-spike.md +7 -3
- package/.claude/commands/avesta-tech-debt.md +24 -4
- package/.claude/commands/avesta-vision.md +7 -3
- package/CLAUDE.md +7 -3
- package/bin/cli.js +1 -1
- package/bin/lib/hooks.js +127 -70
- package/bin/lib/init.js +5 -3
- package/bin/lib/settings.js +85 -32
- package/bin/lib/utils.js +16 -9
- package/package.json +8 -14
- package/bin/lib/test-local.js +0 -121
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
# Group 0 Dogfood Learnings
|
|
2
|
+
|
|
3
|
+
> **Source**: Manual walkthrough of `/avesta-shape` on the Prevention product itself, 2026-04-10, as the first step of the shape phase implementation per `docs/SHAPE-PHASE-IMPLEMENTATION-PLAN.md` §10.
|
|
4
|
+
>
|
|
5
|
+
> **Purpose**: Validate the schema, flow, template, and brand approach before writing any agent code. These learnings feed directly into Groups 1–8 of the implementation.
|
|
6
|
+
>
|
|
7
|
+
> **Artifacts produced**:
|
|
8
|
+
> - `brand.yml` — AvestaHQ brand configuration extracted from `Avesta_BrandGuide_V1.pdf`
|
|
9
|
+
> - `story-map.yml` — 144 stories across 14 backbone phases, 3 personas, 4 releases
|
|
10
|
+
> - `story-map.html` — rendered HTML visually verified against the GTPCL reference design
|
|
11
|
+
> - `fonts/Nohemi-*.woff2` — 4 self-hosted weights (Regular, Medium, SemiBold, Bold)
|
|
12
|
+
> - `scripts/render-story-map-dogfood.mjs` — throwaway renderer (the production version comes in Group 2)
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Summary
|
|
17
|
+
|
|
18
|
+
13 concrete learnings surfaced during the dogfood. Each has a specific fix location in the implementation plan or a new fast-follow item. None of the learnings invalidate the overall approach — they refine the agent prompt, the schema, and the render strategy.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Learnings
|
|
23
|
+
|
|
24
|
+
### #1 — Agent must glob for vision docs, not hardcode the canonical path
|
|
25
|
+
|
|
26
|
+
**What happened**: The agent prompt in `SHAPE-PHASE-IMPLEMENTATION-PLAN.md` §5.15 instructs the agent to read `.avesta/docs/vision/PRODUCT-VISION.md` as pre-flight. But Prevention's vision lives at `docs/PREVENTION-VISION-NARRATIVE.md` and `docs/PREVENTION-PRODUCT-SPEC.md` — paths that exist in most brownfield projects but not at the canonical `.avesta/docs/vision/` location.
|
|
27
|
+
|
|
28
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Update the pre-flight step to:
|
|
29
|
+
1. First look at `.avesta/docs/vision/PRODUCT-VISION.md`
|
|
30
|
+
2. If not found, glob for `**/vision*.md`, `**/*VISION*.md`, `**/PRODUCT-SPEC*.md`
|
|
31
|
+
3. If multiple candidates, ask the user which to use
|
|
32
|
+
4. If none, offer to run `/avesta-vision` first
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
### #2 — `brand.yml` schema needs font source type and face array
|
|
37
|
+
|
|
38
|
+
**What happened**: The plan's §5.4 brand schema assumed all fonts come from Google Fonts. The AvestaHQ brand uses Nohemi (paid, self-hosted) + Work Sans (Google Fonts) + DM Mono (Google Fonts). Self-hosted fonts need `@font-face` declarations with weight-specific file paths — not just a `google_fonts_import` URL.
|
|
39
|
+
|
|
40
|
+
**Fix location**: `src/mcp/templates/brand.schema.yaml` (Group 2, §5.4). Add to typography section:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
typography:
|
|
44
|
+
font_display: "'Nohemi', 'Space Grotesk', sans-serif"
|
|
45
|
+
font_display_source: local | google_fonts | cdn
|
|
46
|
+
font_display_faces: # only when source = local
|
|
47
|
+
- { family, weight, file }
|
|
48
|
+
font_body: "..."
|
|
49
|
+
font_body_source: ...
|
|
50
|
+
google_fonts_import: "..." # only when one or more sources = google_fonts
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The render script must handle all three source types and emit `@font-face` rules for local fonts.
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### #3 — `brand.default.yaml` values in the plan are wrong
|
|
58
|
+
|
|
59
|
+
**What happened**: The default brand values in `SHAPE-PHASE-IMPLEMENTATION-PLAN.md` §5.4 were copied from the reference GTPCL HTML, which used **desaturated approximations** of the AvestaHQ brand for web-safety. The authentic brand guide specifies different values:
|
|
60
|
+
|
|
61
|
+
| Plan said | Brand guide says |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `#F47852` (coral) | `#FE6A3A` (Avesta Coral) |
|
|
64
|
+
| `#224241` (teal) | `#224242` (Deep Teal) |
|
|
65
|
+
| Instrument Serif | Nohemi |
|
|
66
|
+
| DM Sans | Aktiv Grotesk (or Work Sans as web fallback) |
|
|
67
|
+
|
|
68
|
+
**Fix location**: `src/mcp/templates/brand.default.yaml` (Group 2, §5.6). Replace the entire file with the authentic AvestaHQ values lifted from `Avesta_BrandGuide_V1.pdf`. Use the dogfood `brand.yml` in this directory as the canonical reference.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
### #4 — Schema needs both Soft Beige and Warm Beige backgrounds
|
|
73
|
+
|
|
74
|
+
**What happened**: The AvestaHQ brand guide distinguishes **Soft Beige** (`#FFFDF4`, page 31, "Key Hue on the Web" — the digital canvas background) from **Warm Beige** (`#F4F1DE`, brand cream — used for panels, sections, cards). The plan's schema only had `bg_primary` and `bg_secondary` without clarifying which is which.
|
|
75
|
+
|
|
76
|
+
**Fix location**: `src/mcp/templates/brand.schema.yaml` (Group 2, §5.4). Rename/clarify:
|
|
77
|
+
- `bg_primary` — digital canvas (Soft Beige for AvestaHQ)
|
|
78
|
+
- `bg_secondary` — panels and sections (Warm Beige for AvestaHQ)
|
|
79
|
+
- Add explanatory comments in the schema so brands with different background conventions can map correctly
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
### #5 — Persona slots should support 4 personas, not 3
|
|
84
|
+
|
|
85
|
+
**What happened**: The plan's §5.4 schema had three persona slots (primary, secondary, tertiary). The AvestaHQ secondary palette has four distinct color families: Deep Teal, Mineral Green, Cloud Blue, Carnation Pink. Supporting four slots gives shape workshops more flexibility and avoids forcing persona merges when there are four legitimate distinct personas.
|
|
86
|
+
|
|
87
|
+
**Fix location**: `src/mcp/templates/brand.schema.yaml` (Group 2, §5.4). Add `quaternary` persona slot. The render script must support the 4th slot in story card rendering.
|
|
88
|
+
|
|
89
|
+
**Note**: Prevention's story map uses 3 personas (Priya, Arjun, Ravi), so this isn't exercised in the dogfood fixture. But the schema must support 4 for products with richer persona sets.
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### #6 — Backbone needs to work for both CLI and dashboard/email personas
|
|
94
|
+
|
|
95
|
+
**What happened**: The plan's §5.3 schema implicitly assumed all personas share the same surface area (CLI). Prevention has **CLI personas** (Priya, Arjun — run commands daily) and **dashboard/email personas** (Ravi — never touches CLI, reads reports). Both need to be on the same backbone because they're part of the same product journey in time, just entering at different phases and via different surfaces.
|
|
96
|
+
|
|
97
|
+
**Fix location**:
|
|
98
|
+
- `src/mcp/templates/story-map.schema.yaml` (Group 2, §5.3). Add optional `surface` field to each persona: `cli | dashboard | email | mixed`.
|
|
99
|
+
- `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Add guidance: *"Backbone is organized by time. Different phases may have different primary personas. A persona's stories can appear in any phase where they act. Buyer personas (dashboard/email) typically act at the start (evaluate) and the end (observe, renew)."*
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
### #7 — Agent must accept feedback on earlier rounds at any time
|
|
104
|
+
|
|
105
|
+
**What happened**: During the dogfood, the user provided feedback on Round 0 and Round 1 while Round 2 was in progress. The correct response was to pause Round 2, process the feedback, and resume — not defer to the end. Patton's talk-then-map-then-talk-more principle: corrections compound if held.
|
|
106
|
+
|
|
107
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Add explicit rule:
|
|
108
|
+
|
|
109
|
+
> At the start of each round, invite the user to revise anything from earlier rounds. Never refuse to go back. If feedback arrives mid-round, pause the current round, process the feedback, capture any new learnings, and resume.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### #8 — Brand guidelines should be LAST in the flow, not FIRST
|
|
114
|
+
|
|
115
|
+
**What happened**: The plan's §5.15 had brand as Step 0 (before Round 1). This was wrong — brand is a rendering concern, so asking about hex codes before any content exists feels bureaucratic and creates friction at the start. Brand naturally fits right before rendering, when the user has the content and asks "how should this look?"
|
|
116
|
+
|
|
117
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Reorder the steps:
|
|
118
|
+
|
|
119
|
+
| Was | Corrected |
|
|
120
|
+
|---|---|
|
|
121
|
+
| Step 0: Brand | Step 0: **Framing message** (see #11) |
|
|
122
|
+
| Step 1: Round 1 (Who & Why) | Step 1: Round 1 (Who & Why) |
|
|
123
|
+
| Step 2: Round 2 (Journey & Backbone) | Step 2: Round 2 (Journey & Backbone) |
|
|
124
|
+
| Step 3: Round 3 (Stories & Slices) | Step 3: Round 3 (Stories & Slices) |
|
|
125
|
+
| Step 4: Validate | Step 4: Validate content |
|
|
126
|
+
| Step 5: Render | Step 5: **Brand guidelines** ("before I render, how should this look?") |
|
|
127
|
+
| Step 6: Confirm | Step 6: Render |
|
|
128
|
+
| — | Step 7: Confirm and approve |
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
### #9 — Agent must NOT mention external authors in facilitation
|
|
133
|
+
|
|
134
|
+
**What happened**: The initial draft of the agent prompt and facilitation conversation repeatedly cited "Patton's rule" and "Patton's method." Prevention should own the methodology in the user-facing conversation — no attribution to Jeff Patton, Kent Beck, Dave Farley, Michael Feathers, or other external sources.
|
|
135
|
+
|
|
136
|
+
**Applies to**: agent facilitation output (`src/mcp/prompts/avesta-shape.md` and any runtime conversation).
|
|
137
|
+
**Does not apply to**: internal skill files in `docs/rules/*.md` — those are developer-facing reference docs and can cite sources for internal methodology grounding.
|
|
138
|
+
|
|
139
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Add explicit rule:
|
|
140
|
+
|
|
141
|
+
> **Never cite external authors in facilitation.** No Jeff Patton, no Kent Beck, no Dave Farley, no Michael Feathers, no Clayton Christensen. When enforcing a rule, state the rule as the rule — not as someone's quoted rule. Example: instead of *"Patton's rule is the map is not the point"*, say *"One rule I'll keep enforcing: the map is not the point, the conversation around it is."*
|
|
142
|
+
|
|
143
|
+
**Alignment with existing guidance**: This is consistent with the AvestaHQ voice rules in `.claude/memory/` that content must be original AvestaHQ voice.
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### #10 — Agent must not narrate meta-commentary during facilitation
|
|
148
|
+
|
|
149
|
+
**What happened**: The initial facilitation had lines like *"I'm going to ask you directly, one focused question at a time"* and *"In Patton's method we..."* — the agent telling the user how it's about to behave instead of just behaving that way.
|
|
150
|
+
|
|
151
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Add explicit rules:
|
|
152
|
+
|
|
153
|
+
> - **Don't** say things like *"I'm going to ask you X"* — just ask
|
|
154
|
+
> - **Don't** announce rules mid-conversation — apply them
|
|
155
|
+
> - **Don't** explain the framework during rounds — explain it once in the opening framing (Step 0), then facilitate silently
|
|
156
|
+
> - **Do** enforce rules crisply: state the rule, cite the consequence, move on
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
### #11 — Agent must start with a framing message
|
|
161
|
+
|
|
162
|
+
**What happened**: The plan's §5.15 jumped straight into Round 0 without explaining to the user *why* the workshop exists, *how long* it takes, *what value* it creates, and *why it's required*. Users need to know the ROI of their time before investing 60-90 minutes in a facilitated workshop.
|
|
163
|
+
|
|
164
|
+
**Fix location**: `src/mcp/prompts/avesta-shape.md` (Group 5, §5.15). Add explicit "Step 0: Framing" with a templated opening message. Canonical version (developed during dogfood):
|
|
165
|
+
|
|
166
|
+
> ## `/avesta-shape` — building shared understanding of what to build
|
|
167
|
+
>
|
|
168
|
+
> This is the **shape** phase. I'm going to facilitate a User Story Mapping workshop with you.
|
|
169
|
+
>
|
|
170
|
+
> ### Why we're doing this
|
|
171
|
+
>
|
|
172
|
+
> Most teams skip the conversation between *"why this product exists"* (your vision) and *"how we build the next feature"* (your plan). That skipped conversation is where product fails — engineering builds well-crafted features for the wrong users in the wrong order, product builds roadmaps disconnected from what engineering can ship, and nobody agrees on what the MVP actually is.
|
|
173
|
+
>
|
|
174
|
+
> A story map fills the gap. When we finish, you'll have a single visual artifact showing:
|
|
175
|
+
>
|
|
176
|
+
> - **Who** your users are and what jobs they're hiring your product for
|
|
177
|
+
> - The **end-to-end journey** they take to get value (the backbone)
|
|
178
|
+
> - **Every story** you might build, stacked vertically by priority
|
|
179
|
+
> - Which stories belong in the **MVP** — the smallest walkable skeleton that delivers real value end-to-end
|
|
180
|
+
> - Which stories belong in R2, R3, R4 — named by the **outcome** they add, not the features
|
|
181
|
+
> - What you're **explicitly NOT building** (as important as what you are)
|
|
182
|
+
>
|
|
183
|
+
> This becomes the bridge between product and engineering. Without it, `/avesta-plan` operates in a vacuum — you'll get well-engineered features for the wrong product.
|
|
184
|
+
>
|
|
185
|
+
> ### Why this is required, not optional
|
|
186
|
+
>
|
|
187
|
+
> Prevention is built on one thesis: **build the product right, ship value fast, learn continuously**. You cannot "build the product right" if product and engineering don't share a picture of what the product *is*. The story map isn't documentation you produce to satisfy a gate — it's the working artifact that keeps the team aligned for the entire life of the product. Every feature planning session will pull from it. Every release will close out stories on it. Every quarterly review will revisit it.
|
|
188
|
+
>
|
|
189
|
+
> That's why it's a hard gate before `/avesta-plan` for new features. Bug fixes and tech debt bypass the gate because they work below the map level.
|
|
190
|
+
>
|
|
191
|
+
> ### What it takes
|
|
192
|
+
>
|
|
193
|
+
> Three focused rounds of conversation. Budget ~60–90 minutes for a first product, longer for complex ones. You can pause and resume — I save progress as we go.
|
|
194
|
+
>
|
|
195
|
+
> 1. **Who & Why** (~15 min) — personas and the jobs they're hiring your product to do
|
|
196
|
+
> 2. **Journey & Backbone** (~30 min) — the time-ordered path they take to get value
|
|
197
|
+
> 3. **Stories & Slices** (~45 min) — what you'll build, prioritised vertically and sliced horizontally into releases
|
|
198
|
+
>
|
|
199
|
+
> I'll ask focused questions and push back when answers are hand-wavy.
|
|
200
|
+
>
|
|
201
|
+
> **One rule I'll keep enforcing**: *the map is not the point — the conversation around it is.* If you try to treat this as a form to fill out, I'll stop you.
|
|
202
|
+
>
|
|
203
|
+
> ### Output
|
|
204
|
+
>
|
|
205
|
+
> - `.avesta/docs/user-story-map/story-map.yml` — canonical source of truth
|
|
206
|
+
> - `.avesta/docs/user-story-map/story-map.html` — shareable visual for stakeholders
|
|
207
|
+
> - `.avesta/docs/user-story-map/brand.yml` — visual brand config for the HTML (covered at the end, right before rendering)
|
|
208
|
+
>
|
|
209
|
+
> ### Ready?
|
|
210
|
+
>
|
|
211
|
+
> I'll start Round 1 with the person your product is most obviously for.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
### #12 — Render script should use `yaml` not `js-yaml`
|
|
216
|
+
|
|
217
|
+
**What happened**: The plan's §5.7 specified `js-yaml` as the YAML parser for the render script. The Prevention repo already has `yaml` (eemeli/yaml) as a dependency in `package.json`. Adding `js-yaml` would create a redundant dependency.
|
|
218
|
+
|
|
219
|
+
**Fix location**: `docs/SHAPE-PHASE-IMPLEMENTATION-PLAN.md` §5.7 — update to use `yaml` package. `scripts/render-story-map.mjs` (Group 2) — use `import YAML from 'yaml'; YAML.parse(...)`.
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
### #13 — Backlog stories need an explicit rendering decision
|
|
224
|
+
|
|
225
|
+
**What happened**: The schema supports `release: backlog` for stories that are captured but not yet slotted into any release. The throwaway renderer excludes backlog stories from the HTML output because there's no "backlog" release line. This means the rendered HTML shows 140 of 144 stories — the 4 backlog items exist in YAML but are invisible on the map.
|
|
226
|
+
|
|
227
|
+
**Fix location**: `src/mcp/templates/story-map.html.hbs` (Group 2, §5.5) + `scripts/render-story-map.mjs` (Group 2, §5.7). Choose one of three options:
|
|
228
|
+
|
|
229
|
+
- **(a)** Implicit backlog release line at the bottom — gray, no label, just shows stories
|
|
230
|
+
- **(b)** "Parking lot" section below the Not-in-scope card — visually distinct, labeled *"Parking Lot — captured but not yet scoped"*
|
|
231
|
+
- **(c)** Keep current behaviour — backlog stories live in YAML only, not rendered
|
|
232
|
+
|
|
233
|
+
**Recommendation**: Option (b) — a parking lot is visually distinct and makes "we haven't decided where this goes yet" explicit, which is honest and prevents the stories from being forgotten.
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Schema additions surfaced during dogfood
|
|
238
|
+
|
|
239
|
+
Beyond the numbered learnings, the dogfood surfaced schema fields that were useful in practice but weren't in the original §5.3 schema:
|
|
240
|
+
|
|
241
|
+
1. `product_description` — the 2-sentence description rendered as the header subtitle. Essential for the HTML header. Add to story-map.schema.yaml.
|
|
242
|
+
2. `personas[].surface` — `cli | dashboard | email | mixed` for backbone rendering decisions. See learning #6.
|
|
243
|
+
3. `personas[].trigger_moment` — narrative description of the specific moment a persona decides to adopt the product. Useful for the agent's walking-skeleton validation (if the trigger moment doesn't walk through the MVP stories, the MVP is wrong).
|
|
244
|
+
4. `stories[].notes` — optional free-text for stories that need context (already in the schema, used for backlog items to document *why* they're backlog).
|
|
245
|
+
5. `releases[].color_key` — reference to `brand.yml` release slots instead of inline hex codes. Already in the schema; dogfood confirmed this indirection works cleanly.
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Flow learnings not captured as numbered items
|
|
250
|
+
|
|
251
|
+
These are softer observations from the dogfood that shape how the agent should behave:
|
|
252
|
+
|
|
253
|
+
1. **Strawman-first is cheaper than cold questions for experienced product owners.** When facilitating a user who already knows their product deeply, proposing a strawman (persona, backbone, story set) and letting them edit is faster than asking cold questions. The agent should detect this: if the user has an existing vision doc, codebase, or prior product experience, lean strawman-first. If the user is pre-product or unclear, lean cold-questions.
|
|
254
|
+
|
|
255
|
+
2. **User feedback on earlier rounds compounds value.** The dogfood surfaced 4 corrections on Rounds 0 and 1 while Round 2 was in progress. Each correction improved the final artifact meaningfully. Design the agent to welcome this.
|
|
256
|
+
|
|
257
|
+
3. **The user/buyer split is critical for B2B products.** The dogfood surfaced that Ravi (CTO) is both an indirect beneficiary (experiences Priya's improved DORA metrics) AND a direct user via a different surface (dashboard, email, renewal flow). This is not a Patton-specific point — it's a B2B product design point — but the agent must handle it. For B2B products, MVP must have a **walking skeleton for the buyer persona too**, even if thin (4-6 stories).
|
|
258
|
+
|
|
259
|
+
4. **Recursive phases work.** The shape phase appears on Prevention's own backbone as phase 6 (shape the solution). Self-referential but not circular. The agent should be OK with this and not flag it as an error.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## Files produced by this dogfood
|
|
264
|
+
|
|
265
|
+
| File | Size | Purpose |
|
|
266
|
+
|---|---|---|
|
|
267
|
+
| `brand.yml` | 4.7 KB | AvestaHQ brand config — canonical reference for `brand.default.yaml` in Group 2 |
|
|
268
|
+
| `story-map.yml` | 37 KB | Full story map schema example — canonical test fixture for Group 2 render script tests |
|
|
269
|
+
| `story-map.html` | 46 KB | Rendered HTML — visually verified against GTPCL reference design |
|
|
270
|
+
| `fonts/Nohemi-Regular.woff2` | 20 KB | Self-hosted brand font |
|
|
271
|
+
| `fonts/Nohemi-Medium.woff2` | 20 KB | Self-hosted brand font |
|
|
272
|
+
| `fonts/Nohemi-SemiBold.woff2` | 20 KB | Self-hosted brand font |
|
|
273
|
+
| `fonts/Nohemi-Bold.woff2` | 19 KB | Self-hosted brand font |
|
|
274
|
+
| `scripts/render-story-map-dogfood.mjs` | 16 KB | Throwaway renderer — to be replaced by production version in Group 2 |
|
|
275
|
+
| `GROUP-0-LEARNINGS.md` | this file | Feeds Groups 1–8 |
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## What happens next
|
|
280
|
+
|
|
281
|
+
With Group 0 complete, implementation proceeds in dependency order:
|
|
282
|
+
|
|
283
|
+
1. **Group 1** — Skills (`docs/rules/user-story-mapping.md`, `docs/rules/persona-jtbd.md`). Skill content is informed by dogfood learnings #6, #7, #8, #9, #10, #11.
|
|
284
|
+
2. **Group 2** — Schema, template, render script (§5.3 – §5.9). Uses Group 0 fixtures as test inputs. Incorporates learnings #2, #3, #4, #5, #12, #13.
|
|
285
|
+
3. **Group 3** — Core types and gate state machine (§5.10 – §5.12).
|
|
286
|
+
4. **Group 4** — Framework catalog (§5.13, §5.14).
|
|
287
|
+
5. **Group 5** — Agent files (§5.15 – §5.17). Agent prompt encodes learnings #1, #6, #7, #8, #9, #10, #11.
|
|
288
|
+
6. **Group 6** — Planner integration (§5.18, §5.19).
|
|
289
|
+
7. **Group 7** — Tests (§5.20 – §5.24). Render test uses Group 0 fixtures.
|
|
290
|
+
8. **Group 8** — Documentation (§5.25 – §5.27).
|
|
291
|
+
|
|
292
|
+
Each group should cross-reference this file to ensure the relevant learnings are applied.
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
schema_version: "1.0"
|
|
2
|
+
name: "AvestaHQ"
|
|
3
|
+
source: user
|
|
4
|
+
# Extracted from Avesta_BrandGuide_V1.pdf during Group 0 dogfood workshop.
|
|
5
|
+
# Colors from pages ~25-30 of the brand guide. Typography from pages ~31-34.
|
|
6
|
+
# Work Sans is explicitly named in the brand guide as the open-source web
|
|
7
|
+
# equivalent to Aktiv Grotesk — used here for body because Aktiv Grotesk
|
|
8
|
+
# web fonts are not available in the brand asset pack (OTF only).
|
|
9
|
+
|
|
10
|
+
typography:
|
|
11
|
+
# Headings — self-hosted Nohemi (brand primary display typeface).
|
|
12
|
+
# .woff2 files copied from /home/av19/Projects/AvestaHQ Branding/.../Nohemi/Web-TT/
|
|
13
|
+
font_display: "'Nohemi', 'Space Grotesk', 'Inter', sans-serif"
|
|
14
|
+
font_display_source: local
|
|
15
|
+
font_display_faces:
|
|
16
|
+
- { family: "Nohemi", weight: 400, file: "fonts/Nohemi-Regular.woff2" }
|
|
17
|
+
- { family: "Nohemi", weight: 500, file: "fonts/Nohemi-Medium.woff2" }
|
|
18
|
+
- { family: "Nohemi", weight: 600, file: "fonts/Nohemi-SemiBold.woff2" }
|
|
19
|
+
- { family: "Nohemi", weight: 700, file: "fonts/Nohemi-Bold.woff2" }
|
|
20
|
+
|
|
21
|
+
# Body — Work Sans from Google Fonts (brand-sanctioned alternate to
|
|
22
|
+
# Aktiv Grotesk, named explicitly in the brand guide as the web equivalent).
|
|
23
|
+
font_body: "'Work Sans', -apple-system, system-ui, sans-serif"
|
|
24
|
+
font_body_source: google_fonts
|
|
25
|
+
|
|
26
|
+
# Mono — DM Mono from Google Fonts (not in brand guide; matches the
|
|
27
|
+
# reference story map aesthetic for small labels and persona tags).
|
|
28
|
+
font_mono: "'DM Mono', ui-monospace, monospace"
|
|
29
|
+
font_mono_source: google_fonts
|
|
30
|
+
|
|
31
|
+
google_fonts_import: "https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&family=DM+Mono:wght@400;500&display=swap"
|
|
32
|
+
|
|
33
|
+
colors:
|
|
34
|
+
# Primary — Avesta Coral + Warm Beige (from brand guide pages 24-25)
|
|
35
|
+
accent_primary: "#FE6A3A" # Avesta Coral — warmth, momentum
|
|
36
|
+
accent_primary_dark: "#E55F34" # darker tint from the coral scale
|
|
37
|
+
bg_warm_beige: "#F4F1DE" # Warm Beige — brand cream
|
|
38
|
+
|
|
39
|
+
# Primary digital background (Soft Beige — page 31, "Key Hue on the Web")
|
|
40
|
+
bg_primary: "#FFFDF4" # Soft Beige — calm, neutral digital canvas
|
|
41
|
+
bg_secondary: "#F4F1DE" # Warm Beige — used for panels and sections
|
|
42
|
+
|
|
43
|
+
# Text
|
|
44
|
+
text_primary: "#181816" # near-black from the cream scale
|
|
45
|
+
text_secondary: "#5C5850" # mid-neutral
|
|
46
|
+
text_muted: "#9C978A" # light-neutral
|
|
47
|
+
text_on_dark: "#F4F1DE" # warm beige on teal backgrounds
|
|
48
|
+
text_on_dark_muted: "#A8BDB5"
|
|
49
|
+
|
|
50
|
+
# Borders
|
|
51
|
+
border: "#DDD8C8" # light warm neutral
|
|
52
|
+
border_dark: "#3A5B59" # teal-shifted border
|
|
53
|
+
|
|
54
|
+
# Secondary palette — the full AvestaHQ secondary colour set
|
|
55
|
+
# (page 26 of the brand guide)
|
|
56
|
+
deep_teal: "#224242" # Depth • Experience — dominant secondary
|
|
57
|
+
deep_teal_mid: "#2D5654" # slightly lighter for backbone mid
|
|
58
|
+
deep_teal_light: "#3A6B69" # lighter for accents
|
|
59
|
+
deep_teal_dark: "#1f3b3b" # darker shade from scale
|
|
60
|
+
mineral_green: "#377D71" # Stability • Process
|
|
61
|
+
cloud_blue: "#8FB9F8" # Product Sense
|
|
62
|
+
carnation_pink: "#FFA3BE" # Open • Culture
|
|
63
|
+
|
|
64
|
+
persona_slots:
|
|
65
|
+
# Each persona gets a background tint (card background) and dark variant
|
|
66
|
+
# (text color). Light tints are derived from the tint scales in the brand
|
|
67
|
+
# guide (pages 25-27). Assignments match the AvestaHQ secondary palette.
|
|
68
|
+
primary:
|
|
69
|
+
# Deep Teal persona (most common — the primary user)
|
|
70
|
+
name_hint: "Deep Teal family"
|
|
71
|
+
bg: "#D4E8E4" # light teal tint (derived)
|
|
72
|
+
text: "#0D2B2A" # deep teal dark
|
|
73
|
+
accent: "#224242"
|
|
74
|
+
secondary:
|
|
75
|
+
# Mineral Green persona
|
|
76
|
+
name_hint: "Mineral Green family"
|
|
77
|
+
bg: "#D9EBE7" # light mineral green tint
|
|
78
|
+
text: "#1E4A42" # mineral dark
|
|
79
|
+
accent: "#377D71"
|
|
80
|
+
tertiary:
|
|
81
|
+
# Cloud Blue persona
|
|
82
|
+
name_hint: "Cloud Blue family"
|
|
83
|
+
bg: "#DCE8FC" # light cloud blue tint
|
|
84
|
+
text: "#1B3A6B" # cloud dark
|
|
85
|
+
accent: "#8FB9F8"
|
|
86
|
+
quaternary:
|
|
87
|
+
# Carnation Pink persona
|
|
88
|
+
name_hint: "Carnation Pink family"
|
|
89
|
+
bg: "#FFE0E8" # light pink tint
|
|
90
|
+
text: "#6B1F35" # pink dark
|
|
91
|
+
accent: "#FFA3BE"
|
|
92
|
+
quinary:
|
|
93
|
+
# Warm Amber persona (5th slot — for products with 5 personas)
|
|
94
|
+
name_hint: "Warm Amber family"
|
|
95
|
+
bg: "#F1E4C5" # soft amber tint
|
|
96
|
+
text: "#5A4418" # deep amber brown
|
|
97
|
+
accent: "#B8862C" # muted gold
|
|
98
|
+
|
|
99
|
+
release_slots:
|
|
100
|
+
# Release lines use the coral for MVP (brand primary — warmth, momentum)
|
|
101
|
+
# and secondary palette for later releases.
|
|
102
|
+
mvp: "#FE6A3A" # Avesta Coral — the drive to ship
|
|
103
|
+
r2: "#377D71" # Mineral Green — stability, process
|
|
104
|
+
r3: "#8FB9F8" # Cloud Blue — product sense
|
|
105
|
+
r4: "#FFA3BE" # Carnation Pink — culture, openness
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Arjun — Junior Dev on Priya's team
|
|
2
|
+
|
|
3
|
+
*Color slot: secondary* · *Surface: cli* · *Frequency: daily*
|
|
4
|
+
|
|
5
|
+
## Jobs to be done
|
|
6
|
+
|
|
7
|
+
### Functional
|
|
8
|
+
> When I use AI to write code, I want to know it's right before I push, so my PR doesn't end up in Priya's queue with 15 review comments.
|
|
9
|
+
|
|
10
|
+
### Emotional
|
|
11
|
+
Feel confident he's learning, not just accepting AI suggestions uncritically. The fear underneath: "am I actually getting better at this, or am I just a Claude Code conduit?"
|
|
12
|
+
|
|
13
|
+
### Social
|
|
14
|
+
Be seen by Priya as someone who ships clean work without hand-holding. Be seen by his peers (other juniors) as the one who figured out how to use AI well. Not be the junior Priya sighs about in her 1:1 with the CTO.
|
|
15
|
+
|
|
16
|
+
## Pains
|
|
17
|
+
- "AI suggests code I don't fully understand and I'm not sure if it's right."
|
|
18
|
+
- "Tests pass but I'm not sure they prove what I think they prove."
|
|
19
|
+
- "My PRs come back with architecture comments I didn't know to check for."
|
|
20
|
+
- "Worried I'm building bad habits by accepting AI output uncritically."
|
|
21
|
+
|
|
22
|
+
## Current workarounds
|
|
23
|
+
- Accept AI suggestions and hope PR review catches issues
|
|
24
|
+
- Ask Priya in Slack before committing anything non-trivial ("hey is this the right way to...")
|
|
25
|
+
- Read skill docs (Clean Architecture, TDD) but not systematically
|
|
26
|
+
- Sometimes paste AI output into ChatGPT for a second opinion
|
|
27
|
+
|
|
28
|
+
## Trigger moment
|
|
29
|
+
|
|
30
|
+
Arjun's PR from last week came back with 12 comments from Priya. Most were "this tests the implementation, not the behaviour" — a phrase he'd never heard in bootcamp. He fixed them but didn't understand *why* the original tests were wrong. The fix felt like cargo-culting Priya's comments.
|
|
31
|
+
|
|
32
|
+
Today's standup, Priya mentioned Prevention and said "Arjun, try it on your next ticket." That's the trigger — not a moment of dread, but a moment of guarded optimism. "Maybe this will teach me what Priya means when she says 'behaviour not implementation'."
|
|
33
|
+
|
|
34
|
+
## Evidence
|
|
35
|
+
|
|
36
|
+
This persona is composited from junior developers I've talked to in the TS/Node bootcamp-graduate community. The specific tension (AI makes them faster but they feel like they're not learning) appears repeatedly. The "12 PR review comments" scenario is pattern-matched from multiple real-world Slack conversations.
|
|
37
|
+
|
|
38
|
+
## Day in the life
|
|
39
|
+
|
|
40
|
+
**9:30** — Standup. Assigned a new ticket: "Add promo code validation to checkout."
|
|
41
|
+
|
|
42
|
+
**10:00** — Opens Claude Code. Types "add promo code validation to checkout.ts". Gets a working implementation in 30 seconds.
|
|
43
|
+
|
|
44
|
+
**10:05** — Runs the tests locally. They pass. Commits.
|
|
45
|
+
|
|
46
|
+
**10:10** — Thinks: "wait, should I run Prevention on this? Priya said try it." Opens Claude Code and types `/avesta-red`.
|
|
47
|
+
|
|
48
|
+
**10:15** — Prevention refuses to write the test Arjun wants, explains why (it's testing the implementation, not the behaviour), and suggests the test that SHOULD exist. Arjun reads the explanation twice. The lightbulb goes on.
|
|
49
|
+
|
|
50
|
+
**10:30** — With Prevention's guardrails, he writes the test first, sees it fail, writes the minimal code to pass. Refactors. Ships. The PR review comes back with 1 comment (a style nit) instead of 12.
|
|
51
|
+
|
|
52
|
+
**11:00** — Pings Priya: *"hey that Prevention thing is actually really good. I get it now."*
|
|
53
|
+
|
|
54
|
+
## Notes
|
|
55
|
+
|
|
56
|
+
- Arjun is an ICP for adoption velocity: if Prevention teaches juniors while gating them, it self-sells.
|
|
57
|
+
- He's NOT the buyer, NOT the champion, but he's the critical mass — if the junior rank rejects the tool, Priya gives up.
|
|
58
|
+
- He'll use Prevention's explanations as learning material more than his teammates. The "agent refuses and explains why" pattern is the onboarding mechanism for behavior-first testing.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Priya — Tech Lead
|
|
2
|
+
|
|
3
|
+
*Color slot: primary* · *Surface: cli* · *Frequency: daily*
|
|
4
|
+
|
|
5
|
+
## Jobs to be done
|
|
6
|
+
|
|
7
|
+
### Functional
|
|
8
|
+
> When my team ships AI-assisted code, I want confidence it won't break production, so I can stop being the last line of defence.
|
|
9
|
+
|
|
10
|
+
### Emotional
|
|
11
|
+
Feel in control of quality without personally reviewing every line of every PR. Stop dreading Monday mornings because something shipped on Friday might blow up.
|
|
12
|
+
|
|
13
|
+
### Social
|
|
14
|
+
Be seen by her CTO as the TL whose team ships fast AND clean — not the one whose team ships slop. Be seen by her juniors as the mentor who gave them guardrails, not roadblocks. Be the TL other TLs ask about how to adopt AI coding agents without losing quality.
|
|
15
|
+
|
|
16
|
+
## Pains
|
|
17
|
+
- "AI-generated code looks right in PR review, then breaks in production two days later."
|
|
18
|
+
- "Our test coverage went up but I don't trust the tests — they feel decorative. AI writes tests that mirror the implementation instead of the behaviour."
|
|
19
|
+
- "I've become the bug firefighter. My calendar is full of 'can you look at this prod issue' since we adopted AI agents."
|
|
20
|
+
- "Our QA cycle got longer, not shorter, because nobody trusts the AI output and QA has to catch what PR review misses."
|
|
21
|
+
- "My CTO is starting to ask why we're paying for Claude Code licences when production incidents are up."
|
|
22
|
+
- "Juniors commit AI slop without understanding it — I can't tell if they learned anything or just accepted the suggestion."
|
|
23
|
+
|
|
24
|
+
## Current workarounds
|
|
25
|
+
- Claude Code / Cursor / Codex for generation — daily, multiple times per day
|
|
26
|
+
- Manual PR review catches some issues, misses others
|
|
27
|
+
- QA manual testing as a safety net that's been expanding since AI agent adoption
|
|
28
|
+
- Fix → QA → fix → QA loop before every prod release
|
|
29
|
+
- Customer-reported bugs as the final (and costly) safety net
|
|
30
|
+
|
|
31
|
+
## Trigger moment
|
|
32
|
+
|
|
33
|
+
Tuesday morning, standup: Arjun (junior on her team) says he shipped his PR end-of-day Monday — Claude Code wrote the whole thing, PR review passed, merge went clean. Priya marks it complete on the board.
|
|
34
|
+
|
|
35
|
+
Wednesday afternoon: checkout starts returning 500s for ~8% of sessions. Customer support pings engineering. Priya drops into debug mode.
|
|
36
|
+
|
|
37
|
+
Thursday: 3-hour root-cause hunt. The Monday PR added a new validation rule to checkout that the tests asserted "correctly" (they tested what the code did, not what checkout should do). The AI wrote mirror-image tests. The bug was in the spec itself — but nobody wrote the spec, AI inferred it.
|
|
38
|
+
|
|
39
|
+
Friday morning: Priya's CTO pulls her into a 1:1. *"Our incident rate is up since we rolled out Claude Code. I can't defend the spend to the board if this continues. Help me understand — should we pull back?"*
|
|
40
|
+
|
|
41
|
+
Friday afternoon: Priya opens her laptop and starts searching for *"how to make AI coding agents actually safe"*.
|
|
42
|
+
|
|
43
|
+
## Evidence
|
|
44
|
+
|
|
45
|
+
This persona is composited from multiple real conversations I've had with tech leads at small-to-mid TS/Node/Next.js startups who adopted Claude Code/Cursor in the last 6-12 months. The specific pain points (decorative tests, AI slop, QA cycle expansion) appear repeatedly across:
|
|
46
|
+
|
|
47
|
+
- Twitter/X discussions in the TS + AI-coding community
|
|
48
|
+
- HackerNews threads on Cursor/Claude Code rollout outcomes
|
|
49
|
+
- Direct conversations with early AvestaHQ design partners
|
|
50
|
+
|
|
51
|
+
The trigger moment scenario is directly modeled on a real incident pattern I've heard described three times in different companies.
|
|
52
|
+
|
|
53
|
+
## Day in the life
|
|
54
|
+
|
|
55
|
+
**9:00** — Standup. Team reports 4 PRs merged Friday + weekend, all AI-assisted. Priya notes them mentally — she'll check CI signal but trusts the merge gate to have done its job.
|
|
56
|
+
|
|
57
|
+
**9:30** — Opens Slack. Customer support has a thread about checkout failures from Sunday. Drops in.
|
|
58
|
+
|
|
59
|
+
**10:00** — Pulls the checkout PR from Friday. Reads the diff, reads the tests, reads the spec... wait, what spec? Scrolls up to find it. There's no spec — the commit message says "add promo code validation" and the description is one sentence. The tests check `validatePromo()` returns `false` for expired codes. Priya thinks "OK but what happens when the user enters a valid code?" — and finds the happy path test doesn't exist.
|
|
60
|
+
|
|
61
|
+
**11:00** — Writes the missing happy-path test locally. It fails. Finds the bug: a new branch in the validator returns `false` when `new Date(code.expires) > new Date()` instead of `<`. Sign inverted. Claude Code wrote both the bug and the asserting test.
|
|
62
|
+
|
|
63
|
+
**14:00** — Fix is in, rolled out, checkout recovers. Slack thanks. Priya writes a post-mortem explaining what happened and drafts a "we need better testing discipline" memo for the team.
|
|
64
|
+
|
|
65
|
+
**16:00** — Drafts a Slack message to her CTO: *"I think we need to talk about how we're using Claude Code."*
|
|
66
|
+
|
|
67
|
+
**17:30** — Leaving for the day. Opens HN on the train. Sees a post about Prevention. Stops scrolling.
|
|
68
|
+
|
|
69
|
+
## Notes
|
|
70
|
+
|
|
71
|
+
- Priya is NOT a QA person who got promoted. She's a former IC who leads through technical judgment.
|
|
72
|
+
- Her team has no dedicated QA — QA is whoever has the least context on the PR.
|
|
73
|
+
- She uses Cursor for her own work AND reviews Claude Code output from juniors. Both generation and review failure modes hit her.
|
|
74
|
+
- She's already tried "we'll write better tests" and "we'll review more carefully" — both failed because human discipline doesn't scale past the third PR of the day.
|
|
75
|
+
- She's the buying ICP's most common surface — if Priya adopts, Ravi (her CTO) asks "how's it going?" at month 1 and at renewal.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Ravi — CTO / Engineering Manager (the buyer)
|
|
2
|
+
|
|
3
|
+
*Color slot: tertiary* · *Surface: mixed* · *Frequency: weekly*
|
|
4
|
+
|
|
5
|
+
## Jobs to be done
|
|
6
|
+
|
|
7
|
+
### Functional
|
|
8
|
+
> When I report to the board, I want to show AI adoption is paying off — not costing us more than it saves.
|
|
9
|
+
|
|
10
|
+
### Emotional
|
|
11
|
+
Feel confident the engineering investment is producing business value. Stop defending the Claude Code line item in every quarterly review.
|
|
12
|
+
|
|
13
|
+
### Social
|
|
14
|
+
Be seen by the board as a CTO who picked winning tools. Be seen by the team as someone who buys them what they actually need, not just what's trending on HackerNews. Be the CTO other CTOs ask "how did you roll out AI coding safely?"
|
|
15
|
+
|
|
16
|
+
## Pains
|
|
17
|
+
- AI tool spend going up quarter over quarter, production incident rate also going up
|
|
18
|
+
- Board asking for evidence AI adoption is producing ROI, not anecdotes
|
|
19
|
+
- Cannot distinguish "the team is working hard" from "the team is producing value"
|
|
20
|
+
- No shared view of team output — only anecdotes from 1:1s with tech leads
|
|
21
|
+
- Every DORA-style metric he tracks is a manually assembled spreadsheet
|
|
22
|
+
|
|
23
|
+
## Current workarounds
|
|
24
|
+
- Quarterly DORA spreadsheet built by Ravi or a staff engineer, by hand
|
|
25
|
+
- Weekly status updates from tech leads in 1:1s
|
|
26
|
+
- Reading PRs to spot-check quality (doesn't scale past ~20 PRs/week)
|
|
27
|
+
- Trusting tech leads' gut feel on whether tooling is working
|
|
28
|
+
|
|
29
|
+
## Trigger moment
|
|
30
|
+
|
|
31
|
+
Ravi's quarterly board review is in 3 weeks. Last quarter the board asked: *"Your engineering headcount is flat, your tool spend is up 40%, your production incident count is up 15%. What's the ROI story on AI tooling?"*
|
|
32
|
+
|
|
33
|
+
He didn't have a good answer. He's been losing sleep about it since.
|
|
34
|
+
|
|
35
|
+
Today, Priya pings him: *"I found something that might help. Can we talk for 15 minutes?"*
|
|
36
|
+
|
|
37
|
+
That's the trigger. Ravi doesn't run CLI commands — he books the 15-minute meeting, listens to Priya, and says "if this gets me a real ROI story for the board, buy it. What tier do we need?"
|
|
38
|
+
|
|
39
|
+
## Evidence
|
|
40
|
+
|
|
41
|
+
Composited from CTO/EM conversations at small-to-mid startups (~20-100 engineers) post-AI-coding-tool adoption. The specific pattern — *board asking for ROI evidence, CTO having only anecdotes* — appears in every conversation. The trigger moment (Priya pings Ravi after finding something) is the classic champion-led B2B buy motion.
|
|
42
|
+
|
|
43
|
+
## Day in the life
|
|
44
|
+
|
|
45
|
+
**9:00** — Ravi's morning routine: coffee, open laptop, scan Slack for overnight fires. One prod incident from Sunday, already fixed. Notes it for the weekly incident report.
|
|
46
|
+
|
|
47
|
+
**9:30** — Opens the Prevention dashboard (after Priya installed it two weeks ago). Sees:
|
|
48
|
+
- 14 features shipped last week with all gates green
|
|
49
|
+
- DORA trend: deploy frequency up 30%, change failure rate down 8%, lead time flat
|
|
50
|
+
- 2 gate violations caught pre-merge
|
|
51
|
+
|
|
52
|
+
**9:35** — Screenshots the dashboard. Drops it into the draft board deck in the "Engineering ROI" section.
|
|
53
|
+
|
|
54
|
+
**10:00** — Pings Priya: *"This Prevention thing — do you have a story I can take to the board about how it changed your team's workflow?"*
|
|
55
|
+
|
|
56
|
+
**13:00** — Priya sends him a 3-paragraph summary. Ravi pastes it into the deck.
|
|
57
|
+
|
|
58
|
+
**17:00** — Before leaving, Ravi submits the renewal for Prevention. He also upgrades the tier from free to pro because he wants his other two teams on it by next quarter.
|
|
59
|
+
|
|
60
|
+
## Notes
|
|
61
|
+
|
|
62
|
+
- Ravi NEVER runs CLI commands. His interaction surface is dashboards, emails, and weekly summaries.
|
|
63
|
+
- The MVP story for Ravi is NOT "full DORA dashboard" — it's *"one number I can put in the board deck."*
|
|
64
|
+
- He's the buying ICP but NOT the user. The product must walk BOTH skeletons — Priya's daily loop AND Ravi's buy-validate-renew cycle.
|
|
65
|
+
- If Prevention fails for Ravi, it gets cancelled at renewal no matter how much Priya loves it.
|
|
66
|
+
- Ravi's "aha" moment is seeing the DORA trend with his own eyes, not hearing Priya say "it's working."
|