diff --git a/README.md b/README.md
index 1223113..b8ab26c 100644
--- a/README.md
+++ b/README.md
@@ -2,12 +2,40 @@
Local **solo EM workbench** for evidence-backed performance reviews and promotion cases.
-ICs never log in. Self/peer input arrives as JSON import bundles. Your vault stays on disk — **Lock & encrypt** seals SQLite + files at rest.
+ICs never log in. Self and peer input arrives as JSON import bundles. Your vault stays on disk: **Lock & encrypt** seals SQLite and dossier files at rest.
+## Why this exists
+
+Most review tools are either a shared HR portal (everyone logs in) or a blank Google Doc. This app is for one engineering manager who wants:
+
+1. **A year-round dossier** so writing season is not a scavenger hunt
+2. **Role frameworks as the bar** so ratings map to expectations, not vibes
+3. **Evidence-linked drafts** so extreme scores and promo claims stay grounded
+4. **Local custody** so private notes and underperformance plans stay on your machine until you export
+
+The product is intentionally single-user. Peers and ICs participate by filling exported forms that you import back. That keeps anonymity and trust simple for v1.
+
+## Core loop
+
+```
+upload role R&R → assign people → capture dossier evidence
+ → open a cycle → import self/peer bundles → writing desk (+ AI)
+ → consistency + team performance check → share export → history / promo packets
+```
+
+| Stage | Intent |
+|-------|--------|
+| Roles + people | Define what "good" means before you score anyone |
+| Dossier | Accumulate achievements, goals, feedback, docs, and concerns all year |
+| Cycle + bundles | Time-box the review without building a multi-user portal |
+| Writing desk | Draft, cite, lint, finalize, then share a subject packet |
+| Consistency / team performance | Catch clustering, thin evidence, and odd rating shapes before you ship |
+| Promotions | Reuse the same role bar for next-level / promo cases |
+
## Quick start
```bash
@@ -24,6 +52,8 @@ pnpm dev
First load: **Create & seed demo team** (8-person org), then unlock. Between sessions use **Lock & encrypt**.
+Requires **pnpm 10.33.3** (see [`AGENTS.md`](./AGENTS.md) if Corepack hands you pnpm 11).
+
### Desktop (Tauri)
```bash
@@ -31,11 +61,11 @@ pnpm desktop:dev # native window (needs WebView + Rust)
pnpm desktop:build
```
-See [`apps/desktop/README.md`](./apps/desktop/README.md).
+Packaged builds on `main` CI upload installers as Actions artifacts (`desktop-windows-x86_64`, `desktop-macos-aarch64`, `desktop-linux-x86_64`). Details: [`apps/desktop/README.md`](./apps/desktop/README.md).
### Cursor MCP (bulk load)
-`@prm/mcp` unlocks the vault and writes dossier evidence — pair with Jira/Google MCPs for cold-start backfill.
+`@prm/mcp` unlocks the vault and writes dossier evidence. Pair it with Jira, Bitbucket, or other MCPs when you need a cold-start backfill instead of typing every note by hand.
```bash
pnpm mcp
@@ -51,49 +81,65 @@ Regenerate with `pnpm screenshots` (UI + API running; default password `workbenc
### Unlock
-Encrypted vault entry. Seed password `workbench`.
+**Intent:** Keep the workspace sealed when you walk away. The unlock gate is the trust boundary for local data.
+
+**How it works:** On first run you create a workspace password and can seed a demo org. Later sessions decrypt the vault with that password. **Lock & encrypt** re-seals SQLite and files so a stolen laptop disk is not a readable review archive.

-### Home — command center
+### Home (command center)
+
+**Intent:** Answer "who is blocked, and what should I do next?" without hunting through every page.
-Who to unblock next: roles, self bundles, then writing.
+**How it works:** Pick a cycle to see pipeline status (self / peer / manager), deadline nudges for missing self reviews, and a compact cycle dashboard (writing time, evidence coverage, thin dossiers). Links out to writing desks, backfill, and team performance when the numbers look thin.

### Team
-Directs roster. Open a dossier to capture year-round evidence.
+**Intent:** Maintain the roster of directs you actually manage reviews for.
+
+**How it works:** List, add, or CSV-import people, then open a person to work their dossier. This is the directory, not the evaluation surface. Role assignment and cycle participation hang off these records.

### Person dossier
-Achievements, goals, feedback, and documents — the citation pool for writing.
+**Intent:** Build a citation pool all year so the writing desk is not empty in week one of reviews.
+
+**How it works:** Capture achievements, goals, feedback (with optional 1:1 theme tags), documents, concern / underperformance notes, and external links (for example Jira or Bitbucket sync). Visibility controls keep EM-only material out of subject exports. AI digests and drafts pull from this pool (and from concerns only when you opt them in).

### Roles
-Assign current (+ next) RoleDefinitions — the evaluation bar.
+**Intent:** Make the evaluation bar explicit. Ratings should map to role expectations, not a private mental model.
+
+**How it works:** Author or import RoleDefinitions (ladder levels, competency keys, expectations). Assign each person a current role and optionally a next role for promo / gap work. Uploaded R&R docs can be structured manually or with AI extract. Writing desks and promotion packets read from these definitions.

### Cycles
-Export/import self & peer JSON bundles outside the app.
+**Intent:** Time-box a review season and collect self / peer input without live IC login.
+
+**How it works:** Create a cycle with a window and soft phases. Export JSON bundles for self and peer forms, collect them outside the app, then import responses. Waive with a reason when someone is not returning a form. Participants snapshot who was on the team for that cycle.

### Writing desk
-Competency scores + evidence links → bias lint → finalize (citation snapshots) → share HTML/PDF.
+**Intent:** Produce an evidence-backed manager review in a bounded amount of time (target ≤45 minutes per person).
+
+**How it works:** Score competencies and overall against the assigned role, link dossier evidence to non-middle scores, draft narrative sections (optionally with AI from an allowlisted citation set), run bias / faithfulness lint, log decision reasons when ratings move, then finalize. Finalize freezes citation snapshots. Share exports HTML (print to PDF) with private notes and EM-only sources stripped.

### Promotions
-Next-role packets for skip-level / promo cases.
+**Intent:** Reuse the same role bar for next-level and promotion cases instead of a parallel doc pile.
+
+**How it works:** Open a promotion packet against a target RoleDefinition. Mark gaps / demonstrating signals, draft the case (optionally with AI), and keep it alongside the cycle review history so skip-level conversations stay evidence-backed.

@@ -101,41 +147,59 @@ Next-role packets for skip-level / promo cases.
### Consistency
-Rating distribution and side-by-side drafts before you finalize.
+**Intent:** Catch unfair shape in your own drafts before anyone else sees them (everyone a 4, extreme scores with no cites, missing roles).
+
+**How it works:** For a selected cycle, show overall rating distribution and a card per person with competencies, evidence link counts, and flags (thin evidence, extreme overall, unassigned role). Jump into each writing desk to fix gaps. This is single-EM calibration, not a multi-manager room.

+### Team performance
+
+**Intent:** See the team's rating and coaching shape as graphs, not only as a queue of drafts.
+
+**How it works:** Cycle-scoped charts for overall distribution, evidence vs overall, competency averages, promo readiness, writing-time buckets, level mix, and top 1:1 themes. The people table adds competency sparklines and prior-cycle overall deltas when history exists. Use it with Consistency: graphs for pattern, cards for per-person fixes.
+
+
+
### Backfill
-Fill thin dossiers (or pair with MCP bulk load) so cold-start writing isn’t empty.
+**Intent:** Unblock writing when dossiers are still empty after you first adopt the tool.
-
+**How it works:** Lists people below the thin-dossier threshold (few achievements / feedback / docs / goals). Walk a short wizard to add starter evidence, or use MCP / integrations for bulk load. The goal is a usable citation pool, not perfect history on day one.
+
+
### AI Chat
-Grounded Q&A over workspace/dossier data — cites ids, doesn’t invent evidence.
+**Intent:** Ask grounded questions over the workspace or a single dossier without inventing evidence.
+
+**How it works:** Chat is scoped to workspace or person context, cites allowlisted ids from real dossier rows, and respects private-tier egress settings. It is for synthesis and retrieval, not a substitute for the writing desk finalize path.
-
+
### Settings
-AI provider, egress gates (including document extracts), theme.
+**Intent:** Configure providers, privacy gates, appearance, and vault maintenance in one place.
+
+**How it works:** Set AI provider and models (Anthropic, OpenAI, Cursor gateway, Ollama), toggle egress for private notes / meetings / document extracts, manage Jira and Bitbucket credentials, run encrypted backup / restore, verify the activity log, and switch dark / light theme.
-
+
---
## What’s in this slice
-- **Encrypted vault** (AES-256-GCM) for DB + dossier files on lock
-- **People / roles / cycles** with self & peer JSON bundles
-- **Writing desk** — competencies, evidence links, citation freeze, HTML/PDF subject packets
-- **Consistency** view + **bias/tone lint** before share
-- **Promotions** against next-role expectations
-- **Backfill** wizard + MCP bulk load for thin dossiers
-- **AI** — digests, section draft, peer synthesize, chat (Anthropic / OpenAI / Ollama) with citation allowlist
-- **Dark / light** theme preference
+- **Encrypted vault** (AES-256-GCM) for DB and dossier files on lock
+- **People / roles / cycles** with self and peer JSON bundles
+- **Writing desk**: competencies, evidence links, citation freeze, HTML subject packets
+- **Consistency** and **team performance** views before you share
+- **Bias / faithfulness lint** (advisory) on drafts
+- **Promotions** against next-role expectations
+- **Backfill** wizard plus MCP / Jira / Bitbucket paths for thin dossiers
+- **AI**: digests, section draft, peer synthesize, chat, with citation allowlist
+- **Desktop** packaging (Tauri) with CI installers on `main`
+- **Dark / light** theme preference
## Docs
-Product & architecture under [`/docs`](./docs). Core loop evaluation: [`docs/CORE_LOOP_EVAL.md`](./docs/CORE_LOOP_EVAL.md). Cursor cloud notes: [`AGENTS.md`](./AGENTS.md).
+Product and architecture live under [`/docs`](./docs). Start with [`docs/PRODUCT_BRIEF.md`](./docs/PRODUCT_BRIEF.md). Core loop evaluation: [`docs/CORE_LOOP_EVAL.md`](./docs/CORE_LOOP_EVAL.md). Cursor cloud notes: [`AGENTS.md`](./AGENTS.md).
diff --git a/docs/screenshots/02-home.png b/docs/screenshots/02-home.png
index 1c7080d..36d3136 100644
Binary files a/docs/screenshots/02-home.png and b/docs/screenshots/02-home.png differ
diff --git a/docs/screenshots/03-team.png b/docs/screenshots/03-team.png
index c7b5c97..3a7165d 100644
Binary files a/docs/screenshots/03-team.png and b/docs/screenshots/03-team.png differ
diff --git a/docs/screenshots/04-person.png b/docs/screenshots/04-person.png
index 03304b7..d218a3f 100644
Binary files a/docs/screenshots/04-person.png and b/docs/screenshots/04-person.png differ
diff --git a/docs/screenshots/05-roles.png b/docs/screenshots/05-roles.png
index 88c80d4..64335ef 100644
Binary files a/docs/screenshots/05-roles.png and b/docs/screenshots/05-roles.png differ
diff --git a/docs/screenshots/06-cycles.png b/docs/screenshots/06-cycles.png
index 8bf0e18..ae91fe5 100644
Binary files a/docs/screenshots/06-cycles.png and b/docs/screenshots/06-cycles.png differ
diff --git a/docs/screenshots/07-writing-desk.png b/docs/screenshots/07-writing-desk.png
index 990fa53..90a87dd 100644
Binary files a/docs/screenshots/07-writing-desk.png and b/docs/screenshots/07-writing-desk.png differ
diff --git a/docs/screenshots/08-promotions.png b/docs/screenshots/08-promotions.png
index 8e6f687..71915cf 100644
Binary files a/docs/screenshots/08-promotions.png and b/docs/screenshots/08-promotions.png differ
diff --git a/docs/screenshots/09-promotion-detail.png b/docs/screenshots/09-promotion-detail.png
index 3b7489a..b705b12 100644
Binary files a/docs/screenshots/09-promotion-detail.png and b/docs/screenshots/09-promotion-detail.png differ
diff --git a/docs/screenshots/10-consistency.png b/docs/screenshots/10-consistency.png
index 2781d6a..8205457 100644
Binary files a/docs/screenshots/10-consistency.png and b/docs/screenshots/10-consistency.png differ
diff --git a/docs/screenshots/11-backfill.png b/docs/screenshots/11-backfill.png
deleted file mode 100644
index 98b012c..0000000
Binary files a/docs/screenshots/11-backfill.png and /dev/null differ
diff --git a/docs/screenshots/11-team-performance.png b/docs/screenshots/11-team-performance.png
new file mode 100644
index 0000000..d423408
Binary files /dev/null and b/docs/screenshots/11-team-performance.png differ
diff --git a/docs/screenshots/12-backfill.png b/docs/screenshots/12-backfill.png
new file mode 100644
index 0000000..2e75724
Binary files /dev/null and b/docs/screenshots/12-backfill.png differ
diff --git a/docs/screenshots/12-chat.png b/docs/screenshots/13-chat.png
similarity index 54%
rename from docs/screenshots/12-chat.png
rename to docs/screenshots/13-chat.png
index cae09f3..71cb8b0 100644
Binary files a/docs/screenshots/12-chat.png and b/docs/screenshots/13-chat.png differ
diff --git a/docs/screenshots/13-settings.png b/docs/screenshots/13-settings.png
deleted file mode 100644
index f5bda82..0000000
Binary files a/docs/screenshots/13-settings.png and /dev/null differ
diff --git a/docs/screenshots/14-settings.png b/docs/screenshots/14-settings.png
new file mode 100644
index 0000000..1f75e0b
Binary files /dev/null and b/docs/screenshots/14-settings.png differ
diff --git a/docs/screenshots/README.md b/docs/screenshots/README.md
index 133ed06..0ba15b0 100644
--- a/docs/screenshots/README.md
+++ b/docs/screenshots/README.md
@@ -10,3 +10,5 @@ pnpm screenshots
```
Requires system Chrome (`google-chrome-stable`) and root `puppeteer-core`.
+
+Numbering matches the README Screens section (`01` unlock through `14` settings), including `11-team-performance`.
diff --git a/scripts/capture-screenshots.mjs b/scripts/capture-screenshots.mjs
index 8482b67..3212cd4 100644
--- a/scripts/capture-screenshots.mjs
+++ b/scripts/capture-screenshots.mjs
@@ -1,14 +1,15 @@
#!/usr/bin/env node
/**
- * One-off gallery capture for README. Usage:
- * node scripts/capture-screenshots.mjs
- * Expects UI on localhost:5175 (or UI_URL) and API unlocked via password.
+ * Gallery capture for README. Usage:
+ * pnpm screenshots
+ * UI_URL=http://localhost:5173 PRM_PASSWORD=workbench pnpm screenshots
+ * Expects UI + API running (defaults: UI :5173, API :8787).
*/
import fs from "node:fs";
import path from "node:path";
import puppeteer from "puppeteer-core";
-const UI = process.env.UI_URL || "http://localhost:5175";
+const UI = process.env.UI_URL || "http://localhost:5173";
const API = process.env.API_URL || "http://127.0.0.1:8787";
const PASSWORD = process.env.PRM_PASSWORD || "workbench";
const OUT = path.resolve("docs/screenshots");
@@ -87,9 +88,10 @@ async function main() {
["07-writing-desk", `/cycles/${cycle.id}/write/${person.id}`],
["08-promotions", "/promotions"],
["10-consistency", "/consistency"],
- ["11-backfill", "/backfill"],
- ["12-chat", "/chat"],
- ["13-settings", "/settings"],
+ ["11-team-performance", "/team-performance"],
+ ["12-backfill", "/backfill"],
+ ["13-chat", "/chat"],
+ ["14-settings", "/settings"],
];
if (promo?.id) routes.splice(6, 0, ["09-promotion-detail", `/promotions/${promo.id}`]);
@@ -102,6 +104,9 @@ async function main() {
document.querySelector(".chat-composer")?.scrollIntoView({ block: "end" });
});
}
+ if (route === "/team-performance") {
+ await page.waitForSelector(".tp-metrics, .tp-grid, h2", { timeout: 15000 });
+ }
await new Promise((r) => setTimeout(r, 450));
await shot(page, name);
}