popilot 0.2.0 → 0.3.0
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/LICENSE +21 -0
- package/README.md +29 -7
- package/adapters/claude-code/.claude/commands/_domain.md.hbs +1 -0
- package/adapters/claude-code/.claude/commands/gtm.md +82 -0
- package/adapters/claude-code/.claude/commands/handoff.md +3 -2
- package/adapters/claude-code/.claude/commands/market.md +1 -1
- package/adapters/claude-code/.claude/commands/start.md +38 -10
- package/adapters/claude-code/.claude/commands/strategy.md +1 -1
- package/adapters/claude-code/CLAUDE.md.hbs +5 -3
- package/bin/cli.mjs +25 -3
- package/lib/hydrate.mjs +1 -0
- package/lib/setup-wizard.mjs +72 -4
- package/package.json +5 -2
- package/scaffold/.context/WORKFLOW.md.hbs +11 -4
- package/scaffold/.context/agents/TEMPLATE.md +1 -1
- package/scaffold/.context/agents/gtm-strategist.md.hbs +382 -0
- package/scaffold/.context/agents/orchestrator.md.hbs +5 -0
- package/scaffold/.context/integrations/_registry.yaml +4 -4
- package/scaffold/.context/integrations/providers/corti.yaml +11 -0
- package/scaffold/.context/integrations/providers/ga4.yaml +32 -0
- package/scaffold/.context/integrations/providers/linear.yaml +11 -0
- package/scaffold/.context/integrations/providers/mixpanel.yaml +30 -0
- package/scaffold/.context/integrations/providers/notebooklm.yaml +10 -0
- package/scaffold/.context/integrations/providers/notion.yaml +11 -0
- package/scaffold/.context/oscar/workflows/setup.md +6 -1
- package/scaffold/.context/project.yaml.example +11 -1
- package/scaffold/.context/templates/gtm-plan.md +52 -0
- package/scaffold/spec-site/package-lock.json +1522 -0
- package/scripts/lint.mjs +56 -0
- package/scripts/typecheck.mjs +24 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yoonjae Song
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> *"Developers have Copilot. Product Owners have Popilot."*
|
|
4
4
|
|
|
5
|
-
**Popilot** is a multi-agent AI assistant for Product Owners and Product Managers, built on [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It scaffolds a complete agent team —
|
|
5
|
+
**Popilot** is a multi-agent AI assistant for Product Owners and Product Managers, built on [Claude Code](https://docs.anthropic.com/en/docs/claude-code). It scaffolds a complete agent team — 15 specialized personas, 30+ slash commands, document templates, and workflow automation — so you can focus on product decisions while AI handles the heavy lifting.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@ Popilot solves this with a **team of specialized agents**, each with deep expert
|
|
|
15
15
|
- **No more context-switching** — Oscar routes your request to the right agent automatically
|
|
16
16
|
- **Structured workflows** — From PRD to Screen Spec to Story to Dev Handoff, nothing falls through the cracks
|
|
17
17
|
- **Data-driven decisions** — Danny queries your analytics; Vicky validates your hypotheses; Tara governs data quality
|
|
18
|
-
- **Full PO coverage** — Strategy, market research, sprint planning, screen specs, tracking, operations, and more
|
|
18
|
+
- **Full PO coverage** — Strategy, market research, GTM, sprint planning, screen specs, tracking, operations, and more
|
|
19
19
|
- **Living specs, not dead docs** — spec-site turns static markdown into interactive, scenario-based mockups that developers actually use
|
|
20
20
|
|
|
21
21
|
---
|
|
@@ -33,13 +33,14 @@ Then open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and type
|
|
|
33
33
|
|
|
34
34
|
## The Agent Team
|
|
35
35
|
|
|
36
|
-
### PO Team (
|
|
36
|
+
### PO Team (10 + Orchestrator)
|
|
37
37
|
|
|
38
38
|
| Icon | Name | Command | Role | Specialty |
|
|
39
39
|
|------|------|---------|------|-----------|
|
|
40
40
|
| :tophat: | **Oscar** | *(default)* | Orchestrator | Routing, coordination, proactive alerts |
|
|
41
41
|
| :dart: | **Simon** | `/strategy` | Strategist | PRD, hypotheses, product strategy |
|
|
42
42
|
| :world_map: | **Marco** | `/market` | Market Researcher | Competitive analysis, positioning |
|
|
43
|
+
| :loudspeaker: | **Mia** | `/gtm` | GTM Strategist | Go-to-market strategy, launch planning, messaging |
|
|
43
44
|
| :clipboard: | **Penny** | `/plan` | Planner | Sprint planning, stories, backlog |
|
|
44
45
|
| :triangular_ruler: | **Hank** | `/handoff` | Handoff Specialist | Screen specs, dev handoff, release readiness |
|
|
45
46
|
| :bar_chart: | **Vicky** | `/validate` | Validator | Hypothesis validation, guard rails, OKR tracking |
|
|
@@ -66,6 +67,7 @@ Then open [Claude Code](https://docs.anthropic.com/en/docs/claude-code) and type
|
|
|
66
67
|
|
|
67
68
|
```
|
|
68
69
|
Strategy: Simon ←→ Marco
|
|
70
|
+
GTM: Mia ←→ Simon + Marco
|
|
69
71
|
Execute: Penny → Hank → Derek + Quinn
|
|
70
72
|
Insight: Danny ←→ Rita
|
|
71
73
|
Measure: Vicky ←→ Tara
|
|
@@ -153,6 +155,7 @@ After setup, open Claude Code and type `/start`. Oscar can run a **deep intervie
|
|
|
153
155
|
|---------|-------------|
|
|
154
156
|
| `/strategy` | Activate Simon (strategy, PRD) |
|
|
155
157
|
| `/market` | Activate Marco (competitive analysis, positioning) |
|
|
158
|
+
| `/gtm` | Activate Mia (GTM strategy, launch planning, messaging) |
|
|
156
159
|
| `/plan` | Activate Penny (sprint planning) |
|
|
157
160
|
| `/validate` | Activate Vicky (hypothesis validation) |
|
|
158
161
|
| `/analytics` | Activate Danny (data analysis) |
|
|
@@ -202,9 +205,9 @@ my-project/
|
|
|
202
205
|
│ ├── .secrets.yaml # Sensitive data (gitignored)
|
|
203
206
|
│ ├── WORKFLOW.md # Workflow guide (hydrated)
|
|
204
207
|
│ │
|
|
205
|
-
│ ├── agents/ #
|
|
208
|
+
│ ├── agents/ # 15 agent personas (+ TEMPLATE.md)
|
|
206
209
|
│ ├── oscar/workflows/ # Oscar extension modules
|
|
207
|
-
│ ├── templates/ #
|
|
210
|
+
│ ├── templates/ # 12 document templates
|
|
208
211
|
│ ├── integrations/ # Provider configs + registry
|
|
209
212
|
│ ├── metrics/ # Metrics data
|
|
210
213
|
│ ├── daily/ # Daily work logs
|
|
@@ -319,6 +322,7 @@ Set `spec_site.deploy_url` in `project.yaml` — agents will use this URL in han
|
|
|
319
322
|
| Template | Owner | File | Purpose |
|
|
320
323
|
|----------|-------|------|---------|
|
|
321
324
|
| Sprint PRD | Simon | `templates/prd.md` | One Question, hypothesis, OMTM |
|
|
325
|
+
| GTM Plan | Mia | `templates/gtm-plan.md` | ICP, messaging, channel mix, launch KPI gates |
|
|
322
326
|
| Epic Spec | PO | `templates/epic-spec.md` | WHY, WHAT, HOW, edge cases |
|
|
323
327
|
| Story v2 | Penny | `templates/story-v2.md` | AC (Given-When-Then), task breakdown |
|
|
324
328
|
| Screen Spec | Hank | `templates/screen-spec.md` | 7-level UI specification |
|
|
@@ -339,7 +343,7 @@ popilot <command> [target-dir] [options]
|
|
|
339
343
|
|
|
340
344
|
Commands:
|
|
341
345
|
init [dir] Scaffold + interactive setup + hydration (default)
|
|
342
|
-
hydrate [dir]
|
|
346
|
+
hydrate [dir] Sync latest scaffold templates + re-hydrate from project.yaml
|
|
343
347
|
doctor [dir] Check installation health
|
|
344
348
|
help Show this help
|
|
345
349
|
|
|
@@ -349,13 +353,31 @@ Options:
|
|
|
349
353
|
|
|
350
354
|
Examples:
|
|
351
355
|
npx popilot init my-project
|
|
352
|
-
npx popilot hydrate
|
|
356
|
+
npx popilot@latest hydrate
|
|
357
|
+
npx popilot@latest hydrate --force
|
|
353
358
|
npx popilot doctor
|
|
354
359
|
npx popilot my-project # same as: popilot init my-project
|
|
355
360
|
```
|
|
356
361
|
|
|
357
362
|
---
|
|
358
363
|
|
|
364
|
+
## Upgrading Existing Projects
|
|
365
|
+
|
|
366
|
+
For projects initialized with older Popilot versions:
|
|
367
|
+
|
|
368
|
+
```bash
|
|
369
|
+
# Safe upgrade (adds missing latest templates/files, then hydrates)
|
|
370
|
+
npx popilot@latest hydrate
|
|
371
|
+
|
|
372
|
+
# Full refresh (overwrites existing scaffold files, then hydrates)
|
|
373
|
+
npx popilot@latest hydrate --force
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
- `hydrate` now syncs the latest scaffold before rendering.
|
|
377
|
+
- Use `--force` only when you intentionally want to replace existing scaffold-managed files.
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
359
381
|
## How It Works
|
|
360
382
|
|
|
361
383
|
1. **`npx popilot init`** copies the scaffold and runs the setup wizard
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# /gtm - Activate GTM Strategist
|
|
2
|
+
|
|
3
|
+
Activate 📣 **Mia** (GTM Strategist) agent.
|
|
4
|
+
|
|
5
|
+
## Load Persona
|
|
6
|
+
|
|
7
|
+
Read `.context/agents/gtm-strategist.md` and activate Mia's persona.
|
|
8
|
+
|
|
9
|
+
## Mia's Identity
|
|
10
|
+
|
|
11
|
+
- **Role**: GTM Strategist + Launch Architect
|
|
12
|
+
- **Personality**: Outcome-driven PMM who turns product value into adoption
|
|
13
|
+
- **Strengths**: ICP focus, messaging design, launch sequencing, KPI gates
|
|
14
|
+
|
|
15
|
+
## Communication Style
|
|
16
|
+
|
|
17
|
+
- Strategic but execution-ready
|
|
18
|
+
- Segment/message/channel structured outputs
|
|
19
|
+
- Explicit decision gates and measurable success criteria
|
|
20
|
+
- Clear ownership boundaries with other agents
|
|
21
|
+
|
|
22
|
+
## Speech Examples
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
📣 Mia: "Let's pick one beachhead ICP first, then expand."
|
|
26
|
+
📣 Mia: "Message-market fit is weak. The claim and proof don't align yet."
|
|
27
|
+
📣 Mia: "We'll define launch gates now: scale, stop, or pivot by week 1."
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
/gtm # Activate Mia + display menu
|
|
34
|
+
/gtm strategic # Strategic tone (direction/trade-off)
|
|
35
|
+
/gtm execution # Execution tone (owner/timeline/checklist)
|
|
36
|
+
/gtm strategy # End-to-end GTM blueprint
|
|
37
|
+
/gtm message # Messaging map refinement
|
|
38
|
+
/gtm launch # Launch playbook
|
|
39
|
+
/gtm experiment # GTM experiment backlog
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Tone Mode Selection
|
|
45
|
+
|
|
46
|
+
| Mode | Use Case | Output Style |
|
|
47
|
+
|------|----------|--------------|
|
|
48
|
+
| **Strategic** | "Which direction should we take?" | options/trade-offs/recommendation |
|
|
49
|
+
| **Execution** | "What do we do this week?" | owner/timeline/checklist/KPI cadence |
|
|
50
|
+
|
|
51
|
+
If not specified, Mia auto-selects mode from the request and states it explicitly.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Trigger Menu
|
|
56
|
+
|
|
57
|
+
| Trigger | Function |
|
|
58
|
+
|---------|----------|
|
|
59
|
+
| **GTM** | GTM blueprint (ICP + positioning + channel + KPI) |
|
|
60
|
+
| **MSG** | Messaging map (problem/value/proof/CTA by segment) |
|
|
61
|
+
| **LCH** | Launch playbook (pre-launch / launch / post-launch) |
|
|
62
|
+
| **EXP** | Experiment backlog (acquisition/activation tests) |
|
|
63
|
+
| **PKG** | Packaging narrative (plan/price story) |
|
|
64
|
+
| **STM** | Strategic mode response (direction decision support) |
|
|
65
|
+
| **EXM** | Execution mode response (launch runbook style) |
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Handoff Flow
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
🗺️ Marco (market evidence) + 🎤 Rita (VOC)
|
|
73
|
+
↓
|
|
74
|
+
📣 Mia (GTM design)
|
|
75
|
+
↓
|
|
76
|
+
📋 Penny / 📡 Tara / 📊 Vicky
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
*Agent*: 📣 Mia (GTM Strategist)
|
|
82
|
+
*Connections*: 🎯 Simon (strategy owner), 🗺️ Marco (market), 🎤 Rita (VOC), 📈 Danny (analysis), 📋 Penny (planning), 📡 Tara (tracking), 📊 Vicky (validation)
|
|
@@ -246,6 +246,7 @@ Automatically suggest handoff at work completion:
|
|
|
246
246
|
| Situation | Suggestion |
|
|
247
247
|
|-----------|-----------|
|
|
248
248
|
| PRD writing complete | "Shall we hand off to 📋 Penny?" |
|
|
249
|
+
| Product direction finalized | "Shall we hand off to 📣 Mia for GTM planning?" |
|
|
249
250
|
| Story writing complete | "Shall we request screen specs from 📐 Hank?" |
|
|
250
251
|
| Screen spec complete | "Shall we hand off to 🔨 Derek?" |
|
|
251
252
|
| Spec has tracking events | "Shall we request review from 📡 Tara?" |
|
|
@@ -254,5 +255,5 @@ Automatically suggest handoff at work completion:
|
|
|
254
255
|
|
|
255
256
|
---
|
|
256
257
|
|
|
257
|
-
*Connected agents*: 🎯 Simon, 📋 Penny, 📐 Hank, 📡 Tara, 🔨 Derek, 🧪 Quinn, 📊 Vicky, 🗓️ Nora
|
|
258
|
-
*Related commands*: `/strategy`, `/plan`, `/market`, `/tracking`, `/validate`, `/retro`
|
|
258
|
+
*Connected agents*: 🎯 Simon, 📣 Mia, 📋 Penny, 📐 Hank, 📡 Tara, 🔨 Derek, 🧪 Quinn, 📊 Vicky, 🗓️ Nora
|
|
259
|
+
*Related commands*: `/strategy`, `/gtm`, `/plan`, `/market`, `/tracking`, `/validate`, `/retro`
|
|
@@ -116,5 +116,5 @@ If `$ARGUMENTS` is `research`:
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
118
|
*Agent*: 🗺️ Marco (Market Researcher)
|
|
119
|
-
*Connections*: 🎯 Simon (strategic decisions), 📈 Danny (market data validation)
|
|
119
|
+
*Connections*: 🎯 Simon (strategic decisions), 📣 Mia (GTM strategy), 📈 Danny (market data validation)
|
|
120
120
|
*Tools*: WebSearch, WebFetch
|
|
@@ -19,14 +19,14 @@ ARGUMENTS: $ARGUMENTS
|
|
|
19
19
|
|
|
20
20
|
## Execution Steps
|
|
21
21
|
|
|
22
|
-
### -1. Setup
|
|
22
|
+
### -1. Setup + Ambiguity Gate Check ⭐
|
|
23
23
|
|
|
24
24
|
**First**, check whether the `.context/project.yaml` file exists.
|
|
25
25
|
|
|
26
26
|
```
|
|
27
27
|
project.yaml exists?
|
|
28
|
-
├──
|
|
29
|
-
└──
|
|
28
|
+
├── No → Start Setup Wizard
|
|
29
|
+
└── Yes → Evaluate ambiguity gate before normal flow
|
|
30
30
|
```
|
|
31
31
|
|
|
32
32
|
#### Setup Wizard Start
|
|
@@ -54,13 +54,10 @@ If `.context/project.yaml` does not exist, treat this as a first run and start t
|
|
|
54
54
|
- Communication style, work style preferences
|
|
55
55
|
- → Generate `user-context.yaml`
|
|
56
56
|
|
|
57
|
-
4. **Phase 2:
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
-
|
|
61
|
-
- What's validated / what needs validation
|
|
62
|
-
- Research unknown areas together via WebSearch
|
|
63
|
-
- → Generate `project.yaml`
|
|
57
|
+
4. **Phase 2: Project Skeleton Setup**
|
|
58
|
+
- Fill minimal project defaults and metadata gate fields
|
|
59
|
+
- Keep deep interview for ambiguity-gate phase
|
|
60
|
+
- → Generate initial `project.yaml`
|
|
64
61
|
|
|
65
62
|
5. **Phase 3: Sensitive Information Guidance** (🎩 Oscar)
|
|
66
63
|
- Suggest creating `.secrets.yaml` template
|
|
@@ -76,6 +73,37 @@ Generated files:
|
|
|
76
73
|
What would you like to start working on?
|
|
77
74
|
```
|
|
78
75
|
|
|
76
|
+
#### Ambiguity Gate (mandatory before normal `/start`)
|
|
77
|
+
|
|
78
|
+
If `.context/project.yaml` exists, read `_meta` and evaluate:
|
|
79
|
+
|
|
80
|
+
```js
|
|
81
|
+
meta = _meta ?? {};
|
|
82
|
+
needsDeepInterview = meta.needs_deep_interview === true;
|
|
83
|
+
ambiguityScoreRaw = meta.ambiguity_score ?? (needsDeepInterview ? 1 : 0);
|
|
84
|
+
ambiguityScoreParsed = Number(ambiguityScoreRaw);
|
|
85
|
+
ambiguityScore = Number.isFinite(ambiguityScoreParsed) ? ambiguityScoreParsed : 1;
|
|
86
|
+
|
|
87
|
+
if (needsDeepInterview || ambiguityScore >= 0.6) {
|
|
88
|
+
// Gate is open: run deep interview first
|
|
89
|
+
} else {
|
|
90
|
+
// Gate is closed: proceed to step 0
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
If `_meta` is missing or malformed, treat it as **gate open** (safe default).
|
|
95
|
+
If gate is open, **do not proceed to step 0/session selection yet**.
|
|
96
|
+
Run the deep project interview first (🎯 Simon-led), then update `.context/project.yaml`:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
_meta:
|
|
100
|
+
needs_deep_interview: false
|
|
101
|
+
ambiguity_score: <updated numeric score>
|
|
102
|
+
last_interview: "<ISO8601>"
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Only after this metadata update should `/start` continue with normal session flow.
|
|
106
|
+
|
|
79
107
|
---
|
|
80
108
|
|
|
81
109
|
### 0. Load Secret Variables (Required)
|
|
@@ -34,7 +34,7 @@ Read `.context/agents/strategist.md` and activate Simon's persona.
|
|
|
34
34
|
| **HYP** | Formulate hypothesis (Problem → Hypothesis → Validation method) |
|
|
35
35
|
| **PRI** | Prioritization (Impact vs Effort) |
|
|
36
36
|
|
|
37
|
-
> **Note**: Market analysis → 🗺️ Marco (`/market`).
|
|
37
|
+
> **Note**: Market analysis → 🗺️ Marco (`/market`). GTM planning → 📣 Mia (`/gtm`).
|
|
38
38
|
|
|
39
39
|
## Response Format
|
|
40
40
|
|
|
@@ -52,6 +52,7 @@ Oscar is prohibited from answering directly. When delegating, explain the reason
|
|
|
52
52
|
| `VOC`, `고객/customer`, `피드백/feedback`, `불만/complaint`, `인터뷰/interview` | 🎤 **Rita** | `agents/researcher.md` |
|
|
53
53
|
| `가설/hypothesis`, `전략/strategy`, `PRD`, `우선순위/priority`, `왜/why` | 🎯 **Simon** | `agents/strategist.md` |
|
|
54
54
|
| `시장/market`, `경쟁사/competitor`, `포지셔닝/positioning`, `벤치마크/benchmark` | 🗺️ **Marco** | `agents/market-researcher.md` |
|
|
55
|
+
| `GTM`, `go-to-market`, `런치/launch`, `메시징/messaging`, `채널/channel` | 📣 **Mia** | `agents/gtm-strategist.md` |
|
|
55
56
|
| `스프린트/sprint`, `스토리/story`, `백로그/backlog`, `속도/velocity` | 📋 **Penny** | `agents/planner.md` |
|
|
56
57
|
| `스크린스펙/screen spec`, `핸드오프/handoff`, `릴리스/release`, `개발전달/dev delivery` | 📐 **Hank** | `agents/handoff-specialist.md` |
|
|
57
58
|
| `검증/validation`, `Before/After`, `Guard Rail`, `OKR check` | 📊 **Vicky** | `agents/validator.md` |
|
|
@@ -129,13 +130,14 @@ Include Working Memory in the handoff context when switching agents.
|
|
|
129
130
|
|
|
130
131
|
### Agents
|
|
131
132
|
|
|
132
|
-
#### PO Team (
|
|
133
|
+
#### PO Team (10 + Orchestrator + Ollie/Sage)
|
|
133
134
|
|
|
134
135
|
| Command | Agent | Role |
|
|
135
136
|
|---------|-------|------|
|
|
136
137
|
| (default) | 🎩 Oscar | **Orchestrator** — Routing, coordination, proactive alerts |
|
|
137
138
|
| `/strategy` | 🎯 Simon | PRD, hypotheses, priorities |
|
|
138
139
|
| `/market` | 🗺️ Marco | Market research, competitive analysis, positioning |
|
|
140
|
+
| `/gtm` | 📣 Mia | Go-to-market strategy, launch planning, messaging |
|
|
139
141
|
| `/plan` | 📋 Penny | Sprint, stories, backlog |
|
|
140
142
|
| `/handoff` | 📐 Hank | Screen specs, handoff, release readiness |
|
|
141
143
|
| `/validate` | 📊 Vicky | Hypothesis validation, Guard Rail, OKR check |
|
|
@@ -171,9 +173,9 @@ Include Working Memory in the handoff context when switching agents.
|
|
|
171
173
|
├── .secrets.yaml # Sensitive data (gitignored)
|
|
172
174
|
├── WORKFLOW.md # Workflow guide
|
|
173
175
|
│
|
|
174
|
-
├── agents/ # Agent personas (
|
|
176
|
+
├── agents/ # Agent personas (15 + TEMPLATE.md)
|
|
175
177
|
├── oscar/workflows/ # Oscar extension modules (conditionally loaded)
|
|
176
|
-
├── templates/ # Reusable templates (
|
|
178
|
+
├── templates/ # Reusable templates (12)
|
|
177
179
|
├── metrics/ # Metrics data
|
|
178
180
|
├── daily/ # Daily work logs (YYYY-MM-DD.yaml)
|
|
179
181
|
│
|
package/bin/cli.mjs
CHANGED
|
@@ -13,7 +13,7 @@ const USAGE = `
|
|
|
13
13
|
|
|
14
14
|
Commands:
|
|
15
15
|
init [dir] Scaffold + interactive setup + hydration (default)
|
|
16
|
-
hydrate [dir]
|
|
16
|
+
hydrate [dir] Sync latest scaffold templates + re-hydrate from project.yaml
|
|
17
17
|
doctor [dir] Check installation health
|
|
18
18
|
help Show this help
|
|
19
19
|
|
|
@@ -26,6 +26,7 @@ const USAGE = `
|
|
|
26
26
|
Examples:
|
|
27
27
|
npx popilot init my-project
|
|
28
28
|
npx popilot hydrate
|
|
29
|
+
npx popilot hydrate --force
|
|
29
30
|
npx popilot doctor
|
|
30
31
|
npx popilot my-project # same as: popilot init my-project
|
|
31
32
|
`;
|
|
@@ -65,7 +66,7 @@ async function main() {
|
|
|
65
66
|
await cmdInit(targetDir, { skipSpecSite, force, platform });
|
|
66
67
|
break;
|
|
67
68
|
case 'hydrate':
|
|
68
|
-
await cmdHydrate(targetDir, { skipSpecSite, platform });
|
|
69
|
+
await cmdHydrate(targetDir, { skipSpecSite, platform, force });
|
|
69
70
|
break;
|
|
70
71
|
case 'doctor':
|
|
71
72
|
await cmdDoctor(targetDir, { skipSpecSite, platform });
|
|
@@ -183,12 +184,33 @@ async function cmdInit(targetDir, { skipSpecSite, force, platform }) {
|
|
|
183
184
|
|
|
184
185
|
// ── hydrate ─────────────────────────────────────────────
|
|
185
186
|
|
|
186
|
-
async function cmdHydrate(targetDir, { skipSpecSite, platform }) {
|
|
187
|
+
async function cmdHydrate(targetDir, { skipSpecSite, platform, force }) {
|
|
187
188
|
console.log();
|
|
188
189
|
console.log(' 🚀 Popilot — Re-hydrating templates');
|
|
189
190
|
console.log(' ══════════════════════════════════════');
|
|
190
191
|
console.log();
|
|
191
192
|
|
|
193
|
+
// 0. Sync scaffold updates before hydration.
|
|
194
|
+
// - default: only add missing files (safe upgrade path)
|
|
195
|
+
// - --force: overwrite existing scaffold files as well
|
|
196
|
+
console.log(` 🔄 Syncing latest scaffold (${force ? 'overwrite enabled' : 'missing files only'})...`);
|
|
197
|
+
const { copied, overwritten, appends } = await copyScaffold(targetDir, {
|
|
198
|
+
skipSpecSite,
|
|
199
|
+
overwriteExisting: force,
|
|
200
|
+
platform,
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
for (const { file, content } of appends) {
|
|
204
|
+
const filePath = resolve(targetDir, file);
|
|
205
|
+
await appendToFile(filePath, content);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
console.log(` +${copied.length} files added`);
|
|
209
|
+
if (overwritten.length > 0) {
|
|
210
|
+
console.log(` ~${overwritten.length} files overwritten (--force)`);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// 1. Hydrate
|
|
192
214
|
const { hydrated, domains } = await hydrate(targetDir, { skipSpecSite, platform });
|
|
193
215
|
for (const f of hydrated) {
|
|
194
216
|
console.log(` ${f} ✅`);
|
package/lib/hydrate.mjs
CHANGED
|
@@ -75,6 +75,7 @@ export async function hydrate(targetDir, opts = {}) {
|
|
|
75
75
|
'orchestrator.md.hbs': 'orchestrator',
|
|
76
76
|
'strategist.md.hbs': 'strategist',
|
|
77
77
|
'market-researcher.md.hbs': 'market-researcher',
|
|
78
|
+
'gtm-strategist.md.hbs': 'gtm-strategist',
|
|
78
79
|
'planner.md.hbs': 'planner',
|
|
79
80
|
'handoff-specialist.md.hbs': 'handoff-specialist',
|
|
80
81
|
'validator.md.hbs': 'validator',
|
package/lib/setup-wizard.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Interactive setup wizard — terminal interview → project.yaml + related files.
|
|
3
3
|
*
|
|
4
4
|
* Collects only essential config. AI deep interview is deferred to Claude Code
|
|
5
|
-
* via `_meta.needs_deep_interview
|
|
5
|
+
* via metadata gate fields (`_meta.needs_deep_interview`, `_meta.ambiguity_score`).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import { readdir, readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
@@ -16,6 +16,7 @@ import { parse as parseYaml, stringify as stringifyYaml } from './yaml-lite.mjs'
|
|
|
16
16
|
* @param {string} targetDir - Project root (scaffold already copied)
|
|
17
17
|
* @param {object} [opts]
|
|
18
18
|
* @param {import('node:readline/promises').Interface} [opts.rl] - Inject readline for testing
|
|
19
|
+
* @param {string|null} [opts.platform] - Optional adapter/platform name
|
|
19
20
|
* @returns {Promise<void>}
|
|
20
21
|
*/
|
|
21
22
|
export async function runSetupWizard(targetDir, opts = {}) {
|
|
@@ -232,14 +233,76 @@ async function collectObjectList(rl, question) {
|
|
|
232
233
|
return items;
|
|
233
234
|
}
|
|
234
235
|
|
|
236
|
+
// ── Ambiguity score ─────────────────────────────────────
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Calculate ambiguity score from project.yaml content.
|
|
240
|
+
* Returns 0.0 (clear) to 1.0 (high ambiguity).
|
|
241
|
+
*
|
|
242
|
+
* Note: fresh setup defaults are usually high ambiguity because deep-interview
|
|
243
|
+
* fields are empty, but this may be below 1.0 if users fill optional basics
|
|
244
|
+
* (for example `project.tagline`) during setup.
|
|
245
|
+
*
|
|
246
|
+
* @param {object} yaml
|
|
247
|
+
* @returns {number}
|
|
248
|
+
*/
|
|
249
|
+
export function calculateAmbiguityScore(yaml) {
|
|
250
|
+
const root = (yaml && typeof yaml === 'object') ? yaml : {};
|
|
251
|
+
|
|
252
|
+
const checks = [
|
|
253
|
+
// Basic clarity
|
|
254
|
+
{ weight: 0.1, filled: !!root.project?.tagline },
|
|
255
|
+
|
|
256
|
+
// Problem & market
|
|
257
|
+
{ weight: 0.15, filled: !!root.problem?.core },
|
|
258
|
+
{ weight: 0.1, filled: !!root.problem?.target },
|
|
259
|
+
{ weight: 0.05, filled: root.problem?.alternatives?.length > 0 },
|
|
260
|
+
{ weight: 0.05, filled: !!root.problem?.timing },
|
|
261
|
+
|
|
262
|
+
// Solution
|
|
263
|
+
{ weight: 0.15, filled: !!root.solution?.approach },
|
|
264
|
+
{ weight: 0.08, filled: !!root.solution?.differentiation },
|
|
265
|
+
{ weight: 0.05, filled: root.solution?.outcome?.length > 0 },
|
|
266
|
+
|
|
267
|
+
// Current state
|
|
268
|
+
{ weight: 0.1, filled: !!root.current_state?.stage },
|
|
269
|
+
{ weight: 0.07, filled: !!root.current_state?.focus },
|
|
270
|
+
{ weight: 0.05, filled: !!root.current_state?.next_milestone },
|
|
271
|
+
|
|
272
|
+
// Validation
|
|
273
|
+
{ weight: 0.05, filled: root.validation?.confirmed?.length > 0 },
|
|
274
|
+
];
|
|
275
|
+
|
|
276
|
+
let totalWeight = 0;
|
|
277
|
+
let filledWeight = 0;
|
|
278
|
+
|
|
279
|
+
for (const { weight, filled } of checks) {
|
|
280
|
+
totalWeight += weight;
|
|
281
|
+
if (filled) filledWeight += weight;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
return Math.round((1 - filledWeight / totalWeight) * 100) / 100;
|
|
285
|
+
}
|
|
286
|
+
|
|
235
287
|
// ── project.yaml builder ────────────────────────────────
|
|
236
288
|
|
|
289
|
+
export const ALL_INTEGRATION_PROVIDERS = [
|
|
290
|
+
'ga4',
|
|
291
|
+
'mixpanel',
|
|
292
|
+
'notion',
|
|
293
|
+
'linear',
|
|
294
|
+
'channel_io',
|
|
295
|
+
'intercom',
|
|
296
|
+
'prod_db',
|
|
297
|
+
'notebooklm',
|
|
298
|
+
'corti',
|
|
299
|
+
];
|
|
300
|
+
|
|
237
301
|
function buildProjectYaml({ projectName, tagline, projectType, domains, devScope, integrations, platform }) {
|
|
238
302
|
// Build the full integrations block with all known providers
|
|
239
|
-
const allProviders = ['ga4', 'mixpanel', 'notion', 'linear', 'channel_io', 'intercom', 'prod_db', 'notebooklm', 'corti'];
|
|
240
303
|
const integrationsBlock = {};
|
|
241
304
|
|
|
242
|
-
for (const id of
|
|
305
|
+
for (const id of ALL_INTEGRATION_PROVIDERS) {
|
|
243
306
|
if (integrations[id]) {
|
|
244
307
|
integrationsBlock[id] = integrations[id];
|
|
245
308
|
} else {
|
|
@@ -247,7 +310,7 @@ function buildProjectYaml({ projectName, tagline, projectType, domains, devScope
|
|
|
247
310
|
}
|
|
248
311
|
}
|
|
249
312
|
|
|
250
|
-
|
|
313
|
+
const yaml = {
|
|
251
314
|
project: {
|
|
252
315
|
name: projectName,
|
|
253
316
|
tagline: tagline || '',
|
|
@@ -298,11 +361,16 @@ function buildProjectYaml({ projectName, tagline, projectType, domains, devScope
|
|
|
298
361
|
created_at: new Date().toISOString(),
|
|
299
362
|
created_by: 'popilot init',
|
|
300
363
|
needs_deep_interview: true,
|
|
364
|
+
ambiguity_score: 0,
|
|
301
365
|
last_interview: null,
|
|
302
366
|
version: '1.0.0',
|
|
303
367
|
...(platform ? { platform } : {}),
|
|
304
368
|
},
|
|
305
369
|
};
|
|
370
|
+
|
|
371
|
+
yaml._meta.ambiguity_score = calculateAmbiguityScore(yaml);
|
|
372
|
+
|
|
373
|
+
return yaml;
|
|
306
374
|
}
|
|
307
375
|
|
|
308
376
|
// ── Helpers ─────────────────────────────────────────────
|
package/package.json
CHANGED
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "popilot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Multi-agent PO/PM system scaffold for Claude Code",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
|
-
"popilot": "
|
|
7
|
+
"popilot": "bin/cli.mjs"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
+
"lint": "node scripts/lint.mjs",
|
|
11
|
+
"typecheck": "node scripts/typecheck.mjs",
|
|
10
12
|
"test": "node --test test/*.test.mjs"
|
|
11
13
|
},
|
|
12
14
|
"files": [
|
|
13
15
|
"bin/",
|
|
14
16
|
"lib/",
|
|
17
|
+
"scripts/",
|
|
15
18
|
"scaffold/",
|
|
16
19
|
"adapters/",
|
|
17
20
|
"README.md"
|
|
@@ -56,10 +56,10 @@ The Oscar system and service codebase are in **separate Git repositories**:
|
|
|
56
56
|
🎩 Oscar
|
|
57
57
|
(Routing & Coordination)
|
|
58
58
|
│
|
|
59
|
-
|
|
60
|
-
│ │ │
|
|
61
|
-
▼ ▼ ▼
|
|
62
|
-
🎯 Simon ◄──────► 📈 Danny ◄──────► 🎤 Rita
|
|
59
|
+
┌─────────────────┼─────────────────┬──────────┐
|
|
60
|
+
│ │ │ │
|
|
61
|
+
▼ ▼ ▼ ▼
|
|
62
|
+
🎯 Simon ◄──────► 📈 Danny ◄──────► 🎤 Rita 📣 Mia
|
|
63
63
|
│ │
|
|
64
64
|
▼ │
|
|
65
65
|
📋 Penny │
|
|
@@ -74,6 +74,8 @@ The Oscar system and service codebase are in **separate Git repositories**:
|
|
|
74
74
|
| From | To | Situation | Oscar's Role |
|
|
75
75
|
|------|-----|-----------|-------------|
|
|
76
76
|
| 🎯 Simon | 📋 Penny | PRD completed | Handoff check |
|
|
77
|
+
| 🎯 Simon | 📣 Mia | Product direction finalized | Trigger GTM blueprint |
|
|
78
|
+
| 📣 Mia | 📋 Penny | GTM plan finalized | Convert GTM scope to sprint stories |
|
|
77
79
|
| 📋 Penny | 📊 Vicky | Development completed | Confirm validation readiness |
|
|
78
80
|
| 📊 Vicky | 🎯 Simon | Validation completed | Prompt learning summary |
|
|
79
81
|
| 📊 Vicky | 📈 Danny | Anomaly detected | Request deep analysis |
|
|
@@ -105,6 +107,10 @@ Level 1: Sprint PRD (Sprint level)
|
|
|
105
107
|
└─→ One Question, hypothesis, OMTM
|
|
106
108
|
└─→ Owner: 🎯 Simon / Template: templates/prd.md
|
|
107
109
|
|
|
110
|
+
Level 1.5: GTM Plan (Launch level, optional but recommended)
|
|
111
|
+
└─→ ICP, messaging, channel, launch KPI/gates
|
|
112
|
+
└─→ Owner: 📣 Mia / Template: templates/gtm-plan.md
|
|
113
|
+
|
|
108
114
|
Level 2: Epic Spec (Epic level) ⭐ Core
|
|
109
115
|
└─→ WHY, WHAT, HOW (overview), EDGE
|
|
110
116
|
└─→ Owner: PO (🎯 Simon support) / Template: templates/epic-spec.md
|
|
@@ -268,6 +274,7 @@ Turso (LibSQL) based team retrospective board. Route: `/retro`.
|
|
|
268
274
|
| Template | Owner | File | Order |
|
|
269
275
|
|----------|-------|------|-------|
|
|
270
276
|
| Sprint PRD | 🎯 Simon | `templates/prd.md` | 1 |
|
|
277
|
+
| GTM Plan | 📣 Mia | `templates/gtm-plan.md` | 1.5 |
|
|
271
278
|
| Epic Spec | PO | `templates/epic-spec.md` | 2 |
|
|
272
279
|
|
|
273
280
|
### Handoff (📋 Penny-led)
|