type: meta

slug: arch-deepening

topic: Architecture deepening 15-25 (tray/account subsystem) via run-plan-codex

exec_mode: run-plan-codex

scheduler: dag-parallel

land_mode: pr

gate0_cmd: python3 -m pytest -q

codex_impl_effort: high

codex_review_effort: low

status_enum: BLOCKED PENDING WORKING WRITTEN REVIEWED COMMITTED

truth_rule: this file is ground truth for INTENT (goals/directions/task list); git is ground truth for DONE-NESS — reconcile statuses against git, never trust a COMMITTED line with no commit

refresh_how: native Read of THIS file — NEVER ctx_execute/ctx_search

refresh_what: meta + every goal/methodology/intent/direction/gated record + all WORKING and BLOCKED tasks

refresh_when:
wave boundary
any task status change
after a compaction system-reminder
before calling advisor

update_rule: on status change, rewrite that task's single line in place; append new tasks/session_memory as new lines

report_rule: at session end emit brief: done / blocked / deferred / canceled — NO next action

executor_notes: run-plan-codex reads: meta.base_branch, meta.gate0_cmd, meta.codex_impl_model/effort, meta.codex_review_model/effort; per task t.wave, t.files, t.blocked_by, t.seat. It IGNORES t.deps and meta.scheduler — cross-wave ordering is enforced purely by t.wave. base_branch is a fail-closed sentinel: setup HALTS until it is set to the reconciled ref.


type: goal

text: Turn shallow God-object-bound modules (Indicator, account_registry, routing) into deep modules with stable seams so the tray/account subsystem is testable through interfaces and AI-navigable; fix the fail-open routing bug and the divergent health-freshness bug as part of the relevant deepenings. Full audit scope 15-25.


type: methodology

text: Contract-first, behavior-preserving extraction. Each wave moves one concern behind a new non-GTK, unit-testable seam and re-points callers + tests, no user-visible change except the two explicit bug fixes. Refactors that break private-method-coupled tests MUST re-target the new seam in the same task, never weaken assertions to pass gate0. Full-suite gate0 (python3 -m pytest -q) per task = cumulative regression net.


type: intent

text: The refactor is worth doing only because it makes the subsystem testable and navigable; a green gate0 achieved by relaxing/deleting tests defeats the entire point. The codex review leg exists to reject that failure mode. Best-practice deepening, not hacky line-shuffling.


type: direction

verbatim: Reconcile with origin/main first


verbatim: i will run the session in another sesion, just prepare the plan


type: deferred

text: Do NOT invoke run-plan-codex from this session

reason: User will run the session elsewhere; this session only prepares the plan artifacts.


type: gated

category: input

needs: origin/main <-> local reconcile completed AND meta.base_branch set to the reconciled ref (currently sentinel RECONCILE-SET-BASE-BRANCH). Working tree clean on that base; uncommitted edits to indicator.py/cdx.py/tests committed into it. Re-verify per-task files after merge.

why: Audited targets (830-line indicator.py, account_registry.py shared-state ~185-319) live only on save-local-main-before-remote-dashboard-20260701, NOT on origin/main (diverged, 994-line indicator lineage). run-plan-codex branches from a committed ref and never sees uncommitted work; building on the wrong lineage would make W4 extract code that isn't there.

blast_radius: entire run builds on wrong tree if base_branch left unresolved/wrong

status: RESOLVED

answer: proceed: base_branch=save-local-main-before-remote-dashboard-20260701 (no merge from origin/main; audited targets only exist on local branch per this gate's own rationale). Pending edits (cdx.py, tests) committed at 0f26ba6 before setup. NOTE: user question timed out with no response — agent decided on timeout, not a user confirmation. This also means origin/main's 5 commits were NOT reconciled in, contradicting the earlier direction "Reconcile with origin/main first" (line 5) — needs user sign-off.

resolved_by: agent-on-timeout

source: author


type: task

desc: Move embedded tests out of production modules; make plain pytest collect the full suite (audit #26/#27/#31).

status: COMMITTED


desc: Add CONTEXT.md domain vocabulary + docs/adr/0001 (record-architecture-decisions) (audit #32/#33). Disjoint from w1.t1 -> parallel.


desc: HealthSnapshotStore: single owner of health-cache read/write/freshness/atomicity; absorb the 3 divergent freshness rules into one policy (audit #16 + freshness bug). Callers become thin.


desc: Fail-open routing fix: unknown-to-registry slug not selectable via optional known_slugs param (default None = current behavior); registry-checked seed_routing_rules (audit #23 + #10). File-local (no cdx/cld edits) -> disjoint from w2.t1, parallel.


desc: Tool-qualified account identity: AccountRef(tool, slug), neutral account_home field, tool-qualified tray keys so shared slugs across Codex/Claude don't collide (audit #19 + #8).


desc: Extract SharedCodexState (Codex-specific merge/symlink engine) out of the generic AccountRegistry (audit #18). Target code exists only on the local lineage -> depends on reconcile (g1).


desc: CommandRouter owns resolve->exec; ToolAdapter/CodexAdapter/ClaudeAdapter carry per-tool differences; kill the cdx:->cld: string leak; wire real known_slugs into RoutingResolver here (audit #17).


desc: Subprocess protocol adapters: CodexAppServer (JSON-RPC rate limits) + DeviceAuthProtocol (stream parse) as explicit modules with typed contracts (audit #22). Kept on LOCALITY grounds only, not pluggable.


desc: Scheduler seam: concurrency policy (daemon thread spawn, GLib idle dispatch, refresh-generation/pending bookkeeping) leaves Indicator (audit #25). First of the strictly-sequential indicator.py breakup.


desc: Tray view-model: build_tray_model(...) -> TrayModel derives title + menu-item state as pure data; GTK only renders (audit #24).


desc: Device-auth operation module: repair/add orchestration (process start, prompt read, commit/rollback, collision) emits FlowEvent iterators; tray only shows dialogs + renders events (audit #20).


desc: Indicator becomes a thin GTK adapter wiring Scheduler + TrayModel + DeviceAuthOperation + HealthSnapshotStore; test_indicator.py shrinks to public-surface wiring (audit #15).


note: run-plan-codex.js ignores t.deps and meta.scheduler; ordering is by t.wave only. deps here are documentation of real dependencies for humans/fix-rot. Within-wave tasks (W1, W2) are genuinely file-disjoint so same-wave parallel is safe.


note: gate0 runs in a raw bash -c outside RTK; meta.gate0_cmd is python3 -m pytest -q (bare pytest on PATH unverified there). Full suite chosen over per-file for cross-module regression coverage (~0.45s).


note: Highest risk W7-W10: test_indicator.py is private-method-coupled (~1909 lines). Failure mode = codex making gate0 green by relaxing/deleting tests. Review leg must reject; assertions move to new seam, never weaken.