From 2fbd1b37a98097d33d5491861c3af3d5190fd166 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 1 May 2026 17:34:50 +0000 Subject: [PATCH] =?UTF-8?q?feat(plan-8):=20deliverable=20packaging=20?= =?UTF-8?q?=E2=80=94=20doc-writer,=20screenshot-capturer,=20deliver=20skil?= =?UTF-8?q?l=20+=2010=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Real agent bodies for doc-writer (README/landing/API) and screenshot-capturer (Playwright PNGs). Real /frinkloop deliver command with doc + screenshot + deploy + phase-2 steps. deliver SKILL.md orchestrates the three passes. 139 tests passing (129 plan-1..7 + 10 new). --- .../plans/2026-04-30-plan-8-deliverables.md | 189 ++++++++++++++++++ plugin/agents/doc-writer.md | 28 ++- plugin/agents/screenshot-capturer.md | 59 +++++- plugin/commands/frinkloop-deliver.md | 37 +++- plugin/skills/deliver/SKILL.md | 48 +++++ tests/plan-8/test_deliverables.bats | 48 +++++ 6 files changed, 402 insertions(+), 7 deletions(-) create mode 100644 docs/superpowers/plans/2026-04-30-plan-8-deliverables.md create mode 100644 plugin/skills/deliver/SKILL.md create mode 100644 tests/plan-8/test_deliverables.bats diff --git a/docs/superpowers/plans/2026-04-30-plan-8-deliverables.md b/docs/superpowers/plans/2026-04-30-plan-8-deliverables.md new file mode 100644 index 0000000..4710895 --- /dev/null +++ b/docs/superpowers/plans/2026-04-30-plan-8-deliverables.md @@ -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 ` 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.* diff --git a/plugin/agents/doc-writer.md b/plugin/agents/doc-writer.md index f7811b8..b15c9f1 100644 --- a/plugin/agents/doc-writer.md +++ b/plugin/agents/doc-writer.md @@ -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. diff --git a/plugin/agents/screenshot-capturer.md b/plugin/agents/screenshot-capturer.md index 1ff0002..c427ee7 100644 --- a/plugin/agents/screenshot-capturer.md +++ b/plugin/agents/screenshot-capturer.md @@ -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`. diff --git a/plugin/commands/frinkloop-deliver.md b/plugin/commands/frinkloop-deliver.md index 32fe0ca..ddf6965 100644 --- a/plugin/commands/frinkloop-deliver.md +++ b/plugin/commands/frinkloop-deliver.md @@ -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 -(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 `` to an absolute path. Export `PROJECT_DIR` and `FRINKLOOP_DIR=/.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 : + - README: /README.md + - Landing: /docs/LANDING.md + - Screenshots: /docs/screenshots/ (hero, feature-1, mobile) + - Deploy: + ``` + +## 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 | diff --git a/plugin/skills/deliver/SKILL.md b/plugin/skills/deliver/SKILL.md new file mode 100644 index 0000000..b88787a --- /dev/null +++ b/plugin/skills/deliver/SKILL.md @@ -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 | diff --git a/tests/plan-8/test_deliverables.bats b/tests/plan-8/test_deliverables.bats new file mode 100644 index 0000000..1a7781c --- /dev/null +++ b/tests/plan-8/test_deliverables.bats @@ -0,0 +1,48 @@ +#!/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 +}