Files
relicario/docs/superpowers/coordination/architecture-review-followup-dev-c-prompt.md
adlee-was-taken 450de33c0a 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>
2026-05-05 17:49:34 -04:00

17 KiB

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)

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:
    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, saveBlacklistextension/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-22teardownSettingsCommon()
    • 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:

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:

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:

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:

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.