Phase 2 / PR #3 of the module refactor. Moves the approval and interactive-
question flows out of core and into src/modules/, wired through the response
dispatcher and delivery action registries.
New modules:
- src/modules/interactive/ — registers a response handler that claims
pending_questions rows, writes question_response to the session DB, wakes
the container. createPendingQuestion call stays inline in delivery.ts
(guarded by hasTable) per plan.
- src/modules/approvals/ — registers 3 delivery actions (install_packages,
request_rebuild, add_mcp_server), a response handler for pending_approvals
(including OneCLI action fall-through), an adapter-ready hook that boots
the OneCLI manual-approval handler, and a shutdown hook that stops it.
OneCLI implementation (src/onecli-approvals.ts) moves into the module.
Core lifecycle hooks added (narrow, not registries):
- onDeliveryAdapterReady(cb) in delivery.ts — fires when setDeliveryAdapter
runs (or immediately if already set). Used by approvals for OneCLI boot.
- onShutdown(cb) in index.ts — fires on SIGTERM/SIGINT. Used by approvals
for OneCLI teardown.
- getDeliveryAdapter() getter in delivery.ts — for live-flow adapter access
in registered delivery actions.
Core shrinks: delivery.ts 911 → 665 lines, index.ts 405 → 224 lines.
dispatchResponse now logs "Unclaimed response" instead of falling through
to an inline handler — the inline fallback moved into the two modules.
Migration files renamed to the module-<name>-<short>.ts convention:
- 003-pending-approvals.ts → module-approvals-pending-approvals.ts
- 007-pending-approvals-title-options.ts → module-approvals-title-options.ts
Migration.name fields unchanged so existing DBs treat them as already-applied.
Degradation verified: emptying the modules barrel builds clean and 137/137
tests pass. Actions would log "Unknown system action"; button clicks would
log "Unclaimed response".
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Additive change — existing code paths still run via inline fallbacks.
Prepares core for per-module extractions in PR #3 onward.
Four registries added with empty defaults:
- delivery action handlers (delivery.ts)
- router inbound gate (router.ts)
- response dispatcher (index.ts)
- MCP tool self-registration (container/agent-runner/src/mcp-tools/server.ts)
Default modules moved to src/modules/ for signaling:
- src/modules/typing/ (extracted from delivery.ts)
- src/modules/mount-security/ (moved from src/mount-security.ts)
Both are imported directly by core — no hook, no registry. Removal
requires editing core imports.
Migrator now keys applied rows by name (uniqueness) so module
migrations can pick arbitrary version numbers. Stored version column
is auto-assigned as an applied-order sequence.
sqlite_master guards added around core calls into module-owned tables
(user_roles, agent_destinations, pending_questions). No-ops today;
load-bearing after the owning modules are extracted.
MODULE-HOOK markers placed at scheduling's two skill-edit sites
(host-sweep.ts recurrence call, poll-loop.ts pre-task gate). PR #4
replaces the marked blocks when scheduling moves to its module.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>