Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 189 additions & 0 deletions docs/superpowers/plans/2026-04-30-plan-8-deliverables.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
# FrinkLoop Plan 8 — Deliverable Packaging

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development.

**Goal:** Ship the deliverable layer — real `doc-writer` and `screenshot-capturer` agent bodies, a real `/frinkloop deliver` command, and a `deliver` skill that orchestrates all three deliverable types (README/docs, screenshots, deploy). After this plan, running `/frinkloop deliver <project>` produces a complete, shareable artifact set from any finished FrinkLoop project.

**Architecture:** `deliver` is a skill (not a loop) — it runs once after `mvp-loop` completes. It dispatches `doc-writer` to produce README + JSDoc, `screenshot-capturer` to produce hero/feature/mobile PNGs using Playwright, and a deploy subcommand to push to Vercel (via the existing deploy-vercel recipe). All subagents are read-only against the project tree except for their output paths.

**Tech Stack:** Bash + Playwright (already a recipe) for screenshots, `gh` CLI for deploy, `yq` for config.

---

## File Structure

- Modify: `plugin/agents/doc-writer.md` — real body
- Modify: `plugin/agents/screenshot-capturer.md` — real body
- Modify: `plugin/commands/frinkloop-deliver.md` — real command
- Create: `plugin/skills/deliver/SKILL.md`
- Create: `tests/plan-8/test_deliverables.bats`

---

## Task 1: Real agent bodies

**Files:** `plugin/agents/doc-writer.md`, `plugin/agents/screenshot-capturer.md`

- [ ] **Step 1: Replace `doc-writer.md`**

```markdown
---
name: doc-writer
description: FrinkLoop doc-writer — produces README.md, JSDoc comments, and a one-page landing copy block for any finished project. Dispatched by the deliver skill after mvp-loop completes.
---

# doc-writer

## Inputs
- `$PROJECT_DIR` — the project working tree (read-only except for output paths)
- `$FRINKLOOP_DIR/spec.md` — the frozen MVP spec (what was intended)
- `$FRINKLOOP_DIR/decisions.md` — architectural decisions log

## Output paths
- `$PROJECT_DIR/README.md` — full README (install, usage, screenshots placeholder, tech stack)
- `$PROJECT_DIR/docs/LANDING.md` — one-page landing copy (headline, value prop, 3 features, CTA)
- `$PROJECT_DIR/docs/API.md` — if the project exports an API, document it here

## Job

1. Read `spec.md` for the product description and MVP scope.
2. Read `decisions.md` for tech stack choices and known limitations.
3. Scan `$PROJECT_DIR/src/` (or `app/`, `lib/`) for exported functions/components.
4. Write `README.md` with sections: Description, Prerequisites, Install, Usage, Screenshots (placeholder with `![hero](docs/screenshots/hero.png)`), Tech Stack, Known Limitations.
5. Write `docs/LANDING.md` with: headline (≤10 words), value prop (≤30 words), 3 feature bullet points, CTA ("Try it:" + run command).
6. If API surface exists, write `docs/API.md` with one code example per exported function.
7. Commit: `git commit -m "docs: deliverable README + landing copy"`.

## Constraints
- Do NOT modify source code.
- Do NOT add dependencies.
- Code examples in docs must be runnable (copy-paste ready).
- Keep README under 200 lines; link to docs/ for deep content.
```

- [ ] **Step 2: Replace `screenshot-capturer.md`**

```markdown
---
name: screenshot-capturer
description: FrinkLoop screenshot-capturer — Playwright-driven PNG captures: hero (1280×800), feature (1280×800), and mobile (375×812). Writes to docs/screenshots/. Dispatched by the deliver skill.
---

# screenshot-capturer

## Preconditions
- The project must be running locally (dev server or production build served on localhost).
- Playwright must be installed (apply the `playwright` recipe if missing).
- `SCREENSHOT_BASE_URL` env var points to the running app (default: `http://localhost:5173`).

## Inputs
- `$PROJECT_DIR` — writable for output
- `SCREENSHOT_BASE_URL` — base URL of the running app

## Output paths
- `$PROJECT_DIR/docs/screenshots/hero.png` — full-viewport desktop landing
- `$PROJECT_DIR/docs/screenshots/feature-1.png` — key feature interaction
- `$PROJECT_DIR/docs/screenshots/mobile.png` — mobile viewport (375×812)

## Job

