Reviewer: GLM-5.1 (via Z.AI), running as Luci CLI session
Date: 2026-05-21
Plan reviewed: ~/workspace/reports/luci-control-room-runtime-independence-plan.md
Supporting docs reviewed:
- ~/workspace/agent-control-room/docs/runtime-independence.md
- ~/workspace/mission-control/docs/runtime-architecture-refresh.md
- scheduler.py (PROFILE_PROVIDER, PROFILE_META, _runtime_profile_defaults)
- mc_pickup.py (Larry provider state, defaults)
- mission-control/dispatch_policy.py (forbidden_runtime_profiles)
- MC ticket database (MC-3898, MC-3907)
The plan is well-structured, honest about current weaknesses, and has the right archural instincts: MC as durable source of truth, runtimes as swappable adapters, control room as governance layer not a second database. Phase 0 and Phase 1 are landed and real. The source-of-truth boundary rules (added after Lucienne's review) are the most important quality gate in the document.
The plan has several factual inaccuracies in its inventory section, one wrong MC ticket reference, and a few gaps where claims about code structure don't match what's actually deployed. These are fixable but should be corrected before Phase 3 work begins, since Phase 3 depends on accurate inventory.
Correct top-level principle. MC as the durable layer, runtimes as adapters, is the right abstraction. The core invariant diagram is clear and accurate.
Source-of-truth boundary is excellent. The "allowed / not allowed" lists for each directory are exactly the kind of guardrail that prevents control-room sprawl. The prohibition on duplicated live state and aspirational profile claims is particularly good.
Honest current-state assessment. The weaknesses section doesn't sugarcoat: docs are spread across too many places, runtime profiles aren't a clean portability layer, Hermes config can drift from active runtime. This honesty is valuable.
Phase 1 was executed correctly. The agent-control-room/ directory
exists with exactly the four files promised (README.md, shared/commands.md,
docs/runtime-independence.md, docs/webui-governance.md). No scope creep.
Gates are appropriate. Architecture/docs, code/runtime, UI, and secrets gates are all reasonable. The Atlas-style signoff requirement for canonical doc changes is correctly applied.
Deferred decisions are correctly deferred. Changing Hermes persistent default from grok-4.3, model/cost routing policy, Telegram home-channel contract — these are all correctly pushed past Phase 1.
The plan says "Mission Control tracking ticket: MC-3898" in three places (header, Phase 0 checklist, Immediate next actions). MC-3898 is actually "Confirm Padel Tuesday availability — resolve schedule conflict" (status: inbox). The real tracking ticket is MC-3907 ("Luci control room and runtime independence foundation", status: done).
Fix: Replace all MC-3898 references with MC-3907.
The plan (and the derived runtime-independence.md) list these scheduler
profiles:
claude_anthropic,claude_glm,claude_kimi,claude_minimax,direct_gemini,direct_anthropic_sdk,direct_mixed
The actual PROFILE_PROVIDER map in scheduler.py (line 131-144) contains:
claude_anthropic -> anthropic
claude_sonnet_medium -> anthropic
claude_opus_medium -> anthropic
claude_opus_1m_medium -> anthropic
claude_opus_1m_high -> anthropic
claude_glm -> glm
claude_kimi -> kimi
claude_minimax -> minimax
glm_api -> glm
kimi_api -> kimi
minimax_api -> minimax
grok_on_sub -> grok-on-sub
Issues:
- direct_gemini, direct_anthropic_sdk, direct_mixed do NOT exist in
PROFILE_PROVIDER. They appear in the runtime-profile honesty rule in
CLAUDE.md as sentinel values for tasks that bypass the claude CLI, but they
are not registered profiles the scheduler can dispatch to.
- claude_sonnet_medium, claude_opus_medium, claude_opus_1m_medium,
claude_opus_1m_high, glm_api, kimi_api, minimax_api, grok_on_sub
are all real profiles that the inventory omits.
The inventory lists 7 profiles. The code has 12. The phantom 3 aren't profiles at all. This matters because Phase 3 depends on accurate inventory.
Fix: Rebuild the profile inventory directly from PROFILE_PROVIDER keys
and PROFILE_META entries. Note which are CLI-backed vs direct-API-backed
(which is none currently — the direct_* sentinels exist only in the honesty
rule, not in the scheduler).
The plan says:
scheduler_profile: claude_anthropic
scheduler_cli_fallback_profile: claude_glm
worker_profile: claude_anthropic
default_profile: claude_anthropic
The static defaults in scheduler.py (lines 300-303) say:
scheduler_profile: claude_anthropic
worker_profile: claude_anthropic
default_profile: claude_anthropic
But _runtime_profile_defaults() (line 410+) dynamically resolves defaults
from the persistent model/provider. The static PROFILE_DEFAULTS dict is a
fallback, not the live truth. The plan should note this distinction.
Also, scheduler_cli_fallback_profile is not visible in the static defaults
— it may be derived elsewhere. The plan should say where.
The plan references ~/workspace/.state/runtime_profile_state.json as a live
override mechanism. This file does not exist on disk. The plan should note
that runtime profile state is currently all defaults with no overrides
applied, rather than implying the file is actively used.
The plan says Larry is at elmar@46.225.208.1. The runtime-independence.md
doc says elmar@46.225.208.1, not on Tailscale. This should be verified
before Phase 3 — if Larry has moved or is on Tailscale now, the docs are
misleading.
Phase 3 says "document backend/provider/model/tools/cost/fallback/smoke test"
for each profile. This is documentation work. What's missing is whether there
should be an actual adapter interface — a Python class or protocol — that
formalizes what "being a runtime adapter" means in code. Currently,
_apply_provider_profile_env() and _larry_runtime_config() are the closest
things to adapters, but they're just env-injection functions. The plan should
state whether Phase 3 is pure documentation or includes code abstraction.
Phase 5A lists six items, all as unchecked todos. This is the right level of detail for now. The key architectural risk — "replacing Luci Persistent with Hermes/OpenAI/Codex should not change Telegram routing semantics" — is correctly identified. But the plan should explicitly state that CCGram's single-poller constraint (from CLAUDE.md) is a hard dependency that any runtime swap must preserve.
Phase 4 is about cost routing, but the plan has zero cost data. There's no mention of current spend per profile, token costs, or even which profiles are expensive vs cheap. Phase 4 can't be evaluated without this baseline. The plan should at least note that cost data collection is a Phase 3 dependency.
The plan says "a runtime can be retired by changing profiles/adapters and fallback docs, not by redesigning workflow" but doesn't describe the rollback mechanism. If a runtime swap breaks something in production, what's the recovery path? The scheduler's fallback chain exists but isn't documented here. A brief "rollback procedure" subsection would strengthen Phase 3/4.
The canonical architecture contract (runtime-architecture-refresh.md) and
this plan are aligned on the fundamentals: MC is source of truth, runtimes
are control surfaces, not independent truth stores. No conflicts detected.
One gap: runtime-architecture-refresh.md references runtime_sessions as
the runtime ledger and discusses WAT actions in detail. This plan mentions
runtime_sessions in the core invariant but doesn't discuss how runtime
session history should be preserved across runtime switches. If MC-3907 is
about independence, session continuity across runtime changes is a gap worth
noting for Phase 3.
Fix the MC ticket number. MC-3898 → MC-3907 everywhere.
Rebuild the profile inventory from code. Use PROFILE_PROVIDER keys
and PROFILE_META entries. Remove direct_gemini, direct_anthropic_sdk,
direct_mixed from the inventory (they're sentinels, not profiles). Add
the missing profiles (claude_sonnet_medium, claude_opus_*, *_api,
grok_on_sub).
Note the runtime_profile_state.json is absent. No overrides are active.
Add a one-line rollback procedure to Phase 3: "If a runtime swap breaks production, revert via runtime_profile_state.json override or static PROFILE_DEFAULTS, then restart scheduler."
Add cost baseline dependency to Phase 3 (collect current per-profile spend) so Phase 4 has data to work with.
Note the CCGram single-poller constraint in Phase 5A as a hard dependency for any Telegram routing changes.
Consider whether Phase 3 is docs-only or includes code abstraction. State this explicitly.
The plan is sound in principle and Phase 0/1 execution is clean. The factual issues are in the inventory section — exactly the section Phase 3 depends on. Fix those before starting Phase 3, and this plan will serve as a solid foundation for the runtime-independence initiative.
Priority: fix the MC ticket number and profile inventory now, before the next session picks up Phase 2/3 work and propagates the errors into new docs.