# Dev B Kickoff Prompt — arch-followup Plan B Paste everything below the `---` line into a fresh Claude Code terminal as the first user message. --- You are a **senior developer** owning Plan B for the arch-followup "architecture-review followups" release train. Plan B is the **CLI restructure** — the "single biggest readability lift" per the synthesis. M-L effort, multi-day. It splits `crates/relicario-cli/src/main.rs` (2641 LOC) into a `commands/` folder + `prompt.rs` + `parse.rs`, then layers on the duplicated git-error UX consolidation, manifest-after-mutation cache discipline, `ParamsFile` dedup, batched purge, and the migration of pure parsers (and a third copy of base32) into `relicario-core` with WASM re-exports. Eight phases. A PM in another terminal coordinates you with Dev-A (security & docs polish) and Dev-C (extension restructure). With the relay server running, you communicate via `post_message` / `read_messages` directly — no user copy-paste needed. If the relay MCP tools are not registered in your session, use the Python shim fallback (see **Relay server** section below). ## Setup (do this first) ```bash cd /home/alee/Sources/relicario git fetch git checkout main git pull git worktree add ../relicario-plan-b -b feature/2026-05-04-b-cli-restructure cd ../relicario-plan-b pwd # should print /home/alee/Sources/relicario-plan-b (or similar absolute path) ``` **ALL subsequent work happens in `/home/alee/Sources/relicario-plan-b`**. Force-cd subagents into this directory — the project's `CLAUDE.md` memory rule explicitly requires that subagent prompts MUST start with `cd /home/alee/Sources/relicario-plan-b` so subagents don't accidentally commit to main. This is non-negotiable. Today: 2026-05-04. Project rules in `CLAUDE.md` apply. ## 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"}' ``` ## Required reading (in order) 1. `CLAUDE.md` — project rules (Spanish flourish in chat replies only, capitalization, autonomy defaults, CLI/extension parity philosophy) 2. `docs/superpowers/reviews/2026-05-04-architecture-review.md` — synthesis (your scope is **P1.2, P1.3, P1.10 + the in-scope CLI P2s only**) 3. `docs/superpowers/specs/2026-05-04-cli-restructure-design.md` — your plan, execute phase by phase 4. `docs/superpowers/reviews/2026-05-04-dev-b-notes.md` — DEV-B's full notes (your primary source for line-level context — the synthesis abbreviates) 5. `docs/superpowers/reviews/2026-05-04-dev-c-notes.md` — read **only** the "Boundary notes for DEV-B" section near the end (cross-boundary contracts you must respect when designing the WASM exports for Phase 8) You do NOT need to read Plan A or Plan C in detail. If a coordination question arises, skim Plan C's "Risks → WASM boundary coordination" paragraph (it cites your Phase 8 explicitly). ## Execution mode Use **subagent-driven-development** (per project memory's default for any multi-task plan). Invoke `superpowers:subagent-driven-development` and follow it: fresh subagent per phase, two-stage review between phases. **Every subagent prompt MUST start with**: ``` cd /home/alee/Sources/relicario-plan-b ``` …before any other instruction. This is non-negotiable per project memory. **Sequencing matters.** Phase 1 (the mechanical `main.rs` split) is the precondition for every other phase — phases 2-6 touch files that don't exist yet until phase 1 lands. Do NOT start phase 2 until phase 1's `cargo test --workspace` is green and a checkpoint commit is in place. ## Your scope and boundaries **In scope:** - Phase 1 — Mechanical split of `main.rs` into `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr,init,generate,rate}.rs` + `prompt.rs` + `parse.rs` - Phase 2 — `helpers::git_run` + sweep of the 16 `bail!("git X failed")` sites - Phase 3 — `prompt_or_flag` and `build_*_item` compression - Phase 4 — `Vault::after_manifest_change` + sweep of the 7 `refresh_groups_cache` sites - Phase 5 — Single canonical `ParamsFile` (one definition shared between init writer and unlock reader) - Phase 6 — Batched purge in `cmd_purge` and `cmd_trash_empty` (3 git invocations for an N-item purge instead of 3N) - Phase 7 — Migrate `parse_month_year` / `base32_decode_lenient` / `guess_mime` to `relicario-core` + `pub(crate) mod base32` (closes DEV-A's three-base32-impls finding) - Phase 8 — WASM exports for the migrated parsers + `extension/src/wasm.d.ts` mirror **Out of scope:** anything in Plan A (security/docs polish — Drop impl, recovery_qr docs, relay launcher) or Plan C (extension restructure — setup.ts SW migration, vault.ts split, StateHost typing, SW router dedup). The CLI P3 nits (let _ = entry pattern, Lock subcommand visibility, Display for ItemType, helpers::relicario_dir adoption sweep, gitea Client per-call construction, edit_and_history.rs scripted prompts, dead test variable, three-test-env-var macro, cmd_recovery_qr_unwrap empty input check, Task 12 cleanup). Server findings (P2/P3 in DEV-B's relicario-server section). WASM findings beyond the parser exports needed for P1.10 (DEV-B's WASM P2 list — double-lookup, Vec clone, naming, concurrency primitive split). The 8 "Open architectural decisions". The WASM JS-naming snake_case → camelCase decision (deferred to a separate plan). If you trip over an out-of-scope issue or a new bug, file it via a `## QUESTION TO PM` block and keep moving. **Hard rules:** - Phase 1 is **mechanical** — no logic changes, no signature changes, no error-message reword. Run `cargo check -p relicario-cli` between every file extraction; existing CLI integration tests at `crates/relicario-cli/tests/*` must stay green throughout. They are the regression budget. - Phase 2's `git_run` switches from `.status()` (inherited stderr to TTY) to `.output()` (captured); the captured stderr MUST be printed to the user's stderr unmodified on failure. Do not silently swallow. - Phase 5's `ParamsFile` migration is on-disk-format-sensitive. Field names and types MUST match the existing `params.json` shape exactly; the round-trip test against a fixture string is required by the plan's Done criteria. - Phase 7 — `MonthYear::new` currently returns `Result<_, &'static str>` (DEV-A's P3 nit). The plan recommends re-wrapping the error in `MonthYear::parse` rather than migrating `new` to `RelicarioError`. If you'd rather migrate `new` for consistency, escalate to PM first — this is a cross-plan coordination concern. - Phase 8 keeps **snake_case** JS names (consistent with every existing export). Do not introduce camelCase for the three new exports. The snake_case → camelCase decision is deferred to a separate plan. - Phase 8 updates `extension/src/wasm.d.ts` and the new `#[wasm_bindgen]` exports in the same commit. Per DEV-C's boundary note, `wasm.d.ts` is hand-maintained — do not let the two surfaces drift even temporarily. - The Steam alphabet at `crates/relicario-core/src/item_types/totp.rs:13` is **intentionally non-RFC-4648** and must NOT move into the new `pub(crate) mod base32`. Add a neighbour comment per the plan. - 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 protocol You are one of multiple terminals. The relay routes messages between them. **At every phase boundary** (complete, blocked, or question): call `read_messages(for="dev-b")` first, then post your update via `post_message(from="dev-b", to="pm", kind="status"|"question", body="...")` and also print it here. Use this format: ``` ## STATUS UPDATE — DEV-B Time: Branch: feature/2026-05-04-b-cli-restructure Task: Status: STARTED | IN-PROGRESS | DONE | BLOCKED | REVIEW-READY Last commit: Tests: Notes: ``` **When you need PM input mid-task**: post via `post_message(kind="question")` with format: ``` ## QUESTION TO PM — DEV-B Time: Context: Options: Recommended: Blocker: yes | no (does work stop without an answer?) ``` **You'll receive**: `## DIRECTIVE TO DEV-B` blocks from the PM via relay (or relayed by user if relay is down). Acknowledge and act. ## Cross-plan coordination - **Plan C consumes your Phase 8 WASM exports** (`parse_month_year` / `base32_decode_lenient` / `guess_mime`) — but only as a deferred follow-up, NOT in Plan C's current execution. You ship the seam; Plan C does not wire the SW handlers in this train. Sequence Phase 8 to land before Plan C touches `wasm.d.ts` if both must touch it. - **`extension/src/wasm.d.ts` shared touchpoint with Plan C.** Plan C says it likely does NOT need to touch this file (its `create_vault`/`attach_vault` handlers reuse already-declared WASM entries). If Plan C does end up touching it, sequence Plan B's edits first and ask Plan C to rebase. - **Plan A's `impl Drop for SessionHandle`** is independent of you. Your `git_run` and parser-migration work doesn't touch the WASM crate's session module. No conflict. ## Authority within the plan You don't need PM permission to: - Execute phase-to-phase per the plan - Make implementation decisions consistent with the plan and synthesis - Add new tests, refactor your own code, fix bugs you introduce - Choose between optional approaches the plan calls out (e.g. whether `Vault::after_manifest_change` calls `save_manifest` internally vs renaming the existing method to `save_manifest_raw`) - Push commits to your feature branch You **do** escalate to PM when: - You discover the grep at the top of Phase 7 returns non-CLI consumers of `parse_month_year` / `base32_decode_lenient` / `guess_mime` / `base32_encode` / `decode_base32_totp` (the plan was drafted assuming zero non-CLI consumers; investigate) - A `cargo test --workspace` failure you can't reproduce locally - You want to deviate on the `MonthYear::new` consistency point (see Hard Rules) - You discover the `ParamsFile` round-trip is not field-compatible with the current on-disk format (rename, type change, etc.) - A test you can't make green after honest debugging (don't fudge — debug) - A discovered bug not in your plan - Anything destructive (per project rules) - Before opening the PR for review ## Final steps before REVIEW-READY Run the project's full validation: ```bash # From the worktree root (/home/alee/Sources/relicario-plan-b): cargo test --workspace cargo clippy --workspace --all-targets --no-deps cargo build -p relicario-wasm --target wasm32-unknown-unknown # Done-criteria sanity greps (all should return zero matches): grep -n 'bail!("git ' crates/relicario-cli/src/ grep -n 'refresh_groups_cache' crates/relicario-cli/src/ | grep -v 'session\.rs' # These should each return one match: grep -n 'struct ParamsFile' crates/relicario-cli/src/ # CLI smoke (post-split, end-to-end): cargo run -p relicario-cli -- --help ``` Then push and open the PR: ```bash git push -u origin feature/2026-05-04-b-cli-restructure gh pr create --base main --head feature/2026-05-04-b-cli-restructure --title "refactor(cli): split main.rs + git_run helper + parsers→core (Plan B)" --body "$(cat <<'EOF' ## Summary Architecture-review followup Plan B (CLI restructure — single biggest readability lift). Source: `docs/superpowers/specs/2026-05-04-cli-restructure-design.md`. - **P1.2** — `cli/main.rs` split from 2641 LOC into `commands/{add,get,list,edit,trash,backup,import,attach,settings,sync,status,device,recovery_qr,init,generate,rate}.rs` + `prompt.rs` + `parse.rs`. `main.rs` retains clap + dispatch only (~470 lines). - **P1.3** — `helpers::git_run(repo, args, context)` captures stderr; 16 duplicated bail sites collapsed. - **P1.10** — `parse_month_year` / `base32_decode_lenient` / `guess_mime` migrated to `relicario-core` (`MonthYear::parse`, `pub(crate) mod base32::{encode_rfc4648,decode_rfc4648_lenient}`, `mime::guess_for_extension`); also closes DEV-A's three-base32-impls finding by extracting the shared module. WASM exports added; `extension/src/wasm.d.ts` mirrored. - **CLI P2 cluster** — `prompt_or_flag` compression of `build_*_item`; `Vault::after_manifest_change` centralizes the `refresh_groups_cache` discipline (7 sites collapsed); single canonical `ParamsFile` shared between init writer and unlock reader; batched purge — a 50-item `trash empty` is now 3 git invocations instead of 150. ## Test plan - [ ] `cargo test --workspace` passes - [ ] `cargo clippy --workspace` silent - [ ] `cargo build -p relicario-wasm --target wasm32-unknown-unknown` clean - [ ] `grep -n 'bail!("git ' crates/relicario-cli/src/` returns zero matches - [ ] `grep -n 'refresh_groups_cache' crates/relicario-cli/src/` returns zero matches outside `session.rs` - [ ] `grep -n 'struct ParamsFile' crates/relicario-cli/src/` returns one match - [ ] New test asserts a multi-item `trash empty` produces exactly one new git commit - [ ] All existing CLI integration tests at `crates/relicario-cli/tests/*` still pass without modification ## Done criteria Per `docs/superpowers/specs/2026-05-04-cli-restructure-design.md` Done criteria — every checkbox. 🤖 Generated with [Claude Code](https://claude.com/claude-code) EOF )" ``` Emit a `## STATUS UPDATE` with `Status: REVIEW-READY` and the PR URL (post via `post_message`). ## First action After reading: emit a `## STATUS UPDATE` confirming setup complete (worktree created at `/home/alee/Sources/relicario-plan-b`, plan absorbed, on `feature/2026-05-04-b-cli-restructure`). Post it via `post_message(from="dev-b", to="pm", kind="status", body="...")`. Then start Phase 1 of your plan (mechanical split of `cli/main.rs`). Remember: phase 1 is mechanical — `cargo check` between every file extraction.