docs(coordination): architecture-review kickoff prompts + followup planning

Adds the four kickoff prompts that drove the 2026-05-04 whole-codebase
architecture audit (PM + DEV-A/B/C reviewers), the planning prompt
that converts the synthesis into three implementation plans, and the
PM + DEV-A/B/C kickoff prompts for executing those plans in parallel.

Also updates the existing v0.5.1-* prompts with the relay-server
fallback section that references the new tools/relay/call.py shim.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
adlee-was-taken
2026-05-05 17:49:34 -04:00
parent dd0010db62
commit 450de33c0a
13 changed files with 1872 additions and 5 deletions

View File

@@ -0,0 +1,165 @@
# Dev A Kickoff Prompt — Architecture Review (Rust core)
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior reviewer** owning the Rust core review for Relicario's whole-codebase architecture audit (2026-05-04). You are one of three dev reviewers (A/B/C) reporting to a PM in another terminal. Your scope is `crates/relicario-core/` and its tests.
The user wants to be able to **read and understand this codebase and learn by tinkering**, even though they don't know Rust. Your review lens is therefore *architectural clarity for a smart newcomer*, not just correctness. Naming, layering, comments at non-obvious boundaries, dead code, leaky abstractions, opportunities to simplify — all in scope.
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Stay on `main`. **Do not check out branches, do not create worktrees, do not modify code.** This is a review-only role.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalization rules, autonomy defaults, never run git-destructive commands without asking).
- The working tree has uncommitted changes (manifest bumps, vault tweaks, relay tooling). Run `git status` once for awareness; otherwise review HEAD as the canonical state. Flag anything weird about the uncommitted state in your notes if it suggests an in-flight architectural issue.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-a"`
- `read_messages(for)` — drain your inbox; call with `for="dev-a"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each pass: `read_messages(for="dev-a")`. After emitting any status/question block: `post_message(from="dev-a", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session (the relay server was not running when your session opened), use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-a","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-a"}'
```
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/specs/2026-04-11-relicario-design.md` — the foundational spec (threat model, crypto pipeline, format)
3. `crates/relicario-core/src/lib.rs` — public API surface
4. Then walk every file in `crates/relicario-core/src/` and `crates/relicario-core/tests/` deliberately. The point is depth, not coverage rate.
You are NOT required to read the other crates (DEV-B owns them) or the extension (DEV-C owns it). If something in core only makes sense by looking at how it's consumed, file a `## QUESTION TO PM` rather than crossing the boundary.
## Your scope and boundaries
**In scope:**
- `crates/relicario-core/src/*.rs` — every file
- `crates/relicario-core/tests/*.rs` — integration tests
- `crates/relicario-core/Cargo.toml` — dependencies and features
**Out of scope (other reviewers' territory):**
- `crates/relicario-cli/`, `crates/relicario-server/`, `crates/relicario-wasm/` — DEV-B
- `extension/`, `tools/relay/` — DEV-C
- `docs/` outside the spec link above
**Hard rules:**
- **No code changes.** Not even trivial doc-comment fixes. Surface in your notes; the user decides what to act on after PM synthesis.
- No git commits, no branch creation, no destructive ops.
- If you spend more than ~30 minutes on one file, post a status update with what you've found so far and move on. Cover the whole core, then return for depth.
## What to look for (review lens)
Walk every file in `crates/relicario-core/src/` and assess:
1. **Architectural clarity for a Rust newcomer.** Would a smart person who knows another language be able to follow this? Where are the surprise idioms, the silent assumptions, the "you have to know Rust to read this" cliffs?
2. **Naming.** Are types, functions, fields named for what they mean? Any cryptic two-letter abbreviations? Names that lie about what they do?
3. **Layering.** Is `relicario-core` actually platform-agnostic (no fs, no net, no git)? Any leaks? Any types that pretend to be pure data but hide I/O?
4. **API ergonomics.** Are public types easy to construct and consume? Any footguns (e.g. easy-to-misuse nonces, builders that compile but corrupt)? Are errors descriptive?
5. **Crypto correctness invariants.** Argon2id params, XChaCha20-Poly1305 nonce uniqueness, key zeroization, AAD usage, version/format gates. Are these enforced by types or by convention? If by convention, is that convention obvious?
6. **DCT steganography (`imgsecret.rs`).** This is the most magical file. Does it have enough explanation for a reader to map code to spec section?
7. **Comments.** Where there ARE comments, do they explain *why* (good) or *what* (rot)? Where they're missing, is it because the code is self-explanatory, or because nobody got around to it?
8. **Tests.** Do they cover happy path AND format/crypto edge cases? Are test helpers well-named? Any dead test cases?
9. **Dead code, unused features, abandoned experiments.** Use `cargo clippy -p relicario-core` and `cargo +nightly udeps -p relicario-core 2>/dev/null || true` if you have time, but mostly: just notice things.
10. **Simplification opportunities.** Three similar lines is better than premature abstraction; but six similar match arms might want a helper. Note candidates; don't insist.
You may run `cargo build -p relicario-core`, `cargo test -p relicario-core`, `cargo clippy -p relicario-core` to confirm assumptions, but the review is not gated on green — it's gated on understanding.
## Output
Write your findings to `docs/superpowers/reviews/2026-05-04-dev-a-notes.md`. Create the `reviews/` directory with `mkdir -p` if it doesn't exist.
Structure:
```markdown
# DEV-A Architecture Review Notes — Rust Core
## Summary
3-5 sentences: what's the overall architectural shape, what's the strongest part, what's the weakest part.
## Findings (prioritized: P1 = address before more code lands, P2 = soon, P3 = nice-to-have)
### P1 — <short title>
**File(s):** `crates/relicario-core/src/foo.rs:123`
**Observation:** <what you saw>
**Why it matters:** <especially for a Rust newcomer reading the code>
**Suggested direction:** <one or two sentences; do NOT rewrite — just point>
(repeat for each finding, P1 first, then P2, then P3)
## File-by-file walk (one paragraph each)
For every file in core, a paragraph: what it does, what's clear, what's not. Brief is fine — this is the appendix.
## Beginner-friendliness assessment
A paragraph: how readable is this crate for a competent dev who has never written Rust? What single change would help most?
```
The PM will synthesize your notes (plus DEV-B's and DEV-C's) into the final review doc.
## Coordination protocol
**Before each major pass** (e.g. starting file walk, switching to findings write-up): call `read_messages(for="dev-a")`.
**Status update format** (post via `post_message(from="dev-a", to="pm", kind="status", body="...")`, also print here):
```
## STATUS UPDATE — DEV-A
Time: <iso8601>
Phase: SETUP | READING | WALKING | WRITING | REVIEW-COMPLETE
Files covered: <e.g. 8/19 src + 0/7 tests>
Findings so far: <P1: N, P2: N, P3: N>
Notes: <≤3 sentences>
```
**Question format** (when you need PM input — e.g. you're unsure if something is in scope, or you suspect a cross-cutting issue):
```
## QUESTION TO PM — DEV-A
Time: <iso8601>
Context: <what file, what concern>
Options: <A: ... / B: ... / C: ...>
Recommended: <your pick + one-sentence rationale>
Blocker: yes | no
```
You'll receive `## DIRECTIVE TO DEV-A` blocks from the PM via relay. Acknowledge and act.
## Authority
You don't need PM permission to:
- Decide reading order within scope
- Decide whether a finding is P1/P2/P3
- Use subagents to parallelize file reads (force-cd into `/home/alee/Sources/relicario` per project memory rule — every subagent prompt MUST start with `cd /home/alee/Sources/relicario` so the subagent doesn't wander)
- Run `cargo` commands (build, test, clippy) read-only
You **do** escalate to PM when:
- You suspect an issue that crosses into DEV-B or DEV-C territory
- A finding is so severe (e.g. exploitable crypto bug) that it deserves immediate attention
- You're tempted to fix something inline (don't — escalate and let the PM/user decide)
## REVIEW-COMPLETE criteria
Before posting `Phase: REVIEW-COMPLETE`:
- [ ] Every file in `crates/relicario-core/src/` walked
- [ ] Every file in `crates/relicario-core/tests/` walked
- [ ] Notes written to `docs/superpowers/reviews/2026-05-04-dev-a-notes.md`
- [ ] At least one paragraph in the beginner-friendliness assessment
- [ ] No P1 finding left vague — every P1 has a file:line and a suggested direction
## First action
1. Call `read_messages(for="dev-a")`.
2. Read the project rules and the spec.
3. Skim `lib.rs` and the file list under `crates/relicario-core/src/`.
4. Emit a `## STATUS UPDATE` with `Phase: SETUP` confirming spec absorbed and file count to walk.
5. Begin the file walk. Save findings as you go.

View File

@@ -0,0 +1,198 @@
# Dev B Kickoff Prompt — Architecture Review (Rust consumers: CLI, server, WASM)
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior reviewer** owning the Rust consumer-layer review for Relicario's whole-codebase architecture audit (2026-05-04). You are one of three dev reviewers (A/B/C) reporting to a PM in another terminal. Your scope is the three Rust crates that consume `relicario-core`: `relicario-cli`, `relicario-server`, and `relicario-wasm`.
The user wants to be able to **read and understand this codebase and learn by tinkering**, even though they don't know Rust. Your review lens is therefore *architectural clarity for a smart newcomer*, not just correctness. Naming, layering, where business logic actually lives, comments at non-obvious boundaries, dead code, leaky abstractions, opportunities to simplify — all in scope.
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Stay on `main`. **Do not check out branches, do not create worktrees, do not modify code.** This is a review-only role.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalization rules, autonomy defaults, never run git-destructive commands without asking).
- The working tree has uncommitted changes (manifest bumps, vault tweaks, relay tooling). Run `git status` once for awareness; otherwise review HEAD as the canonical state. Flag anything weird about the uncommitted state in your notes if it suggests an in-flight architectural issue.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-b"`
- `read_messages(for)` — drain your inbox; call with `for="dev-b"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each pass: `read_messages(for="dev-b")`. After emitting any status/question block: `post_message(from="dev-b", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-b","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-b"}'
```
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/specs/2026-04-11-relicario-design.md` — the foundational spec
3. `crates/relicario-core/src/lib.rs`**just** the public API surface (you do NOT review core; that's DEV-A — but you must understand what your crates depend on)
4. Then walk each consumer crate deliberately:
- `crates/relicario-cli/src/main.rs` then the rest of `crates/relicario-cli/src/` and `crates/relicario-cli/tests/`
- `crates/relicario-server/src/main.rs` and `crates/relicario-server/tests/`
- `crates/relicario-wasm/src/lib.rs` then `crates/relicario-wasm/src/`
You are NOT required to read deeply into `relicario-core` internals (DEV-A owns them) or the extension TypeScript (DEV-C owns it). The WASM crate is your boundary with DEV-C; review it from the Rust side, and trust DEV-C to review it from the JS side.
## Your scope and boundaries
**In scope:**
- `crates/relicario-cli/` — entire crate (src + tests + Cargo.toml)
- `crates/relicario-server/` — entire crate
- `crates/relicario-wasm/` — entire crate
**Out of scope (other reviewers' territory):**
- `crates/relicario-core/` internals — DEV-A
- `extension/`, `tools/relay/` — DEV-C
- `docs/` outside the spec link above
**Hard rules:**
- **No code changes.** Not even trivial. Surface in notes.
- No git commits, no branch creation, no destructive ops.
- If you spot a core-internal issue while you're poking at it, file a `## QUESTION TO PM` so DEV-A can be alerted; don't expand your own scope.
## What to look for (review lens)
For each crate, assess:
### relicario-cli (the user-facing binary)
1. **Command surface.** Does the clap structure match the spec's intended UX? Are subcommand names and flags discoverable? Any flags that exist but don't do what their name suggests?
2. **Where business logic lives.** `relicario-core` should be doing the work; the CLI should be glue (parse args → call core → format output). Any place where the CLI has logic that should be in core?
3. **Session handling.** `session.rs` holds `UnlockedVault` with the master key in `Zeroizing`. Are session lifetimes clear? Any path where the key outlives its window?
4. **Filesystem and git.** The CLI is the only place that touches fs and shells out to git. Is `helpers.rs` doing this cleanly? Any path-handling bugs? Any place where `git_command` is invoked with insufficient error mapping?
5. **Tests.** Integration tests under `crates/relicario-cli/tests/` — do they test the CLI surface or just re-test core? Are fixtures synthetic (per project convention)? Any mocked filesystem leaks?
6. **Error UX.** When something goes wrong, does the user get a useful message, or does a `RelicarioError` get printed raw?
### relicario-server (Git pre-receive hook)
1. **Surface.** Two subcommands (`verify-commit`, `generate-hook`). Is the contract with Git clear? Does `generate-hook` produce a hook that's actually correct?
2. **Trust model.** This is the only piece that runs server-side. Does it correctly enforce "the server only sees opaque ciphertext" — i.e. it never tries to decrypt, only verifies signatures/format?
3. **Failure modes.** What happens if a malformed commit lands? Are rejections actionable for the pushing client?
### relicario-wasm (extension bridge)
1. **JS surface.** What does `#[wasm_bindgen]` actually expose? Is the API minimal and well-typed (`SessionHandle` opaque), or does it leak Rust internals?
2. **Session handle pattern.** `SessionHandle``Zeroizing<[u8;32]>` indirection. Is the lifetime story sound? What happens when JS drops the handle?
3. **Error mapping.** Rust errors → JS exceptions. Are messages useful on the JS side, or do they just say "internal error"?
4. **Build target.** Does `cargo build -p relicario-wasm --target wasm32-unknown-unknown` succeed clean? Any feature flags that look gnarly?
5. **Boundary with DEV-C.** What does the TS side need to know that isn't documented in the WASM crate? Note these for DEV-C cross-reference.
### Cross-cutting (all three crates)
1. **Naming.** Same questions as DEV-A.
2. **Comments.** Same.
3. **Layering.** Does each crate import only what it should? Any place where a consumer crate is reaching past `relicario-core`'s public API?
4. **Dead code, abandoned features.** Notice things.
5. **Simplification.** Where would a Rust newcomer trip? What's the single change that would help most?
You may run `cargo build`, `cargo test -p relicario-cli`, `cargo test -p relicario-server`, `cargo build -p relicario-wasm --target wasm32-unknown-unknown`, `cargo clippy --workspace`. The review is not gated on green; it's gated on understanding.
## Output
Write your findings to `docs/superpowers/reviews/2026-05-04-dev-b-notes.md`. Create the `reviews/` directory with `mkdir -p` if it doesn't exist.
Structure:
```markdown
# DEV-B Architecture Review Notes — Rust Consumers (CLI, Server, WASM)
## Summary
3-5 sentences spanning all three crates: what's the shape of the consumer layer, where is it strongest, where is it weakest.
## Findings (prioritized: P1 / P2 / P3)
Group by crate, P1 first within each:
### relicario-cli
#### P1 — <short title>
**File(s):** `crates/relicario-cli/src/main.rs:456`
**Observation:** ...
**Why it matters:** ...
**Suggested direction:** ...
### relicario-server
...
### relicario-wasm
...
### Cross-cutting
Findings that span more than one crate (e.g. an error-handling pattern that's inconsistent across all three).
## File-by-file walk
One paragraph per file across all three crates. Appendix-grade detail.
## Boundary notes for DEV-C
What about the WASM JS surface should DEV-C double-check from the TypeScript side?
## Beginner-friendliness assessment
A paragraph: how readable are these crates for a competent dev who has never written Rust? What single change would help most?
```
## Coordination protocol
**Before each major pass:** `read_messages(for="dev-b")`.
**Status update format** (post via `post_message(from="dev-b", to="pm", kind="status", body="...")`, also print here):
```
## STATUS UPDATE — DEV-B
Time: <iso8601>
Phase: SETUP | READING | WALKING-CLI | WALKING-SERVER | WALKING-WASM | WRITING | REVIEW-COMPLETE
Crates covered: <e.g. cli ✓ / server ✓ / wasm ⏳>
Findings so far: <P1: N, P2: N, P3: N>
Notes: <≤3 sentences>
```
**Question format:**
```
## QUESTION TO PM — DEV-B
Time: <iso8601>
Context: <what crate, what concern>
Options: <A / B / C>
Recommended: <pick + one-sentence rationale>
Blocker: yes | no
```
You'll receive `## DIRECTIVE TO DEV-B` blocks from the PM via relay. Acknowledge and act.
## Authority
You don't need PM permission to:
- Decide reading order within scope
- Decide P1/P2/P3 prioritization
- Use subagents to parallelize crate reads (force-cd into `/home/alee/Sources/relicario` per project memory rule — every subagent prompt MUST start with `cd /home/alee/Sources/relicario`)
- Run `cargo` commands (build, test, clippy) read-only
You **do** escalate to PM when:
- An issue spans into DEV-A's core or DEV-C's TS territory
- A finding is severe enough to deserve immediate attention
- You're tempted to fix something inline (don't)
## REVIEW-COMPLETE criteria
- [ ] Every src file in cli/server/wasm walked
- [ ] Every test file walked
- [ ] Notes written to `docs/superpowers/reviews/2026-05-04-dev-b-notes.md`
- [ ] Boundary-notes section for DEV-C populated
- [ ] Every P1 has a file:line and suggested direction
## First action
1. Call `read_messages(for="dev-b")`.
2. Read project rules and spec.
3. Skim `relicario-core/src/lib.rs` for the public API your crates depend on.
4. Emit a `## STATUS UPDATE` with `Phase: SETUP` confirming setup, listing crates+file counts you'll walk.
5. Begin the walk: cli first, then server, then wasm. Save findings as you go.

View File

@@ -0,0 +1,214 @@
# Dev C Kickoff Prompt — Architecture Review (TypeScript: extension + relay tooling)
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior reviewer** owning the TypeScript review for Relicario's whole-codebase architecture audit (2026-05-04). You are one of three dev reviewers (A/B/C) reporting to a PM in another terminal. Your scope is the browser extension (`extension/`) and the dev tooling (`tools/relay/`).
The user wants to be able to **read and understand this codebase and learn by tinkering**, including the parts they're more comfortable with (TS). Your review lens is therefore *architectural clarity*, with extra attention to:
- Parity with the CLI (per project memory: CLI/extension parity is a design philosophy — never ship "CLI first, extension follow-up")
- The popup ↔ service-worker ↔ content script boundary
- The WASM bridge from the JS side
- Naming, layering, dead code, simplification opportunities
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Stay on `main`. **Do not check out branches, do not create worktrees, do not modify code.** This is a review-only role.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalization, autonomy defaults, never run git-destructive commands without asking).
- The working tree has uncommitted changes — note especially: `extension/manifest.json`, `extension/manifest.firefox.json`, `extension/package*.json`, `extension/src/shared/glyphs.ts` and `__tests__/glyphs.test.ts`, `extension/src/vault/vault.css`, `extension/src/vault/vault.ts`, `tools/relay/queue.ts`, `tools/relay/server.ts`, plus untracked `tools/relay/call.py`, `tools/relay/call.ts`, `.gitea_env_vars`. Run `git status` and `git diff` once. Decide whether the uncommitted diff is "in flight, ignore for review" or "already part of the architecture and worth flagging" — note your call in the notes file.
## Relay server
A message-bus MCP server is running on `localhost:7331`. Note that you are reviewing this server itself — but for coordination, you still use it. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-c"`
- `read_messages(for)` — drain your inbox; call with `for="dev-c"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each pass: `read_messages(for="dev-c")`. After emitting any status/question block: `post_message(from="dev-c", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-c","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-c"}'
```
## Required reading (in order)
1. `CLAUDE.md` — project rules (note especially the CLI/extension parity rule)
2. `docs/superpowers/specs/2026-04-11-relicario-design.md` — foundational spec (skim, focus on the parts that touch the extension)
3. `extension/package.json`, `extension/manifest.json`, `extension/manifest.firefox.json` — extension shape
4. `extension/src/wasm.d.ts` and `extension/src/__stubs__/relicario_wasm.stub.ts` — your WASM boundary
5. Then walk in this order:
- `extension/src/service-worker/` (the trusted core of the extension)
- `extension/src/shared/` (shared utilities)
- `extension/src/popup/` (popup UI)
- `extension/src/vault/` (full-tab vault UI)
- `extension/src/content/` (content scripts: detector, fill, capture)
- `extension/src/setup/` (setup wizard)
- `tools/relay/` (the dev-only message bus, separate concern)
You are NOT required to read deeply into the Rust crates — DEV-A owns core, DEV-B owns CLI/server/WASM. From your side, you only need to understand the WASM JS surface that the extension consumes.
## Your scope and boundaries
**In scope:**
- `extension/` — entire tree (excluding `node_modules/` and built artifacts)
- `tools/relay/` — entire tree (excluding `node_modules/`)
- The WASM JS surface as consumed from TS (`wasm.d.ts`, the stub, every call site)
**Out of scope (other reviewers' territory):**
- `crates/relicario-core/` internals — DEV-A
- `crates/relicario-cli/`, `crates/relicario-server/`, `crates/relicario-wasm/` Rust internals — DEV-B
- `docs/` outside the spec link above
**Hard rules:**
- **No code changes.** Not even trivial. Surface in notes.
- No git commits, no branch creation, no destructive ops.
- If you find a Rust-side issue while looking at the WASM boundary, file a `## QUESTION TO PM` so DEV-B can be alerted; don't expand scope.
## What to look for (review lens)
### Extension architecture
1. **Layering — popup vs service-worker vs content vs vault tab.** Each has a clear role; are the lines clean? Any place where popup is doing trusted work that should live in the service-worker, or vice versa? Any direct WASM calls in content scripts (a security smell)?
2. **Message-passing.** `extension/src/shared/messages.ts` and the service-worker router — is the typing tight? Are there messages that exist but are never sent, or sent but never handled?
3. **WASM session handle.** The session handle is a number (an opaque pointer into the Rust session map). Where does it live? Who creates it, who drops it? Is the locked/unlocked state machine obvious from the code?
4. **CLI/extension parity.** Walk through the CLI's commands (skim `crates/relicario-cli/src/main.rs` for the surface only) and check: for every CLI capability, does the extension have an equivalent UI path? If not, is that a deliberate choice or an oversight? This is a project-philosophy lens — flag any gap as a P1 architectural issue.
5. **Component organization.** `extension/src/popup/components/` has settings, item-form, item-list, fields, generator-panel, etc. Are component boundaries clean? Any teardown leaks (the project has had teardown bugs before — see commit `ddfb95d` and `8baef5b`)?
6. **Storage and state.** What lives in `chrome.storage.local`? In `chrome.storage.session`? Any sensitive data persisted that shouldn't be? Any cleartext secrets in DOM that survive teardown?
7. **Settings architecture.** v0.5.1 just landed a unified left-nav settings (commit `bd6a301`). Is the new structure clean, or are there leftover bits from the old structure?
### Vault tab vs popup
8. **Two render targets, one component.** Settings (and possibly other components) render into both the popup and the vault tab. Is the rendering target abstracted, or are there `if (in popup)` branches? Note any pattern that breaks down.
9. **Vault tab session timeout.** There's been work on this (per project memory). Is the session-timer logic in `service-worker/session-timer.ts` legible?
### Shared utilities
10. **`shared/types.ts`, `shared/messages.ts`, `shared/state.ts`.** Are these doing what their names suggest? Any `any`-leaking? Any types that should be generated from the WASM bindings instead of hand-maintained?
11. **`shared/glyphs.ts`.** Per project rules, no inline emoji — all UI glyphs go through this. Is the abstraction tight? (Recent uncommitted edits here — note your read.)
### Relay tooling (`tools/relay/`)
12. **Single-purpose dev tool.** It's the message bus you're using right now. Is it appropriately isolated from the rest of the codebase (no cross-imports, separate package.json)? Is the role enum (`pm`, `dev-a`, `dev-b`, `dev-c`) maintained in lockstep across `queue.ts`, `server.ts`, and any client (`call.py`, `call.ts`)?
13. **Untracked `call.py` and `call.ts`.** What are these for? Are they the documented fallback shims? Should they be tracked?
### Cross-cutting
14. **Naming.** Are TS names crisp? Any that lie about behavior?
15. **Dead code.** `bun run build` cleanly? Any imports unused? Any components rendered nowhere?
16. **Simplification.** Where would a beginner trip? What's the single change that would help most?
17. **Tests.** `extension/src/**/__tests__/*.test.ts` — meaningful coverage, or smoke-only?
You may run `bun run build`, `bun run build:firefox`, `bun run test`, `cd tools/relay && bun test`, `bun run lint` if available. Review is not gated on green; it's gated on understanding.
## Output
Write your findings to `docs/superpowers/reviews/2026-05-04-dev-c-notes.md`. Create the `reviews/` directory with `mkdir -p` if it doesn't exist.
Structure:
```markdown
# DEV-C Architecture Review Notes — TypeScript (Extension + Relay)
## Summary
3-5 sentences: shape of the TS layer, strongest part, weakest part. Note the CLI/extension parity status.
## Findings (prioritized: P1 / P2 / P3)
Group by area, P1 first within each:
### Extension — service-worker
### Extension — popup + components
### Extension — vault tab
### Extension — content scripts
### Extension — setup
### Extension — shared utilities
### WASM boundary (JS side)
### Relay tooling
### CLI/extension parity gaps
### Cross-cutting
(use the same finding format as DEV-A/DEV-B: file:line, observation, why it matters, suggested direction)
## File-by-file walk
One paragraph per file (or per small group of related files). Appendix-grade.
## CLI/extension parity table
| CLI capability | Extension equivalent | Notes |
|----------------|----------------------|-------|
| ... | ✓ or ✗ or partial | ... |
## Boundary notes for DEV-B
What about the WASM JS surface (or session handle, error mapping) does DEV-B need to double-check from the Rust side?
## Beginner-friendliness assessment
A paragraph for the TS side specifically.
## Uncommitted-state read
A short paragraph: what's in the working tree but not in HEAD, and is any of it architecturally relevant?
```
## Coordination protocol
**Before each major pass:** `read_messages(for="dev-c")`.
**Status update format** (post via `post_message(from="dev-c", to="pm", kind="status", body="...")`, also print here):
```
## STATUS UPDATE — DEV-C
Time: <iso8601>
Phase: SETUP | READING | WALKING-SW | WALKING-POPUP | WALKING-VAULT | WALKING-CONTENT | WALKING-SETUP | WALKING-SHARED | WALKING-RELAY | WRITING | REVIEW-COMPLETE
Areas covered: <checklist>
Findings so far: <P1: N, P2: N, P3: N>
Notes: <≤3 sentences>
```
**Question format:**
```
## QUESTION TO PM — DEV-C
Time: <iso8601>
Context: <what file, what concern>
Options: <A / B / C>
Recommended: <pick + one-sentence rationale>
Blocker: yes | no
```
You'll receive `## DIRECTIVE TO DEV-C` blocks from the PM via relay. Acknowledge and act.
## Authority
You don't need PM permission to:
- Decide reading order within scope
- Decide P1/P2/P3 prioritization
- Use subagents to parallelize area reads (force-cd into `/home/alee/Sources/relicario` per project memory rule — every subagent prompt MUST start with `cd /home/alee/Sources/relicario`)
- Run `bun` and `cargo` commands read-only
You **do** escalate to PM when:
- A finding spans into DEV-A's core or DEV-B's Rust crates
- A finding is severe (e.g. a real security smell, leaked secret in storage)
- You're tempted to fix something inline (don't)
## REVIEW-COMPLETE criteria
- [ ] Every TS file under `extension/src/` walked (including `__tests__`)
- [ ] Every TS file under `tools/relay/` walked
- [ ] Notes written to `docs/superpowers/reviews/2026-05-04-dev-c-notes.md`
- [ ] CLI/extension parity table populated (every CLI capability either ✓, ✗, or partial)
- [ ] Boundary-notes section for DEV-B populated
- [ ] Uncommitted-state read paragraph written
- [ ] Every P1 has a file:line and suggested direction
## First action
1. Call `read_messages(for="dev-c")`.
2. Read project rules and spec.
3. Look at `manifest.json` and skim `wasm.d.ts` so you know your boundaries.
4. Run `git status` and `git diff` once for awareness of uncommitted state.
5. Emit a `## STATUS UPDATE` with `Phase: SETUP` confirming setup, listing area buckets you'll walk.
6. Begin the walk: service-worker first, then shared, then popup, then vault, then content, then setup, then relay tooling. Save findings as you go.

View File

@@ -0,0 +1,200 @@
# Dev A Kickoff Prompt — Architecture Review Followup, Stream A (Security & Docs Polish)
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement the plan task-by-task once it lands.
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior developer** owning Stream A for the Relicario architecture-review-followup work. Stream A is the small, security-flavored quick-win PR that goes first: SessionHandle Drop semantics, the matching JS-side audit, recovery_qr.rs documentation density, and the relay launcher fix for the dev-c fourth window. Goal is **under-a-day, all-S effort, ships first**.
A PM in another terminal coordinates you with two other senior devs. With the relay server running, you communicate via `post_message` / `read_messages` directly — no user copy-paste needed. **Your plan does not exist yet.** The PM is drafting it as their first action. Set up your worktree, post acknowledgement, and wait for the PM's `PROCEED` directive containing the plan path before starting Task 1.
## Setup (do this first)
```bash
cd /home/alee/Sources/relicario
git fetch
git worktree add /home/alee/Sources/relicario.arch-followup-stream-a -b feature/arch-followup-stream-a-security-polish
cd /home/alee/Sources/relicario.arch-followup-stream-a
pwd # should print /home/alee/Sources/relicario.arch-followup-stream-a
```
**Note on `git pull`:** main has uncommitted polish changes from in-flight post-v0.5.1 work. The setup above branches from local main HEAD without pulling, which is intentional. If `git fetch` reveals new upstream commits, surface them to the PM before incorporating.
**ALL subsequent work happens in `/home/alee/Sources/relicario.arch-followup-stream-a`**. Every subagent prompt MUST begin with `cd /home/alee/Sources/relicario.arch-followup-stream-a` (project memory rule — without the force-cd, subagents may commit to main).
Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalize "Relicario", default to "yes"/recommended, never run git-destructive commands without asking).
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/reviews/2026-05-04-architecture-review.md` — synthesis (your scope is **P1.1, the JS free-swallow fix, P1.7, P1.8 only**)
3. `docs/superpowers/reviews/2026-05-04-dev-a-notes.md` — full DEV-A reviewer notes (Rust core; covers recovery_qr.rs context)
4. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — full DEV-B reviewer notes (covers SessionHandle context on the WASM side)
5. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — full DEV-C reviewer notes (covers the JS free-swallow + start.sh launcher context)
6. **Your plan (will land at):** `docs/superpowers/specs/2026-05-04-security-polish-design.md` — read once the PM directs you to PROCEED
## Execution mode
Use **superpowers:subagent-driven-development**. Fresh subagent per task, two-stage review between tasks. Every subagent prompt MUST start with:
```
cd /home/alee/Sources/relicario.arch-followup-stream-a
```
…before any other instruction. This is non-negotiable per project memory.
## Your scope and boundaries
**In scope:**
- P1.1 — `impl Drop for SessionHandle` in `crates/relicario-wasm/src/lib.rs` (and `session.rs`); `wasm-bindgen-test` for construct → drop → confirm `SESSIONS` registry empty; audit every `.free()` callsite under `extension/src/` to confirm `wasm.lock(handle)` happens first regardless
- JS partner fix at `extension/src/service-worker/session.ts:26` — remove the `try { current.free() }` swallow; let exceptions propagate or log + counter
- P1.7 — `crates/relicario-core/src/recovery_qr.rs` documentation pass to match `crypto.rs` / `imgsecret.rs` / `backup.rs` / `tar_safe.rs` density
- P1.8 — `tools/relay/start.sh:80` launcher fix for the dev-c fourth window (the queue.test.ts assertion is already fixed in `061facd`; only the launcher line remains)
**Out of scope (other DEVs own these):**
- P1.2, P1.3, P1.10 + the in-scope CLI P2s — DEV-B (Stream B)
- P1.4, P1.5, P1.6, P1.9 + the in-scope extension P2s — DEV-C (Stream C)
- Any other P2/P3 not listed in your plan
- The 8 "Open architectural decisions" at the bottom of the synthesis — those are user-judgement calls
If you trip over an out-of-scope issue or a new bug while doing your work, file a `## QUESTION TO PM` block and keep moving.
**Hard rules:**
- **P1.1 is defense-in-depth crypto.** The `wasm-bindgen-test` covering construct → drop → registry-empty is a required acceptance gate. Do not skip or weaken it.
- **The `.free()` callsite audit is part of P1.1.** Every callsite under `extension/src/` must be checked to confirm `wasm.lock(handle)` is called before `.free()`. Document the audit results in the PR.
- **Do not remove the JS free-swallow before `impl Drop` lands.** The order matters: Rust fix first (so `.free()` becomes meaningful cleanup), JS swallow removal second (so failures surface).
- **`recovery_qr.rs` docs must match the existing core standard.** Multi-paragraph module-level `//!` rationale, ASCII diagram of the 109-byte layout, doc-comments on the four public functions, comment or `const` for the `production_params()` divergence. Read `crypto.rs` and `backup.rs` first to absorb the tone.
- **Test-only Argon2id params stay fast** (m=256, t=1, p=1) per project convention.
- Synthetic JPEG fixtures only — no binary blobs in the test suite (project rule).
- Do not merge your branch to main. The PM owns merges.
- Do not push `--force` or run `git reset --hard`. Per `CLAUDE.md`: ask first.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-a"`
- `read_messages(for)` — drain your inbox; call with `for="dev-a"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-a")`. After emitting any status/question block: `post_message(from="dev-a", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-a","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-a"}'
```
## Coordination protocol
You are one of four terminals. Before starting each task, call `read_messages(for="dev-a")` to drain your inbox.
When posting a status update, call `post_message(from="dev-a", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-A
Time: <iso8601 like 2026-05-04T14:30:00-07:00>
Branch: feature/arch-followup-stream-a-security-polish
Task: <number / short name>
Status: STARTED | IN-PROGRESS | DONE | BLOCKED | REVIEW-READY
Last commit: <short sha + first line of message>
Tests: <green | red (which failed) | N/A>
Notes: <anything PM needs to know — keep to 3 sentences max>
```
**When you need PM input mid-task:**
```
## QUESTION TO PM — DEV-A
Time: <iso8601>
Context: <what task, what decision point>
Options: <A: ... / B: ... / C: ...>
Recommended: <your pick + one-sentence rationale>
Blocker: yes | no
```
**You'll receive:** `## DIRECTIVE TO DEV-A` blocks from the PM. The first one will say `Action: PROCEED` with the plan path once the PM has drafted it. Acknowledge and start Task 1.
## Authority within the plan
You don't need PM permission to:
- Execute task-to-task per the plan once you have it
- Make implementation decisions consistent with the plan and synthesis
- Write tests, refactor your own code, fix bugs you introduce
- Push commits to your feature branch
You **do** escalate to PM when:
- A scope question outside the plan
- A test you can't make green after honest debugging (don't fudge — debug)
- A discovered bug not in your plan
- Anything destructive (per CLAUDE.md)
- Before opening the PR for review
## Final steps before REVIEW-READY
Run the project's full validation:
```bash
cd /home/alee/Sources/relicario.arch-followup-stream-a
cargo test
cargo build -p relicario-wasm --target wasm32-unknown-unknown
cd extension && bun run test && bun run build && cd ..
cd tools/relay && bun test && cd ../..
```
All four must be green. The wasm-bindgen-test for SessionHandle Drop is the headline acceptance.
Then push and open the PR:
```bash
git push -u origin feature/arch-followup-stream-a-security-polish
gh pr create --base main --head feature/arch-followup-stream-a-security-polish \
--title "fix(security/docs): SessionHandle Drop + free-swallow + recovery_qr docs + dev-c launcher (Stream A)" \
--body "$(cat <<'EOF'
## Summary
Stream A of the architecture-review-followup. Small security-flavored polish PR addressing four findings from the 2026-05-04 audit:
- **P1.1** — `impl Drop for SessionHandle` so `.free()` becomes a real cleanup safety net (Rust fix); `wasm-bindgen-test` for construct → drop → registry empty; audit of every `.free()` callsite under `extension/src/`
- **JS free-swallow** — removed `try { current.free() }` at `extension/src/service-worker/session.ts:26` so failures propagate
- **P1.7** — `crates/relicario-core/src/recovery_qr.rs` brought up to the documentation density of `crypto.rs` / `backup.rs` / `tar_safe.rs`
- **P1.8** — `tools/relay/start.sh:80` launcher fix for the dev-c fourth window
## Synthesis references
- `docs/superpowers/reviews/2026-05-04-architecture-review.md` — P1.1, P1.7, P1.8
- `docs/superpowers/specs/2026-05-04-security-polish-design.md` — Plan A
## Test plan
- [x] `cargo test` green
- [x] `cargo build -p relicario-wasm --target wasm32-unknown-unknown` green
- [x] `cd extension && bun run test && bun run build` green
- [x] `cd tools/relay && bun test` green (4-pass after dev-c assertion fix in 061facd)
- [x] New wasm-bindgen-test: SessionHandle construct → drop → SESSIONS registry empty
- [x] `.free()` callsite audit under `extension/src/` — every site preceded by `wasm.lock(handle)`
- [x] `start.sh` opens 4 windows including dev-c
EOF
)"
```
Emit a `## STATUS UPDATE` with `Status: REVIEW-READY` and the PR URL.
## First action
After reading the required inputs and setting up the worktree:
1. Call `read_messages(for="dev-a")` to drain any early inbox messages.
2. Emit a `## STATUS UPDATE` confirming setup complete:
```
## STATUS UPDATE — DEV-A
Time: <iso8601>
Branch: feature/arch-followup-stream-a-security-polish
Task: setup
Status: DONE
Last commit: <main HEAD sha + first line>
Tests: N/A
Notes: Worktree at /home/alee/Sources/relicario.arch-followup-stream-a. Synthesis + reviewer notes absorbed. Awaiting Plan A at docs/superpowers/specs/2026-05-04-security-polish-design.md.
```
3. **Wait** for the PM's `## DIRECTIVE TO DEV-A` with `Action: PROCEED` and the plan path.
4. Read the plan, then start Task 1 using `superpowers:subagent-driven-development`.

View File

@@ -0,0 +1,242 @@
# Dev B Kickoff Prompt — Architecture Review Followup, Stream B (CLI Restructure)
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement the plan task-by-task once it lands.
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior developer** owning Stream B for the Relicario architecture-review-followup work. Stream B is the **single biggest readability lift** in the bundle (per the synthesis): split the 2641-LOC `crates/relicario-cli/src/main.rs` into a `commands/` folder, centralize the duplicated git-shell error UX, migrate three pure parsers to `relicario-core`, and pick up four in-scope CLI P2s. Multi-day, M-L effort.
A PM in another terminal coordinates you with two other senior devs. With the relay server running, you communicate via `post_message` / `read_messages` directly. **Your plan does not exist yet.** The PM is drafting it as their first action. Set up your worktree, post acknowledgement, and wait for the PM's `PROCEED` directive containing the plan path before starting Task 1.
## Setup (do this first)
```bash
cd /home/alee/Sources/relicario
git fetch
git worktree add /home/alee/Sources/relicario.arch-followup-stream-b -b feature/arch-followup-stream-b-cli-restructure
cd /home/alee/Sources/relicario.arch-followup-stream-b
pwd # should print /home/alee/Sources/relicario.arch-followup-stream-b
```
**Note on `git pull`:** main has uncommitted polish changes from in-flight post-v0.5.1 work. The setup above branches from local main HEAD without pulling, which is intentional. None of those uncommitted files are in Stream B's scope, so this should not produce conflicts at PR time.
**ALL subsequent work happens in `/home/alee/Sources/relicario.arch-followup-stream-b`**. Every subagent prompt MUST begin with `cd /home/alee/Sources/relicario.arch-followup-stream-b` (project memory rule — without the force-cd, subagents may commit to main).
Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalize "Relicario", default to "yes"/recommended, never run git-destructive commands without asking).
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/reviews/2026-05-04-architecture-review.md` — synthesis (your scope is **P1.2, P1.3, P1.10 + the four in-scope CLI P2s only**)
3. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — full DEV-B reviewer notes (your stream's primary source)
4. `docs/superpowers/reviews/2026-05-04-dev-a-notes.md` — full DEV-A reviewer notes (covers the base32 dedup that pairs with P1.10)
5. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — read the **"Boundary notes for DEV-B"** section in particular (covers the parity-relevant cross-references for the parser→core migration and WASM exports)
6. **Your plan (will land at):** `docs/superpowers/specs/2026-05-04-cli-restructure-design.md` — read once the PM directs you to PROCEED
## Execution mode
Use **superpowers:subagent-driven-development**. Fresh subagent per task, two-stage review between tasks. Every subagent prompt MUST start with:
```
cd /home/alee/Sources/relicario.arch-followup-stream-b
```
…before any other instruction. This is non-negotiable per project memory.
## Your scope and boundaries
**In scope:**
- P1.2 — split `crates/relicario-cli/src/main.rs` (2641 LOC) into:
- `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr}.rs`
- `prompt.rs` (six `prompt_*` helpers + `prompt_secret`)
- `parse.rs` (the three pure parsers, before they migrate to core)
- `main.rs` keeps clap definitions + dispatcher (~470 lines)
- P1.3 — add `helpers::git_run(repo: &Path, args: &[&str], context: &str)` using `.output()` to capture stderr; print captured stderr unmodified on failure; embed a human-readable `context` ("commit add: GitHub", "register device", "purge trashed item"). Sweep ~16 duplicated bail sites listed in the synthesis (`main.rs:601, 602, 610, 986, 988, 1477, 1480, 1767, 1897, 1900, 2432, 2438, 2533, 2540` and others).
- P1.10 — migrate to `relicario-core`:
- `parse_month_year` (already partial in `time.rs`)
- `base32_decode_lenient` (rename / fold into a new `pub(crate) mod base32` with `encode_rfc4648` / `decode_rfc4648`; keep Steam's bespoke alphabet untouched in `item_types/totp.rs`)
- `guess_mime``mime::guess_for_extension`
- Re-export the new functions through `relicario-wasm` via `#[wasm_bindgen]` so the extension can consume them in a future round
- CLI keeps thin wrappers as needed
- In-scope CLI P2s:
- `build_*_item` helper compression (`main.rs:664-921`) with a `prompt_or_flag<T>` helper
- `refresh_groups_cache` discipline via `Vault::after_manifest_change(&self, manifest: &Manifest)` (7 manual sites at `main.rs:641, 998, 1123, 1197, 1414, 1432, 1474`)
- `ParamsFile` dedup between `main.rs:2287` (write side, has `aead`/`salt_path`/`format_version`) and `session.rs:114` (read side, only `kdf`)
- Batched purge in `cmd_purge` and `cmd_trash_empty` (`main.rs:1476-1480, 1896-1900`) — currently 50-item purge does 150 git invocations
**Out of scope (other DEVs own these):**
- P1.1, JS free-swallow, P1.7, P1.8 — DEV-A (Stream A)
- P1.4, P1.5, P1.6, P1.9 + the in-scope extension P2s — DEV-C (Stream C)
- Any other P2/P3 not listed in your plan
- WASM JS-naming snake_case → camelCase rename (DEV-B/DEV-C P3) — explicitly deferred to a separate decision
- Server hardening items from DEV-B's P2 (generate-hook PATH, bootstrap permissiveness, stdin parsing, test gaps) — explicitly deferred
- Any of the 8 "Open architectural decisions" at the bottom of the synthesis
If you trip over an out-of-scope issue or a new bug while doing your work, file a `## QUESTION TO PM` block and keep moving.
**Hard rules:**
- **The P1.2 main.rs split MUST land first.** Every other phase in your plan touches files that don't exist yet until the split happens. Do not interleave.
- **The split is purely structural — no behavior changes.** Run `cargo test -p relicario-cli` before AND after the split commits to prove parity. Any behavior delta is a bug.
- **Keep the helper module visibility tight.** `commands/` modules are `pub(crate)` only; `main.rs` dispatches into them.
- **`helpers::git_run` signature** is `(repo: &Path, args: &[&str], context: &str)` and it captures stderr. The old `git_command` may stay temporarily during the sweep, but Phase B-N (sweep) deletes it.
- **`base32` extraction** must keep Steam's bespoke alphabet untouched at `item_types/totp.rs`. Add a neighbour comment pointing to the new core module and explaining why Steam stays separate.
- **WASM re-exports use snake_case** in JS for now (`#[wasm_bindgen]` defaults). Do not rename to camelCase — that's a separate decision (DEV-B/DEV-C P3 at the bottom of the synthesis).
- **Test-only Argon2id params stay fast** (m=256, t=1, p=1) per project convention.
- **No binary test fixtures.** Synthetic JPEGs only via `make_test_jpeg()`.
- **Git history is preserved.** No squash merges (project rule).
- Do not merge your branch to main. The PM owns merges.
- Do not push `--force` or run `git reset --hard`. Per `CLAUDE.md`: ask first.
## Coordination with Stream C
Your parser→core migration produces new `relicario-core` functions and re-exports them through `relicario-wasm`. Stream C does NOT need to consume these in this round. Document the new WASM surface in your PR body so a future round can pick it up. If you discover a parser signature change that would break the future extension consumer, raise it via `## QUESTION TO PM` before committing.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-b"`
- `read_messages(for)` — drain your inbox; call with `for="dev-b"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-b")`. After emitting any status/question block: `post_message(from="dev-b", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-b","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-b"}'
```
## Coordination protocol
You are one of four terminals. Before starting each task, call `read_messages(for="dev-b")` to drain your inbox.
When posting a status update, call `post_message(from="dev-b", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-B
Time: <iso8601 like 2026-05-04T14:30:00-07:00>
Branch: feature/arch-followup-stream-b-cli-restructure
Task: <number / short name>
Status: STARTED | IN-PROGRESS | DONE | BLOCKED | REVIEW-READY
Last commit: <short sha + first line of message>
Tests: <green | red (which failed) | N/A>
Notes: <anything PM needs to know — keep to 3 sentences max>
```
**When you need PM input mid-task:**
```
## QUESTION TO PM — DEV-B
Time: <iso8601>
Context: <what task, what decision point>
Options: <A: ... / B: ... / C: ...>
Recommended: <your pick + one-sentence rationale>
Blocker: yes | no
```
**You'll receive:** `## DIRECTIVE TO DEV-B` blocks from the PM. The first one will say `Action: PROCEED` with the plan path once the PM has drafted it. Acknowledge and start Task 1.
## Authority within the plan
You don't need PM permission to:
- Execute task-to-task per the plan once you have it
- Make implementation decisions consistent with the plan and synthesis
- Write tests, refactor your own code, fix bugs you introduce
- Push commits to your feature branch
You **do** escalate to PM when:
- A scope question outside the plan
- A signature change in the parser→core migration that would affect the future extension consumer
- A test you can't make green after honest debugging (don't fudge — debug)
- A discovered bug not in your plan
- Anything destructive (per CLAUDE.md)
- Before opening the PR for review
## Final steps before REVIEW-READY
Run the project's full validation:
```bash
cd /home/alee/Sources/relicario.arch-followup-stream-b
cargo build
cargo test
cargo test -p relicario-core
cargo test -p relicario-cli --test basic_flows
cargo test -p relicario-cli --test edit_and_history
cargo test -p relicario-cli --test attachments
cargo test -p relicario-cli --test settings
cargo test -p relicario-cli --test vault_detection
cargo build -p relicario-wasm --target wasm32-unknown-unknown
cargo run -p relicario-cli -- --help
cargo run -p relicario-cli -- generate --length 32
```
All must be green. The CLI integration suite covers the surface area touched by the split + git_run sweep; pay particular attention to `basic_flows` and `edit_and_history` for regression coverage.
Then push and open the PR:
```bash
git push -u origin feature/arch-followup-stream-b-cli-restructure
gh pr create --base main --head feature/arch-followup-stream-b-cli-restructure \
--title "refactor(cli): split main.rs into commands/ + git_run helper + parsers→core (Stream B)" \
--body "$(cat <<'EOF'
## Summary
Stream B of the architecture-review-followup. The single biggest readability lift in the bundle:
- **P1.2** — `crates/relicario-cli/src/main.rs` (2641 LOC) split into `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr}.rs` + `prompt.rs` + `parse.rs`. `main.rs` keeps clap definitions + dispatcher.
- **P1.3** — `helpers::git_run(repo, args, context)` with stderr capture; ~16 duplicated bail sites swept.
- **P1.10** — `parse_month_year`, `base32_decode_lenient` (folded into a new `relicario_core::base32` module alongside DEV-A's P2 dedup), `guess_mime` migrated to `relicario-core`. Re-exported through `relicario-wasm` via `#[wasm_bindgen]` for future extension consumption.
- **CLI P2 cluster** — `build_*_item` helper compression, `Vault::after_manifest_change`, `ParamsFile` dedup, batched purge.
## Synthesis references
- `docs/superpowers/reviews/2026-05-04-architecture-review.md` — P1.2, P1.3, P1.10 + DEV-B's CLI P2 cluster + DEV-A's base32 dedup
- `docs/superpowers/specs/2026-05-04-cli-restructure-design.md` — Plan B
## New WASM surface (for future Stream C consumption)
The extension does NOT consume these in this round. A future plan should wire them up via `wasm.d.ts` regeneration:
- `parse_month_year` — for QR-import / smart-input flows
- `base32_encode_rfc4648` / `base32_decode_rfc4648` — for TOTP / future QR work
- `guess_mime_for_extension` — for attachment MIME detection
## Test plan
- [x] `cargo build` green
- [x] `cargo test` green (workspace-wide)
- [x] `cargo test -p relicario-core` green (new base32 module + parser tests)
- [x] `cargo test -p relicario-cli --test basic_flows` green (regression on the split)
- [x] `cargo test -p relicario-cli --test edit_and_history` green
- [x] `cargo test -p relicario-cli --test attachments` green
- [x] `cargo test -p relicario-cli --test settings` green
- [x] `cargo build -p relicario-wasm --target wasm32-unknown-unknown` green (new exports)
- [x] `cargo run -p relicario-cli -- --help` displays unchanged surface
- [x] `cargo run -p relicario-cli -- generate --length 32` smoke
- [x] git_run sweep: every git failure path now prints captured stderr + context
- [x] Steam alphabet at `item_types/totp.rs` untouched
EOF
)"
```
Emit a `## STATUS UPDATE` with `Status: REVIEW-READY` and the PR URL.
## First action
After reading the required inputs and setting up the worktree:
1. Call `read_messages(for="dev-b")` to drain any early inbox messages.
2. Emit a `## STATUS UPDATE` confirming setup complete:
```
## STATUS UPDATE — DEV-B
Time: <iso8601>
Branch: feature/arch-followup-stream-b-cli-restructure
Task: setup
Status: DONE
Last commit: <main HEAD sha + first line>
Tests: N/A
Notes: Worktree at /home/alee/Sources/relicario.arch-followup-stream-b. Synthesis + DEV-B/DEV-A notes + DEV-C boundary section absorbed. Awaiting Plan B at docs/superpowers/specs/2026-05-04-cli-restructure-design.md.
```
3. **Wait** for the PM's `## DIRECTIVE TO DEV-B` with `Action: PROCEED` and the plan path.
4. Read the plan, then start Task 1 using `superpowers:subagent-driven-development`. Phase 1 is the main.rs split — finish it cleanly before any other phase.