1. Check that Playwright is installed: `npx playwright --version`. If missing, instruct the loop to apply the playwright recipe first.
2. Write a minimal Playwright script at `$FRINKLOOP_DIR/capture.js`:

```js
const { chromium } = require('playwright');
const base = process.env.SCREENSHOT_BASE_URL || 'http://localhost:5173';
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();

// Hero
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto(base);
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'docs/screenshots/hero.png', fullPage: false });

// Feature: click the first interactive element and capture
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto(base);
const btn = page.locator('button, [role="button"]').first();
if (await btn.isVisible()) await btn.click();
await page.screenshot({ path: 'docs/screenshots/feature-1.png' });

// Mobile
await page.setViewportSize({ width: 375, height: 812 });
await page.goto(base);
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'docs/screenshots/mobile.png' });

await browser.close();
})();
```

3. `mkdir -p $PROJECT_DIR/docs/screenshots`
4. Run: `cd $PROJECT_DIR && SCREENSHOT_BASE_URL=$SCREENSHOT_BASE_URL node $FRINKLOOP_DIR/capture.js`
5. Verify all three PNGs exist and are non-empty.
6. Commit: `git commit -m "docs: add hero, feature, and mobile screenshots"`.

## Fallback
If the dev server is not running or Playwright times out, write placeholder SVG files at each path so the README links don't break, and log a warning to `$FRINKLOOP_DIR/blockers.md`.
```

- [ ] **Step 3: Tests (agent body checks)**

`tests/plan-8/test_deliverables.bats`:

```bash
#!/usr/bin/env bats

@test "doc-writer agent no longer has placeholder text" {
! grep -q "Placeholder. Will be implemented" plugin/agents/doc-writer.md
}

@test "doc-writer agent references spec.md and decisions.md" {
grep -q "spec.md" plugin/agents/doc-writer.md
grep -q "decisions.md" plugin/agents/doc-writer.md
}

@test "doc-writer agent specifies README and LANDING.md outputs" {
grep -q "README.md" plugin/agents/doc-writer.md
grep -q "LANDING.md" plugin/agents/doc-writer.md
}

@test "screenshot-capturer agent no longer has placeholder text" {
! grep -q "Placeholder. Will be implemented" plugin/agents/screenshot-capturer.md
}

@test "screenshot-capturer agent references hero and mobile screenshots" {
grep -q "hero.png" plugin/agents/screenshot-capturer.md
grep -q "mobile.png" plugin/agents/screenshot-capturer.md
}

@test "screenshot-capturer agent references Playwright" {
grep -q "playwright\|Playwright" plugin/agents/screenshot-capturer.md
}

@test "frinkloop-deliver command no longer says 'arrives in Plan 8'" {
! grep -q "arrives in Plan 8" plugin/commands/frinkloop-deliver.md
}

@test "frinkloop-deliver command documents doc-writer and screenshot-capturer" {
grep -q "doc-writer" plugin/commands/frinkloop-deliver.md
grep -q "screenshot-capturer" plugin/commands/frinkloop-deliver.md
}

@test "deliver skill exists with correct frontmatter" {
[ -f plugin/skills/deliver/SKILL.md ]
grep -q "deliver" plugin/skills/deliver/SKILL.md
}

