| name | perfect |
| contexts | tracked |
| memory | vault |
| category | Development |
| description | Session-after-session product perfection loop. The strongest available model at xhigh reasoning (currently Fable 5) directs — it walks the repo's context map context-by-context, proposes 5 challenged, high-value directions per context (features, design elevations, significant optimizations), gates them with the user until 10 are accepted, then orchestrates one Opus-class builder subagent per context in isolated worktrees while making every review/merge decision itself. All state lives in a linked Obsidian vault so any future session resumes the loop exactly where the last one stopped. Invoke with `/perfect [init|propose|build|status|reflect] [context-name]`. |
Perfect — the direction-and-delivery loop
One model configuration is best at judgment — seeing what would make a product excellent, challenging its own ideas, reviewing diffs ruthlessly. A well-scoped builder is great at execution inside a tight brief. /perfect wires the two together in a permanent loop: the strongest model at xhigh directs, Opus-class builders build, the vault remembers. Each session moves the product measurably closer to the best UX, architecture, and feature quality it can have; no session ever starts from zero.
Roles — Director and Builders
- Director (the main session — the strongest available model at xhigh reasoning; currently Fable 5, Opus 5 acceptable fallback). Owns everything that is judgment: opportunity-scoring contexts, drafting directions, adversarially challenging them before the user ever sees them, running the acceptance gate, writing builder briefs, answering builders' product questions mid-flight, reviewing every diff, deciding merge/redo/drop, running the repo gates, committing, and writing the vault. The Director never delegates a decision to a builder and never rubber-stamps a builder's diff.
- Builders (Opus-class subagents,
model: "opus", one per context). Each receives a tight brief (direction specs + acceptance criteria + the context's file_paths scope + repo-convention digest) and implements in its own worktree. Builders return a structured report; when they hit a genuine product ambiguity they return the question instead of guessing — the Director answers via SendMessage and the builder continues.
- Scouts (Explore subagents, cheap). Produce the per-context current-state brief the Director synthesizes directions from. Never used for judgment.
The Obsidian vault — durable loop state
Resolve the vault root (first hit wins), then use $VAULT/Perfect/:
VAULT="C:/Users/kazda/Documents/Obsidian/personas"
Perfect/
Perfect.md # HOME / Map-of-Content — always reflects current truth:
# mission, the scored context QUEUE with the CURSOR,
# the ACCEPTED POOL (n/10), shipped ledger headline, link to last session
config.md # per-repo overlay: gates to run, worktree recipe, wave size,
# direction sizing rules, cooldown, + ## Skill improvement log
contexts/<name>.md # one per context-map context (long-lived, updated in place)
directions/<slug>.md # one per direction (long-lived; the atom of the whole loop)
sessions/<YYYY-MM-DD[-n]>.md # immutable run records, each ends with a `next:` pointer
Context note (contexts/<name>.md):
---
name: <context-map name> type: perfect/context
group: <group> category: ui|api|lib|data|config
opportunity: <0-10> # value reach × headroom × strategic fit (Director's judgment)
last_proposed: <YYYY-MM-DD|never> cooldown_until: <date|—>
directions: ["[[<slug>]]", …]
---
## Current state (scout brief digest + file:line evidence — refreshed each proposal pass)
## Direction history (proposed / accepted / REJECTED-and-why — rejections are memory too)
## Shipped (direction → commit SHA → observed effect)
Direction note (directions/<slug>.md):
---
slug: <kebab, stable> type: perfect/direction
context: "[[<context-name>]]" lens: feature|ux|optimization|robustness|wildcard
status: proposed | accepted | building | shipped | failed | dropped | rejected
size: S|M|L # must fit ONE builder session (≲15 files, no cross-context schema break)
proposed: <date> accepted: <date|—> shipped: <date|—> commit: <sha|—>
---
## What & why (the user value, one paragraph, no fluff)
## Evidence (file:line of the gap/opportunity in today's code)
## Acceptance criteria (3-6 checkable bullets — the builder's contract AND the review checklist)
## Risks / non-goals
## Build record (builder report digest, review verdict, gate results — filled during build)
Session note: phases run, contexts covered, accept/reject tallies, build outcomes with SHAs, deltas, and next: <the exact resumption instruction for the following session>.
Vault hygiene: slugs are stable; update notes, never duplicate. Subagents may fail to write files in some harnesses — after any parallel phase the Director MUST ls the target dir and backfill missing notes from the agents' returned content before trusting "written".
The loop — a vault-driven state machine
Every invocation starts the same way; the vault decides which phase runs.
Phase 0 — Recall & register
- Read
Perfect.md (+ last session's next: pointer). If missing → run init (below).
- Read
context-map.json; diff against contexts/* — new contexts get notes + a queue slot, removed ones get archived (status: retired in frontmatter).
- Repo rituals: read
.claude/active-runs.md, surface overlaps, append this session's entry. Scan MEMORY.md signals that veto directions (e.g. "Langfuse REMOVED — don't re-suggest").
- Announce the resumption point in one sentence, then go where the state machine points: pool < 10 → Propose; pool ≥ 10 (or user said
build) → Build.
Init (first run only)
- Scaffold the vault tree +
config.md (record: gates = npm run check, npm run test -- --run, check:i18n:strict when locales touched, cargo clippy/check + cargo test --lib --features desktop when Rust touched; wave size = 3; cooldown = 2 rounds).
- Score every context 0-10 for opportunity = user-facing reach × headroom (distance from "perfect", judged from context-map metadata,
docs/features/*, and memory) × strategic fit (active arcs in memory). Write the ranked queue into Perfect.md with the cursor at the top. Don't deep-read code yet — scoring is refined per-context at proposal time.
- Write session note; proceed straight into Propose.
Phase P — Propose (context by context, until the pool holds 10)
Loop while pool < 10 and the user hasn't said stop:
-
Cursor = highest-opportunity context not on cooldown. Prefetch: before presenting context k, launch the scout for context k+1 in the background.
-
Scout (Explore, "very thorough", read-only): given the context's file_paths, entry_points, db_tables → return a current-state brief: what exists, what's rough, dead ends, UX seams, perf smells, with file:line evidence. A component only "exists" if it RENDERS — trace every surface the brief describes to an actual mount point (round 3's smoke pass caught a strip that scout + two builders treated as live while it had zero consumers).
-
Draft 5 directions — one per lens by default: feature (new user value), ux (design/flow elevation), optimization (perf/cost/significant simplification), robustness (failure modes, observability, architecture), wildcard (the non-obvious idea a great PM would pitch). Each sized to ONE builder session; a bigger vision ships as its phase-1 slice.
Weight the slate by config.md → ## User taste — the lens spread is a starting point, not a quota. Learned taste through round 8: the user accepts outcome-value work (features/optimizations with a visible user payoff) and rejects cosmetic churn (e.g. dark-mode remount tweaks). Pre-filter the 5 through that lens and say in the presentation that you did. Default depth is the engine, not the chrome: for any context with backend/algorithmic substance, most directions should be architecture-level (data model, algorithms, lifecycle, prompt/recall paths, cost structure); UI surfacing appears at most once-twice unless the user steers otherwise. Scout prompts must match this depth (trace the full pipeline, not just the components).
-
Challenge before presenting (the Director argues against itself; a direction that fails any check is replaced, not presented):
- Does it already exist in code? (scout evidence, not assumption)
- Was it already proposed/rejected/shipped? (check
contexts/<name>.md history + memory)
- Does it conflict with an active arc or a "removed, don't re-suggest" memory?
- Is the value claim concrete — can I name the user moment it improves?
- Can one builder session genuinely ship it behind the acceptance criteria?
Director self-check before the gate — a proposal that fails any of these never reaches the user:
- Names the concrete files it will touch (from scout evidence, not guessed).
- Names the user-visible outcome in one sentence a non-developer would care about.
- States why it beats the next-best alternative direction for this context.
- Survives the taste filter above (outcome-value, not cosmetic churn).
-
Present the 5 in chat — numbered, each: title · lens · size · one-paragraph why · evidence · acceptance criteria. Then gate with AskUserQuestion (multiSelect) — the tool caps options at 4 per question, so use TWO questions in one call: Q1 = directions 1–3, Q2 = directions 4–5 (labels = N · short title, description = one-line value claim + size). The user can annotate via "Other" (e.g. edit 2: …, stop); selecting nothing in both = none accepted.
-
Record outcomes in the vault (rejected ones too, with the user's implied reason — rejections steer future proposals). Accepted → directions/<slug>.md with status: accepted, pool counter++, context gets cooldown_until. Update Perfect.md after every context, not at session end — a killed session must lose nothing.
-
A none gate that carries a steer (the user says what they wanted instead) is a re-scout order, not a rejection of the context: promote the steer to config.md → ## User taste if it generalizes, re-scout at the steered depth/angle, and re-propose the SAME context once before advancing the cursor. Never re-present any rejected direction.
Phase B — Build (one Opus-class builder per context, the Director decides everything)
- Wave plan: group the pool's accepted directions by context → one builder per context, ≤
config.wave_size (default 3) concurrent, and ≤ 3 directions per builder brief (a 4-direction brief exceeded one agent-session budget in round 1 — split a bigger context into two sequential builders). Present the wave plan in one screen; on user go (or when invoked as /perfect build), execute.
- Worktree per builder — prepared by the Director, NOT via Agent-tool isolation (those worktrees lack
node_modules):
git worktree add .claude/worktrees/perfect-<ctx> -b worktree-perfect-<ctx>
cmd //c mklink //J ".claude\\worktrees\\perfect-<ctx>\\node_modules" "..\\..\\..\\node_modules"
- Brief each builder (see template below); launch with
model: "opus", subagent_type: "general-purpose", all briefs in one message so they run concurrently. Brief quality bar: every brief lists the exact repo gates the builder must pass before reporting done — npx tsc --noEmit, npm run lint (no new warnings in touched files), targeted vitest, npm run check:i18n:strict if any string/locale touched, cargo test export_bindings + commit src/lib/bindings/ if any Rust struct touched. Director review time is for judgment, not gate failures.
- Mid-flight decisions: a builder returning
DECISION NEEDED: … gets an answer from the Director via SendMessage — product calls, trade-offs, and scope cuts are the Director's alone. A builder that stops without its final report gets one SendMessage nudge.
Builder-death recovery (learned round 1 — session limits WILL kill builders): the instant a builder dies, git add -A && git commit --no-verify a wip(…) snapshot inside its worktree (isolated tree — add-all is safe there; never-lose-work beats commit hygiene). Then the Director either finishes the work inline (review the WIP diff, complete gaps, split into per-direction commits along file boundaries — same-file hunks may share a commit if the message says so) or re-briefs a fresh builder after the limit resets with "continue from the WIP commit".
- Review — the Director earns its title here. Per builder branch:
git diff master...worktree-perfect-<ctx> and review against each direction's acceptance criteria, repo conventions (shared-component catalog, design tokens, i18n keys, invokeWithTimeout, error registry), and taste. Verdict per direction: merge / redo with notes (SendMessage, builder fixes in place) / drop (status: failed, reason recorded). Never merge on "tests pass" alone — read the diff.
Docs-vs-code check (learned round 1): when a diff documents a behavior (contract text, formula, doc comment), grep for the code that implements it before merging — one builder shipped a beautifully-documented decay formula with the implementing SQL never written. A contract describing behavior the code doesn't have is worse than nothing.
Rust gate calibration: gate on no NEW warnings in files this diff touched (clippy full-crate -D warnings fails on hundreds of pre-existing warnings in this repo — compare against master's warnings for the same files before blaming the diff).
- Merge serially: per direction,
git merge --squash (or cherry-pick) → ONE atomic commit on master, message feat(<context>): <direction title> + Co-Authored-By footer. Stage per-file, verify git diff --cached --stat matches intent (foreign pre-staged files → git restore --staged them). Run the config gates on master after each merge; a red gate is fixed inline before the next merge.
Concurrent-master locale conflicts (learned round 1): when another session moves the locale files under a pending cherry-pick, don't hand-merge JSON — re-apply the branch's key adds/removes programmatically over master's current locale files (flatten base vs branch per locale, set/delete on current, write), then regenerate gen-types.mjs + split-locales.mjs and git add the artifacts before cherry-pick --continue. Round 1's script: session scratchpad merge-locale-keys.mjs — recreate it from this recipe.
Union-merge discipline (learned round 4 the hard way): both-append cherry-pick conflicts are USUALLY safe to keep-both — but only when each side is a complete declaration. NEVER blind-union hunks whose sides end mid-function (a glued test-fn and a swallowed closing brace turned master red for two picks). Read every seam; and read the gate's output BEFORE the next state-changing action — cherry-pick --continue AND git commit both count (round 5 repeated round 4's mistake in miniature: an integration fix was committed while its test run sat unread showing 3 failures). A departing builder that flags a master regression in its final report is gold — treat those flags as gate input, not noise.
Concurrent-session DIRTY files blocking a pick (learned round 2): never stash, never wait — commit around them. (a) Dirty en.json: stage HEAD + your keys directly into the index (git hash-object -w + git update-index --cacheinfo), and write their-working-copy + your keys to disk — their uncommitted work stays theirs, and their later commit can't revert your keys. (b) Dirty Rust/source file: same index trick, content built by git merge-file (base=branch-fork, ours=HEAD, theirs=branch), plus a second merge-file for the working copy. (c) Shared append-files (lib.rs command registrations, commandNames.generated.ts, generated i18n): NEVER wholesale-checkout a branch's version across sequential picks — it clobbers earlier picks' registrations (tsc catches it too late). Patch-union (git diff branch~..branch -- file | git apply --3way) or regenerate from source, always.
6b. Cross-builder integration gate (learned round 3): parallel builders each verify against the master they forked from — their work can be mutually incompatible (one retired a type-union member another targeted; one restructured a component another wrote tests against). After ALL of a wave's picks land, run tsc + the union of the wave's test suites on master BEFORE wrap; treat failures as Director-fixed integration commits, not builder redos. When two builders share a direction dependency, fork the dependent builder's worktree AFTER the dependency merges (sequenced builder) — it worked cleanly in round 3.
- Doc-sync in the same turn: user-visible changes update the mapped
docs/features/* (+ onboarding flow / marketing module if mapped) — the Stop hook will demand it anyway.
- Cleanup: per worktree —
cmd //c rmdir the node_modules junction FIRST, then git worktree remove, then delete the branch once its commits are on master.
Phase W — Wrap (every session, even interrupted ones)
- Update every touched vault note; write the session note with the
next: pointer (e.g. next: propose — cursor at overview-analytics, pool 7/10 or next: build wave 2 — trigger-system + agent-lab remain).
Perfect.md headline refreshed: pool count, queue cursor, shipped-total, last-session link.
- Move the active-runs ledger entry to Recently completed with SHAs.
- Reflect on the skill itself: 2-4 bullets in
config.md → ## Skill improvement log — what dragged, what the user overrode, what the next round should change. This log is the input for the between-rounds skill revision.
Direction quality bar (what earns a slot in the 5)
- Value-first: names the user moment it improves; "nice refactor" is not a direction unless it unlocks something.
- Evidence-backed: cites today's code (
file:line), not vibes.
- One-session-shippable: ≲15 files, no cross-context schema breaks; else slice it.
- Novel to the vault: not shipped, not pending, not previously rejected (unless the world changed — say so).
- Lens-diverse: default one per lens; substituting a second entry in one lens requires the Director to say why.
Builder brief template
You are an Opus-class builder for the `<context>` context of the Personas desktop app
(Tauri 2 + React 19 + TS + Tailwind 4 + Zustand 5; local-first SQLite).
Work ONLY in this worktree: <abs path>. Your scope is this context's files:
<file_paths from context-map.json>. Touching other contexts requires DECISION NEEDED.
Implement these accepted directions, one atomic commit each, message `feat(<context>): <title>`:
<per direction: What & why · Acceptance criteria · Evidence file:line · Risks/non-goals>
COMMIT EACH DIRECTION THE MOMENT IT IS DONE AND VERIFIED — never batch commits
for the end of the session. An interrupted session must lose at most the
direction in progress, not everything.
FOREGROUND ONLY — this means the tool mechanics: NEVER set run_in_background
on a shell command, never spawn "waiter" scripts, never end your turn with
"the notification will tell me" (it won't — you will idle until the Director
nudges you; this has burned 5+ nudges across waves). Run every compile/test as
ONE blocking foreground command; shared-cargo-target lock waits are normal.
SEARCH BEFORE BUILDING: before implementing any new mechanism, grep for an
existing implementation of the same concept and LAYER ON it rather than
forking a parallel system (round 3's history builder found a load-bearing
back-only nav history this way — unifying beat replacing).
NO INTERACTIVE GIT: `git add -p`, `git add -i`, `git rebase -i` HANG this
harness (a round-5 builder stalled 600s on add -p). When directions interleave
in shared files, commit by FILE boundaries and document the shared commit —
never hunk-split interactively.
Repo law (non-negotiable):
- Read .claude/CLAUDE.md § Styling before any UI; reuse shared/components (CATALOG.md) — never hand-roll
spinners/modals/tooltips/buttons; semantic tokens only (typo-*, rounded-*, shadow-elevation-*).
- Every user-facing string: add key to src/i18n/locales/en.json AND translate into all 13 other
locales yourself via scripts/i18n/translate-extract.mjs → fill .i18n-work/missing-<code>.json
(medium quality fine) → translate-merge.mjs. The pre-commit hook blocks gaps.
- IPC via invokeWithTimeout; errors via toastCatch/silentCatch + error registry; components < 200 LOC.
- New Rust types with ts-rs: run `cargo test export_bindings` and commit src/lib/bindings/ changes.
- GATES you must pass before reporting done: npx tsc --noEmit · npm run lint (no new warnings in
files you touched) · targeted vitest · npm run check:i18n:strict if you touched strings/locales ·
cargo test export_bindings (+ commit src/lib/bindings/) if you touched Rust structs. Then drive
the actual flow when a dev server is available; report what you COULD NOT verify honestly.
If a product decision is ambiguous, STOP that direction and return `DECISION NEEDED: <question>`
with your recommendation — never guess. Final report format:
per direction → status (done|blocked|decision-needed), commits, files, verification evidence, open risks.
Modes
/perfect — resume the loop wherever the vault says it stopped (the default; covers init on first run).
/perfect propose [context] — force a proposal pass (optionally jump the cursor to a named context).
/perfect build — build now with the current pool even if < 10.
/perfect status — read-only: queue, cursor, pool, in-flight builds, shipped ledger, last session. No agents.
/perfect smoke — live L2 verification pass over recent waves' shipped surfaces: drive the USER'S running instance via the :17320 bridge (verify a new-code marker first — never trust a stale port), read-mostly navigation, and use read-only sqlite3 queries against the live DB (sqlite3 "file:<path>?mode=ro") as the primary diagnostic — one GROUP BY beats an hour of DOM archaeology. Record verified/not-driven/fixes in a sessions/<date>-smoke note; small fixes commit inline (gates BEFORE commit). Run after every ~2 waves; state-dependent surfaces that keep rolling over go to a fresh-DB harness session instead.
/perfect reflect — read config.md → Skill improvement log + last sessions and propose concrete edits to THIS skill file.
Guardrails
- Never stash, never
git add -A — per-file staging, staged-count check before every commit; other sessions' work is sacred (parallel-safety primitives in CLAUDE.md apply in full).
- Cost discipline: scouts are Explore-tier; builder-tier model spend goes only to accepted work; the Director never re-runs a scout whose brief is < 1 round old (it's in the context note).
- Honest ledger: a direction only reaches
shipped with gates green AND the Director having read the diff; anything else is failed with a reason. No silent drops — every accepted direction's fate is recorded.
- Interruptibility is a feature: write the vault incrementally (after every context in P, after every merge in B) so a killed session resumes losslessly.
- The user is the product owner: the gate is theirs; the Director challenges but never overrides a rejection, and repeated rejections of a lens/context recalibrate the queue scores.
App context coverage (Personas-managed repos)
This skill declares contexts: tracked — the Personas app measures per-context memory coverage for it. When run inside a Personas-managed repo (a .personas/ dir exists, or the app dispatched this run), before finishing append JSON lines to .personas/memory-outbox.jsonl at the repo root (append, never rewrite) — one node per context you meaningfully worked on:
{"type":"node","kind":"progress","title":"<=200 chars: what you did in this context","body":"optional detail","context":"<exact context name from context-map.json>","skill":"perfect"}
Always set both "skill":"perfect" and "context":"<name>" — together they drive the per-skill context-coverage % (last 30 days). The app ingests and deletes the file when the session ends. Skip silently when not Personas-managed.