View File

@@ -0,0 +1,275 @@
# Dev C Kickoff Prompt — Architecture Review Followup, Stream C (Extension Restructure)
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement the plan task-by-task once it lands.
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are a **senior developer** owning Stream C for the Relicario architecture-review-followup work. Stream C is the **largest plan in the bundle** (multi-day to multi-week): turn `setup.ts` into a UI that posts SW messages instead of orchestrating WASM directly, split `vault.ts` into focused modules, give `shared/state.ts` a real type contract, deduplicate the SW router helpers, and pick up the in-scope extension P2 cluster.
A PM in another terminal coordinates you with two other senior devs. With the relay server running, you communicate via `post_message` / `read_messages` directly. **Your plan does not exist yet.** The PM is drafting it as their first action. Set up your worktree, post acknowledgement, and wait for the PM's `PROCEED` directive containing the plan path before starting Task 1.
## Setup (do this first)
```bash
cd /home/alee/Sources/relicario
git fetch
git worktree add /home/alee/Sources/relicario.arch-followup-stream-c -b feature/arch-followup-stream-c-extension-restructure
cd /home/alee/Sources/relicario.arch-followup-stream-c
pwd # should print /home/alee/Sources/relicario.arch-followup-stream-c
```
**Note on `git pull`:** main has uncommitted polish changes from in-flight post-v0.5.1 work, including edits to `extension/src/vault/vault.ts`, `vault.css`, and `shared/glyphs.ts` — files Stream C will touch heavily. **Surface this to the PM as a Question before starting Phase 1** so the user can choose to commit/stash the in-flight work, defer Stream C, or proceed and merge at PR time. The setup above branches from local main HEAD without pulling, so your worktree starts clean of those uncommitted edits.
**ALL subsequent work happens in `/home/alee/Sources/relicario.arch-followup-stream-c`**. Every subagent prompt MUST begin with `cd /home/alee/Sources/relicario.arch-followup-stream-c` (project memory rule — without the force-cd, subagents may commit to main).
Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalize "Relicario", default to "yes"/recommended, never run git-destructive commands without asking).
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/reviews/2026-05-04-architecture-review.md` — synthesis (your scope is **P1.4, P1.5, P1.6, P1.9 + the in-scope extension P2 cluster only**)
3. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — full DEV-C reviewer notes (your stream's primary source)
4. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — read the **"Boundary notes for DEV-C"** section in particular (covers the parity-relevant cross-references, especially the new WASM surface that Plan B will produce)
5. `docs/superpowers/reviews/2026-05-04-dev-a-notes.md` — light skim for context only
6. **Your plan (will land at):** `docs/superpowers/specs/2026-05-04-extension-restructure-design.md` — read once the PM directs you to PROCEED
## Execution mode
Use **superpowers:subagent-driven-development**. Fresh subagent per task, two-stage review between tasks. Every subagent prompt MUST start with:
```
cd /home/alee/Sources/relicario.arch-followup-stream-c
```
…before any other instruction. This is non-negotiable per project memory.
## Your scope and boundaries
**In scope:**
- P1.4 — `extension/src/setup/setup.ts` (1220 LOC):
- Add `create_vault` and `attach_vault` SW messages to `service-worker/router/popup-only.ts` + the message-type union in `shared/messages.ts`
- Rewrite `setup.ts` as a UI that posts those messages with gathered config + image bytes (no direct `relicario-wasm` import)
- Convert the 6-step procedural wizard into a step-registry pattern: `Array<{ id: StepId; render: (host) => void; attach: (host) => () => void }>`
- `clearWizardState()` bound to `beforeunload` and to "return to step 0"
- Target ~500 LOC after the rewrite (down from 1220)
- P1.5 — split `extension/src/vault/vault.ts` (1027 LOC) into:
- `vault-shell.ts` (init, hash routing)
- `vault-sidebar.ts` (sidebar render)
- `vault-list.ts` (list pane render)
- `vault-drawer.ts` (drawer state + render)
- `vault-form-wrapper.ts` (form integration)
- `vault.ts` keeps only routing + state coordination
- **Lift the `vault_locked` RPC intercept into `shared/state.ts`** (or a wrapper around `sendMessage`) so popup and vault tab use the same channel — closes the synthesis P2 about RPC vs `session_expired` event divergence
- Reset `state.drawerOpen` at the start of `renderPane` for non-list views
- P1.6 — concrete `StateHost` interface in `extension/src/shared/state.ts`:
```ts
interface StateHost {
state: PopupState;
navigate: (view: View) => void;
popOutToTab(): void;
isInTab(): boolean;
openVaultTab(hash?: string): void;
}
```
- Make `getState`/`setState` generic over `keyof PopupState`
- Throw on `registerHost()` re-register
- Export `__resetHostForTests()` helper
- P1.9 — extract from both router files:
- `loadDeviceSettings`, `loadBlacklist`, `saveBlacklist` → `extension/src/service-worker/storage.ts`
- `itemToManifestEntry` (17-line projection) → `extension/src/service-worker/vault.ts`
- Import from both `popup-only.ts` and `content-callable.ts`
- In-scope extension P2 cluster:
- Inactivity-timer reset on content-callable messages (`service-worker/index.ts:76-78`)
- Null `state.gitHost` alongside `state.manifest` on session expiry (`service-worker/index.ts:51-58`)
- Teardown helper extraction: `settings.ts:56-65` and `settings-vault.ts:15-22` → `teardownSettingsCommon()`
- `Promise.allSettled` in `devices.ts:47-50` and `trash.ts:39-46`
- MutationObserver debounce in `content/detector.ts:96-103` (`requestIdleCallback` or 200ms timer)
- Vault-tab status indicator from new `get_vault_status` SW message returning `{ ahead, behind, lastSyncAt, pendingItems }` (closes the `relicario status` parity gap)
**Out of scope (other DEVs own these):**
- P1.1, JS free-swallow, P1.7, P1.8 — DEV-A (Stream A). **Note:** if A merges first, you'll inherit `impl Drop for SessionHandle`. That's expected and benign.
- P1.2, P1.3, P1.10 + the in-scope CLI P2s — DEV-B (Stream B). The new WASM exports (`parse_month_year`, `base32_*`, `guess_mime_for_extension`) that Plan B produces are NOT consumed in this round. Document the future consumer in your plan's "Out of scope" section; a later round wires them up.
- Other DEV-C P2/P3 not listed in your scope (e.g. shared-utilities response typing, group-autocomplete escaping, restore_backup payload extract, content-script `fillFields()` ack, content/icon outside-click leak) — explicitly deferred to a future round
- Setup-wizard manifest path constants (`VAULT_PATHS`) — folds into your P1.4 work; if convenient include it, else defer
- WASM JS-naming snake_case → camelCase rename — explicitly deferred
- Any of the 8 "Open architectural decisions" at the bottom of the synthesis
If you trip over an out-of-scope issue or a new bug while doing your work, file a `## QUESTION TO PM` block and keep moving.
**Hard rules:**
- **P1.6 (state.ts typing) MUST land first internally.** Both P1.4 and P1.5 push through the `StateHost` surface. Plan should call this out as Phase 1.
- **`setup.ts` MUST stop importing `relicario-wasm` directly after P1.4.** This is the architectural invariant the synthesis is fixing. After P1.4, the only file in `extension/src/` that imports `relicario-wasm` should be the service worker.
- **New SW message names are `create_vault` and `attach_vault`.** Use these exact names everywhere (`shared/messages.ts`, `service-worker/router/popup-only.ts`, `setup.ts`). The PM's coherence pass on the plans confirms naming consistency.
- **`vault_locked` unification goes in `shared/state.ts`** (or a wrapper around `sendMessage`). Popup AND vault tab use the same channel after this lands. Two channels for one outcome was the synthesis observation.
- **No emoji anywhere in `extension/src/`** (existing project rule from v0.5.1). If you see one while editing, replace with the monochrome glyph from `glyphs.ts`.
- **`glyphs.ts` is single source of truth** for icon characters. No inline Unicode literals at call sites.
- **Discriminated-union message contract is preserved.** New messages get added to `shared/messages.ts` and the appropriate capability set (`POPUP_ONLY_TYPES` or `CONTENT_CALLABLE_TYPES`). The boundary discipline holds.
- **WASM remains snake_case in JS** — no `#[wasm_bindgen(js_name = ...)]` renaming. That's a separate decision (DEV-B/DEV-C P3).
- **Test setup is vitest** for the extension (`extension/package.json: "test": "vitest run"`), `bun test` for `tools/relay/`. Do not change runners.
- **Synthetic test fixtures only.** No binary blobs.
- Do not merge your branch to main. The PM owns merges.
- Do not push `--force` or run `git reset --hard`. Per `CLAUDE.md`: ask first.
## Coordination with Stream B
Stream B will produce new `relicario-wasm` exports (`parse_month_year`, `base32_*`, `guess_mime_for_extension`). You do NOT consume these in this round — your plan's "Out of scope" section should explicitly call this out and reference the future consumer (likely a smart-input / QR-import / attachment-MIME round). If Stream B's WASM signature for any of these would NOT match what the extension would naturally consume, raise a `## QUESTION TO PM` so it can be reconciled before Stream B merges.
If Stream A merges first and you inherit `impl Drop for SessionHandle` plus the JS free-swallow removal: that's benign. Your `.free()` callsites should already be `wasm.lock(handle)` first per DEV-A's audit.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-c"`
- `read_messages(for)` — drain your inbox; call with `for="dev-c"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-c")`. After emitting any status/question block: `post_message(from="dev-c", to="pm", kind="status"|"question", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"dev-c","to":"pm","kind":"status","body":"..."}'
python3 call.py read_messages '{"for":"dev-c"}'
```
## Coordination protocol
You are one of four terminals. Before starting each task, call `read_messages(for="dev-c")` to drain your inbox.
When posting a status update, call `post_message(from="dev-c", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-C
Time: <iso8601 like 2026-05-04T14:30:00-07:00>
Branch: feature/arch-followup-stream-c-extension-restructure
Task: <number / short name>
Status: STARTED | IN-PROGRESS | DONE | BLOCKED | REVIEW-READY
Last commit: <short sha + first line of message>
Tests: <green | red (which failed) | N/A>
Notes: <anything PM needs to know — keep to 3 sentences max>
```
**When you need PM input mid-task:**
```
## QUESTION TO PM — DEV-C
Time: <iso8601>
Context: <what task, what decision point>
Options: <A: ... / B: ... / C: ...>
Recommended: <your pick + one-sentence rationale>
Blocker: yes | no
```
**You'll receive:** `## DIRECTIVE TO DEV-C` blocks from the PM. The first one will say `Action: PROCEED` with the plan path once the PM has drafted it. Acknowledge and start Task 1.
## Authority within the plan
You don't need PM permission to:
- Execute task-to-task per the plan once you have it
- Make implementation decisions consistent with the plan and synthesis
- Write tests, refactor your own code, fix bugs you introduce
- Push commits to your feature branch
You **do** escalate to PM when:
- A scope question outside the plan
- A WASM signature mismatch with what Stream B is producing
- A test you can't make green after honest debugging (don't fudge — debug)
- A discovered bug not in your plan
- The in-flight uncommitted changes on `vault.ts`/`vault.css`/`glyphs.ts` need resolution before a merge
- Anything destructive (per CLAUDE.md)
- Before opening the PR for review
## Final steps before REVIEW-READY
Run the project's full validation:
```bash
cd /home/alee/Sources/relicario.arch-followup-stream-c
cd extension
bun run test
bun run build
bun run build:firefox
cd ..
cargo build -p relicario-wasm --target wasm32-unknown-unknown
```
All must be green. Vitest covers the new `StateHost` typing, the message-router dedup, and the wizard step registry.
Then sweep for emoji and in-flight collision:
```bash
grep -rn '\U0001F\|🔑\|📝\|🪪\|💳\|🗝\|📄\|⏱️\|🖥\|🔐\|📎' /home/alee/Sources/relicario.arch-followup-stream-c/extension/src/ 2>/dev/null
```
Expected: no output (project rule).
Then push and open the PR:
```bash
git push -u origin feature/arch-followup-stream-c-extension-restructure
gh pr create --base main --head feature/arch-followup-stream-c-extension-restructure \
--title "refactor(ext): setup-via-SW + vault.ts split + state.ts typing + SW router dedup (Stream C)" \
--body "$(cat <<'EOF'
## Summary
Stream C of the architecture-review-followup. The largest plan in the bundle — turns three "code lies about the architecture" surfaces into uniform readable modules:
- **P1.4** — `extension/src/setup/setup.ts` no longer imports `relicario-wasm` directly. New `create_vault` / `attach_vault` SW messages do the crypto orchestration. The 6-step wizard is now a step registry. ~500 LOC down from 1220.
- **P1.5** — `extension/src/vault/vault.ts` (1027 LOC) split into `vault-shell.ts` / `vault-sidebar.ts` / `vault-list.ts` / `vault-drawer.ts` / `vault-form-wrapper.ts`. `vault_locked` RPC intercept lifted into `shared/state.ts` so popup and vault tab share one channel.
- **P1.6** — `extension/src/shared/state.ts` has a concrete `StateHost` interface; `getState`/`setState` are generic over `keyof PopupState`; double-registration guard + `__resetHostForTests` helper.
- **P1.9** — duplicated SW router helpers extracted: `service-worker/storage.ts` for the three storage helpers, `service-worker/vault.ts` for `itemToManifestEntry`.
- **Extension P2 cluster** — inactivity-timer reset on content-callable messages, `state.gitHost` clear on session expiry, `teardownSettingsCommon()`, `Promise.allSettled` in devices/trash, MutationObserver debounce in content/detector, vault-tab status indicator (closes `relicario status` parity gap).
## Synthesis references
- `docs/superpowers/reviews/2026-05-04-architecture-review.md` — P1.4, P1.5, P1.6, P1.9 + DEV-C's extension P2 cluster
- `docs/superpowers/specs/2026-05-04-extension-restructure-design.md` — Plan C
## Future-round consumer (NOT in this PR)
Plan B produces new `relicario-wasm` exports (`parse_month_year`, `base32_*`, `guess_mime_for_extension`). A later round will wire them up via `wasm.d.ts` regeneration and add SW message handlers. Out of scope here.
## Test plan
- [x] `bun run test` green in `extension/`
- [x] `bun run build` green
- [x] `bun run build:firefox` green
- [x] `cargo build -p relicario-wasm --target wasm32-unknown-unknown` green
- [x] No emoji anywhere in `extension/src/` (grep clean)
- [x] `setup.ts` no longer imports `relicario-wasm`
- [x] `vault.ts` LOC dropped substantially; new modules each under ~300 LOC
- [x] Vault tab and popup both use one channel for `vault_locked` (no RPC intercept divergence)
- [x] StateHost interface concrete; tests cover double-registration guard and reset helper
EOF
)"
```
Emit a `## STATUS UPDATE` with `Status: REVIEW-READY` and the PR URL.
## First action
After reading the required inputs and setting up the worktree:
1. Call `read_messages(for="dev-c")` to drain any early inbox messages.
2. Emit a `## STATUS UPDATE` confirming setup complete:
```
## STATUS UPDATE — DEV-C
Time: <iso8601>
Branch: feature/arch-followup-stream-c-extension-restructure
Task: setup
Status: DONE
Last commit: <main HEAD sha + first line>
Tests: N/A
Notes: Worktree at /home/alee/Sources/relicario.arch-followup-stream-c. Synthesis + DEV-C notes + DEV-B boundary section absorbed. Awaiting Plan C at docs/superpowers/specs/2026-05-04-extension-restructure-design.md.
```
3. **Also emit a `## QUESTION TO PM`** about the in-flight uncommitted edits to `vault.ts` / `vault.css` / `glyphs.ts` on main:
```
## QUESTION TO PM — DEV-C
Time: <iso8601>
Context: setup, before Phase 1
Options: A: PM/user commits or stashes the in-flight v0.5.x polish on main before I start, so my worktree has a stable baseline. B: I proceed and rebase/merge those changes at PR time. C: PM defers Stream C until the in-flight work is committed.
Recommended: A — clean baseline avoids merge churn during the largest plan in the bundle.
Blocker: no — I can read the plan and start Phase 1 (P1.6 state.ts typing) which doesn't touch the in-flight files. Resolution needed before Phase 2 (P1.5 vault.ts split).
```
4. **Wait** for the PM's `## DIRECTIVE TO DEV-C` with `Action: PROCEED` and the plan path.
5. Read the plan, then start Task 1 using `superpowers:subagent-driven-development`. Phase 1 is P1.6 (state.ts typing) — finish it cleanly before P1.4 / P1.5.