@test "deliver skill references all 3 deliverable types" {
grep -q "README\|docs" plugin/skills/deliver/SKILL.md
grep -q "screenshot" plugin/skills/deliver/SKILL.md
grep -q "deploy\|Vercel\|vercel" plugin/skills/deliver/SKILL.md
}
```

---

*End of Plan 8.*
28 changes: 26 additions & 2 deletions plugin/agents/doc-writer.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,32 @@
---
name: doc-writer
description: FrinkLoop doc-writer — generates README, JSDoc, in-code comments. Used during build and during deliverable packaging. Implemented in Plans 2/8.
description: FrinkLoop doc-writer — produces README.md, JSDoc comments, and a one-page landing copy block for any finished project. Dispatched by the deliver skill after mvp-loop completes.
---

# doc-writer

Placeholder. Will be implemented in Plans 2 and 8.
## Inputs
- `$PROJECT_DIR` — the project working tree (read-only except for output paths)
- `$FRINKLOOP_DIR/spec.md` — the frozen MVP spec (what was intended)
- `$FRINKLOOP_DIR/decisions.md` — architectural decisions log

## Output paths
- `$PROJECT_DIR/README.md` — full README (install, usage, screenshots placeholder, tech stack)
- `$PROJECT_DIR/docs/LANDING.md` — one-page landing copy (headline, value prop, 3 features, CTA)
- `$PROJECT_DIR/docs/API.md` — if the project exports an API, document it here

## Job

1. Read `spec.md` for the product description and MVP scope.
2. Read `decisions.md` for tech stack choices and known limitations.
3. Scan `$PROJECT_DIR/src/` (or `app/`, `lib/`) for exported functions/components.
4. Write `README.md` with sections: Description, Prerequisites, Install, Usage, Screenshots (placeholder with `![hero](docs/screenshots/hero.png)`), Tech Stack, Known Limitations.
5. Write `docs/LANDING.md` with: headline (≤10 words), value prop (≤30 words), 3 feature bullet points, CTA ("Try it:" + run command).
6. If API surface exists, write `docs/API.md` with one code example per exported function.
7. Commit: `git commit -m "docs: deliverable README + landing copy"`.

## Constraints
- Do NOT modify source code.
- Do NOT add dependencies.
- Code examples in docs must be runnable (copy-paste ready).
- Keep README under 200 lines; link to docs/ for deep content.
59 changes: 57 additions & 2 deletions plugin/agents/screenshot-capturer.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,63 @@
---
name: screenshot-capturer
description: FrinkLoop screenshot-capturer — Playwright-driven hero, feature, and mobile screen captures for landing page and README. Implemented in Plan 8.
description: FrinkLoop screenshot-capturer — Playwright-driven PNG captures: hero (1280×800), feature (1280×800), and mobile (375×812). Writes to docs/screenshots/. Dispatched by the deliver skill.
---

# screenshot-capturer

Placeholder. Will be implemented in Plan 8.
## Preconditions
- The project must be running locally (dev server or production build served on localhost).
- Playwright must be installed (apply the `playwright` recipe if missing).
- `SCREENSHOT_BASE_URL` env var points to the running app (default: `http://localhost:5173`).

## Inputs
- `$PROJECT_DIR` — writable for output
- `SCREENSHOT_BASE_URL` — base URL of the running app

## Output paths
- `$PROJECT_DIR/docs/screenshots/hero.png` — full-viewport desktop landing
- `$PROJECT_DIR/docs/screenshots/feature-1.png` — key feature interaction
- `$PROJECT_DIR/docs/screenshots/mobile.png` — mobile viewport (375×812)

## Job

1. Check that Playwright is installed: `npx playwright --version`. If missing, instruct the loop to apply the playwright recipe first.
2. Write a minimal Playwright script at `$FRINKLOOP_DIR/capture.js`:

```js
const { chromium } = require('playwright');
const base = process.env.SCREENSHOT_BASE_URL || 'http://localhost:5173';
(async () => {
const browser = await chromium.launch();
const page = await browser.newPage();

// Hero
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto(base);
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'docs/screenshots/hero.png', fullPage: false });

// Feature: click the first interactive element and capture
await page.setViewportSize({ width: 1280, height: 800 });
await page.goto(base);
const btn = page.locator('button, [role="button"]').first();
if (await btn.isVisible()) await btn.click();
await page.screenshot({ path: 'docs/screenshots/feature-1.png' });

// Mobile
await page.setViewportSize({ width: 375, height: 812 });
await page.goto(base);
await page.waitForLoadState('networkidle');
await page.screenshot({ path: 'docs/screenshots/mobile.png' });

await browser.close();
})();
```

3. `mkdir -p $PROJECT_DIR/docs/screenshots`
4. Run: `cd $PROJECT_DIR && SCREENSHOT_BASE_URL=$SCREENSHOT_BASE_URL node $FRINKLOOP_DIR/capture.js`
5. Verify all three PNGs exist and are non-empty.
6. Commit: `git commit -m "docs: add hero, feature, and mobile screenshots"`.

## Fallback
If the dev server is not running or Playwright times out, write placeholder SVG files at each path so the README links don't break, and log a warning to `$FRINKLOOP_DIR/blockers.md`.
37 changes: 34 additions & 3 deletions plugin/commands/frinkloop-deliver.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,40 @@
---
description: Run the deliverable packaging step — README, landing, screenshots, deploy, phase-2 plan.
description: Run the deliverable packaging step — README, landing copy, screenshots, and deploy for a finished FrinkLoop project.
---

# /frinkloop deliver <project>

