Generated via release workflow (multi mode). Covers: - PM: Phase 3+4+6 oversight, relay wiring, pre-tag checklist - Dev-A: Phase 3 (setup wizard SW migration + step registry) - Dev-B: Phase 4 (vault.ts split) + Phase 6 (get_vault_status) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
12 KiB
Dev-B Kickoff Prompt — extension-restructure (Phase 4 + Phase 6)
For agentic workers: REQUIRED SUB-SKILL: Use
superpowers:subagent-driven-developmentto implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.
Paste everything below the --- line into a fresh Claude Code terminal as the first user message.
You are Dev-B for the Relicario extension-restructure release.
Goal: Own Phase 4 and Phase 6 in sequence. Phase 4 splits the 1027-LOC vault.ts monolith into five focused modules (vault-shell.ts, vault-sidebar.ts, vault-list.ts, vault-drawer.ts, vault-form-wrapper.ts) and lifts the vault_locked RPC intercept into shared/state.ts, building on the Phase 1 StateHost foundation that is already shipped. Phase 6 closes the CLI/extension parity gap by implementing the get_vault_status SW handler and wiring the sidebar status indicator — it depends on the vault-sidebar.ts module that Phase 4 produces.
Architecture: TypeScript extension only. No Rust crates touched. All new modules live in extension/src/vault/ (Phase 4) and extension/src/service-worker/ (Phase 6). The StateHost foundation (shared/state.ts, typed PopupState, __resetHostForTests) was shipped in Phase 1 and is already on main. Do not redo it.
Tech Stack: TypeScript, vitest + happy-dom, webpack, Rust core via WASM (no new WASM entry points needed).
Step 0 — Worktree setup (do this FIRST, before anything else)
git -C /home/alee/Sources/relicario worktree add /home/alee/Sources/relicario.ext-restructure-b -b feature/extension-restructure-phase-b
Then all subsequent work happens in /home/alee/Sources/relicario.ext-restructure-b.
ALL subagent prompts MUST begin with:
cd /home/alee/Sources/relicario.ext-restructure-b &&
Never rely on working-directory headers alone — subagents may commit to main if they do not force-cd into the worktree at prompt start.
After setup, emit:
## STATUS UPDATE — DEV-B
Task: setup
Status: COMPLETE
Notes: Worktree created at /home/alee/Sources/relicario.ext-restructure-b on branch feature/extension-restructure-phase-b. Baseline test count confirmed.
Next: Phase 4 Task 4.1
Post this update to the relay (see Relay section below).
Already-shipped context
Phases 1, 2, and 5 have been merged to main. The following are done — do not redo:
shared/popup-state.ts—View+PopupStatetypes extractedshared/state.ts— typedStateHostwithregisterHost,__resetHostForTests,sendMessagewrappershared/__tests__/state.test.ts— 7 StateHost testsservice-worker/storage.ts—loadDeviceSettings,saveDeviceSettings,loadBlacklist,saveBlacklist- Phase 5 P2 fixes (inactivity-timer invert,
Promise.allSettledin devices/trash, MutationObserver debounce,teardownSettingsCommon, WASM stub rounding-out)
Baseline: 389/389 vitest tests pass on main. You must maintain or grow this count. Never let tests regress.
Required reading
Before writing any code, read:
CLAUDE.md— project rules (always applies)docs/superpowers/plans/2026-05-30-extension-restructure.md— authoritative plan; Phase 4 and Phase 6 task details are defined thereextension/ARCHITECTURE.md— bundle structure, SW message protocol, component architectureextension/src/vault/vault.ts— the 1027-LOC monolith you will split (read it in full before Task 4.1)extension/src/shared/state.ts— shipped StateHost contract (Phase 4 liftsvault_lockedintosendMessagehere)
Execution mode
Use the superpowers:subagent-driven-development skill. Fresh subagent per task, two-stage review between tasks. Every subagent prompt MUST start with cd /home/alee/Sources/relicario.ext-restructure-b &&.
Scope
Phase 4 — Split vault.ts monolith (Tasks 4.1–4.7)
You own all seven tasks:
- Task 4.1 — Extract
vault-shell.ts: DOM scaffolding, color-scheme apply,onMessagewiring - Task 4.2 — Extract
vault-sidebar.ts: sidebar categories, debounced search, nav buttons, status slot wiring - Task 4.3 — Extract
vault-list.ts: list pane rendering and row rendering - Task 4.4 — Extract
vault-drawer.ts+ensureDrawerClosedForRoute+drawer-state.test.ts - Task 4.5 — Extract
vault-form-wrapper.ts:renderFormWrapped, sticky bar, header - Task 4.6 — Trim
vault.tsto ~200 LOC of routing + state (delete everything extracted above) - Task 4.7 — Lift
vault_lockedRPC intercept intoshared/state.tssendMessage+ writestate-vault-locked.test.ts
Phase 6 — CLI/extension parity: get_vault_status (Tasks 6.1–6.3)
Phase 6 depends on vault-sidebar.ts from Phase 4. Do not start Phase 6 until Phase 4 is complete and all tests pass.
- Task 6.1 — Implement
get_vault_statusSW handler inextension/src/service-worker/vault.ts+ writevault-status.test.ts - Task 6.2 — Create
vault-status.tsrenderer (sidebar-footer status indicator) + writestatus-indicator.test.ts - Task 6.3 — Wire the status indicator into
vault-sidebar.tssidebar footer
Out of scope
Phase 3 (Tasks 3.1–3.7) is owned by another developer. Do NOT touch setup.ts, setup/__tests__/setup.test.ts, or the SW create_vault / attach_vault handlers. If you need to coordinate on a shared file, post a question to the relay.
Hard rules
- Maintain or grow the 389-test baseline. No vitest regressions — ever.
- TDD for all new logic. Write the failing test first, then the implementation.
- Commit after each task (not each step — one logical commit per task, bundling its files).
- No
as anycasts. The typedStateHostcontract is in place; use it. - Do not push or open a PR until both phases are complete and the final test run passes.
- Do not merge to
main. The PM owns merges.
Relay
A message-bus server is running at localhost:7331. Your identity is from="dev-b".
Python shim (use this to call the relay):
cd /home/alee/Sources/relicario/tools/relay && python3 call.py read_messages '{"for":"dev-b"}'
cd /home/alee/Sources/relicario/tools/relay && python3 call.py post_message '{"from":"dev-b","to":"pm","kind":"status","body":"..."}'
Recipients: pm, dev-a, dev-b.
Before each task: call read_messages with {"for":"dev-b"} to drain your inbox.
After each status update: call post_message to relay your STATUS UPDATE block to pm.
STATUS UPDATE format
Use this format for every update — print it locally AND relay it to pm:
## STATUS UPDATE — DEV-B
Task: <task id, e.g. 4.1>
Status: COMPLETE | IN-PROGRESS | BLOCKED
Notes: <what was done, why the approach was taken, any surprise found — 3 sentences max>
Next: <next task id or "waiting for PM">
Emit IN-PROGRESS updates at meaningful moments: when a subagent is dispatched, a key architectural decision is made, a surprise is found, or a direction change occurs. Do not wait for phase boundaries.
Phase 4 task details
Refer to docs/superpowers/plans/2026-05-30-extension-restructure.md for the full step-by-step breakdown of each task. The plan is authoritative. Below is a summary of what each task produces to orient you before you read the plan:
Task 4.1 — vault-shell.ts
Extracts: the initVaultShell(container) bootstrapper, applyColorScheme(), document.addEventListener('message', ...) wiring. vault.ts imports initVaultShell and calls it at startup.
Task 4.2 — vault-sidebar.ts
Extracts: renderSidebar(container, state), debounced search input handler, category nav button click wiring, and a <div class="vault-sidebar__status"> slot at the footer (empty until Phase 6 Task 6.3). Exports renderSidebar and updateSidebarStatus(text: string).
Task 4.3 — vault-list.ts
Extracts: renderList(container, entries, state) and renderRow(entry, state). The list pane is a pure render function — no side effects beyond DOM mutation.
Task 4.4 — vault-drawer.ts + drawer tests
Extracts: openDrawer(view), closeDrawer(), renderDrawerContent(view, state), and ensureDrawerClosedForRoute(route) (closes the drawer automatically when navigating to list/unlock). Creates extension/src/vault/__tests__/drawer-state.test.ts covering the auto-close behavior.
Task 4.5 — vault-form-wrapper.ts
Extracts: renderFormWrapped(container, title, renderBody) — the sticky-header + save-bar scaffold used by add/edit/detail views.
Task 4.6 — Trim vault.ts to ~200 LOC
After extracting all the above, vault.ts should contain only: route dispatch (handleRoute), top-level state management (initVault, setState), and import wiring. Delete the extracted code. Run the full test suite to confirm nothing broke.
Task 4.7 — Lift vault_locked intercept into shared/state.ts
The pre-Phase-4 vault.ts has a vault_locked channel intercept inside its local sendMessage wrapper. Lift this into the sendMessage export in shared/state.ts (Phase 1 left a placeholder comment there). Write extension/src/shared/__tests__/state-vault-locked.test.ts that:
- registers a mock host
- dispatches a
sendMessagethat returns{ ok: false, error: 'vault_locked' } - asserts that
navigate('unlock')was called on the host - asserts the original rejection is re-thrown (or rethrown as appropriate per the existing intercept logic)
Phase 6 task details
Do not start Phase 6 until Phase 4 is fully committed and all 389+ tests pass.
Task 6.1 — get_vault_status SW handler
Add a get_vault_status case to extension/src/service-worker/vault.ts. The handler returns:
{
ok: true,
data: {
unlocked: boolean, // whether a session is active
vault_dir: string | null, // from cached state.vaultDir
git_host: string | null, // from cached state.gitHost
item_count: number, // manifest entry count or 0
}
}
Add get_vault_status to extension/src/shared/messages.ts as a new Request variant.
Write extension/src/service-worker/__tests__/vault-status.test.ts covering: unlocked path, locked path, and missing-vault path.
Task 6.2 — vault-status.ts renderer
Create extension/src/vault/vault-status.ts with:
export function renderVaultStatus(container: HTMLElement, status: VaultStatusData): void;
The renderer fills container with a one-line status indicator: a colored dot + short text (Unlocked · 42 items or Locked or No vault). Write extension/src/vault/__tests__/status-indicator.test.ts covering all three states with happy-dom.
Task 6.3 — Wire indicator into vault-sidebar.ts
At sidebar boot, call sendMessage({ type: 'get_vault_status' }) and pass the result to renderVaultStatus(statusSlot, data). Re-fetch on every setState call so the count stays current. The status slot element (<div class="vault-sidebar__status">) was created in Task 4.2.
Final verification
Before opening a PR, run:
cd /home/alee/Sources/relicario.ext-restructure-b && pnpm --filter extension test && pnpm --filter extension build
All tests must pass. Build must be clean. Post your final STATUS UPDATE to pm with Status: COMPLETE.
Opening the PR
Once both phases are complete and the final run passes:
gh pr create --base main --title "feat(extension): restructure Phase 4 (Tasks 4.1-4.7): extract vault-shell.ts; extract vault-sidebar.ts with debounced search; extract vault-list.ts; extract vault-drawer.ts + ensureDrawerClosedForRoute + drawer-state tests; extract vault-form-wrapper.ts; trim vault.ts to ~200 LOC routing+state; lift vault_locked intercept into shared/state.ts + state-vault-locked tests+Phase 6 (Tasks 6.1-6.3): implement get_vault_status SW handler + vault-status.test.ts; create vault-status.ts renderer + status-indicator tests; wire indicator into vault-sidebar.ts sidebar footer — Dev-B"
Return the PR URL in your final STATUS UPDATE.
First action
- Run the worktree setup command above.
- Confirm the baseline:
cd /home/alee/Sources/relicario.ext-restructure-b && pnpm --filter extension test 2>&1 | tail -5 - Emit STATUS UPDATE "setup complete" locally and relay it to
pm. - Begin Phase 4 Task 4.1 by reading
extension/src/vault/vault.tsin full, then dispatching a subagent.