From a96fc89389824fd6f387e69742f9fc126d19032e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 5 Sep 2026 22:08:29 +0000 Subject: [PATCH 01/14] plans: add ck plugin phase-one PRD, the agent-workflows proposal, and a devlog entry Turn the 2026-09-05 agent-workflows research proposal into a phase-one PRD for a single code-katz plugin named ck: 21 persona subagents generated from team-cli profiles, /ck:panel (three lenses on three models) and /ck:prd (River-led, panel-challenged) end to end, one instrumentation hook, no UI. - Resolves proposal section 8; Q2 sets the shape: gates live in skills, each span between gates is one plugin workflow, single-agent spans run inline. - Records fifteen corrections to the proposal, led by the plugin name (the command prefix is the plugin name, so it must be ck) and the section 5.5 vs 5.6 model contradiction, resolved by a per-invocation override in panel.js. - Answers plugin vs web app vs wrapper vs dashboard: plugin; /workflows is the run view; a phase-two /ck:map renders the catalog from meta; any workbench is local, never a hosted app with its own store. - Commits the proposal alongside so the PRD's derives-from link resolves. - Appendices carry both workflow scripts, both skills, the generated River agent excerpt, a cost model at 2026-09-05 prices, and sources. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014aqcjmXas9EFDx3pstfpyE --- DEVLOG.md | 31 + ...5-agent-workflows-research-and-proposal.md | 379 +++++ plans/2026-09-05-ck-plugin-prd-phase-1.md | 1417 +++++++++++++++++ 3 files changed, 1827 insertions(+) create mode 100644 plans/2026-09-05-agent-workflows-research-and-proposal.md create mode 100644 plans/2026-09-05-ck-plugin-prd-phase-1.md diff --git a/DEVLOG.md b/DEVLOG.md index 9ba7117..85bd8f5 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -5,6 +5,37 @@ Auto-maintained via [claude-devlog-skill](https://github.com/code-katz/claude-de --- +## [2026-09-05] `ck` plugin phase-one PRD: gates in skills, spans in workflows, no UI yet + +**Category:** `decision` +**Tags:** `ck`, `plugin`, `workflows`, `personas`, `prd`, `marketplace` +**Risk Level:** `medium` +**Breaking Change:** `no` + +### Summary +Turned the 2026-09-05 agent-workflows research proposal into a phase-one PRD for a single code-katz plugin named `ck`: 21 persona subagents generated from team-cli profiles, `/ck:panel` (three lenses on three models) and `/ck:prd` (River-led, panel-challenged) end to end, one instrumentation hook, no UI. Both documents are committed under `plans/`. + +### Detail + +- **Proposal §8 resolved.** Q2 (granularity) decides the shape: a sign-off is a gate in a skill, the only place `AskUserQuestion` exists; each span between gates that needs fan-out is one plugin workflow; single-agent spans run inline. Docs quote: "For sign-off between stages, run each stage as its own workflow." +- **Fifteen corrections to the proposal** are recorded in PRD §3.3. The load-bearing ones: the plugin must be named `ck` because the command prefix is the plugin name; §5.5 (each lens on a different model) contradicts §5.6 (River, Toni, Kai all on Opus 5) and is resolved by a per-invocation override in `panel.js` only; seven personas left unassigned in §5.6 are placed on Opus 5; `TaskCompleted` and `Stop` hook gates are replaced by in-workflow validation; `PreModelSwitch` does not cover subagent fallback; the roster is 21, not 22. +- **Plugin, web app, wrapper, or dashboard:** plugin. `/workflows` is the run view. A phase-two `/ck:map` renders the catalog from workflow `meta`. A workbench, if ever, is local: the viewer may read from files, the editor must run the generator and tests before a commit. Never a hosted app with its own store of definitions. +- **Harness facts** were verified against code.claude.com docs and the pricing page on 2026-09-05. Sonnet 5's scheduled price increase was cancelled, so $2/$10 stands. + +### Decisions Made +- **Marketplace publishing superseded for `ck` only.** team-cli's 2026-07-31 retirement stands for team-cli. `ck` accepts the two-character prefix because workflows and subagents need no shell CLI, and `/akira`, `launch`, and `session` stay on team-cli's install path. +- **Coexist, not retire.** `ck` is additive. Revisit at 90 days with the usage log the plugin ships. +- **All 21 personas port now; prune on evidence.** Generated from a vendored, pinned copy of team-cli profiles with a drift test. `## Required Interactive Behaviors` is rewritten mechanically to output form, because a subagent cannot ask. +- **Tiers change upstream first.** `tiers.conf` is the single source of truth. The §5.6 re-base is a prerequisite team-cli PR; `ck` copies the value verbatim. +- **New repo `code-katz/ck`, one plugin per repo,** as the eighth marketplace entry. + +### Related +- PRD: `plans/2026-09-05-ck-plugin-prd-phase-1.md` +- Proposal: `plans/2026-09-05-agent-workflows-research-and-proposal.md` +- team-cli `ROADMAP.md` revision history, 2026-07-29 and 2026-07-31 (superseded for `ck`) + +--- + ## [2026-03-22] Code Katz marketing plan fully executed: 20 blog posts, README overhauls, org infrastructure **Category:** `milestone` diff --git a/plans/2026-09-05-agent-workflows-research-and-proposal.md b/plans/2026-09-05-agent-workflows-research-and-proposal.md new file mode 100644 index 0000000..2251f8f --- /dev/null +++ b/plans/2026-09-05-agent-workflows-research-and-proposal.md @@ -0,0 +1,379 @@ +# Code Katz Agent Workflows — Research & Product Proposal + +> **Status:** proposal, ready for PRD +> **Date:** 2026-09-05 +> **Author:** Will Curran (with Claude) +> **Handoff:** intended input for Fable to turn into a PRD and build +> **Supersedes:** `claude-conductor/plans/2026-09-04-agent-coordination-engine.md` — see §9 + +--- + +## 1. How to use this document + +This is a research summary and a product proposal, not a PRD. It contains the evidence, the decisions taken and why, the proposed shape of the product, and the questions still open. It deliberately does not contain acceptance criteria, schemas beyond illustrative sketches, or sequencing beyond a rough phase order. + +Every empirical claim is graded: + +- **[M]** measured, independent, method stated +- **[V]** vendor self-measured +- **[D]** product documentation, verified against primary source on 2026-09-05 +- **[P]** practitioner assertion, no measurement + +Where the evidence is weak or absent, the document says so. Several recommendations rest on judgment rather than measurement, and those are flagged. + +--- + +## 2. Goals + +Stated by Will, in his own framing: + +1. **Enjoyment and utility.** claude-team-cli gives a sense of assigning experts to tasks in a larger project. Advance it to be as useful as possible given current models and current harness capability. +2. **Willingness to break.** The next iteration should respond to the research and to current technology. It may break from the current implementation. +3. **Customer zero: Will and his wife.** Used to build and maintain real products. The core requirement is **team members that behave consistently.** A product should start with exploration of the opportunity, then a PRD, then a branding guide — and there is a specific way a branding guide should be done, with specific expected artifacts. +4. **Adversarial and complementary input.** On a decision such as whether to include a feature, get the product lens, the marketing lens, and the UX lens. +5. **Building should be fun.** Personas make building feel exciting and engaging. +6. **Kill it if it does not help.** If this is no better — or worse — than opening Claude and working directly, say so. Challenge the affinity for personas. +7. **Current evidence only.** Ideas should be grounded in the last two months. Models and harnesses have moved. + +### 2.1 How Will works today + +Open a project. Open a session, "use Akira." Open another session, "use Toni." The repeatable activity is: open Claude to advance a project, where the work is the next stage of a project plan, plus occasional exploratory analysis. + +Named recurring jobs: market research; implement a roadmap feature (backend + frontend + UX + marketing content); fix bugs; plan the next roadmap phase; write a PRD; create a GTM plan. + +**The unit is the workflow, not the roster.** Most of these should be present in every project, run in the right order, and produce consistent output. + +--- + +## 3. The central finding + +> The persona is the interface. The artifact spec is the mechanism. The model tier is a policy decision. Today all three are conflated into a markdown profile, and only the first one is actually working. + +Three distinct claims, each with its own evidence, follow. + +### 3.1 Role-based decomposition of a single build task is worse, not merely pricier + +This was the load-bearing question, and the first answer given was wrong and had to be corrected. + +Anthropic's frequently-cited planner/implementer/tester/reviewer experiment reports **token allocation only** — no quality metric, no N, no pass rate. They assert a correctness mechanism ("each handoff degrading fidelity") but publish a cost number. **[V]** On its own it cannot settle the question, and citing it as a quality finding is over-reading. + +Independent work does measure quality: + +| Source | Method | Finding | +|---|---|---| +| arXiv 2606.00308 **[M]** | Roles ON/OFF ablation, 164 HumanEval, 1,968 paired obs, gpt-4o | Pure Analyst→Coder→Tester pipeline is **worst at 84.15%**; debugger-only configs reach **92.07%**. Persona-heavy configs produced 50–130% more complex code for zero pass@1 gain. | +| E2EDev, ACL 2026 **[M]** | 8 frameworks × 6 backbones incl. Claude Haiku 4.5 | Single-agent GPT-Engineer best on **4/6**; ChatDev falls *below* a plain single prompt on 4/6. | +| *Nature Machine Intelligence* 8(7), Jul 2026 **[M]** | 260 compute-matched configs, SWE-bench Verified + Terminal-Bench | Coordination effect ranges **+80.8% to −70.0%**. A **~45% single-agent-capability threshold** above which multi-agent is zero-to-negative; predicts the sign in **94%** of validation configs. Our tasks sit well above it. | +| CooperBench, Jan 2026 **[M]** | 600+ real OSS collaborative tasks | Agents score **~30% lower collaborating than solo**. Communication reduced merge conflicts but **did not improve success rate at all.** | + +**Mechanism.** The damage is handoff loss and Cognition's "conflicting implicit decisions" — every action silently fixes a decision the spec never named, and two agents holding different resolutions produce artifacts that are individually correct and jointly unmergeable. Full context sharing does not fix this **[P]**. This is a property of *topology*, not of the persona string. + +### 3.2 Persona strings do very little; profile *content* does the work + +Expert personas are measurably inert for correctness on frontier models: + +- Wharton *Prompting Science Report 4*, Dec 2025 **[M]** — GPQA-D + MMLU-Pro, 4,950–7,500 runs per cell, four model families: **30 expert-persona comparisons, one significant, and it is negative.** +- Zheng et al., Findings of EMNLP 2024 **[M]** — 162 personas × 2,410 MMLU questions × 9 models: no significant difference vs control; in-domain match worth **+0.4pp**. +- CodePromptEval, IEEE TSE **[M]** — 63,648 functions: persona has **no statistically significant impact on correctness**, but **does** measurably reduce code smells and complexity. + +**Read this carefully, because it is easy to misread as "drop the personas."** What it says is that "you are a senior backend engineer" buys nothing. What buys something is the *content* of the profile — Akira's "as much as needed, as little as possible" principle, a specific API-design checklist, a required output shape. The persona is a container. Today some of Code Katz's 22 profiles are full of real constraints and some are closer to character description. That ratio is the actual lever. + +And the null results are all on single-turn QA or single-function generation. **Nobody has measured persona effects on multi-turn agentic work or on judgment/creative tasks.** Extending these findings to "personas don't help Will pick a positioning angle" would be reasoning from analogy, not evidence. + +### 3.3 Where spending more genuinely buys better work + +| Intervention | Evidence | Effect | +|---|---|---| +| Cross-model review | arXiv 2607.21656, Jul 2026, 116 LiveCodeBench tasks **[M]** | Claude Opus 4.7 reviewing Codex GPT-5.5: **+18.1pp** (p=.0010) | +| Same-model self-review | same study **[M]** | Claude Opus 4.7 on own output: 3 fixes, 3 regressions, **±0, at +72% cost** | +| External oracle vs LLM critique | Stechly et al., ICLR 2025 **[M]** | GPT-4 Game of 24: 5% → **3%** with self-critique → **36–38%** with a sound external verifier | +| Cheap verification pre-pass | AgentGUI, ETH Zürich, Jul 2026 **[M]** | Completion **44%→78%** on a 4B worker, manager tokens **0.19–0.56%** of total | +| One-at-a-time human review | AgentGUI, N=8 within-participant **[M]** | **38% faster** (90s vs 145s, p=0.023), accuracy **93% vs 80%** (p=0.031), lower NASA-TLX. Small sample; authors flag limited power | + +**Conclusion:** buy quality with a *different model checking against a real oracle*, and with more thinking inside one agent. Do not buy it with more job titles. + +### 3.4 What this means for the goals + +| Goal | Verdict | +|---|---| +| 3 — consistency | **Not an agent problem.** Consistency comes from an artifact template plus a checklist plus a gate. The five existing Code Katz skills each own a file format, and that is exactly why their output is stable. The personas own no artifacts, which is exactly why theirs varies. | +| 4 — multi-lens panels | **Supported, with one correction.** This is not decomposition; it is coverage of considerations on a judgment call, which the null results do not touch. But lenses must run on **different models** — >350 models agree 60% of the time *when both are wrong*, and error correlation rises with capability **[M]**. Same model in three costumes is one opinion. | +| 5 — fun | **Legitimate and load-bearing.** Retention is the real success metric for a personal tool; an optimal tool that goes unused is worth nothing. But the fun should come from real disagreement between lenses, not a name badge on identical output. | +| 6 — the challenge | **Personas earn their cost at phase transitions and panels, not at task execution.** Inside an established context on a single task, opening Claude directly wins: `claude-team launch` means fresh context, and re-explaining the project costs more than the specialist adds. If the next iteration does not make that distinction structural, it is a tax with a nicer wrapper. | + +--- + +## 4. Platform capabilities, verified 2026-09-05 + +All **[D]**, verified against primary docs on the date above. This section is the reason the earlier plan is obsolete: most of what it proposed to build now ships natively. + +### 4.1 Dynamic workflows — the key primitive + +A dynamic workflow is a **JavaScript script that orchestrates many subagents**, written by Claude, executed by a runtime *outside the conversation context*. Only the final answer enters context. + +```javascript +export const meta = { + name: 'audit-routes', + description: 'Audit every route handler for missing auth checks', +} + +const found = await agent('List every .ts file under src/routes/.', { + schema: { type: 'object', required: ['files'], + properties: { files: { type: 'array', items: { type: 'string' } } } }, +}) + +const audits = await pipeline(found.files, file => + agent(`Audit ${file} for missing authentication checks.`, { label: file }), +) + +return audits.filter(Boolean) +``` + +Primitives available in the script body: `agent()` spawns one subagent, `pipeline()` runs one per list item, `parallel()` runs a set concurrently, `phase()` groups agents in the progress view, `log()` emits a message, and `args` is a global carrying invocation input. + +**Repeatability — this is the whole answer to goal 3.** Run `/workflows`, select a run, press `s`, and the script saves to `.claude/workflows/` (repo-shared) or `~/.claude/workflows/` (personal). It then runs as `/` in every future session. + +**Distribution.** Place a script in `workflows/` at a plugin root and it is namespaced: a plugin `acme-tools` with `meta.name: release-audit` runs as `/acme-tools:release-audit`. + +**Constraints that shape the design:** + +| Constraint | Consequence | +|---|---| +| **No mid-run user input.** Docs: *"For sign-off between stages, run each stage as its own workflow."* | **Goal 5 is a decomposition rule, not a feature.** Every stage requiring Will's sign-off must be its own workflow. | +| Up to 16 concurrent agents; 1,000 agents per run; 4,096 items per `parallel()`/`pipeline()` | Generous. Not a binding limit for this use case. | +| `Date.now()`, `Math.random()`, no-arg `new Date()` **throw** inside scripts | Enforced determinism so a relaunched run repeats the same calls. Pass timestamps via `args`. | +| No module loading; no direct filesystem or shell access from the script | The script coordinates; agents do the work. | +| Resumable **within the same session**. A failed agent reruns, and so does every agent that started after it | A mid-fan-out failure reruns completed work. Prefer smaller workflows. | +| Size guideline in `/config`: `small` <5, `medium` <15 (default), `large` <50 agents | Set per workflow expectation. | +| Warning at >25 agents or >1.5M projected tokens | Advisory only, does not pause. | + +**Prompt caching.** In a fan-out, agents sharing model + effort + agent type + tools + output schema + cwd build the same prefix; the runtime holds all but the first until the first response begins so the rest read a warm cache. Default stagger cap 5000ms. Workflow agents sit outside the main conversation's cache TTL bucket — 5 minutes by default, settable to `1h` via `subagentPromptCacheTtl`. + +**Bundled:** `/deep-research` — fans out web searches across angles, cross-checks sources, votes on claims, returns a cited report with unsurvived claims filtered out. This is a working reference implementation for the market-research workflow. + +**Authoring:** `/workflow-authoring` bundled skill (v2.1.248+) loads the script-writing reference before editing a saved script. + +### 4.2 Subagents — the persona vehicle + +`agents/*.md` frontmatter supports `name`, `description`, `tools`, `disallowedTools`, `model`, `effort`, `maxTurns`, `maxBudgetUsd`, `skills`, `memory`, `background`, and `isolation: worktree`. + +`model` accepts family aliases (`sonnet`, `opus`, `haiku`, `fable`), `inherit`, or a full ID. Only the subagent's **final message** returns to the caller; intermediate tool calls stay inside. Limits: `CLAUDE_CODE_MAX_CONCURRENT_SUBAGENTS` (20), `CLAUDE_CODE_MAX_SUBAGENTS_PER_SESSION` (200), `CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH` (3). + +**`isolation: worktree` is available to subagents and not to teammates.** This is the single most important asymmetry for parallel implementation work. + +### 4.3 Agent Teams — verified, and not the executor + +Experimental, disabled unless `CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1`. + +**What it genuinely provides:** a shared task list with claiming and dependency tracking (a pending task with unresolved dependencies cannot be claimed); direct teammate-to-teammate messaging via mailbox JSON at `~/.claude/teams/{team}/inboxes/{agent}.json`; per-teammate models; roles drawn from subagent definitions; `TaskCreated` / `TaskCompleted` / `TeammateIdle` hooks where exit code 2 blocks and returns feedback. + +**Why it is not the executor for shipped pipelines:** + +1. **Cannot be packaged or versioned.** Team config holds live runtime state — session IDs, tmux pane IDs — and the docs say do not hand-author or pre-author it. There is no project-level equivalent; `.claude/teams/teams.json` is treated as an ordinary file. A team is convened, never shipped. +2. **Cannot run unattended.** *"In non-interactive mode with the `-p` flag, including Agent SDK sessions, Claude doesn't spawn teammates."* No scheduled or headless runs, ever. +3. **No source-file protection.** File locking exists **only for task claiming**. On source files: *"Two teammates editing the same file leads to overwrites. Break the work so each teammate owns a different set of files."* No worktree option. +4. **Documented breakage on routine operations.** `/resume` and `/rewind` do not restore in-process teammates; task status lags and blocks dependents; shutdown is slow; one team per session; no nested teams; lead is fixed; teammates cannot spawn background subagents. +5. **Enabling it changes unrelated behavior.** Any subagent Claude names launches as a teammate, so teams form when not requested. + +**Where Teams is right.** The docs' own headline examples are goal 4 — *"one on UX, one on technical architecture, one playing devil's advocate"*, a three-lens parallel PR review, and adversarial competing-hypothesis debugging. For **ad-hoc exploration where the decomposition is unknown**, Teams is the better tool. For anything repeatable, Workflows win because they can be saved and shipped. + +### 4.4 Plugins, skills, hooks + +**Plugins** bundle skills, commands, agents, hooks, MCP servers, LSP servers, output styles, background monitors, and **workflows**, via `.claude-plugin/plugin.json`, distributed through a GitHub or GitLab marketplace. This is the distribution unit; it replaces `install.sh`, symlinking, and sync logic entirely. + +**Skills** — `SKILL.md` with frontmatter supporting `name`, `description`, `allowed-tools`, `model`, `disable-model-invocation`, `argument-hint`. `context: fork` runs a skill as a subagent with no conversation history; `agent:` selects the subagent type. Since Jul 2026 forked skills run in the background by default. + +**Hooks** — the enforcement layer. `TaskCreated`, `TaskCompleted`, `TeammateIdle`, `SubagentStart`, `SubagentStop`, `Stop`, `PreToolUse`/`PostToolUse`, `SessionStart`/`SessionEnd`, `PreCompact`/`PostCompact`, and — new in Aug 2026 — **`PreModelSwitch`/`PostModelSwitch`**, which can block, confirm, or annotate a model switch. `PreToolUse` can rewrite tool arguments and its `deny` holds even under bypass-permissions. + +**Output styles do not reach subagents.** They apply to the main conversation only and are fixed at session start. **Artifact consistency must therefore come from skill bodies plus hooks, not from a style.** + +**Routines** — GA on Pro/Max/Team/Enterprise. Cloud-run automations triggered by schedule, API call, or GitHub event. The path to unattended pipeline runs. + +**Advisor tool** — experimental, Anthropic API only. Lets a cheaper executor consult a stronger model at decision points with full conversation context. **[V]** +2.7pp SWE-bench Multilingual at −11.9% cost. Relevant to the routing goal: it escalates *without* a model switch, so it sidesteps the context-rebuild cost entirely. + +### 4.5 Model lineup — the tier map is stale + +| Model | ID | In/Out $/MTok | Cache read | Context | Position | +|---|---|---|---|---|---| +| Fable 5.1 | `claude-fable-5-1` | $10 / $50 | **0.025×** | 1M | Hours-long agent sessions, multistep deep research | +| Opus 5 | `claude-opus-5` | $5 / $25 | 0.1× | 1M | Complex agentic coding, systems engineering, vision-heavy | +| Sonnet 5 | `claude-sonnet-5` | $2 / $10 | 0.1× | 1M | Everyday coding, data analysis, content creation | +| Haiku 4.5 | `claude-haiku-4-5-20251001` | $1 / $5 | 0.1× | 200K | Real-time, high-volume, sub-agent tasks | + +**Changed in the last eight weeks:** Opus 5 launched Jul 24 as the coding flagship at half Fable's price. Fable 5.1 launched Sep 1 with a **4× cache-read price cut**. Sonnet 5's $2/$10 was made permanent Sep 1 — the scheduled increase to $3/$15 was cancelled. Opus 4.1 retired Aug 5. Sonnet 4.5's retirement window opens **Sep 29, 2026**. + +`tiers.conf` currently references `claude-fable-5` and `claude-opus-4-8`. Both are legacy. **Opus 5 should absorb most of what currently routes to Fable.** + +--- + +## 5. Proposal: the `code-katz` plugin + +### 5.1 Shape + +Retire the bash CLI. Ship one installable plugin containing four component types: + +``` +code-katz/ +├── .claude-plugin/plugin.json +├── workflows/ # the product: named, ordered, repeatable pipelines +│ ├── opportunity.js ├── prd.js ├── brand-guide.js +│ ├── roadmap.js ├── feature.js ├── bugfix.js +│ ├── gtm.js ├── market-research.js +│ └── panel.js +├── agents/ # the roster: 22 personas as subagent definitions +│ ├── akira.md ├── sasha.md ├── river.md ├── toni.md ├── kai.md … +├── skills/ # the artifact contracts (templates + checklists) +│ ├── prd/SKILL.md ├── brand-guide/SKILL.md ├── gtm/SKILL.md … +└── hooks/ # the gates + └── hooks.json # TaskCompleted / Stop → artifact validators +``` + +The five existing skill repos (`plans`, `todo`, `roadmap`, `devlog`, `publish`) fold in as the artifact contracts they already are. + +### 5.2 The four layers, and what each is for + +| Layer | Primitive | Owns | Why here | +|---|---|---|---| +| **Workflow** | `workflows/*.js` | The order of stages | Repeatable, versioned, shippable, runs outside context. Goal 3. | +| **Persona** | `agents/*.md` | Voice, domain constraints, model tier | Fun and intent expression (goals 1, 5); model policy (goal 2) | +| **Artifact** | `skills/*/SKILL.md` | Output template + checklist | The actual mechanism of consistency (§3.2) | +| **Gate** | `hooks/hooks.json` | Rejection of malformed output | Enforcement; personas cannot be trusted to self-certify | + +The design intent: **a persona without an artifact contract is decoration.** Every workflow stage names an owning persona *and* the artifact skill it must produce into. + +### 5.3 Workflow catalog + +Each is one workflow. Each stage boundary that needs Will's sign-off is a workflow boundary, because workflows accept no mid-run input (§4.1). + +| Command | Purpose | Owner persona | Artifact | +|---|---|---|---| +| `/ck:opportunity` | Explore the opportunity before committing | River | `opportunity-brief.md` | +| `/ck:market-research` | Competitive and market scan | River + Toni | `market-research.md` | +| `/ck:prd` | Product requirements | River | `PRD.md` | +| `/ck:brand-guide` | Brand and visual system | Iris + Kai | `brand/` asset set + `brand-guide.md` | +| `/ck:roadmap` | Plan or re-plan the next phase | River + Quinn | `ROADMAP.md` (existing skill) | +| `/ck:feature` | Implement a roadmap item end to end | per slice | code + tests + docs | +| `/ck:bugfix` | Diagnose and fix | Robin → owner | fix + regression test | +| `/ck:gtm` | Go-to-market plan | Toni | `gtm.md` | +| `/ck:panel` | Multi-lens decision input | 3 lenses | decision memo | + +The natural project order is `opportunity → market-research → prd → brand-guide → roadmap → feature*`, with `panel` callable at any point. **Recommendation: do not hard-wire the order in code.** Ship it as documented convention plus a `/ck:next` helper that reads which artifacts exist and suggests the next stage. Hard sequencing would fight exploratory use, which is goal 1. + +### 5.4 `/ck:feature` — the one with real parallelism + +The only workflow where the build-topology research binds. Structure: + +1. **Plan phase** (Opus 5, one agent) — decompose the feature into **vertical slices**, each owning a feature plus its tests plus its docs. Emit an interface contract naming every decision two slices could otherwise resolve differently: exact signatures, the enumerated error set, canonical entity names, single file ownership. Freeze it. +2. **Build phase** — `parallel()` over slices, one persona each, each subagent declared `isolation: worktree`. One writer per slice. No mid-feature handoffs. +3. **Verify phase** — per slice, a gate agent on a **different persona and a different model tier** than the writer, whose job is to *run the oracle*, not to opine. Carries the anti-early-victory instruction verbatim: *"You MUST run the complete test suite before marking as passed."* +4. **Merge** — sequential, one at a time, base suite as the gate. + +Parallelize only when the interface contract exists. Absent it, run sequential — §3.1 is unambiguous that unshared implicit decisions are what break parallel builds. + +### 5.5 `/ck:panel` — goal 4 + +The one piece with no native primitive, and the one Will will feel most day to day. + +- Three lenses, invoked on one question: **product** (River), **marketing** (Toni), **UX** (Kai). +- **Each lens runs on a different model.** Not negotiable — same model in three costumes is one opinion, and error correlation rises with capability **[M]**. +- Each lens must return, in a fixed schema: its recommendation, its **strongest argument against its own recommendation**, and **the specific condition that would make it say no**. Forcing the disagreement is the point; three approvals is a failed panel. +- A synthesis agent surfaces *where the lenses disagree* and does not resolve it. The decision is Will's. + +The workflow runtime explicitly supports this shape: *"it can have independent agents adversarially review each other's findings before they're reported, or draft a plan from several angles and weigh them against each other."* + +### 5.6 Proposed tier re-base + +Simplify from three tiers across 22 personas to a policy with four positions: + +| Tier | Model | Assign to | +|---|---|---| +| Deep research | Fable 5.1 | `/ck:market-research`, `/ck:opportunity` deep passes only | +| Judgment | **Opus 5** | Akira, River, Toni, Kai, Iris, Morgan, Sage, Jordan, Quinn, Casey — most of what is currently Fable **or** Opus 4.8 | +| Execution | Sonnet 5 | Sasha, Alex, Robin, Piper, and all high-volume implementation | +| Classification | Haiku 4.5 | Routing, status rollups, summarization, `/ck:next` | + +Opus 5 becomes the default judgment tier. Fable 5.1 is reserved for genuinely long-horizon research, where its 4× cache-read discount also does the most good. + +**Keep tiers.conf as declared intent** and treat the resolved model as separate, recorded per run. Two additions: + +- **Fallback chain** (`fable-5-1 → opus-5 → sonnet-5`) with quota/429 detection, using the new `PreModelSwitch` hook as the enforcement point. This fixes the observed failure where an Akira delegation pinned to Fable died on quota exhaustion and had to be rerun by hand. +- **Prefer the Advisor tool over a model switch** where available. Escalating within a task avoids the context-rebuild cost entirely, which is the correct answer to the "switching is not free" objection. + +### 5.7 Artifact contracts + +For each artifact, the skill defines: the section structure, the required fields, the file path convention, and a **machine-checkable validator**. The hook (`TaskCompleted` or `Stop`, exit code 2) rejects malformed output and returns the specific failure. + +This is where goal 3 is actually satisfied. "There is a specific way I like a branding guide" becomes a template plus a checklist plus a validator — not a personality trait of Iris. + +--- + +## 6. What we are deliberately not building + +| Not building | Because | +|---|---| +| A bash orchestrator | Dynamic workflows are the orchestrator, and they are saveable and shippable | +| A custom task graph, lock protocol, or state file | Workflow scripts hold state in script variables; the runtime handles resumption | +| An Agent Teams executor for shipped pipelines | §4.3 — unpackageable, interactive-only, no source-file protection, documented breakage | +| A model picker | The thesis is that the user expresses intent and policy resolves the model | +| Role pipelines for building a single feature | §3.1 — measured 8–40pp worse at 3–10× the tokens | +| A bandit router | No outcome data yet. A bandit with no data is a random number generator. Revisit after telemetry exists | +| Free-form inter-agent chat | CooperBench: communication reduced conflicts, did not improve success **[M]** | +| A batch review mode | §3.3 — one at a time is 38% faster and 13pp more accurate | + +--- + +## 7. Honest assessment against goal 6 + +**Where this beats opening Claude directly:** + +- Phase transitions. Starting a PRD from a fresh context with a template and a checklist is genuinely better than continuing a conversation that has drifted. +- Repeated multi-stage jobs. `/ck:prd` producing the same shape every time, in every project, is a real gain over remembering how you did it last time. +- Panels. Three lenses on different models surfaces considerations one session will not. +- Fan-out work. Auditing 40 route handlers is what workflows are for. + +**Where it does not, and should not be used:** + +- Any single task inside a context you are already deep in. Fresh context costs more than the specialist adds. +- Small changes. The coordination overhead exceeds the benefit. +- Work where the decomposition is unknown. Use a team, or just work directly. + +**The specific risk to watch:** 22 personas is likely 15 more than are used. Unused personas are maintenance surface and choice paralysis. Recommendation for the PRD: instrument which personas and workflows actually get invoked, and prune on evidence after 90 days. + +--- + +## 8. Open questions for the PRD + +1. **Retire or coexist?** Does `claude-team-cli` get archived once the plugin ships, or does the CLI remain for the `/akira`-in-current-session route? The three-route model (current context / fresh context / separate session) is good and should survive in some form. +2. **Workflow granularity vs sign-off.** Because workflows take no mid-run input, every sign-off point is a workflow boundary. Is `/ck:prd` one workflow, or `prd-draft` → review → `prd-finalize`? This is the highest-leverage open design question. +3. **Where do artifacts live?** Repo-relative (`docs/`, `brand/`) or a `.code-katz/` directory? Committed, presumably — confirm. +4. **Which personas survive?** A proposed cut list based on 90-day usage should precede the port, not follow it. +5. **Panel model assignment.** Which three models for the three lenses? Constrained to the Claude family, decorrelation is imperfect — all share one training pipeline. Worth stating that limitation explicitly. +6. **`/ck:feature` scope.** Full end-to-end including marketing copy, or code-only with content as a separate workflow? +7. **Routines integration.** Which workflows, if any, should run scheduled or on GitHub events? +8. **Verification for non-code artifacts.** A test suite is a real oracle. What is the oracle for a brand guide? Probably a structural validator plus Will's review — which means non-code stages lean harder on the human gate, and should be sized accordingly. + +--- + +## 9. Relationship to the previous plan + +`claude-conductor/plans/2026-09-04-agent-coordination-engine.md` proposed extending claude-conductor with a task graph, a spawn wrapper, a routing module, and a coordination UI, executing via Agent Teams. **That plan is substantially obsolete.** Dynamic workflows, packageable in a plugin, provide the orchestration, the repeatability, the distribution, and the resumption it proposed to build. Agent Teams is the wrong executor for the reasons in §4.3. + +Two things from it survive and should carry forward: + +- **The conductor bug findings.** `update_session_field` and `insert_active_row` both write a fixed `.tmp` then `mv`, with no lock — two concurrent writers destroy each other. And `dashboard/watcher.js:134` filters empty cells while the four awk parsers are positional, so a row with an empty Notes field is already parsed differently by the two. Both are real and worth fixing regardless of this proposal. +- **The coordination UI question.** Workflows have a built-in progress view (`/workflows` — phases, agent counts, token totals, elapsed time, drill-down to any agent's prompt and result). **Recommendation: use it and do not build a UI until it proves insufficient.** Goal 6 applies to the UI as much as to the personas. + +--- + +## 10. Sources + +**Platform documentation** — all verified 2026-09-05: +[Agent teams](https://code.claude.com/docs/en/agent-teams) · [Dynamic workflows](https://code.claude.com/docs/en/workflows) · [Subagents](https://code.claude.com/docs/en/sub-agents) · [Skills](https://code.claude.com/docs/en/skills) · [Plugins reference](https://code.claude.com/docs/en/plugins-reference) · [Hooks](https://code.claude.com/docs/en/hooks) · [Routines](https://code.claude.com/docs/en/routines) · [Advisor tool](https://code.claude.com/docs/en/advisor) · [Prompt caching](https://code.claude.com/docs/en/prompt-caching) · [Pricing](https://platform.claude.com/docs/en/about-claude/pricing) · [Model deprecations](https://platform.claude.com/docs/en/about-claude/model-deprecations) + +**Measured research:** +[Capable language models can outgrow the benefits of collaboration](https://www.nature.com/articles/s42256-026-01268-y), *Nature Machine Intelligence* 8(7), Jul 2026 · [How Generation Architecture Shapes Code Complexity](https://arxiv.org/abs/2606.00308) · [E2EDev](https://arxiv.org/abs/2510.14509), ACL 2026 · [CooperBench](https://cooperbench.com/), Jan 2026 · [Why Do Multi-Agent LLM Systems Fail? (MAST)](https://arxiv.org/abs/2503.13657) · [AgentGUI](https://arxiv.org/html/2607.26300v1), ETH Zürich, Jul 2026 · [Cross-Model LLM Code Review](https://arxiv.org/abs/2607.21656), Jul 2026 · [Expert Personas Don't Improve Factual Accuracy](https://arxiv.org/abs/2512.05858), Wharton, Dec 2025 · [Personas in System Prompts Do Not Improve Performance](https://arxiv.org/abs/2311.10054), EMNLP 2024 · [Impact of Prompt Programming on Function-Level Code Generation](https://arxiv.org/abs/2412.20545), IEEE TSE · [Stechly et al.](https://arxiv.org/abs/2402.08115), ICLR 2025 · [Great Models Think Alike](https://arxiv.org/abs/2502.04313), ICML 2025 + +**Position pieces:** +[Building multi-agent systems: When and how to use them](https://claude.com/blog/building-multi-agent-systems-when-and-how-to-use-them), Anthropic, Jan 2026 · [How we built our multi-agent research system](https://www.anthropic.com/engineering/multi-agent-research-system), Anthropic, Jun 2025 · [Don't Build Multi-Agents](https://cognition.com/blog/dont-build-multi-agents), Cognition, Jun 2025 · [The model picker is a dead end](https://lovable.dev/blog/the-model-picker-is-a-dead-end), Lovable + +**Prior art reviewed:** [ruvnet/ruflo](https://github.com/ruvnet/ruflo) — renamed from claude-flow; task DAG and complexity-bucketed Thompson-bandit router are worth studying, but its own commissioned audit found headline performance multipliers unsubstantiated and one fabricated at runtime. Do not copy its template decomposition or its executor-less agent pool. diff --git a/plans/2026-09-05-ck-plugin-prd-phase-1.md b/plans/2026-09-05-ck-plugin-prd-phase-1.md new file mode 100644 index 0000000..e025c41 --- /dev/null +++ b/plans/2026-09-05-ck-plugin-prd-phase-1.md @@ -0,0 +1,1417 @@ +# `ck` Plugin, Phase One: Product Requirements Document + +> **Status:** PRD, ready for build +> **Date:** 2026-09-05 +> **Author:** Fable (with Will Curran) +> **Derives from:** [`plans/2026-09-05-agent-workflows-research-and-proposal.md`](2026-09-05-agent-workflows-research-and-proposal.md) (the research proposal) +> **Supersedes:** the marketplace-retired decision in `claude-team-cli` (2026-07-31), for `ck` only; see §3.1 +> **Scope:** phase one only: plugin skeleton, `/ck:prd` and `/ck:panel` end to end, 21 personas as subagents on the §5.6 tiers. Everything else is in §10 + +--- + +## 0. How to read this document + +### 0.1 Grading + +Every claim carries the proposal's grade, plus one more: + +| Grade | Meaning | +|---|---| +| **[D]** | Product documentation, verified against the primary source on 2026-09-05. The URL is in Appendix G | +| **[M]** | Measured, independent, method stated (carried over from the proposal) | +| **[V]** | Vendor self-measured | +| **[R]** | The family's own record: a devlog entry, roadmap revision, or test in a code-katz repo | +| **[P]** | Practitioner assertion or judgment call. Open to challenge; the rationale is stated | + +### 0.2 What this document is + +The proposal is a research summary with a proposed shape. This is the specification for the first slice of that shape: what ships, what each piece must do, how it is tested, and what is deliberately left out. It contains acceptance criteria, schemas, and the full text of the two workflow scripts and two skills, as appendices. + +### 0.3 The three answers up front + +1. **It is a plugin.** Claude Code is the runtime for subagents, workflow scripts, and skills; nothing else can run them. No UI ships in phase one. The catalog view is a phase-two command that renders from files. A workbench is phase three, only if the files-as-workbench proves insufficient, and never a hosted app with its own store of definitions. See §4.7. +2. **The skill owns the gates; each span between gates is one workflow.** A sign-off point is not a workflow. It is a gate, and a gate can only live in the main session, because `AskUserQuestion` is removed from every subagent and a workflow cannot pause for input. See §4.2. +3. **`ck` coexists with `claude-team-cli`.** Phase one is additive. The three handoff routes survive: switch this session (team-cli), delegate one task (`ck:`), open a separate session (team-cli). Retirement is revisited at 90 days with usage data. See §8.6. + +--- + +## 1. Summary + +`ck` is a Claude Code plugin. Phase one ships: + +| Component | Count | What it is | +|---|---|---| +| Persona subagents | 21 | `agents/.md`, generated from `claude-team-cli` profiles, registered as `ck:`, model from the §5.6 tiers | +| Workflows | 2 | `/ck:panel` (three lenses on different models, one decision memo) and `/ck:prd-draft` (River drafts, a validator checks, the panel challenges, River synthesizes) | +| Skills | 2 | `/ck:prd` (the interactive entry point that owns both gates) and `prd-artifact` (the PRD contract: template, required fields, checklist) | +| Hooks | 1 | `SubagentStart` on `^ck:` appending one line per persona invocation to a usage log, so the 90-day prune has data | +| Tests | 1 suite | Manifest, drift against the pinned upstream, script lint, end-to-end drill | + +Everything in the proposal's §5.3 catalog beyond these two commands, the hook-based gates, the model fallback chain, the Advisor tool, Routines, folding in the five artifact skills, persona switch skills, `/ck:map`, and any workbench are deferred with reasons in §10. + +--- + +## 2. Problem, user, outcome + +### 2.1 Problem + +The unit of Will's work is the workflow, not the roster (proposal §2.1). Today the personas exist only as session takeovers and delegation subagents. They own no artifacts, so their output varies run to run (proposal §3.4). Multi-lens input on a decision requires opening three sessions by hand, and the three lenses run on one model, which is one opinion in three costumes (proposal §3.4, [M] error correlation rises with capability). Nothing is repeatable across projects, and nothing is measured, so the 22-persona question ("likely 15 more than are used", proposal §7) cannot be answered. + +### 2.2 User + +Customer zero: Will and his wife, building and maintaining real products (proposal §2, goal 3). The core requirement is team members that behave consistently, starting a product from an opportunity exploration, then a PRD, then a brand guide. Phase one covers the PRD step and the decision panel that every step uses. + +### 2.3 Success metrics + +| Metric | Target | How measured | +|---|---|---| +| Both commands run end to end on a real project | Before the phase-one release is tagged | The end-to-end drill in §9, run by hand on one of Will's projects, with the files listed in §6.9 and §7.10 present | +| Retention (proposal §3.4: the real metric for a personal tool) | At 30 days after install, at least one `/ck:prd` or `/ck:panel` run per week of active building | `${CLAUDE_PLUGIN_DATA}/usage.jsonl`, §5.5 | +| The panel disagrees | In more than half of panel runs, at least one lens recommends differently from the others, or at least one condition-to-say-no is unmet by the material | `panelFailedToDisagree` in each `decision-memo.md` | +| Leading indicator | Usage log entries in the first week | `usage.jsonl` | + +A panel that always agrees is a failed panel (proposal §5.5). If the disagreement rate is low, the lenses or the question template are wrong, not the users. + +### 2.4 Non-goals for phase one + +- No workflow other than `panel` and `prd-draft`. The catalog in proposal §5.3 is phase two. +- No UI, dashboard, map, or workbench. `/workflows` is the run view (proposal §9, [D]). +- No retirement of `claude-team-cli`, no persona switch skills (`/ck:river`), no CLI in `bin/`. +- No hook-enforced artifact gates, no model fallback chain, no Advisor tool, no Routines. +- No persona pruning. All 21 port; the instrument ships; the cut list follows the data. +- No changes to the persona text. Profiles stay upstream; `ck` transforms them mechanically. + +--- + +## 3. Decisions + +### 3.1 Decisions on record that this PRD supersedes or honors + +| Date | Decision and where it is recorded | What `ck` does | Grade | +|---|---|---|---| +| 2026-07-29 | No second source of persona truth. Local overrides and team-scoped profiles retired (team-cli `ROADMAP.md` revision history, `CONTRIBUTING.md`) | Honored. `ck/agents/` is generated from a byte-for-byte vendored copy of team-cli `profiles/` at a pinned commit, committed, and drift-tested. Editing a persona still means a PR or a fork upstream | [R] | +| 2026-07-31 | Marketplace publishing retired for team-cli, not deferred: `/akira` would become `/claude-team:akira`, and a plugin cannot put `claude-team` in the user's shell, so `launch` and `session` could not ship (team-cli `ROADMAP.md`, `DEVLOG.md`) | **Superseded for `ck` only.** `ck` accepts namespacing because the prefix is two characters, because workflows and subagents need no shell CLI, and because the things the 07-31 decision protected (`/akira`, `launch`, `session`, the coordinator) stay exactly where they are. team-cli's own decision stands | [R], [P] | +| 2026-07-04 | Conductor: keep and harden the local Node dashboard; JSONL parsing fenced with fixtures; plugin packaging (conductor `DEVLOG.md`) | Honored as precedent for any future viewer: local server plus browser, reading files on disk | [R] | +| 2026-07-25 | Conductor research branch: "drop Tauri, target local server + browser" | Honored. A desktop app is not on the table | [R] | +| proposal §9 | "Use `/workflows` and do not build a UI until it proves insufficient" | Honored in phase one. §4.7 says what would count as insufficient | [P] | + +### 3.2 Decisions made in this PRD (the proposal's §8, resolved) + +| # | Question (proposal §8) | Decision | Grade | +|---|---|---|---| +| 1 | Retire or coexist? | **Coexist.** `ck` is additive. team-cli keeps switch commands, coordinator, `launch`, `session`, `install.sh`. The three routes survive (§8.6). Revisit at 90 days with `usage.jsonl` | [P] | +| 2 | Workflow granularity vs sign-off | **The skill owns the gates; each span between gates that needs fan-out or verification is one workflow; a single-agent span runs inline via the Agent tool.** `/ck:prd` is a skill: Gate 0 → `prd-draft` workflow → Gate 1 → inline finalize. `/ck:panel` is a pure workflow: inputs are args, output is a memo, no gate. Full rule and the failure modes it must survive: §4.2, §4.3 | [D]-backed | +| 3 | Where artifacts live | **Final artifacts follow the family's convention per artifact type, committed.** A PRD defaults to `plans/--prd.md`, the location the plans skill already indexes and where this PRD itself lives; overridable at Gate 0. Run intermediates live under `.ck/runs//`, excluded via `.git/info/exclude`; a memo worth keeping is promoted with `/devlog`. The plugin never edits the user's `.gitignore` | [P] | +| 4 | Which personas survive? | **All 21 port now; prune at 90 days on evidence.** The port is generated, so carrying 21 costs nothing. No usage data exists, so a cut list today is a guess. The instrument ships in phase one (§5.5). This contradicts proposal §8.4 and agrees with proposal §7 | [P] | +| 5 | Panel model assignment | **River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5 by default,** overridable per run. `panel.js` is the one script allowed to set `model` on a persona agent, because per-invocation model beats frontmatter [D] and decorrelation is the point. The memo header states the limitation: one training pipeline, partial decorrelation. A lens that dies on an API error returns `null`; the memo runs on the survivors and says so | [P] | +| 6 | `/ck:feature` scope | **Deferred to phase two.** Both options recorded in §10.2 | deferred | +| 7 | Routines | **Deferred.** One constraint carried into phase one: `panel` must be runnable headless (no gate inside it), which it is. `prd` cannot be, by construction | deferred | +| 8 | Oracle for non-code artifacts | **A structural validator plus the human gate.** `skills/prd-artifact/SKILL.md` carries the checklist; a neutral Haiku agent checks the draft against it inside the workflow, with at most two revise loops; Gate 1 is the human oracle. Hook-based gates are a phase-two spike (§3.3 item 7) | [P] | + +### 3.3 Corrections to the proposal + +Each item names the proposal section, what is wrong, and what this PRD does instead. + +1. **§5.1, plugin name.** The tree is rooted at `code-katz/` and every command is `/ck:...`. The command prefix is the plugin's `name` and cannot be opted out of [D]. The plugin is named `ck`. The repo is `code-katz/ck`. +2. **§5.1 vs §8.1, retire or coexist.** §5.1 says "retire the bash CLI"; §8.1 asks whether to. Resolved: coexist (§3.2 item 1). A plugin `bin/` directory is on the Bash tool's PATH [D], so a `ck` CLI for Claude's use is possible later; it still cannot reach the user's shell, which is what `launch` needs. +3. **§3.2, §5.1, §5.6, §7, roster count.** The proposal says 22. `profiles/` holds 21 personas and the 2026-09-04 devlog says twenty-one [R]. +4. **§5.6, unassigned personas.** The tier table assigns 14 of 21. Reiner, Cornelius, Ernie, Rez, Tracy, Travolta, and Noon are unassigned. All seven are judgment or craft seats, so they go to Judgment (Opus 5); Reiner moves from Fable, the other six from Opus 4.8. Piper is Execution as listed. Result: 17 on Opus 5, 4 on Sonnet 5, none on Fable. Fable 5.1 and Haiku 4.5 are workflow-stage tiers, not persona tiers. §5.3 has the table. +5. **§5.5 vs §5.6, the panel contradiction.** "Each lens runs on a different model. Not negotiable" and "River, Toni, Kai: Opus 5" cannot both hold through frontmatter alone. Resolved by a per-invocation override in `panel.js` only (§3.2 item 5). Consequence for the PRD: tiers are defaults; the document says which script may override them (one) and which may not (every other). +6. **§5.6, where the tier re-base happens.** `tiers.conf` in team-cli names itself the single source of truth [R]. The re-base is a prerequisite PR to team-cli; `ck`'s generator copies the value verbatim. Recommendation for that PR: aliases (`opus`, `sonnet`) rather than full IDs, so a tier tracks the current generation and the resolved model is recorded per run by `/workflows` [D]. [P] +7. **§5.2 and §5.7, the gate mechanism.** "`TaskCompleted` or `Stop`, exit code 2, rejects malformed output." `Stop` is the main conversation's event; the subagent event is `SubagentStop`, whose exit-2 feedback path to the agent is not documented [D as read]; plugin agents ignore per-agent `hooks:` frontmatter [D]. Phase one validates inside the workflow: schema-forced output, which the harness retries on mismatch [D], plus a validator agent against the artifact checklist. Hook gates are a phase-two spike with a stated test. +8. **§5.6, fallback chain via `PreModelSwitch`.** The hook fires "before Claude Code applies a model switch that you or a client requested" [D]. Nothing says it covers subagent model selection or an API quota error. Phase-one resilience is null-tolerant scripts: a lens or stage that fails returns `null`, and the script continues and logs it. A real fallback is a phase-two spike. +9. **§8.4 vs §7.** "A cut list should precede the port" against "instrument and prune after 90 days." No data exists. Port everything and instrument (§3.2 item 4). +10. **§6, "no state file".** Script variables die with the run. A gate between two workflows requires the artifact on disk. `.ck/runs/` is the artifact directory, not a coordination state file in the conductor sense; the proposal's argument against a custom task graph and lock protocol still holds. +11. **§4.1 vs §3.4, what buys consistency.** §4.1 says repeatability "is the whole answer to goal 3"; §3.4 says consistency comes from the artifact contract. §3.4 is right. Workflows give the same process; artifact skills give the same shape. Phase one's most important file is `skills/prd-artifact/SKILL.md`, not `prd-draft.js`. +12. **§4.2, `maxBudgetUsd`.** Not in the subagent frontmatter table read today [D]. Not relied on. +13. **§9, the superseded plan.** `claude-conductor/plans/2026-09-04-agent-coordination-engine.md` is on no branch of that repo. Commit it, so the supersession is traceable. +14. **§5.2, the persona layer.** "Voice, domain constraints, model tier" omits that a subagent has no user to ask. Every persona's `## Required Interactive Behaviors` is written as questions to the user; unrewritten, it is dead text or a stall. §5.4 has the transform. +15. **§4.1, fan-out cache economics.** The prompt-cache sharing described there applies to agents matching on model, effort, agent type, tools, schema, and cwd [D]. A persona panel is three agent types on three models and shares nothing. The cost model in Appendix F assumes no sharing. + +What the proposal gets right and this PRD keeps unchanged: §3 (topology, not persona strings, is the lever; buy quality with a different model and a real oracle), §4.3 (Agent Teams is not the executor), §5.2 (the four layers), §5.5 (forced self-disagreement; three approvals is a failed panel), §6 (the not-building list), §7 (the honest assessment), §9 (the UI stance). + +--- + +## 4. Architecture + +### 4.1 The four layers and their phase-one instances + +| Layer | Primitive | Owns | Phase-one instance | +|---|---|---|---| +| Workflow | `workflows/*.js` | The order of stages, outside the conversation | `panel.js`, `prd-draft.js` | +| Persona | `agents/*.md` | Voice, domain constraints, default model tier | 21 generated files, `ck:` | +| Artifact | `skills/*/SKILL.md` | Output template, required fields, checklist | `prd-artifact` | +| Gate | The skill in the main session | Sign-off, using `AskUserQuestion`; plus schema-forced output and a validator agent inside the workflow | `prd` (Gate 0, Gate 1); `panel.js` and `prd-draft.js` schemas | + +The proposal put the gate layer in `hooks/hooks.json`. Phase one puts human gates in the skill and machine gates in the scripts (§3.3 item 7). The hook that does ship is instrumentation, not enforcement. + +### 4.2 The gate rule + +The docs: "No mid-run user input. Only agent permission prompts can pause a run. For sign-off between stages, run each stage as its own workflow." [D] And: `AskUserQuestion` is removed from every subagent [D]. + +Therefore: + +1. A sign-off is a **gate**. A gate runs in the main session, inside a skill, with `AskUserQuestion`. +2. The span between two gates is a **workflow** when it needs fan-out, structured output, or resume. A span that is one agent runs inline through the Agent tool; a workflow for one agent buys nothing. +3. A workflow never contains a decision point. A skill never fans out by hand. +4. A skill or slash command whose instructions say to call Workflow is explicit opt-in [D]; no `ultracode` keyword, no "use a workflow" phrase is needed. + +Rejected alternatives: one workflow per persona action (the skill would orchestrate fan-out itself, which is what Workflow exists to do); one workflow per command (impossible with a gate in the middle); no workflows (loses resume, schema validation, the progress view, and the "don't ask again for ``" consent that plugin workflows get by name [D]). + +What would make the rule wrong: subagents regaining `AskUserQuestion`, or workflows gaining a pause primitive. Neither is on the record. + +### 4.3 Run directory contract + +Every run has an id and a directory. The skill mints both; workflows receive them in `args`; agents do all reading and writing under the directory (the script has no filesystem access [D]). + +``` +.ck/runs// +├── run.json { runId, createdAt, status, outputPath, lenses, harnessRunId, scriptPath } +├── brief.md Gate 0 output, appended answer by answer +├── draft-v0.md River's first draft (prd-draft) +├── prd-draft.md River's synthesis after the panel (prd-draft) +├── panel/.json one file per lens +├── decision-memo.md the panel's synthesis +└── gate-1.md Gate 1 answers and edits (prd) +``` + +Rules, each of which closes a failure mode found in review: + +| Rule | Failure it closes | +|---|---| +| `run-id` is `-`, minted by the skill with `date -u`; workflows receive `timestamp` in `args` because `Date.now()` throws in scripts [D] | Non-deterministic scripts break resume | +| `runDir` is passed **absolute** in `args` | Subagents inherit the session cwd; a user in a subdirectory would get `.ck/` in the wrong place | +| The skill appends each Gate 0 answer to `brief.md` as it is given, and on entry offers to resume any run with a `brief.md` but no `prd-draft.md` | Compaction in the middle of Three Whys loses the answers | +| The skill writes the Workflow tool's own run id into `run.json` as `harnessRunId` before it waits | Without it, a compacted or `--resume`d session cannot `resumeFromRunId` and re-runs the workflow at full cost | +| The skill adds `.ck/` to `.git/info/exclude` on first use, never to `.gitignore` | team-cli's `session done` refuses untracked files [R, tests/run.sh]; a run inside a session worktree would block closing it | +| Every agent that writes returns the path it wrote, in its schema | The script cannot check the filesystem; the next stage needs the path | +| Final artifacts are written outside `.ck/` at the path chosen at Gate 0 | Intermediates stay excluded; the deliverable is committed | + +### 4.4 Naming + +- Plugin `name`: `ck`. Everything is `/ck:` or `ck:` [D]. +- Skills: `prd` (user-invocable, `disable-model-invocation: true`), `prd-artifact` (not user-invocable; read by agents and loadable by Claude when writing any PRD). +- Workflows: `panel`, `prd-draft`. A plugin workflow is itself a slash command [D], so `/ck:panel` and `/ck:prd-draft` both appear in autocomplete. `prd-draft` is safe to run directly if a `brief.md` exists; the skill is the supported path. +- No name is shared between a skill and a workflow, because both occupy `/ck:`. +- Agents: `river`, `akira`, ... in frontmatter (no colon allowed [D]); registered as `ck:river`, referenced as `agentType: 'ck:river'` in scripts and `subagent_type: "ck:river"` from the Agent tool. + +### 4.5 Model policy + +| Agent kind | Where the model comes from | Who may override | +|---|---|---| +| Persona agent (`agentType: 'ck:'`) | Frontmatter `model:` from the §5.6 tiers, via `tiers.conf` upstream | `panel.js` only, for lens decorrelation | +| Neutral utility agent (no `agentType`): validator, synthesis | The script sets `model` explicitly for the validator (Haiku 4.5, classification tier); synthesis inherits the session model | The script | +| The main session (gates, finalize) | The user's session model | The user | + +Precedence is per-invocation → frontmatter → `CLAUDE_CODE_SUBAGENT_MODEL` → session [D]. `/workflows` shows the requested and any substituted model per agent [D]; that is the "resolved model recorded per run" the proposal asks for, at no cost. + +### 4.6 What phase one deliberately does not build + +Everything in proposal §6, plus: hook-enforced gates, a fallback chain, the Advisor tool, Routines, `/ck:next`, persona switch skills, a `bin/` CLI, any UI. Reasons are in §10. + +### 4.7 Plugin, web app, wrapper, or dashboard + +Will's question, answered with a recommendation: + +1. **It is a plugin.** Subagents, workflow scripts, and skills execute only inside Claude Code. A web app cannot run them. The plugin is the product; nothing wraps it. +2. **Single source of truth rules out a hosted app with its own store.** The family retired local persona overrides twice on exactly this ground [R]. A web app that stores persona or workflow definitions recreates the problem. Anything that edits must edit the same files, and the change must flow through git, the generator, and the tests. +3. **`/workflows` is the run view** [D]: phases, agent counts, tokens, elapsed time, drill-down to any agent's prompt and result. What it does not show is the static catalog (which workflows exist; which personas, tiers, and models each stage uses) and the per-run interaction graph (which lens asked which lens what). +4. **The catalog is derivable from files.** Every `ck` workflow declares `phases` and a `personas` list in `meta` (§6.5, §7.5). `meta` is a pure literal [D], so it names the default roster, not a run-time choice. Phase two `/ck:map` emits a Mermaid graph (workflow → phase → persona → tier → model) with one agent and no infrastructure; `/ck:map --run ` draws the per-run graph from `panel/*.json`. GitHub renders Mermaid in Markdown. +5. **If a workbench is ever built**, decide its two halves separately. The *viewer* half reads and never owns; it could be a local page or a published Artifact generated from the plugin's files. The *editor* half must be local, because only a local process can run `generate-agents.sh` and `tests/run.sh` before a commit. The conductor precedent applies: local server plus browser, Tauri dropped [R], Python by preference. Build it only when the files-as-workbench is shown insufficient, which means a specific edit Will could not make in a text editor plus `bump-upstream.sh`. + +--- + +## 5. Personas as subagents + +### 5.1 Source of truth and vendoring + +`claude-team-cli/profiles/.md` and `profiles/tiers.conf` remain the only place persona text and tiers are edited [R]. `ck` vendors them: + +- `upstream/profiles/*.md` and `upstream/tiers.conf`: byte-for-byte copies at a pinned commit. +- `scripts/upstream.lock`: `repo=https://github.com/code-katz/claude-team-cli` and `commit=<40-hex>`. Today's `main` is `b4b211fbf4ec6f4d365a550b55e9981610ed7dda`. +- `scripts/bump-upstream.sh `: fetches the commit, replaces `upstream/`, regenerates `agents/`, updates the lock, and prints the diff of `agents/`. + +A byte copy at a pinned SHA with a CI equality check is a cache, not a second source. It keeps the drift test offline, matching team-cli's rule that network checks are opt-in (its link check runs on dispatch, not on push) [R]. [P] + +### 5.2 Generation rule + +`scripts/generate-agents.sh` is a fork of team-cli's generator [R] with the transform in §5.4. For each `upstream/profiles/.md` except `coordinator*`: + +``` +--- +name: +description: , . Reviews and drafts from the perspective for ck panels and delegation; returns structured findings. +model: +--- + + + + + +--- + +You are running as a delegated subagent. When the prompt names a run directory, read inputs from it and write outputs only there. If a schema is imposed, fill every required field; anything you would have asked goes in `questions`. Return findings first, detail after. +``` + +Frontmatter carries `name`, `description`, `model` and nothing else. Not set, with the reason: + +| Field | Why not in phase one | +|---|---| +| `effort` | Would override the session effort for every panel run; keep the policy in one place (the session) until the drill shows a need | +| `tools`, `disallowedTools` | Agents must write under the run directory; per-path scoping is not available; revisit after the drill | +| `maxTurns` | Workflow caps are the budget guard in phase one | +| `color` | Cosmetic; the style guide assigns colors to projects, not personas | +| `permissionMode`, `hooks`, `mcpServers` | Ignored for plugin agents [D] | + +### 5.3 Tier table + +From proposal §5.6, with the seven unassigned personas placed by this PRD (§3.3 item 4). The `Model` column is what `tiers.conf` must say after the prerequisite team-cli PR (§8.4); `ck` copies it verbatim. + +| Persona | Role | Tier | Model | Change from today | +|---|---|---|---|---| +| akira | Backend Engineering | Judgment | `claude-opus-5` | from Fable 5 | +| river | Product Manager | Judgment | `claude-opus-5` | from Fable 5 | +| morgan | Security Engineering | Judgment | `claude-opus-5` | from Fable 5 | +| sage | Business Advisor | Judgment | `claude-opus-5` | from Fable 5 | +| jordan | Data and ML | Judgment | `claude-opus-5` | from Fable 5 | +| reiner | Tabletop Game Designer | Judgment | `claude-opus-5` | from Fable 5 (placed by this PRD) | +| toni | Product Marketing | Judgment | `claude-opus-5` | from Opus 4.8 | +| kai | UX Design and Visual Art | Judgment | `claude-opus-5` | from Opus 4.8 | +| iris | Brand and Illustration | Judgment | `claude-opus-5` | from Opus 4.8 | +| quinn | Project Manager | Judgment | `claude-opus-5` | from Opus 4.8 | +| casey | Data Analyst | Judgment | `claude-opus-5` | from Opus 4.8 | +| cornelius | Military Historian | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| ernie | WW2 Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| rez | Cyberpunk Genre Advisor | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| tracy | Fantasy Genre Advisor | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| travolta | Fantasy Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| noon | Cyberpunk Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| sasha | Frontend Engineering | Execution | `claude-sonnet-5` | unchanged | +| alex | DevOps and Platform | Execution | `claude-sonnet-5` | unchanged | +| robin | QA and Testing | Execution | `claude-sonnet-5` | unchanged | +| piper | Tabletop Playtester | Execution | `claude-sonnet-5` | unchanged | + +Workflow-stage tiers, set in scripts, never on a persona: Deep research, `claude-fable-5-1` (the panel's decorrelation lens in phase one; deep passes in phase two); Classification, `claude-haiku-4-5-20251001` (the validator). + +Two [P] notes for the team-cli PR: (a) aliases `opus` and `sonnet` would let the tier follow the current generation without a file edit; the resolved model is recorded per agent in `/workflows` [D]; (b) moving River and Akira off Fable is a reasoning-tier downgrade for the two personas that write the PRD. The proposal's argument is price (Opus 5 at half) and Fable's cache advantage mattering most on long-horizon research. The 90-day usage data and the panel disagreement rate are the check; if PRD quality drops, the change is one line in `tiers.conf`. + +### 5.4 The interactive-behavior rewrite + +Every profile has a `## Required Interactive Behaviors` section written as questions to the user (River: Three Whys, V0 Challenge, Premortem). team-cli's generator strips it from the slash command and keeps it in the subagent [R]. A subagent cannot ask [D]. The transform is mechanical, identical for all 21 personas, and adds no per-persona prose: + +1. Rename the heading to `## Required Behaviors (subagent form)`. +2. Insert directly under it: + + > You are running with no user present. Every behavior below still applies, in output form. Where a behavior tells you to ask, halt, interrupt, or require an answer before proceeding: do not stop. State the question verbatim under `questions` (addressed to `author` or to a named teammate), state the assumption you will proceed on, and proceed. Where a behavior produces an artifact (table, diagram, scenario, counter-proposal, pitch), produce it in full. Where it requires a decision from the user, give your recommendation with evidence and mark the decision as open. + +3. Keep the upstream text verbatim beneath. + +What the preamble makes River do, and what `prd-draft.js` asks for by name: + +| Upstream behavior | Subagent form | +|---|---| +| Three Whys: ask "Why?" up to three times | Write the root-cause chain yourself from the brief (solution → why → why → why), each step more specific, until the user pain is exposed or the request is shown to address a symptom; say which. A why the brief cannot answer becomes a `questions` entry with your assumption | +| V0 Challenge: propose a V0 cutting half the scope and require a decision | Always include the V0 counter-proposal, what it cuts, whether it would still move the metric, and your recommendation with evidence. The decision stays with the author and is listed as open | +| Premortem: write the failure scenario and ask "What went wrong?" | Write the 2-3 sentence scenario in which this shipped on time and missed the metric, name the assumption it exposes, add that assumption to the Assumptions section, and leave the question verbatim for the author's gate | + +The interactive versions of River's three behaviors live in `skills/prd/SKILL.md` for Gate 0 and Gate 1, where there is a user. A CI check asserts the skill carries the three behavior headings from `upstream/profiles/river.md`, so a renamed behavior fails the build instead of diverging silently (§9). + +### 5.5 Instrumentation hook + +`hooks/hooks.json`: + +```json +{ + "description": "ck: persona usage log, so the 90-day prune has data", + "hooks": { + "SubagentStart": [ + { + "matcher": "^ck:", + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/usage-log.sh\"" } + ] + } + ] + } +} +``` + +`scripts/usage-log.sh` reads the hook's stdin JSON, appends one line `{"ts":"","agent_type":"ck:","session_id":"","cwd":""}` to `${CLAUDE_PLUGIN_DATA}/usage.jsonl`, and always exits 0. Facts it relies on: `SubagentStart` matchers accept plugin-scoped names such as `^my-plugin:reviewer$`; stdin carries `agent_type` and `session_id`; `CLAUDE_PLUGIN_DATA` is exported to hook processes and survives plugin updates [D]. It never blocks: a logging failure must not stop a persona. + +The 90-day review reads this file and answers proposal §8.4. + +### 5.6 Acceptance criteria + +- [ ] `agents/` holds exactly one file per `upstream/profiles/*.md` excluding `coordinator*` (21 today). +- [ ] Every agent's `model:` equals its `tiers.conf` line; `name:` equals the filename and contains no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble present; the generated-from comment names the lock's commit. +- [ ] Regenerating from `upstream/` produces no diff against the committed `agents/`. +- [ ] In a session with the plugin enabled, `@ck:river` appears in the subagent typeahead and `Agent({subagent_type: "ck:river", ...})` runs on `claude-opus-5` (visible in the transcript). +- [ ] After one `ck:` delegation, `${CLAUDE_PLUGIN_DATA}/usage.jsonl` has one new line with `agent_type` set. + +--- + +## 6. `/ck:panel` + +### 6.1 Purpose + +Proposal goal 4: adversarial and complementary input on one decision, from the product lens, the marketing lens, and the UX lens, each on a different model, each forced to argue against itself. The output is a decision memo that shows where the lenses disagree and leaves the decision to the author (proposal §5.5). + +### 6.2 Invocation + +``` +/ck:panel Should the first release include the branding guide step? +/ck:panel Is this PRD ready for review? --context plans/2026-09-05-thing-prd.md +/ck:panel --lenses river:claude-opus-5,morgan:claude-fable-5-1,sasha:claude-sonnet-5 +``` + +Claude passes the invocation as `args` [D]: + +```json +{ + "runId": "20260905T210000Z-branding-step", + "runDir": "/abs/path/.ck/runs/20260905T210000Z-branding-step", + "pluginRoot": "/abs/path/to/ck", + "timestamp": "20260905T210000Z", + "question": "Should the first release include the branding guide step?", + "contextPath": "/abs/path/plans/2026-09-05-thing-prd.md", + "lenses": [{ "persona": "river", "lens": "product", "model": "claude-opus-5" }] +} +``` + +`runId`, `runDir`, `pluginRoot`, `timestamp`, and `question` are required; the script throws without them. Because a workflow is a slash command with no skill in front of it, the main session mints `runId` and `timestamp` with `date -u` and passes absolute paths, following the same instructions the `prd` skill carries; those instructions are duplicated in the workflow's `description` so a direct invocation still works. + +### 6.3 Lenses and models + +| Lens | Persona | Default model | Why this model | +|---|---|---|---| +| product | `ck:river` | `claude-opus-5` | River's own tier; the anchor lens | +| marketing | `ck:toni` | `claude-fable-5-1` | The strongest model on the lens most often under-argued in a product decision; also the most expensive lens (Appendix F) | +| ux | `ck:kai` | `claude-sonnet-5` | Completes three distinct models at the lowest added cost | + +Any lens can be replaced or re-modelled per run. If two lenses share a model the script logs that their agreement counts as one opinion. The memo header always states: all lenses are Claude models from one training pipeline, so decorrelation is partial (proposal §8.5). [P] + +### 6.4 Lens schema + +Every lens returns, and writes to `panel/.json`: + +| Field | Meaning | +|---|---| +| `recommendation` | `yes`, `no`, `yes-if`, `not-yet` | +| `position` | One paragraph | +| `reasoning` | Evidence from the material or the lens's domain, not from the other lenses | +| `strongestArgumentAgainstOwnRecommendation` | The best case a smart colleague would make against it; a weak one is a failed answer | +| `conditionThatWouldMakeMeSayNo` | The specific, checkable condition under which the lens reverses | +| `questionsForOtherLenses` | `[{to, question}]`, addressed to `author` or a lens persona | +| `handoffBrief` | Decisions to record, open risks in the domain, one direct question to a named lens | + +The schema is enforced at the tool-call layer, so a lens that omits a field is retried by the harness [D]. + +### 6.5 Stages + +`meta.phases` and `meta.personas` (for the phase-two map): + +| Phase | Agents | What happens | +|---|---|---| +| Lenses | 3, in parallel, `agentType: 'ck:'`, `model` per lens | Each reads the context, applies its behaviors in subagent form, writes `panel/.json`, returns the object | +| Synthesis | 1, neutral (no `agentType`, session model) | Reads the three results, writes `decision-memo.md`, returns the memo object | + +Four agents. One concurrency round on any machine with four or more CPUs. Full script: Appendix A. + +### 6.6 Decision memo + +`decision-memo.md` sections, in order: + +1. Question and context (with the run id, timestamp, lens table, and the decorrelation limitation) +2. Recommendations: table, lens | persona | model | recommendation | one-line position +3. Where they agree +4. Where they disagree: topic, each position with its evidence, the decision the author must make +5. Each lens against itself, verbatim +6. Conditions to say no, verbatim +7. Questions between lenses, verbatim +8. Handoff briefs, verbatim, one per lens + +The synthesis agent is neutral and holds no lens. It never averages positions or picks a winner. If every lens recommends the same thing and no self-argument is substantive, it sets `panelFailedToDisagree` and says in the header that the panel should be re-run with a different question or lens set. + +### 6.7 Failure handling + +| Failure | Behavior | +|---|---| +| A lens is stopped by the user or dies on an API error | `agent()` returns `null` [D]; the script logs which lens is missing and synthesizes on the survivors; the memo header says so | +| Every lens fails | The script throws; nothing is written; the session sees the error | +| Synthesis returns `null` | The script returns the raw lens results with `memoPath: null`; `panel/*.json` is on disk | +| Two lenses share a model | Logged; the run proceeds | + +### 6.8 Cost + +About $0.75 per run at today's prices, dominated by the Fable lens. Assumptions and arithmetic: Appendix F. + +### 6.9 Acceptance criteria + +- [ ] `/ck:panel ` in a session with the plugin enabled shows the consent prompt with the option "don't ask again for `ck:panel`" [D]; after consent it runs in the background and `/workflows` shows phases Lenses and Synthesis. +- [ ] `.ck/runs//panel/river.json`, `toni.json`, `kai.json` exist and validate against the lens schema; `decision-memo.md` exists with the eight sections. +- [ ] `/workflows` shows three different models on the three lens agents. +- [ ] Stopping one lens in `/workflows` produces a memo whose header names the missing lens. +- [ ] `--lenses` with a replaced persona and model is honored (visible in `/workflows` and in the memo's table). +- [ ] The memo of a deliberately one-sided question ("Should we keep the tests passing?") reports `panelFailedToDisagree: true`. +- [ ] The script passes §9 test 9: `node --check` on the body wrapped as an async function, and no `Date.now`, `Math.random`, `new Date()`, `require(`, or `import(`. + +--- + +## 7. `/ck:prd` + +### 7.1 Purpose + +Proposal goal 3: a PRD that has the same shape every time, in every project, produced by River with the product, marketing, and UX lenses challenging it before the author sees it. The shape comes from the artifact contract (§7.8); the process comes from the skill and the workflow. + +### 7.2 Invocation + +``` +/ck:prd +/ck:prd A branding-guide step between the PRD and the roadmap +``` + +The argument, if given, answers Q1 below. Everything else is asked. + +### 7.3 Gate 0: intake, in the main session, as River + +The skill reads `${CLAUDE_PLUGIN_ROOT}/agents/river.md` for voice; the interactive forms below are the skill's own text (a subagent cannot ask, so the skill carries the interactive versions of River's three behaviors). One `AskUserQuestion` per step. **Each answer is appended to `brief.md` as it is given.** + +| Step | Question (River's wording) | Options | +|---|---|---| +| Resume check | If any `.ck/runs/*/brief.md` exists without a `prd-draft.md`: "Resume run `` from ``, or start new?" | Resume, Start new | +| Q1 Proposal | "In one or two sentences, what do you want to build?" | free text (skipped when given as the argument) | +| Q2 Why 1 | "Why does that need to exist? What happens to the user today without it?" | free text; "That is the root cause"; "I am solving a symptom and I know it" | +| Q3 Why 2 | "Why is [answer] a problem worth solving now?" | same; stop early on either fixed option | +| Q4 Why 3 | "Why [answer]? What is underneath that?" | same | +| Q5 User | "Who exactly has this pain? One primary user." | options drawn from the answers, plus Other | +| Q6 Metric | "What single number moves if this works, by how much, by when? And what leading indicator will you watch?" | free text | +| Q7 Non-goals | "Name two or three things this will explicitly not do." | free text | +| Q8 V0 Challenge | River states a V0 cutting at least half the scope, then: "Would this still move [metric]?" | "Build the V0"; "Build the full scope"; "Full scope, and here is what specifically requires it" (free text) | +| Q9 Lenses | "Default panel (River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5), or name lenses and models?" | Default; custom | +| Q10 Output | "Where should the final PRD go?" | default `plans/--prd.md`; free text | + +`brief.md` sections, in order: Proposal; Root-cause chain; User; Success metric and leading indicator; Scope decision and rationale; Non-goals; Lenses; Output path. + +After Q10 the skill mints the run: + +```bash +timestamp=$(date -u +%Y%m%dT%H%M%SZ) +runId="${timestamp}-" +runDir="$(pwd)/.ck/runs/${runId}" +mkdir -p "$runDir" +grep -qxF '.ck/' .git/info/exclude 2>/dev/null || echo '.ck/' >> .git/info/exclude +``` + +and writes `run.json` with `{runId, createdAt, status: "gate-0", outputPath, lenses}`. + +### 7.4 Launch and wait + +The skill calls, exactly: + +``` +Workflow({ + scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/prd-draft.js", + args: { + runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp, + briefPath: "/brief.md", + lenses: + } +}) +``` + +It writes the returned run id into `run.json` as `harnessRunId` together with `scriptPath`, sets `status: "drafting"`, tells the user the draft is running in the background, and **stops: it waits for the task notification. It does not poll, does not narrate, and does not start other work on this run.** If the notification reports a stop or failure, it offers `Workflow({ scriptPath, resumeFromRunId: harnessRunId })`, which replays completed agents from cache [D]. + +`${CLAUDE_PLUGIN_ROOT}` expands anywhere in skill content [D]. Whether `name: "ck:prd-draft"` also works for the Workflow tool is unverified (§10.2); `scriptPath` is the specified path. + +### 7.5 The `prd-draft` workflow + +`meta.personas: ['river', 'toni', 'kai']`. Full script: Appendix B. + +| Phase | Agents | What happens | Output | +|---|---|---|---| +| Draft | 1, `ck:river` | Reads `brief.md` and the artifact contract. Writes `draft-v0.md` to the contract's section order. Tags every claim not taken from the brief `[C1]`, `[C2]`, ... so the lenses can address it. Root-cause chain and V0 counter-proposal in subagent form. No premortem yet | `draft-v0.md`; claims list; assumptions; V0; questions | +| Validate | 1 neutral, `claude-haiku-4-5-20251001`; then `ck:river` to revise, at most twice | Checks the draft against every item in the contract's checklist; returns `{valid, missing[], notes}`. On `missing`, River revises in place, keeping every `[C]` tag. After two revisions the workflow proceeds and logs what is still missing | validation result | +| Panel | 4, nested `workflow({scriptPath: pluginRoot + '/workflows/panel.js'})` | Question: "Is this PRD ready for the author's review, and what would you change before it ships?" Context: `draft-v0.md`. Same lenses as Q9 | `panel/*.json`, `decision-memo.md` | +| Synthesize | 1, `ck:river` | Writes `prd-draft.md`: the PRD revised where the panel showed a claim wrong or unsupported; **Appendix A, Challenged claims** (claim, challenged by, severity, status ∈ upheld, revised, withdrawn, open; resolution; the panel's disagreements reproduced verbatim; nothing deleted); **Appendix B, Premortem** (the scenario, the exposed assumption, the question "What went wrong?" left verbatim for Gate 1) | `prd-draft.md`; challenged claims; premortem; open decisions | + +Seven agents without a revision, up to nine with two. Under the default "medium" size guideline; two concurrency rounds on a 4-CPU laptop. If the nested panel throws, the workflow logs it and synthesizes without it, saying so in the PRD header. + +### 7.6 Gate 1: review, in the main session, as River + +The skill reads `prd-draft.md` and shows, in this order: the summary; the Challenged claims table; the open decisions; the premortem scenario verbatim. Then: + +| Step | Question | Options | +|---|---|---| +| Premortem | "What went wrong?" | "The metric was wrong"; "The user was not who we thought"; "Scope crept"; free text | +| Disposition | "Accept, edit named sections, or re-run the panel on named sections?" | Accept; Edit: ...; Re-run panel on: ... | + +Answers and edits go to `gate-1.md`. A re-run calls `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { ..., question: "", contextPath: "/prd-draft.md" } })`, waits, and returns to this gate. + +### 7.7 Finalize, inline + +One agent, so no workflow (§4.2): + +``` +Agent({ + subagent_type: "ck:river", + description: "Finalize PRD", + prompt: "Read /prd-draft.md and /gate-1.md. Fold the premortem answer into Assumptions and Risks, apply the requested edits, resolve each open decision as answered, keep Appendix A intact. Write the final PRD to . Set status 'final' in /run.json. Return the path and a five-line summary." +}) +``` + +The skill prints the output path and the run directory and suggests `/devlog` for the decision memo. + +### 7.8 The PRD artifact contract + +`skills/prd-artifact/SKILL.md` (full text: Appendix D). Not user-invocable. It is the file River reads to draft, the validator reads to check, and Claude loads on its own when asked to write a PRD outside the workflow (its description says so), which is the proposal's consistency mechanism (§3.4) reaching the plain session too. + +Section order: Summary; Problem; User; Success metric and leading indicator; Scope (the decision, and the V0 counter-proposal); Non-goals; Requirements (numbered, each with acceptance criteria); Sequencing and dependencies; Assumptions; Risks; Open questions; Appendix A Challenged claims; Appendix B Premortem. + +Checklist (each item is a statement the validator can check by reading): + +1. Every section above is present, in order, with its heading verbatim. +2. Problem names the user pain, not the solution, and cites the root-cause chain. +3. Success metric is one number with a target and a date, plus one leading indicator. +4. Scope records the V0 or full decision and the V0 counter-proposal with what it cuts. +5. Non-goals has at least two entries. +6. Every requirement has at least one acceptance criterion that a reader could verify without asking the author. +7. Every claim not from the brief carries a `[C]` tag, and every tag appears in Appendix A or is marked unchallenged. +8. Assumptions includes the assumption the premortem exposed. +9. Open questions lists every decision left to the author. +10. No em-dashes in prose (the family writing rule; the structural-list exception applies). + +### 7.9 Cost + +About $1.50 per run without a revision, about $2.00 with one, plus the main session's own turns. Appendix F. + +### 7.10 Acceptance criteria + +- [ ] `/ck:prd` never auto-triggers (`disable-model-invocation: true`); typing it starts Gate 0 as River. +- [ ] After Q3, `brief.md` already contains Proposal and the first two whys (compaction safety). +- [ ] Killing the session after Q6 and running `/ck:prd` again offers to resume the run. +- [ ] `run.json` contains `harnessRunId` before the skill goes idle. +- [ ] `.git/info/exclude` contains `.ck/`; `git status` shows nothing under `.ck/`. +- [ ] `/workflows` shows phases Draft, Validate, Panel (with the nested panel's agents), Synthesize; the validator agent runs on Haiku 4.5. +- [ ] `prd-draft.md` has every contract section, an Appendix A with at least one row per blocking or major lens finding, and an Appendix B with a scenario and the verbatim question. +- [ ] Gate 1 asks "What went wrong?" first, then the disposition. +- [ ] The final PRD lands at the Q10 path with `status: final` in `run.json`, and its checklist passes when re-validated by hand against §7.8. +- [ ] The consent prompts seen during the drill are recorded, including whether the nested panel prompted separately (§10.2). +- [ ] `skills/prd/SKILL.md` contains the three behavior headings from `upstream/profiles/river.md` (CI-checked). + +--- + +## 8. Repository, packaging, release + +### 8.1 Repository and layout + +New repository `code-katz/ck`, one plugin per repo like the seven marketplace entries today [R]. Rejected: inside `claude-team-cli` (reopens the 07-31 decision inside the same repo and mixes the shell install path with the plugin) and inside `claude-plugins` as a subdirectory plugin (supported by the marketplace-root source form [D], but it breaks the family's per-repo README, DEVLOG, ROADMAP, and test convention). [P] + +``` +ck/ +├── .claude-plugin/plugin.json +├── README.md DEVLOG.md ROADMAP.md LICENSE +├── upstream/ vendored from claude-team-cli at the pinned commit +│ ├── profiles/*.md +│ └── tiers.conf +├── agents/*.md 21 generated files (§5) +├── skills/ +│ ├── prd/SKILL.md /ck:prd (Appendix C) +│ └── prd-artifact/SKILL.md the contract (Appendix D) +├── workflows/ +│ ├── panel.js /ck:panel (Appendix A) +│ └── prd-draft.js /ck:prd-draft (Appendix B) +├── hooks/hooks.json §5.5 +├── scripts/ +│ ├── generate-agents.sh +│ ├── bump-upstream.sh +│ ├── usage-log.sh +│ └── upstream.lock +└── tests/ + ├── run.sh + └── fixtures/ a tiny project with a brief.md and a one-page context doc +``` + +### 8.2 Manifest + +```json +{ + "name": "ck", + "description": "Persona workflows for Claude Code: /ck:prd (a River-led PRD challenged by a three-lens panel), /ck:panel (product, marketing, and UX lenses on different models), and 21 Code Katz personas as ck: subagents.", + "version": "0.1.0", + "author": { "name": "Code Katz" } +} +``` + +`version` pins the plugin: users receive a new copy only when the string changes [D]. Every release, including a regenerated `agents/` after `bump-upstream.sh`, bumps it. This is written next to `bump-upstream.sh` because it is not testable. + +### 8.3 Marketplace entry + +Appended to `claude-plugins/.claude-plugin/marketplace.json` (bumping its `metadata.version` to 1.4.0): + +```json +{ + "name": "ck", + "source": { "source": "github", "repo": "code-katz/ck" }, + "description": "Persona workflows: /ck:prd (River-led PRD with a three-lens panel), /ck:panel (product, marketing, UX lenses on different models), and 21 personas as ck: subagents. Phase one of the code-katz plugin.", + "category": "workflow", + "keywords": ["workflows", "personas", "prd", "panel", "subagents"] +} +``` + +Install: `/plugin marketplace add code-katz/claude-plugins` then `/plugin install ck@code-katz`. For development: `claude --plugin-dir /path/to/ck`, then `/reload-skills` after editing a workflow [D]. + +### 8.4 Prerequisites + +| Prerequisite | Why | Grade | +|---|---|---| +| A paid Claude Code plan with dynamic workflows available; on Pro, enabled in `/config` | Workflows are the orchestrator | [D] | +| Workflows not disabled by the organization (`disableWorkflows`) | Same | [D] | +| team-cli PR re-basing `tiers.conf` to §5.3 | `ck` copies the tier verbatim; without the PR, River runs on Fable 5 and the panel's Opus lens is an override, not a tier | [R] | +| Node 20+ on the developer's machine, for `node --check` in the tests only | The plugin itself needs no Node at run time | [P] | +| `jq` optional, for the usage log; the script falls back to appending the raw line | Family convention: jq is optional | [R] | + +### 8.5 Version and update policy + +- `0.1.0` is the phase-one release. `0.x` until the 90-day review. +- A change to any file under `agents/`, `skills/`, `workflows/`, or `hooks/` bumps the patch or minor version in the same commit. +- `bump-upstream.sh` refuses to run if the working tree is dirty and prints the `agents/` diff so the reviewer sees what changed in persona text. + +### 8.6 Coexistence with `claude-team-cli` + +| Route | How | Lives in | +|---|---|---| +| Switch this session to a persona | `/river`, `/akira`, ... | team-cli (`install.sh`) | +| Delegate one task to a persona on its tier | `ck:river` subagent, or team-cli's `river` subagent | both; `ck:` is the plugin form | +| Open a separate session as a persona | `claude-team launch river` | team-cli | +| Run a repeatable pipeline | `/ck:prd`, `/ck:panel` | ck | +| Plan parallel sessions, track them | `/parallel`, `/conductor` | team-cli, conductor | + +A user with both installed has two River subagents (`river` from `~/.claude/agents/`, priority 4, and `ck:river`, priority 5) [D]. They are generated from the same profile text at possibly different commits; `upstream.lock` says which. The README says this once. + +--- + +## 9. Tests + +`tests/run.sh`, bash, `set -uo pipefail`, `ok`/`fail` helpers and a `mktemp` scratch tree, in the family's style [R]. + +| # | Test | Type | +|---|---|---| +| 1 | `plugin.json` parses; `name` is `ck`; `version` matches a semver | static | +| 2 | Regenerate `agents/` from `upstream/` into scratch; `diff -q` each file against the committed copy; fail listing stale names | drift | +| 3 | Agent count equals profile count minus `coordinator*` | drift | +| 4 | Per agent: `model:` equals the `tiers.conf` line; `name:` equals the filename, no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble sentence present | drift | +| 5 | `scripts/upstream.lock` has exactly one `commit=` with a 40-hex value | drift | +| 6 | Opt-in (dispatch or schedule, never on push): `git fetch --depth 1 origin ` and `diff -r` the vendored files against it | drift, network | +| 7 | `skills/prd/SKILL.md` contains the three `### N. ` headings from `upstream/profiles/river.md` | contract | +| 8 | `skills/prd-artifact/SKILL.md` section list equals the list in the `prd-draft.js` Draft prompt | contract | +| 9 | Every `workflows/*.js`: `node --check` passes on a copy with `export` stripped and the body wrapped in `(async () => { ... })()`, because workflow scripts use top-level `return` and `await`, which a bare module rejects; first statement is `export const meta`; `meta` has `name`, `description`, `phases`, `personas`; grep for `Date.now|Math.random|new Date\(\)|require\(|import\(` is empty | lint | +| 10 | `hooks/hooks.json` parses; the matcher is `^ck:`; `usage-log.sh` given a fixture stdin appends one valid JSON line and exits 0, and exits 0 on garbage input | hook | +| 11 | End-to-end drill, by hand, on the fixture project and then on one real project: `/ck:panel` then `/ck:prd`; record the consent prompts, the files under `.ck/runs//`, the models shown in `/workflows`, and the final PRD path. The drill log is committed under `tests/drill/.md` | e2e | + +`claude plugin eval` is early access and not enabled today; when it is, the drill becomes an eval suite and test 11 stops being manual. + +--- + +## 10. Deferred and open + +### 10.1 Deferred, with the trigger to revisit + +| Item | Why not in phase one | Revisit when | +|---|---|---| +| The other seven workflows in proposal §5.3 (`opportunity`, `market-research`, `brand-guide`, `roadmap`, `feature`, `bugfix`, `gtm`) and `/ck:next` | Phase one proves the gate rule, the port, and the artifact contract on one workflow first | Phase one has been used weekly for 30 days | +| `/ck:review`: a six-reviewer artifact review with adversarial refuters and a verify cap (designed during this PRD's review; a different product from the three-lens panel) | The panel is the decision primitive the proposal asks for; a review workflow is a second one | The panel proves too narrow for code, design, or plan reviews | +| Persona switch skills `/ck:` | team-cli's `/name` commands cover the switch route today | The retire-or-coexist decision at 90 days | +| Hook-enforced artifact gates (`SubagentStop`, exit 2) | Feedback path undocumented; plugin agents ignore per-agent hooks [D]; the validator agent covers the shape check | More than one draft in five passes the validator and still fails Gate 1 on structure | +| Model fallback chain | `PreModelSwitch` does not cover it [D]; null-tolerant scripts cover phase one | More than one run in ten loses a lens to an API error | +| Advisor tool | API-only and experimental [V] | Available inside Claude Code | +| Routines | No headless workflow the user wants scheduled yet | `market-research` ships (the natural candidate) | +| Folding in `devlog`, `roadmap`, `plans`, `todo`, `publish` as artifact contracts | Their repos work as they are; folding in orphans seven marketplace entries | A `ck` workflow needs to read one of them as a contract (`roadmap.js` first) | +| Retiring `claude-team-cli` | No usage data | The 90-day review | +| `/ck:map`, any workbench | §4.7 | A specific edit Will could not make in a text editor plus `bump-upstream.sh` | +| A `bin/` CLI | Nothing needs one | Never, unless a workflow needs a helper the Bash tool should call | +| Conductor bug fixes from proposal §9 (`update_session_field` and `insert_active_row` tmp-then-mv without a lock; `watcher.js:134` empty-cell filter vs positional awk) | They are conductor's, not `ck`'s | Filed against conductor now | + +### 10.2 Open questions carried forward + +1. Proposal §8.6, verbatim: "`/ck:feature` scope. Full end-to-end including marketing copy, or code-only with content as a separate workflow?" Not needed until `feature.js`. +2. Proposal §8.7, verbatim: "Routines integration. Which workflows, if any, should run scheduled or on GitHub events?" +3. Does the Workflow tool's `name` parameter accept `ck:prd-draft` for a plugin workflow? `scriptPath` is the specified path; the drill tries `name` and records the answer. +4. Does a nested `workflow({scriptPath})` prompt for consent separately on first run, and does "don't ask again for `ck:panel`" cover the nested call? The drill records it. +5. Does the workflow loader accept the extra `personas` key in `meta`? The docs require `name` and `description` and describe `whenToUse` and `phases`; an extra literal key is expected to pass. Test 9 asserts it; the drill confirms `/ck:panel` still appears in autocomplete. +6. Does `SubagentStop` exit 2 feed stderr back to a workflow agent? Decides the hook-gate spike. +7. Aliases or full IDs in `tiers.conf`? The team-cli PR decides (§5.3). + +--- + +## 11. Risks + +| Risk | Likelihood | Impact | Mitigation | +|---|---|---|---| +| Workflows unavailable (plan, `/config`, or org `disableWorkflows`) | Low for Will; real for other users | The plugin is inert | README states the prerequisite; the `prd` skill checks for the Workflow tool before Gate 0 and stops with the reason | +| An API error nulls a lens | Medium | Memo on two lenses | Logged; memo header says so; re-run offered; a lens can be re-modelled per run | +| The Fable lens dominates cost | Certain | About $0.30 to $0.50 of every panel | `--lenses` override; an all-Opus-and-Sonnet assignment is one flag away | +| Persona text drifts from upstream | Low | Two Rivers disagree | `upstream.lock`, drift test, `bump-upstream.sh` prints the diff | +| 21 personas is 15 too many | Likely (proposal §7) | Maintenance and choice paralysis | Generated, so carrying cost is near zero; `usage.jsonl`; prune at 90 days | +| River and Akira on Opus 5 write worse PRDs than on Fable | Unknown | Quality of the flagship artifact | One line in `tiers.conf` reverts it; the panel disagreement rate and Gate 1 edit volume are the signal | +| The 4.7-and-later tokenizer produces about 30% more tokens [D] | Certain | Appendix F underestimates by up to 30% | Stated in Appendix F; `/workflows` shows real token totals | +| Compaction during Gate 0 | Medium on long intakes | Lost answers | Append-as-you-go and the resume check (§4.3) | +| Consent prompts on every run annoy | Medium | Friction | "Don't ask again for `ck:panel`" on the first run; allow rules `Workflow(ck:panel)`, `Workflow(ck:prd-draft)` | +| Two River subagents (`river`, `ck:river`) confuse delegation | Low | Wrong tier or stale text | README note; every `ck` prompt names `ck:` explicitly | +| `meta.personas` rejected by the loader | Low | Workflow missing from autocomplete | Open question 5; fallback is to move the roster into `description` | + +--- + +## Appendix A. `workflows/panel.js` + +```js +export const meta = { + name: 'panel', + description: 'Three-lens decision panel: product (river), marketing (toni), and UX (kai) personas, each on a different model, argue one question; a neutral memo surfaces where they disagree and leaves the decision to the author. Args: runId, runDir (absolute), pluginRoot, timestamp (UTC, minted by the caller with date -u), question, contextPath (optional), lenses (optional [{persona, lens, model}]).', + phases: [ + { title: 'Lenses', detail: 'ck:river, ck:toni, ck:kai in parallel, one model each, each forced to argue against itself' }, + { title: 'Synthesis', detail: 'one neutral agent writes decision-memo.md; disagreement preserved, decision left to the author' }, + ], + personas: ['river', 'toni', 'kai'], +} + +if (!args || !args.runId || !args.runDir || !args.pluginRoot || !args.timestamp || !args.question) { + throw new Error('panel: args.runId, args.runDir, args.pluginRoot, args.timestamp, and args.question are required') +} +const runDir = args.runDir +const stamp = args.timestamp +const question = args.question +const contextPath = args.contextPath || null + +// Three lenses, three models: the same model in three costumes is one opinion. +// This is the one script in ck allowed to set `model` on a persona agent; the +// per-invocation model beats the agent's frontmatter tier. Any lens may be +// replaced or re-modelled through args.lenses. +const DEFAULT_LENSES = [ + { persona: 'river', lens: 'product', model: 'claude-opus-5' }, + { persona: 'toni', lens: 'marketing', model: 'claude-fable-5-1' }, + { persona: 'kai', lens: 'ux', model: 'claude-sonnet-5' }, +] +const lenses = Array.isArray(args.lenses) && args.lenses.length + ? args.lenses.map((l, i) => ({ + persona: l.persona, + lens: l.lens || l.persona, + model: l.model || DEFAULT_LENSES[i % DEFAULT_LENSES.length].model, + })) + : DEFAULT_LENSES +if (lenses.some(l => !l.persona)) throw new Error('panel: every entry in args.lenses needs a persona') +if (new Set(lenses.map(l => l.model)).size < lenses.length) { + log('panel: two or more lenses share a model; their agreement counts as one opinion') +} + +const QUESTION = { + type: 'object', + properties: { to: { type: 'string' }, question: { type: 'string' } }, + required: ['to', 'question'], +} + +const LENS_SCHEMA = { + type: 'object', + properties: { + persona: { type: 'string' }, + lens: { type: 'string' }, + recommendation: { type: 'string', enum: ['yes', 'no', 'yes-if', 'not-yet'] }, + position: { type: 'string' }, + reasoning: { type: 'string' }, + strongestArgumentAgainstOwnRecommendation: { type: 'string' }, + conditionThatWouldMakeMeSayNo: { type: 'string' }, + questionsForOtherLenses: { type: 'array', items: QUESTION }, + handoffBrief: { type: 'string' }, + }, + required: [ + 'persona', 'lens', 'recommendation', 'position', 'reasoning', + 'strongestArgumentAgainstOwnRecommendation', 'conditionThatWouldMakeMeSayNo', + 'questionsForOtherLenses', 'handoffBrief', + ], +} + +const MEMO_SCHEMA = { + type: 'object', + properties: { + memoPath: { type: 'string' }, + question: { type: 'string' }, + recommendations: { + type: 'array', + items: { + type: 'object', + properties: { + persona: { type: 'string' }, lens: { type: 'string' }, + model: { type: 'string' }, recommendation: { type: 'string' }, + }, + required: ['persona', 'lens', 'model', 'recommendation'], + }, + }, + agreements: { type: 'array', items: { type: 'string' } }, + disagreements: { + type: 'array', + items: { + type: 'object', + properties: { + topic: { type: 'string' }, + positions: { + type: 'array', + items: { + type: 'object', + properties: { persona: { type: 'string' }, position: { type: 'string' } }, + required: ['persona', 'position'], + }, + }, + decisionForAuthor: { type: 'string' }, + }, + required: ['topic', 'positions', 'decisionForAuthor'], + }, + }, + conditions: { + type: 'array', + items: { + type: 'object', + properties: { persona: { type: 'string' }, condition: { type: 'string' } }, + required: ['persona', 'condition'], + }, + }, + panelFailedToDisagree: { type: 'boolean' }, + summary: { type: 'string' }, + }, + required: [ + 'memoPath', 'question', 'recommendations', 'agreements', 'disagreements', + 'conditions', 'panelFailedToDisagree', 'summary', + ], +} + +// ---- Lenses ---- +phase('Lenses') +const roster = lenses.map(l => `${l.persona}: ${l.lens}`).join('; ') +const results = (await parallel(lenses.map(l => () => agent( + `You are ${l.persona}, the ${l.lens} lens on a ${lenses.length}-lens decision panel (${roster}).\n` + + `The question: ${question}\n` + + (contextPath ? `Read ${contextPath} in full before answering; it is the material the question is about. ` : '') + + `If ${runDir}/brief.md exists, read it too; it records the author's intent.\n` + + `Answer from your own domain only. Apply your Required Behaviors in subagent form: where a behavior tells you ` + + `to ask the user, put the question in questionsForOtherLenses addressed to 'author' or to a lens persona, ` + + `state your assumption, and proceed.\n` + + `Return: recommendation (yes, no, yes-if, not-yet); position (one paragraph); reasoning (evidence from the ` + + `material or from your domain, not from the other lenses); strongestArgumentAgainstOwnRecommendation (the ` + + `best case a smart colleague would make against you; a weak one is a failed answer); ` + + `conditionThatWouldMakeMeSayNo (the specific, checkable condition under which you would reverse); ` + + `handoffBrief (decisions you want recorded, open risks in your domain, one direct question to a named lens).\n` + + `Write the same object as JSON to ${runDir}/panel/${l.persona}.json (create the directory if needed) and ` + + `return it with persona '${l.persona}' and lens '${l.lens}'.`, + { label: `${l.lens}:${l.persona}`, phase: 'Lenses', agentType: 'ck:' + l.persona, model: l.model, schema: LENS_SCHEMA }, +)))).filter(Boolean) + +if (results.length === 0) throw new Error('panel: every lens was stopped or failed; nothing to synthesize') +const missing = lenses.filter(l => !results.some(r => r.persona === l.persona)).map(l => l.persona) +if (missing.length) { + log(`panel: ${missing.join(', ')} returned nothing (stopped or API error); the memo runs on ${results.length} lens(es)`) +} + +// ---- Synthesis ---- +phase('Synthesis') +const modelOf = persona => (lenses.find(l => l.persona === persona) || {}).model || 'unknown' +const memo = await agent( + `Write the decision memo for a ${lenses.length}-lens panel. Question: ${question}. Run ${args.runId}, generated ${stamp}.\n` + + `Lens results, also on disk under ${runDir}/panel/:\n` + + JSON.stringify(results.map(r => ({ ...r, model: modelOf(r.persona) })), null, 1) + '\n' + + (missing.length ? `Lenses that returned nothing: ${missing.join(', ')}. Say so in the memo header.\n` : '') + + `Rules. You are neutral and hold no lens. Surface where the lenses disagree and do not resolve it; the ` + + `decision is the author's. Never average positions or pick a winner. Quote each lens's strongest argument ` + + `against itself and its condition to say no verbatim. If every lens recommends the same thing and no ` + + `self-argument is substantive, set panelFailedToDisagree to true and say in the header that the panel ` + + `failed to disagree and should be re-run with a different question or lens set. State in the header that ` + + `all lenses are Claude models from one training pipeline, so decorrelation is partial.\n` + + `Write ${runDir}/decision-memo.md with these sections: 1 Question and context (run id, timestamp, lens ` + + `table with models, the limitation); 2 Recommendations (table: lens | persona | model | recommendation | ` + + `one-line position); 3 Where they agree; 4 Where they disagree (topic, each position with its evidence, ` + + `the decision the author must make); 5 Each lens against itself (verbatim); 6 Conditions to say no ` + + `(verbatim); 7 Questions between lenses (to -> question, verbatim); 8 Handoff briefs (verbatim, one per ` + + `lens). Then return the memo object; memoPath must be '${runDir}/decision-memo.md'.`, + { label: 'synthesis', phase: 'Synthesis', schema: MEMO_SCHEMA }, +) + +if (!memo) { + log('panel: synthesis returned nothing; returning raw lens results') + return { + runId: args.runId, question, memoPath: null, lenses: lenses.map(l => l.persona), missing, + recommendations: results.map(r => ({ persona: r.persona, lens: r.lens, model: modelOf(r.persona), recommendation: r.recommendation })), + agreements: [], disagreements: [], conditions: results.map(r => ({ persona: r.persona, condition: r.conditionThatWouldMakeMeSayNo })), + panelFailedToDisagree: null, summary: 'synthesis agent returned nothing; see panel/*.json', + } +} +if (memo.panelFailedToDisagree) log('panel: the panel failed to disagree; re-run with a different question or lens set') +return { runId: args.runId, ...memo, lenses: lenses.map(l => l.persona), missing } +``` + +## Appendix B. `workflows/prd-draft.js` + +```js +export const meta = { + name: 'prd-draft', + description: "River drafts a PRD from brief.md to the prd-artifact contract, a validator checks it, the three-lens panel challenges it, and River writes prd-draft.md with a Challenged claims appendix and a premortem. Args: runId, runDir (absolute), pluginRoot, timestamp, briefPath (optional), lenses (optional). Normally launched by /ck:prd, which owns the gates before and after.", + phases: [ + { title: 'Draft', detail: 'ck:river writes draft-v0.md from brief.md to the contract; every non-brief claim tagged [C]' }, + { title: 'Validate', detail: 'one neutral Haiku agent checks the draft against the contract checklist; ck:river revises at most twice' }, + { title: 'Panel', detail: "nested /ck:panel on the draft: is it ready for the author's review, and what would you change" }, + { title: 'Synthesize', detail: 'ck:river writes prd-draft.md: revised PRD, Appendix A Challenged claims, Appendix B Premortem' }, + ], + personas: ['river', 'toni', 'kai'], +} + +if (!args || !args.runId || !args.runDir || !args.pluginRoot || !args.timestamp) { + throw new Error('prd-draft: args.runId, args.runDir, args.pluginRoot, and args.timestamp are required') +} +const runDir = args.runDir +const brief = args.briefPath || (runDir + '/brief.md') +const stamp = args.timestamp +const contract = args.pluginRoot + '/skills/prd-artifact/SKILL.md' +const draftPath = runDir + '/draft-v0.md' +const prdPath = runDir + '/prd-draft.md' +const MAX_REVISIONS = 2 +const VALIDATOR_MODEL = 'claude-haiku-4-5-20251001' + +const QUESTION = { + type: 'object', + properties: { to: { type: 'string' }, question: { type: 'string' } }, + required: ['to', 'question'], +} + +const DRAFT_SCHEMA = { + type: 'object', + properties: { + draftPath: { type: 'string' }, + title: { type: 'string' }, + rootCauseChain: { type: 'array', items: { type: 'string' } }, + claims: { + type: 'array', + items: { + type: 'object', + properties: { id: { type: 'string' }, text: { type: 'string' }, section: { type: 'string' } }, + required: ['id', 'text', 'section'], + }, + }, + assumptions: { type: 'array', items: { type: 'string' } }, + v0: { + type: 'object', + properties: { + scope: { type: 'string' }, + cuts: { type: 'array', items: { type: 'string' } }, + recommendation: { type: 'string' }, + }, + required: ['scope', 'cuts', 'recommendation'], + }, + questions: { type: 'array', items: QUESTION }, + }, + required: ['draftPath', 'title', 'rootCauseChain', 'claims', 'assumptions', 'v0', 'questions'], +} + +const VALIDATION_SCHEMA = { + type: 'object', + properties: { + valid: { type: 'boolean' }, + missing: { type: 'array', items: { type: 'string' } }, + notes: { type: 'string' }, + }, + required: ['valid', 'missing', 'notes'], +} + +const PRD_SCHEMA = { + type: 'object', + properties: { + prdPath: { type: 'string' }, + title: { type: 'string' }, + challengedClaims: { + type: 'array', + items: { + type: 'object', + properties: { + claim: { type: 'string' }, + challengedBy: { type: 'string' }, + severity: { type: 'string', enum: ['blocking', 'major', 'minor'] }, + status: { type: 'string', enum: ['upheld', 'revised', 'withdrawn', 'open'] }, + resolution: { type: 'string' }, + }, + required: ['claim', 'challengedBy', 'severity', 'status', 'resolution'], + }, + }, + premortem: { + type: 'object', + properties: { + scenario: { type: 'string' }, + exposedAssumption: { type: 'string' }, + question: { type: 'string' }, + }, + required: ['scenario', 'exposedAssumption', 'question'], + }, + openDecisions: { type: 'array', items: { type: 'string' } }, + summary: { type: 'string' }, + }, + required: ['prdPath', 'title', 'challengedClaims', 'premortem', 'openDecisions', 'summary'], +} + +// ---- Draft ---- +phase('Draft') +let draft = await agent( + `Read ${brief}. It records the intake gate the author already answered with you: proposal, root-cause chain, ` + + `user, success metric and leading indicator, scope decision (V0 or full, with rationale), non-goals, lenses, ` + + `and the output path. Do not re-ask any of it.\n` + + `Read ${contract}. It is the PRD contract: section order, required fields, and the checklist your draft will ` + + `be validated against.\n` + + `Write ${draftPath} to that contract, all sections in order. Apply your Required Behaviors in subagent form: ` + + `restate the root-cause chain from the brief and extend it if the brief stopped at a symptom, saying which; ` + + `always present the V0 counter-proposal with what it cuts and your recommendation, even if the brief chose ` + + `full scope; leave the premortem for the synthesis pass after the panel, and say so under Appendix B.\n` + + `Tag every claim that is not taken directly from the brief with an inline marker [C1], [C2], ... so the panel ` + + `can address it, and list those claims with their section. Put anything you would have asked the author in ` + + `questions, with your assumption.\n` + + `Return the draft object; draftPath must be '${draftPath}'.`, + { label: 'river:draft', phase: 'Draft', agentType: 'ck:river', schema: DRAFT_SCHEMA }, +) +if (!draft) throw new Error('prd-draft: River returned nothing for the draft; check ' + runDir) +log(`draft: ${draft.claims.length} tagged claim(s), ${draft.assumptions.length} assumption(s), ${draft.questions.length} question(s) for the author`) + +// ---- Validate ---- +phase('Validate') +let validation = null +for (let round = 1; round <= MAX_REVISIONS + 1; round++) { + validation = await agent( + `Read ${contract} and ${draftPath}. Check the draft against every numbered item in the contract's Checklist ` + + `section and against the section order. Return valid=true only if every item holds. For each unmet item, ` + + `one line in missing that quotes the checklist item and says what is absent or wrong. Judge the shape, ` + + `not the product.`, + { label: `validate:${round}`, phase: 'Validate', model: VALIDATOR_MODEL, schema: VALIDATION_SCHEMA }, + ) + if (!validation) { log('validate: validator returned nothing; proceeding unvalidated'); break } + if (validation.valid) { log(`validate: draft passes the contract checklist (round ${round})`); break } + if (round > MAX_REVISIONS) { + log(`validate: still unmet after ${MAX_REVISIONS} revision(s): ${validation.missing.join(' | ')}`) + break + } + log(`validate: ${validation.missing.length} unmet item(s); River revises (revision ${round} of ${MAX_REVISIONS})`) + const revised = await agent( + `Read ${contract}, ${brief}, and ${draftPath}. A validator found these unmet checklist items:\n` + + validation.missing.map(m => '- ' + m).join('\n') + '\n' + + `Revise ${draftPath} in place so each item holds. Keep every existing [C] tag and add tags for any new ` + + `claim not from the brief. Return the updated draft object; draftPath must be '${draftPath}'.`, + { label: `river:revise:${round}`, phase: 'Validate', agentType: 'ck:river', schema: DRAFT_SCHEMA }, + ) + if (!revised) { log('validate: revision returned nothing; keeping the previous draft'); break } + draft = revised +} + +// ---- Panel (nested; one level only) ---- +phase('Panel') +let panel = null +try { + panel = await workflow({ scriptPath: args.pluginRoot + '/workflows/panel.js' }, { + runId: args.runId, + runDir, + pluginRoot: args.pluginRoot, + timestamp: stamp, + question: "Is this PRD ready for the author's review, and what would you change before it ships?", + contextPath: draftPath, + lenses: args.lenses || null, + }) +} catch (e) { + log('panel: failed (' + (e && e.message ? e.message : String(e)) + '); synthesizing without it') +} +if (panel) { + log(`panel: ${panel.lenses.join(', ')}; ${(panel.disagreements || []).length} disagreement(s)` + + (panel.panelFailedToDisagree ? '; the panel failed to disagree' : '') + + (panel.missing && panel.missing.length ? `; missing: ${panel.missing.join(', ')}` : '')) +} + +// ---- Synthesize ---- +phase('Synthesize') +const panelInputs = panel && panel.memoPath + ? `${panel.memoPath} and every file under ${runDir}/panel/` + : (panel + ? `every file under ${runDir}/panel/ (the memo was not written)` + : 'nothing else: the panel did not run, and the PRD header must say so') +const prd = await agent( + `Read ${brief}, ${draftPath}, ${contract}, and ${panelInputs}.\n` + + `Write ${prdPath}: the same PRD sections as the draft, in contract order, revised where the panel showed a ` + + `claim wrong or unsupported, followed by two appendices.\n` + + `Appendix A, Challenged claims: one row per point a lens raised against a [C] claim or against something ` + + `untagged: claim | challenged by (persona and lens) | severity (blocking, major, minor: your call from the ` + + `memo) | status | resolution. Status is upheld (you kept it; say why), revised (you changed it; quote the ` + + `change), withdrawn, or open (the author must decide). Never delete a challenge. Reproduce the memo's Where ` + + `they disagree section and its Conditions to say no verbatim below the table.\n` + + `Appendix B, Premortem: your Required Behavior in subagent form. Write the 2-3 sentence scenario in which ` + + `this shipped on time and did not move the success metric; name the hidden assumption it exposes; add that ` + + `assumption to the Assumptions section; leave the question "What went wrong?" verbatim for the author. ` + + `The next gate asks it.\n` + + `Check your own output against the contract checklist before returning. List every decision you left open ` + + `under openDecisions. Generated ${stamp}, run ${args.runId}. Return the PRD object; prdPath must be '${prdPath}'.`, + { label: 'river:synthesize', phase: 'Synthesize', agentType: 'ck:river', schema: PRD_SCHEMA }, +) +if (!prd) throw new Error('prd-draft: River returned nothing for the synthesis; the draft is at ' + draftPath) + +return { + runId: args.runId, + prdPath: prd.prdPath, + draftPath, + memoPath: panel ? panel.memoPath : null, + lenses: panel ? panel.lenses : [], + validation, + challengedClaims: prd.challengedClaims, + premortem: prd.premortem, + openDecisions: prd.openDecisions, + summary: prd.summary, +} +``` + +## Appendix C. `skills/prd/SKILL.md` + +````markdown +--- +name: prd +description: Write a PRD with River. An intake gate (Three Whys, V0 Challenge), a background draft challenged by the product, marketing, and UX lenses on different models, a premortem gate, then finalize to the path you choose. Launches a paid workflow, so it runs only when you type /ck:prd. +disable-model-invocation: true +argument-hint: "[one-sentence proposal]" +--- + +You are River for the whole of this skill. Read `${CLAUDE_PLUGIN_ROOT}/agents/river.md` for your voice and standards. The subagent form of your behaviors is in that file; the interactive form is here, because this is the one place a user is present. + +Before anything else, confirm the Workflow tool is available in this session. If it is not, stop and say: "Dynamic workflows are not available here (plan, /config, or organization setting). /ck:prd needs them." Do not fall back to running the stages by hand. + +## 0. Resume check + +Run `ls .ck/runs/*/brief.md 2>/dev/null`. For any run directory that has `brief.md` but no `prd-draft.md`, ask with AskUserQuestion: "Resume run `` from ``, or start new?" On resume, read `run.json`; if it has `harnessRunId`, skip to step 3 and relaunch with `resumeFromRunId`; otherwise continue Gate 0 from the last section present in `brief.md`. + +## 1. Gate 0: intake + +Ask one question at a time with AskUserQuestion. **After every answer, append it to `brief.md` under its section heading before asking the next question.** If the run directory does not exist yet, create it first (step 2 shows how; do it as soon as Q1 is answered, using a provisional slug from the proposal). + +### 1. Three Whys + +Do not accept the proposal as the problem. Ask "Why?" up to three times, each answer more specific than the last: + +- Q1 Proposal: "In one or two sentences, what do you want to build?" (skip if `$ARGUMENTS` is given; record it) +- Q2: "Why does that need to exist? What happens to the user today without it?" +- Q3: "Why is [their answer] a problem worth solving now?" +- Q4: "Why [their answer]? What is underneath that?" + +Each of Q2 to Q4 offers two fixed options, "That is the root cause" and "I am solving a symptom and I know it", plus free text. Stop early on either fixed option and record which. + +Then: + +- Q5 User: "Who exactly has this pain? One primary user." Offer options drawn from the answers so far, plus Other. +- Q6 Metric: "What single number moves if this works, by how much, by when? And what leading indicator will you watch?" +- Q7 Non-goals: "Name two or three things this will explicitly not do." + +### 2. V0 Challenge + +Propose a V0 that cuts at least half the requested scope. Say: "Here is a V0 that solves the core problem with half the features: [scope]. It cuts [list]. Would this still move [metric]?" Offer: "Build the V0"; "Build the full scope"; "Full scope, and here is what specifically requires it" (free text). Record the decision and the rationale. + +- Q9 Lenses: "Default panel (River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5), or name lenses and models?" Record as a list of `{persona, lens, model}` or `null`. +- Q10 Output: "Where should the final PRD go?" Default `plans/--prd.md`. + +`brief.md` sections, in this order: Proposal; Root-cause chain; User; Success metric and leading indicator; Scope decision and rationale; Non-goals; Lenses; Output path. + +## 2. Mint the run + +```bash +timestamp=$(date -u +%Y%m%dT%H%M%SZ) +runId="${timestamp}-" +runDir="$(pwd)/.ck/runs/${runId}" +mkdir -p "$runDir" +grep -qxF '.ck/' .git/info/exclude 2>/dev/null || echo '.ck/' >> .git/info/exclude +``` + +Write `run.json`: `{ "runId", "createdAt": timestamp, "status": "gate-0", "outputPath", "lenses" }`. Tell the user once: `.ck/` is excluded from git locally; the final PRD is not. + +## 3. Launch the draft and wait + +Call the Workflow tool exactly like this: + +``` +Workflow({ + scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/prd-draft.js", + args: { + runId: "", runDir: "", pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp: "", + briefPath: "/brief.md", lenses: + } +}) +``` + +Immediately write the returned run id into `run.json` as `harnessRunId`, with `scriptPath`, and set `status` to `drafting`. Tell the user the draft is running in the background and that `/workflows` shows progress. Then stop. Wait for the task notification. Do not poll, do not narrate, do not start other work on this run. + +If the notification reports a stop or a failure, offer to relaunch: `Workflow({ scriptPath: "", resumeFromRunId: "" })`. Completed agents replay from cache. + +## 4. Gate 1: review + +Read `/prd-draft.md`. Show, in this order: the summary; the Challenged claims table (Appendix A); the open decisions; the premortem scenario from Appendix B, verbatim. + +### 3. Premortem + +Ask, with AskUserQuestion: "What went wrong?" Options: "The metric was wrong"; "The user was not who we thought"; "Scope crept"; plus free text. Use the answer to surface the hidden assumption; do not argue with it. + +Then ask: "Accept, edit named sections, or re-run the panel on named sections?" Options: Accept; Edit: ...; Re-run the panel on: ... Write the premortem answer, the edits, and a decision for each open item to `/gate-1.md`. + +On re-run: `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp: "", question: "", contextPath: "/prd-draft.md", lenses } })`, record its run id in `run.json`, wait for the notification, and return to the top of this gate. + +## 5. Finalize + +One agent, inline: + +``` +Agent({ + subagent_type: "ck:river", + description: "Finalize PRD", + prompt: "Read /prd-draft.md and /gate-1.md. Fold the premortem answer into Assumptions and Risks, apply the requested edits, resolve each open decision as answered, keep Appendix A intact. Write the final PRD to . Set status 'final' in /run.json. Return the path and a five-line summary." +}) +``` + +Print the output path and the run directory. Suggest `/devlog` for the decision memo if the user has the devlog skill. +```` + +## Appendix D. `skills/prd-artifact/SKILL.md` + +````markdown +--- +name: prd-artifact +description: The Code Katz PRD contract: section order, required fields, and the checklist a PRD must pass. Load when writing, revising, or validating a PRD, inside or outside a ck workflow. +user-invocable: false +--- + +# The PRD contract + +A PRD written to this contract has the same shape every time, in every project. Consistency comes from this file, not from who writes it. + +## Section order + +Use these headings verbatim, in this order. + +1. `## Summary`: three sentences: what, for whom, and the one number that says it worked. +2. `## Problem`: the user pain, not the solution. Cite the root-cause chain (solution → why → why → why) and say whether it reached a root cause or a known symptom. +3. `## User`: one primary user, specific enough to recognize. +4. `## Success metric and leading indicator`: one number, a target, a date; one leading indicator. +5. `## Scope`: the decision taken (V0 or full, with rationale) and the V0 counter-proposal: what it keeps, what it cuts, whether it would still move the metric. +6. `## Non-goals`: at least two, each a thing this will explicitly not do. +7. `## Requirements`: numbered. Each has at least one acceptance criterion a reader could verify without asking the author. +8. `## Sequencing and dependencies`: what must be true before this can ship; what depends on what. +9. `## Assumptions`: every assumption the document rests on, including the one the premortem exposed. +10. `## Risks`: what would cause this to fail, with a mitigation or an explicit acceptance. +11. `## Open questions`: every decision left to the author. +12. `## Appendix A. Challenged claims`: claim | challenged by | severity | status | resolution. Nothing deleted. +13. `## Appendix B. Premortem`: the scenario, the exposed assumption, and the question "What went wrong?" verbatim. + +## Claim tags + +Every claim not taken directly from the brief carries an inline tag `[C1]`, `[C2]`, ... in the body. Appendix A addresses tags by id. A tag no lens challenged is listed there as unchallenged. + +## File path + +Default `plans/--prd.md`, next to the archived plans. The author may choose another path at Gate 0. + +## Checklist + +A validator checks each item by reading. Each is a statement that is true or false. + +1. Every section above is present, in order, with its heading verbatim. +2. Problem names the user pain, not the solution, and cites the root-cause chain. +3. Success metric is one number with a target and a date, plus one leading indicator. +4. Scope records the V0 or full decision and the V0 counter-proposal with what it cuts. +5. Non-goals has at least two entries. +6. Every requirement has at least one acceptance criterion a reader could verify without asking the author. +7. Every claim not from the brief carries a `[C]` tag, and every tag appears in Appendix A or is marked unchallenged. +8. Assumptions includes the assumption the premortem exposed (or, before the premortem exists, says the premortem is pending). +9. Open questions lists every decision left to the author. +10. No em-dashes in prose. Em-dashes are acceptable only as separators in structured lists. + +## Writing + +Plain technical English: name the actor, one instruction per sentence, no filler, no loss of precision. Second person is fine for the user; third person for the system. +```` + +## Appendix E. `agents/river.md` as generated (excerpt) + +```markdown +--- +name: river +description: River, Product Manager. Reviews and drafts from the product manager perspective for ck panels and delegation; returns structured findings. +model: claude-opus-5 +--- + + + +# River — Product Manager + +[body verbatim from upstream/profiles/river.md through "## How You Communicate"] + +## Required Behaviors (subagent form) + +You are running with no user present. Every behavior below still applies, in output form. Where a behavior tells you to ask, halt, interrupt, or require an answer before proceeding: do not stop. State the question verbatim under `questions` (addressed to `author` or to a named teammate), state the assumption you will proceed on, and proceed. Where a behavior produces an artifact (table, diagram, scenario, counter-proposal, pitch), produce it in full. Where it requires a decision from the user, give your recommendation with evidence and mark the decision as open. + +### 1. Three Whys +[verbatim] + +### 2. V0 Challenge +[verbatim] + +### 3. Premortem +[verbatim] + +## Handoff Brief +[verbatim] + +## Signature Question +[verbatim] + +--- + +You are running as a delegated subagent. When the prompt names a run directory, read inputs from it and write outputs only there. If a schema is imposed, fill every required field; anything you would have asked goes in `questions`. Return findings first, detail after. +``` + +The `model` line shows the value after the team-cli tiers PR (§8.4). Before that PR it reads `claude-fable-5`, verbatim from today's `tiers.conf`. + +## Appendix F. Cost model + +Prices per million tokens from the pricing page read 2026-09-05 [D]: Fable 5.1 $10 in / $50 out; Opus 5 $5 / $25; Sonnet 5 $2 / $10; Haiku 4.5 $1 / $5. Token counts are assumptions [P] for a one-page context document; the newer tokenizer produces about 30% more tokens than these figures assume [D]. No prompt-cache sharing between lenses (§3.3 item 15). Neutral agents assumed on Opus 5 (the session model). + +### `/ck:panel` + +| Agent | Model | Input | Output | Cost | +|---|---|---|---|---| +| river (product) | Opus 5 | 16k | 3k | $0.16 | +| toni (marketing) | Fable 5.1 | 16k | 3k | $0.31 | +| kai (ux) | Sonnet 5 | 16k | 3k | $0.06 | +| synthesis | Opus 5 | 20k | 4k | $0.20 | +| **Total** | | | | **about $0.73** | + +### `/ck:prd` (the `prd-draft` workflow) + +| Agent | Model | Input | Output | Cost | +|---|---|---|---|---| +| river draft | Opus 5 | 20k | 8k | $0.30 | +| validator | Haiku 4.5 | 15k | 1k | $0.02 | +| panel (above) | mixed | | | $0.73 | +| river synthesize | Opus 5 | 35k | 10k | $0.43 | +| **Total, no revision** | | | | **about $1.48** | +| one revision (validator again plus River revise) | | | | + about $0.32 | +| finalize (inline, Opus 5) | | 30k | 8k | + about $0.35 | + +Call it $1.50 to $2.20 per PRD plus the main session's own gate turns. Concurrency: min(16, CPUs minus 2) [D]; on a 4-CPU laptop the panel runs in one round and `prd-draft` in about four sequential steps, since its stages depend on each other. + +## Appendix G. Sources + +Documentation, verified 2026-09-05: + +- Dynamic workflows: https://code.claude.com/docs/en/workflows +- Subagents: https://code.claude.com/docs/en/sub-agents +- Plugins reference: https://code.claude.com/docs/en/plugins-reference +- Plugin marketplaces: https://code.claude.com/docs/en/plugin-marketplaces +- Hooks: https://code.claude.com/docs/en/hooks +- Skills: https://code.claude.com/docs/en/skills +- Pricing: https://platform.claude.com/docs/en/about-claude/pricing + +Family record [R]: + +- `claude-team-cli`: `ROADMAP.md` revision history (2026-07-29, 2026-07-31), `DEVLOG.md` (2026-09-04 entries), `scripts/generate-agents.sh`, `profiles/tiers.conf`, `tests/run.sh` +- `claude-conductor`: `DEVLOG.md` (2026-07-04), `docs/2026-07-03-fable-harness-modernization-analysis.md`, `docs/2026-07-04-agent-teams-spike.md`, branch `claude/research-desktop-tile-updates-BJqoP` +- `claude-plugins`: `.claude-plugin/marketplace.json` v1.3.0 + +Research [M], [V]: as listed in the proposal's §10; this PRD adds none. From f0c2234e059eae919cf2d2e7e12f7bd453f0c526 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 7 Sep 2026 18:03:29 +0000 Subject: [PATCH 02/14] plans: revise ck PRD after a cross-model panel; add the panel memo and Opus inputs Fable took the engineering lens from Will's panel brief and reviewed the Opus-written PRD, its brief, and its workbench mockups against the docs and the repos. The ck PRD stays the base; nine changes are ported from the Opus PRD and eleven of its claims are rejected with reasons, recorded in plans/2026-09-05-ck-prd-panel-memo.md. Adopted: a users table and journey for the harder user, with three failure rules and a done criterion; /ck:brief before /ck:prd with an optional interview; the artifact is the state (docs/brief.md, docs/PRD.md, docs/decisions/) and the run directory is a cache with start-at resume; per-lens evidence and a two-pass read of the rationale in the panel; effort set per workflow stage; a Phase 0 of six spikes; /ck:next in phase one; persona scopes as the shape of the 90-day prune; a goals table. Will's rule for feedback, review pages with comments and mockups as labeled variants, is now section 4.9 and the review path of /ck:prd. Rejected with reasons: no workflow() primitive (it exists); pausing a workflow to arbitrate (no mid-run input); quota fallback via PreModelSwitch (fires on a requested session switch only); Stop/TaskCompleted gates; the Phase 1 vs Phase 5 team-cli retirement contradiction; 22 personas; retiring TODOS.md; maxBudgetUsd; editing the installed plugin copy; commands/ for switches; cache replay across sessions. Appendices now carry three workflow scripts (syntax-checked as the runtime runs them), three skills, the two-part contract, the River excerpt, a cost model, and sources. The Opus inputs are committed verbatim under plans/opus/. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014aqcjmXas9EFDx3pstfpyE --- DEVLOG.md | 30 + plans/2026-09-05-ck-plugin-prd-phase-1.md | 1111 +++++++++++------ plans/2026-09-05-ck-prd-panel-memo.md | 94 ++ plans/opus/2026-09-05-panel-review-brief.md | 174 +++ plans/opus/2026-09-05-prd-code-katz.md | 434 +++++++ plans/opus/2026-09-05-workbench-concepts.html | 810 ++++++++++++ 6 files changed, 2274 insertions(+), 379 deletions(-) create mode 100644 plans/2026-09-05-ck-prd-panel-memo.md create mode 100644 plans/opus/2026-09-05-panel-review-brief.md create mode 100644 plans/opus/2026-09-05-prd-code-katz.md create mode 100644 plans/opus/2026-09-05-workbench-concepts.html diff --git a/DEVLOG.md b/DEVLOG.md index 85bd8f5..de4cb6f 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -5,6 +5,36 @@ Auto-maintained via [claude-devlog-skill](https://github.com/code-katz/claude-de --- +## [2026-09-05] `ck` PRD revised after a cross-model panel: nine changes adopted, eleven rejected with reasons; review pages become the feedback channel + +**Category:** `decision` +**Tags:** `ck`, `prd`, `panel`, `cross-model-review`, `user-2`, `review-pages` +**Risk Level:** `medium` +**Breaking Change:** `no` + +### Summary +Will shared a PRD for the same plugin written by Opus, with a hand-run panel brief and five workbench mockups. Fable took the brief's engineering lens and verified the Opus PRD's load-bearing claims against the docs and the repos. Result: the `ck` PRD stays the base; nine changes are ported from the Opus PRD; eleven of its claims are rejected with the reason recorded. Will's new rule for feedback (review pages with comments; mockups as labeled variants) is written into the PRD. Record: `plans/2026-09-05-ck-prd-panel-memo.md`. + +### Detail + +- **Biggest finding against the `ck` PRD:** it named Will's wife as customer zero and then designed for Will (a ten-question interview, model names in a prompt, a hidden run directory). The Opus PRD made her the harder constraint. The `ck` PRD now has a users table, her journey, three failure rules (no stack trace, model name, or token count; always name the file holding the work; always one next action), and a done criterion: she produces a PRD on a new project without a text editor or `.ck/`. +- **Shape changes:** `/ck:brief` added before `/ck:prd`; the interview is optional; the review is a page with comments or a file edit; documents live at fixed committed paths (`docs/brief.md`, `docs/PRD.md`, `docs/decisions/`); the run directory is a cache; workflows accept a start-at stage; `/ck:next` promoted to phase one; a Phase 0 of six spikes; each panel lens reads its own evidence and sees the author's rationale only after forming a view; effort is set per workflow stage, never per persona. +- **Verified errors in the Opus PRD:** it says workflows cannot call workflows (they can, one level); it pauses a running workflow to ask about escalation (workflows accept no mid-run input, and its own principle P6 says so); its quota fallback hangs on a hook that fires only on a requested session model switch; its gates use the wrong hook for subagents; it retires team-cli at Phase 1 in one place and Phase 5 in another; it counts 22 personas (21); it retires `TODOS.md`, a shipped plugin; its workbench edits the installed plugin copy, which updates overwrite; it ignores conductor's existing cost parser. +- **Panel health:** one lens ran, so no agreement rate. The memo follows the brief's format anyway so the gaps show. + +### Decisions Made +- **Base document: the `ck` PRD.** Engineering-complete, verified, family-aware. Product thinking ported from Opus. +- **The artifact is the state.** Fixed, conventional, committed paths; the plugin keeps nothing the deliverable depends on. +- **Review pages are the feedback channel** (Will's rule). A private page with comments per review; Claude holds and resolves every comment after "done"; mockups as labeled variants side by side; a file-edit path always remains. +- **`PreModelSwitch` arbitration: answered no.** Recorded as Phase 0 spike S6 with the docs citation, so it is not re-litigated. + +### Related +- Panel memo: `plans/2026-09-05-ck-prd-panel-memo.md` +- Opus inputs, verbatim: `plans/opus/` +- Revised PRD: `plans/2026-09-05-ck-plugin-prd-phase-1.md` + +--- + ## [2026-09-05] `ck` plugin phase-one PRD: gates in skills, spans in workflows, no UI yet **Category:** `decision` diff --git a/plans/2026-09-05-ck-plugin-prd-phase-1.md b/plans/2026-09-05-ck-plugin-prd-phase-1.md index e025c41..bf15ed3 100644 --- a/plans/2026-09-05-ck-plugin-prd-phase-1.md +++ b/plans/2026-09-05-ck-plugin-prd-phase-1.md @@ -5,7 +5,8 @@ > **Author:** Fable (with Will Curran) > **Derives from:** [`plans/2026-09-05-agent-workflows-research-and-proposal.md`](2026-09-05-agent-workflows-research-and-proposal.md) (the research proposal) > **Supersedes:** the marketplace-retired decision in `claude-team-cli` (2026-07-31), for `ck` only; see §3.1 -> **Scope:** phase one only: plugin skeleton, `/ck:prd` and `/ck:panel` end to end, 21 personas as subagents on the §5.6 tiers. Everything else is in §10 +> **Scope:** phase one only: plugin skeleton, `/ck:brief`, `/ck:prd`, `/ck:panel`, and `/ck:next` end to end, 21 personas as subagents on the §5.6 tiers. Everything else is in §10 +> **Revised:** 2026-09-05, after a cross-model panel against the Opus-written PRD; see [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md) --- @@ -17,7 +18,7 @@ Every claim carries the proposal's grade, plus one more: | Grade | Meaning | |---|---| -| **[D]** | Product documentation, verified against the primary source on 2026-09-05. The URL is in Appendix G | +| **[D]** | Product documentation, verified against the primary source on 2026-09-05. The URL is in Appendix I | | **[M]** | Measured, independent, method stated (carried over from the proposal) | | **[V]** | Vendor self-measured | | **[R]** | The family's own record: a devlog entry, roadmap revision, or test in a code-katz repo | @@ -30,7 +31,7 @@ The proposal is a research summary with a proposed shape. This is the specificat ### 0.3 The three answers up front 1. **It is a plugin.** Claude Code is the runtime for subagents, workflow scripts, and skills; nothing else can run them. No UI ships in phase one. The catalog view is a phase-two command that renders from files. A workbench is phase three, only if the files-as-workbench proves insufficient, and never a hosted app with its own store of definitions. See §4.7. -2. **The skill owns the gates; each span between gates is one workflow.** A sign-off point is not a workflow. It is a gate, and a gate can only live in the main session, because `AskUserQuestion` is removed from every subagent and a workflow cannot pause for input. See §4.2. +2. **The skill owns the gates; each span between gates is one workflow.** A sign-off point is not a workflow. It is a gate: a review page with comments, a file the author edits, or, for Will, an interview. Gates live in the main session, because a workflow cannot pause for input and subagents cannot ask. See §4.2 and §4.9. 3. **`ck` coexists with `claude-team-cli`.** Phase one is additive. The three handoff routes survive: switch this session (team-cli), delegate one task (`ck:`), open a separate session (team-cli). Retirement is revisited at 90 days with usage data. See §8.6. --- @@ -42,42 +43,67 @@ The proposal is a research summary with a proposed shape. This is the specificat | Component | Count | What it is | |---|---|---| | Persona subagents | 21 | `agents/.md`, generated from `claude-team-cli` profiles, registered as `ck:`, model from the §5.6 tiers | -| Workflows | 2 | `/ck:panel` (three lenses on different models, one decision memo) and `/ck:prd-draft` (River drafts, a validator checks, the panel challenges, River synthesizes) | -| Skills | 2 | `/ck:prd` (the interactive entry point that owns both gates) and `prd-artifact` (the PRD contract: template, required fields, checklist) | +| Workflows | 3 | `/ck:brief` (River writes the brief from one sentence), `/ck:panel` (three lenses on different models and different evidence, one decision memo), and `/ck:prd-draft` (River drafts, a checker validates, the panel challenges, River rewrites) | +| Skills | 3 | `/ck:prd` (the entry point that owns the review before and after the draft), `/ck:next` (says what to run next in one sentence), and `prd-artifact` (the contract for the brief and the PRD: template, required fields, checklist) | | Hooks | 1 | `SubagentStart` on `^ck:` appending one line per persona invocation to a usage log, so the 90-day prune has data | -| Tests | 1 suite | Manifest, drift against the pinned upstream, script lint, end-to-end drill | +| Tests | 1 suite | Manifest, drift against the pinned upstream, script lint, user-2 wording, Phase 0 answers, end-to-end drills | -Everything in the proposal's §5.3 catalog beyond these two commands, the hook-based gates, the model fallback chain, the Advisor tool, Routines, folding in the five artifact skills, persona switch skills, `/ck:map`, and any workbench are deferred with reasons in §10. +Revised on 2026-09-05 after a cross-model panel against the Opus-written PRD: nine changes adopted and eleven rejected, each with a reason, recorded in [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md). + +Everything in the proposal's §5.3 catalog beyond these commands, the hook-based gates, the model fallback chain, the Advisor tool, Routines, folding in the five artifact skills, persona switch skills, `/ck:map`, and any workbench are deferred with reasons in §10. --- -## 2. Problem, user, outcome +## 2. Problem, users, journey, goals ### 2.1 Problem -The unit of Will's work is the workflow, not the roster (proposal §2.1). Today the personas exist only as session takeovers and delegation subagents. They own no artifacts, so their output varies run to run (proposal §3.4). Multi-lens input on a decision requires opening three sessions by hand, and the three lenses run on one model, which is one opinion in three costumes (proposal §3.4, [M] error correlation rises with capability). Nothing is repeatable across projects, and nothing is measured, so the 22-persona question ("likely 15 more than are used", proposal §7) cannot be answered. - -### 2.2 User +The unit of Will's work is the workflow, not the roster (proposal §2.1). Today the personas exist only as session takeovers and delegation subagents. They own no artifacts, so their output varies run to run (proposal §3.4). Multi-lens input on a decision requires opening three sessions by hand, and the three lenses run on one model, which is one opinion in three costumes (proposal §3.4, [M] error correlation rises with capability). Nothing is repeatable across projects, and nothing is measured, so the persona question ("likely 15 more than are used", proposal §7) cannot be answered. -Customer zero: Will and his wife, building and maintaining real products (proposal §2, goal 3). The core requirement is team members that behave consistently, starting a product from an opportunity exploration, then a PRD, then a brand guide. Phase one covers the PRD step and the decision panel that every step uses. +### 2.2 Users -### 2.3 Success metrics +Adapted from the Opus PRD §3, which made the harder user the first-class one. Where the two conflict, she wins and Will gets an escape hatch. -| Metric | Target | How measured | +| | Will | Will's wife | |---|---|---| -| Both commands run end to end on a real project | Before the phase-one release is tagged | The end-to-end drill in §9, run by hand on one of Will's projects, with the files listed in §6.9 and §7.10 present | -| Retention (proposal §3.4: the real metric for a personal tool) | At 30 days after install, at least one `/ck:prd` or `/ck:panel` run per week of active building | `${CLAUDE_PLUGIN_DATA}/usage.jsonl`, §5.5 | -| The panel disagrees | In more than half of panel runs, at least one lens recommends differently from the others, or at least one condition-to-say-no is unmet by the material | `panelFailedToDisagree` in each `decision-memo.md` | -| Leading indicator | Usage log entries in the first week | `usage.jsonl` | +| Technical? | Yes. Reads and writes code, comfortable in files and the terminal | No. Has shipped several iOS apps with Claude and claude-team-cli | +| Wants | Repeatability, adversarial input on decisions, visibility into cost and activity, a place to tune personas | To say what she wants in her own words and get a good document back | +| Tolerates | Several commands, flags, JavaScript, terminal output, cost decisions | One command at a time, plain language, no model names, no token counts | +| Fails when | The tool is slower than doing it himself | A command errors and she cannot tell what to do next | + +### 2.3 Journey J1: Will's wife starts a new product + +The primary journey. Phase one is done when this works without her opening a text editor or a hidden directory. + +1. She has an idea. She creates a folder and opens Claude Code in it. +2. She types `/ck:` and sees the commands. She does not know where to start, so she runs `/ck:next`. It sees an empty project and says: "Start with `/ck:brief` and describe your idea in a sentence. It takes about a minute and writes `docs/brief.md`." +3. She runs `/ck:brief An app that reminds you to water each plant on its own schedule`. River writes the brief: the problem and the chain of whys behind it, the user, one success number, the scope with a smaller first version, and what it will not do. A checker confirms the shape. `docs/brief.md` appears with a short list of questions River could not answer for her. +4. She reads it. The user is not quite right. She either edits the file and saves, or, when the review page is available, opens the page and leaves a comment on the line. No approval screen, no command. +5. `/ck:next` now says: "Run `/ck:prd`. It turns the brief into full requirements and takes a few minutes." She runs it. It reads her edited brief. A draft is written and checked, three specialists argue about it on three different models, and River revises it. `docs/PRD.md` appears. +6. She gets a review page for `docs/PRD.md` with a short question at the top: "Imagine this shipped and did not move the number. What went wrong?" She comments where she disagrees, answers the question in a comment, and says "done". Claude works through every comment, changes the document, and marks each comment resolved with one line saying what changed. Without the review page she edits the file and runs `/ck:prd` again. +7. `/ck:next` suggests what comes next. + +What she never does: choose a model, learn what a subagent is, sequence the stages herself, approve or reject anything in a form, or see a token count. -A panel that always agrees is a failed panel (proposal §5.5). If the disagreement rate is low, the lenses or the question template are wrong, not the users. +### 2.4 Goals and measures -### 2.4 Non-goals for phase one +| # | Goal | Measure | Source | +|---|---|---|---| +| G1 | Consistency: the same stage produces the same document shape every time | Two PRDs from two projects have identical section structure; the validator passes on both | The contract checklist (§7.8) | +| G2 | Repeatability: the stages ship with every project | A fresh project has every phase-one command after one install | The install drill (§9) | +| G3 | Adversarial input: real disagreement on a judgment call | In more than half of panel runs, at least one lens recommends differently, or at least one kill condition is met | `panelFailedToDisagree` and `agreementRate` in each memo | +| G4 | The harder user succeeds | J1 completes on a new project without a text editor or a hidden directory | The user-2 drill (§9) | +| G5 | Retention (proposal §3.4: the real metric for a personal tool) | At 30 days after install, at least one `/ck:prd`, `/ck:brief`, or `/ck:panel` run per week of active building | `${CLAUDE_PLUGIN_DATA}/usage.jsonl` (§5.5) | +| G6 | Instrumented: the persona question can be answered at 90 days | Every persona invocation is logged with its type and session | The same log | + +Leading indicator: usage log entries in the first week. A panel that always agrees is a failed panel (proposal §5.5); if G3 is missed, the lenses or the question template are wrong, not the users. + +### 2.5 Non-goals for phase one -- No workflow other than `panel` and `prd-draft`. The catalog in proposal §5.3 is phase two. +- No workflow other than `brief`, `panel`, and `prd-draft`. The rest of the catalog in proposal §5.3 is phase two. - No UI, dashboard, map, or workbench. `/workflows` is the run view (proposal §9, [D]). - No retirement of `claude-team-cli`, no persona switch skills (`/ck:river`), no CLI in `bin/`. -- No hook-enforced artifact gates, no model fallback chain, no Advisor tool, no Routines. +- No hook-enforced artifact gates, no model fallback chain, no Advisor tool, no Routines, no mid-run arbitration (workflows cannot pause; §4.2). - No persona pruning. All 21 port; the instrument ships; the cut list follows the data. - No changes to the persona text. Profiles stay upstream; `ck` transforms them mechanically. @@ -100,8 +126,8 @@ A panel that always agrees is a failed panel (proposal §5.5). If the disagreeme | # | Question (proposal §8) | Decision | Grade | |---|---|---|---| | 1 | Retire or coexist? | **Coexist.** `ck` is additive. team-cli keeps switch commands, coordinator, `launch`, `session`, `install.sh`. The three routes survive (§8.6). Revisit at 90 days with `usage.jsonl` | [P] | -| 2 | Workflow granularity vs sign-off | **The skill owns the gates; each span between gates that needs fan-out or verification is one workflow; a single-agent span runs inline via the Agent tool.** `/ck:prd` is a skill: Gate 0 → `prd-draft` workflow → Gate 1 → inline finalize. `/ck:panel` is a pure workflow: inputs are args, output is a memo, no gate. Full rule and the failure modes it must survive: §4.2, §4.3 | [D]-backed | -| 3 | Where artifacts live | **Final artifacts follow the family's convention per artifact type, committed.** A PRD defaults to `plans/--prd.md`, the location the plans skill already indexes and where this PRD itself lives; overridable at Gate 0. Run intermediates live under `.ck/runs//`, excluded via `.git/info/exclude`; a memo worth keeping is promoted with `/devlog`. The plugin never edits the user's `.gitignore` | [P] | +| 2 | Workflow granularity vs sign-off | **The skill owns the gates; each span between gates that needs fan-out or verification is one workflow; a single-agent span runs inline via the Agent tool.** `/ck:prd` is a skill: the brief (from `/ck:brief`, or an optional interview) → `prd-draft` workflow → review (a page with comments, or a file edit) → inline finalize. `/ck:panel` and `/ck:brief` are pure workflows: inputs are args, output is a document, no gate. Full rule and the failure modes it must survive: §4.2, §4.3 | [D]-backed | +| 3 | Where artifacts live | **The artifact is the state** (adopted from the Opus PRD §7.9). Deliverables live at fixed, conventional, committed paths: `docs/brief.md`, `docs/PRD.md`, `docs/decisions/-.md`, overridable by argument. `.ck/runs//` is a cache (per-lens JSON, the harness run id), locally excluded via `.git/info/exclude`; nothing depends on it. Resume works from which documents exist plus a start-at stage (§4.3). The plugin never edits the user's `.gitignore` | [P] | | 4 | Which personas survive? | **All 21 port now; prune at 90 days on evidence.** The port is generated, so carrying 21 costs nothing. No usage data exists, so a cut list today is a guess. The instrument ships in phase one (§5.5). This contradicts proposal §8.4 and agrees with proposal §7 | [P] | | 5 | Panel model assignment | **River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5 by default,** overridable per run. `panel.js` is the one script allowed to set `model` on a persona agent, because per-invocation model beats frontmatter [D] and decorrelation is the point. The memo header states the limitation: one training pipeline, partial decorrelation. A lens that dies on an API error returns `null`; the memo runs on the survivors and says so | [P] | | 6 | `/ck:feature` scope | **Deferred to phase two.** Both options recorded in §10.2 | deferred | @@ -126,10 +152,12 @@ Each item names the proposal section, what is wrong, and what this PRD does inst 12. **§4.2, `maxBudgetUsd`.** Not in the subagent frontmatter table read today [D]. Not relied on. 13. **§9, the superseded plan.** `claude-conductor/plans/2026-09-04-agent-coordination-engine.md` is on no branch of that repo. Commit it, so the supersession is traceable. 14. **§5.2, the persona layer.** "Voice, domain constraints, model tier" omits that a subagent has no user to ask. Every persona's `## Required Interactive Behaviors` is written as questions to the user; unrewritten, it is dead text or a stall. §5.4 has the transform. -15. **§4.1, fan-out cache economics.** The prompt-cache sharing described there applies to agents matching on model, effort, agent type, tools, schema, and cwd [D]. A persona panel is three agent types on three models and shares nothing. The cost model in Appendix F assumes no sharing. +15. **§4.1, fan-out cache economics.** The prompt-cache sharing described there applies to agents matching on model, effort, agent type, tools, schema, and cwd [D]. A persona panel is three agent types on three models and shares nothing. The cost model in Appendix H assumes no sharing. What the proposal gets right and this PRD keeps unchanged: §3 (topology, not persona strings, is the lever; buy quality with a different model and a real oracle), §4.3 (Agent Teams is not the executor), §5.2 (the four layers), §5.5 (forced self-disagreement; three approvals is a failed panel), §6 (the not-building list), §7 (the honest assessment), §9 (the UI stance). +A second review, against the PRD Opus wrote from the same proposal, produced nine changes adopted into this document and eleven rejections. The Opus PRD's own errors, verified against the docs, and the reason for each rejection are in [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md). The largest change: this document had named Will's wife as customer zero and then designed for Will. §2.2, §2.3, §4.8, and the file-edit path in §7.6 exist because the Opus PRD made her the harder constraint. + --- ## 4. Architecture @@ -141,7 +169,7 @@ What the proposal gets right and this PRD keeps unchanged: §3 (topology, not pe | Workflow | `workflows/*.js` | The order of stages, outside the conversation | `panel.js`, `prd-draft.js` | | Persona | `agents/*.md` | Voice, domain constraints, default model tier | 21 generated files, `ck:` | | Artifact | `skills/*/SKILL.md` | Output template, required fields, checklist | `prd-artifact` | -| Gate | The skill in the main session | Sign-off, using `AskUserQuestion`; plus schema-forced output and a validator agent inside the workflow | `prd` (Gate 0, Gate 1); `panel.js` and `prd-draft.js` schemas | +| Gate | The skill in the main session | Sign-off: a review page with comments, a file edit, or the optional interview; plus schema-forced output and a validator agent inside the workflow | `prd` (the brief check and the review); the validators in `brief.js` and `prd-draft.js` | The proposal put the gate layer in `hooks/hooks.json`. Phase one puts human gates in the skill and machine gates in the scripts (§3.3 item 7). The hook that does ship is instrumentation, not enforcement. @@ -151,7 +179,7 @@ The docs: "No mid-run user input. Only agent permission prompts can pause a run. Therefore: -1. A sign-off is a **gate**. A gate runs in the main session, inside a skill, with `AskUserQuestion`. +1. A sign-off is a **gate**. A gate runs in the main session, inside a skill: a review page with comments (§4.9), a file the author edits and re-runs, or, optionally, an interview with `AskUserQuestion`. 2. The span between two gates is a **workflow** when it needs fan-out, structured output, or resume. A span that is one agent runs inline through the Agent tool; a workflow for one agent buys nothing. 3. A workflow never contains a decision point. A skill never fans out by hand. 4. A skill or slash command whose instructions say to call Workflow is explicit opt-in [D]; no `ultracode` keyword, no "use a workflow" phrase is needed. @@ -160,19 +188,26 @@ Rejected alternatives: one workflow per persona action (the skill would orchestr What would make the rule wrong: subagents regaining `AskUserQuestion`, or workflows gaining a pause primitive. Neither is on the record. -### 4.3 Run directory contract +### 4.3 Artifacts are the state; the run directory is a cache + +Adopted from the Opus PRD §7.9. The deliverables outlive the tool, so they live at plain, committed paths, and the plugin keeps no private state that anything depends on. -Every run has an id and a directory. The skill mints both; workflows receive them in `args`; agents do all reading and writing under the directory (the script has no filesystem access [D]). +| Artifact | Path | Written by | Committed | +|---|---|---|---| +| Brief | `docs/brief.md` | `/ck:brief`, or the optional interview in `/ck:prd` | Yes | +| PRD | `docs/PRD.md` | `/ck:prd` (written progressively by the `prd-draft` stages, then finalized) | Yes | +| Decision memo | `docs/decisions/-.md` | `/ck:panel`, and the nested panel inside `prd-draft` | Yes | + +Paths are overridable by argument. `docs/` is the Opus convention; the family's root-level files (`ROADMAP.md`, `DEVLOG.md`) are unchanged. + +The run directory is a cache. It holds what a fresh session might want but nothing the deliverable depends on: ``` .ck/runs// -├── run.json { runId, createdAt, status, outputPath, lenses, harnessRunId, scriptPath } -├── brief.md Gate 0 output, appended answer by answer -├── draft-v0.md River's first draft (prd-draft) -├── prd-draft.md River's synthesis after the panel (prd-draft) +├── run.json { runId, createdAt, status, stage, outputPath, lenses, harnessRunId, scriptPath } +├── interview.md the optional interview's answers, appended one at a time ├── panel/.json one file per lens -├── decision-memo.md the panel's synthesis -└── gate-1.md Gate 1 answers and edits (prd) +└── gate-1.md review-page comments or file edits, as applied ``` Rules, each of which closes a failure mode found in review: @@ -181,33 +216,37 @@ Rules, each of which closes a failure mode found in review: |---|---| | `run-id` is `-`, minted by the skill with `date -u`; workflows receive `timestamp` in `args` because `Date.now()` throws in scripts [D] | Non-deterministic scripts break resume | | `runDir` is passed **absolute** in `args` | Subagents inherit the session cwd; a user in a subdirectory would get `.ck/` in the wrong place | -| The skill appends each Gate 0 answer to `brief.md` as it is given, and on entry offers to resume any run with a `brief.md` but no `prd-draft.md` | Compaction in the middle of Three Whys loses the answers | -| The skill writes the Workflow tool's own run id into `run.json` as `harnessRunId` before it waits | Without it, a compacted or `--resume`d session cannot `resumeFromRunId` and re-runs the workflow at full cost | -| The skill adds `.ck/` to `.git/info/exclude` on first use, never to `.gitignore` | team-cli's `session done` refuses untracked files [R, tests/run.sh]; a run inside a session worktree would block closing it | +| Every workflow accepts `args.startAt` and skips completed stages; the skill decides `startAt` by which artifacts exist | A fresh session cannot replay the harness cache [D]; the file on disk is what survives | +| The optional interview appends each answer to `interview.md` as it is given, and the skill offers to resume an interview that has answers but no brief | Compaction in the middle of the interview loses the answers | +| The skill writes the Workflow tool's own run id into `run.json` as `harnessRunId` before it waits | Within a session, `resumeFromRunId` replays completed agents at no cost [D] | +| The skill adds `.ck/` to `.git/info/exclude` on first use, never to `.gitignore` | team-cli's `session done` refuses untracked files [R]; the cache must not block closing a worktree | | Every agent that writes returns the path it wrote, in its schema | The script cannot check the filesystem; the next stage needs the path | -| Final artifacts are written outside `.ck/` at the path chosen at Gate 0 | Intermediates stay excluded; the deliverable is committed | ### 4.4 Naming - Plugin `name`: `ck`. Everything is `/ck:` or `ck:` [D]. -- Skills: `prd` (user-invocable, `disable-model-invocation: true`), `prd-artifact` (not user-invocable; read by agents and loadable by Claude when writing any PRD). -- Workflows: `panel`, `prd-draft`. A plugin workflow is itself a slash command [D], so `/ck:panel` and `/ck:prd-draft` both appear in autocomplete. `prd-draft` is safe to run directly if a `brief.md` exists; the skill is the supported path. +- Skills: `prd` and `next` (user-invocable, `disable-model-invocation: true`), `prd-artifact` (not user-invocable; read by agents and loadable by Claude when writing any brief or PRD). +- Workflows: `brief`, `panel`, `prd-draft`. A plugin workflow is itself a slash command [D], so `/ck:brief`, `/ck:panel`, and `/ck:prd-draft` all appear in autocomplete. `prd-draft` is safe to run directly if `docs/brief.md` exists; `/ck:prd` is the supported path. - No name is shared between a skill and a workflow, because both occupy `/ck:`. - Agents: `river`, `akira`, ... in frontmatter (no colon allowed [D]); registered as `ck:river`, referenced as `agentType: 'ck:river'` in scripts and `subagent_type: "ck:river"` from the Agent tool. -### 4.5 Model policy +### 4.5 Model policy and the effort axis -| Agent kind | Where the model comes from | Who may override | -|---|---|---| -| Persona agent (`agentType: 'ck:'`) | Frontmatter `model:` from the §5.6 tiers, via `tiers.conf` upstream | `panel.js` only, for lens decorrelation | -| Neutral utility agent (no `agentType`): validator, synthesis | The script sets `model` explicitly for the validator (Haiku 4.5, classification tier); synthesis inherits the session model | The script | -| The main session (gates, finalize) | The user's session model | The user | +Two axes, adopted from the Opus PRD §7.8: the persona sets the model floor; the workflow stage sets the effort. Difficulty belongs to the task, not the persona. + +| Agent kind | Model comes from | Effort comes from | Who may override the model | +|---|---|---|---| +| Persona agent (`agentType: 'ck:'`) | Frontmatter `model:` from the §5.6 tiers, via `tiers.conf` upstream | The script, per stage; omitted means the session's effort | `panel.js` only, for lens decorrelation | +| Neutral utility agent (no `agentType`): validator, synthesis | The script sets `model` for the validator (Haiku 4.5, classification tier); synthesis inherits the session model | The script: validators run at `low` | The script | +| The main session (gates, `/ck:next`, finalize) | The user's session model | The session | The user | + +Precedence is per-invocation → frontmatter → `CLAUDE_CODE_SUBAGENT_MODEL` → session [D]. `agent()` accepts `effort` per call [D]. Persona frontmatter never sets `effort`, so one persona can run a mechanical stage at `low` and a design stage at `xhigh` without a second definition. `/workflows` shows the requested and any substituted model per agent [D]; that is the "resolved model recorded per run" the proposal asks for, at no cost. -Precedence is per-invocation → frontmatter → `CLAUDE_CODE_SUBAGENT_MODEL` → session [D]. `/workflows` shows the requested and any substituted model per agent [D]; that is the "resolved model recorded per run" the proposal asks for, at no cost. +Not in phase one: escalation chains, the Advisor tool, and mid-run arbitration. Workflows cannot pause for input [D], and `PreModelSwitch` fires only on a requested session switch [D], so the escalation design in the Opus PRD §7.8 has no mechanism today. Phase-one resilience is null-tolerant scripts: a stage that fails returns `null`, the script logs it and continues where it can. ### 4.6 What phase one deliberately does not build -Everything in proposal §6, plus: hook-enforced gates, a fallback chain, the Advisor tool, Routines, `/ck:next`, persona switch skills, a `bin/` CLI, any UI. Reasons are in §10. +Everything in proposal §6, plus: hook-enforced gates, a fallback chain, the Advisor tool, Routines, mid-run arbitration, persona switch skills, a `bin/` CLI, any UI. Reasons are in §10. ### 4.7 Plugin, web app, wrapper, or dashboard @@ -219,6 +258,42 @@ Will's question, answered with a recommendation: 4. **The catalog is derivable from files.** Every `ck` workflow declares `phases` and a `personas` list in `meta` (§6.5, §7.5). `meta` is a pure literal [D], so it names the default roster, not a run-time choice. Phase two `/ck:map` emits a Mermaid graph (workflow → phase → persona → tier → model) with one agent and no infrastructure; `/ck:map --run ` draws the per-run graph from `panel/*.json`. GitHub renders Mermaid in Markdown. 5. **If a workbench is ever built**, decide its two halves separately. The *viewer* half reads and never owns; it could be a local page or a published Artifact generated from the plugin's files. The *editor* half must be local, because only a local process can run `generate-agents.sh` and `tests/run.sh` before a commit. The conductor precedent applies: local server plus browser, Tauri dropped [R], Python by preference. Build it only when the files-as-workbench is shown insufficient, which means a specific edit Will could not make in a text editor plus `bump-upstream.sh`. +### 4.8 Failure handling for the harder user + +Adapted from the Opus PRD §7.11. This is a phase-one deliverable, not polish: one bad failure is how user 2 abandons a tool. + +Three rules for every message the skills print: + +1. Never show a stack trace, a model name, or a token count. +2. Always name the file that holds the work completed so far. +3. Always give exactly one next action. + +Three failure classes and what she sees: + +| Failure | What she sees | What she can do | +|---|---|---| +| The checker rejects a draft | "The PRD is missing a success metric. Fixing that section." | Nothing. It self-corrects, up to twice | +| A stage fails after retries | "I couldn't finish the requirements section. Everything up to it is saved in `docs/PRD.md`. Run `/ck:prd` again to continue from there." | Run it again. Completed stages are skipped | +| A panel lens or the whole workflow is unavailable | "One of the three reviewers didn't answer. The memo is based on the other two and says so." or "Claude is at capacity right now. Run `/ck:prd` again in a few minutes." | Wait or retry | + +Will's escape hatch: `/workflows` shows every agent, model, and token count for anyone who wants them. The skills never print them. + + +### 4.9 Review pages: the feedback channel + +Will's rule, recorded 2026-09-05: whenever a workflow produces a document for review, it arrives as a web page he can comment on; whenever there are designs to review, they arrive as mockups with labeled variants side by side, also commentable. That page is how he gives feedback. Claude holds every comment, then works through and resolves all of them once he says he is done. + +Mechanism, verified in this session's tool contract: a published Artifact is a private HTML page on claude.ai; viewers leave comment threads on it; Claude reads the threads, replies on threads a person has sent to Claude, republishes the same URL, and marks each thread resolved. + +Rules: + +1. One page per review, republished in place; never a new URL for a revision. +2. When the author says "done", read every thread, apply each change to the file on disk (the artifact is the state, §4.3), republish, and resolve each thread with one line saying what changed. A comment Claude will not act on gets a reply with the reason and stays open. +3. Mockup pages show labeled variants (A, B, C); the author comments to pick one or ask for changes. +4. Availability is a Phase 0 spike (§8.0, S5). Every gate keeps a file-edit path that works without it. + +Phase one uses this at Gate 1 of `/ck:prd` (§7.6). Mockup review pages arrive with `/ck:brand-guide` in phase two. + --- ## 5. Personas as subagents @@ -314,7 +389,7 @@ What the preamble makes River do, and what `prd-draft.js` asks for by name: | V0 Challenge: propose a V0 cutting half the scope and require a decision | Always include the V0 counter-proposal, what it cuts, whether it would still move the metric, and your recommendation with evidence. The decision stays with the author and is listed as open | | Premortem: write the failure scenario and ask "What went wrong?" | Write the 2-3 sentence scenario in which this shipped on time and missed the metric, name the assumption it exposes, add that assumption to the Assumptions section, and leave the question verbatim for the author's gate | -The interactive versions of River's three behaviors live in `skills/prd/SKILL.md` for Gate 0 and Gate 1, where there is a user. A CI check asserts the skill carries the three behavior headings from `upstream/profiles/river.md`, so a renamed behavior fails the build instead of diverging silently (§9). +The interactive versions of River's three behaviors live in `skills/prd/SKILL.md`, for the optional interview and the review, where there is a user. A CI check asserts the skill carries the three behavior headings from `upstream/profiles/river.md`, so a renamed behavior fails the build instead of diverging silently (§9). ### 5.5 Instrumentation hook @@ -354,13 +429,13 @@ The 90-day review reads this file and answers proposal §8.4. ### 6.1 Purpose -Proposal goal 4: adversarial and complementary input on one decision, from the product lens, the marketing lens, and the UX lens, each on a different model, each forced to argue against itself. The output is a decision memo that shows where the lenses disagree and leaves the decision to the author (proposal §5.5). +Proposal goal 4: adversarial and complementary input on one decision, from the product lens, the marketing lens, and the UX lens, each on a different model, each reading its own evidence, each forced to argue against itself. The output is a decision memo that shows where the lenses disagree and leaves the decision to the author (proposal §5.5). The memo format follows Will's own panel brief: agreement is flagged as low-information, kill conditions are quoted and checked, and unique findings and unchecked areas are listed. ### 6.2 Invocation ``` /ck:panel Should the first release include the branding guide step? -/ck:panel Is this PRD ready for review? --context plans/2026-09-05-thing-prd.md +/ck:panel Is this PRD ready for review? --context docs/PRD.md /ck:panel --lenses river:claude-opus-5,morgan:claude-fable-5-1,sasha:claude-sonnet-5 ``` @@ -373,34 +448,44 @@ Claude passes the invocation as `args` [D]: "pluginRoot": "/abs/path/to/ck", "timestamp": "20260905T210000Z", "question": "Should the first release include the branding guide step?", - "contextPath": "/abs/path/plans/2026-09-05-thing-prd.md", - "lenses": [{ "persona": "river", "lens": "product", "model": "claude-opus-5" }] + "contextPath": "/abs/path/docs/PRD.md", + "rationalePath": "/abs/path/docs/brief.md", + "memoPath": "docs/decisions/20260905T210000Z-branding-step.md", + "lenses": [{ "persona": "river", "lens": "product", "model": "claude-opus-5", "reads": ["docs/PRD.md", "ROADMAP.md"] }] } ``` -`runId`, `runDir`, `pluginRoot`, `timestamp`, and `question` are required; the script throws without them. Because a workflow is a slash command with no skill in front of it, the main session mints `runId` and `timestamp` with `date -u` and passes absolute paths, following the same instructions the `prd` skill carries; those instructions are duplicated in the workflow's `description` so a direct invocation still works. +`runId`, `runDir`, `pluginRoot`, `timestamp`, and `question` are required; the script throws without them. Because a workflow is a slash command with no skill in front of it, the main session mints `runId` and `timestamp` with `date -u` and passes absolute paths; the workflow's `description` carries those instructions so a direct invocation still works. -### 6.3 Lenses and models +### 6.3 Lenses, models, and evidence -| Lens | Persona | Default model | Why this model | -|---|---|---|---| -| product | `ck:river` | `claude-opus-5` | River's own tier; the anchor lens | -| marketing | `ck:toni` | `claude-fable-5-1` | The strongest model on the lens most often under-argued in a product decision; also the most expensive lens (Appendix F) | -| ux | `ck:kai` | `claude-sonnet-5` | Completes three distinct models at the lowest added cost | +| Lens | Persona | Default model | Reads by default | Why this model | +|---|---|---|---|---| +| product | `ck:river` | `claude-opus-5` | `docs/PRD.md`, `ROADMAP.md` | River's own tier; the anchor lens | +| marketing | `ck:toni` | `claude-fable-5-1` | `docs/market-research.md`, `docs/gtm.md` | The strongest model on the lens most often under-argued in a product decision; also the most expensive lens (Appendix H) | +| ux | `ck:kai` | `claude-sonnet-5` | `brand/`, `docs/mockups/` | Completes three distinct models at the lowest added cost | -Any lens can be replaced or re-modelled per run. If two lenses share a model the script logs that their agreement counts as one opinion. The memo header always states: all lenses are Claude models from one training pipeline, so decorrelation is partial (proposal §8.5). [P] +Every lens also reads `contextPath` when given. Files in `reads` that do not exist are skipped and named in the result. Varying the evidence does more than varying the model (Opus PRD P7): three Claude tiers give scale diversity, not independent judgment, because they share one training pipeline. The memo header states this limitation (proposal §8.5). + +**Two passes.** Each lens forms and records its view from the material and its own evidence first. Only then, if `rationalePath` is given, does it read the author's rationale, check whether the claims it relied on are supported, and report whether its view changed. A reviewer who reads the rationale first ratifies instead of testing (Will's panel brief). + +Any lens can be replaced or re-modelled per run. If two lenses share a model the script logs that their agreement counts as one opinion. `panel.js` is the one script allowed to pass `model` on a persona agent (§4.5). [P] ### 6.4 Lens schema -Every lens returns, and writes to `panel/.json`: +Every lens returns, and writes to `/panel/.json`: | Field | Meaning | |---|---| | `recommendation` | `yes`, `no`, `yes-if`, `not-yet` | | `position` | One paragraph | -| `reasoning` | Evidence from the material or the lens's domain, not from the other lenses | +| `reasoning` | Evidence from the material or the lens's own reading, not from the other lenses | +| `evidenceRead` | The files actually read, so the memo can say what each lens saw | | `strongestArgumentAgainstOwnRecommendation` | The best case a smart colleague would make against it; a weak one is a failed answer | -| `conditionThatWouldMakeMeSayNo` | The specific, checkable condition under which the lens reverses | +| `killCondition` | The specific, observable condition under which the lens would say this should not be done at all | +| `killConditionMet` | `yes`, `no`, or `unknown`: does the material already show that condition | +| `killConditionEvidence` | Where in the material, or why unknown | +| `viewChangedByRationale` | `yes`, `no`, or `not-read` | | `questionsForOtherLenses` | `[{to, question}]`, addressed to `author` or a lens persona | | `handoffBrief` | Decisions to record, open risks in the domain, one direct question to a named lens | @@ -412,97 +497,86 @@ The schema is enforced at the tool-call layer, so a lens that omits a field is r | Phase | Agents | What happens | |---|---|---| -| Lenses | 3, in parallel, `agentType: 'ck:'`, `model` per lens | Each reads the context, applies its behaviors in subagent form, writes `panel/.json`, returns the object | -| Synthesis | 1, neutral (no `agentType`, session model) | Reads the three results, writes `decision-memo.md`, returns the memo object | +| Lenses | 3, in parallel, `agentType: 'ck:'`, `model` per lens | Each reads the material and its own evidence, records its view, then reads the rationale if given; applies its behaviors in subagent form; writes `panel/.json`; returns the object | +| Synthesis | 1, neutral (no `agentType`, session model) | Reads the three results, writes the memo at `memoPath`, returns the memo object | Four agents. One concurrency round on any machine with four or more CPUs. Full script: Appendix A. ### 6.6 Decision memo -`decision-memo.md` sections, in order: +Default path `docs/decisions/-.md`, committed; the artifact is the state (§4.3). Sections, in order: -1. Question and context (with the run id, timestamp, lens table, and the decorrelation limitation) +1. Question and context: run id, timestamp, the lens table with models and what each read, the decorrelation limitation, any lens that did not answer 2. Recommendations: table, lens | persona | model | recommendation | one-line position -3. Where they agree -4. Where they disagree: topic, each position with its evidence, the decision the author must make -5. Each lens against itself, verbatim -6. Conditions to say no, verbatim -7. Questions between lenses, verbatim -8. Handoff briefs, verbatim, one per lens +3. Agreement, flagged as low-information: what all lenses concur on, and whether that is because it is obviously true or because they share a blind spot; the memo says which +4. Disagreement: every point where two lenses conflict, both positions at full strength, and the decision the author must make. Not adjudicated +5. Kill conditions, verbatim, with each lens's own answer to whether the material already shows it met +6. Each lens against itself, verbatim +7. Unique findings: anything only one lens saw +8. What nobody checked +9. Questions between lenses, verbatim +10. Handoff briefs, verbatim, one per lens -The synthesis agent is neutral and holds no lens. It never averages positions or picks a winner. If every lens recommends the same thing and no self-argument is substantive, it sets `panelFailedToDisagree` and says in the header that the panel should be re-run with a different question or lens set. +The synthesis agent is neutral and holds no lens. It never averages positions or picks a winner. It computes `agreementRate` (the share of lenses on the most common recommendation) and sets `panelFailedToDisagree` when every lens recommends the same thing and no self-argument is substantive; the header then says the panel should be re-run with a different question or lens set. Above roughly two-thirds agreement the panel is theater (Will's brief); the rate is in the memo so `/ck:report` can track it later. ### 6.7 Failure handling | Failure | Behavior | |---|---| -| A lens is stopped by the user or dies on an API error | `agent()` returns `null` [D]; the script logs which lens is missing and synthesizes on the survivors; the memo header says so | -| Every lens fails | The script throws; nothing is written; the session sees the error | +| A lens is stopped by the user or dies on an API error | `agent()` returns `null` [D]; the script logs which lens is missing and synthesizes on the survivors; the memo header says so; the skill's message follows §4.8 | +| Every lens fails | The script throws; nothing is written; the session sees the error and the skill translates it | | Synthesis returns `null` | The script returns the raw lens results with `memoPath: null`; `panel/*.json` is on disk | | Two lenses share a model | Logged; the run proceeds | +| A file in `reads` does not exist | Skipped; listed in `evidenceRead` as absent | ### 6.8 Cost -About $0.75 per run at today's prices, dominated by the Fable lens. Assumptions and arithmetic: Appendix F. +About $0.75 per run at today's prices, dominated by the Fable lens. Assumptions and arithmetic: Appendix H. ### 6.9 Acceptance criteria - [ ] `/ck:panel ` in a session with the plugin enabled shows the consent prompt with the option "don't ask again for `ck:panel`" [D]; after consent it runs in the background and `/workflows` shows phases Lenses and Synthesis. -- [ ] `.ck/runs//panel/river.json`, `toni.json`, `kai.json` exist and validate against the lens schema; `decision-memo.md` exists with the eight sections. +- [ ] `/panel/river.json`, `toni.json`, `kai.json` exist and validate against the lens schema; the memo exists at `docs/decisions/` with the ten sections. - [ ] `/workflows` shows three different models on the three lens agents. +- [ ] Each lens's `evidenceRead` lists different files when the default `reads` exist. +- [ ] With `rationalePath` given, each lens reports `viewChangedByRationale` as `yes` or `no`, never `not-read`. - [ ] Stopping one lens in `/workflows` produces a memo whose header names the missing lens. - [ ] `--lenses` with a replaced persona and model is honored (visible in `/workflows` and in the memo's table). -- [ ] The memo of a deliberately one-sided question ("Should we keep the tests passing?") reports `panelFailedToDisagree: true`. -- [ ] The script passes §9 test 9: `node --check` on the body wrapped as an async function, and no `Date.now`, `Math.random`, `new Date()`, `require(`, or `import(`. +- [ ] A deliberately one-sided question ("Should we keep the tests passing?") yields `panelFailedToDisagree: true` and an `agreementRate` of 1. +- [ ] The script passes §9 test 9. --- -## 7. `/ck:prd` +## 7. `/ck:brief`, `/ck:prd`, and `/ck:next` ### 7.1 Purpose -Proposal goal 3: a PRD that has the same shape every time, in every project, produced by River with the product, marketing, and UX lenses challenging it before the author sees it. The shape comes from the artifact contract (§7.8); the process comes from the skill and the workflow. +Proposal goal 3: a PRD that has the same shape every time, in every project, produced by River with the product, marketing, and UX lenses challenging it before the author sees it. The shape comes from the artifact contract (§7.8); the process comes from three commands. The split between `brief` and `prd` is the one place a cheap early document governs an expensive later run (Opus PRD §7.4). + +### 7.2 `/ck:brief` -### 7.2 Invocation +A workflow (`workflows/brief.js`, Appendix C). Input: one line of idea text. Output: `docs/brief.md`. ``` -/ck:prd -/ck:prd A branding-guide step between the PRD and the roadmap +/ck:brief An app that reminds you to water each plant on its own schedule ``` -The argument, if given, answers Q1 below. Everything else is asked. +| Phase | Agents | What happens | +|---|---|---| +| Draft | 1, `ck:river` | Reads the idea and Part A of the contract. Writes `docs/brief.md`: the idea; the problem with the root-cause chain (why, why, why) written out; the user; one success number with a date and a leading indicator; the scope with a smaller first version and River's recommendation; non-goals; open questions for the author. River's interactive behaviors run in subagent form (§5.4): the chain of whys is written, not asked; the smaller version is proposed, not negotiated | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` once if needed | Checks the brief against Part A's checklist; one revision at most | -### 7.3 Gate 0: intake, in the main session, as River +Three agents at most. About a minute. Cost in Appendix H. Acceptance: `docs/brief.md` exists with Part A's seven sections; the open-questions list is present even when empty; the skill's closing message names the file and gives one next action ("Read it, change anything, then run `/ck:prd`"). -The skill reads `${CLAUDE_PLUGIN_ROOT}/agents/river.md` for voice; the interactive forms below are the skill's own text (a subagent cannot ask, so the skill carries the interactive versions of River's three behaviors). One `AskUserQuestion` per step. **Each answer is appended to `brief.md` as it is given.** +### 7.3 `/ck:prd`: entry -| Step | Question (River's wording) | Options | -|---|---|---| -| Resume check | If any `.ck/runs/*/brief.md` exists without a `prd-draft.md`: "Resume run `` from ``, or start new?" | Resume, Start new | -| Q1 Proposal | "In one or two sentences, what do you want to build?" | free text (skipped when given as the argument) | -| Q2 Why 1 | "Why does that need to exist? What happens to the user today without it?" | free text; "That is the root cause"; "I am solving a symptom and I know it" | -| Q3 Why 2 | "Why is [answer] a problem worth solving now?" | same; stop early on either fixed option | -| Q4 Why 3 | "Why [answer]? What is underneath that?" | same | -| Q5 User | "Who exactly has this pain? One primary user." | options drawn from the answers, plus Other | -| Q6 Metric | "What single number moves if this works, by how much, by when? And what leading indicator will you watch?" | free text | -| Q7 Non-goals | "Name two or three things this will explicitly not do." | free text | -| Q8 V0 Challenge | River states a V0 cutting at least half the scope, then: "Would this still move [metric]?" | "Build the V0"; "Build the full scope"; "Full scope, and here is what specifically requires it" (free text) | -| Q9 Lenses | "Default panel (River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5), or name lenses and models?" | Default; custom | -| Q10 Output | "Where should the final PRD go?" | default `plans/--prd.md`; free text | - -`brief.md` sections, in order: Proposal; Root-cause chain; User; Success metric and leading indicator; Scope decision and rationale; Non-goals; Lenses; Output path. - -After Q10 the skill mints the run: +A skill (`skills/prd/SKILL.md`, Appendix D), `disable-model-invocation: true`, argument hint `[--interview] [idea]`. -```bash -timestamp=$(date -u +%Y%m%dT%H%M%SZ) -runId="${timestamp}-" -runDir="$(pwd)/.ck/runs/${runId}" -mkdir -p "$runDir" -grep -qxF '.ck/' .git/info/exclude 2>/dev/null || echo '.ck/' >> .git/info/exclude -``` - -and writes `run.json` with `{runId, createdAt, status: "gate-0", outputPath, lenses}`. +1. **Precondition.** If the Workflow tool is not available in the session, stop: "Dynamic workflows are not available here. `/ck:prd` needs them." No fallback to running the stages by hand. +2. **Find the brief.** If `docs/brief.md` exists, go to step 4. If not and `--interview` was given, run the interview (step 3). Otherwise stop with one action: "Run `/ck:brief ` first. It takes about a minute and writes `docs/brief.md`. Then run `/ck:prd` again." +3. **The interview (Will's path).** River asks, one question at a time, and appends each answer to `/interview.md` before asking the next. Three Whys with early-stop options; the user; the success number and leading indicator; non-goals; the V0 Challenge with its three options; the lens choice ("default panel, or name lenses"); the output path (default `docs/PRD.md`). Then River writes `docs/brief.md` from the answers. The interview's three behavior headings match `upstream/profiles/river.md` (CI-checked, §9). An interview with answers but no brief is offered for resume on the next run. +4. **Resume check.** If `docs/PRD.md` exists and the latest `run.json` says the run stopped at a stage, offer to continue from that stage. If it says `final`, ask whether to revise (re-run the panel on named sections) or start over. +5. **Mint the run** (§4.3): timestamp, run id, absolute cache directory, `.git/info/exclude`, `run.json` with `status: "starting"`. ### 7.4 Launch and wait @@ -513,41 +587,41 @@ Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/prd-draft.js", args: { runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp, - briefPath: "/brief.md", - lenses: + briefPath: "/docs/brief.md", prdPath: "/docs/PRD.md", + startAt: "", + lenses: } }) ``` -It writes the returned run id into `run.json` as `harnessRunId` together with `scriptPath`, sets `status: "drafting"`, tells the user the draft is running in the background, and **stops: it waits for the task notification. It does not poll, does not narrate, and does not start other work on this run.** If the notification reports a stop or failure, it offers `Workflow({ scriptPath, resumeFromRunId: harnessRunId })`, which replays completed agents from cache [D]. +It writes the returned run id into `run.json` as `harnessRunId` with `scriptPath`, sets `status: "drafting"`, tells the user in plain words that the draft is running in the background, and **stops: it waits for the task notification. It does not poll, does not narrate, and does not start other work on this run.** On a stop or failure it prints the §4.8 message naming `docs/PRD.md` and the one action, and records the failed stage in `run.json` so the next run passes the right `startAt`. Within the same session it may instead offer `Workflow({ scriptPath, resumeFromRunId: harnessRunId })`, which replays completed agents from cache [D]. `${CLAUDE_PLUGIN_ROOT}` expands anywhere in skill content [D]. Whether `name: "ck:prd-draft"` also works for the Workflow tool is unverified (§10.2); `scriptPath` is the specified path. ### 7.5 The `prd-draft` workflow -`meta.personas: ['river', 'toni', 'kai']`. Full script: Appendix B. +`meta.personas: ['river', 'toni', 'kai']`. Full script: Appendix B. Stages run in order and each is skipped when `args.startAt` names a later one. -| Phase | Agents | What happens | Output | +| Phase | Agents | What happens | Writes | |---|---|---|---| -| Draft | 1, `ck:river` | Reads `brief.md` and the artifact contract. Writes `draft-v0.md` to the contract's section order. Tags every claim not taken from the brief `[C1]`, `[C2]`, ... so the lenses can address it. Root-cause chain and V0 counter-proposal in subagent form. No premortem yet | `draft-v0.md`; claims list; assumptions; V0; questions | -| Validate | 1 neutral, `claude-haiku-4-5-20251001`; then `ck:river` to revise, at most twice | Checks the draft against every item in the contract's checklist; returns `{valid, missing[], notes}`. On `missing`, River revises in place, keeping every `[C]` tag. After two revisions the workflow proceeds and logs what is still missing | validation result | -| Panel | 4, nested `workflow({scriptPath: pluginRoot + '/workflows/panel.js'})` | Question: "Is this PRD ready for the author's review, and what would you change before it ships?" Context: `draft-v0.md`. Same lenses as Q9 | `panel/*.json`, `decision-memo.md` | -| Synthesize | 1, `ck:river` | Writes `prd-draft.md`: the PRD revised where the panel showed a claim wrong or unsupported; **Appendix A, Challenged claims** (claim, challenged by, severity, status ∈ upheld, revised, withdrawn, open; resolution; the panel's disagreements reproduced verbatim; nothing deleted); **Appendix B, Premortem** (the scenario, the exposed assumption, the question "What went wrong?" left verbatim for Gate 1) | `prd-draft.md`; challenged claims; premortem; open decisions | +| Draft | 1, `ck:river` | Reads `docs/brief.md` and Part B of the contract. Writes `docs/PRD.md` to the contract's section order. Tags every claim not taken from the brief `[C1]`, `[C2]`, ... so the lenses can address it. Root-cause chain and V0 counter-proposal in subagent form. No premortem yet | `docs/PRD.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` to revise, at most twice | Checks the draft against Part B's checklist; returns `{valid, missing[], notes}`. On `missing`, River revises in place, keeping every `[C]` tag. After two revisions the workflow proceeds and logs what is still missing | `docs/PRD.md` | +| Panel | 4, nested `workflow({scriptPath: pluginRoot + '/workflows/panel.js'})` | Question: "Is this PRD ready for the author's review, and what would you change before it ships?" Material: `docs/PRD.md`. Rationale, read second: `docs/brief.md`. Evidence per lens: River the brief and `ROADMAP.md`; Toni any positioning material; Kai any screens or mockups | `panel/*.json`, `docs/decisions/-prd-review.md` | +| Synthesize | 1, `ck:river` | Rewrites `docs/PRD.md`: revised where the panel showed a claim wrong or unsupported; **Appendix A, Challenged claims** (claim, challenged by, severity, status ∈ upheld, revised, withdrawn, open; resolution; the memo's disagreements reproduced verbatim; nothing deleted); **Appendix B, Premortem** (the scenario, the exposed assumption, the question "What went wrong?" left verbatim for the review) | `docs/PRD.md` | -Seven agents without a revision, up to nine with two. Under the default "medium" size guideline; two concurrency rounds on a 4-CPU laptop. If the nested panel throws, the workflow logs it and synthesizes without it, saying so in the PRD header. +Seven agents without a revision, up to nine with two. Under the default "medium" size guideline; about four sequential steps on a 4-CPU laptop, since the stages depend on each other. If the nested panel throws, the workflow logs it and synthesizes without it, saying so in the PRD header. -### 7.6 Gate 1: review, in the main session, as River +### 7.6 Gate 1: the review -The skill reads `prd-draft.md` and shows, in this order: the summary; the Challenged claims table; the open decisions; the premortem scenario verbatim. Then: +Two paths, chosen by whether the Artifact tool is available in the session (Phase 0 spike, §8.0). -| Step | Question | Options | -|---|---|---| -| Premortem | "What went wrong?" | "The metric was wrong"; "The user was not who we thought"; "Scope crept"; free text | -| Disposition | "Accept, edit named sections, or re-run the panel on named sections?" | Accept; Edit: ...; Re-run panel on: ... | +**Review page (Will's feedback channel, §4.9).** The skill publishes `docs/PRD.md` as a private review page, with the premortem question at the top and one line of instructions: "Comment on anything. Say 'done' here when you are finished." It waits. When the user says done, it reads every comment thread, applies each one to `docs/PRD.md` (or replies with a reason when it will not), republishes the same page, and resolves each thread with one line saying what changed. Then it finalizes. + +**File edit (always available).** "Open `docs/PRD.md`, change anything you like, save, and run `/ck:prd` again. I'll fold your edits in." On the next run the skill sees `status: "review"` in `run.json` and finalizes from the edited file. -Answers and edits go to `gate-1.md`. A re-run calls `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { ..., question: "", contextPath: "/prd-draft.md" } })`, waits, and returns to this gate. +Either path may also trigger a targeted re-run: `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { ..., question: "", contextPath: "/docs/PRD.md", rationalePath: "/docs/brief.md" } })`, then back to this gate. -### 7.7 Finalize, inline +### 7.7 Finalize One agent, so no workflow (§4.2): @@ -555,46 +629,54 @@ One agent, so no workflow (§4.2): Agent({ subagent_type: "ck:river", description: "Finalize PRD", - prompt: "Read /prd-draft.md and /gate-1.md. Fold the premortem answer into Assumptions and Risks, apply the requested edits, resolve each open decision as answered, keep Appendix A intact. Write the final PRD to . Set status 'final' in /run.json. Return the path and a five-line summary." + prompt: "Read docs/PRD.md and /gate-1.md (the review comments and how each was applied, or the note that the file was edited directly). Fold the premortem answer into Assumptions and Risks, resolve each open decision as answered, keep Appendix A intact, and check the result against Part B of the contract. Write docs/PRD.md. Set status 'final' in /run.json. Return the path and a five-line summary." }) ``` -The skill prints the output path and the run directory and suggests `/devlog` for the decision memo. +The skill prints the path and one next action: "Run `/ck:next`." It suggests `/devlog` for the decision memo when that skill is installed. -### 7.8 The PRD artifact contract +### 7.8 The artifact contract -`skills/prd-artifact/SKILL.md` (full text: Appendix D). Not user-invocable. It is the file River reads to draft, the validator reads to check, and Claude loads on its own when asked to write a PRD outside the workflow (its description says so), which is the proposal's consistency mechanism (§3.4) reaching the plain session too. +`skills/prd-artifact/SKILL.md` (full text: Appendix F). Not user-invocable. Two parts in one file, so the validator has one thing to read. -Section order: Summary; Problem; User; Success metric and leading indicator; Scope (the decision, and the V0 counter-proposal); Non-goals; Requirements (numbered, each with acceptance criteria); Sequencing and dependencies; Assumptions; Risks; Open questions; Appendix A Challenged claims; Appendix B Premortem. +**Part A, the brief.** Sections: Idea; Problem and root-cause chain; User; Success metric and leading indicator; Scope (decision and the smaller first version); Non-goals; Open questions for the author. Checklist A1 to A6. -Checklist (each item is a statement the validator can check by reading): +**Part B, the PRD.** Sections: Summary; Problem; User; Success metric and leading indicator; Scope; Non-goals; Requirements (numbered, each with acceptance criteria); Sequencing and dependencies; Assumptions; Risks; Open questions; Appendix A Challenged claims; Appendix B Premortem. Checklist B1 to B10, each a statement the validator can check by reading. -1. Every section above is present, in order, with its heading verbatim. -2. Problem names the user pain, not the solution, and cites the root-cause chain. -3. Success metric is one number with a target and a date, plus one leading indicator. -4. Scope records the V0 or full decision and the V0 counter-proposal with what it cuts. -5. Non-goals has at least two entries. -6. Every requirement has at least one acceptance criterion that a reader could verify without asking the author. -7. Every claim not from the brief carries a `[C]` tag, and every tag appears in Appendix A or is marked unchallenged. -8. Assumptions includes the assumption the premortem exposed. -9. Open questions lists every decision left to the author. -10. No em-dashes in prose (the family writing rule; the structural-list exception applies). +Claude also loads this skill on its own when asked to write a brief or a PRD outside the workflow (its description says so), which is the proposal's consistency mechanism (§3.4) reaching the plain session too. -### 7.9 Cost +### 7.9 `/ck:next` + +A skill (`skills/next/SKILL.md`, Appendix E). It looks at which of `docs/brief.md`, `docs/PRD.md`, and `docs/decisions/` exist and says one thing in plain words: + +| State | It says | +|---|---| +| No `docs/brief.md` | "Start with `/ck:brief` and describe your idea in a sentence. It takes about a minute and writes `docs/brief.md`." | +| Brief, no PRD | "Run `/ck:prd`. It turns the brief into full requirements and takes a few minutes." | +| PRD not final (`run.json` says review or a stopped stage) | "Your PRD is waiting for your review. Open `docs/PRD.md` (or the review page), then run `/ck:prd` again." or the resume message from §4.8 | +| PRD final | "The PRD is done. When you have a decision to make, run `/ck:panel `. The next stages (`brand-guide`, `roadmap`) are not installed yet." | -About $1.50 per run without a revision, about $2.00 with one, plus the main session's own turns. Appendix F. +No model names, no token counts, no more than one action. It runs in the main session with no agents. -### 7.10 Acceptance criteria +### 7.10 Cost -- [ ] `/ck:prd` never auto-triggers (`disable-model-invocation: true`); typing it starts Gate 0 as River. -- [ ] After Q3, `brief.md` already contains Proposal and the first two whys (compaction safety). -- [ ] Killing the session after Q6 and running `/ck:prd` again offers to resume the run. +About $0.20 for `/ck:brief`; about $1.50 for `/ck:prd` without a revision, about $2.00 with one, plus the main session's own turns. Appendix H. + +### 7.11 Acceptance criteria + +- [ ] `/ck:brief ` writes `docs/brief.md` with Part A's sections and passes the validator; the closing message names the file and one action. +- [ ] `/ck:prd` without a brief stops with the one-action message and runs nothing. +- [ ] `/ck:prd --interview` asks one question at a time; after the second why, `/interview.md` already holds the first two answers; killing the session and re-running offers to resume. - [ ] `run.json` contains `harnessRunId` before the skill goes idle. -- [ ] `.git/info/exclude` contains `.ck/`; `git status` shows nothing under `.ck/`. -- [ ] `/workflows` shows phases Draft, Validate, Panel (with the nested panel's agents), Synthesize; the validator agent runs on Haiku 4.5. -- [ ] `prd-draft.md` has every contract section, an Appendix A with at least one row per blocking or major lens finding, and an Appendix B with a scenario and the verbatim question. -- [ ] Gate 1 asks "What went wrong?" first, then the disposition. -- [ ] The final PRD lands at the Q10 path with `status: final` in `run.json`, and its checklist passes when re-validated by hand against §7.8. +- [ ] `.git/info/exclude` contains `.ck/`; `git status` shows `docs/` files and nothing under `.ck/`. +- [ ] `/workflows` shows phases Draft, Validate, Panel (with the nested panel's agents), Synthesize; the validator runs on Haiku 4.5. +- [ ] `docs/PRD.md` has every Part B section, an Appendix A with at least one row per finding a lens raised, and an Appendix B with a scenario and the verbatim question. +- [ ] Stopping the workflow during Panel, then running `/ck:prd` again, continues from Panel without re-drafting (`startAt`). +- [ ] With the Artifact tool available: a review page is published; two comments are applied and resolved with one-line replies; the page is republished. +- [ ] Without it: the file-edit message is printed; an edit to `docs/PRD.md` followed by `/ck:prd` finalizes from the edited file. +- [ ] The final PRD is at `docs/PRD.md` with `status: final` in `run.json`, and its checklist passes when re-validated by hand. +- [ ] `/ck:next` gives the right one-line answer in each of the four states, with no model names. +- [ ] J1 (§2.3) completes on a fresh project without a text editor or `.ck/`, on the file-edit path. - [ ] The consent prompts seen during the drill are recorded, including whether the nested panel prompted separately (§10.2). - [ ] `skills/prd/SKILL.md` contains the three behavior headings from `upstream/profiles/river.md` (CI-checked). @@ -602,6 +684,19 @@ About $1.50 per run without a revision, about $2.00 with one, plus the main sess ## 8. Repository, packaging, release +### 8.0 Phase 0: spikes before the build + +Adopted from the Opus PRD §9. Each is a one-session experiment with a yes-or-no answer recorded in `tests/drill/`. + +| # | Spike | Why it gates the build | Answer today | +|---|---|---|---| +| S1 | Install from the marketplace on a second machine; `/ck:next` runs | Distribution is the whole point | Open | +| S2 | Inside a workflow, `agentType: 'ck:river'` runs on the model in its frontmatter, and `model:` on the call overrides it | The tier table and the panel's decorrelation both depend on it | Open; the docs say yes [D] | +| S3 | A nested `workflow({scriptPath})` consent: separate prompt or covered by "don't ask again" | Friction on every `/ck:prd` run | Open | +| S4 | The `SubagentStart` hook's stdin carries `agent_type` and `session_id`, and `CLAUDE_PLUGIN_DATA` is writable | The usage log, so G6 | Open; the docs say yes [D] | +| S5 | The Artifact tool (review pages) is available in Will's local Claude Code, and its comments can be read from a skill | Chooses the Gate 1 path | Open | +| S6 | Can `PreModelSwitch` interrupt a workflow to arbitrate a model change | The Opus PRD's escalation design | **Answered: no.** Workflows accept no mid-run input and the hook fires on a requested session switch only [D] | + ### 8.1 Repository and layout New repository `code-katz/ck`, one plugin per repo like the seven marketplace entries today [R]. Rejected: inside `claude-team-cli` (reopens the 07-31 decision inside the same repo and mixes the shell install path with the plugin) and inside `claude-plugins` as a subdirectory plugin (supported by the marketplace-root source form [D], but it breaks the family's per-repo README, DEVLOG, ROADMAP, and test convention). [P] @@ -615,11 +710,13 @@ ck/ │ └── tiers.conf ├── agents/*.md 21 generated files (§5) ├── skills/ -│ ├── prd/SKILL.md /ck:prd (Appendix C) -│ └── prd-artifact/SKILL.md the contract (Appendix D) +│ ├── prd/SKILL.md /ck:prd (Appendix D) +│ ├── next/SKILL.md /ck:next (Appendix E) +│ └── prd-artifact/SKILL.md the contract, Parts A and B (Appendix F) ├── workflows/ │ ├── panel.js /ck:panel (Appendix A) -│ └── prd-draft.js /ck:prd-draft (Appendix B) +│ ├── prd-draft.js /ck:prd-draft (Appendix B) +│ └── brief.js /ck:brief (Appendix C) ├── hooks/hooks.json §5.5 ├── scripts/ │ ├── generate-agents.sh @@ -628,15 +725,18 @@ ck/ │ └── upstream.lock └── tests/ ├── run.sh - └── fixtures/ a tiny project with a brief.md and a one-page context doc + ├── drill/ Phase 0 answers and drill logs, dated + └── fixtures/ a tiny project with a one-line idea and a one-page context doc ``` +A project that uses the plugin gains: `docs/brief.md`, `docs/PRD.md`, `docs/decisions/*.md` (committed), and `.ck/runs/` (a cache, locally excluded). + ### 8.2 Manifest ```json { "name": "ck", - "description": "Persona workflows for Claude Code: /ck:prd (a River-led PRD challenged by a three-lens panel), /ck:panel (product, marketing, and UX lenses on different models), and 21 Code Katz personas as ck: subagents.", + "description": "Persona workflows for Claude Code: /ck:brief and /ck:prd (a River-led brief and PRD, challenged by a three-lens panel), /ck:panel (product, marketing, and UX lenses on different models), /ck:next, and 21 Code Katz personas as ck: subagents.", "version": "0.1.0", "author": { "name": "Code Katz" } } @@ -652,9 +752,9 @@ Appended to `claude-plugins/.claude-plugin/marketplace.json` (bumping its `metad { "name": "ck", "source": { "source": "github", "repo": "code-katz/ck" }, - "description": "Persona workflows: /ck:prd (River-led PRD with a three-lens panel), /ck:panel (product, marketing, UX lenses on different models), and 21 personas as ck: subagents. Phase one of the code-katz plugin.", + "description": "Persona workflows: /ck:brief and /ck:prd (River-led, challenged by a three-lens panel), /ck:panel (product, marketing, UX lenses on different models), /ck:next, and 21 personas as ck: subagents. Phase one of the code-katz plugin.", "category": "workflow", - "keywords": ["workflows", "personas", "prd", "panel", "subagents"] + "keywords": ["workflows", "personas", "prd", "brief", "panel", "subagents"] } ``` @@ -667,7 +767,8 @@ Install: `/plugin marketplace add code-katz/claude-plugins` then `/plugin instal | A paid Claude Code plan with dynamic workflows available; on Pro, enabled in `/config` | Workflows are the orchestrator | [D] | | Workflows not disabled by the organization (`disableWorkflows`) | Same | [D] | | team-cli PR re-basing `tiers.conf` to §5.3 | `ck` copies the tier verbatim; without the PR, River runs on Fable 5 and the panel's Opus lens is an override, not a tier | [R] | -| Node 20+ on the developer's machine, for `node --check` in the tests only | The plugin itself needs no Node at run time | [P] | +| The Artifact tool, for the review-page path of Gate 1 | Optional; the file-edit path always works | Spike S5 | +| Node 20+ on the developer's machine, for the script check in the tests only | The plugin itself needs no Node at run time | [P] | | `jq` optional, for the usage log; the script falls back to appending the raw line | Family convention: jq is optional | [R] | ### 8.5 Version and update policy @@ -683,7 +784,7 @@ Install: `/plugin marketplace add code-katz/claude-plugins` then `/plugin instal | Switch this session to a persona | `/river`, `/akira`, ... | team-cli (`install.sh`) | | Delegate one task to a persona on its tier | `ck:river` subagent, or team-cli's `river` subagent | both; `ck:` is the plugin form | | Open a separate session as a persona | `claude-team launch river` | team-cli | -| Run a repeatable pipeline | `/ck:prd`, `/ck:panel` | ck | +| Run a repeatable pipeline | `/ck:brief`, `/ck:prd`, `/ck:panel`, `/ck:next` | ck | | Plan parallel sessions, track them | `/parallel`, `/conductor` | team-cli, conductor | A user with both installed has two River subagents (`river` from `~/.claude/agents/`, priority 4, and `ck:river`, priority 5) [D]. They are generated from the same profile text at possibly different commits; `upstream.lock` says which. The README says this once. @@ -699,16 +800,19 @@ A user with both installed has two River subagents (`river` from `~/.claude/agen | 1 | `plugin.json` parses; `name` is `ck`; `version` matches a semver | static | | 2 | Regenerate `agents/` from `upstream/` into scratch; `diff -q` each file against the committed copy; fail listing stale names | drift | | 3 | Agent count equals profile count minus `coordinator*` | drift | -| 4 | Per agent: `model:` equals the `tiers.conf` line; `name:` equals the filename, no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble sentence present | drift | +| 4 | Per agent: `model:` equals the `tiers.conf` line; `name:` equals the filename, no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble sentence present; no `effort:` line | drift | | 5 | `scripts/upstream.lock` has exactly one `commit=` with a 40-hex value | drift | | 6 | Opt-in (dispatch or schedule, never on push): `git fetch --depth 1 origin ` and `diff -r` the vendored files against it | drift, network | | 7 | `skills/prd/SKILL.md` contains the three `### N. ` headings from `upstream/profiles/river.md` | contract | -| 8 | `skills/prd-artifact/SKILL.md` section list equals the list in the `prd-draft.js` Draft prompt | contract | +| 8 | `skills/prd-artifact/SKILL.md` Part A and Part B section lists equal the lists in the `brief.js` and `prd-draft.js` Draft prompts | contract | | 9 | Every `workflows/*.js`: `node --check` passes on a copy with `export` stripped and the body wrapped in `(async () => { ... })()`, because workflow scripts use top-level `return` and `await`, which a bare module rejects; first statement is `export const meta`; `meta` has `name`, `description`, `phases`, `personas`; grep for `Date.now|Math.random|new Date\(\)|require\(|import\(` is empty | lint | | 10 | `hooks/hooks.json` parses; the matcher is `^ck:`; `usage-log.sh` given a fixture stdin appends one valid JSON line and exits 0, and exits 0 on garbage input | hook | -| 11 | End-to-end drill, by hand, on the fixture project and then on one real project: `/ck:panel` then `/ck:prd`; record the consent prompts, the files under `.ck/runs//`, the models shown in `/workflows`, and the final PRD path. The drill log is committed under `tests/drill/.md` | e2e | +| 11 | `skills/next/SKILL.md` and `skills/prd/SKILL.md` contain no model names and no token counts in user-facing text (grep for `claude-`, `opus`, `sonnet`, `fable`, `haiku`, `token` outside code fences) | user 2 | +| 12 | Phase 0 answers recorded under `tests/drill/` for S1 to S6 before the release is tagged | phase 0 | +| 13 | End-to-end drill, by hand, on the fixture project and then on one real project: `/ck:next`, `/ck:brief`, `/ck:prd` on the file-edit path, `/ck:panel`; a second pass on the review-page path where S5 says yes; a stop during Panel followed by a resume. Record the consent prompts, the files under `docs/` and `.ck/runs//`, the models shown in `/workflows`, and every message the skills printed. The drill log is committed under `tests/drill/.md` | e2e | +| 14 | The J1 drill: someone who is not Will runs the file-edit path on a fresh project from the README alone; every message they see is checked against §4.8's three rules | user 2 | -`claude plugin eval` is early access and not enabled today; when it is, the drill becomes an eval suite and test 11 stops being manual. +`claude plugin eval` is early access and not enabled today; when it is, the drills become an eval suite and tests 13 and 14 stop being manual. --- @@ -718,9 +822,12 @@ A user with both installed has two River subagents (`river` from `~/.claude/agen | Item | Why not in phase one | Revisit when | |---|---|---| -| The other seven workflows in proposal §5.3 (`opportunity`, `market-research`, `brand-guide`, `roadmap`, `feature`, `bugfix`, `gtm`) and `/ck:next` | Phase one proves the gate rule, the port, and the artifact contract on one workflow first | Phase one has been used weekly for 30 days | +| The other seven workflows in proposal §5.3 (`opportunity`, `market-research`, `brand-guide`, `roadmap`, `feature`, `bugfix`, `gtm`) | Phase one proves the gate rule, the port, and the artifact contract on the brief and the PRD first | Phase one has been used weekly for 30 days | | `/ck:review`: a six-reviewer artifact review with adversarial refuters and a verify cap (designed during this PRD's review; a different product from the three-lens panel) | The panel is the decision primitive the proposal asks for; a review workflow is a second one | The panel proves too narrow for code, design, or plan reviews | | Persona switch skills `/ck:` | team-cli's `/name` commands cover the switch route today | The retire-or-coexist decision at 90 days | +| Persona scopes: core, project cast (the game and genre seats moved to the projects that use them), personal (Opus PRD §7.7) | The shape of the 90-day prune; casts stay generated from upstream, never hand-copied | The 90-day review | +| `/ck:report`: a static HTML report of spend, runs, and persona usage | Phase one has no data yet; conductor's fixture-fenced cost parser and `pricing.json` are the reuse [R] | Thirty days of usage log | +| Mockup review pages with labeled variants (§4.9) | No design stage in phase one | `/ck:brand-guide` | | Hook-enforced artifact gates (`SubagentStop`, exit 2) | Feedback path undocumented; plugin agents ignore per-agent hooks [D]; the validator agent covers the shape check | More than one draft in five passes the validator and still fails Gate 1 on structure | | Model fallback chain | `PreModelSwitch` does not cover it [D]; null-tolerant scripts cover phase one | More than one run in ten loses a lens to an API error | | Advisor tool | API-only and experimental [V] | Available inside Claude Code | @@ -740,6 +847,7 @@ A user with both installed has two River subagents (`river` from `~/.claude/agen 5. Does the workflow loader accept the extra `personas` key in `meta`? The docs require `name` and `description` and describe `whenToUse` and `phases`; an extra literal key is expected to pass. Test 9 asserts it; the drill confirms `/ck:panel` still appears in autocomplete. 6. Does `SubagentStop` exit 2 feed stderr back to a workflow agent? Decides the hook-gate spike. 7. Aliases or full IDs in `tiers.conf`? The team-cli PR decides (§5.3). +8. Is the Artifact tool (review pages, §4.9) available in Will's local Claude Code, and can a skill read its comments there? Phase 0 spike S5. The file-edit path covers phase one either way. --- @@ -747,14 +855,15 @@ A user with both installed has two River subagents (`river` from `~/.claude/agen | Risk | Likelihood | Impact | Mitigation | |---|---|---|---| -| Workflows unavailable (plan, `/config`, or org `disableWorkflows`) | Low for Will; real for other users | The plugin is inert | README states the prerequisite; the `prd` skill checks for the Workflow tool before Gate 0 and stops with the reason | +| Workflows unavailable (plan, `/config`, or org `disableWorkflows`) | Low for Will; real for other users | The plugin is inert | README states the prerequisite; the `prd` skill checks for the Workflow tool before anything else and stops with a plain reason | | An API error nulls a lens | Medium | Memo on two lenses | Logged; memo header says so; re-run offered; a lens can be re-modelled per run | | The Fable lens dominates cost | Certain | About $0.30 to $0.50 of every panel | `--lenses` override; an all-Opus-and-Sonnet assignment is one flag away | | Persona text drifts from upstream | Low | Two Rivers disagree | `upstream.lock`, drift test, `bump-upstream.sh` prints the diff | | 21 personas is 15 too many | Likely (proposal §7) | Maintenance and choice paralysis | Generated, so carrying cost is near zero; `usage.jsonl`; prune at 90 days | | River and Akira on Opus 5 write worse PRDs than on Fable | Unknown | Quality of the flagship artifact | One line in `tiers.conf` reverts it; the panel disagreement rate and Gate 1 edit volume are the signal | -| The 4.7-and-later tokenizer produces about 30% more tokens [D] | Certain | Appendix F underestimates by up to 30% | Stated in Appendix F; `/workflows` shows real token totals | -| Compaction during Gate 0 | Medium on long intakes | Lost answers | Append-as-you-go and the resume check (§4.3) | +| The 4.7-and-later tokenizer produces about 30% more tokens [D] | Certain | Appendix H underestimates by up to 30% | Stated in Appendix H; `/workflows` shows real token totals | +| Compaction during the interview | Medium on long interviews | Lost answers | Append-as-you-go and the resume check (§4.3) | +| The harder user gets designed out again as features accrete | Medium | She abandons it after one bad run | J1 is a test (§9 test 14); §4.8's three rules are grep-checked (test 11); every new command needs a one-line `/ck:next` answer | | Consent prompts on every run annoy | Medium | Friction | "Don't ask again for `ck:panel`" on the first run; allow rules `Workflow(ck:panel)`, `Workflow(ck:prd-draft)` | | Two River subagents (`river`, `ck:river`) confuse delegation | Low | Wrong tier or stale text | README note; every `ck` prompt names `ck:` explicitly | | `meta.personas` rejected by the loader | Low | Workflow missing from autocomplete | Open question 5; fallback is to move the roster into `description` | @@ -766,10 +875,10 @@ A user with both installed has two River subagents (`river` from `~/.claude/agen ```js export const meta = { name: 'panel', - description: 'Three-lens decision panel: product (river), marketing (toni), and UX (kai) personas, each on a different model, argue one question; a neutral memo surfaces where they disagree and leaves the decision to the author. Args: runId, runDir (absolute), pluginRoot, timestamp (UTC, minted by the caller with date -u), question, contextPath (optional), lenses (optional [{persona, lens, model}]).', + description: 'Three-lens decision panel: product (river), marketing (toni), and UX (kai) personas, each on a different model and each reading its own evidence, argue one question; a neutral memo surfaces where they disagree and leaves the decision to the author. Args: runId, runDir (absolute cache directory), pluginRoot, timestamp (UTC, minted by the caller with date -u), question, contextPath (optional), rationalePath (optional; each lens reads it only after forming its view), memoPath (optional; default docs/decisions/-panel.md), lenses (optional [{persona, lens, model, reads}]).', phases: [ - { title: 'Lenses', detail: 'ck:river, ck:toni, ck:kai in parallel, one model each, each forced to argue against itself' }, - { title: 'Synthesis', detail: 'one neutral agent writes decision-memo.md; disagreement preserved, decision left to the author' }, + { title: 'Lenses', detail: 'ck:river, ck:toni, ck:kai in parallel, one model each, each reading its own evidence, each forced to argue against itself' }, + { title: 'Synthesis', detail: 'one neutral agent writes the decision memo: agreement flagged as low-information, disagreement preserved, decision left to the author' }, ], personas: ['river', 'toni', 'kai'], } @@ -781,24 +890,25 @@ const runDir = args.runDir const stamp = args.timestamp const question = args.question const contextPath = args.contextPath || null +const rationalePath = args.rationalePath || null +const memoPath = args.memoPath || ('docs/decisions/' + stamp + '-panel.md') -// Three lenses, three models: the same model in three costumes is one opinion. +// Three lenses, three models, three bodies of evidence. The same model in three +// costumes is one opinion; the same evidence read three times is one reading. // This is the one script in ck allowed to set `model` on a persona agent; the -// per-invocation model beats the agent's frontmatter tier. Any lens may be -// replaced or re-modelled through args.lenses. +// per-invocation model beats the agent's frontmatter tier. const DEFAULT_LENSES = [ - { persona: 'river', lens: 'product', model: 'claude-opus-5' }, - { persona: 'toni', lens: 'marketing', model: 'claude-fable-5-1' }, - { persona: 'kai', lens: 'ux', model: 'claude-sonnet-5' }, + { persona: 'river', lens: 'product', model: 'claude-opus-5', reads: ['docs/PRD.md', 'ROADMAP.md'] }, + { persona: 'toni', lens: 'marketing', model: 'claude-fable-5-1', reads: ['docs/market-research.md', 'docs/gtm.md'] }, + { persona: 'kai', lens: 'ux', model: 'claude-sonnet-5', reads: ['brand/', 'docs/mockups/'] }, ] const lenses = Array.isArray(args.lenses) && args.lenses.length - ? args.lenses.map((l, i) => ({ - persona: l.persona, - lens: l.lens || l.persona, - model: l.model || DEFAULT_LENSES[i % DEFAULT_LENSES.length].model, - })) + ? args.lenses.map((l, i) => { + if (!l || !l.persona) throw new Error('panel: every entry in args.lenses needs a persona') + const d = DEFAULT_LENSES[i % DEFAULT_LENSES.length] + return { persona: l.persona, lens: l.lens || l.persona, model: l.model || d.model, reads: Array.isArray(l.reads) ? l.reads : [] } + }) : DEFAULT_LENSES -if (lenses.some(l => !l.persona)) throw new Error('panel: every entry in args.lenses needs a persona') if (new Set(lenses.map(l => l.model)).size < lenses.length) { log('panel: two or more lenses share a model; their agreement counts as one opinion') } @@ -808,6 +918,7 @@ const QUESTION = { properties: { to: { type: 'string' }, question: { type: 'string' } }, required: ['to', 'question'], } +const YES_NO_UNKNOWN = { type: 'string', enum: ['yes', 'no', 'unknown'] } const LENS_SCHEMA = { type: 'object', @@ -817,15 +928,19 @@ const LENS_SCHEMA = { recommendation: { type: 'string', enum: ['yes', 'no', 'yes-if', 'not-yet'] }, position: { type: 'string' }, reasoning: { type: 'string' }, + evidenceRead: { type: 'array', items: { type: 'string' } }, strongestArgumentAgainstOwnRecommendation: { type: 'string' }, - conditionThatWouldMakeMeSayNo: { type: 'string' }, + killCondition: { type: 'string' }, + killConditionMet: YES_NO_UNKNOWN, + killConditionEvidence: { type: 'string' }, + viewChangedByRationale: { type: 'string', enum: ['yes', 'no', 'not-read'] }, questionsForOtherLenses: { type: 'array', items: QUESTION }, handoffBrief: { type: 'string' }, }, required: [ - 'persona', 'lens', 'recommendation', 'position', 'reasoning', - 'strongestArgumentAgainstOwnRecommendation', 'conditionThatWouldMakeMeSayNo', - 'questionsForOtherLenses', 'handoffBrief', + 'persona', 'lens', 'recommendation', 'position', 'reasoning', 'evidenceRead', + 'strongestArgumentAgainstOwnRecommendation', 'killCondition', 'killConditionMet', + 'killConditionEvidence', 'viewChangedByRationale', 'questionsForOtherLenses', 'handoffBrief', ], } @@ -845,7 +960,9 @@ const MEMO_SCHEMA = { required: ['persona', 'lens', 'model', 'recommendation'], }, }, - agreements: { type: 'array', items: { type: 'string' } }, + agreementRate: { type: 'number' }, + agreement: { type: 'string' }, + agreementIsLowInformationBecause: { type: 'string', enum: ['obviously-true', 'shared-blind-spot', 'mixed', 'no-agreement'] }, disagreements: { type: 'array', items: { @@ -865,20 +982,33 @@ const MEMO_SCHEMA = { required: ['topic', 'positions', 'decisionForAuthor'], }, }, - conditions: { + killConditions: { type: 'array', items: { type: 'object', - properties: { persona: { type: 'string' }, condition: { type: 'string' } }, - required: ['persona', 'condition'], + properties: { + persona: { type: 'string' }, condition: { type: 'string' }, + met: YES_NO_UNKNOWN, evidence: { type: 'string' }, + }, + required: ['persona', 'condition', 'met', 'evidence'], }, }, + uniqueFindings: { + type: 'array', + items: { + type: 'object', + properties: { persona: { type: 'string' }, finding: { type: 'string' } }, + required: ['persona', 'finding'], + }, + }, + nobodyChecked: { type: 'array', items: { type: 'string' } }, panelFailedToDisagree: { type: 'boolean' }, summary: { type: 'string' }, }, required: [ - 'memoPath', 'question', 'recommendations', 'agreements', 'disagreements', - 'conditions', 'panelFailedToDisagree', 'summary', + 'memoPath', 'question', 'recommendations', 'agreementRate', 'agreement', + 'agreementIsLowInformationBecause', 'disagreements', 'killConditions', + 'uniqueFindings', 'nobodyChecked', 'panelFailedToDisagree', 'summary', ], } @@ -888,16 +1018,24 @@ const roster = lenses.map(l => `${l.persona}: ${l.lens}`).join('; ') const results = (await parallel(lenses.map(l => () => agent( `You are ${l.persona}, the ${l.lens} lens on a ${lenses.length}-lens decision panel (${roster}).\n` + `The question: ${question}\n` + - (contextPath ? `Read ${contextPath} in full before answering; it is the material the question is about. ` : '') + - `If ${runDir}/brief.md exists, read it too; it records the author's intent.\n` + + `Work in two passes and keep them separate.\n` + + `Pass 1. Read ` + (contextPath ? `${contextPath} (the material the question is about) and ` : '') + + `your own evidence: ${l.reads.length ? l.reads.join(', ') : 'nothing beyond the material'}. Skip any file or ` + + `directory that does not exist and record what you actually read in evidenceRead. Form your view and write it ` + + `down: recommendation (yes, no, yes-if, not-yet); position (one paragraph); reasoning (evidence from what you ` + + `read or from your domain, not from the other lenses); strongestArgumentAgainstOwnRecommendation (the best ` + + `case a smart colleague would make against you; a weak one is a failed answer); killCondition (the specific, ` + + `observable condition under which this should not be done at all); killConditionMet (does the material already ` + + `show it: yes, no, unknown) with killConditionEvidence (where, or why unknown).\n` + + (rationalePath + ? `Pass 2. Only now read ${rationalePath}, the author's rationale. Check whether the claims you relied on ` + + `are supported there. Set viewChangedByRationale to yes or no and, if yes, say how in reasoning. Do not ` + + `rewrite pass 1 to agree with it.\n` + : `Pass 2. There is no rationale document; set viewChangedByRationale to not-read.\n`) + `Answer from your own domain only. Apply your Required Behaviors in subagent form: where a behavior tells you ` + `to ask the user, put the question in questionsForOtherLenses addressed to 'author' or to a lens persona, ` + `state your assumption, and proceed.\n` + - `Return: recommendation (yes, no, yes-if, not-yet); position (one paragraph); reasoning (evidence from the ` + - `material or from your domain, not from the other lenses); strongestArgumentAgainstOwnRecommendation (the ` + - `best case a smart colleague would make against you; a weak one is a failed answer); ` + - `conditionThatWouldMakeMeSayNo (the specific, checkable condition under which you would reverse); ` + - `handoffBrief (decisions you want recorded, open risks in your domain, one direct question to a named lens).\n` + + `handoffBrief: decisions you want recorded, open risks in your domain, one direct question to a named lens.\n` + `Write the same object as JSON to ${runDir}/panel/${l.persona}.json (create the directory if needed) and ` + `return it with persona '${l.persona}' and lens '${l.lens}'.`, { label: `${l.lens}:${l.persona}`, phase: 'Lenses', agentType: 'ck:' + l.persona, model: l.model, schema: LENS_SCHEMA }, @@ -919,29 +1057,40 @@ const memo = await agent( (missing.length ? `Lenses that returned nothing: ${missing.join(', ')}. Say so in the memo header.\n` : '') + `Rules. You are neutral and hold no lens. Surface where the lenses disagree and do not resolve it; the ` + `decision is the author's. Never average positions or pick a winner. Quote each lens's strongest argument ` + - `against itself and its condition to say no verbatim. If every lens recommends the same thing and no ` + - `self-argument is substantive, set panelFailedToDisagree to true and say in the header that the panel ` + - `failed to disagree and should be re-run with a different question or lens set. State in the header that ` + - `all lenses are Claude models from one training pipeline, so decorrelation is partial.\n` + - `Write ${runDir}/decision-memo.md with these sections: 1 Question and context (run id, timestamp, lens ` + - `table with models, the limitation); 2 Recommendations (table: lens | persona | model | recommendation | ` + - `one-line position); 3 Where they agree; 4 Where they disagree (topic, each position with its evidence, ` + - `the decision the author must make); 5 Each lens against itself (verbatim); 6 Conditions to say no ` + - `(verbatim); 7 Questions between lenses (to -> question, verbatim); 8 Handoff briefs (verbatim, one per ` + - `lens). Then return the memo object; memoPath must be '${runDir}/decision-memo.md'.`, + `against itself and its kill condition verbatim.\n` + + `agreementRate is the share of lenses on the most common recommendation (two of three is 0.67). Treat ` + + `agreement as low-information: say whether what they agree on is obviously true or a shared blind spot, and ` + + `which. If every lens recommends the same thing and no self-argument is substantive, set ` + + `panelFailedToDisagree to true and say in the header that the panel should be re-run with a different ` + + `question or lens set. State in the header that all lenses are Claude models from one training pipeline, so ` + + `decorrelation is partial, and list what each lens actually read.\n` + + `Write ${memoPath} (create the directory if needed) with these sections: 1 Question and context (run id, ` + + `timestamp, lens table with models and evidence read, the limitation, any missing lens); 2 Recommendations ` + + `(table: lens | persona | model | recommendation | one-line position); 3 Agreement, flagged as ` + + `low-information, with why; 4 Disagreement (every point where two lenses conflict, both positions at full ` + + `strength, the decision the author must make); 5 Kill conditions, verbatim, each with the lens's own answer ` + + `to whether the material already shows it met; 6 Each lens against itself, verbatim; 7 Unique findings ` + + `(anything only one lens saw); 8 What nobody checked; 9 Questions between lenses (to -> question, verbatim); ` + + `10 Handoff briefs (verbatim, one per lens). Then return the memo object; memoPath must be '${memoPath}'.`, { label: 'synthesis', phase: 'Synthesis', schema: MEMO_SCHEMA }, ) if (!memo) { log('panel: synthesis returned nothing; returning raw lens results') + const recs = results.map(r => r.recommendation) + const top = recs.sort((a, b) => recs.filter(x => x === b).length - recs.filter(x => x === a).length)[0] return { runId: args.runId, question, memoPath: null, lenses: lenses.map(l => l.persona), missing, recommendations: results.map(r => ({ persona: r.persona, lens: r.lens, model: modelOf(r.persona), recommendation: r.recommendation })), - agreements: [], disagreements: [], conditions: results.map(r => ({ persona: r.persona, condition: r.conditionThatWouldMakeMeSayNo })), - panelFailedToDisagree: null, summary: 'synthesis agent returned nothing; see panel/*.json', + agreementRate: recs.filter(x => x === top).length / recs.length, + agreement: '', agreementIsLowInformationBecause: 'no-agreement', disagreements: [], + killConditions: results.map(r => ({ persona: r.persona, condition: r.killCondition, met: r.killConditionMet, evidence: r.killConditionEvidence })), + uniqueFindings: [], nobodyChecked: [], panelFailedToDisagree: false, + summary: 'synthesis agent returned nothing; see panel/*.json', } } if (memo.panelFailedToDisagree) log('panel: the panel failed to disagree; re-run with a different question or lens set') +log(`panel: agreement rate ${memo.agreementRate}; ${memo.disagreements.length} disagreement(s); ${memo.killConditions.filter(k => k.met === 'yes').length} kill condition(s) already met`) return { runId: args.runId, ...memo, lenses: lenses.map(l => l.persona), missing } ``` @@ -950,12 +1099,12 @@ return { runId: args.runId, ...memo, lenses: lenses.map(l => l.persona), missing ```js export const meta = { name: 'prd-draft', - description: "River drafts a PRD from brief.md to the prd-artifact contract, a validator checks it, the three-lens panel challenges it, and River writes prd-draft.md with a Challenged claims appendix and a premortem. Args: runId, runDir (absolute), pluginRoot, timestamp, briefPath (optional), lenses (optional). Normally launched by /ck:prd, which owns the gates before and after.", + description: "River drafts docs/PRD.md from docs/brief.md to Part B of the prd-artifact contract, a checker validates it, the three-lens panel challenges it (forming its view before reading the brief), and River rewrites it with a Challenged claims appendix and a premortem. Args: runId, runDir (absolute cache directory), pluginRoot, timestamp, briefPath (optional; default docs/brief.md), prdPath (optional; default docs/PRD.md), startAt (optional: draft | validate | panel | synthesize; earlier stages are skipped and the PRD on disk is used), lenses (optional). Normally launched by /ck:prd, which owns the review before and after.", phases: [ - { title: 'Draft', detail: 'ck:river writes draft-v0.md from brief.md to the contract; every non-brief claim tagged [C]' }, - { title: 'Validate', detail: 'one neutral Haiku agent checks the draft against the contract checklist; ck:river revises at most twice' }, + { title: 'Draft', detail: 'ck:river writes docs/PRD.md from docs/brief.md to the contract; every non-brief claim tagged [C]' }, + { title: 'Validate', detail: 'one neutral Haiku agent checks Part B of the contract; ck:river revises at most twice' }, { title: 'Panel', detail: "nested /ck:panel on the draft: is it ready for the author's review, and what would you change" }, - { title: 'Synthesize', detail: 'ck:river writes prd-draft.md: revised PRD, Appendix A Challenged claims, Appendix B Premortem' }, + { title: 'Synthesize', detail: 'ck:river rewrites docs/PRD.md: revised PRD, Appendix A Challenged claims, Appendix B Premortem' }, ], personas: ['river', 'toni', 'kai'], } @@ -964,14 +1113,18 @@ if (!args || !args.runId || !args.runDir || !args.pluginRoot || !args.timestamp) throw new Error('prd-draft: args.runId, args.runDir, args.pluginRoot, and args.timestamp are required') } const runDir = args.runDir -const brief = args.briefPath || (runDir + '/brief.md') const stamp = args.timestamp +const brief = args.briefPath || 'docs/brief.md' +const prdPath = args.prdPath || 'docs/PRD.md' const contract = args.pluginRoot + '/skills/prd-artifact/SKILL.md' -const draftPath = runDir + '/draft-v0.md' -const prdPath = runDir + '/prd-draft.md' const MAX_REVISIONS = 2 const VALIDATOR_MODEL = 'claude-haiku-4-5-20251001' +const ORDER = ['draft', 'validate', 'panel', 'synthesize'] +const startAt = ORDER.includes(args.startAt) ? args.startAt : 'draft' +const runs = stage => ORDER.indexOf(stage) >= ORDER.indexOf(startAt) +if (startAt !== 'draft') log(`prd-draft: starting at ${startAt}; ${prdPath} on disk is the draft`) + const QUESTION = { type: 'object', properties: { to: { type: 'string' }, question: { type: 'string' } }, @@ -981,7 +1134,7 @@ const QUESTION = { const DRAFT_SCHEMA = { type: 'object', properties: { - draftPath: { type: 'string' }, + prdPath: { type: 'string' }, title: { type: 'string' }, rootCauseChain: { type: 'array', items: { type: 'string' } }, claims: { @@ -1004,7 +1157,7 @@ const DRAFT_SCHEMA = { }, questions: { type: 'array', items: QUESTION }, }, - required: ['draftPath', 'title', 'rootCauseChain', 'claims', 'assumptions', 'v0', 'questions'], + required: ['prdPath', 'title', 'rootCauseChain', 'claims', 'assumptions', 'v0', 'questions'], } const VALIDATION_SCHEMA = { @@ -1052,75 +1205,90 @@ const PRD_SCHEMA = { } // ---- Draft ---- -phase('Draft') -let draft = await agent( - `Read ${brief}. It records the intake gate the author already answered with you: proposal, root-cause chain, ` + - `user, success metric and leading indicator, scope decision (V0 or full, with rationale), non-goals, lenses, ` + - `and the output path. Do not re-ask any of it.\n` + - `Read ${contract}. It is the PRD contract: section order, required fields, and the checklist your draft will ` + - `be validated against.\n` + - `Write ${draftPath} to that contract, all sections in order. Apply your Required Behaviors in subagent form: ` + - `restate the root-cause chain from the brief and extend it if the brief stopped at a symptom, saying which; ` + - `always present the V0 counter-proposal with what it cuts and your recommendation, even if the brief chose ` + - `full scope; leave the premortem for the synthesis pass after the panel, and say so under Appendix B.\n` + - `Tag every claim that is not taken directly from the brief with an inline marker [C1], [C2], ... so the panel ` + - `can address it, and list those claims with their section. Put anything you would have asked the author in ` + - `questions, with your assumption.\n` + - `Return the draft object; draftPath must be '${draftPath}'.`, - { label: 'river:draft', phase: 'Draft', agentType: 'ck:river', schema: DRAFT_SCHEMA }, -) -if (!draft) throw new Error('prd-draft: River returned nothing for the draft; check ' + runDir) -log(`draft: ${draft.claims.length} tagged claim(s), ${draft.assumptions.length} assumption(s), ${draft.questions.length} question(s) for the author`) +let draft = null +if (runs('draft')) { + phase('Draft') + draft = await agent( + `Read ${brief}. It records what the author already decided: the idea, the problem and its root-cause chain, ` + + `the user, the success metric and leading indicator, the scope decision and the smaller first version, ` + + `non-goals, and open questions. Do not re-ask any of it.\n` + + `Read Part B of ${contract}. It is the PRD contract: section order, required fields, and the checklist ` + + `your draft will be validated against.\n` + + `Write ${prdPath} to that contract, all sections in order (create the directory if needed). Apply your ` + + `Required Behaviors in subagent form: restate the root-cause chain from the brief and extend it if the brief ` + + `stopped at a symptom, saying which; always present the smaller first version with what it cuts and your ` + + `recommendation, even if the brief chose full scope; leave the premortem for the pass after the panel, and ` + + `say so under Appendix B.\n` + + `Tag every claim that is not taken directly from the brief with an inline marker [C1], [C2], ... so the ` + + `panel can address it, and list those claims with their section. Put anything you would have asked the ` + + `author under Open questions, with your assumption.\n` + + `Return the draft object; prdPath must be '${prdPath}'.`, + { label: 'river:draft', phase: 'Draft', agentType: 'ck:river', schema: DRAFT_SCHEMA }, + ) + if (!draft) throw new Error('prd-draft: River returned nothing for the draft') + log(`draft: ${draft.claims.length} tagged claim(s), ${draft.assumptions.length} assumption(s), ${draft.questions.length} open question(s)`) +} // ---- Validate ---- -phase('Validate') let validation = null -for (let round = 1; round <= MAX_REVISIONS + 1; round++) { - validation = await agent( - `Read ${contract} and ${draftPath}. Check the draft against every numbered item in the contract's Checklist ` + - `section and against the section order. Return valid=true only if every item holds. For each unmet item, ` + - `one line in missing that quotes the checklist item and says what is absent or wrong. Judge the shape, ` + - `not the product.`, - { label: `validate:${round}`, phase: 'Validate', model: VALIDATOR_MODEL, schema: VALIDATION_SCHEMA }, - ) - if (!validation) { log('validate: validator returned nothing; proceeding unvalidated'); break } - if (validation.valid) { log(`validate: draft passes the contract checklist (round ${round})`); break } - if (round > MAX_REVISIONS) { - log(`validate: still unmet after ${MAX_REVISIONS} revision(s): ${validation.missing.join(' | ')}`) - break +if (runs('validate')) { + phase('Validate') + for (let round = 1; round <= MAX_REVISIONS + 1; round++) { + validation = await agent( + `Read Part B of ${contract} and ${prdPath}. Check the PRD against every numbered item in Part B's ` + + `checklist and against the section order. Return valid=true only if every item holds. For each unmet ` + + `item, one line in missing that quotes the checklist item and says what is absent or wrong. Judge the ` + + `shape, not the product.`, + { label: `validate:${round}`, phase: 'Validate', model: VALIDATOR_MODEL, effort: 'low', schema: VALIDATION_SCHEMA }, + ) + if (!validation) { log('validate: validator returned nothing; proceeding unvalidated'); break } + if (validation.valid) { log(`validate: draft passes the contract checklist (round ${round})`); break } + if (round > MAX_REVISIONS) { + log(`validate: still unmet after ${MAX_REVISIONS} revision(s): ${validation.missing.join(' | ')}`) + break + } + log(`validate: ${validation.missing.length} unmet item(s); River revises (revision ${round} of ${MAX_REVISIONS})`) + const revised = await agent( + `Read Part B of ${contract}, ${brief}, and ${prdPath}. A checker found these unmet checklist items:\n` + + validation.missing.map(m => '- ' + m).join('\n') + '\n' + + `Revise ${prdPath} in place so each item holds. Keep every existing [C] tag and add tags for any new ` + + `claim not from the brief. Return the updated draft object; prdPath must be '${prdPath}'.`, + { label: `river:revise:${round}`, phase: 'Validate', agentType: 'ck:river', schema: DRAFT_SCHEMA }, + ) + if (!revised) { log('validate: revision returned nothing; keeping the previous draft'); break } + draft = revised } - log(`validate: ${validation.missing.length} unmet item(s); River revises (revision ${round} of ${MAX_REVISIONS})`) - const revised = await agent( - `Read ${contract}, ${brief}, and ${draftPath}. A validator found these unmet checklist items:\n` + - validation.missing.map(m => '- ' + m).join('\n') + '\n' + - `Revise ${draftPath} in place so each item holds. Keep every existing [C] tag and add tags for any new ` + - `claim not from the brief. Return the updated draft object; draftPath must be '${draftPath}'.`, - { label: `river:revise:${round}`, phase: 'Validate', agentType: 'ck:river', schema: DRAFT_SCHEMA }, - ) - if (!revised) { log('validate: revision returned nothing; keeping the previous draft'); break } - draft = revised } -// ---- Panel (nested; one level only) ---- -phase('Panel') +// ---- Panel (nested; one level only; each lens reads its own evidence and sees the brief last) ---- let panel = null -try { - panel = await workflow({ scriptPath: args.pluginRoot + '/workflows/panel.js' }, { - runId: args.runId, - runDir, - pluginRoot: args.pluginRoot, - timestamp: stamp, - question: "Is this PRD ready for the author's review, and what would you change before it ships?", - contextPath: draftPath, - lenses: args.lenses || null, - }) -} catch (e) { - log('panel: failed (' + (e && e.message ? e.message : String(e)) + '); synthesizing without it') -} -if (panel) { - log(`panel: ${panel.lenses.join(', ')}; ${(panel.disagreements || []).length} disagreement(s)` + - (panel.panelFailedToDisagree ? '; the panel failed to disagree' : '') + - (panel.missing && panel.missing.length ? `; missing: ${panel.missing.join(', ')}` : '')) +if (runs('panel')) { + phase('Panel') + const lenses = Array.isArray(args.lenses) && args.lenses.length ? args.lenses : [ + { persona: 'river', lens: 'product', model: 'claude-opus-5', reads: ['ROADMAP.md'] }, + { persona: 'toni', lens: 'marketing', model: 'claude-fable-5-1', reads: ['docs/market-research.md', 'docs/gtm.md'] }, + { persona: 'kai', lens: 'ux', model: 'claude-sonnet-5', reads: ['brand/', 'docs/mockups/'] }, + ] + try { + panel = await workflow({ scriptPath: args.pluginRoot + '/workflows/panel.js' }, { + runId: args.runId, + runDir, + pluginRoot: args.pluginRoot, + timestamp: stamp, + question: "Is this PRD ready for the author's review, and what would you change before it ships?", + contextPath: prdPath, + rationalePath: brief, + memoPath: 'docs/decisions/' + stamp + '-prd-review.md', + lenses, + }) + } catch (e) { + log('panel: failed (' + (e && e.message ? e.message : String(e)) + '); synthesizing without it') + } + if (panel) { + log(`panel: ${panel.lenses.join(', ')}; agreement ${panel.agreementRate}; ${(panel.disagreements || []).length} disagreement(s)` + + (panel.panelFailedToDisagree ? '; the panel failed to disagree' : '') + + (panel.missing && panel.missing.length ? `; missing: ${panel.missing.join(', ')}` : '')) + } } // ---- Synthesize ---- @@ -1131,28 +1299,28 @@ const panelInputs = panel && panel.memoPath ? `every file under ${runDir}/panel/ (the memo was not written)` : 'nothing else: the panel did not run, and the PRD header must say so') const prd = await agent( - `Read ${brief}, ${draftPath}, ${contract}, and ${panelInputs}.\n` + - `Write ${prdPath}: the same PRD sections as the draft, in contract order, revised where the panel showed a ` + - `claim wrong or unsupported, followed by two appendices.\n` + + `Read ${brief}, ${prdPath}, Part B of ${contract}, and ${panelInputs}.\n` + + `Rewrite ${prdPath}: the same sections, in contract order, revised where the panel showed a claim wrong or ` + + `unsupported, followed by two appendices.\n` + `Appendix A, Challenged claims: one row per point a lens raised against a [C] claim or against something ` + `untagged: claim | challenged by (persona and lens) | severity (blocking, major, minor: your call from the ` + `memo) | status | resolution. Status is upheld (you kept it; say why), revised (you changed it; quote the ` + - `change), withdrawn, or open (the author must decide). Never delete a challenge. Reproduce the memo's Where ` + - `they disagree section and its Conditions to say no verbatim below the table.\n` + + `change), withdrawn, or open (the author must decide). Never delete a challenge. Reproduce the memo's ` + + `Disagreement section and its Kill conditions verbatim below the table.\n` + `Appendix B, Premortem: your Required Behavior in subagent form. Write the 2-3 sentence scenario in which ` + `this shipped on time and did not move the success metric; name the hidden assumption it exposes; add that ` + `assumption to the Assumptions section; leave the question "What went wrong?" verbatim for the author. ` + - `The next gate asks it.\n` + - `Check your own output against the contract checklist before returning. List every decision you left open ` + + `The review asks it.\n` + + `Check your own output against Part B's checklist before returning. List every decision you left open ` + `under openDecisions. Generated ${stamp}, run ${args.runId}. Return the PRD object; prdPath must be '${prdPath}'.`, { label: 'river:synthesize', phase: 'Synthesize', agentType: 'ck:river', schema: PRD_SCHEMA }, ) -if (!prd) throw new Error('prd-draft: River returned nothing for the synthesis; the draft is at ' + draftPath) +if (!prd) throw new Error('prd-draft: River returned nothing for the synthesis; the draft is at ' + prdPath) return { runId: args.runId, + startedAt: startAt, prdPath: prd.prdPath, - draftPath, memoPath: panel ? panel.memoPath : null, lenses: panel ? panel.lenses : [], validation, @@ -1163,55 +1331,170 @@ return { } ``` -## Appendix C. `skills/prd/SKILL.md` +## Appendix C. `workflows/brief.js` + +```js +export const meta = { + name: 'brief', + description: 'River writes docs/brief.md from one line of idea text, to Part A of the prd-artifact contract, and a checker validates the shape. Args: runId, runDir (absolute cache directory), pluginRoot, timestamp, idea (text), briefPath (optional; default docs/brief.md).', + phases: [ + { title: 'Draft', detail: 'ck:river writes the brief: problem and root-cause chain, user, success metric, scope with a smaller first version, non-goals, open questions' }, + { title: 'Validate', detail: 'one neutral Haiku agent checks Part A of the contract; ck:river revises at most once' }, + ], + personas: ['river'], +} + +if (!args || !args.runId || !args.runDir || !args.pluginRoot || !args.timestamp || !args.idea) { + throw new Error('brief: args.runId, args.runDir, args.pluginRoot, args.timestamp, and args.idea are required') +} +const briefPath = args.briefPath || 'docs/brief.md' +const contract = args.pluginRoot + '/skills/prd-artifact/SKILL.md' +const stamp = args.timestamp +const VALIDATOR_MODEL = 'claude-haiku-4-5-20251001' + +const BRIEF_SCHEMA = { + type: 'object', + properties: { + briefPath: { type: 'string' }, + title: { type: 'string' }, + rootCauseChain: { type: 'array', items: { type: 'string' } }, + user: { type: 'string' }, + successMetric: { type: 'string' }, + leadingIndicator: { type: 'string' }, + v0: { + type: 'object', + properties: { + scope: { type: 'string' }, + cuts: { type: 'array', items: { type: 'string' } }, + recommendation: { type: 'string' }, + }, + required: ['scope', 'cuts', 'recommendation'], + }, + nonGoals: { type: 'array', items: { type: 'string' } }, + openQuestions: { type: 'array', items: { type: 'string' } }, + }, + required: ['briefPath', 'title', 'rootCauseChain', 'user', 'successMetric', 'leadingIndicator', 'v0', 'nonGoals', 'openQuestions'], +} + +const VALIDATION_SCHEMA = { + type: 'object', + properties: { + valid: { type: 'boolean' }, + missing: { type: 'array', items: { type: 'string' } }, + notes: { type: 'string' }, + }, + required: ['valid', 'missing', 'notes'], +} + +// ---- Draft ---- +phase('Draft') +let brief = await agent( + `The author's idea, in their own words: ${args.idea}\n` + + `Read Part A of ${contract}. It is the brief contract: section order, required fields, and the checklist ` + + `your brief will be validated against.\n` + + `Write ${briefPath} to that contract (create the directory if needed). Apply your Required Behaviors in ` + + `subagent form. Three Whys: do not accept the idea as the problem; write the chain (idea, why, why, why), ` + + `each step more specific, until the user pain is exposed or the idea is shown to address a symptom, and say ` + + `which. V0 Challenge: propose a first version that cuts at least half the scope, say what it cuts, and give ` + + `your recommendation with the decision marked open for the author. Premortem: not yet; it belongs to the PRD.\n` + + `One primary user. One success number with a target and a date, plus one leading indicator. At least two ` + + `non-goals. Anything you would have asked the author goes under Open questions for the author, each with ` + + `the assumption you proceeded on; the list is present even when empty.\n` + + `Plain words: the author may not be technical. Return the brief object; briefPath must be '${briefPath}'.`, + { label: 'river:draft', phase: 'Draft', agentType: 'ck:river', schema: BRIEF_SCHEMA }, +) +if (!brief) throw new Error('brief: River returned nothing') +log(`brief: ${brief.rootCauseChain.length} step(s) in the root-cause chain, ${brief.openQuestions.length} open question(s)`) + +// ---- Validate ---- +phase('Validate') +const validation = await agent( + `Read Part A of ${contract} and ${briefPath}. Check the brief against every numbered item in Part A's ` + + `checklist and against the section order. Return valid=true only if every item holds. For each unmet item, ` + + `one line in missing that quotes the checklist item and says what is absent or wrong. Judge the shape, not ` + + `the idea.`, + { label: 'validate', phase: 'Validate', model: VALIDATOR_MODEL, effort: 'low', schema: VALIDATION_SCHEMA }, +) +if (validation && !validation.valid) { + log(`validate: ${validation.missing.length} unmet item(s); River revises once`) + const revised = await agent( + `Read Part A of ${contract} and ${briefPath}. A checker found these unmet checklist items:\n` + + validation.missing.map(m => '- ' + m).join('\n') + '\n' + + `Revise ${briefPath} in place so each item holds. Return the updated brief object; briefPath must be '${briefPath}'.`, + { label: 'river:revise', phase: 'Validate', agentType: 'ck:river', schema: BRIEF_SCHEMA }, + ) + if (revised) brief = revised + else log('validate: revision returned nothing; keeping the first draft') +} else if (!validation) { + log('validate: validator returned nothing; proceeding unvalidated') +} else { + log('validate: brief passes the contract checklist') +} + +return { + runId: args.runId, + briefPath: brief.briefPath, + title: brief.title, + openQuestions: brief.openQuestions, + validation, + generated: stamp, +} +``` + +## Appendix D. `skills/prd/SKILL.md` ````markdown --- name: prd -description: Write a PRD with River. An intake gate (Three Whys, V0 Challenge), a background draft challenged by the product, marketing, and UX lenses on different models, a premortem gate, then finalize to the path you choose. Launches a paid workflow, so it runs only when you type /ck:prd. +description: Turn docs/brief.md into a full PRD with River. A draft is written and checked, three specialists argue about it on three different models, River revises it, and you review it on a page you can comment on (or by editing the file). Runs only when you type /ck:prd. disable-model-invocation: true -argument-hint: "[one-sentence proposal]" +argument-hint: "[--interview] [idea]" --- -You are River for the whole of this skill. Read `${CLAUDE_PLUGIN_ROOT}/agents/river.md` for your voice and standards. The subagent form of your behaviors is in that file; the interactive form is here, because this is the one place a user is present. +You are River for the whole of this skill. Read `${CLAUDE_PLUGIN_ROOT}/agents/river.md` for your voice and standards. Speak plainly: the person running this may not be technical. Never print a stack trace, a model name, or a token count. Always name the file that holds the work so far. Always give exactly one next action. -Before anything else, confirm the Workflow tool is available in this session. If it is not, stop and say: "Dynamic workflows are not available here (plan, /config, or organization setting). /ck:prd needs them." Do not fall back to running the stages by hand. +## 0. Preconditions -## 0. Resume check +Confirm the Workflow tool is available in this session. If it is not, stop and say: "Dynamic workflows are not available here. `/ck:prd` needs them. This is a setting in Claude Code, not something in your project." Do not run the stages by hand. -Run `ls .ck/runs/*/brief.md 2>/dev/null`. For any run directory that has `brief.md` but no `prd-draft.md`, ask with AskUserQuestion: "Resume run `` from ``, or start new?" On resume, read `run.json`; if it has `harnessRunId`, skip to step 3 and relaunch with `resumeFromRunId`; otherwise continue Gate 0 from the last section present in `brief.md`. +## 1. Find the brief -## 1. Gate 0: intake +- If `docs/brief.md` exists, go to step 3. +- If it does not and `--interview` was given, run step 2. +- Otherwise stop with one action: "Run `/ck:brief ` first. It takes about a minute and writes `docs/brief.md`. Then run `/ck:prd` again." -Ask one question at a time with AskUserQuestion. **After every answer, append it to `brief.md` under its section heading before asking the next question.** If the run directory does not exist yet, create it first (step 2 shows how; do it as soon as Q1 is answered, using a provisional slug from the proposal). +## 2. The interview (only with `--interview`) -### 1. Three Whys +Create the run directory first (step 4, with a provisional slug from the first answer) so every answer can be saved as it is given. Ask one question at a time with AskUserQuestion. **After every answer, append it to `/interview.md` under its heading before asking the next.** On entry, if an `interview.md` with answers but no `docs/brief.md` exists, offer to continue it. -Do not accept the proposal as the problem. Ask "Why?" up to three times, each answer more specific than the last: +### 1. Three Whys -- Q1 Proposal: "In one or two sentences, what do you want to build?" (skip if `$ARGUMENTS` is given; record it) -- Q2: "Why does that need to exist? What happens to the user today without it?" -- Q3: "Why is [their answer] a problem worth solving now?" -- Q4: "Why [their answer]? What is underneath that?" +Do not accept the idea as the problem. Ask "Why?" up to three times, each answer more specific than the last: -Each of Q2 to Q4 offers two fixed options, "That is the root cause" and "I am solving a symptom and I know it", plus free text. Stop early on either fixed option and record which. +- "In one or two sentences, what do you want to build?" (skip if the idea was given after `--interview`) +- "Why does that need to exist? What happens to the person today without it?" +- "Why is [their answer] a problem worth solving now?" +- "Why [their answer]? What is underneath that?" -Then: +Each why offers two fixed options, "That is the root cause" and "I am solving a symptom and I know it", plus free text. Stop early on either fixed option and record which. -- Q5 User: "Who exactly has this pain? One primary user." Offer options drawn from the answers so far, plus Other. -- Q6 Metric: "What single number moves if this works, by how much, by when? And what leading indicator will you watch?" -- Q7 Non-goals: "Name two or three things this will explicitly not do." +Then: "Who exactly has this problem? One main person." (options drawn from the answers, plus Other); "What single number moves if this works, by how much, by when? And what early sign will you watch?"; "Name two or three things this will not do." ### 2. V0 Challenge -Propose a V0 that cuts at least half the requested scope. Say: "Here is a V0 that solves the core problem with half the features: [scope]. It cuts [list]. Would this still move [metric]?" Offer: "Build the V0"; "Build the full scope"; "Full scope, and here is what specifically requires it" (free text). Record the decision and the rationale. +Propose a first version that cuts at least half the scope. Say: "Here is a smaller first version that solves the core problem: [scope]. It leaves out [list]. Would this still move [the number]?" Offer: "Build the smaller version"; "Build the full scope"; "Full scope, and here is what specifically needs the extra" (free text). Record the decision and the reason. + +Finally: "Default reviewers, or name them?" (record as a lens list or nothing) and "Where should the PRD go?" (default `docs/PRD.md`). Then write `docs/brief.md` from the answers, to Part A of `${CLAUDE_PLUGIN_ROOT}/skills/prd-artifact/SKILL.md`, and continue. + +## 3. Resume check -- Q9 Lenses: "Default panel (River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5), or name lenses and models?" Record as a list of `{persona, lens, model}` or `null`. -- Q10 Output: "Where should the final PRD go?" Default `plans/--prd.md`. +Read the latest `.ck/runs/*/run.json` for this project, if any. -`brief.md` sections, in this order: Proposal; Root-cause chain; User; Success metric and leading indicator; Scope decision and rationale; Non-goals; Lenses; Output path. +- If `docs/PRD.md` exists and `status` names a stopped stage, offer: "Your PRD stopped at [stage]. Everything before it is saved in `docs/PRD.md`. Continue from there, or start over?" Continue means `startAt` = that stage. +- If `status` is `review`, go to step 7: the author has edited the file. +- If `status` is `final`, ask: "The PRD is finished. Re-run the reviewers on some sections, or start over?" -## 2. Mint the run +## 4. Mint the run ```bash timestamp=$(date -u +%Y%m%dT%H%M%SZ) @@ -1221,39 +1504,43 @@ mkdir -p "$runDir" grep -qxF '.ck/' .git/info/exclude 2>/dev/null || echo '.ck/' >> .git/info/exclude ``` -Write `run.json`: `{ "runId", "createdAt": timestamp, "status": "gate-0", "outputPath", "lenses" }`. Tell the user once: `.ck/` is excluded from git locally; the final PRD is not. +Write `run.json`: `{ "runId", "createdAt": timestamp, "status": "starting", "stage": "draft", "outputPath": "docs/PRD.md", "lenses" }`. The `.ck/` folder is a cache; the documents in `docs/` are the work. -## 3. Launch the draft and wait +## 5. Launch the draft and wait -Call the Workflow tool exactly like this: +Call the Workflow tool exactly like this (absolute paths): ``` Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/prd-draft.js", args: { runId: "", runDir: "", pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp: "", - briefPath: "/brief.md", lenses: + briefPath: "/docs/brief.md", prdPath: "/docs/PRD.md", + startAt: "", + lenses: } }) ``` -Immediately write the returned run id into `run.json` as `harnessRunId`, with `scriptPath`, and set `status` to `drafting`. Tell the user the draft is running in the background and that `/workflows` shows progress. Then stop. Wait for the task notification. Do not poll, do not narrate, do not start other work on this run. +Immediately write the returned run id into `run.json` as `harnessRunId`, with `scriptPath`, and set `status` to `drafting`. Say: "Writing the PRD. This takes a few minutes and runs in the background; I'll tell you when it's ready." Then stop. Wait for the task notification. Do not poll, do not narrate, do not start other work on this run. -If the notification reports a stop or a failure, offer to relaunch: `Workflow({ scriptPath: "", resumeFromRunId: "" })`. Completed agents replay from cache. +If the notification reports a stop or a failure: record the failed stage in `run.json` and say: "I couldn't finish the [stage] step. Everything up to it is saved in `docs/PRD.md`. Run `/ck:prd` again to continue from there." Within the same session you may instead offer to relaunch with `resumeFromRunId`. -## 4. Gate 1: review +## 6. The review -Read `/prd-draft.md`. Show, in this order: the summary; the Challenged claims table (Appendix A); the open decisions; the premortem scenario from Appendix B, verbatim. +Set `status` to `review`. Read `docs/PRD.md`. Then take one of two paths. -### 3. Premortem +**Review page (when the Artifact tool is available).** Publish `docs/PRD.md` as a private page. At the top put the premortem question from Appendix B and one line: "Comment on anything. Say 'done' here when you are finished." Tell the user the link and stop. When they say done: read every comment thread; apply each one to `docs/PRD.md` (write the change and the reason to `/gate-1.md`); where you will not apply one, reply with the reason and leave it open; republish the same page; resolve each applied thread with one line saying what changed. Then go to step 7. + +**File edit (always).** Say: "Your PRD is at `docs/PRD.md`. Open it, change anything you like, save, and run `/ck:prd` again. I'll fold your edits in." Stop. On the next run, step 3 sees `review` and continues at step 7. -Ask, with AskUserQuestion: "What went wrong?" Options: "The metric was wrong"; "The user was not who we thought"; "Scope crept"; plus free text. Use the answer to surface the hidden assumption; do not argue with it. +### 3. Premortem -Then ask: "Accept, edit named sections, or re-run the panel on named sections?" Options: Accept; Edit: ...; Re-run the panel on: ... Write the premortem answer, the edits, and a decision for each open item to `/gate-1.md`. +The question at the top of the review, and the first thing to ask if the author is reviewing in conversation: "Imagine this shipped on time and did not move the number. What went wrong?" Use the answer to surface the hidden assumption; do not argue with it. Record it in `/gate-1.md`. -On re-run: `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp: "", question: "", contextPath: "/prd-draft.md", lenses } })`, record its run id in `run.json`, wait for the notification, and return to the top of this gate. +To re-run the reviewers on named sections, call `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp: "", question: "", contextPath: "/docs/PRD.md", rationalePath: "/docs/brief.md", lenses } })`, record its run id, wait, and return to this step. -## 5. Finalize +## 7. Finalize One agent, inline: @@ -1261,73 +1548,124 @@ One agent, inline: Agent({ subagent_type: "ck:river", description: "Finalize PRD", - prompt: "Read /prd-draft.md and /gate-1.md. Fold the premortem answer into Assumptions and Risks, apply the requested edits, resolve each open decision as answered, keep Appendix A intact. Write the final PRD to . Set status 'final' in /run.json. Return the path and a five-line summary." + prompt: "Read docs/PRD.md and /gate-1.md (the review comments and how each was applied, or the note that the file was edited directly). Fold the premortem answer into Assumptions and Risks, resolve each open decision as answered, keep Appendix A intact, and check the result against Part B of ${CLAUDE_PLUGIN_ROOT}/skills/prd-artifact/SKILL.md. Write docs/PRD.md. Set status 'final' in /run.json. Return the path and a five-line summary." }) ``` -Print the output path and the run directory. Suggest `/devlog` for the decision memo if the user has the devlog skill. +Say: "Your PRD is finished: `docs/PRD.md`. Next: run `/ck:next`." If the devlog skill is installed, add that `/devlog` can record the reviewers' memo from `docs/decisions/`. ```` -## Appendix D. `skills/prd-artifact/SKILL.md` +## Appendix E. `skills/next/SKILL.md` + +````markdown +--- +name: next +description: Says what to run next, in one sentence, by looking at which documents exist. Use when you do not know where to start or what comes after the step you just finished. +disable-model-invocation: true +--- + +Look at the project and say exactly one thing. Plain words. No model names, no token counts, no more than one action. + +Check, in order: + +1. Does `docs/brief.md` exist? +2. Does `docs/PRD.md` exist, and what does the latest `.ck/runs/*/run.json` say its `status` is (if any)? +3. Does `docs/decisions/` contain anything? + +Then say: + +| State | Say | +|---|---| +| No `docs/brief.md` | "Start with `/ck:brief` and describe your idea in a sentence. It takes about a minute and writes `docs/brief.md`." | +| Brief, no PRD | "Run `/ck:prd`. It turns the brief into full requirements and takes a few minutes." | +| PRD exists, status is a stopped stage | "Your PRD stopped partway. Everything so far is in `docs/PRD.md`. Run `/ck:prd` again to continue." | +| PRD exists, status `review` | "Your PRD is waiting for your review. Open `docs/PRD.md` (or the review page), make any changes, then run `/ck:prd` again." | +| PRD exists, status `final` or unknown | "The PRD is done. When you have a decision to make, run `/ck:panel` followed by your question. The next stages (brand guide, roadmap) are not installed yet." | + +Do not run any agent. Do not explain how the tool works unless asked. +```` + +## Appendix F. `skills/prd-artifact/SKILL.md` ````markdown --- name: prd-artifact -description: The Code Katz PRD contract: section order, required fields, and the checklist a PRD must pass. Load when writing, revising, or validating a PRD, inside or outside a ck workflow. +description: The Code Katz contract for a product brief (Part A) and a PRD (Part B): section order, required fields, and the checklist each must pass. Load when writing, revising, or validating a brief or a PRD, inside or outside a ck workflow. user-invocable: false --- -# The PRD contract +# The brief and PRD contract -A PRD written to this contract has the same shape every time, in every project. Consistency comes from this file, not from who writes it. +A document written to this contract has the same shape every time, in every project. Consistency comes from this file, not from who writes it. Plain words throughout: the author may not be technical. + +# Part A: the brief (`docs/brief.md`) ## Section order Use these headings verbatim, in this order. +1. `## Idea`: the author's idea, in their words, one paragraph. +2. `## Problem and root-cause chain`: the person's pain, not the solution. The chain written out (idea, why, why, why), each step more specific, ending at a root cause or at "this addresses a symptom", and saying which. +3. `## User`: one main person, specific enough to recognize. +4. `## Success metric and leading indicator`: one number, a target, a date; one early sign to watch. +5. `## Scope`: the smaller first version (what it keeps, what it leaves out, whether it would still move the number) and River's recommendation, with the decision marked open unless the author has made it. +6. `## Non-goals`: at least two things this will not do. +7. `## Open questions for the author`: anything River could not answer, each with the assumption used meanwhile. Present even when empty. + +## Checklist A + +1. Every Part A section is present, in order, with its heading verbatim. +2. Problem names the person's pain and the chain reaches a root cause or says it stops at a symptom. +3. User is one person, not a category. +4. Success metric has a number, a target, and a date, plus one leading indicator. +5. Scope names what the smaller version leaves out and carries a recommendation. +6. Non-goals has at least two entries. + +# Part B: the PRD (`docs/PRD.md`) + +## Section order + 1. `## Summary`: three sentences: what, for whom, and the one number that says it worked. -2. `## Problem`: the user pain, not the solution. Cite the root-cause chain (solution → why → why → why) and say whether it reached a root cause or a known symptom. -3. `## User`: one primary user, specific enough to recognize. -4. `## Success metric and leading indicator`: one number, a target, a date; one leading indicator. -5. `## Scope`: the decision taken (V0 or full, with rationale) and the V0 counter-proposal: what it keeps, what it cuts, whether it would still move the metric. -6. `## Non-goals`: at least two, each a thing this will explicitly not do. -7. `## Requirements`: numbered. Each has at least one acceptance criterion a reader could verify without asking the author. +2. `## Problem`: the pain, not the solution. Cite the root-cause chain from the brief and say whether it reached a root cause or a known symptom. +3. `## User`: one main person, from the brief. +4. `## Success metric and leading indicator`: from the brief, restated. +5. `## Scope`: the decision taken (smaller version or full, with the reason) and the smaller version River would still propose: what it keeps, what it leaves out, whether it would still move the number. +6. `## Non-goals`: at least two. +7. `## Requirements`: numbered. Each has at least one acceptance criterion a reader could check without asking the author. 8. `## Sequencing and dependencies`: what must be true before this can ship; what depends on what. -9. `## Assumptions`: every assumption the document rests on, including the one the premortem exposed. -10. `## Risks`: what would cause this to fail, with a mitigation or an explicit acceptance. +9. `## Assumptions`: every assumption the document rests on, including the one the premortem exposes. +10. `## Risks`: what would cause this to fail, each with a mitigation or an explicit acceptance. 11. `## Open questions`: every decision left to the author. -12. `## Appendix A. Challenged claims`: claim | challenged by | severity | status | resolution. Nothing deleted. +12. `## Appendix A. Challenged claims`: claim | challenged by | severity | status | resolution. Nothing deleted. The reviewers' disagreements and kill conditions reproduced verbatim below the table. 13. `## Appendix B. Premortem`: the scenario, the exposed assumption, and the question "What went wrong?" verbatim. ## Claim tags -Every claim not taken directly from the brief carries an inline tag `[C1]`, `[C2]`, ... in the body. Appendix A addresses tags by id. A tag no lens challenged is listed there as unchallenged. - -## File path +Every claim not taken directly from the brief carries an inline tag `[C1]`, `[C2]`, ... in the body. Appendix A addresses tags by id. A tag no reviewer challenged is listed there as unchallenged. -Default `plans/--prd.md`, next to the archived plans. The author may choose another path at Gate 0. +## Checklist B -## Checklist - -A validator checks each item by reading. Each is a statement that is true or false. - -1. Every section above is present, in order, with its heading verbatim. -2. Problem names the user pain, not the solution, and cites the root-cause chain. +1. Every Part B section is present, in order, with its heading verbatim. +2. Problem names the pain, not the solution, and cites the root-cause chain. 3. Success metric is one number with a target and a date, plus one leading indicator. -4. Scope records the V0 or full decision and the V0 counter-proposal with what it cuts. +4. Scope records the decision and the smaller version with what it leaves out. 5. Non-goals has at least two entries. -6. Every requirement has at least one acceptance criterion a reader could verify without asking the author. +6. Every requirement has at least one acceptance criterion a reader could check without asking the author. 7. Every claim not from the brief carries a `[C]` tag, and every tag appears in Appendix A or is marked unchallenged. 8. Assumptions includes the assumption the premortem exposed (or, before the premortem exists, says the premortem is pending). 9. Open questions lists every decision left to the author. 10. No em-dashes in prose. Em-dashes are acceptable only as separators in structured lists. +## File paths + +`docs/brief.md` and `docs/PRD.md`, committed with the project. Decision memos from reviewers go to `docs/decisions/`. The author may choose other paths when running the commands. + ## Writing -Plain technical English: name the actor, one instruction per sentence, no filler, no loss of precision. Second person is fine for the user; third person for the system. +Plain technical English: name the actor, one instruction per sentence, no filler, no loss of precision. Second person is fine for the reader; third person for the system. ```` -## Appendix E. `agents/river.md` as generated (excerpt) +## Appendix G. `agents/river.md` as generated (excerpt) ```markdown --- @@ -1368,19 +1706,29 @@ You are running as a delegated subagent. When the prompt names a run directory, The `model` line shows the value after the team-cli tiers PR (§8.4). Before that PR it reads `claude-fable-5`, verbatim from today's `tiers.conf`. -## Appendix F. Cost model +## Appendix H. Cost model Prices per million tokens from the pricing page read 2026-09-05 [D]: Fable 5.1 $10 in / $50 out; Opus 5 $5 / $25; Sonnet 5 $2 / $10; Haiku 4.5 $1 / $5. Token counts are assumptions [P] for a one-page context document; the newer tokenizer produces about 30% more tokens than these figures assume [D]. No prompt-cache sharing between lenses (§3.3 item 15). Neutral agents assumed on Opus 5 (the session model). +### `/ck:brief` + +| Agent | Model | Input | Output | Cost | +|---|---|---|---|---| +| river draft | Opus 5 | 12k | 4k | $0.16 | +| validator | Haiku 4.5 | 8k | 1k | $0.01 | +| **Total** | | | | **about $0.17**, plus about $0.15 if one revision runs | + ### `/ck:panel` | Agent | Model | Input | Output | Cost | |---|---|---|---|---| -| river (product) | Opus 5 | 16k | 3k | $0.16 | -| toni (marketing) | Fable 5.1 | 16k | 3k | $0.31 | -| kai (ux) | Sonnet 5 | 16k | 3k | $0.06 | -| synthesis | Opus 5 | 20k | 4k | $0.20 | -| **Total** | | | | **about $0.73** | +| river (product) | Opus 5 | 18k | 3k | $0.17 | +| toni (marketing) | Fable 5.1 | 18k | 3k | $0.33 | +| kai (ux) | Sonnet 5 | 18k | 3k | $0.07 | +| synthesis | Opus 5 | 22k | 5k | $0.24 | +| **Total** | | | | **about $0.80** | + +Per-lens evidence and the second pass over the rationale add about 2k input tokens per lens over the earlier estimate. ### `/ck:prd` (the `prd-draft` workflow) @@ -1388,15 +1736,15 @@ Prices per million tokens from the pricing page read 2026-09-05 [D]: Fable 5.1 $ |---|---|---|---|---| | river draft | Opus 5 | 20k | 8k | $0.30 | | validator | Haiku 4.5 | 15k | 1k | $0.02 | -| panel (above) | mixed | | | $0.73 | +| panel (above) | mixed | | | $0.80 | | river synthesize | Opus 5 | 35k | 10k | $0.43 | -| **Total, no revision** | | | | **about $1.48** | +| **Total, no revision** | | | | **about $1.55** | | one revision (validator again plus River revise) | | | | + about $0.32 | | finalize (inline, Opus 5) | | 30k | 8k | + about $0.35 | -Call it $1.50 to $2.20 per PRD plus the main session's own gate turns. Concurrency: min(16, CPUs minus 2) [D]; on a 4-CPU laptop the panel runs in one round and `prd-draft` in about four sequential steps, since its stages depend on each other. +Call it $1.60 to $2.30 per PRD plus the main session's own turns. Concurrency: min(16, CPUs minus 2) [D]; on a 4-CPU laptop the panel runs in one round and `prd-draft` in about four sequential steps, since its stages depend on each other. `/ck:next` costs one main-session turn and runs no agents. -## Appendix G. Sources +## Appendix I. Sources Documentation, verified 2026-09-05: @@ -1414,4 +1762,9 @@ Family record [R]: - `claude-conductor`: `DEVLOG.md` (2026-07-04), `docs/2026-07-03-fable-harness-modernization-analysis.md`, `docs/2026-07-04-agent-teams-spike.md`, branch `claude/research-desktop-tile-updates-BJqoP` - `claude-plugins`: `.claude-plugin/marketplace.json` v1.3.0 +The cross-model panel, 2026-09-05: + +- The Opus PRD, its panel brief, and its workbench mockups: `plans/opus/` +- The panel memo recording what was adopted and rejected, with reasons: `plans/2026-09-05-ck-prd-panel-memo.md` + Research [M], [V]: as listed in the proposal's §10; this PRD adds none. diff --git a/plans/2026-09-05-ck-prd-panel-memo.md b/plans/2026-09-05-ck-prd-panel-memo.md new file mode 100644 index 0000000..3979da3 --- /dev/null +++ b/plans/2026-09-05-ck-prd-panel-memo.md @@ -0,0 +1,94 @@ +# Panel memo: the `ck` phase-one PRD against the Opus PRD + +> **Date:** 2026-09-05 +> **Question:** Should the `ck` phase-one PRD change in light of the Opus-written PRD, its panel brief, and its workbench mockups? +> **Inputs under review:** [`plans/opus/2026-09-05-prd-code-katz.md`](opus/2026-09-05-prd-code-katz.md), [`plans/opus/2026-09-05-panel-review-brief.md`](opus/2026-09-05-panel-review-brief.md), [`plans/opus/2026-09-05-workbench-concepts.html`](opus/2026-09-05-workbench-concepts.html), against [`plans/2026-09-05-ck-plugin-prd-phase-1.md`](2026-09-05-ck-plugin-prd-phase-1.md) +> **Lenses that ran:** one. Fable 5.1 took the engineering lens from the brief (verify the load-bearing claims against current documentation), with the repos as extra evidence. The product and UX lenses did not run. This memo follows the brief's synthesis format anyway, so the gaps are visible. +> **Decision:** Will's. Recorded in section 7. + +--- + +## 1. Input difference, stated first + +The Opus PRD was written from the research proposal alone. It never mentions claude-conductor, the seven marketplace plugins, or team-cli's recorded decisions, and it repeats the proposal's persona count of 22. Some of its gaps are missing inputs, not weaker reasoning. The `ck` PRD had the repos and the docs as read on 2026-09-05; its gaps run the other way: engineering-complete, product-thin. + +## 2. Agreement (low-information) + +Both documents agree on: a plugin on native Claude Code primitives with no orchestration of its own; `/panel` in phase one; three lenses on Opus 5, Fable 5.1, and Sonnet 5 with a forced argument against the lens's own recommendation; a synthesis that surfaces disagreement and never resolves it; unanimous panels as a failure signal; a live activity view duplicating `/workflows`; a workflow editor as a trap; hooks as the telemetry spine. + +Per the brief, agreement is either obviously true or a shared blind spot. Judgment: obviously true for the first six, because each follows from a documented constraint. The last two are shared judgment, not fact, and the Opus PRD's own sizing table is the only evidence for them. + +## 3. Disagreement, both positions at full strength + +| Topic | Opus PRD | `ck` PRD | What decides it | +|---|---|---|---| +| Who the design is for | Will's wife is the harder user and wins conflicts; she never approves in a UI, never sees a model name | Designed for Will: a ten-question interview, model names in a question, flags | Whether user 2 is the customer. Both authors say yes. Only Opus designed for it | +| How a human signs off | The file is the gate: read it, edit it, run the next command | A gate in the skill, using questions in the terminal; later, a review page with comments | The docs allow both. The file gate works for user 2; the review page works for both once its availability is proven | +| Where state lives | Artifacts at conventional committed paths; the plugin keeps no private state | A hidden run directory holds the brief, drafts, and memos, excluded from git | "The artifact is the state" survives a fresh session and a new machine; a hidden directory does not | +| Composing workflows | "There is no `workflow()` primitive" | `workflow()` exists, one level deep | The harness reference. Opus is wrong | +| Model policy | Effort first, then the Advisor, then a model switch; fallback on quota via a hook; pause mid-run to arbitrate | Tiers in agent files; one override in the panel; null-tolerant scripts; no mid-run pause | The docs: no mid-run input, and the hook fires only on a requested session switch. Opus's mechanism does not exist as described | +| Quality gates | Hooks reject malformed output with exit code 2 | Schema-forced output plus a validator agent inside the workflow | Plugin agents ignore per-agent hooks; the subagent hook's feedback path is undocumented | +| team-cli | Retired at Phase 1 (§1) or Phase 5 (§9) | Coexists; revisit at 90 days | Opus contradicts itself, and a plugin cannot provide the shell commands team-cli owns | +| Persona roster | 22; a core of 9 that omits Alex, Morgan, Sage, Jordan while tiering them | 21, all generated from upstream, prune on evidence | The repo has 21 profiles | + +## 4. Kill conditions + +**Engineering lens on the Opus PRD:** if a workflow cannot pause for input and `PreModelSwitch` cannot catch a subagent quota failure, then goal G3, principles P9 and P10, section 7.8, journey J2 step 6, and the Economics mockup's "Model resolution" table cannot be built as written. The docs show both. Met. This kills the "policy resolves the model" pillar, not the document. + +**Engineering lens on the `ck` PRD:** if Will's wife cannot produce a PRD without answering an interview in a terminal or opening `.ck/`, the design as specified should not be built. The document shows this: section 7.3 requires ten answers before anything runs. Met. Changes A1 to A3 below exist to remove it. + +## 5. Unique findings (one lens saw them) + +1. The Opus PRD retires `TODOS.md`, which is a shipped marketplace plugin with its own repository and published posts. That is a product decision for that repository, not a line in this PRD. +2. The Opus workbench's persona editor writes `agents/toni.md` in place. An installed plugin is a copy under the user's plugin directory and is replaced on update, so edits there are lost. Any editor must write the source checkout and run the generator. +3. The Opus telemetry plan rebuilds cost parsing that claude-conductor already has, fixture-fenced, with a pricing table. +4. The Opus PRD's "prior stages replay from cache" holds only within one session or a resumed one. A fresh session needs a start-at-stage argument that reads artifacts from disk. The Opus PRD describes that mechanism in §7.4 and then contradicts it in §7.11. +5. The Opus PRD never states the plugin's `name`, which fixes the `/katz:` prefix. +6. The mockups' colour code (hue for model, shade for effort) passes only because each block also carries a text label. The swatch legend alone would not. + +## 6. What nobody checked + +- Whether the Artifact tool (the review page) is available in Will's local Claude Code, as opposed to this web session. It is now a Phase 0 spike. +- Whether `agentType` with a frontmatter model honors the tier inside a running workflow. Both PRDs assume it. Phase 0 spike. +- Whether a nested workflow prompts for consent separately. Phase 0 spike. +- A user-2 test of the panel's own output: can she read a decision memo and act on it. Neither PRD has one. +- The panel brief's model table swaps the marketing lens for an engineering lens while saying it matches the PRD. Fine for reviewing a PRD; not what it claims. + +## 7. Decision and record + +Will's decision, 2026-09-05: keep the `ck` PRD as the base and adopt nine changes from the Opus PRD plus the review-page idea. Rejections carry the reason. + +### Adopted + +| # | From the Opus PRD | Change to the `ck` PRD | +|---|---|---| +| A1 | Users table, journey J1, failure rules, "done when she produces a PRD without touching a file" | Users table and J1 added; the three failure rules adopted; user-2 done criterion added | +| A2 | `brief` before `prd`; the file is the gate | `/ck:brief` added; the interview becomes optional; Gate 1 is a review page with a file-edit fallback | +| A3 | The artifact is the state; conventional committed paths | `docs/brief.md`, `docs/PRD.md`, `docs/decisions/`; the run directory becomes a cache; resume by start-at stage | +| A4 | Each lens reads different evidence | Per-lens `reads` list in the panel | +| A5 | Persona sets the model floor; the stage sets effort | Effort per stage in scripts; never in persona files | +| A6 | Phase 0 spikes | Phase 0 added with five spikes; the `PreModelSwitch` spike is answered: no | +| A7 | `/next` | `/ck:next` promoted to phase one | +| A8 | Three persona scopes | Adopted as the shape of the 90-day prune; all 21 still generated from upstream | +| A9 | Goals with a measure each | Goals table | +| A10 | (Will's idea, neither PRD) | Review pages with comments as the feedback channel for documents and mockups | + +### Rejected, with reasons + +| # | Opus PRD claim | Reason | +|---|---|---| +| W1 | No `workflow()` primitive | It exists, one level deep | +| W2 | Pause a running workflow to arbitrate | Workflows accept no mid-run input; contradicts its own P6 | +| W3 | Quota fallback via `PreModelSwitch` | The hook fires on a requested session switch only | +| W4 | Gates via `Stop` or `TaskCompleted` hooks | Wrong event for subagents; feedback path undocumented; plugin agents ignore per-agent hooks | +| W5 | Retire team-cli at Phase 1, or Phase 5 | Contradiction; the plugin cannot provide shell commands | +| W6 | 22 personas; a core list that omits four it tiers | The repo has 21; the split is inconsistent | +| W7 | Retire `TODOS.md` | Out of scope; a shipped plugin | +| W8 | `maxBudgetUsd` in agent frontmatter | Not in the documented frontmatter table | +| W9 | Persona editor writes the installed agent file; telemetry ignores conductor | Installed copies are replaced on update; conductor already parses cost | +| W10 | `commands/` for persona switches | The docs say new plugins use `skills/` | +| W11 | Re-runs replay from cache | Only within a session; a fresh session needs start-at | + +### Panel health + +Agreement rate cannot be computed from one lens. The brief's threshold ("above roughly two-thirds agreement the panel is theater") is recorded as the target for when `/ck:panel` runs this comparison properly, with three lenses that have not seen each other. diff --git a/plans/opus/2026-09-05-panel-review-brief.md b/plans/opus/2026-09-05-panel-review-brief.md new file mode 100644 index 0000000..0cb009c --- /dev/null +++ b/plans/opus/2026-09-05-panel-review-brief.md @@ -0,0 +1,174 @@ +# Panel Review — handoff brief + +How to get an adversarial review of `PRD-code-katz.md` and `workbench-concepts.html` from other agents. This is `/katz:panel` executed by hand, on its own PRD. + +--- + +## Mechanics + +**Run each lens in its own session.** Not three lenses in one conversation — the second lens would read the first's argument and anchor to it, which is the exact failure the panel design exists to prevent. Three separate sessions, opened in `~/development/code-katz` so each can read the files directly. + +**Use a different model per lens**, matching the PRD's own assignment. Set it with `/model` before pasting. + +| Lens | Model | Why | +|---|---|---| +| Product | Opus 5 | Must hold the whole picture | +| Engineering | Fable 5.1 | Deepest reasoning; this is the lens most likely to find a structural flaw | +| UX | Sonnet 5 | Narrow, concrete, argues from the mockups | + +**What to share, and when.** Give each lens only: + +- `PRD-code-katz.md` +- `workbench-concepts.html` + +**Do not give them `2026-09-05-agent-workflows-research-and-proposal.md` up front.** It contains the justification for every decision in the PRD, and a reviewer who reads it first will tend to ratify rather than test. Mention it exists and let them consult it *after* forming an initial view, to check whether a claim is supported. That ordering is the whole point. + +--- + +## Lens 1 — Product + +``` +You are reviewing a PRD as a product lens. Read PRD-code-katz.md and open +workbench-concepts.html in this folder. + +Context: a personal developer toolchain for two people — Will (technical) and +his wife (non-technical, has shipped several iOS apps with Claude). It turns +repeatable product stages into named commands. + +Review for product soundness only. Stay in your lane: not implementation, not +visual design. + +Answer these, in order: + +1. Is this solving a real problem, or an interesting one? Name the strongest + evidence in the doc that it is real, and the weakest. +2. Does it serve BOTH users, or is user 2 an afterthought dressed up as a + priority? Journey J1 is the claim — assess whether the rest of the document + actually honours it. +3. What is missing that a product person would insist on before build? +4. Which of the 12 commands would you cut, and why? +5. Phasing: is Phase 1 the right first slice? What would you ship first instead? + +Then end with two things, both mandatory: + +- THE STRONGEST ARGUMENT AGAINST YOUR OWN RECOMMENDATION. +- THE KILL CONDITION: state the specific, observable thing that would mean this + should not be built at all, and say whether the document already shows it. + +Be direct. A review where you agree with everything is a failed review. +``` + +--- + +## Lens 2 — Engineering + +``` +You are reviewing a PRD as an engineering lens. Read PRD-code-katz.md in this +folder. Skim workbench-concepts.html for what the UI implies about data. + +Context: this is built entirely on Claude Code native primitives — dynamic +workflows, subagents, skills, hooks, plugins. It deliberately owns no +orchestration of its own. + +Review for buildability and structural soundness. Stay in your lane: not +product strategy, not visual design. + +Answer these, in order: + +1. The design rests on claims about how Claude Code works. Verify the load- + bearing ones against current documentation at code.claude.com/docs. Flag + anything that is wrong, stale, or unverifiable. This is the most valuable + thing you can do — the author verified against docs, not against runtime. +2. Phase 0 lists three spikes. Are they the right three? What fourth thing + should be proven before building? +3. Where will this break in ways the doc does not anticipate? Be specific + about the failure, not the category. +4. §7.5 runs slices in parallel git worktrees with a frozen interface + contract. Is that sound, and is the contract as specified sufficient? +5. The workbench is read-only by constraint. Is that constraint stable, or + will it break within a month of real use? + +Then end with two things, both mandatory: + +- THE STRONGEST ARGUMENT AGAINST YOUR OWN RECOMMENDATION. +- THE KILL CONDITION: the specific technical finding that would mean this + should not be built as specified. + +Cite doc URLs for anything you verify or refute. +``` + +--- + +## Lens 3 — UX + +``` +You are reviewing a PRD and a set of mockups as a UX lens. Open +workbench-concepts.html in this folder first and look at all five tabs, then +read PRD-code-katz.md — especially §6 (user journeys) and §7.11 (failure +handling). + +Context: two users. Will is technical. His wife is not, and she is the harder +constraint — the doc states that where they conflict, she wins. + +Review for whether these two people will actually succeed. Stay in your lane: +not architecture, not product strategy. + +Answer these, in order: + +1. Walk journey J1 as Will's wife. Where does she get stuck, confused, or + quietly give up? Be specific about the moment. +2. §7.11 is the failure UX. Is it sufficient? What failure is not covered? +3. The mockups: five concepts. Which would you build, which would you delete, + and what is missing from all five? +4. The colour system encodes model as hue and effort as shade. Does that + actually communicate, or is it decoration? Consider accessibility. +5. "Building should be fun" is goal G7. Does this design deliver that, or + does it make an enjoyable thing into an administered one? + +Then end with two things, both mandatory: + +- THE STRONGEST ARGUMENT AGAINST YOUR OWN RECOMMENDATION. +- THE KILL CONDITION: the specific usability finding that would mean this + should not be built as specified. + +Reference specific screens and journey steps, not general principles. +``` + +--- + +## Synthesis + +Run last, in a fourth session, on **Opus 5**. Paste all three lens outputs. + +``` +Three independent reviews of the same PRD are below, from a product lens, an +engineering lens, and a UX lens. Each ran in isolation on a different model and +did not see the others. + +Your job is to surface where they DISAGREE, not to resolve it. + +Produce: + +1. AGREEMENT — where all three concur. Flag this section as low-information: + if they agree, either it is obviously true or all three share a blind spot. + Say which you think it is. +2. DISAGREEMENT — every point where two lenses conflict. State both positions + at full strength. Do not adjudicate. +3. THE THREE KILL CONDITIONS, verbatim. Then say whether the PRD already + contains evidence that any of them is met. +4. UNIQUE FINDINGS — anything only one lens saw. These are often the most + valuable and the easiest to lose in a summary. +5. WHAT NOBODY CHECKED — gaps none of the three covered. + +Do not recommend a course of action. The decision is the author's. +``` + +--- + +## Reading the result + +**If all three lenses agree, the panel failed.** The PRD's own §7.6 sets the threshold: above roughly two-thirds agreement, the panel is theater. That applies to this review too. Unanimous approval means the lenses were too similar, the prompts were too leading, or the reviewers were being agreeable — not that the document is good. + +**The engineering lens is the one most likely to find something fatal**, because the whole design rests on documented behaviour that has not been tested against the runtime. Weight that lens accordingly. + +**Bring the disagreements back here.** The research document holds the evidence behind each contested decision, and several of them were argued at length — the cost-versus-quality question on role pipelines, the choice against Agent Teams, the effort-before-model escalation order. A reviewer who reaches a different conclusion may be right, or may be missing a measurement. diff --git a/plans/opus/2026-09-05-prd-code-katz.md b/plans/opus/2026-09-05-prd-code-katz.md new file mode 100644 index 0000000..93fc069 --- /dev/null +++ b/plans/opus/2026-09-05-prd-code-katz.md @@ -0,0 +1,434 @@ +# PRD — Code Katz + +> **Version:** 1.0 +> **Date:** 2026-09-05 +> **Author:** Will Curran +> **Status:** ready for build planning +> **Inputs:** `2026-09-05-agent-workflows-research-and-proposal.md` (evidence and design rationale), `2026-09-05-prd-draft-workbench.md` (superseded by this document) + +--- + +## 1. Summary + +Code Katz turns the repeatable stages of building a product into named, versioned commands that ship with every project. + +`/katz:brief`, `/katz:prd`, `/katz:brand-guide`, `/katz:panel` — each owned by a specialist persona, each producing a specified artifact, each gated. Built entirely on native Claude Code primitives, adding no orchestration of its own. + +Alongside it, a **Workbench** shows what has been run, what it cost, which models and personas did the work, and lets those personas be tuned. It observes; it never launches. + +This replaces `claude-team-cli`, which is retired on completion of Phase 1. + +**One sentence:** the user expresses intent, policy resolves the model, a contract guarantees the artifact, and a gate proves it. + +--- + +## 2. Background + +Will and his wife build and maintain real products with Claude. The current practice is manual: open a session, "use Akira"; open another, "use Toni." It works, and it is enjoyable, but it has three failures. + +**Output is inconsistent.** A product should begin with an opportunity exploration, then a PRD, then a brand guide — and there is a specific way a brand guide should be done, with specific expected assets. Nothing enforces any of this. The 22 personas own no artifact formats, so output varies between runs and between projects. + +**Nothing is repeatable across projects.** Every new product re-derives the process from memory. The stages exist in Will's head, not in a file. + +**Nothing is visible.** There is no way to see what ran, what it cost, which model did the work, or — over months — which personas earn their keep. + +A fourth consideration is not a failure but a requirement: **building should be fun.** The persona metaphor is what makes it fun, and a redesign that optimizes it away has failed regardless of how it benchmarks. + +### 2.1 What the research settled + +Full evidence in the research document. Four findings govern this design. + +**Role pipelines are worse, not merely pricier.** Decomposing one build task across specialist roles measures 8–40pp worse at 3–10× the tokens. The cause is handoff loss and conflicting implicit decisions — a property of topology, not of the persona string. **Consequence:** one writer per slice, no mid-feature handoffs. + +**Persona strings are inert for correctness; profile content is not.** "You are a senior backend engineer" buys nothing measurable. A specific checklist, a required output shape, and a domain constraint buy a lot. **Consequence:** the artifact contract does the work, and the persona is the interface. + +**Cross-model verification is where extra spend buys better output.** A different model reviewing against a real oracle: +18.1pp. The same model reviewing itself: ±0 at +72% cost. **Consequence:** gates run a different persona on a different tier against an executable oracle. + +**One-at-a-time review beats a queue.** 38% faster, 93% vs 80% accuracy. **Consequence:** never a review queue, and because workflows accept no mid-run input, sign-off points are command boundaries. + +--- + +## 3. Users + +| | **Will** | **Will's wife** | +|---|---|---| +| Technical? | Yes — reads and writes code, comfortable in files | No — has shipped several iOS apps with Claude and claude-team-cli | +| Wants | Repeatability, adversarial input on decisions, visibility into cost and activity, a place to tune personas | To express intent and receive a good artifact | +| Tolerates | Multiple commands, JS, terminal output, cost decisions | One command at a time, plain language, no model names | +| Fails when | The tool is slower than doing it himself | A command errors and she cannot tell what to do next | + +**User 2 is the harder constraint and the more important one.** Every surface must work for someone who will never open `workflows/prd.js`. Where the two users conflict, she wins, and Will gets an escape hatch. + +--- + +## 4. Goals + +| | Goal | Success measure | +|---|---|---| +| **G1** | **Consistency** — the same stage produces the same artifact shape every time | Two PRDs from different projects have identical section structure; validators pass on both | +| **G2** | **Repeatability** — stages ship with every project | A fresh project has all commands available after one install | +| **G3** | **Right model for the work** — tier follows the job, availability-aware | Zero manual reruns caused by quota exhaustion | +| **G4** | **Adversarial input** — real disagreement on judgment calls | Panel lenses reach different recommendations more than a third of the time | +| **G5** | **Visibility** — activity, models, tokens, cost, live and historical | Will can answer "what did last month cost, and which personas did I actually use" | +| **G6** | **Tunability** — a place to build and maintain personas | A persona is tuned without opening a text editor | +| **G7** | **Fun** — the persona metaphor survives and gets sharper | Will still uses it after 90 days | + +### Non-goals + +- **Not a harness.** We do not own the agent loop, model client, permissions, caching, or context management. +- **Not an orchestrator.** Dynamic workflows are the orchestrator. +- **Not multi-user.** Two people, local machines, no server, no auth, no sync. +- **Not a model picker.** No upfront model choice. An explicit override stays, and the system may arbitrate at genuine tradeoff points (P10). +- **Not a launcher.** The Workbench never starts work. + +--- + +## 5. Principles + +| # | Principle | +|---|---| +| **P1** | **The artifact spec does the work; the persona is the interface.** Every stage names an owning persona *and* the contract it must satisfy. A persona without a contract is decoration | +| **P2** | **One writer per slice.** Build work is decomposed by context boundary, never by job title | +| **P3** | **Verification is the only legitimate handoff.** Gates use a different persona, a different tier, and a real external oracle | +| **P4** | **Sequential by default.** Parallelize only when a frozen interface contract exists | +| **P5** | **One review at a time.** Never a queue | +| **P6** | **Sign-off points are command boundaries.** Workflows take no mid-run input | +| **P7** | **Panels vary the model, not just the prompt** — and vary the *inputs* more than the model | +| **P8** | **Build nothing the harness already does** | +| **P9** | **Effort before model.** Difficulty belongs to the task. Dial effort first, then the Advisor, then a model switch | +| **P10** | **Arbitrate, don't ask up front.** Pause and ask Will only when a tradeoff becomes legible. Never ask user 2 | +| **P11** | **Extend the native practice; never reimplement it.** Name the feature you would duplicate before building | + +--- + +## 6. User journeys + +### J1 — Will's wife starts a new product + +*The primary journey. If this is not delightful, nothing else matters.* + +1. She has an idea for an app. She creates a folder and opens Claude Code in it. +2. She types `/katz:` and autocomplete shows the available stages. She does not know where to start, so she runs **`/katz:next`**. +3. It sees an empty project and replies: *"Start with `/katz:brief` — it captures the problem, who it's for, and what success looks like. Takes about two minutes."* +4. She runs **`/katz:brief`** and describes her idea in her own words. Three agents run. A minute later `docs/brief.md` exists: problem, user, success metric, one page. +5. She reads it. The problem statement is not quite right, so she **edits the file directly** and saves. No approval UI, no command. +6. `/katz:next` now says: *"`/katz:prd` — turns the brief into full requirements."* She runs it. It reads her edited brief. Twelve agents run over several minutes; the progress line shows phases completing. +7. `docs/PRD.md` appears. A gate has already checked it against the contract — every required section present, every requirement numbered and testable. +8. `/katz:next` suggests `/katz:brand-guide`. She continues. + +**What she never does:** choose a model, learn what a subagent is, sequence the stages herself, approve or reject anything in a UI, or see a token count. + +### J2 — Will implements a roadmap feature + +1. `ROADMAP.md` has a Tier 1 item: offline sync. He runs **`/katz:plan-feature offline sync`**. +2. It enters **plan mode** — the native one — explores the codebase, and proposes an approach. Will iterates with it in conversation until the shape is right, then approves the plan. +3. The workflow adds the two things plan mode does not produce: a decomposition into **vertical slices** (each owning a feature plus its tests plus its docs), and a **frozen interface contract** naming every decision two slices could otherwise resolve differently. It archives to `plans/2026-09-12-offline-sync.md` through the existing plans contract. +4. Will reads the plan. **This is the checkpoint that matters** — it is cheap and it governs everything expensive that follows. He notices the contract leaves an error case ambiguous, edits that line, and saves. +5. He runs **`/katz:feature`**. The plan's manifest says this feature has a UI surface and is user-visible, so all six phases run: + - **Design** — Kai produces a mockup for the sync-status UI. This gates frontend work. + - **Build** — three slices in parallel, each in its own git worktree, one persona each. + - **Verify** — each slice checked by a different persona on a different tier, running the actual test suite. + - **Merge** — sequential, one at a time, base suite green before the next. + - **Content** — Toni writes the release note, from behavior that now exists. +6. Partway through, a verify gate fails twice at `high` effort. The system **arbitrates**: *"Slice 2 verification failed twice. Retry at `xhigh` (~$0.40 more), or escalate to Fable 5.1 (~$1.10 more)? [default: xhigh]"* Will presses return. +7. Done. He opens the diff, reads the release note, and ships. + +### J3 — Will decides whether to build a feature + +1. He is unsure whether to add social sharing. He runs **`/katz:panel should we add social sharing to the app?`** +2. Three lenses run in parallel on different models, each reading different evidence: River reads the PRD and roadmap; Toni reads competitor positioning; Kai reads the actual screens. +3. Each returns a recommendation, its **strongest argument against itself**, and **the specific condition that would make it say no**. +4. A synthesis agent surfaces where they disagree — Toni says yes for acquisition, Kai says the share sheet has nowhere to live without a nav redesign — and **does not resolve it**. +5. `docs/decisions/003-social-sharing.md` is written. Will decides. + +*If all three agree, the output says so prominently, because unanimous panels are a signal that the panel is not working.* + +### J4 — Will tunes a persona + +1. Toni's marketing copy keeps coming out too long. He opens the **Workbench** and finds Toni. +2. He sees Toni's model tier, budget, and profile body, plus how often Toni has run in the last 30 days and what it cost. +3. He adds a constraint to the profile body: a hard word ceiling for release notes. The editor validates the frontmatter and shows a diff. +4. He saves. The Workbench writes `agents/toni.md`. Next run picks it up. + +### J5 — Will reviews the month + +1. He runs `/katz:report` and a static HTML file opens in his browser. +2. Spend by project, by workflow, by persona, by model. Run counts and outcomes. Gate pass rates. +3. Two things stand out: `/katz:market-research` on Fable 5.1 is a third of his spend, and four personas have not run in 90 days. +4. He moves those four to the relevant project's `.claude/agents/` and drops the market-research default to Opus 5 to see whether quality holds. + +--- + +## 7. The Plugin + +### 7.1 Structure + +``` +code-katz/ +├── plugin/ +│ ├── .claude-plugin/plugin.json +│ ├── workflows/*.js # stages — native dynamic workflows +│ ├── agents/*.md # personas — native subagent definitions +│ ├── commands/*.md # persona slash-commands (/katz:akira) +│ ├── skills/*/SKILL.md # artifact contracts +│ └── hooks/hooks.json # gates + telemetry +└── workbench/ + ├── server/ + └── ui/ +``` + +Distributed through a GitHub marketplace. One install. + +### 7.2 Layer responsibilities + +| Layer | Owns | Never does | +|---|---|---| +| **Workflow** | Order of stages, fan-out, synthesis | Holds domain knowledge | +| **Persona** | Voice, domain constraints, model tier, tool scope, budget | Defines output format | +| **Artifact contract** | Template, section structure, checklist, validator | Decides who runs it | +| **Gate** | Rejects malformed output, emits telemetry | Modifies content | +| **Workbench** | Observes, aggregates, edits personas | Launches work | + +### 7.3 Command catalog + +| Command | Stage | Owner | Artifact | +|---|---|---|---| +| `/katz:next` | Suggest the next stage | — | none | +| `/katz:opportunity` | Explore the opportunity | River | `docs/opportunity-brief.md` | +| `/katz:market-research` | Market and competitor scan | River + Toni | `docs/market-research.md` | +| `/katz:brief` | Problem, user, success metric | River | `docs/brief.md` | +| `/katz:prd` | Product requirements | River | `docs/PRD.md` | +| `/katz:brand-guide` | Brand and visual system | Iris + Kai | `brand/` + `brand/brand-guide.md` | +| `/katz:roadmap` | Plan the next phase | River + Quinn | `ROADMAP.md` | +| `/katz:plan-feature` | Slices + frozen interface contract | Akira or River | `plans/YYYY-MM-DD-slug.md` | +| `/katz:feature` | Implement, end to end | per slice | code, tests, docs, copy | +| `/katz:bugfix` | Diagnose and fix | Robin → owner | fix + regression test | +| `/katz:gtm` | Go-to-market plan | Toni | `docs/gtm.md` | +| `/katz:panel` | Multi-lens decision input | 3 lenses | `docs/decisions/NNN.md` | +| `/katz:` | Adopt a persona in the current session | — | none | +| `/katz:report` | Generate and open the analytics report | — | `~/.code-katz/report.html` | +| `/katz:workbench` | Start the local workbench server *(v1)* | — | none | + +**There is no shell CLI.** Every surface, including the Workbench, is a `/katz:` command. Nothing goes on `PATH`, there is no `install.sh`, and there are no symlinks to keep in sync — which is exactly the machinery claude-team-cli existed to manage and the plugin makes unnecessary. Install is one marketplace add. + +**Ordering is convention, not enforcement.** `/katz:next` reads which artifacts exist plus roadmap and plan status and suggests. Hard sequencing would fight exploratory use. + +### 7.4 Granularity + +**Default coarse. Checkpoint universally. Split exactly twice.** + +Every workflow writes each stage's artifact as it completes and accepts a starting stage in `args`, so any workflow can resume rather than regenerate. There is no review mechanism to build: the artifact is a file, reviewing means reading it, rejecting means editing it. + +Two splits, both where a cheap early artifact governs an expensive downstream run: + +- `/katz:brief` → `/katz:prd` +- `/katz:plan-feature` → `/katz:feature` + +Everything else is one command. Split later only on felt pain. + +### 7.5 `/katz:feature` + +Six phases, conditional on a manifest the plan phase emits. + +| # | Phase | Who | Gates | Runs when | +|---|---|---|---|---| +| 1 | Plan | Akira or River | Everything | Always — split out as `/katz:plan-feature` | +| 2 | Design | Kai | Any UI slice | Feature has a surface | +| 3 | Build | one persona per slice | — | Always | +| 4 | Verify | different persona, different tier | Merge | Always | +| 5 | Merge | — | Content | Always | +| 6 | Content | Toni | — | Feature is user-visible | + +Two orderings that differ from the obvious: **design gates build** — reacting to a mockup is cheaper than rewriting a component — and **content follows merge** — Toni writes about behavior that exists. + +**Composition is at the skill layer.** There is no `workflow()` primitive, so a workflow cannot invoke another. The content phase writes through the same contract `/katz:gtm` uses: one contract, one place to change it. + +Within build: vertical slices, one persona each, `isolation: worktree`, one writer per slice. The interface contract is **frozen before build starts**. Refuse to parallelize without it. + +Within verify: a different persona on a different tier, whose job is to run the oracle rather than opine, carrying verbatim — *"You MUST run the complete test suite before marking as passed."* + +### 7.6 `/katz:panel` + +| Lens | Persona | Model | Reads | +|---|---|---|---| +| Marketing | Toni | Fable 5.1 | Competitor positioning, market context | +| Product | River | Opus 5 | PRD, roadmap, usage data | +| UX | Kai | Sonnet 5 | Actual screens and flows | +| Synthesis | — | Opus 5 | All three arguments | + +Each lens returns a fixed schema: recommendation, **strongest argument against its own recommendation**, and **the condition that would make it say no**. Synthesis surfaces disagreement and does not resolve it. + +**Three Claude tiers give scale diversity, not independent judgment** — all share one training pipeline, and the measured cross-review result was Claude reviewing *Codex*. The tier spread is the weakest of the three mechanisms. **Differentiated inputs do most of the work**, and the forced disqualifying condition does the rest. + +**Instrument the agreement rate.** Above roughly two-thirds agreement the panel is theater. Cross-vendor via MCP is the documented escalation. + +### 7.7 Personas + +Ported to `agents/*.md`. Frontmatter carries `name`, `description`, `model`, `effort`, `tools`, `maxTurns`, `maxBudgetUsd`, `isolation`. The body carries domain constraints and checklists — the part that measurably works. + +**Three scopes, not one roster:** + +| Scope | Contents | Location | +|---|---|---| +| **Plugin core** | Personas that appear in every project — Akira, Sasha, River, Toni, Kai, Robin, Iris, Quinn, Casey | plugin `agents/` | +| **Project cast** | Domain personas for one product — Reiner, Cornelius, Ernie, Piper, Rez | that project's `.claude/agents/` | +| **User** | Experiments not yet earning a place | `~/.claude/agents/` | + +Half the 22 go unused, but most of those are a project cast in the wrong place, not dead weight. **The exact split is a Phase 0 deliverable** and it sets the port scope. + +### 7.8 Model and effort + +**Two axes.** Persona sets the model floor. The workflow stage sets the effort. Difficulty belongs to the task — Sasha builds both the static marketing page and the dynamic app. + +| Model | Personas | +|---|---| +| Fable 5.1 | None by default — reached by escalation. Default for `/katz:market-research` | +| Opus 5 | Akira, River, Toni, Kai, Iris, Morgan, Sage, Jordan, Quinn, Casey | +| Sonnet 5 | Sasha, Alex, Robin, Piper | +| Haiku 4.5 | `/katz:next`, routing, rollups | + +| Task shape | Effort | +|---|---| +| Mechanical, well-specified | `low`–`medium` | +| Normal implementation | `high` (default) | +| Novel architecture, security-sensitive | `xhigh`–`max` | +| Still short at `max` | escalate to Fable 5.1 | + +**Escalation order: effort → Advisor → model switch.** Effort costs no context rebuild. The Advisor escalates one decision without moving the session. A model switch is last because it is the only one that pays the rebuild. + +**Fallback chain** `fable-5-1 → opus-5 → sonnet-5` with quota detection at the `PreModelSwitch` hook. Resolved model *and* effort recorded per run so per-tier quality stays auditable. + +**Arbitration (P10).** Pause and ask Will when: escalation passes a declared ceiling, a fallback *degrades* capability, or projected cost crosses a threshold. The prompt states what failed, what each option costs in dollars, defaults to safe, and offers "don't ask again for this workflow." **User 2 never sees it.** + +### 7.9 Artifact contracts + +An artifact has two halves: + +- **Contract** — template, section structure, required fields, checklist, validator. Product-agnostic. Lives in the plugin. +- **Instance** — `docs/PRD.md` for one product. Project content, committed to the project repo. + +**Conventional paths** — `docs/`, `brand/`, `ROADMAP.md` at root — not a dotted directory. These deliverables outlive the tool. + +**The plugin keeps no private state in the project.** The artifact is the state: `/katz:next` and stage-resume both work by checking which files exist. + +Enforcement is a `Stop` or `TaskCompleted` hook, exit code 2, returning the specific defect. Output styles cannot do this — they are session-fixed and do not reach subagents. + +### 7.10 State altitudes + +| Altitude | Question | Artifact | Lifetime | +|---|---|---|---| +| Strategic | What to build, in what order | `ROADMAP.md` | Months, committed | +| Execution | How to build this one thing | `plans/*.md` | One effort, committed | +| In-flight | What this run is doing | Native task list | One session | + +`TODOS.md` is **retired** — it sat between the first two and duplicated both. + +Two of three altitudes are already native. Per P11, extend rather than rebuild: `/katz:plan-feature` runs **plan mode** and adds only slices and the interface contract. + +### 7.11 Failure handling for user 2 + +*The difference between a tool she trusts and one she abandons.* + +Three failure classes, three responses: + +| Failure | What she sees | What she can do | +|---|---|---| +| **Validator rejects the artifact** | "The PRD is missing a success metric. Retrying that section." | Nothing — it self-corrects, up to twice | +| **A stage fails after retries** | "I couldn't finish the requirements section. Everything up to it is saved in `docs/PRD.md`. Run `/katz:prd` again to resume from there." | Re-run. Prior stages replay from cache | +| **Quota or availability** | "Claude is at capacity for this model. Waiting, or run `/katz:prd` again in a few minutes." | Wait or retry | + +Three rules: **never show a stack trace, a model ID, or a token count**; **always name the file that holds completed work**; **always give exactly one next action.** + +--- + +## 8. The Workbench + +Local web app. Observes and edits personas. Never launches work. + +### 8.1 Complexity + +Sizes relative: **S** ≈ a weekend, **M** ≈ a week, **L** ≈ several weeks, **XL** ≈ a project of its own. + +| Component | Size | Risk | Value | +|---|---|---|---| +| Event ingest via hooks | S | Low | High | +| **Token and cost ingest** | M | **High** | High | +| Store (SQLite) | S | Low | — | +| Static analytics report | S–M | Low | **High** | +| Server + live view | **L** | Med–High | **Low** | +| Persona editor | S–M | Low | High | +| Workflow editor | **XL** | **High** | Uncertain | +| Publish | S *or* L | Low *or* Med | Med | + +**Roughly 80% of the value is in four S/M components.** Two dominate the cost: + +**Live view duplicates `/workflows`**, which already shows phases, agent counts, token totals, elapsed time, and per-agent drill-down. There is no push API, so it means polling and byte-offset tailing plus a server and its lifecycle. P11 applies. + +**The workflow editor has a known trap.** A workflow is JavaScript. Editing it visually means either parsing and regenerating — brittle, hand edits silently lost — or owning a declarative format that compiles to JS, which never round-trips back. It also competes with `/workflow-authoring`, which already exists. + +### 8.2 Build order + +| Step | What | Gets you | +|---|---|---| +| **v0** | Hooks + store + `/katz:report` static HTML | All analytics. No server, no polling. The shape `/insights` already uses | +| **v1** | Minimal server + persona editor | Authoring — the "workbench" part | +| **v2** | Live view | Only if `/workflows` proves insufficient | +| **v3** | Workflow editor | Only if `/workflow-authoring` proves painful | + +### 8.3 Telemetry + +| Source | Official | Carries | Risk | +|---|---|---|---| +| **Hooks** | Yes | Our identifiers: workflow, stage, persona, artifact, verdict | Only what we instrument | +| **OpenTelemetry** | Yes | Tokens, cost, tool activity | Needs a collector | +| **Transcript JSONL** | No | Everything else | Undocumented; **deleted after 30 days** | + +**Hooks are the spine** — the only source that knows what a persona is, and a stable contract because we own both ends. OTel supplies the numbers. Transcripts enrich, fixture-fenced so drift breaks CI rather than the user. + +**Retention:** session data is cleaned up after `cleanupPeriodDays` (30 default), so the Workbench persists its own rollups. SQLite at `~/.code-katz/workbench.db`, append-only events plus derived daily rollups. + +**The riskiest dependency in the whole project is whether hooks plus OTel carry tokens and cost in a usable shape. Prove it in Phase 0.** + +--- + +## 9. Phasing + +| Phase | Content | Done when | +|---|---|---| +| **0** | Repo, plugin skeleton, marketplace install. **Three spikes: (a) can a workflow resume from a prior artifact; (b) can `PreModelSwitch` interrupt a workflow; (c) do hooks + OTel carry cost.** Persona scope split | `/katz:hello` runs from a fresh install on a second machine; all three spikes answered | +| **1** | `/katz:brief`, `/katz:prd`, `/katz:panel`, `/katz:next`. Contracts, validators, gate hooks. Core personas ported | **Will's wife produces a PRD in a new project without touching a file** | +| **2** | Workbench v0 — hooks, store, `/katz:report` | A week of real use is queryable | +| **3** | `/katz:opportunity`, `/katz:market-research`, `/katz:brand-guide`, `/katz:roadmap`, `/katz:gtm`, `/katz:bugfix` | A product goes zero-to-roadmap through the plugin | +| **4** | `/katz:plan-feature` + `/katz:feature` — slices, worktrees, cross-model gates | A roadmap feature ships through it | +| **5** | Workbench v1 — server + persona editor. **Retire claude-team-cli** | A persona is tuned without opening an editor | +| **Later** | Live view; workflow editor; Routines; launching from the Workbench | Only on evidence | + +`/katz:panel` is in Phase 1 deliberately — highest delight, lowest risk, and the fastest way to learn whether the premise holds. + +**claude-team-cli is archived at the end of Phase 5**, not before: it has a live user, and she moves over during Phase 1. + +--- + +## 10. Risks + +| Risk | Severity | Mitigation | +|---|---|---| +| Dynamic workflows are new; behavior may change | High | Own no orchestration. Pin a minimum version. Keep workflows small so a rewrite is cheap | +| Cost telemetry does not exist in usable form | **High** | Phase 0 spike. If it fails, the Workbench is report-only over hook events, with no dollar figures | +| Workflow granularity wrong | Med | Start coarse; split on felt pain. Splitting later is cheap | +| Arbitration cannot interrupt a workflow | Med | Phase 0 spike. Fallback is a pre-declared budget ceiling — weaker, but functional | +| Workbench becomes a second product | High | Read-only. No launching. Live view and workflow editor gated behind evidence | +| Non-code artifacts have no real oracle | Med | Structural validators plus Will's review. Size those stages accordingly | +| Fun gets optimized away | Med | G7 is a goal. Panels and persona voice are the fun; protect them in review | +| User 2 abandons it after one bad failure | **High** | §7.11 is a Phase 1 deliverable, not a polish item | + +--- + +## 11. Open questions + +1. **Design phase handoff** — does Kai hand `/katz:feature` a mockup file or a written spec? +2. **`/katz:bugfix` phases** — shares `/katz:feature`'s phases, or stays separate? +3. **Workbench v3 authoring format** — JS directly, or a declarative spec that compiles? Only if v3 happens. +4. **History retention** — how far back to keep rollups. Daily granularity is cheap; raw events are not. +5. **Publish scope** — "write the file and commit," or marketplace versioning with changelogs? +6. **Public or private marketplace** — this is a personal toolchain, but the research and the panel design may be worth publishing. diff --git a/plans/opus/2026-09-05-workbench-concepts.html b/plans/opus/2026-09-05-workbench-concepts.html new file mode 100644 index 0000000..6dbee4e --- /dev/null +++ b/plans/opus/2026-09-05-workbench-concepts.html @@ -0,0 +1,810 @@ + + + + + +Katz Workbench — 5 Concepts (rev 2) + + + + +
+
+

Katz Workbench

— five concepts · rev 2 +
+ mockup · not live data +
+
+ + + + + +
+
+ + +
+

What it is

A generated static HTML file. No server, no polling. Run /katz:report, a file opens. The shape /insights already uses.

+

When it wins

Answering "what happened last month" — spend, which personas earn their keep, gate pass rates.

+

Cost

S–M low risk. Recommended as v0.

+
+ +
+
+

Spend · 30d

$284.60
▲ 18% vs prior 30d
+

Workflow runs

63
across 3 projects
+

Gate pass rate

86%
▼ 9 reworks, all recovered
+

Personas used

9 / 22
13 idle 90d+
+
+ +
+
+

Spend by week

by model tier
+ + + $120$80$40$0 + + + + + + + + + Aug 11Aug 18Aug 25Sep 1 + +
+ Fable 5.1 Opus 5 Sonnet 5 +
+
+ +
+

Persona usage

runs, last 30 days
+ + + + + + + + +
River
18
Akira
14
Toni
11
Sasha
9
Kai
7
Robin
4
Iris
2
+
+ 13 personas idle 90+ days. Reiner, Cornelius, Ernie, Piper and Rez are a project cast — move them to that repo's .claude/agents/ rather than deleting. +
+
+
+ +
+

Recent runs

+ + + + + + + + + + + + + + + + +
WorkflowProjectPersonasModelsTokensCostOutcome
/katz:featureTrailheadAkira · Sasha · Robinopus·xhigh sonnet·high1.24M$18.40merged
/katz:panelTrailheadRiver · Toni · Kaifable·high opus·high186K$4.102 of 3 agreed
/katz:market-researchNightgridRiver · Tonifable·xhigh2.1M$31.80done
/katz:prdNightgridRiveropus·high340K$6.201 rework
+
+
+ + + + +
+
+
+
/katz:feature
Trailhead · offline sync
+
phase 3/6 · 3 agents · 6m 12s · $6.84
+
+
+
+
/katz:market-research
Nightgrid
+
phase 2/3 · 8 agents · 11m 40s · $19.20
+
+
+
+
/katz:panel
Trailhead · social sharing
+
phase 1/2 · 3 agents · 1m 04s · $0.90
+
+
+
+ +
+
+
+

Selected run

+
/katz:feature — offline sync
+
Trailhead · 3 slices, worktree-isolated · manifest: design ✓ content ✓
+
+
$6.84
+
est. $14 total
+
+ +
+
+
AGENT
+
+
1 Plan
+
2 Design
+
3 Build
+
4 Verify
+
5 Merge
+
6 Content
+
+
+ +
+
+ + +
+
A
+
Akira
slice 1 · sync engine
+
+
plan · max
+
writing resolver · xhigh
+
gate ← Robin
+
+
+ + +
+
K
+
Kai
design · sync UI
+
+
2 mockup states · high
+
+
+ + +
+
S
+
Sasha
slice 2 · status UI
+
+
SyncBadge.tsx · high
+
gate ← Akira
+
+
+ + +
+
R
+
Robin
slice 3 · migration tests
+
+
blocked on slice 1
+
queued
+
+
+ + +
+
T
+
Toni
content · release note
+
+
after merge · med
+
+
+
+
+ +
+ Block colour = model, shade = effort + low → max + dashed = verification gate + hatched = pending / blocked +
+
+ +
+

Event feed

selected run only
+
+
06:12Sasha edited SyncBadge.tsx
+
06:04Akira ran npm test -- sync · 14 passed, 2 failed
+
05:31⚑ Phase Design complete — brand/mock-sync.html
+
02:14✓ Interface contract frozen · 3 slices, scopes disjoint
+
00:41Plan approved · manifest: design ✓ content ✓
+
+
+
+ + + + +
+
+

/katz:feature — offline sync

Trailhead · 11 agents · 6 phases · $6.84
+ + + + offline syncjob · roadmap #12 + + + + + + + 1 · Plan✓ Akira · max + + 2 · Design✓ Kai · high + + 3 · Build● 3 slices + + 4 · Verifypending + + 5 · Merge → 6 · Content + + + + + A + Akiraopus · xhigh · worktree + + S + Sashasonnet · high · worktree + + R + Robinqueued · blocked on s1 + + + + gate · Robinsonnet · npm test + + gate · Akiraopus · npm test + + LEGEND + complete + running + pending + gate + + +
+ The structural rule made visible: every gate uses a different persona and tier than the slice it checks, and downstream work depends on the gate, not the writer. +
+
+
+ + + + +
+
+
+

Cost per tier

30 days · with gate pass rate alongside
+ + + + + + + + + + + + +
TierRunsTokensSpendGate pass
fable 5.165.9M$118.40100%
opus 5318.2M$104.9091%
sonnet 52414.1M$59.2074%
haiku 4.5881.2M$2.10n/a
+
+ Sonnet 5 gate pass rate fell to 74% from 88% last month. Aggregate spend looks fine; the tier is drifting. Raise effort to xhigh on affected stages before changing model. +
+
+ +
+

Where the money goes

by workflow · 30 days
+ + + /katz:market-research + $118 + /katz:feature + $79 + /katz:prd + $39 + /katz:panel + $29 + everything else + $19 + + +
+ One workflow is 41% of spend. Worth asking whether /katz:market-research needs Fable 5.1 by default, or only on escalation. +
+
+
+ +
+

Model resolution

declared vs resolved · why they differed
+ + + + + + + + + + + + + +
WhenStageDeclaredResolvedReasonΔ cost
Sep 3 14:22/katz:feature · verify s2opus·highopus·maxESCALATE_RETRY+$0.41
Sep 2 09:10/katz:market-researchfable·xhighopus·xhighFALLBACK_QUOTA−$14.20
Aug 28 11:03/katz:prd · requirementsopus·highopus·highSTAY_CONTINUITY
+
+ The FALLBACK_QUOTA row is the failure that started all of this — except now it fell back automatically and told you. +
+
+
+ + + + +
+
+ +
+
+ PersonasWorkflows +
+ +
+
plugin core · 9
+
+
A
Akira14
+
S
Sasha9
+
R
River18
+
T
Toni11
+
K
Kai7
+
R
Robin4
+
I
Iris2
+
Q
Quinn1
+
C
Casey1
+
+
+ project cast · 5 · Nightgrid
+
+ + +
+ + +
+
+
T
+
+
Toni
+
Product Marketing Manager · agents/toni.md
+
+ ● unsaved + +
+ +
+
+
HaikuSonnetOpus 5Fable
+
+
+
+ + +
+
+
+ +
+
+
+
+ +
+ + +
+ +
+ + +
+ ✓ frontmatter valid +
+
+ + + +
+ +
+

Colour system

hue = model · shade = effort · darker = more effort
+
+
Fable 5.1
+ + +
+
Opus 5
+ + +
+
Sonnet 5
+ + +
+
Haiku 4.5
+ + +
+
+
+
low · med · high · xhigh · max
low · med · high · xhigh · max
+
low · med · high · xhigh · max
low · med · high · xhigh · max
+
+
+ One glance answers both questions: what is this costing (hue) and how hard is it thinking (shade). A dark purple block is Fable at max — the most expensive thing that can appear on screen. +
+
+
+ + +
+
+ +

Toni · 30 days

+
+
11 runs
+
$21.40 · 890K tokens
+
+ + + + + +
Used by4 workflows
Gate pass91%
Avg cost/run$1.95
Escalations2
+
Appears in
+
+ /katz:gtm
/katz:panel
/katz:market-research
/katz:feature · content +
+
Effort actually used
+
+
low
+
med
+
high
+
xhi
+
max
+
+
+ Changing the model floor affects 4 workflows. The diff will list them. +
+
+ + + + From b663f86b40a227a04639481c5358d95e946c8527 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 8 Sep 2026 18:28:55 +0000 Subject: [PATCH 03/14] plans: correct the PRD intro to three scripts and three skills Section 0.2 still described the appendices as two workflow scripts and two skills; the revision carries three of each plus the brief-and-PRD contract. Found while building the review page. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014aqcjmXas9EFDx3pstfpyE --- plans/2026-09-05-ck-plugin-prd-phase-1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plans/2026-09-05-ck-plugin-prd-phase-1.md b/plans/2026-09-05-ck-plugin-prd-phase-1.md index bf15ed3..73d11c7 100644 --- a/plans/2026-09-05-ck-plugin-prd-phase-1.md +++ b/plans/2026-09-05-ck-plugin-prd-phase-1.md @@ -26,7 +26,7 @@ Every claim carries the proposal's grade, plus one more: ### 0.2 What this document is -The proposal is a research summary with a proposed shape. This is the specification for the first slice of that shape: what ships, what each piece must do, how it is tested, and what is deliberately left out. It contains acceptance criteria, schemas, and the full text of the two workflow scripts and two skills, as appendices. +The proposal is a research summary with a proposed shape. This is the specification for the first slice of that shape: what ships, what each piece must do, how it is tested, and what is deliberately left out. It contains acceptance criteria, schemas, and the full text of the three workflow scripts, three skills, and the brief-and-PRD contract, as appendices. ### 0.3 The three answers up front From 41e415a10f346f0c7d068cf042fd4826b9b690df Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 9 Sep 2026 00:10:36 +0000 Subject: [PATCH 04/14] plans: rewrite the ck PRD (revision 3) after Will's sixteen-comment review ck is independent of the old team tool: no coexistence, no vendored profiles; uninstall is a prerequisite. Clare is the primary user with two journeys. Every path is written against . Six judgment seats return to Fable 5.1. Phase one is the full product-definition pipeline (opportunity, market research, brief with a market pass, PRD, team, roadmap, architecture, brand guide, design) plus panel, next, and 21 switch commands, with ten document contracts and four complete workflow scripts. The Workbench is phase three. Reviews go through Claude's built-in comment system. PRD section 3.4 records each comment and the decision it drove. Panel memo gains section 8 for the superseded items. DEVLOG entry added. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_014aqcjmXas9EFDx3pstfpyE --- DEVLOG.md | 31 + plans/2026-09-05-ck-plugin-prd-phase-1.md | 1961 ++++++++++++++------- plans/2026-09-05-ck-prd-panel-memo.md | 19 +- 3 files changed, 1355 insertions(+), 656 deletions(-) diff --git a/DEVLOG.md b/DEVLOG.md index de4cb6f..aef9f1a 100644 --- a/DEVLOG.md +++ b/DEVLOG.md @@ -5,6 +5,37 @@ Auto-maintained via [claude-devlog-skill](https://github.com/code-katz/claude-de --- +## [2026-09-09] `ck` PRD revision 3 after Will's review: `ck` independent, the full definition pipeline in phase one, Fable tier restored, Workbench committed as phase three + +**Category:** `decision` +**Tags:** `ck`, `prd`, `review`, `clare`, `pipeline`, `model-tiers`, `workbench` +**Risk Level:** `medium` +**Breaking Change:** `no` + +### Summary +Will reviewed revision 2 of the `ck` phase-one PRD on its review page and left sixteen comments. Revision 3 is a rewrite, not a patch: the old team tool is out of the picture, Clare is the primary user with two named journeys, every path is written against ``, six judgment seats return to Fable 5.1, phase one grows from four commands to the whole product-definition pipeline plus a design step, the Workbench is committed as phase three, and every review goes through Claude's built-in comment system. Each comment and the decision it drove is recorded in PRD §3.4. + +### Detail + +- **`ck` is independent.** Every coexistence and retirement passage is gone. `ck` owns `profiles/` and `tiers.conf` after a one-time import; there is no vendored copy, lock, or sync script. Uninstalling the old tool is a prerequisite, with a `SessionStart` hook that warns in plain words while it remains. +- **Clare, not "Will's wife".** Proficient with the current tool, runs many sessions at once, and her learnings drive the rebuild. Her failure mode is inconsistency, not error text. J1 (idea to definition) and J2 (feature to design mockups, the same way every time) are the acceptance journeys; efficiency (fewer sessions and hand-offs) is a goal with a measure. +- **Phase one is the pipeline:** `/ck:opportunity`, `/ck:market-research`, `/ck:brief` (with a market pass), `/ck:prd`, `/ck:team` (roles and responsibilities), `/ck:roadmap`, `/ck:architecture`, `/ck:brand-guide` (proposals, finalists, guide; modelled on the NIGHTGRID process and the d20Mob guide), `/ck:design`, plus `/ck:panel`, `/ck:next`, and 21 persona switch commands. Ten document contracts. One drafting engine (`draft.js`) serves the PRD and the architecture document. Four scripts written in full; five to the stage level. +- **Models:** Fable 5.1 for River, Akira, Morgan, Sage, Jordan, Reiner; Opus 5 for the eleven craft seats; Sonnet 5 for the four execution seats; Haiku for validators. The panel default is River on Fable, Toni on Opus, Kai moved down to Sonnet; the one override moves a lens down, never up. +- **Reviews:** Claude's built-in review and comment system, in the desktop app or at claude.ai. Every review page carries the five how-to-comment steps in its banner, because the first one did not and could not be commented on. +- **Phase two:** `/ck:feature` (explained; open for Will to pull forward), `/ck:bugfix`, `/ck:gtm`, Routines, `/ck:map`, `/ck:report`. **Phase three:** the Workbench, a rewrite replacing the conductor dashboard, local, never a hosted store. + +### Decisions Made +- **Treat `ck` as a replacement, built independently; require the old tool's removal.** Will, 2026-09-08. +- **Fable where judgment matters, Sonnet where volume matters.** Three persona tiers; stage tiers for research, validation, and synthesis. +- **The document is the state, under `/docs/`.** The cache directory holds nothing a document depends on. +- **The Workbench will be built** as phase three, after phase one has run on a real product. + +### Related +- PRD revision 3: `plans/2026-09-05-ck-plugin-prd-phase-1.md` (§3.4 for the comment-by-comment record) +- Panel memo, §8 added for the superseded items: `plans/2026-09-05-ck-prd-panel-memo.md` + +--- + ## [2026-09-05] `ck` PRD revised after a cross-model panel: nine changes adopted, eleven rejected with reasons; review pages become the feedback channel **Category:** `decision` diff --git a/plans/2026-09-05-ck-plugin-prd-phase-1.md b/plans/2026-09-05-ck-plugin-prd-phase-1.md index 73d11c7..a5331c0 100644 --- a/plans/2026-09-05-ck-plugin-prd-phase-1.md +++ b/plans/2026-09-05-ck-plugin-prd-phase-1.md @@ -1,12 +1,11 @@ # `ck` Plugin, Phase One: Product Requirements Document -> **Status:** PRD, ready for build -> **Date:** 2026-09-05 +> **Status:** PRD, revision 3, ready for build +> **Date:** 2026-09-08 (first version 2026-09-05) > **Author:** Fable (with Will Curran) > **Derives from:** [`plans/2026-09-05-agent-workflows-research-and-proposal.md`](2026-09-05-agent-workflows-research-and-proposal.md) (the research proposal) -> **Supersedes:** the marketplace-retired decision in `claude-team-cli` (2026-07-31), for `ck` only; see §3.1 -> **Scope:** phase one only: plugin skeleton, `/ck:brief`, `/ck:prd`, `/ck:panel`, and `/ck:next` end to end, 21 personas as subagents on the §5.6 tiers. Everything else is in §10 -> **Revised:** 2026-09-05, after a cross-model panel against the Opus-written PRD; see [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md) +> **Scope:** phase one: the plugin skeleton, the full product-definition pipeline (`/ck:opportunity`, `/ck:market-research`, `/ck:brief`, `/ck:prd`, `/ck:team`, `/ck:roadmap`, `/ck:architecture`, `/ck:brand-guide`, `/ck:design`), `/ck:panel`, `/ck:next`, and 21 personas as subagents and switch commands on three model tiers. Phases two and three are in §10 +> **Revision history:** rev 2 (2026-09-05) after a cross-model panel against the Opus-written PRD, see [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md); rev 3 (2026-09-08) after Will's sixteen-comment review of rev 2, see §3.4 --- @@ -14,25 +13,34 @@ ### 0.1 Grading -Every claim carries the proposal's grade, plus one more: +Every claim carries the proposal's grade, plus two more: | Grade | Meaning | |---|---| -| **[D]** | Product documentation, verified against the primary source on 2026-09-05. The URL is in Appendix I | +| **[D]** | Product documentation, verified against the primary source on 2026-09-05. The URL is in Appendix J | | **[M]** | Measured, independent, method stated (carried over from the proposal) | | **[V]** | Vendor self-measured | | **[R]** | The family's own record: a devlog entry, roadmap revision, or test in a code-katz repo | +| **[W]** | Will's decision, recorded with its date. Not open to challenge in this document | | **[P]** | Practitioner assertion or judgment call. Open to challenge; the rationale is stated | ### 0.2 What this document is -The proposal is a research summary with a proposed shape. This is the specification for the first slice of that shape: what ships, what each piece must do, how it is tested, and what is deliberately left out. It contains acceptance criteria, schemas, and the full text of the three workflow scripts, three skills, and the brief-and-PRD contract, as appendices. +The proposal is a research summary with a proposed shape. This is the specification for the first release of that shape: what ships, what each command must do, what each document it produces must contain, how it is tested, and what is deliberately left for phases two and three. It contains acceptance criteria, schemas, four complete workflow scripts, two complete skills, and two complete document contracts, as appendices. The remaining workflows are specified to the stage level in §6; their scripts are build work that follows the four written here. -### 0.3 The three answers up front +### 0.3 Three words that mean one thing each -1. **It is a plugin.** Claude Code is the runtime for subagents, workflow scripts, and skills; nothing else can run them. No UI ships in phase one. The catalog view is a phase-two command that renders from files. A workbench is phase three, only if the files-as-workbench proves insufficient, and never a hosted app with its own store of definitions. See §4.7. -2. **The skill owns the gates; each span between gates is one workflow.** A sign-off point is not a workflow. It is a gate: a review page with comments, a file the author edits, or, for Will, an interview. Gates live in the main session, because a workflow cannot pause for input and subagents cannot ask. See §4.2 and §4.9. -3. **`ck` coexists with `claude-team-cli`.** Phase one is additive. The three handoff routes survive: switch this session (team-cli), delegate one task (`ck:`), open a separate session (team-cli). Retirement is revisited at 90 days with usage data. See §8.6. +| Word | Meaning in this document | +|---|---| +| `` | The git repository of the product being built: the folder where Claude Code was opened. Every document `ck` produces is written here and committed here. It is never the plugin's own directory and never the home directory. See §4.3 | +| Gate | A point where a person reviews and decides. Gates run in the main session, never inside a workflow, because a workflow cannot pause for input [D]. See §4.2 | +| Review page | Claude's built-in review and comment system: a private page in the Claude desktop app or at claude.ai, with comment mode. Every document or gallery that needs a decision is reviewed there. See §4.9 | + +### 0.4 The three answers up front + +1. **It is a plugin, and a Workbench follows it.** Claude Code is the runtime for subagents, workflow scripts, and skills; nothing else can run them. Phase one ships the plugin with no UI. Phase three rewrites the conductor dashboard as the `ck` Workbench: catalog, runs, cost, and persona and workflow editing against the plugin's source checkout, running locally. See §4.7 and §10.3. +2. **The skill owns the gates; each span between gates is one workflow.** A sign-off point is not a workflow. It is a gate: a review page with comments, or a file the author edits. See §4.2. +3. **`ck` is independent.** It replaces `claude-team-cli`, owns its persona definitions, and requires that `claude-team-cli` be uninstalled before use. Nothing in this document depends on, defers to, or coexists with it. [W, 2026-09-08] --- @@ -42,121 +50,155 @@ The proposal is a research summary with a proposed shape. This is the specificat | Component | Count | What it is | |---|---|---| -| Persona subagents | 21 | `agents/.md`, generated from `claude-team-cli` profiles, registered as `ck:`, model from the §5.6 tiers | -| Workflows | 3 | `/ck:brief` (River writes the brief from one sentence), `/ck:panel` (three lenses on different models and different evidence, one decision memo), and `/ck:prd-draft` (River drafts, a checker validates, the panel challenges, River rewrites) | -| Skills | 3 | `/ck:prd` (the entry point that owns the review before and after the draft), `/ck:next` (says what to run next in one sentence), and `prd-artifact` (the contract for the brief and the PRD: template, required fields, checklist) | -| Hooks | 1 | `SubagentStart` on `^ck:` appending one line per persona invocation to a usage log, so the 90-day prune has data | -| Tests | 1 suite | Manifest, drift against the pinned upstream, script lint, user-2 wording, Phase 0 answers, end-to-end drills | +| Persona subagents | 21 | `agents/.md`, generated from `ck/profiles/`, registered as `ck:`, on three model tiers: Fable 5.1 for judgment, Opus 5 for craft, Sonnet 5 for execution (§5.3) | +| Persona switch commands | 21 | `/ck:`, generated from the same profiles, for the session-switch route that `claude-team-cli` used to provide (§5.6) | +| Pipeline commands | 9 | `/ck:opportunity`, `/ck:market-research`, `/ck:brief`, `/ck:prd`, `/ck:team`, `/ck:roadmap`, `/ck:architecture`, `/ck:brand-guide`, `/ck:design`: the definition pipeline from an idea to a designed feature, each writing one committed document or gallery into `` (§6) | +| Decision and navigation commands | 2 | `/ck:panel` (three lenses on three models argue one question; a memo shows where they disagree) and `/ck:next` (says what to run next in one sentence) | +| Document contracts | 10 | One skill per document type: section order, required fields, checklist. Consistency comes from these, not from who writes (§7) | +| Workflow scripts | 9 | `panel`, `brief`, `draft` (serves the PRD and the architecture document), `team`, `opportunity`, `market-research`, `roadmap`, `brand`, `design` | +| Hooks | 2 | `SubagentStart` on `^ck:` appending one line per persona invocation to a usage log; `SessionStart` warning in plain words if `claude-team-cli` is still installed | +| Tests | 1 suite | Manifest, generation drift, script lint, contract-to-script consistency, plain-language checks, Phase 0 answers, end-to-end drills (§9) | -Revised on 2026-09-05 after a cross-model panel against the Opus-written PRD: nine changes adopted and eleven rejected, each with a reason, recorded in [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md). +What changed in revision 3, from Will's review (§3.4): `ck` no longer references `claude-team-cli` except to require its removal; Clare is named as the primary user and her two journeys drive the design; every path is written as `/...`; the Fable tier is restored for the six judgment seats; phase one grows from four commands to the full definition pipeline; the Workbench is committed as phase three; and every review happens in Claude's built-in comment system. -Everything in the proposal's §5.3 catalog beyond these commands, the hook-based gates, the model fallback chain, the Advisor tool, Routines, folding in the five artifact skills, persona switch skills, `/ck:map`, and any workbench are deferred with reasons in §10. +Phase two is `/ck:feature`, `/ck:bugfix`, `/ck:gtm`, Routines, `/ck:map`, and `/ck:report`. Phase three is the Workbench. Both are in §10 with the reason for each placement, and one question for Will: whether `/ck:feature` moves into phase one. --- -## 2. Problem, users, journey, goals +## 2. Problem, users, journeys, goals ### 2.1 Problem -The unit of Will's work is the workflow, not the roster (proposal §2.1). Today the personas exist only as session takeovers and delegation subagents. They own no artifacts, so their output varies run to run (proposal §3.4). Multi-lens input on a decision requires opening three sessions by hand, and the three lenses run on one model, which is one opinion in three costumes (proposal §3.4, [M] error correlation rises with capability). Nothing is repeatable across projects, and nothing is measured, so the persona question ("likely 15 more than are used", proposal §7) cannot be answered. +The unit of the work is the workflow, not the roster (proposal §2.1). Today the personas exist only as session takeovers and delegation subagents. They own no documents, so their output varies run to run (proposal §3.4). Multi-lens input on a decision means opening three sessions by hand, and the three lenses run on one model, which is one opinion in three costumes (proposal §3.4; [M] error correlation rises with capability). Nothing is repeatable across projects, and nothing is measured, so the persona question ("likely 15 more than are used", proposal §7) cannot be answered. -### 2.2 Users +The person who feels this most is not Will. It is Clare, who runs the current tool every day. -Adapted from the Opus PRD §3, which made the harder user the first-class one. Where the two conflict, she wins and Will gets an escape hatch. +### 2.2 Users -| | Will | Will's wife | +| | Clare | Will | |---|---|---| -| Technical? | Yes. Reads and writes code, comfortable in files and the terminal | No. Has shipped several iOS apps with Claude and claude-team-cli | -| Wants | Repeatability, adversarial input on decisions, visibility into cost and activity, a place to tune personas | To say what she wants in her own words and get a good document back | -| Tolerates | Several commands, flags, JavaScript, terminal output, cost decisions | One command at a time, plain language, no model names, no token counts | -| Fails when | The tool is slower than doing it himself | A command errors and she cannot tell what to do next | +| Technical? | No. She has shipped several iOS apps with Claude and `claude-team-cli`, and has become proficient with it: she knows which workflows, process, and documents a product needs | Yes. Reads and writes code; maintains the plugin | +| How she works | Runs many sessions at once, one persona per session, and hands work between them by hand | One session at a time, plus panels on decisions | +| Wants | The same, efficient, high-fidelity process every time: an idea to a definition, a feature to design mockups, without re-explaining the process to each persona | Repeatability, adversarial input on decisions, visibility into cost and activity, a place to tune personas | +| Tolerates | Plain language and one command at a time. Model names are fine when they explain a cost; she does not need to choose one | Flags, JavaScript, terminal output, cost decisions | +| Fails when | Workflows, personas, and documents are inconsistent: the same step produces a different shape, asks different questions, or needs a different number of sessions than last time | The tool is slower than doing it himself | + +The rebuild is based on Clare's learnings from running the current tool. Two things follow. First, she is the primary user, and a phase-one command is done when it works for her from the README alone. Second, she is not fragile: she does not need to be protected from the tool, she needs it to be consistent and to cost her fewer sessions. Her persona work should take fewer hand-offs than it does today. [W, 2026-09-08] -### 2.3 Journey J1: Will's wife starts a new product +### 2.3 Journeys -The primary journey. Phase one is done when this works without her opening a text editor or a hidden directory. +**J1. Clare takes a new product from an idea to a definition.** The primary journey. Phase one is done when it works end to end on a new project. -1. She has an idea. She creates a folder and opens Claude Code in it. -2. She types `/ck:` and sees the commands. She does not know where to start, so she runs `/ck:next`. It sees an empty project and says: "Start with `/ck:brief` and describe your idea in a sentence. It takes about a minute and writes `docs/brief.md`." -3. She runs `/ck:brief An app that reminds you to water each plant on its own schedule`. River writes the brief: the problem and the chain of whys behind it, the user, one success number, the scope with a smaller first version, and what it will not do. A checker confirms the shape. `docs/brief.md` appears with a short list of questions River could not answer for her. -4. She reads it. The user is not quite right. She either edits the file and saves, or, when the review page is available, opens the page and leaves a comment on the line. No approval screen, no command. -5. `/ck:next` now says: "Run `/ck:prd`. It turns the brief into full requirements and takes a few minutes." She runs it. It reads her edited brief. A draft is written and checked, three specialists argue about it on three different models, and River revises it. `docs/PRD.md` appears. -6. She gets a review page for `docs/PRD.md` with a short question at the top: "Imagine this shipped and did not move the number. What went wrong?" She comments where she disagrees, answers the question in a comment, and says "done". Claude works through every comment, changes the document, and marks each comment resolved with one line saying what changed. Without the review page she edits the file and runs `/ck:prd` again. -7. `/ck:next` suggests what comes next. +1. She has an idea. She creates a folder, opens Claude Code in it, and runs `/ck:next`. It sees an empty project and says: "Start with `/ck:opportunity` and describe your idea in a sentence. It writes `docs/opportunity.md`: what the product is, who it is for, what the market looks like, and whether it is worth doing." +2. She runs `/ck:opportunity `. River frames it, Toni writes the market context and positioning, Akira the technical shape, and the domain seat (a game designer, for a game) its own section. River assembles the analysis with stage gates, risks, and open questions. A review page opens. She comments where she disagrees and says "done". Claude applies every comment, republishes, and resolves each one with a line saying what changed. `docs/opportunity.md` is committed. +3. `/ck:next` says: "Run `/ck:market-research` to go deeper on the market, or `/ck:brief` if the opportunity is enough." She picks. Each writes its document into `docs/`. +4. `/ck:brief` writes the brief, with its own short market pass, and asks nothing. She reads it and edits or comments. +5. `/ck:team` writes `docs/TEAM.md`: which personas are on this product, who owns which document and stage, and which seat is missing. She adjusts by comment. +6. `/ck:prd` drafts the requirements, checks them, has three specialists argue about them on three different models, and rewrites. The review page carries one question at the top: "Imagine this shipped and did not move the number. What went wrong?" She answers in a comment. Claude finalizes `docs/PRD.md`. +7. `/ck:roadmap`, `/ck:architecture`, and `/ck:brand-guide` follow, each with the same shape: run, review by comment, done. The brand guide takes two review rounds, first on proposals, then on finalists, both as galleries she comments on. +8. At the end, `docs/` holds one document per step, every one committed, every one the same shape it was on her last product. -What she never does: choose a model, learn what a subagent is, sequence the stages herself, approve or reject anything in a form, or see a token count. +**J2. Clare takes one feature to design mockups, the same way every time.** The journey that fails most often today. + +1. In a project with a PRD and a brand guide, she runs `/ck:design `. +2. Kai reads the feature's requirements from `docs/PRD.md` and the brand guide, and produces a gallery: three labeled variants (A, B, C) of the feature's screens, each with its rationale and its trade-off. +3. The gallery opens as a review page. She comments on the variant she wants, and on what to change. +4. Claude applies the comments, produces the chosen variant at full fidelity with a written design spec, republishes, and resolves each comment. +5. `docs/design//` holds the gallery, the chosen variant, and the spec, committed. The next feature runs exactly the same way. + +**J3. Will runs a panel on a decision.** `/ck:panel ` with any context document. Three lenses on three models argue it; a memo shows where they disagree and leaves the decision to him. `docs/decisions/` holds the memo, committed. ### 2.4 Goals and measures | # | Goal | Measure | Source | |---|---|---|---| -| G1 | Consistency: the same stage produces the same document shape every time | Two PRDs from two projects have identical section structure; the validator passes on both | The contract checklist (§7.8) | -| G2 | Repeatability: the stages ship with every project | A fresh project has every phase-one command after one install | The install drill (§9) | +| G1 | Consistency: the same step produces the same document shape every time | Two documents of one type from two projects have identical section structure; the validator passes on both | The contracts (§7) | +| G2 | Repeatability: the pipeline ships with every project | A fresh project has every phase-one command after one install | The install drill (§9) | | G3 | Adversarial input: real disagreement on a judgment call | In more than half of panel runs, at least one lens recommends differently, or at least one kill condition is met | `panelFailedToDisagree` and `agreementRate` in each memo | -| G4 | The harder user succeeds | J1 completes on a new project without a text editor or a hidden directory | The user-2 drill (§9) | -| G5 | Retention (proposal §3.4: the real metric for a personal tool) | At 30 days after install, at least one `/ck:prd`, `/ck:brief`, or `/ck:panel` run per week of active building | `${CLAUDE_PLUGIN_DATA}/usage.jsonl` (§5.5) | -| G6 | Instrumented: the persona question can be answered at 90 days | Every persona invocation is logged with its type and session | The same log | +| G4 | Clare's journeys work | J1 and J2 complete on a new project from the README alone | The J1 and J2 drills (§9) | +| G5 | Efficiency for Clare | J2 takes one command and one review, where today it takes several sessions and hand-offs by hand | The J2 drill, session count | +| G6 | Retention (proposal §3.4: the real metric for a personal tool) | At 30 days after install, at least one pipeline or panel run per week of active building | `${CLAUDE_PLUGIN_DATA}/usage.jsonl` (§5.5) | +| G7 | Instrumented: the persona question can be answered at 90 days | Every persona invocation is logged with its type and session | The same log | -Leading indicator: usage log entries in the first week. A panel that always agrees is a failed panel (proposal §5.5); if G3 is missed, the lenses or the question template are wrong, not the users. +Leading indicator: usage-log entries in the first week. A panel that always agrees is a failed panel (proposal §5.5); if G3 is missed, the lenses or the question template are wrong, not the users. ### 2.5 Non-goals for phase one -- No workflow other than `brief`, `panel`, and `prd-draft`. The rest of the catalog in proposal §5.3 is phase two. -- No UI, dashboard, map, or workbench. `/workflows` is the run view (proposal §9, [D]). -- No retirement of `claude-team-cli`, no persona switch skills (`/ck:river`), no CLI in `bin/`. -- No hook-enforced artifact gates, no model fallback chain, no Advisor tool, no Routines, no mid-run arbitration (workflows cannot pause; §4.2). -- No persona pruning. All 21 port; the instrument ships; the cut list follows the data. -- No changes to the persona text. Profiles stay upstream; `ck` transforms them mechanically. +- No `/ck:feature`, `/ck:bugfix`, or `/ck:gtm`. They need the definition pipeline's documents as inputs and are phase two (§10.2), with `/ck:feature` open for Will to pull forward. +- No UI. `/workflows` is the run view in phase one [D]. The Workbench is phase three (§10.3). +- No hook-enforced document gates, no model fallback chain, no Advisor tool, no Routines, no mid-run arbitration (workflows cannot pause; §4.2). +- No persona pruning. All 21 ship; the instrument ships; the cut list follows the data. +- No compatibility with, migration from, or reference to `claude-team-cli` beyond the one-time import of its profiles (§5.1) and the uninstall prerequisite (§8.4). --- ## 3. Decisions -### 3.1 Decisions on record that this PRD supersedes or honors +### 3.1 Decisions on record that this PRD honors or supersedes | Date | Decision and where it is recorded | What `ck` does | Grade | |---|---|---|---| -| 2026-07-29 | No second source of persona truth. Local overrides and team-scoped profiles retired (team-cli `ROADMAP.md` revision history, `CONTRIBUTING.md`) | Honored. `ck/agents/` is generated from a byte-for-byte vendored copy of team-cli `profiles/` at a pinned commit, committed, and drift-tested. Editing a persona still means a PR or a fork upstream | [R] | -| 2026-07-31 | Marketplace publishing retired for team-cli, not deferred: `/akira` would become `/claude-team:akira`, and a plugin cannot put `claude-team` in the user's shell, so `launch` and `session` could not ship (team-cli `ROADMAP.md`, `DEVLOG.md`) | **Superseded for `ck` only.** `ck` accepts namespacing because the prefix is two characters, because workflows and subagents need no shell CLI, and because the things the 07-31 decision protected (`/akira`, `launch`, `session`, the coordinator) stay exactly where they are. team-cli's own decision stands | [R], [P] | -| 2026-07-04 | Conductor: keep and harden the local Node dashboard; JSONL parsing fenced with fixtures; plugin packaging (conductor `DEVLOG.md`) | Honored as precedent for any future viewer: local server plus browser, reading files on disk | [R] | -| 2026-07-25 | Conductor research branch: "drop Tauri, target local server + browser" | Honored. A desktop app is not on the table | [R] | -| proposal §9 | "Use `/workflows` and do not build a UI until it proves insufficient" | Honored in phase one. §4.7 says what would count as insufficient | [P] | +| 2026-07-29 | No second source of persona truth (team-cli `ROADMAP.md` revision history, `CONTRIBUTING.md`) | Honored by moving the source, not forking it. `ck/profiles/` is the only place persona text is edited; `agents/` and the switch skills are generated from it and drift-tested. The import from the old tool happens once (§5.1) | [R] | +| 2026-07-04 | Conductor: keep and harden the local Node dashboard; JSONL parsing fenced with fixtures (conductor `DEVLOG.md`) | Superseded in part. The dashboard is rewritten as the `ck` Workbench after phase one (§10.3). The fixture-fenced JSONL cost parser and `pricing.json` are reused | [W, 2026-09-08] | +| 2026-07-25 | Conductor research branch: "drop Tauri, target local server + browser" | Honored. The Workbench is a local server and a browser | [R] | +| proposal §9 | "Use `/workflows` and do not build a UI until it proves insufficient" | Honored in phase one, superseded for phase three: the Workbench will be built | [W, 2026-09-08] | -### 3.2 Decisions made in this PRD (the proposal's §8, resolved) +### 3.2 The proposal's §8, resolved | # | Question (proposal §8) | Decision | Grade | |---|---|---|---| -| 1 | Retire or coexist? | **Coexist.** `ck` is additive. team-cli keeps switch commands, coordinator, `launch`, `session`, `install.sh`. The three routes survive (§8.6). Revisit at 90 days with `usage.jsonl` | [P] | -| 2 | Workflow granularity vs sign-off | **The skill owns the gates; each span between gates that needs fan-out or verification is one workflow; a single-agent span runs inline via the Agent tool.** `/ck:prd` is a skill: the brief (from `/ck:brief`, or an optional interview) → `prd-draft` workflow → review (a page with comments, or a file edit) → inline finalize. `/ck:panel` and `/ck:brief` are pure workflows: inputs are args, output is a document, no gate. Full rule and the failure modes it must survive: §4.2, §4.3 | [D]-backed | -| 3 | Where artifacts live | **The artifact is the state** (adopted from the Opus PRD §7.9). Deliverables live at fixed, conventional, committed paths: `docs/brief.md`, `docs/PRD.md`, `docs/decisions/-.md`, overridable by argument. `.ck/runs//` is a cache (per-lens JSON, the harness run id), locally excluded via `.git/info/exclude`; nothing depends on it. Resume works from which documents exist plus a start-at stage (§4.3). The plugin never edits the user's `.gitignore` | [P] | -| 4 | Which personas survive? | **All 21 port now; prune at 90 days on evidence.** The port is generated, so carrying 21 costs nothing. No usage data exists, so a cut list today is a guess. The instrument ships in phase one (§5.5). This contradicts proposal §8.4 and agrees with proposal §7 | [P] | -| 5 | Panel model assignment | **River on Opus 5, Toni on Fable 5.1, Kai on Sonnet 5 by default,** overridable per run. `panel.js` is the one script allowed to set `model` on a persona agent, because per-invocation model beats frontmatter [D] and decorrelation is the point. The memo header states the limitation: one training pipeline, partial decorrelation. A lens that dies on an API error returns `null`; the memo runs on the survivors and says so | [P] | -| 6 | `/ck:feature` scope | **Deferred to phase two.** Both options recorded in §10.2 | deferred | -| 7 | Routines | **Deferred.** One constraint carried into phase one: `panel` must be runnable headless (no gate inside it), which it is. `prd` cannot be, by construction | deferred | -| 8 | Oracle for non-code artifacts | **A structural validator plus the human gate.** `skills/prd-artifact/SKILL.md` carries the checklist; a neutral Haiku agent checks the draft against it inside the workflow, with at most two revise loops; Gate 1 is the human oracle. Hook-based gates are a phase-two spike (§3.3 item 7) | [P] | +| 1 | Retire or coexist with the old tool? | **Neither is a consideration.** `ck` is a replacement, built independently. The old tool must be uninstalled before `ck` is used (§8.4). What it did that must not be lost (persona switch, "who should be on this", parallel work) is carried by `ck` itself (§5.6, §6.5, §10.2) | [W, 2026-09-08] | +| 2 | Workflow granularity vs sign-off | **The skill owns the gates; each span between gates that needs fan-out or verification is one workflow; a single-agent span runs inline via the Agent tool.** Full rule: §4.2 | [D]-backed | +| 3 | Where documents live | **The document is the state.** Every deliverable lives at a fixed, conventional, committed path under `` (§4.3). `.ck/runs//` is a cache; nothing depends on it | [W, 2026-09-08], [P] | +| 4 | Which personas survive? | **All 21 ship; prune at 90 days on evidence.** Generation makes carrying 21 free. No usage data exists, so a cut list today is a guess. The instrument ships in phase one (§5.5). Agrees with proposal §7, contradicts §8.4 | [P] | +| 5 | Panel model assignment | **River on Fable 5.1, Toni on Opus 5, Kai on Sonnet 5 by default.** River and Toni run on their own tiers; only Kai is moved, downward, so that three lenses are three models. Overridable per run. The memo header states the limitation: one training pipeline, partial decorrelation | [W, 2026-09-08] for the tiers; [P] for the assignment | +| 6 | `/ck:feature` scope | **Phase two, with the question open for Will** (§10.2, §10.4). Both scope options recorded | open | +| 7 | Routines | **Phase two.** One constraint carried into phase one: every pure workflow (`panel`, `market-research`, `brief`, `team`, `roadmap`) is runnable headless. `market-research` is the first candidate for a schedule | deferred | +| 8 | Oracle for non-code documents | **A structural validator plus the human gate.** Each contract skill carries a checklist; a neutral Haiku agent checks the draft against it inside the workflow, with at most two revise loops; the review page is the human oracle. Hook-based gates are a phase-two spike (§3.3 item 6) | [P] | ### 3.3 Corrections to the proposal Each item names the proposal section, what is wrong, and what this PRD does instead. 1. **§5.1, plugin name.** The tree is rooted at `code-katz/` and every command is `/ck:...`. The command prefix is the plugin's `name` and cannot be opted out of [D]. The plugin is named `ck`. The repo is `code-katz/ck`. -2. **§5.1 vs §8.1, retire or coexist.** §5.1 says "retire the bash CLI"; §8.1 asks whether to. Resolved: coexist (§3.2 item 1). A plugin `bin/` directory is on the Bash tool's PATH [D], so a `ck` CLI for Claude's use is possible later; it still cannot reach the user's shell, which is what `launch` needs. -3. **§3.2, §5.1, §5.6, §7, roster count.** The proposal says 22. `profiles/` holds 21 personas and the 2026-09-04 devlog says twenty-one [R]. -4. **§5.6, unassigned personas.** The tier table assigns 14 of 21. Reiner, Cornelius, Ernie, Rez, Tracy, Travolta, and Noon are unassigned. All seven are judgment or craft seats, so they go to Judgment (Opus 5); Reiner moves from Fable, the other six from Opus 4.8. Piper is Execution as listed. Result: 17 on Opus 5, 4 on Sonnet 5, none on Fable. Fable 5.1 and Haiku 4.5 are workflow-stage tiers, not persona tiers. §5.3 has the table. -5. **§5.5 vs §5.6, the panel contradiction.** "Each lens runs on a different model. Not negotiable" and "River, Toni, Kai: Opus 5" cannot both hold through frontmatter alone. Resolved by a per-invocation override in `panel.js` only (§3.2 item 5). Consequence for the PRD: tiers are defaults; the document says which script may override them (one) and which may not (every other). -6. **§5.6, where the tier re-base happens.** `tiers.conf` in team-cli names itself the single source of truth [R]. The re-base is a prerequisite PR to team-cli; `ck`'s generator copies the value verbatim. Recommendation for that PR: aliases (`opus`, `sonnet`) rather than full IDs, so a tier tracks the current generation and the resolved model is recorded per run by `/workflows` [D]. [P] -7. **§5.2 and §5.7, the gate mechanism.** "`TaskCompleted` or `Stop`, exit code 2, rejects malformed output." `Stop` is the main conversation's event; the subagent event is `SubagentStop`, whose exit-2 feedback path to the agent is not documented [D as read]; plugin agents ignore per-agent `hooks:` frontmatter [D]. Phase one validates inside the workflow: schema-forced output, which the harness retries on mismatch [D], plus a validator agent against the artifact checklist. Hook gates are a phase-two spike with a stated test. -8. **§5.6, fallback chain via `PreModelSwitch`.** The hook fires "before Claude Code applies a model switch that you or a client requested" [D]. Nothing says it covers subagent model selection or an API quota error. Phase-one resilience is null-tolerant scripts: a lens or stage that fails returns `null`, and the script continues and logs it. A real fallback is a phase-two spike. -9. **§8.4 vs §7.** "A cut list should precede the port" against "instrument and prune after 90 days." No data exists. Port everything and instrument (§3.2 item 4). -10. **§6, "no state file".** Script variables die with the run. A gate between two workflows requires the artifact on disk. `.ck/runs/` is the artifact directory, not a coordination state file in the conductor sense; the proposal's argument against a custom task graph and lock protocol still holds. -11. **§4.1 vs §3.4, what buys consistency.** §4.1 says repeatability "is the whole answer to goal 3"; §3.4 says consistency comes from the artifact contract. §3.4 is right. Workflows give the same process; artifact skills give the same shape. Phase one's most important file is `skills/prd-artifact/SKILL.md`, not `prd-draft.js`. -12. **§4.2, `maxBudgetUsd`.** Not in the subagent frontmatter table read today [D]. Not relied on. -13. **§9, the superseded plan.** `claude-conductor/plans/2026-09-04-agent-coordination-engine.md` is on no branch of that repo. Commit it, so the supersession is traceable. -14. **§5.2, the persona layer.** "Voice, domain constraints, model tier" omits that a subagent has no user to ask. Every persona's `## Required Interactive Behaviors` is written as questions to the user; unrewritten, it is dead text or a stall. §5.4 has the transform. -15. **§4.1, fan-out cache economics.** The prompt-cache sharing described there applies to agents matching on model, effort, agent type, tools, schema, and cwd [D]. A persona panel is three agent types on three models and shares nothing. The cost model in Appendix H assumes no sharing. - -What the proposal gets right and this PRD keeps unchanged: §3 (topology, not persona strings, is the lever; buy quality with a different model and a real oracle), §4.3 (Agent Teams is not the executor), §5.2 (the four layers), §5.5 (forced self-disagreement; three approvals is a failed panel), §6 (the not-building list), §7 (the honest assessment), §9 (the UI stance). - -A second review, against the PRD Opus wrote from the same proposal, produced nine changes adopted into this document and eleven rejections. The Opus PRD's own errors, verified against the docs, and the reason for each rejection are in [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md). The largest change: this document had named Will's wife as customer zero and then designed for Will. §2.2, §2.3, §4.8, and the file-edit path in §7.6 exist because the Opus PRD made her the harder constraint. +2. **§3.2, §5.1, §5.6, §7, roster count.** The proposal says 22. `profiles/` holds 21 personas [R]. +3. **§5.6, collapsing Fable into Opus.** The proposal re-bases the six Fable seats onto Opus 5 on price. Rejected: Will wants Fable where judgment matters and Sonnet where volume matters [W, 2026-09-08]. The six judgment seats stay on Fable, moving from Fable 5 to Fable 5.1 (same price [D]); the eleven craft seats move from Opus 4.8 to Opus 5; the four execution seats stay on Sonnet 5. The seven personas the proposal left unassigned (Reiner, Cornelius, Ernie, Rez, Tracy, Travolta, Noon) are placed in §5.3. Haiku 4.5 is a workflow-stage tier for validators, never a persona tier. +4. **§5.5 vs §5.6, the panel contradiction.** "Each lens runs on a different model. Not negotiable" and a tier table that puts River and Toni on one model cannot both hold through frontmatter alone. With the tiers in item 3, River (Fable 5.1) and Toni (Opus 5) already differ; Kai is moved from Opus 5 to Sonnet 5 by a per-invocation override in `panel.js`. Tiers are defaults; `panel.js` is the one script that may override them (§4.5). +5. **§5.2 and §5.7, the gate mechanism.** "`TaskCompleted` or `Stop`, exit code 2, rejects malformed output." `Stop` is the main conversation's event; the subagent event is `SubagentStop`, whose exit-2 feedback path to the agent is not documented [D as read]; plugin agents ignore per-agent `hooks:` frontmatter [D]. Phase one validates inside the workflow: schema-forced output, which the harness retries on mismatch [D], plus a validator agent against the contract checklist. +6. **§5.6, fallback chain via `PreModelSwitch`.** The hook fires "before Claude Code applies a model switch that you or a client requested" [D]. Nothing says it covers subagent model selection or an API quota error. Phase-one resilience is null-tolerant scripts: a lens or stage that fails returns `null`, and the script continues and logs it. +7. **§8.4 vs §7.** "A cut list should precede the port" against "instrument and prune after 90 days." No data exists. Ship everything and instrument (§3.2 item 4). +8. **§6, "no state file".** Script variables die with the run. A gate between two workflows requires the document on disk. The documents in `/docs/` are that state; `.ck/runs/` is a cache. The proposal's argument against a custom task graph and lock protocol still holds. +9. **§4.1 vs §3.4, what buys consistency.** §4.1 says repeatability "is the whole answer to goal 3"; §3.4 says consistency comes from the document contract. §3.4 is right, and Clare's failure mode (§2.2) is exactly the one contracts fix. Workflows give the same process; contracts give the same shape. Phase one's most important files are the ten contracts in §7. +10. **§4.2, `maxBudgetUsd`.** Not in the subagent frontmatter table read today [D]. Not relied on. +11. **§9, the superseded plan.** `claude-conductor/plans/2026-09-04-agent-coordination-engine.md` is on no branch of that repo. Commit it, so the supersession is traceable. +12. **§5.2, the persona layer.** "Voice, domain constraints, model tier" omits that a subagent has no user to ask. Every persona's `## Required Interactive Behaviors` is written as questions to the user; unrewritten, it is dead text or a stall. §5.4 has the transform. +13. **§4.1, fan-out cache economics.** The prompt-cache sharing described there applies to agents matching on model, effort, agent type, tools, schema, and cwd [D]. A persona panel is three agent types on three models and shares nothing. The cost model in Appendix I assumes no sharing. +14. **§5.3, the catalog's phasing.** The proposal's phase one was `/ck:prd` and `/ck:panel`. To test the shape on a real product the whole definition pipeline is needed, and Clare's design step with it [W, 2026-09-08]. §6 is that pipeline. + +What the proposal gets right and this PRD keeps unchanged: §3 (topology, not persona strings, is the lever; buy quality with a different model and a real oracle), §4.3 (Agent Teams is not the executor), §5.2 (the four layers), §5.5 (forced self-disagreement; three approvals is a failed panel), §6 (the not-building list), §7 (the honest assessment). + +### 3.4 Will's review of revision 2 (sixteen comments, 2026-09-08) + +Revision 2 was published as a review page; Will left sixteen comments. Each is recorded here with the decision it drove, so the thread on the page can be resolved against a line in the document. + +| # | Comment (abridged) | Decision | Where | +|---|---|---|---| +| 1 | "Why is this PRD so focused on retiring team-cli? Treat ck as independent." (four comments) | Every coexistence and retirement passage removed; `ck` owns its profiles; uninstall required | §0.4, §3.2 item 1, §5.1, §8.4 | +| 2 | "Clare is not technical, but has become very proficient. She runs many multiple sessions. I want her persona work to be more efficient." | Clare named as primary user; her learnings drive the design; efficiency is a goal | §2.2, §2.4 G5 | +| 3 | "Workflows, personas and artifacts are not consistent. She wants the same, efficient, high-fidelity process for moving features into design mockups." | J2 and `/ck:design` added; contracts made the consistency mechanism | §2.3 J2, §6.9, §7 | +| 4 | "I would prefer a rewrite of the UI / dashboard after we complete ck." | Conductor's dashboard is rewritten as the Workbench, phase three | §3.1, §10.3 | +| 5 | "Be precise on these paths. Use `/docs/brief.md`." (two comments) | `` defined once; every path written against it | §0.3, §4.3 | +| 6 | "`/ck:feature`: what is this? Why is it out of scope?" | Explained in one paragraph; phase two with the question open | §10.2, §10.4 | +| 7 | "It will be built." (the Workbench) | "If ever" removed; phase three committed | §4.7, §10.3 | +| 8 | "Use Claude's review/comment system in the Claude desktop UI." | §4.9 rewritten around it; `ck` builds nothing of its own for reviews | §4.9 | +| 9 | "Why are there no Fable models? Use Fable where it matters, Sonnet where it matters." | Fable tier restored for six judgment seats; Sonnet for four execution seats; panel default follows | §3.3 item 3, §5.3, §6.10 | +| 10 | "The brief must do some basic market research." | Toni's market pass added to `/ck:brief` and to the brief contract | §6.3, §7.3 | +| 11 | "I also want a branding / style guide. See d20mob and nightgrid." | `/ck:brand-guide` modelled on the NIGHTGRID process and the d20Mob guide | §6.8, §7.8 | +| 12 | "I also want team selection. This step basically outlines R&R." | `/ck:team` writes `docs/TEAM.md` | §6.5, §7.5 | +| 13 | "I also want an architecture workflow. PRD and roadmap in, architecture out." | `/ck:architecture` | §6.7, §7.7 | +| 14 | "To truly test this I need opportunity, market-research, branding." | Phase one is the full definition pipeline | §6 | + +The earlier cross-model review (2026-09-05, against the PRD Opus wrote from the same proposal) still stands where Will's review did not touch it: the users table, the goals table, the document-is-the-state rule, per-lens evidence, the effort axis, Phase 0 spikes, `/ck:next`, and persona scopes for the 90-day prune came from that review. Its record, including eleven rejected items with reasons, is [`plans/2026-09-05-ck-prd-panel-memo.md`](2026-09-05-ck-prd-panel-memo.md). One of its rejections (coexistence with the old tool) is now moot: Will's decision replaced both positions. --- @@ -166,12 +208,14 @@ A second review, against the PRD Opus wrote from the same proposal, produced nin | Layer | Primitive | Owns | Phase-one instance | |---|---|---|---| -| Workflow | `workflows/*.js` | The order of stages, outside the conversation | `panel.js`, `prd-draft.js` | +| Workflow | `workflows/*.js` | The order of stages, outside the conversation | `panel`, `brief`, `draft`, `team`, `opportunity`, `market-research`, `roadmap`, `brand`, `design` | | Persona | `agents/*.md` | Voice, domain constraints, default model tier | 21 generated files, `ck:` | -| Artifact | `skills/*/SKILL.md` | Output template, required fields, checklist | `prd-artifact` | -| Gate | The skill in the main session | Sign-off: a review page with comments, a file edit, or the optional interview; plus schema-forced output and a validator agent inside the workflow | `prd` (the brief check and the review); the validators in `brief.js` and `prd-draft.js` | +| Contract | `skills/-artifact/SKILL.md` | Section order, required fields, checklist for one document type | 10 contracts (§7) | +| Gate | The skill in the main session | Sign-off: a review page with comments, or a file edit; plus schema-forced output and a validator agent inside the workflow | `opportunity`, `prd`, `architecture`, `brand-guide`, `design` skills; the validators in every workflow | -The proposal put the gate layer in `hooks/hooks.json`. Phase one puts human gates in the skill and machine gates in the scripts (§3.3 item 7). The hook that does ship is instrumentation, not enforcement. +The proposal put the gate layer in `hooks/hooks.json`. Phase one puts human gates in the skill and machine gates in the scripts (§3.3 item 5). The hooks that ship are instrumentation and a prerequisite check, not enforcement. + +**One drafting engine.** `/ck:prd` and `/ck:architecture` have the same shape: one author drafts to a contract, a checker validates, a three-lens panel challenges, the author rewrites with a challenged-claims appendix and a premortem. One script, `workflows/draft.js`, serves both; the skill passes which contract, which author, and which lenses. A third document with that shape costs a skill and a contract, not a script. [P] ### 4.2 The gate rule @@ -179,7 +223,7 @@ The docs: "No mid-run user input. Only agent permission prompts can pause a run. Therefore: -1. A sign-off is a **gate**. A gate runs in the main session, inside a skill: a review page with comments (§4.9), a file the author edits and re-runs, or, optionally, an interview with `AskUserQuestion`. +1. A sign-off is a **gate**. A gate runs in the main session, inside a skill: a review page with comments (§4.9), or a file the author edits and re-runs. 2. The span between two gates is a **workflow** when it needs fan-out, structured output, or resume. A span that is one agent runs inline through the Agent tool; a workflow for one agent buys nothing. 3. A workflow never contains a decision point. A skill never fans out by hand. 4. A skill or slash command whose instructions say to call Workflow is explicit opt-in [D]; no `ultracode` keyword, no "use a workflow" phrase is needed. @@ -188,26 +232,45 @@ Rejected alternatives: one workflow per persona action (the skill would orchestr What would make the rule wrong: subagents regaining `AskUserQuestion`, or workflows gaining a pause primitive. Neither is on the record. -### 4.3 Artifacts are the state; the run directory is a cache +Applied to the catalog: -Adopted from the Opus PRD §7.9. The deliverables outlive the tool, so they live at plain, committed paths, and the plugin keeps no private state that anything depends on. +| Command | Shape | Gates | +|---|---|---| +| `/ck:panel`, `/ck:market-research`, `/ck:brief`, `/ck:team`, `/ck:roadmap` | A pure workflow: inputs are arguments, output is a document, no gate. The document is reviewed afterwards by comment or by edit whenever the author wants | None inside | +| `/ck:opportunity`, `/ck:prd`, `/ck:architecture` | Skill: workflow, then one review gate, then an inline finalize | One | +| `/ck:brand-guide` | Skill: three workflow stages with a gallery gate between each | Two | +| `/ck:design` | Skill: one workflow stage, a gallery gate, one more stage | One | +| `/ck:next`, `/ck:` | Skill only, no agents | None | -| Artifact | Path | Written by | Committed | -|---|---|---|---| -| Brief | `docs/brief.md` | `/ck:brief`, or the optional interview in `/ck:prd` | Yes | -| PRD | `docs/PRD.md` | `/ck:prd` (written progressively by the `prd-draft` stages, then finalized) | Yes | -| Decision memo | `docs/decisions/-.md` | `/ck:panel`, and the nested panel inside `prd-draft` | Yes | +### 4.3 ``: the document is the state -Paths are overridable by argument. `docs/` is the Opus convention; the family's root-level files (`ROADMAP.md`, `DEVLOG.md`) are unchanged. +`` is the git repository of the product being built: the folder in which Claude Code was opened. It is not the `ck` plugin's install directory (a copy under `~/.claude/plugins/`), not the `ck` source checkout, and not `~/.claude`. Every document `ck` writes goes into `` at a fixed, conventional path, and is committed with the product. [W, 2026-09-08] -The run directory is a cache. It holds what a fresh session might want but nothing the deliverable depends on: +| Document | Path in `` | Written by | +|---|---|---| +| Opportunity analysis | `docs/opportunity.md` | `/ck:opportunity` | +| Market research | `docs/market-research.md` | `/ck:market-research` | +| Brief | `docs/brief.md` | `/ck:brief` | +| PRD | `docs/PRD.md` | `/ck:prd` | +| Team, roles and responsibilities | `docs/TEAM.md` | `/ck:team` | +| Roadmap | `ROADMAP.md` (the family's root-level convention [R]) | `/ck:roadmap` | +| Architecture | `docs/ARCHITECTURE.md` | `/ck:architecture` | +| Brand direction record | `docs/decisions/-brand-direction.md` | `/ck:brand-guide` | +| Brand guide | `docs/brand-guide.md` | `/ck:brand-guide` | +| Brand galleries and assets | `brand/proposals/`, `brand/finalists/`, `brand/final/` | `/ck:brand-guide` | +| Design gallery, chosen variant, spec | `docs/design//gallery.html`, `chosen.html`, `spec.md` | `/ck:design` | +| Decision memo | `docs/decisions/-.md` | `/ck:panel`, and the panel inside `draft` | + +Paths are overridable by argument. The plugin never edits `.gitignore`; nothing it writes needs excluding except the cache below. + +The cache lives at `/.ck/runs//` and holds what a fresh session might want but nothing a document depends on: ``` .ck/runs// -├── run.json { runId, createdAt, status, stage, outputPath, lenses, harnessRunId, scriptPath } -├── interview.md the optional interview's answers, appended one at a time +├── run.json { runId, command, createdAt, status, stage, outputPath, lenses, harnessRunId, scriptPath } ├── panel/.json one file per lens -└── gate-1.md review-page comments or file edits, as applied +├── sections/.md one file per contributor, for the assembled documents +└── review.md the comments and how each was applied ``` Rules, each of which closes a failure mode found in review: @@ -215,60 +278,69 @@ Rules, each of which closes a failure mode found in review: | Rule | Failure it closes | |---|---| | `run-id` is `-`, minted by the skill with `date -u`; workflows receive `timestamp` in `args` because `Date.now()` throws in scripts [D] | Non-deterministic scripts break resume | -| `runDir` is passed **absolute** in `args` | Subagents inherit the session cwd; a user in a subdirectory would get `.ck/` in the wrong place | -| Every workflow accepts `args.startAt` and skips completed stages; the skill decides `startAt` by which artifacts exist | A fresh session cannot replay the harness cache [D]; the file on disk is what survives | -| The optional interview appends each answer to `interview.md` as it is given, and the skill offers to resume an interview that has answers but no brief | Compaction in the middle of the interview loses the answers | +| `projectRoot` and `runDir` are passed **absolute** in `args` | Subagents inherit the session cwd; a user in a subdirectory would write `docs/` in the wrong place | +| Every workflow accepts `args.startAt` and skips completed stages; the skill decides `startAt` by which documents exist | A fresh session cannot replay the harness cache [D]; the file on disk is what survives | | The skill writes the Workflow tool's own run id into `run.json` as `harnessRunId` before it waits | Within a session, `resumeFromRunId` replays completed agents at no cost [D] | -| The skill adds `.ck/` to `.git/info/exclude` on first use, never to `.gitignore` | team-cli's `session done` refuses untracked files [R]; the cache must not block closing a worktree | +| The skill adds `.ck/` to `/.git/info/exclude` on first use, never to `.gitignore` | The cache must not appear in the product's history, and the plugin must not edit a tracked file the author did not ask it to | | Every agent that writes returns the path it wrote, in its schema | The script cannot check the filesystem; the next stage needs the path | ### 4.4 Naming - Plugin `name`: `ck`. Everything is `/ck:` or `ck:` [D]. -- Skills: `prd` and `next` (user-invocable, `disable-model-invocation: true`), `prd-artifact` (not user-invocable; read by agents and loadable by Claude when writing any brief or PRD). -- Workflows: `brief`, `panel`, `prd-draft`. A plugin workflow is itself a slash command [D], so `/ck:brief`, `/ck:panel`, and `/ck:prd-draft` all appear in autocomplete. `prd-draft` is safe to run directly if `docs/brief.md` exists; `/ck:prd` is the supported path. -- No name is shared between a skill and a workflow, because both occupy `/ck:`. +- Pipeline skills: `opportunity`, `prd`, `architecture`, `brand-guide`, `design`, `next` (user-invocable, `disable-model-invocation: true`). +- Workflows: `panel`, `market-research`, `brief`, `team`, `roadmap` (user-invocable directly, since they have no gate) and `draft`, `opportunity-draft`, `brand`, `design-round` (launched by their skills; runnable directly by Will). A plugin workflow is itself a slash command [D], so all nine appear in autocomplete. No name is shared between a skill and a workflow, because both occupy `/ck:`. +- Contracts: `-artifact` (not user-invocable; read by agents and loadable by Claude when writing that document type anywhere). +- Persona switch skills: `/ck:`, one per persona (§5.6). No persona name collides with a command name. - Agents: `river`, `akira`, ... in frontmatter (no colon allowed [D]); registered as `ck:river`, referenced as `agentType: 'ck:river'` in scripts and `subagent_type: "ck:river"` from the Agent tool. ### 4.5 Model policy and the effort axis -Two axes, adopted from the Opus PRD §7.8: the persona sets the model floor; the workflow stage sets the effort. Difficulty belongs to the task, not the persona. +Three persona tiers and two stage tiers. The persona sets the model floor; the workflow stage sets the effort. Difficulty belongs to the task, not the persona. [W, 2026-09-08] for the tiers; the effort axis is from the Opus PRD §7.8. + +| Tier | Model | Who | Why | +|---|---|---|---| +| Judgment | `claude-fable-5-1` | River, Akira, Morgan, Sage, Jordan, Reiner | The seats whose output is a decision: product, architecture, security, business, data, game design. Fable where it matters | +| Craft | `claude-opus-5` | Toni, Kai, Iris, Quinn, Casey, Cornelius, Ernie, Rez, Tracy, Travolta, Noon | Judgment-heavy craft at moderate volume | +| Execution | `claude-sonnet-5` | Sasha, Alex, Robin, Piper | Implementation and volume. Sonnet where it matters | +| Research (stage) | `claude-sonnet-5` | Neutral research agents in `market-research` | Volume reading and web search, checked afterwards | +| Classification (stage) | `claude-haiku-4-5-20251001` | Validators in every workflow | Shape checks against a checklist | +| Synthesis (stage) | The session model | Neutral synthesis and assembly agents | Holds no lens; inherits | | Agent kind | Model comes from | Effort comes from | Who may override the model | |---|---|---|---| -| Persona agent (`agentType: 'ck:'`) | Frontmatter `model:` from the §5.6 tiers, via `tiers.conf` upstream | The script, per stage; omitted means the session's effort | `panel.js` only, for lens decorrelation | -| Neutral utility agent (no `agentType`): validator, synthesis | The script sets `model` for the validator (Haiku 4.5, classification tier); synthesis inherits the session model | The script: validators run at `low` | The script | -| The main session (gates, `/ck:next`, finalize) | The user's session model | The session | The user | +| Persona agent (`agentType: 'ck:'`) | Frontmatter `model:` from `ck/tiers.conf` | The script, per stage; omitted means the session's effort | `panel.js` only, and only downward, for lens decorrelation | +| Neutral utility agent (no `agentType`) | The script | The script: validators at `low`, researchers at `medium` | The script | +| The main session (gates, `/ck:next`, finalize, switch skills) | The user's session model | The session | The user | -Precedence is per-invocation → frontmatter → `CLAUDE_CODE_SUBAGENT_MODEL` → session [D]. `agent()` accepts `effort` per call [D]. Persona frontmatter never sets `effort`, so one persona can run a mechanical stage at `low` and a design stage at `xhigh` without a second definition. `/workflows` shows the requested and any substituted model per agent [D]; that is the "resolved model recorded per run" the proposal asks for, at no cost. +Precedence is per-invocation → frontmatter → `CLAUDE_CODE_SUBAGENT_MODEL` → session [D]. `agent()` accepts `effort` per call [D]. Persona frontmatter never sets `effort`, so one persona can run a mechanical stage at `low` and a design stage at `xhigh` without a second definition. `/workflows` shows the requested and any substituted model per agent [D]. -Not in phase one: escalation chains, the Advisor tool, and mid-run arbitration. Workflows cannot pause for input [D], and `PreModelSwitch` fires only on a requested session switch [D], so the escalation design in the Opus PRD §7.8 has no mechanism today. Phase-one resilience is null-tolerant scripts: a stage that fails returns `null`, the script logs it and continues where it can. +Not in phase one: escalation chains, the Advisor tool, and mid-run arbitration. Workflows cannot pause for input [D], and `PreModelSwitch` fires only on a requested session switch [D]. Phase-one resilience is null-tolerant scripts: a stage that fails returns `null`, the script logs it and continues where it can. ### 4.6 What phase one deliberately does not build -Everything in proposal §6, plus: hook-enforced gates, a fallback chain, the Advisor tool, Routines, mid-run arbitration, persona switch skills, a `bin/` CLI, any UI. Reasons are in §10. +Everything in proposal §6, plus: hook-enforced gates, a fallback chain, the Advisor tool, Routines, mid-run arbitration, a `bin/` CLI, any UI, any review mechanism of its own (§4.9). Reasons are in §10. ### 4.7 Plugin, web app, wrapper, or dashboard -Will's question, answered with a recommendation: +Will's question, answered: 1. **It is a plugin.** Subagents, workflow scripts, and skills execute only inside Claude Code. A web app cannot run them. The plugin is the product; nothing wraps it. -2. **Single source of truth rules out a hosted app with its own store.** The family retired local persona overrides twice on exactly this ground [R]. A web app that stores persona or workflow definitions recreates the problem. Anything that edits must edit the same files, and the change must flow through git, the generator, and the tests. -3. **`/workflows` is the run view** [D]: phases, agent counts, tokens, elapsed time, drill-down to any agent's prompt and result. What it does not show is the static catalog (which workflows exist; which personas, tiers, and models each stage uses) and the per-run interaction graph (which lens asked which lens what). -4. **The catalog is derivable from files.** Every `ck` workflow declares `phases` and a `personas` list in `meta` (§6.5, §7.5). `meta` is a pure literal [D], so it names the default roster, not a run-time choice. Phase two `/ck:map` emits a Mermaid graph (workflow → phase → persona → tier → model) with one agent and no infrastructure; `/ck:map --run ` draws the per-run graph from `panel/*.json`. GitHub renders Mermaid in Markdown. -5. **If a workbench is ever built**, decide its two halves separately. The *viewer* half reads and never owns; it could be a local page or a published Artifact generated from the plugin's files. The *editor* half must be local, because only a local process can run `generate-agents.sh` and `tests/run.sh` before a commit. The conductor precedent applies: local server plus browser, Tauri dropped [R], Python by preference. Build it only when the files-as-workbench is shown insufficient, which means a specific edit Will could not make in a text editor plus `bump-upstream.sh`. +2. **Single source of truth rules out a hosted app with its own store.** The family retired local persona overrides twice on exactly this ground [R]. Anything that edits a persona or a workflow edits the same files in the `ck` source checkout, and the change flows through git, the generator, and the tests. +3. **`/workflows` is the run view in phase one** [D]: phases, agent counts, tokens, elapsed time, drill-down to any agent's prompt and result. What it does not show: the static catalog (which workflows exist; which personas, tiers, and models each stage uses) and the per-run interaction graph (which lens asked which lens what). +4. **The catalog is derivable from files.** Every `ck` workflow declares `phases` and a `personas` list in `meta`. `meta` is a pure literal [D], so it names the default roster, not a run-time choice. Phase two `/ck:map` emits a Mermaid graph (workflow → phase → persona → tier → model) with one agent and no infrastructure; `/ck:map --run ` draws the per-run graph from `panel/*.json`. +5. **The Workbench will be built, as phase three** [W, 2026-09-08]. It is a rewrite of the conductor dashboard, not an extension of it: a local server and a browser (the shape conductor already settled on [R]), Python by Will's preference, that shows the catalog, run history, cost, and persona usage, and edits personas and workflows against the `ck` source checkout by running the generator and the tests and committing. It reuses conductor's fixture-fenced JSONL cost parser and `pricing.json`. It never hosts a store of definitions. Its own PRD is written after phase one has run for real, because the catalog and run data it displays do not exist yet. §10.3 has the scope as far as it is known today. -### 4.8 Failure handling for the harder user +### 4.8 Plain language: house style for every message a skill prints -Adapted from the Opus PRD §7.11. This is a phase-one deliverable, not polish: one bad failure is how user 2 abandons a tool. +Adapted from the Opus PRD §7.11. Clare is proficient, so this is house style rather than protection. Three rules: -Three rules for every message the skills print: - -1. Never show a stack trace, a model name, or a token count. +1. Never show a stack trace. 2. Always name the file that holds the work completed so far. 3. Always give exactly one next action. -Three failure classes and what she sees: +Model names and costs may appear once, in the closing line of a run ("Three reviewers on three models; about $0.80"), never as a choice the user must make to proceed. Will's escape hatch: `/workflows` shows every agent, model, and token count. + +Three failure classes and what the user sees: | Failure | What she sees | What she can do | |---|---|---| @@ -276,128 +348,138 @@ Three failure classes and what she sees: | A stage fails after retries | "I couldn't finish the requirements section. Everything up to it is saved in `docs/PRD.md`. Run `/ck:prd` again to continue from there." | Run it again. Completed stages are skipped | | A panel lens or the whole workflow is unavailable | "One of the three reviewers didn't answer. The memo is based on the other two and says so." or "Claude is at capacity right now. Run `/ck:prd` again in a few minutes." | Wait or retry | -Will's escape hatch: `/workflows` shows every agent, model, and token count for anyone who wants them. The skills never print them. +### 4.9 Reviews: Claude's built-in review and comment system +Will's rule, recorded 2026-09-05 and confirmed 2026-09-08: every document for review arrives as a page he can comment on; every design for review arrives as a gallery of labeled variants, side by side, that he can comment on. That page is how feedback is given. Claude holds every comment, then works through and resolves all of them once the reviewer says "done". The page is Claude's own review and comment system, in the Claude desktop app or at claude.ai; `ck` builds nothing of its own for this. [W] -### 4.9 Review pages: the feedback channel +Mechanism, verified in this session's tool contract: a published page is private to the account; viewers switch it to comment mode and leave threads on any passage or element; Claude reads the threads, replies on threads a person has sent to Claude, republishes the same URL, and marks each thread resolved. -Will's rule, recorded 2026-09-05: whenever a workflow produces a document for review, it arrives as a web page he can comment on; whenever there are designs to review, they arrive as mockups with labeled variants side by side, also commentable. That page is how he gives feedback. Claude holds every comment, then works through and resolves all of them once he says he is done. +Every review page carries these five steps in its banner, because a page that says "comment anywhere" without them is a page nobody can comment on [R, 2026-09-08]: -Mechanism, verified in this session's tool contract: a published Artifact is a private HTML page on claude.ai; viewers leave comment threads on it; Claude reads the threads, replies on threads a person has sent to Claude, republishes the same URL, and marks each thread resolved. +1. Open the link signed in to your Claude account. +2. Switch the page to comment mode from the bar at the top. +3. Click the passage or the variant and type. +4. Put `@claude` in the comment so Claude can reply to it and resolve it. +5. Say "done" in the chat when you have finished. Rules: 1. One page per review, republished in place; never a new URL for a revision. -2. When the author says "done", read every thread, apply each change to the file on disk (the artifact is the state, §4.3), republish, and resolve each thread with one line saying what changed. A comment Claude will not act on gets a reply with the reason and stays open. -3. Mockup pages show labeled variants (A, B, C); the author comments to pick one or ask for changes. -4. Availability is a Phase 0 spike (§8.0, S5). Every gate keeps a file-edit path that works without it. +2. When the reviewer says "done", Claude reads every thread, applies each change to the file on disk (the document is the state, §4.3), republishes, and resolves each thread with one line saying what changed. A comment Claude will not act on gets a reply with the reason and stays open. A thread not sent to Claude is applied and reported in chat, because it cannot be replied to or resolved. +3. Document pages render the document with a sticky table of contents, so a comment can point at a section. +4. Gallery pages show labeled variants (A, B, C) side by side, each with its rationale and trade-off, each commentable; the reviewer comments to pick one or ask for changes. Brand galleries and design galleries use one page shape (§7.8, §7.9). +5. Availability of the publishing tool inside local Claude Code is Phase 0 spike S5 (§8.0). Every gate keeps a file-edit path that works without it: "Edit the file and run the command again; I'll pick up from your edits." -Phase one uses this at Gate 1 of `/ck:prd` (§7.6). Mockup review pages arrive with `/ck:brand-guide` in phase two. +Phase one uses this at every gate in §4.2's table, and for the PRD you are reading. --- -## 5. Personas as subagents +## 5. Personas as subagents and switch commands -### 5.1 Source of truth and vendoring +### 5.1 Source of truth -`claude-team-cli/profiles/.md` and `profiles/tiers.conf` remain the only place persona text and tiers are edited [R]. `ck` vendors them: +`ck/profiles/.md` and `ck/tiers.conf` are the only place persona text and tiers are edited. They are imported once from the old tool's `profiles/` directory at its commit `b4b211fbf4ec6f4d365a550b55e9981610ed7dda`, in the first commit of the `ck` repository, and are owned by `ck` from then on. There is no vendored copy, no lock file, no sync script, and no drift check against anything outside the repository. [W, 2026-09-08] -- `upstream/profiles/*.md` and `upstream/tiers.conf`: byte-for-byte copies at a pinned commit. -- `scripts/upstream.lock`: `repo=https://github.com/code-katz/claude-team-cli` and `commit=<40-hex>`. Today's `main` is `b4b211fbf4ec6f4d365a550b55e9981610ed7dda`. -- `scripts/bump-upstream.sh `: fetches the commit, replaces `upstream/`, regenerates `agents/`, updates the lock, and prints the diff of `agents/`. +Two files are generated from every profile, and one index from all of them: -A byte copy at a pinned SHA with a CI equality check is a cache, not a second source. It keeps the drift test offline, matching team-cli's rule that network checks are opt-in (its link check runs on dispatch, not on push) [R]. [P] +| Generated file | Purpose | Registered as | +|---|---|---| +| `agents/.md` | The persona as a subagent, on its tier, with interactive behaviors rewritten for output (§5.2, §5.4) | `ck:` | +| `skills//SKILL.md` | The persona as a session switch: the profile with its interactive behaviors intact, because a session has a user (§5.6) | `/ck:` | +| `profiles/ROSTER.md` | One line per persona: name, role, tier, one-sentence domain. Read by `/ck:team` and `/ck:opportunity` when choosing a cast | none | -### 5.2 Generation rule +`scripts/generate.sh` produces all three; CI fails on drift between `profiles/` and the generated files (§9). The two coordinator profiles are not imported: their routing behavior becomes `/ck:team` (§6.5) and `/ck:next` (§6.12), and their session greeting has no equivalent in a plugin. -`scripts/generate-agents.sh` is a fork of team-cli's generator [R] with the transform in §5.4. For each `upstream/profiles/.md` except `coordinator*`: +### 5.2 Generation rule for agents + +For each `profiles/.md`: ``` --- name: -description: , . Reviews and drafts from the perspective for ck panels and delegation; returns structured findings. +description: , . Reviews and drafts from the perspective for ck workflows and delegation; returns structured findings. model: --- - + --- -You are running as a delegated subagent. When the prompt names a run directory, read inputs from it and write outputs only there. If a schema is imposed, fill every required field; anything you would have asked goes in `questions`. Return findings first, detail after. +You are running as a delegated subagent. When the prompt names a project root and a run directory, read inputs from the project and write outputs only where the prompt says. If a schema is imposed, fill every required field; anything you would have asked goes in `questions`. Return findings first, detail after. ``` Frontmatter carries `name`, `description`, `model` and nothing else. Not set, with the reason: | Field | Why not in phase one | |---|---| -| `effort` | Would override the session effort for every panel run; keep the policy in one place (the session) until the drill shows a need | -| `tools`, `disallowedTools` | Agents must write under the run directory; per-path scoping is not available; revisit after the drill | +| `effort` | Effort belongs to the stage, set by the script (§4.5) | +| `tools`, `disallowedTools` | Agents must write under ``; per-path scoping is not available; revisit after the drill | | `maxTurns` | Workflow caps are the budget guard in phase one | | `color` | Cosmetic; the style guide assigns colors to projects, not personas | | `permissionMode`, `hooks`, `mcpServers` | Ignored for plugin agents [D] | ### 5.3 Tier table -From proposal §5.6, with the seven unassigned personas placed by this PRD (§3.3 item 4). The `Model` column is what `tiers.conf` must say after the prerequisite team-cli PR (§8.4); `ck` copies it verbatim. +`ck/tiers.conf`, format ` `, one line each. Three tiers [W, 2026-09-08]; the seven personas the proposal left unassigned are placed by role. -| Persona | Role | Tier | Model | Change from today | +| Persona | Role | Tier | Model | Change from the imported file | |---|---|---|---|---| -| akira | Backend Engineering | Judgment | `claude-opus-5` | from Fable 5 | -| river | Product Manager | Judgment | `claude-opus-5` | from Fable 5 | -| morgan | Security Engineering | Judgment | `claude-opus-5` | from Fable 5 | -| sage | Business Advisor | Judgment | `claude-opus-5` | from Fable 5 | -| jordan | Data and ML | Judgment | `claude-opus-5` | from Fable 5 | -| reiner | Tabletop Game Designer | Judgment | `claude-opus-5` | from Fable 5 (placed by this PRD) | -| toni | Product Marketing | Judgment | `claude-opus-5` | from Opus 4.8 | -| kai | UX Design and Visual Art | Judgment | `claude-opus-5` | from Opus 4.8 | -| iris | Brand and Illustration | Judgment | `claude-opus-5` | from Opus 4.8 | -| quinn | Project Manager | Judgment | `claude-opus-5` | from Opus 4.8 | -| casey | Data Analyst | Judgment | `claude-opus-5` | from Opus 4.8 | -| cornelius | Military Historian | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | -| ernie | WW2 Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | -| rez | Cyberpunk Genre Advisor | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | -| tracy | Fantasy Genre Advisor | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | -| travolta | Fantasy Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | -| noon | Cyberpunk Narrative Author | Judgment | `claude-opus-5` | from Opus 4.8 (placed by this PRD) | +| river | Product Manager | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| akira | Backend Engineering | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| morgan | Security Engineering | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| sage | Business Advisor | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| jordan | Data and ML | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| reiner | Tabletop Game Designer | Judgment | `claude-fable-5-1` | Fable 5 to Fable 5.1 | +| toni | Product Marketing | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| kai | UX Design and Visual Art | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| iris | Brand and Illustration | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| quinn | Project Manager | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| casey | Data Analyst | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| cornelius | Military Historian | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| ernie | WW2 Narrative Author | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| rez | Cyberpunk Genre Advisor | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| tracy | Fantasy Genre Advisor | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| travolta | Fantasy Narrative Author | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | +| noon | Cyberpunk Narrative Author | Craft | `claude-opus-5` | Opus 4.8 to Opus 5 | | sasha | Frontend Engineering | Execution | `claude-sonnet-5` | unchanged | | alex | DevOps and Platform | Execution | `claude-sonnet-5` | unchanged | | robin | QA and Testing | Execution | `claude-sonnet-5` | unchanged | | piper | Tabletop Playtester | Execution | `claude-sonnet-5` | unchanged | -Workflow-stage tiers, set in scripts, never on a persona: Deep research, `claude-fable-5-1` (the panel's decorrelation lens in phase one; deep passes in phase two); Classification, `claude-haiku-4-5-20251001` (the validator). +Six on Fable 5.1, eleven on Opus 5, four on Sonnet 5. Stage tiers (research, classification, synthesis) are set in scripts, never on a persona (§4.5). -Two [P] notes for the team-cli PR: (a) aliases `opus` and `sonnet` would let the tier follow the current generation without a file edit; the resolved model is recorded per agent in `/workflows` [D]; (b) moving River and Akira off Fable is a reasoning-tier downgrade for the two personas that write the PRD. The proposal's argument is price (Opus 5 at half) and Fable's cache advantage mattering most on long-horizon research. The 90-day usage data and the panel disagreement rate are the check; if PRD quality drops, the change is one line in `tiers.conf`. +Fable 5.1 rather than Fable 5: same price [D], newer generation. Full model IDs rather than aliases, so a tier changes only when someone edits this file; the resolved model is visible per agent in `/workflows` [D]. [P] ### 5.4 The interactive-behavior rewrite -Every profile has a `## Required Interactive Behaviors` section written as questions to the user (River: Three Whys, V0 Challenge, Premortem). team-cli's generator strips it from the slash command and keeps it in the subagent [R]. A subagent cannot ask [D]. The transform is mechanical, identical for all 21 personas, and adds no per-persona prose: +Every profile has a `## Required Interactive Behaviors` section written as questions to the user (River: Three Whys, V0 Challenge, Premortem). A subagent cannot ask [D]. The transform is mechanical, identical for all 21 personas, and adds no per-persona prose: 1. Rename the heading to `## Required Behaviors (subagent form)`. 2. Insert directly under it: > You are running with no user present. Every behavior below still applies, in output form. Where a behavior tells you to ask, halt, interrupt, or require an answer before proceeding: do not stop. State the question verbatim under `questions` (addressed to `author` or to a named teammate), state the assumption you will proceed on, and proceed. Where a behavior produces an artifact (table, diagram, scenario, counter-proposal, pitch), produce it in full. Where it requires a decision from the user, give your recommendation with evidence and mark the decision as open. -3. Keep the upstream text verbatim beneath. +3. Keep the profile text verbatim beneath. -What the preamble makes River do, and what `prd-draft.js` asks for by name: +What the preamble makes River do, and what the scripts ask for by name: -| Upstream behavior | Subagent form | +| Profile behavior | Subagent form | |---|---| -| Three Whys: ask "Why?" up to three times | Write the root-cause chain yourself from the brief (solution → why → why → why), each step more specific, until the user pain is exposed or the request is shown to address a symptom; say which. A why the brief cannot answer becomes a `questions` entry with your assumption | +| Three Whys: ask "Why?" up to three times | Write the root-cause chain yourself from the input (solution → why → why → why), each step more specific, until the user pain is exposed or the request is shown to address a symptom; say which. A why the input cannot answer becomes a `questions` entry with your assumption | | V0 Challenge: propose a V0 cutting half the scope and require a decision | Always include the V0 counter-proposal, what it cuts, whether it would still move the metric, and your recommendation with evidence. The decision stays with the author and is listed as open | -| Premortem: write the failure scenario and ask "What went wrong?" | Write the 2-3 sentence scenario in which this shipped on time and missed the metric, name the assumption it exposes, add that assumption to the Assumptions section, and leave the question verbatim for the author's gate | +| Premortem: write the failure scenario and ask "What went wrong?" | Write the 2-3 sentence scenario in which this shipped on time and missed the metric, name the assumption it exposes, add that assumption to the Assumptions section, and leave the question verbatim for the author's review | -The interactive versions of River's three behaviors live in `skills/prd/SKILL.md`, for the optional interview and the review, where there is a user. A CI check asserts the skill carries the three behavior headings from `upstream/profiles/river.md`, so a renamed behavior fails the build instead of diverging silently (§9). +The interactive versions of River's three behaviors live in `skills/prd/SKILL.md` for the optional interview, and in `skills/river/SKILL.md` for the switch. A CI check asserts both carry the three behavior headings from `profiles/river.md`, so a renamed behavior fails the build instead of diverging silently (§9). -### 5.5 Instrumentation hook +### 5.5 Hooks `hooks/hooks.json`: ```json { - "description": "ck: persona usage log, so the 90-day prune has data", + "description": "ck: persona usage log, and a check that the old tool is gone", "hooks": { "SubagentStart": [ { @@ -406,279 +488,496 @@ The interactive versions of River's three behaviors live in `skills/prd/SKILL.md { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/usage-log.sh\"" } ] } + ], + "SessionStart": [ + { + "hooks": [ + { "type": "command", "command": "\"${CLAUDE_PLUGIN_ROOT}/scripts/check-prereqs.sh\"" } + ] + } ] } } ``` -`scripts/usage-log.sh` reads the hook's stdin JSON, appends one line `{"ts":"","agent_type":"ck:","session_id":"","cwd":""}` to `${CLAUDE_PLUGIN_DATA}/usage.jsonl`, and always exits 0. Facts it relies on: `SubagentStart` matchers accept plugin-scoped names such as `^my-plugin:reviewer$`; stdin carries `agent_type` and `session_id`; `CLAUDE_PLUGIN_DATA` is exported to hook processes and survives plugin updates [D]. It never blocks: a logging failure must not stop a persona. +`scripts/usage-log.sh` reads the hook's stdin JSON, appends one line `{"ts":"","agent_type":"ck:","session_id":"","cwd":""}` to `${CLAUDE_PLUGIN_DATA}/usage.jsonl`, and always exits 0. Facts it relies on: `SubagentStart` matchers accept plugin-scoped names such as `^my-plugin:reviewer$`; stdin carries `agent_type` and `session_id`; `CLAUDE_PLUGIN_DATA` is exported to hook processes and survives plugin updates [D]. It never blocks: a logging failure must not stop a persona. The 90-day review reads this file and answers proposal §8.4. -The 90-day review reads this file and answers proposal §8.4. +`scripts/check-prereqs.sh` looks for `~/.claude/team/`, `~/.local/bin/claude-team`, and the old tool's block in `~/.claude/CLAUDE.md`. If any is present it prints one plain sentence ("The old team tool is still installed and its persona commands will collide with ck's. Remove it with the steps in the ck README.") and exits 0. It never blocks a session. -### 5.6 Acceptance criteria +### 5.6 Persona switch commands -- [ ] `agents/` holds exactly one file per `upstream/profiles/*.md` excluding `coordinator*` (21 today). -- [ ] Every agent's `model:` equals its `tiers.conf` line; `name:` equals the filename and contains no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble present; the generated-from comment names the lock's commit. -- [ ] Regenerating from `upstream/` produces no diff against the committed `agents/`. -- [ ] In a session with the plugin enabled, `@ck:river` appears in the subagent typeahead and `Agent({subagent_type: "ck:river", ...})` runs on `claude-opus-5` (visible in the transcript). +The session-switch route survives as `/ck:`, one generated skill per persona, `disable-model-invocation: true`, description "Switch this session to , ." The body is the profile verbatim, including `## Required Interactive Behaviors` and `## Greeting`, because a switched session has a user to ask. One sentence is prepended: "You are now for the rest of this session. You run on this session's model, not on your tier; to run on your tier, delegate to the `ck:` subagent." + +The three hand-off routes, all inside `ck`: + +| Route | How | Runs on | +|---|---|---| +| Switch this session | `/ck:river` | The session's model | +| Delegate one task | `Agent({ subagent_type: "ck:river" })` | River's tier | +| Run a pipeline stage or a fan-out | The `ck` workflows | Each persona's tier, per stage | + +The fourth route the old tool offered, a separate terminal session per persona, is what the workflows replace. What still needs a separate session (a long parallel build in its own worktree) is `/ck:feature`'s job in phase two. + +### 5.7 Acceptance criteria + +- [ ] `agents/` and `skills//` each hold exactly one file per `profiles/*.md` (21 today); `profiles/ROSTER.md` has 21 rows. +- [ ] Every agent's `model:` equals its `tiers.conf` line; `name:` equals the filename and contains no colon; `## Handoff Brief` present; `## Greeting` absent; the §5.4 preamble present; no `effort:` line. +- [ ] Every switch skill carries `## Required Interactive Behaviors` and `## Greeting` verbatim from its profile, and the prepended sentence. +- [ ] Regenerating from `profiles/` produces no diff against the committed generated files. +- [ ] In a session with the plugin enabled, `@ck:river` appears in the subagent typeahead and `Agent({subagent_type: "ck:river", ...})` runs on `claude-fable-5-1` (visible in the transcript); `/ck:river` switches the session. - [ ] After one `ck:` delegation, `${CLAUDE_PLUGIN_DATA}/usage.jsonl` has one new line with `agent_type` set. +- [ ] With `~/.claude/team/` present, a new session prints the one-sentence warning; without it, nothing. --- -## 6. `/ck:panel` +## 6. The pipeline -### 6.1 Purpose +### 6.1 Order, inputs, and outputs -Proposal goal 4: adversarial and complementary input on one decision, from the product lens, the marketing lens, and the UX lens, each on a different model, each reading its own evidence, each forced to argue against itself. The output is a decision memo that shows where the lenses disagree and leaves the decision to the author (proposal §5.5). The memo format follows Will's own panel brief: agreement is flagged as low-information, kill conditions are quoted and checked, and unique findings and unchecked areas are listed. +Each command runs when its required inputs exist in `` and names the missing one in a sentence when they do not. Optional inputs are read when present and skipped when absent. The order below is the order `/ck:next` recommends; any command can run on its own. -### 6.2 Invocation +| Step | Command | Requires | Reads if present | Writes | Gate | +|---|---|---|---|---|---| +| 1 | `/ck:opportunity` | An idea in a sentence | `docs/market-research.md`, `docs/TEAM.md` | `docs/opportunity.md` | Review page | +| 2 | `/ck:market-research` | `docs/opportunity.md` or `docs/brief.md` or a focus in a sentence | both | `docs/market-research.md` | None | +| 3 | `/ck:brief` | An idea in a sentence, or `docs/opportunity.md` | `docs/market-research.md` | `docs/brief.md` | None | +| 4 | `/ck:team` | `docs/brief.md` or `docs/opportunity.md` | `docs/PRD.md`, `docs/market-research.md` | `docs/TEAM.md` | None | +| 5 | `/ck:prd` | `docs/brief.md` | `docs/opportunity.md`, `docs/market-research.md`, `docs/TEAM.md`, `ROADMAP.md` | `docs/PRD.md`, `docs/decisions/-prd-review.md` | Review page | +| 6 | `/ck:roadmap` | `docs/PRD.md` | `docs/opportunity.md`, `docs/market-research.md`, `docs/TEAM.md` | `ROADMAP.md` | None | +| 7 | `/ck:architecture` | `docs/PRD.md`, `ROADMAP.md` | `docs/TEAM.md`, `docs/opportunity.md` | `docs/ARCHITECTURE.md`, `docs/decisions/-architecture-review.md` | Review page | +| 8 | `/ck:brand-guide` | `docs/opportunity.md` or `docs/brief.md` | `docs/PRD.md`, `docs/market-research.md` | `brand/`, `docs/decisions/-brand-direction.md`, `docs/brand-guide.md` | Two gallery pages | +| 9 | `/ck:design ` | `docs/PRD.md` | `docs/brand-guide.md`, `brand/final/`, `docs/ARCHITECTURE.md` | `docs/design//` | Gallery page | +| any | `/ck:panel ` | A question | Anything named as context | `docs/decisions/-.md` | None | +| any | `/ck:next` | Nothing | The table above | Nothing | None | -``` -/ck:panel Should the first release include the branding guide step? -/ck:panel Is this PRD ready for review? --context docs/PRD.md -/ck:panel --lenses river:claude-opus-5,morgan:claude-fable-5-1,sasha:claude-sonnet-5 -``` +Every subsection below has the same parts: purpose, invocation, cast and models, stages, the document, the gate, cost, acceptance. Stages are given as the `meta.phases` of the script. Four scripts are written in full in the appendices (`panel`, `brief`, `draft`, `team`); the other five are specified here to the stage level and follow the same conventions (required args, `startAt`, null-tolerant stages, a validator, the document path returned in the schema). -Claude passes the invocation as `args` [D]: +### 6.2 `/ck:opportunity` -```json -{ - "runId": "20260905T210000Z-branding-step", - "runDir": "/abs/path/.ck/runs/20260905T210000Z-branding-step", - "pluginRoot": "/abs/path/to/ck", - "timestamp": "20260905T210000Z", - "question": "Should the first release include the branding guide step?", - "contextPath": "/abs/path/docs/PRD.md", - "rationalePath": "/abs/path/docs/brief.md", - "memoPath": "docs/decisions/20260905T210000Z-branding-step.md", - "lenses": [{ "persona": "river", "lens": "product", "model": "claude-opus-5", "reads": ["docs/PRD.md", "ROADMAP.md"] }] -} -``` +**Purpose.** The first document on a new product: is this worth doing, for whom, in what market, in what technical shape, and what would have to be true. Modelled on the NIGHTGRID opportunity analysis, which is a multi-persona document: each lens writes its own section, and River holds the frame, the stage gates, and the risks. [W, 2026-09-08] -`runId`, `runDir`, `pluginRoot`, `timestamp`, and `question` are required; the script throws without them. Because a workflow is a slash command with no skill in front of it, the main session mints `runId` and `timestamp` with `date -u` and passes absolute paths; the workflow's `description` carries those instructions so a direct invocation still works. +**Invocation.** `/ck:opportunity `. With `docs/opportunity.md` already present, the skill offers to revise it (re-running Sections and Assemble on the comments) or start over. -### 6.3 Lenses, models, and evidence +**Cast and models.** River (Fable 5.1) frames and assembles. Contributors are chosen by River from `profiles/ROSTER.md` and `docs/TEAM.md` when it exists, up to four: Toni (Opus 5) always, for market context, positioning, and a go-to-market sketch; Akira (Fable 5.1) always, for the technical shape; a domain seat for the product's kind (Reiner for a game, Jordan for a data product, Sage for a business-model question, Cornelius for a historical setting); Sage optionally, for stage gates and monetization when the domain seat is not Sage. Contributors whose sections make claims about the world use web search and cite a source per claim (Phase 0 spike S7 confirms web search is available to subagents inside a workflow). -| Lens | Persona | Default model | Reads by default | Why this model | -|---|---|---|---|---| -| product | `ck:river` | `claude-opus-5` | `docs/PRD.md`, `ROADMAP.md` | River's own tier; the anchor lens | -| marketing | `ck:toni` | `claude-fable-5-1` | `docs/market-research.md`, `docs/gtm.md` | The strongest model on the lens most often under-argued in a product decision; also the most expensive lens (Appendix H) | -| ux | `ck:kai` | `claude-sonnet-5` | `brand/`, `docs/mockups/` | Completes three distinct models at the lowest added cost | +**Stages** (`workflows/opportunity-draft.js`, `meta.personas: ['river', 'toni', 'akira', 'sage', 'reiner', 'jordan']`): -Every lens also reads `contextPath` when given. Files in `reads` that do not exist are skipped and named in the result. Varying the evidence does more than varying the model (Opus PRD P7): three Claude tiers give scale diversity, not independent judgment, because they share one training pipeline. The memo header states this limitation (proposal §8.5). +| Phase | Agents | What happens | Writes | +|---|---|---|---| +| Frame | 1, `ck:river` | Reads the idea, the roster, and `docs/TEAM.md` and `docs/market-research.md` if present. Writes the concept statement and the hypothesis, chooses the contributors with a reason each, and writes one brief per contributor: the questions that section must answer | `/frame.json` | +| Sections | Up to 4, in parallel, `agentType` per contributor, `effort: 'high'` | Each writes its section to the contract's section spec for its lens, with sources for external claims and its Handoff Brief | `/sections/.md` | +| Assemble | 1, `ck:river` | Writes `docs/opportunity.md` to the contract: summary, concept, market context, one section per lens, stage gates, monetization, risks, open questions, sources. Applies River's behaviors in subagent form: the root-cause chain under the problem; a smaller first version under scope; the premortem left for the review | `docs/opportunity.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` to revise, at most twice | Checks the document against the contract checklist | `docs/opportunity.md` | -**Two passes.** Each lens forms and records its view from the material and its own evidence first. Only then, if `rationalePath` is given, does it read the author's rationale, check whether the claims it relied on are supported, and report whether its view changed. A reviewer who reads the rationale first ratifies instead of testing (Will's panel brief). +Seven to nine agents. Under the "medium" size guideline [D]. -Any lens can be replaced or re-modelled per run. If two lenses share a model the script logs that their agreement counts as one opinion. `panel.js` is the one script allowed to pass `model` on a persona agent (§4.5). [P] +**The document.** `docs/opportunity.md`, contract §7.1. -### 6.4 Lens schema +**The gate.** The skill publishes the document as a review page (§4.9) with one question at the top: "Imagine this was built and nobody wanted it. What did we get wrong?" On "done" it applies every comment, republishes, resolves, and finalizes inline with `ck:river` (fold the answer into Risks and Assumptions; resolve answered open questions; re-check the contract). -Every lens returns, and writes to `/panel/.json`: +**Cost.** About $2.50 per run (Appendix I). -| Field | Meaning | -|---|---| -| `recommendation` | `yes`, `no`, `yes-if`, `not-yet` | -| `position` | One paragraph | -| `reasoning` | Evidence from the material or the lens's own reading, not from the other lenses | -| `evidenceRead` | The files actually read, so the memo can say what each lens saw | -| `strongestArgumentAgainstOwnRecommendation` | The best case a smart colleague would make against it; a weak one is a failed answer | -| `killCondition` | The specific, observable condition under which the lens would say this should not be done at all | -| `killConditionMet` | `yes`, `no`, or `unknown`: does the material already show that condition | -| `killConditionEvidence` | Where in the material, or why unknown | -| `viewChangedByRationale` | `yes`, `no`, or `not-read` | -| `questionsForOtherLenses` | `[{to, question}]`, addressed to `author` or a lens persona | -| `handoffBrief` | Decisions to record, open risks in the domain, one direct question to a named lens | +**Acceptance.** +- [ ] On a fixture idea for a game, River chooses Reiner as the domain seat and says why in `frame.json`; on a fixture idea for a data product, Jordan. +- [ ] Every external claim in Market context carries a source; the Sources section lists each once. +- [ ] `docs/opportunity.md` has every contract section in order and passes the validator. +- [ ] The review page shows the premortem question at the top and the five comment steps in the banner; two comments are applied and resolved with one-line replies. +- [ ] Re-running with the document present offers revise or start over, and revise re-runs only Sections and Assemble. -The schema is enforced at the tool-call layer, so a lens that omits a field is retried by the harness [D]. +### 6.3 `/ck:market-research` -### 6.5 Stages +**Purpose.** A deeper market pass than the brief's, run as a fan-out: several questions researched in parallel on the web, cross-checked, and written up with a source per claim. The shape of a deep-research run: plan, fan out, cross-check, cite. [W, 2026-09-08] -`meta.phases` and `meta.personas` (for the phase-two map): +**Invocation.** `/ck:market-research [focus in a sentence]`. With no focus, the questions come from `docs/opportunity.md` or `docs/brief.md`; with neither and no focus, the workflow stops and names the missing input. -| Phase | Agents | What happens | -|---|---|---| -| Lenses | 3, in parallel, `agentType: 'ck:'`, `model` per lens | Each reads the material and its own evidence, records its view, then reads the rationale if given; applies its behaviors in subagent form; writes `panel/.json`; returns the object | -| Synthesis | 1, neutral (no `agentType`, session model) | Reads the three results, writes the memo at `memoPath`, returns the memo object | +**Cast and models.** Toni (Opus 5) plans and writes. Research agents are neutral, on Sonnet 5 at `effort: 'medium'`, one per question, with web search. The cross-checker is neutral on Sonnet 5. The validator is Haiku 4.5. -Four agents. One concurrency round on any machine with four or more CPUs. Full script: Appendix A. +**Stages** (`workflows/market-research.js`, `meta.personas: ['toni']`): -### 6.6 Decision memo +| Phase | Agents | What happens | Writes | +|---|---|---|---| +| Plan | 1, `ck:toni` | Reads the inputs. Writes four to six research questions across: market size and trends; competitors and substitutes; customers, segments, and channels; pricing and business models; platform, legal, or regulatory constraints. Each question names what a good answer contains | `/plan.json` | +| Research | 4 to 6, in parallel, neutral, Sonnet 5, `effort: 'medium'` | Each answers one question from the web: findings, each with a source URL, a date, and a confidence; contradictions it noticed; what it could not find | `/research/.json` | +| Cross-check | 1 neutral, Sonnet 5 | Every claim must carry a source or be marked unverified; claims that contradict each other across researchers are listed with both sources; stale sources (older than 18 months for a moving market) are flagged | `/crosscheck.json` | +| Write | 1, `ck:toni` | Writes `docs/market-research.md` to the contract: summary; market size and trends; competitors table; customers and channels; pricing and business models; constraints; contradictions and unknowns; implications for positioning; sources | `docs/market-research.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; Toni revises at most once | Contract checklist, including "every claim in the body has a source in Sources" | `docs/market-research.md` | -Default path `docs/decisions/-.md`, committed; the artifact is the state (§4.3). Sections, in order: +Eight to ten agents. Runnable headless; the first candidate for a Routine in phase two. -1. Question and context: run id, timestamp, the lens table with models and what each read, the decorrelation limitation, any lens that did not answer -2. Recommendations: table, lens | persona | model | recommendation | one-line position -3. Agreement, flagged as low-information: what all lenses concur on, and whether that is because it is obviously true or because they share a blind spot; the memo says which -4. Disagreement: every point where two lenses conflict, both positions at full strength, and the decision the author must make. Not adjudicated -5. Kill conditions, verbatim, with each lens's own answer to whether the material already shows it met -6. Each lens against itself, verbatim -7. Unique findings: anything only one lens saw -8. What nobody checked -9. Questions between lenses, verbatim -10. Handoff briefs, verbatim, one per lens +**The document.** `docs/market-research.md`, contract §7.2. No gate: the author reviews by comment or edit when they want to, and `/ck:brief` and `/ck:prd` read it as it stands. -The synthesis agent is neutral and holds no lens. It never averages positions or picks a winner. It computes `agreementRate` (the share of lenses on the most common recommendation) and sets `panelFailedToDisagree` when every lens recommends the same thing and no self-argument is substantive; the header then says the panel should be re-run with a different question or lens set. Above roughly two-thirds agreement the panel is theater (Will's brief); the rate is in the memo so `/ck:report` can track it later. +**Cost.** About $1.20 per run (Appendix I). -### 6.7 Failure handling +**Acceptance.** +- [ ] `plan.json` has between four and six questions covering at least four of the five areas. +- [ ] `/workflows` shows the Research phase running its agents in parallel on Sonnet 5. +- [ ] Every body claim carries a footnote or inline source that appears in Sources; a fixture with a planted contradiction (two researchers given conflicting seed facts) appears in Contradictions and unknowns. +- [ ] With no inputs and no focus, the workflow stops with one sentence naming what to run first. -| Failure | Behavior | -|---|---| -| A lens is stopped by the user or dies on an API error | `agent()` returns `null` [D]; the script logs which lens is missing and synthesizes on the survivors; the memo header says so; the skill's message follows §4.8 | -| Every lens fails | The script throws; nothing is written; the session sees the error and the skill translates it | -| Synthesis returns `null` | The script returns the raw lens results with `memoPath: null`; `panel/*.json` is on disk | -| Two lenses share a model | Logged; the run proceeds | -| A file in `reads` does not exist | Skipped; listed in `evidenceRead` as absent | +### 6.4 `/ck:brief` -### 6.8 Cost +**Purpose.** The short document that governs the expensive PRD run: the problem, the person, the number, the scope, and a basic market pass. One line of idea text in; `docs/brief.md` out; nothing asked. [W, 2026-09-08] for the market pass. -About $0.75 per run at today's prices, dominated by the Fable lens. Assumptions and arithmetic: Appendix H. +**Invocation.** `/ck:brief `, or `/ck:brief` alone when `docs/opportunity.md` exists, in which case the idea and the market context come from it. -### 6.9 Acceptance criteria +**Cast and models.** Toni (Opus 5) for the market pass, with web search; River (Fable 5.1) drafts; Haiku 4.5 validates. -- [ ] `/ck:panel ` in a session with the plugin enabled shows the consent prompt with the option "don't ask again for `ck:panel`" [D]; after consent it runs in the background and `/workflows` shows phases Lenses and Synthesis. -- [ ] `/panel/river.json`, `toni.json`, `kai.json` exist and validate against the lens schema; the memo exists at `docs/decisions/` with the ten sections. -- [ ] `/workflows` shows three different models on the three lens agents. -- [ ] Each lens's `evidenceRead` lists different files when the default `reads` exist. -- [ ] With `rationalePath` given, each lens reports `viewChangedByRationale` as `yes` or `no`, never `not-read`. -- [ ] Stopping one lens in `/workflows` produces a memo whose header names the missing lens. -- [ ] `--lenses` with a replaced persona and model is honored (visible in `/workflows` and in the memo's table). -- [ ] A deliberately one-sided question ("Should we keep the tests passing?") yields `panelFailedToDisagree: true` and an `agreementRate` of 1. -- [ ] The script passes §9 test 9. +**Stages** (`workflows/brief.js`, Appendix C, `meta.personas: ['toni', 'river']`): ---- +| Phase | Agents | What happens | Writes | +|---|---|---|---| +| Market pass | 1, `ck:toni` | Reads `docs/market-research.md` and `docs/opportunity.md` if present and searches only for what they lack. Returns three to five comparable products: what each does, who it is for, its price or model, and the gap this idea would fill; one source each; one paragraph on how crowded the space is | `/market.json` | +| Draft | 1, `ck:river` | Writes `docs/brief.md` to the contract: idea; problem and root-cause chain; user; success metric and leading indicator; comparable products (from Toni's pass, attributed); scope with a smaller first version and a recommendation; non-goals; open questions for the author. River's behaviors in subagent form: the whys are written, not asked; the smaller version is proposed, not negotiated | `docs/brief.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` once if needed | Contract checklist; one revision at most | `docs/brief.md` | -## 7. `/ck:brief`, `/ck:prd`, and `/ck:next` +Three to four agents. About two minutes. -### 7.1 Purpose +**The document.** `docs/brief.md`, contract §7.3 (full text: Appendix G). -Proposal goal 3: a PRD that has the same shape every time, in every project, produced by River with the product, marketing, and UX lenses challenging it before the author sees it. The shape comes from the artifact contract (§7.8); the process comes from three commands. The split between `brief` and `prd` is the one place a cheap early document governs an expensive later run (Opus PRD §7.4). +**The gate.** None. The closing message names the file and gives one action: "Read it, change anything, then run `/ck:team` or `/ck:prd`." -### 7.2 `/ck:brief` +**Cost.** About $0.55 per run (Appendix I). -A workflow (`workflows/brief.js`, Appendix C). Input: one line of idea text. Output: `docs/brief.md`. +**Acceptance.** +- [ ] `docs/brief.md` has the contract's eight sections in order and passes the validator. +- [ ] Comparable products lists three to five entries with a source each; when `docs/market-research.md` exists, the section cites it and the market pass makes fewer searches (visible in the transcript). +- [ ] The open-questions list is present even when empty. +- [ ] The closing message names the file and one next action. -``` -/ck:brief An app that reminds you to water each plant on its own schedule -``` +### 6.5 `/ck:team` -| Phase | Agents | What happens | -|---|---|---| -| Draft | 1, `ck:river` | Reads the idea and Part A of the contract. Writes `docs/brief.md`: the idea; the problem with the root-cause chain (why, why, why) written out; the user; one success number with a date and a leading indicator; the scope with a smaller first version and River's recommendation; non-goals; open questions for the author. River's interactive behaviors run in subagent form (§5.4): the chain of whys is written, not asked; the smaller version is proposed, not negotiated | -| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` once if needed | Checks the brief against Part A's checklist; one revision at most | +**Purpose.** Team selection and roles and responsibilities: which personas are on this product, who owns which document and stage, who reviews, and which seat is missing. "Say you are building a game: do you have the game designer on your team?" [W, 2026-09-08]. This is the old coordinator's routing behavior, written down once per product instead of asked once per session. -Three agents at most. About a minute. Cost in Appendix H. Acceptance: `docs/brief.md` exists with Part A's seven sections; the open-questions list is present even when empty; the skill's closing message names the file and gives one next action ("Read it, change anything, then run `/ck:prd`"). +**Invocation.** `/ck:team`. Reads `docs/opportunity.md`, `docs/brief.md`, `docs/PRD.md`, `docs/market-research.md`, whichever exist; requires at least one of the first two. With `docs/TEAM.md` present, re-nominates against the current documents and shows the diff in the closing message. -### 7.3 `/ck:prd`: entry +**Cast and models.** River (Fable 5.1) nominates and assembles. Each nominated persona confirms on its own tier at `effort: 'low'`. Haiku 4.5 validates. -A skill (`skills/prd/SKILL.md`, Appendix D), `disable-model-invocation: true`, argument hint `[--interview] [idea]`. +**Stages** (`workflows/team.js`, Appendix D, `meta.personas: [all 21]`): -1. **Precondition.** If the Workflow tool is not available in the session, stop: "Dynamic workflows are not available here. `/ck:prd` needs them." No fallback to running the stages by hand. -2. **Find the brief.** If `docs/brief.md` exists, go to step 4. If not and `--interview` was given, run the interview (step 3). Otherwise stop with one action: "Run `/ck:brief ` first. It takes about a minute and writes `docs/brief.md`. Then run `/ck:prd` again." -3. **The interview (Will's path).** River asks, one question at a time, and appends each answer to `/interview.md` before asking the next. Three Whys with early-stop options; the user; the success number and leading indicator; non-goals; the V0 Challenge with its three options; the lens choice ("default panel, or name lenses"); the output path (default `docs/PRD.md`). Then River writes `docs/brief.md` from the answers. The interview's three behavior headings match `upstream/profiles/river.md` (CI-checked, §9). An interview with answers but no brief is offered for resume on the next run. -4. **Resume check.** If `docs/PRD.md` exists and the latest `run.json` says the run stopped at a stage, offer to continue from that stage. If it says `final`, ask whether to revise (re-run the panel on named sections) or start over. -5. **Mint the run** (§4.3): timestamp, run id, absolute cache directory, `.git/info/exclude`, `run.json` with `status: "starting"`. +| Phase | Agents | What happens | Writes | +|---|---|---|---| +| Nominate | 1, `ck:river` | Reads the documents and `profiles/ROSTER.md`. Proposes the cast, up to eight: for each pipeline document and stage, an owner and reviewers; for each requirement area in the PRD if present, an owner; and the missing seats: needs no persona covers (legal, audio, localization, a specific domain), with what a person in that seat would own | `/nominations.json` | +| Confirm | Up to 8, in parallel, `agentType` per nominee, `effort: 'low'` | Each nominee reads the documents and its nomination and returns: accept or decline each responsibility with a reason; what it needs from whom before it can start; one risk in its domain; and one seat it thinks is missing | `/confirmations/.json` | +| Assemble | 1, `ck:river` | Writes `docs/TEAM.md` to the contract: cast table (persona, role, tier, why on this product); roles and responsibilities matrix (document or stage × owner, contributors, reviewers); hand-off order with what each hand-off carries; needs per persona; missing seats; declined nominations and why | `docs/TEAM.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; River revises at most once | Contract checklist, including "every pipeline document has exactly one owner" | `docs/TEAM.md` | -### 7.4 Launch and wait +Up to eleven agents; under the "medium" guideline. The Confirm fan-out is where a persona says "not me, and here is who": a nominee that declines names a replacement from the roster, and River takes it or explains why not. -The skill calls, exactly: +**The document.** `docs/TEAM.md`, contract §7.5. It is read by `/ck:opportunity` and `/ck:architecture` when choosing contributors and lenses, so a persona added here shows up in the later steps. -``` -Workflow({ - scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/prd-draft.js", - args: { - runId, runDir, pluginRoot: "${CLAUDE_PLUGIN_ROOT}", timestamp, - briefPath: "/docs/brief.md", prdPath: "/docs/PRD.md", - startAt: "", - lenses: - } -}) -``` +**The gate.** None. The author edits or comments when they disagree. + +**Cost.** About $1.00 per run (Appendix I). -It writes the returned run id into `run.json` as `harnessRunId` with `scriptPath`, sets `status: "drafting"`, tells the user in plain words that the draft is running in the background, and **stops: it waits for the task notification. It does not poll, does not narrate, and does not start other work on this run.** On a stop or failure it prints the §4.8 message naming `docs/PRD.md` and the one action, and records the failed stage in `run.json` so the next run passes the right `startAt`. Within the same session it may instead offer `Workflow({ scriptPath, resumeFromRunId: harnessRunId })`, which replays completed agents from cache [D]. +**Acceptance.** +- [ ] On the game fixture, Reiner and Piper are nominated and the missing-seats list is non-empty (audio, at least); on the data-product fixture, Jordan and Casey are nominated and Reiner is not. +- [ ] `/workflows` shows Confirm running the nominees in parallel, each on its tier model, at low effort. +- [ ] A fixture nominee instructed (via a seeded profile note in the test) to decline produces a replacement in `docs/TEAM.md` with River's reason. +- [ ] Every pipeline document in §6.1 has exactly one owner in the matrix; the validator passes. -`${CLAUDE_PLUGIN_ROOT}` expands anywhere in skill content [D]. Whether `name: "ck:prd-draft"` also works for the Workflow tool is unverified (§10.2); `scriptPath` is the specified path. +### 6.6 `/ck:prd` -### 7.5 The `prd-draft` workflow +**Purpose.** Proposal goal 3: a PRD that has the same shape every time, in every project, produced by River with the product, marketing, and UX lenses challenging it on three different models before the author sees it. The shape comes from the contract (§7.4); the process comes from the `draft` workflow (§4.1, one drafting engine). -`meta.personas: ['river', 'toni', 'kai']`. Full script: Appendix B. Stages run in order and each is skipped when `args.startAt` names a later one. +**Invocation.** `/ck:prd [--interview]`. Requires `docs/brief.md`; without it: "Run `/ck:brief ` first. It takes about two minutes and writes `docs/brief.md`. Then run `/ck:prd` again." With `--interview` and no brief, River interviews in the session (Will's path, Appendix E step 2) and writes the brief from the answers. + +**Cast and models.** River (Fable 5.1) drafts and rewrites. The panel: River on Fable 5.1 reading the brief, `docs/opportunity.md`, and `ROADMAP.md`; Toni on Opus 5 reading `docs/market-research.md` and `docs/opportunity.md`; Kai on Sonnet 5 (moved down from Opus 5 by the script, §4.5) reading `brand/` and `docs/design/`. Haiku 4.5 validates. Neutral synthesis inherits the session model. + +**Stages** (`workflows/draft.js` with `args.artifact: 'prd'`, Appendix B, `meta.personas: ['river', 'akira', 'toni', 'kai', 'morgan', 'alex', 'jordan']`; stages are skipped when `args.startAt` names a later one): | Phase | Agents | What happens | Writes | |---|---|---|---| -| Draft | 1, `ck:river` | Reads `docs/brief.md` and Part B of the contract. Writes `docs/PRD.md` to the contract's section order. Tags every claim not taken from the brief `[C1]`, `[C2]`, ... so the lenses can address it. Root-cause chain and V0 counter-proposal in subagent form. No premortem yet | `docs/PRD.md` | -| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` to revise, at most twice | Checks the draft against Part B's checklist; returns `{valid, missing[], notes}`. On `missing`, River revises in place, keeping every `[C]` tag. After two revisions the workflow proceeds and logs what is still missing | `docs/PRD.md` | -| Panel | 4, nested `workflow({scriptPath: pluginRoot + '/workflows/panel.js'})` | Question: "Is this PRD ready for the author's review, and what would you change before it ships?" Material: `docs/PRD.md`. Rationale, read second: `docs/brief.md`. Evidence per lens: River the brief and `ROADMAP.md`; Toni any positioning material; Kai any screens or mockups | `panel/*.json`, `docs/decisions/-prd-review.md` | -| Synthesize | 1, `ck:river` | Rewrites `docs/PRD.md`: revised where the panel showed a claim wrong or unsupported; **Appendix A, Challenged claims** (claim, challenged by, severity, status ∈ upheld, revised, withdrawn, open; resolution; the memo's disagreements reproduced verbatim; nothing deleted); **Appendix B, Premortem** (the scenario, the exposed assumption, the question "What went wrong?" left verbatim for the review) | `docs/PRD.md` | +| Draft | 1, `ck:river` | Reads `docs/brief.md`, the optional inputs, and the PRD contract. Writes `docs/PRD.md` to the contract's section order. Tags every claim not taken from the brief `[C1]`, `[C2]`, ... so the lenses can address it. Root-cause chain and V0 counter-proposal in subagent form. No premortem yet | `docs/PRD.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; then `ck:river` to revise, at most twice | Checks the draft against the contract checklist; returns `{valid, missing[], notes}`. On `missing`, River revises in place, keeping every tag. After two revisions the workflow proceeds and logs what is still missing | `docs/PRD.md` | +| Panel | 4, nested `workflow({scriptPath: pluginRoot + '/workflows/panel.js'})` | Question: "Is this PRD ready for the author's review, and what would you change before it ships?" Material: `docs/PRD.md`. Rationale, read second: `docs/brief.md`. Evidence per lens as above | `panel/*.json`, `docs/decisions/-prd-review.md` | +| Synthesize | 1, `ck:river` | Rewrites `docs/PRD.md`: revised where the panel showed a claim wrong or unsupported; **Appendix A, Challenged claims** (claim, challenged by, severity, status ∈ upheld, revised, withdrawn, open; resolution; the memo's disagreements and kill conditions reproduced verbatim; nothing deleted); **Appendix B, Premortem** (the scenario, the exposed assumption, the question "What went wrong?" left verbatim for the review) | `docs/PRD.md` | + +Seven agents without a revision, up to nine with two. If the nested panel throws, the workflow logs it and synthesizes without it, saying so in the PRD header. -Seven agents without a revision, up to nine with two. Under the default "medium" size guideline; about four sequential steps on a 4-CPU laptop, since the stages depend on each other. If the nested panel throws, the workflow logs it and synthesizes without it, saying so in the PRD header. +**Launch and wait.** The skill calls the Workflow tool with `scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/draft.js"` and the args in Appendix E, writes the returned run id into `run.json` as `harnessRunId`, tells the user in plain words that the draft is running in the background, and **stops: it waits for the task notification. It does not poll, does not narrate, and does not start other work on this run.** On a stop or failure it prints the §4.8 message naming `docs/PRD.md` and the one action, and records the failed stage in `run.json` so the next run passes the right `startAt`. `${CLAUDE_PLUGIN_ROOT}` expands anywhere in skill content [D]. -### 7.6 Gate 1: the review +**The document.** `docs/PRD.md`, contract §7.4 (full text: Appendix G). -Two paths, chosen by whether the Artifact tool is available in the session (Phase 0 spike, §8.0). +**The gate.** The review page (§4.9) with the premortem question at the top. On "done": every comment applied to `docs/PRD.md` (or answered with a reason), the page republished, each thread resolved with one line. File-edit fallback: "Open `docs/PRD.md`, change anything, save, and run `/ck:prd` again; I'll fold your edits in." Either path may trigger a focused re-run of the panel on named sections before finalizing. -**Review page (Will's feedback channel, §4.9).** The skill publishes `docs/PRD.md` as a private review page, with the premortem question at the top and one line of instructions: "Comment on anything. Say 'done' here when you are finished." It waits. When the user says done, it reads every comment thread, applies each one to `docs/PRD.md` (or replies with a reason when it will not), republishes the same page, and resolves each thread with one line saying what changed. Then it finalizes. +**Finalize.** One agent, inline (§4.2): `ck:river` folds the premortem answer into Assumptions and Risks, resolves each open decision as answered, keeps Appendix A intact, checks the result against the contract, writes `docs/PRD.md`, sets `status: final` in `run.json`. The skill prints the path and one next action: "Run `/ck:next`." + +**Cost.** About $2.30 per run without a revision, about $2.90 with one, plus the main session's turns (Appendix I). + +**Acceptance.** +- [ ] `/ck:prd` without a brief stops with the one-action message and runs nothing. +- [ ] `/ck:prd --interview` asks one question at a time; after the second why, `/interview.md` already holds the first two answers; killing the session and re-running offers to resume. +- [ ] `run.json` contains `harnessRunId` before the skill goes idle; `.git/info/exclude` contains `.ck/`; `git status` shows `docs/` files and nothing under `.ck/`. +- [ ] `/workflows` shows phases Draft, Validate, Panel (with the nested panel's agents on three models), Synthesize; the validator runs on Haiku 4.5; River runs on Fable 5.1. +- [ ] `docs/PRD.md` has every contract section, an Appendix A with at least one row per finding a lens raised, and an Appendix B with a scenario and the verbatim question. +- [ ] Stopping the workflow during Panel, then running `/ck:prd` again, continues from Panel without re-drafting (`startAt`). +- [ ] The review page is published with the five steps in its banner; two comments are applied and resolved with one-line replies; a thread not sent to Claude is applied and reported in chat. +- [ ] Without the publishing tool: the file-edit message is printed; an edit to `docs/PRD.md` followed by `/ck:prd` finalizes from the edited file. +- [ ] The final PRD is at `docs/PRD.md` with `status: final` in `run.json`, and its checklist passes when re-validated by hand. +- [ ] `skills/prd/SKILL.md` contains the three behavior headings from `profiles/river.md` (CI-checked). + +### 6.7 `/ck:roadmap` + +**Purpose.** The roadmap in the family's own format (the roadmap skill's `ROADMAP.md` structure [R]): a current-state snapshot, opportunities in three tiers with why-now and a success signal, recommended sequencing, open questions, an OKR table, and a revision history. River prioritizes; Quinn sequences. + +**Invocation.** `/ck:roadmap`. Requires `docs/PRD.md`. With `ROADMAP.md` present, runs in update mode: Section 1 is rewritten and a revision-history entry is appended, per the roadmap skill's own workflow [R]. + +**Cast and models.** River (Fable 5.1), Quinn (Opus 5), Haiku 4.5 validates. + +**Stages** (`workflows/roadmap.js`, `meta.personas: ['river', 'quinn']`): + +| Phase | Agents | What happens | Writes | +|---|---|---|---| +| Prioritize | 1, `ck:river` | Reads the PRD and the optional inputs. Writes the current-state snapshot and the opportunities in three tiers (ship next; high value, next sprint; strategic), each with why now or why not now and a measurable success signal, and the OKR table | `/priorities.json` | +| Sequence | 1, `ck:quinn` | Writes `ROADMAP.md` to the contract: recommended sequencing with dependencies and what each step unblocks; open questions; the revision-history entry (what changed, why, open questions resolved or added, triggered by) | `ROADMAP.md` | +| Validate | 1 neutral, Haiku 4.5, `effort: 'low'`; Quinn revises at most once | Contract checklist | `ROADMAP.md` | -**File edit (always available).** "Open `docs/PRD.md`, change anything you like, save, and run `/ck:prd` again. I'll fold your edits in." On the next run the skill sees `status: "review"` in `run.json` and finalizes from the edited file. +Three to four agents. -Either path may also trigger a targeted re-run: `Workflow({ scriptPath: "${CLAUDE_PLUGIN_ROOT}/workflows/panel.js", args: { ..., question: "", contextPath: "/docs/PRD.md", rationalePath: "/docs/brief.md" } })`, then back to this gate. +**The document.** `ROADMAP.md` at the root of ``, contract §7.6, which is the roadmap skill's structure verbatim so that the skill and this workflow produce interchangeable files. -### 7.7 Finalize +**The gate.** None. -One agent, so no workflow (§4.2): +**Cost.** About $0.70 per run (Appendix I). + +**Acceptance.** +- [ ] On a project with no `ROADMAP.md`, the file is created with Section 1 and Section 2 in the roadmap skill's format and passes that skill's lint check [R]. +- [ ] On a project with one, Section 1 is replaced and exactly one revision-history entry is prepended, dated with the run's timestamp. +- [ ] Every Tier 1 opportunity traces to a numbered PRD requirement. + +### 6.8 `/ck:architecture` + +**Purpose.** The PRD and the roadmap in; a recommended architecture out, with the alternatives considered, the decision record, and a security, platform, and data challenge on three models before the author sees it. [W, 2026-09-08] + +**Invocation.** `/ck:architecture`. Requires `docs/PRD.md` and `ROADMAP.md`; names the missing one otherwise. + +**Cast and models.** Akira (Fable 5.1) drafts and rewrites. The panel: Morgan (security) on Fable 5.1 reading `docs/PRD.md` and any `SECURITY.md`; Alex (platform and operations) on Sonnet 5 reading any `infra/`, `Dockerfile`, or CI configuration; Jordan (data) on Opus 5 (moved down from Fable 5.1 by the script) reading `docs/market-research.md` and any `data/` or schema files. Three models. Haiku 4.5 validates. + +**Stages.** `workflows/draft.js` with `args.artifact: 'architecture'` (Appendix B): the same Draft, Validate, Panel, Synthesize as §6.6, with the architecture contract, Akira as author, the lenses above, and the panel question "Would you build it this way, and what would you change before the first line of code?" + +| Phase | Author's work, specific to this document | +|---|---| +| Draft | `docs/ARCHITECTURE.md` to the contract: context and constraints from the PRD and roadmap; quality attributes ranked; the recommended architecture with a Mermaid diagram; components and their responsibilities; data model sketch; integration points; alternatives considered and why not; decision record; sequencing against the roadmap; risks; open questions. Every claim not from the PRD tagged `[C]` | +| Synthesize | The same appendices as the PRD: Challenged claims, and a Premortem written as "this shipped and fell over in production; what did we get wrong?" | + +**The document.** `docs/ARCHITECTURE.md`, contract §7.7. + +**The gate.** The review page with the premortem question. Finalize inline with `ck:akira`. + +**Cost.** About $2.40 per run (Appendix I). + +**Acceptance.** +- [ ] Without `ROADMAP.md`, the skill stops and names `/ck:roadmap`. +- [ ] `/workflows` shows Akira on Fable 5.1, and the three lenses on three different models. +- [ ] `docs/ARCHITECTURE.md` has a rendered Mermaid diagram, an alternatives table with at least two rows, and a decision record with a date. +- [ ] Every Tier 1 roadmap item is placed in the sequencing section. + +### 6.9 `/ck:brand-guide` + +**Purpose.** A brand identity, produced the way NIGHTGRID's was: proposal rounds, then candidates, then finalists, each as a gallery of labeled variants the author comments on, ending in a brand direction record and a brand identity guide with the d20Mob guide's structure. [W, 2026-09-08] + +**Invocation.** `/ck:brand-guide`. Requires `docs/opportunity.md` or `docs/brief.md`. With `docs/brand-guide.md` present, offers a revision round on the finalists. + +**Cast and models.** Iris (Opus 5) leads: marks, palette, type, art direction. Kai (Opus 5) skins UI surfaces in each direction. Toni (Opus 5) supplies one positioning line per direction before Iris starts. Haiku 4.5 validates each gallery against the gallery contract. Output is SVG, HTML, and CSS; raster generation is out of scope. + +**Stages** (`workflows/brand.js` with `args.stage` ∈ `proposals | finalists | guide`; the skill runs one stage, gates, then the next; `meta.personas: ['iris', 'kai', 'toni']`): + +| Stage | Agents | What happens | Writes | +|---|---|---|---| +| Proposals | Toni, then Iris, then Kai, then validator | Toni: a positioning line and an audience note per candidate direction. Iris: four to six brand directions, each with a name treatment, palette, type pairing, mood words, one hero mark, and a rationale and trade-off. Kai: one UI surface per direction in that direction's skin. Assembled as a gallery page, labeled A to F | `brand/proposals/gallery.html`, `brand/proposals/