View File

@@ -0,0 +1,133 @@
# Planning Kickoff Prompt — Architecture-Review Follow-up
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are an architect drafting **three implementation plans** that follow up on the whole-codebase architecture review committed to `main` on 2026-05-04 (`061facd docs(reviews): whole-codebase architecture audit 2026-05-04`). Three reviewers (DEV-A: Rust core; DEV-B: Rust consumers; DEV-C: TypeScript) walked the codebase; the PM synthesized 10 P1s plus a long P2/P3 tail. Your job is to convert those findings into three discrete, well-scoped plans that the user (or future agents) can execute.
This is **planning-only work.** Do not modify the codebase being planned. Do not commit. Do not ship anything. Each plan is a markdown file in `docs/superpowers/specs/` and that is the only output.
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Stay on `main`. Do not create branches or worktrees.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalization rules, autonomy defaults, never run git-destructive commands without asking).
- The working tree has uncommitted changes from in-flight v0.5.x work (manifests, vault.ts/css, glyphs, relay tooling, Cargo.toml version bumps). Treat them as "in flight, ignore" — do not include them in any plan.
## Required reading (in order)
1. `CLAUDE.md` — project rules (Spanish flourish, capitalization, autonomy)
2. `docs/superpowers/specs/2026-04-11-relicario-design.md` — foundational design spec (threat model, crypto pipeline, format)
3. `docs/superpowers/reviews/2026-05-04-architecture-review.md`**PM synthesis. This is the canonical source. Every plan below must trace its scope back to specific findings here.**
4. `docs/superpowers/reviews/2026-05-04-dev-a-notes.md` — DEV-A's full notes (Rust core)
5. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — DEV-B's full notes (CLI/server/WASM), especially the "Boundary notes for DEV-C" section
6. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — DEV-C's full notes (extension + relay), especially the "Boundary notes for DEV-B" section
Also skim two existing plan docs to match the format and tone:
- `docs/superpowers/specs/2026-05-02-v0.5.0-polish-harden-design.md`
- `docs/superpowers/specs/2026-05-03-v0.5.x-ux-polish-and-recovery-qr-design.md`
## What to produce
Three plan files, all under `docs/superpowers/specs/`:
### Plan A — Security & docs polish PR
**Filename:** `docs/superpowers/specs/2026-05-04-security-polish-design.md`
**Scope (drawn from synthesis):** P1.1 (`SessionHandle` `impl Drop` + Rust `wasm-bindgen-test` + extension `.free()` callsite audit), the partner JS-side fix at `service-worker/session.ts:26` (remove the `try { current.free() }` swallow), P1.7 (`recovery_qr.rs` documentation to match `crypto.rs`/`backup.rs` density), and the launcher fix DEV-C suspected at `tools/relay/start.sh:80` (4-window dev-c support; queue.test.ts assertion already fixed in `061facd`). Goal: one short PR, all-S-effort items, ships in under a day. This is the security-flavored quick win that goes first; nothing in B or C should depend on it.
### Plan B — CLI restructure
**Filename:** `docs/superpowers/specs/2026-05-04-cli-restructure-design.md`
**Scope:** P1.2 (split `crates/relicario-cli/src/main.rs` 2641 LOC into `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr}.rs` + `prompt.rs` + `parse.rs`, leaving `main.rs` as clap definitions + dispatcher), P1.3 (`helpers::git_run(repo, args, context)` with stderr capture; sweep the ~16 duplicated bail sites), P1.10 (migrate `parse_month_year`, `base32_decode_lenient`, `guess_mime` to `relicario-core` and re-export through `relicario-wasm` for the extension; pair with the core base32 dedup from DEV-A's P2), plus the in-scope CLI P2s (`build_*_item` helper compression, `refresh_groups_cache` discipline via `Vault::after_manifest_change`, `ParamsFile` dedup between `main.rs:2287` and `session.rs:114`, batched purge in `cmd_purge`/`cmd_trash_empty`). Sequencing matters here: the `main.rs` split must land first because every other P2 in this plan touches files that don't exist yet until the split happens. Goal: M-L effort, multi-day plan; "single biggest readability lift" per the synthesis.
### Plan C — Extension restructure
**Filename:** `docs/superpowers/specs/2026-05-04-extension-restructure-design.md`
**Scope:** P1.4 (`extension/src/setup/setup.ts` 1220 LOC: add `create_vault` and `attach_vault` SW messages; rewrite setup as a UI that posts those messages with gathered config + image bytes; convert the 6-step procedural wizard into a step-registry pattern `{ id, render, attach }[]`; add `clearWizardState()` on `beforeunload`), P1.5 (split `extension/src/vault/vault.ts` 1027 LOC into `vault-shell.ts` / `vault-sidebar.ts` / `vault-list.ts` / `vault-drawer.ts` / `vault-form-wrapper.ts`; lift the `vault_locked` RPC intercept into `shared/state.ts` so popup and vault use one channel; reset `state.drawerOpen` on non-list `renderPane`), P1.6 (concrete `StateHost` interface in `shared/state.ts` with `state: PopupState`, `navigate`, `popOutToTab`, `isInTab`, `openVaultTab`; generic `getState`/`setState` over `keyof PopupState`; double-registration guard + `__resetHostForTests` helper), P1.9 (extract duplicated SW router helpers — `loadDeviceSettings`/`loadBlacklist`/`saveBlacklist` to `service-worker/storage.ts`; `itemToManifestEntry` to `service-worker/vault.ts`), plus the in-scope extension P2s (inactivity-timer reset on content-callable messages; `state.gitHost` clear on session expiry; teardown helper extraction; `Promise.allSettled` in devices/trash; mutation-observer debounce in content/detector.ts; vault-tab status indicator from `get_vault_status` for the `relicario status` parity gap). Sequencing: P1.6 (state.ts typing) is a precondition for P1.4 and P1.5 because lifting `vault_locked` and adding setup-via-SW both push through that surface. Goal: largest plan, multi-day to multi-week.
## What's explicitly NOT in these three plans
- The full P2/P3 tail outside what's listed above. The synthesis doc is canonical; if a P2 isn't named in one of the three scopes above, it doesn't go in. Future plans can pick those up.
- WASM JS-naming snake_case → camelCase (DEV-B/DEV-C P3) — defer to a separate decision, not these plans.
- The 8 "Open architectural decisions" at the bottom of the synthesis — those are user-judgement calls, not implementation tasks.
- Anything that requires touching the in-flight uncommitted v0.5.x work (manifests, glyphs, vault.css, relay tooling beyond start.sh).
## Plan format (match the existing specs)
Each plan file should have, at minimum:
```markdown
# <Title> — Design
**Date:** 2026-05-04
**Status:** Proposed
**Source:** docs/superpowers/reviews/2026-05-04-architecture-review.md (P1.X, P1.Y, ...)
**Effort estimate:** S | M | L
## Summary
2-4 sentences: what this plan accomplishes and why it matters for the user's stated goal ("make this app's architecture logical and readable for someone who doesn't know Rust but wants to learn by tinkering").
## Findings addressed
Bullet list, each entry citing the synthesis P-tag, the reviewer who found it, and the file:line.
## Approach
The architectural shape of the work — what gets extracted, what gets created, what gets renamed. Include directory trees / module diagrams if it helps a reader follow the layout change.
## Implementation phases
Numbered phases. Each phase:
- **Goal:** one-sentence outcome
- **Changes:** specific files touched, new files created, with paths
- **Tests:** what gets added or moved (synthetic fixtures only — no binary blobs, per project convention)
- **Effort:** S/M/L for the phase
- **Depends on:** other phases, or "none"
## Risks and mitigations
What can break, especially across the CLI/extension parity boundary. Cite specific findings.
## Out of scope
Explicit list of adjacent things this plan does NOT touch.
## Done criteria
Checklist a reviewer can use to confirm the plan shipped.
```
Mirror the tone and depth of `2026-05-02-v0.5.0-polish-harden-design.md` and `2026-05-03-v0.5.x-ux-polish-and-recovery-qr-design.md`. Use the same heading conventions.
## Execution approach
**Use subagents.** Per the user's standing preference (CLAUDE.md memory: "Default to subagent-driven execution — for any multi-task plan use subagent-driven mode without asking"), drafting these plans is parallel work. Spawn three `Plan` subagents in parallel (single message, three tool calls), one per plan file. Each subagent reads the same shared inputs (synthesis + relevant notes file(s)), then writes only its assigned plan file. Plan B and Plan C subagents should each receive the relevant cross-boundary section of the *other* reviewer's notes ("Boundary notes for DEV-C" goes to Plan C's drafter; "Boundary notes for DEV-B" goes to Plan B's drafter) so the parity boundary is respected.
After the three subagents return, do a coherence pass yourself:
- Confirm Plan A doesn't depend on B or C
- Confirm Plan B's `parse_month_year`/`base32` migration to core is reachable from Plan C's WASM consumers (or note explicitly that Plan C will pick up the WASM exports in a later phase)
- Confirm Plan C's setup-via-SW migration cites the same `create_vault`/`attach_vault` message names everywhere
Each subagent prompt **must** start with `cd /home/alee/Sources/relicario` (project memory rule — without the force-cd, subagents may write to the wrong tree).
## Hard constraints
- **Read-only on the codebase being planned.** No `cargo`, `bun`, or any other write commands beyond writing the three plan files.
- **No commits.** The user commits when ready.
- **No git operations.** Don't even `git status` unless you have a specific reason.
- **Three files, no fewer, no more.** If a finding doesn't fit any of the three scopes above, leave it out — future plans handle it.
- **Spanish flourish in replies (1-2 phrases per reply with `[translation]` brackets), per CLAUDE.md.** Do not put Spanish into the plan files themselves — those are project artifacts.
## Done criteria
Before posting your final summary:
- [ ] All three plan files exist under `docs/superpowers/specs/` with the exact filenames specified above
- [ ] Each plan cites at least one specific P1 from the synthesis in its "Findings addressed" section
- [ ] Each plan has phases, each phase has effort, each phase names specific files
- [ ] Plan A is independent (no dependencies on B or C)
- [ ] Plan B and Plan C call out the parity-relevant cross-references explicitly
- [ ] You did NOT modify any code, run any test, or commit anything
- [ ] You ask the user whether to commit the three plan files (do not commit unprompted)
## First action
1. Read the synthesis (`docs/superpowers/reviews/2026-05-04-architecture-review.md`) end-to-end. Internalize the 10 P1s and the cross-cutting themes.
2. Skim the three per-reviewer notes files for the file:line context the synthesis abbreviates.
3. Skim the two existing plan docs above to absorb the format.
4. Tell the user what you absorbed in 3-5 sentences.
5. Spawn three `Plan` subagents in parallel with the scopes specified above.
6. Do the coherence pass.
7. Ask the user whether to commit the three plan files.

View File

@@ -0,0 +1,211 @@
# PM Kickoff Prompt — Architecture Review Followup (2026-05-04)
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are the **project manager** for the Relicario architecture-review-followup work. Three senior developers report to you, each working in their own terminal on a parallel feature branch. The user runs all four terminals.
This release has no version tag — it's a structural-cleanup bundle from the 2026-05-04 architecture audit (commit `061facd`). The goal is to make the codebase uniformly readable for a smart developer who doesn't know Rust but wants to learn by tinkering. There is no merge freeze, no CHANGELOG entry needed, and no tag at the end unless the user requests one.
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Branch: stay on `main`. Do not check out feature branches.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalize "Relicario", default to "yes"/recommended, never run git-destructive commands without asking, default to subagent-driven execution).
- **Working-tree note:** main has uncommitted polish changes from in-flight post-v0.5.1 work (glyphs/vault/relay/manifests/Cargo.toml version bumps, plus the four `architecture-review-*-prompt.md` files this session is generating). The synthesis explicitly tags these "in flight, ignore" — none of the three plans should include them. Also: Stream C touches `extension/src/vault/vault.ts`, `vault.css`, and `shared/glyphs.ts` which currently have uncommitted edits on main. Surface this to the user before unlocking DEV-C; either commit/stash the in-flight changes or note that C will need to merge them in at PR time.
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/reviews/2026-05-04-architecture-review.md`**PM synthesis. This is the canonical source. Every plan must trace its scope back to specific findings here.**
3. `docs/superpowers/reviews/2026-05-04-dev-a-notes.md` — full DEV-A notes (Rust core)
4. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — full DEV-B notes (CLI/server/WASM), especially the "Boundary notes for DEV-C" section
5. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — full DEV-C notes (extension + relay), especially the "Boundary notes for DEV-B" section
6. `docs/superpowers/specs/2026-05-02-v0.5.0-polish-harden-design.md` and `docs/superpowers/specs/2026-05-03-v0.5.x-ux-polish-and-recovery-qr-design.md` — format reference for the plan docs you will draft
## Stream overview
| Stream | Branch | Owner | Plan file (to be drafted) | Items |
|--------|--------|-------|---------------------------|-------|
| A — Security & docs polish | `feature/arch-followup-stream-a-security-polish` | DEV-A | `docs/superpowers/specs/2026-05-04-security-polish-design.md` | P1.1, JS free-swallow fix, P1.7, P1.8 |
| B — CLI restructure | `feature/arch-followup-stream-b-cli-restructure` | DEV-B | `docs/superpowers/specs/2026-05-04-cli-restructure-design.md` | P1.2, P1.3, P1.10 + 4 in-scope CLI P2s |
| C — Extension restructure | `feature/arch-followup-stream-c-extension-restructure` | DEV-C | `docs/superpowers/specs/2026-05-04-extension-restructure-design.md` | P1.4, P1.5, P1.6, P1.9 + in-scope ext P2s |
## Your authority
- Approve or deny scope changes from devs
- Review and merge PRs from each stream's feature branch
- **Draft the three plan docs as your first hands-on action.** This is the single biggest piece of work you own personally.
- Edit `docs/`, `CLAUDE.md`, or other doc artifacts as needed; do not write feature code
## Your boundaries
- Don't write feature code yourself. Edits to docs / `CLAUDE.md` are fine.
- Don't deviate from the synthesis scope without user approval.
- Don't merge a PR until the dev says `REVIEW-READY` and you've run `gh pr diff` to confirm.
- Don't tag (none planned for this work).
- Project rule: ask the user before any git-destructive op (`git push --force`, `git reset --hard`, `git branch -D`, `rm -rf`).
## Cross-stream coordination
- **Stream A is independent** — no dependencies on B or C. Merge first if it's ready.
- **Stream B's parser→core migration** (`parse_month_year`, `base32_decode_lenient`, `guess_mime` + the base32 dedup from DEV-A's P2) produces new `relicario-core` functions and re-exports them through `relicario-wasm`. Stream C does NOT need to consume these in this round; the plan should document the new WASM surface so a future round picks it up.
- **Stream C's internal sequencing**: P1.6 (`shared/state.ts` typing) must land before P1.4 (setup-via-SW migration) and P1.5 (`vault.ts` split). This is internal to Plan C, not a cross-stream concern.
- **No interface contracts between streams** that require pre-work coordination beyond the plan-drafting itself. Once plans are written and committed, all three DEVs can run fully in parallel.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; `from` is always `"pm"` for you
- `read_messages(for)` — drain your inbox; call with `for="pm"` before each action
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. After sending any directive, call `post_message(from="pm", to="dev-X", kind="directive", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session (this happens when the relay server was not running when your session opened), use the Python shim instead:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"pm","to":"dev-a","kind":"directive","body":"..."}'
python3 call.py read_messages '{"for":"pm"}'
```
## Coordination protocol
You are one of four terminals. With the relay server running, use `post_message` / `read_messages` directly — you do not need the user to copy-paste messages. Call `read_messages(for="pm")` before every action.
**You receive:** `## STATUS UPDATE — DEV-<letter>` or `## QUESTION TO PM — DEV-<letter>` blocks.
**You emit:** a `## DIRECTIVE TO DEV-<letter>` block — post it via `post_message` and also print it here so the user can see it. Format:
```
## DIRECTIVE TO DEV-<letter>
Time: <iso8601>
Action: PROCEED | HOLD | RESCOPE | REVIEW-COMPLETE | MERGE-APPROVED
Notes: <one paragraph max>
Next: <one concrete instruction or "continue plan">
```
When asked "status?" by the user, give a current rollup:
```
## RELEASE STATUS — Architecture Review Followup
Devs: <per-dev one-line state>
PM: <what you're working on>
Blockers: <list, or "none">
Next milestone: <e.g., "Plan A drafted", "DEV-B REVIEW-READY">
```
## Reviewing PRs
When a dev posts `Action: REVIEW-READY` with a PR URL:
1. `gh pr view <url>` to read description and CI status
2. `gh pr diff <url>` to read changes
3. Check the diff against the plan's "Done criteria" and the synthesis P-tags it claims to address
4. If green: post `Action: MERGE-APPROVED` and run `gh pr merge --merge` (preserve git history; no squash per project convention)
5. If red: post `Action: HOLD` with specific concerns the dev needs to address
Use the `superpowers:requesting-code-review` skill if you want a deeper independent review from a fresh subagent before approving.
## Pre-merge checklist (per stream)
Before each `MERGE-APPROVED`:
- [ ] Plan's "Done criteria" all checked
- [ ] Every synthesis P-tag the plan claims to address has a corresponding diff change
- [ ] Full test suite green for that stream's languages (`cargo test`, `bun run test` in `extension/`, etc.)
- [ ] No regression in CLI/extension parity (synthesis section "CLI/extension parity status")
- [ ] No emoji introduced anywhere in `extension/src/` (existing project rule)
## First action — draft the three plan docs
Before unlocking any DEV to start work, you must draft the three plan files. The DEVs will set up their worktrees and post acknowledgement STATUS UPDATEs, then wait for your `PROCEED` directive containing the path to their plan. Until the plans exist, the DEVs are blocked.
**Spawn three Plan subagents in parallel** (single message, three Plan tool calls — per CLAUDE.md memory rule "default to subagent-driven execution"). Each subagent prompt **must start with** `cd /home/alee/Sources/relicario` (project memory rule — without the force-cd, subagents may write to the wrong tree).
Each subagent reads the synthesis + relevant per-reviewer notes + format references, then writes ONLY its assigned plan file. None modify code, run tests, or commit.
### Plan A subagent scope
**Filename:** `docs/superpowers/specs/2026-05-04-security-polish-design.md`
**Effort:** S — under-a-day PR
**Items:**
- P1.1 — `impl Drop for SessionHandle { fn drop(&mut self) { session::remove(self.0); } }` in `crates/relicario-wasm/src/lib.rs:15-23` + `wasm-bindgen-test` covering construct → drop → confirm `SESSIONS` registry empty + extension `.free()` callsite audit confirming `wasm.lock(handle)` happens first regardless
- JS partner fix at `extension/src/service-worker/session.ts:26` — remove the `try { current.free() }` swallow so exceptions propagate (or log + counter)
- P1.7 — `crates/relicario-core/src/recovery_qr.rs` documentation pass: module-level `//!` summarizing format + KDF-input domain separation + parameter-pinning rationale; ASCII diagram of the 109-byte layout near the constants; doc-comment the four public functions; either replace `production_params()` with a `const` or comment the deliberate divergence from `KdfParams::default()`. Match the density of `crypto.rs` / `imgsecret.rs` / `backup.rs` / `tar_safe.rs`.
- P1.8 — `tools/relay/start.sh:80` launcher fix for the dev-c fourth window (queue.test.ts assertion already fixed in `061facd`; only the launcher line remains)
- **Independent** — no cross-plan dependencies. Plan A goes first.
### Plan B subagent scope
**Filename:** `docs/superpowers/specs/2026-05-04-cli-restructure-design.md`
**Effort:** M-L — multi-day. "Single biggest readability lift" per synthesis.
**Items:**
- P1.2 — split `crates/relicario-cli/src/main.rs` (2641 LOC) into `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr}.rs` + `prompt.rs` (six `prompt_*` helpers + `prompt_secret`) + `parse.rs` (the three pure parsers). `main.rs` keeps clap definitions + dispatcher (~470 lines).
- P1.3 — add `helpers::git_run(repo, args, context)` that uses `.output()` capturing stderr, prints captured stderr unmodified on failure, and embeds a human-readable `context`; sweep ~16 duplicated bail sites listed in the synthesis (`main.rs:601, 602, 610, 986, 988, 1477, 1480, 1767, 1897, 1900, 2432, 2438, 2533, 2540` and others)
- P1.10 — migrate `parse_month_year`, `base32_decode_lenient`, `guess_mime` to `relicario-core`; pair with DEV-A's P2 base32 dedup (extract `pub(crate) mod base32` with `encode_rfc4648` / `decode_rfc4648`, leave Steam's bespoke alphabet untouched); re-export through `relicario-wasm` via `#[wasm_bindgen]` so the extension can consume them in a later round
- In-scope CLI P2s:
- `build_*_item` helper compression with a `prompt_or_flag<T>` helper (`main.rs:664-921`)
- `refresh_groups_cache` discipline via `Vault::after_manifest_change(&self, manifest: &Manifest)` (7 manual sites at `main.rs:641, 998, 1123, 1197, 1414, 1432, 1474`)
- `ParamsFile` dedup between `main.rs:2287` (write side, has `aead`/`salt_path`/`format_version`) and `session.rs:114` (read side, only `kdf`) — single struct in core or shared session module
- Batched purge in `cmd_purge` and `cmd_trash_empty` (`main.rs:1476-1480, 1896-1900`) — 50-item purge currently does 150 git invocations
- **Sequencing:** the P1.2 main.rs split must land first because every other P2 in this plan touches files that don't exist yet until the split happens. Plan should call this out as Phase 1.
- **Receives:** the "Boundary notes for DEV-B" section from `dev-c-notes.md`
### Plan C subagent scope
**Filename:** `docs/superpowers/specs/2026-05-04-extension-restructure-design.md`
**Effort:** L — multi-day to multi-week. Largest plan.
**Items:**
- P1.4 — `extension/src/setup/setup.ts` (1220 LOC): add `create_vault` and `attach_vault` SW messages; rewrite setup as a UI that posts those messages with gathered config + image bytes; convert the 6-step procedural wizard into a step-registry pattern `{ id, render, attach }[]`; add `clearWizardState()` bound to `beforeunload` and to "return to step 0" so abandoned wizards don't persist sensitive material. Setup must stop importing `relicario-wasm` directly.
- P1.5 — split `extension/src/vault/vault.ts` (1027 LOC) into `vault-shell.ts` / `vault-sidebar.ts` / `vault-list.ts` / `vault-drawer.ts` / `vault-form-wrapper.ts`, leaving `vault.ts` to own only routing and state. Lift the `vault_locked` RPC intercept into `shared/state.ts` (or a wrapper around `sendMessage`) so popup and vault use one path; reset `state.drawerOpen` at the start of `renderPane` for non-list views.
- P1.6 — concrete `StateHost` interface in `shared/state.ts`: `state: PopupState`, `navigate: (view: View) => void`, `popOutToTab(): void`, `isInTab(): boolean`, `openVaultTab(hash?: string): void`. Make `getState`/`setState` generic over `keyof PopupState`. Throw on `registerHost()` re-register; export `__resetHostForTests()`.
- P1.9 — extract `loadDeviceSettings` / `loadBlacklist` / `saveBlacklist` from both router files to `service-worker/storage.ts`; move `itemToManifestEntry` (17-line projection) to `service-worker/vault.ts`. Import from both routers.
- In-scope extension P2s:
- Inactivity-timer reset on content-callable messages (`service-worker/index.ts:76-78`)
- Null `state.gitHost` alongside `state.manifest` on session expiry (`service-worker/index.ts:51-58`)
- Teardown helper extraction (`settings.ts:56-65` and `settings-vault.ts:15-22``teardownSettingsCommon()`)
- `Promise.allSettled` in `devices.ts:47-50` and `trash.ts:39-46`
- MutationObserver debounce in `content/detector.ts:96-103`
- Vault-tab status indicator from new `get_vault_status` SW message returning `{ ahead, behind, lastSyncAt, pendingItems }` (closes the `relicario status` parity gap)
- **Sequencing:** P1.6 (state.ts typing) is a precondition for P1.4 and P1.5 — both push through the StateHost surface. Plan should call this out as Phase 1.
- **Receives:** the "Boundary notes for DEV-C" section from `dev-b-notes.md`. Should also document the new WASM surface that Plan B exposes (parsers + base32 dedup) so a future round picks them up; explicitly do NOT consume them this round.
### Format reference
All three plans match the structure of `2026-05-02-v0.5.0-polish-harden-design.md`:
- `# <Title> — Design`
- Date / Status / Source (cite synthesis P-tags) / Effort estimate
- Summary (2-4 sentences)
- Findings addressed (bullet list, each citing P-tag + reviewer + file:line)
- Approach (architectural shape; module diagrams or directory trees if it helps)
- Implementation phases (numbered; each with Goal, Changes, Tests, Effort, Depends-on)
- Risks and mitigations
- Out of scope
- Done criteria (reviewer checklist)
### After the subagents return
1. **Coherence pass:**
- Confirm Plan A doesn't depend on B or C
- Confirm Plan B's `parse_month_year`/`base32` migration to core is reachable from Plan C's WASM consumers (or that Plan C explicitly notes deferred consumption)
- Confirm Plan C's setup-via-SW migration cites the same `create_vault` / `attach_vault` message names everywhere
- Confirm no plan touches the in-flight uncommitted v0.5.x work (vault.ts, vault.css, glyphs.ts, manifests, relay tooling beyond start.sh, Cargo.toml version bumps)
2. **Ask the user whether to commit the three plan files** (do not commit unprompted — there are unrelated uncommitted changes on main).
3. Once committed (or the user says "ship without committing"), post opening directives to all three devs:
- Confirm their plan path
- PROCEED to start Task 1
4. Wait for acknowledgement STATUS UPDATEs from all devs before clearing the queue.
## First action
1. Call `read_messages(for="pm")` to drain any early inbox messages.
2. Read the synthesis end-to-end. Internalize the 10 P1s and the cross-cutting themes.
3. Skim the three per-reviewer notes for the file:line context the synthesis abbreviates.
4. Skim the two existing plan docs above to absorb the format.
5. Emit a `## RELEASE STATUS` block confirming context absorbed; flag the in-flight uncommitted main state (vault.ts/glyphs.ts/etc.) for the user.
6. Spawn three `Plan` subagents in parallel with the scopes specified above.
7. Do the coherence pass.
8. Ask the user whether to commit the three plan files.
9. Post opening directives to all three devs unlocking their work.