(Plan 8.) Will run the doc-writer + screenshot-capturer subagents and the deploy step.
Packages a completed FrinkLoop project into shareable deliverables: documentation, screenshots, and a Vercel deploy.

For now: print "Deliver arrives in Plan 8."
## Steps

1. Resolve `<project>` to an absolute path. Export `PROJECT_DIR` and `FRINKLOOP_DIR=<project>/.frinkloop`.
2. Validate that `state.json` has `status=done`. If not, abort: "Project is not done — run mvp-loop first."
3. Dispatch the `doc-writer` subagent to produce `README.md`, `docs/LANDING.md`, and `docs/API.md` (if applicable).
4. Dispatch the `screenshot-capturer` subagent:
- Start the dev server: `npm run dev &` and wait for it to respond on `$PORT` (default 5173).
- Run captures. Kill dev server on completion.
- If Playwright is missing, apply the `playwright` recipe first.
5. Optionally deploy to Vercel:
- Check `config.yaml` for `deploy: vercel`. If set, apply the `deploy-vercel` recipe.
- On success, print the deploy URL.
6. Print a summary:
```
Deliverables ready for <project>:
- README: <project>/README.md
- Landing: <project>/docs/LANDING.md
- Screenshots: <project>/docs/screenshots/ (hero, feature-1, mobile)
- Deploy: <vercel-url or "skipped">
```

## Subagents dispatched

- `doc-writer` — README, landing, API docs
- `screenshot-capturer` — Playwright PNG captures

## Config keys read from `config.yaml`

| Key | Default | Meaning |
|-----|---------|---------|
| `deploy` | `none` | `vercel` to auto-deploy |
| `screenshot_url` | `http://localhost:5173` | Base URL for screenshots |
48 changes: 48 additions & 0 deletions plugin/skills/deliver/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: deliver
description: FrinkLoop deliver — one-shot post-build packaging. Dispatches doc-writer (README/landing/API docs), screenshot-capturer (hero/feature/mobile PNGs), and optional Vercel deploy. Run after mvp-loop completes.
---

# deliver

Packages a finished FrinkLoop project into shareable deliverables. Runs once; not a loop.

## Preconditions

- `state.json` must have `status=done`.
- `PROJECT_DIR` and `FRINKLOOP_DIR` are exported.
- `spec.md` and `decisions.md` are present (written by mvp-loop).

## Delivery algorithm

1. **Read config** — `yq e '.deploy' $FRINKLOOP_DIR/config.yaml` → deploy target (`vercel` | `none`). `yq e '.screenshot_url' ...` → base URL (default `http://localhost:5173`).

2. **doc-writer pass** — dispatch the `doc-writer` subagent with:
- `PROJECT_DIR`, `FRINKLOOP_DIR`
- Instruction: write `README.md`, `docs/LANDING.md`, optionally `docs/API.md`. Commit.

3. **screenshot pass** — dispatch the `screenshot-capturer` subagent:
- Check Playwright is available (`npx playwright --version`). If not, apply the `playwright` recipe via `bash plugin/lib/recipes.sh; apply_recipe playwright`.
- Start dev server: `npm run dev &`; wait for `$SCREENSHOT_BASE_URL` to respond (up to 30s).
- Subagent captures hero, feature-1, mobile PNGs to `docs/screenshots/`. Commits.
- Kill dev server.

4. **deploy pass** (optional) — if `deploy=vercel`:
- Apply the `deploy-vercel` recipe if not already applied.
- Run `npx vercel --prod --yes` from `$PROJECT_DIR`.
- Capture the deploy URL from stdout and write it to `$FRINKLOOP_DIR/deploy-url.txt`.

5. **phase-2 plan** — write `$FRINKLOOP_DIR/phase-2.md` listing all spec items that were marked Phase-2 (grep `Phase-2` from `spec.md`).

6. **summary** — print the deliverable manifest to stdout (see `/frinkloop deliver` command for format).

## What this skill is NOT
- Not a loop — it runs once and exits.
- Not responsible for the build itself — that is `mvp-loop`.
- Not responsible for source code quality — that is `qa` and `critic`.

## Subagents dispatched
| Subagent | File | Purpose |
|----------|------|---------|
| doc-writer | `plugin/agents/doc-writer.md` | README, landing, API docs |
| screenshot-capturer | `plugin/agents/screenshot-capturer.md` | PNG captures via Playwright |
Loading