View File

@@ -0,0 +1,168 @@
# PM Kickoff Prompt — Architecture Review (whole codebase)
Paste everything below the `---` line into a fresh Claude Code terminal as the first user message.
---
You are the **project manager** for Relicario's whole-codebase architecture audit (2026-05-04). Three senior reviewers report to you, each working in their own terminal on a partition of the codebase. The user runs all four terminals; the relay server routes messages.
This is **not** a feature release — it is a one-shot architecture review. The user's stated goal: *"I really want to make this app's architecture logical. I don't know Rust but I want to be able to read and understand the code and learn by tinkering with it."* Treat that goal as the primary lens for everything: reviews are valuable when they reduce confusion for a smart non-Rust reader; they are not valuable when they restate what's already obvious.
## Setup
- Working directory: `/home/alee/Sources/relicario`
- Stay on `main`. **Do not check out branches, do not create worktrees.** This is a review-only operation. The PM may edit the synthesis doc; reviewers do not edit code.
- Today: 2026-05-04. Project rules in `CLAUDE.md` apply (Spanish flourish in replies, capitalization rules, autonomy defaults, never run git-destructive commands without asking).
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"pm"`
- `read_messages(for)` — drain your inbox; call with `for="pm"` before each action
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm, dev-a, dev-b, dev-c`. Use these instead of asking the user to copy-paste. After sending any directive, call `post_message(from="pm", to="dev-X", kind="directive", body="...")`.
**Fallback:** If the relay MCP tools are not registered in your session, use the Python shim:
```bash
cd /home/alee/Sources/relicario/tools/relay
python3 call.py post_message '{"from":"pm","to":"dev-a","kind":"directive","body":"..."}'
python3 call.py read_messages '{"for":"pm"}'
```
## Required reading (in order)
1. `CLAUDE.md` — project rules
2. `docs/superpowers/specs/2026-04-11-relicario-design.md` — foundational spec (threat model, crypto pipeline, format)
3. `docs/superpowers/coordination/architecture-review-dev-a-prompt.md` — DEV-A's scope (Rust core)
4. `docs/superpowers/coordination/architecture-review-dev-b-prompt.md` — DEV-B's scope (CLI, server, WASM)
5. `docs/superpowers/coordination/architecture-review-dev-c-prompt.md` — DEV-C's scope (TS extension + relay)
You should NOT walk every file yourself — the reviewers do that. Your job is to coordinate, then synthesize.
## Partition
| Reviewer | Scope | Lens |
|----------|-------|------|
| DEV-A | `crates/relicario-core/` | Crypto correctness, API ergonomics, naming for newcomers |
| DEV-B | `crates/relicario-{cli,server,wasm}/` | Layering on top of core, command surface, session, WASM bridge |
| DEV-C | `extension/`, `tools/relay/` | Extension architecture, popup ↔ SW ↔ content boundary, CLI/extension parity, relay |
## Your authority
- Approve or deny scope changes from reviewers (in this context: e.g. "DEV-A wants to also look at WASM" — usually deny, since DEV-B has it)
- Read each reviewer's notes file (`docs/superpowers/reviews/2026-05-04-dev-{a,b,c}-notes.md`) as they're updated
- Cross-reference findings to identify cross-cutting issues (e.g. a core API ergonomics issue that bites the WASM consumer)
- **Write the synthesis doc** at `docs/superpowers/reviews/2026-05-04-architecture-review.md` — this is your hands-on work
- Decide P1/P2/P3 final priority across all reviewers' findings (their P-tags are inputs, not final)
- Resolve scope-boundary questions
## Your boundaries
- **Do not write feature code.** Edits to the synthesis doc are fine. Edits to other docs / `CLAUDE.md` are fine if they're directly informed by the review (e.g. clarifying a project rule that's actually unwritten).
- Do not modify the codebase being reviewed. The reviewers don't either; act as a backstop on this rule.
- Do not redirect a reviewer mid-stream without good reason. They are doing depth work; context-switching is expensive.
- Do not synthesize prematurely. Wait for at least two reviewers to post `Phase: REVIEW-COMPLETE` before opening the synthesis doc. (You can pre-skim notes earlier, but don't write conclusions.)
- Project rule: ask the user before any git-destructive op.
## Coordination protocol
**Before each action:** `read_messages(for="pm")`.
**You receive:** `## STATUS UPDATE` and `## QUESTION TO PM` blocks from `dev-a`, `dev-b`, `dev-c`.
**You emit:** directives via `post_message(from="pm", to="dev-X", kind="directive", body="...")`. Body format:
```
## DIRECTIVE TO DEV-<letter>
Time: <iso8601>
Action: PROCEED | HOLD | RESCOPE | ANSWER | REVIEW-ACKED
Notes: <one paragraph max>
Next: <one concrete instruction>
```
**Status rollup** (when asked "status?" by the user):
```
## REVIEW STATUS — Architecture Audit 2026-05-04
DEV-A: <phase, files covered, findings count>
DEV-B: <phase, crates covered, findings count>
DEV-C: <phase, areas covered, findings count>
PM: <current action — coordinating | reading-notes | synthesizing | done>
Open questions: <list, or "none">
Next milestone: <e.g., "DEV-A REVIEW-COMPLETE", "synthesis draft", "user review">
```
## Synthesis doc
When at least two reviewers have posted `Phase: REVIEW-COMPLETE` (and ideally all three), write the final review doc to `docs/superpowers/reviews/2026-05-04-architecture-review.md` with this structure:
```markdown
# Relicario — Whole-Codebase Architecture Review
**Date:** 2026-05-04
**Reviewers:** DEV-A (Rust core), DEV-B (Rust consumers), DEV-C (TypeScript)
**Synthesis:** PM
**Goal lens:** "Make this app's architecture logical and readable for a smart developer who doesn't know Rust but wants to learn by tinkering."
## Executive summary
4-6 sentences: overall architectural shape, the 3 most important things to address, the 3 strongest aspects worth preserving.
## Top-priority recommendations (P1)
For each P1 (across all three reviewers — your final prioritization, not theirs):
### P1.N — <short title>
**Area:** <core | cli | server | wasm | extension | shared | tooling | cross-cutting>
**File(s):** `<path>:<line>`
**Found by:** DEV-A | DEV-B | DEV-C | (multiple)
**Observation:** <one paragraph>
**Why it matters for the user's goal:** <how this confuses a Rust newcomer or otherwise blocks "learn by tinkering">
**Suggested direction:** <one paragraph; specific enough to act on, not so prescriptive that it's a plan>
**Effort:** S | M | L (rough — S = under an hour, M = half a day, L = a day or more)
## P2 recommendations
Same format, lighter detail.
## P3 / nice-to-have
Bullets.
## Cross-cutting themes
2-4 paragraphs on patterns that show up in multiple areas (e.g. "error messages are inconsistent across crates", "naming for crypto types is opaque", "TS message types could be generated from the WASM bindings"). These are usually the highest-leverage things — flag them clearly.
## What's strong (preserve)
3-5 specific things that are well-done and that future changes should not erode.
## CLI/extension parity status
A short summary of DEV-C's parity table: gaps, intentional gaps, gaps to close.
## Beginner-friendliness assessment
Pull together DEV-A's, DEV-B's, and DEV-C's beginner sections into one short story: where will the user trip first when trying to read/tinker, and what's the single most valuable change to make.
## Appendix: pointers to per-reviewer notes
- [DEV-A notes — Rust core](./2026-05-04-dev-a-notes.md)
- [DEV-B notes — Rust consumers](./2026-05-04-dev-b-notes.md)
- [DEV-C notes — TypeScript](./2026-05-04-dev-c-notes.md)
```
You may use the `superpowers:requesting-code-review` skill to get an independent second-pass on your synthesis before declaring done — but only after the synthesis is in draft.
## Done criteria
Before posting `## REVIEW STATUS — Architecture Audit 2026-05-04` with `PM: done`:
- [ ] All three reviewers posted `Phase: REVIEW-COMPLETE`
- [ ] All three notes files exist and are non-empty under `docs/superpowers/reviews/`
- [ ] `docs/superpowers/reviews/2026-05-04-architecture-review.md` exists and matches the structure above
- [ ] Every P1 in the synthesis has a file:line, an effort estimate, and a "why it matters for the user's goal" line
- [ ] Cross-cutting themes section is populated (not empty)
- [ ] You have explicitly asked the user whether to commit the review docs (do not commit unprompted)
## First action
1. Call `read_messages(for="pm")`.
2. Read the project rules and the spec.
3. Read each dev's prompt (links above) so you know exactly what scope each owns.
4. Emit a `## REVIEW STATUS — Architecture Audit 2026-05-04` block to the user, confirming setup.
5. Send opening directives to all three devs via `post_message`, each saying `Action: PROCEED` and reaffirming their scope (so it's recorded in the relay log).
6. Wait for acknowledgement status updates from all three before settling into coordination mode.

View File

@@ -69,8 +69,22 @@ Your vault.ts should call `renderSettings(pane)` when the `#settings` route is a
- `glyphs.ts` is the single source of truth. No inline Unicode literals at call sites.
- Don't merge to main. The PM owns merges.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-a"`
- `read_messages(for)` — drain your inbox; call with `for="dev-a"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm`, `dev-a`, `dev-b`, `dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-a")`. After emitting any status/question block: `post_message(from="dev-a", to="pm", kind="status"|"question", body="...")`.
## Coordination protocol
Before starting each task, call `read_messages(for="dev-a")` to drain your inbox.
When posting a status update, call `post_message(from="dev-a", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-A
Time: <iso8601>
@@ -1438,6 +1452,8 @@ gh pr create --title "feat: fullscreen 3-column layout + popup polish (Stream A)
- [ ] **Step 5: Post status to PM**
Call `post_message(from="dev-a", to="pm", kind="status", body="...")` with:
```
## STATUS UPDATE — DEV-A
Time: <iso8601>

View File

@@ -83,8 +83,22 @@ export function teardownSecuritySection(): void;
- Device sections read/write `chrome.storage.local`. Vault sections call `sendMessage` to the service worker.
- Don't merge to main. The PM owns merges.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-b"`
- `read_messages(for)` — drain your inbox; call with `for="dev-b"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm`, `dev-a`, `dev-b`, `dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-b")`. After emitting any status/question block: `post_message(from="dev-b", to="pm", kind="status"|"question", body="...")`.
## Coordination protocol
Before starting each task, call `read_messages(for="dev-b")` to drain your inbox.
When posting a status update, call `post_message(from="dev-b", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-B
Time: <iso8601>
@@ -1064,6 +1078,8 @@ gh pr create --title "feat: settings UX redesign — left-nav sectioned layout (
- [ ] **Step 6: Post status to PM**
Call `post_message(from="dev-b", to="pm", kind="status", body="...")` with:
```
## STATUS UPDATE — DEV-B
Time: <iso8601>

View File

@@ -72,8 +72,22 @@ export function teardownSecuritySection(): void;
DEV-B has a stub. Your Task 9 provides the real implementation.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; your `from` is always `"dev-c"`
- `read_messages(for)` — drain your inbox; call with `for="dev-c"` before each task
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm`, `dev-a`, `dev-b`, `dev-c`. Use these instead of asking the user to copy-paste. Before starting each task: `read_messages(for="dev-c")`. After emitting any status/question block: `post_message(from="dev-c", to="pm", kind="status"|"question", body="...")`.
## Coordination protocol
Before starting each task, call `read_messages(for="dev-c")` to drain your inbox.
When posting a status update, call `post_message(from="dev-c", to="pm", kind="status", body="...")` with the body:
```
## STATUS UPDATE — DEV-C
Time: <iso8601>
@@ -1349,5 +1363,5 @@ git commit -m "feat(ext/setup): recovery QR banner in final wizard step"
## Final steps
- [ ] Open PR: `gh pr create --title "feat: recovery QR (Stream C)" --base main`
- [ ] Post `## STATUS UPDATE — DEV-C / Action: REVIEW-READY` with PR URL to PM
- [ ] Call `post_message(from="dev-c", to="pm", kind="status", body="## STATUS UPDATE — DEV-C\nTime: <iso8601>\nTask: 13 of 13\nStatus: REVIEW-READY\nSummary: All 13 tasks complete. PR open. Recovery QR implemented end-to-end.\nNext: waiting for PM")`
- [ ] Respond to any PM review comments

View File

@@ -105,13 +105,23 @@ DEV-B stubs this interface in `settings-security.ts` immediately after receiving
3. No squash merges — git history is preserved per project rule.
4. No force pushes. Each dev opens a PR; PM reviews diff; PM merges with `gh pr merge --merge`.
## Relay server
A message-bus MCP server is running on `localhost:7331`. You have three native tools:
- `post_message(from, to, kind, body)` — push a message; `from` is always `"pm"` for you
- `read_messages(for)` — drain your inbox; call with `for="pm"` before each action
- `list_pending(for)` — check inbox count without consuming
Recipients: `pm`, `dev-a`, `dev-b`, `dev-c`. Use these instead of asking the user to copy-paste. After sending any directive, call `post_message(from="pm", to="dev-X", kind="directive", body="...")`.
## Coordination protocol
You are one of four terminals. The user relays messages.
**Before each action:** call `read_messages(for="pm")` to drain your inbox.
**You receive:** `## STATUS UPDATE — DEV-A/B/C` or `## QUESTION TO PM — DEV-X` blocks.
**You receive:** `STATUS UPDATE`, `QUESTION`, or `status` kind messages from `dev-a`, `dev-b`, `dev-c`.
**You emit:** a `## DIRECTIVE TO DEV-X` block. Format:
**You emit:** directives via `post_message(from="pm", to="dev-X", kind="directive", body="...")`. The body should follow this format:
```
## DIRECTIVE TO DEV-A (or B or C)
@@ -162,4 +172,9 @@ Before tagging v0.5.1:
## First action
After reading: post a `## RELEASE STATUS — v0.5.1` block, then post your first directive to all three devs simultaneously — confirming the AB and BC interface contracts above. Wait for devs to acknowledge before instructing them to proceed with their task lists.
1. Call `read_messages(for="pm")` to drain any early inbox messages.
2. Emit a `## RELEASE STATUS — v0.5.1` block to the user.
3. Call `post_message(from="pm", to="dev-a", kind="directive", body="...")` — confirming the AB interface contract.
4. Call `post_message(from="pm", to="dev-b", kind="directive", body="...")` — confirming both the AB and BC interface contracts, and the `settings-security.ts` stub instruction.
5. Call `post_message(from="pm", to="dev-c", kind="directive", body="...")` — confirming the BC interface contract.
6. Wait for acknowledgement status messages from all three before instructing them to proceed.