Carolopedia

A friendly guide to Carol, her ecosystem, and the agents who built her.

📖 CarolopediaServicesBuild InitiativesAll activitiesINI-999902813Guide page
📋

CAROL-INI-3893-00: The lane switch has been dead for ten days: restore the module the CLI overwrote, and make the forced-tool guard reachable

Initiative
Open in Initiatives →

📖About

Found while starting 3891. On 2026-08-06 at 02:00 the lane switch's command-line wrapper was copied OVER the shared module it imports. The module now imports itself: readiness, preflight, probe, switch, grant_exception and expired_exceptions are all gone, and running the tool raises AttributeError immediately. The last good copy is in git at the 01:00 commit that hour, 703 lines, so this is a RESTORATION with an exact original, not a rebuild.

WHAT WAS LOST FOR TEN DAYS: the readiness probe, every preflight refusal (retired subscription, unpriced model, unreachable lane, reserved lane), the automatic rollback that makes a half-switched estate impossible, and the DATED operator exception that cookbook 1220 requires before a track may sit on Claude - including expired_exceptions, the check that is supposed to turn the suite red when an exception outlives its promise. So every lane move since 2026-08-06 was made by hand with no preflight and no rollback, including the moves off Codex and Kimi when they ran out of quota.

WHY NOBODY SAW IT: test_ini3694 went red that same hour and has recorded 0 passed / 1 failed in every run since - sitting among about 200 other red files that nobody triages. Its twelve checks do not fail on their merits, they ERROR on a missing attribute, which is the creed's own rule: a check that could not run is not a pass.

SAME VISIT, SECOND FIX (operator-approved in session CLI-271): the claude adapter's guard against running an action turn on a lane that cannot force a tool call reads tool_choice from a keyword argument, while every real caller nests it inside the tools envelope - proven by signature, since the adapter takes tools as a NAMED parameter, so kwargs never holds that key. The guard has never fired in production, and its own test passes the kwarg shape no caller uses, which is how it stayed green while Carol lost every receipt for seventeen days (3882). Both files are root-owned protected core, so both go through ONE core_install visit under Radagast with operator approval.

⚖️Decisions

  • Elrond's bypass methodology checklist (a reminder, not a gate -- you've got this): 0. File it requested_mode='bypass' (planner-vs-bypass is a deliberate choice). bypass_start REFUSES a non-bypass initiative (CAROL-INI-1846), and the dispatcher only skips the bypass lane when the mode says bypass -- a 'planner' mistag lets Merlin's pipeline grab the placeholder step and block your finished work. 1. Filed as planned status -- let the bypass claim/activate it; never file active. 2. Open the bypass (bypass_start) with your droid id + the remediation answer (remediates_initiative_id=NNN, or remediates_nothing=True). 3. Work the blocks for your work-type: template -> design -> code -> test -> review. Do the real work; record decisions on the initiative as you make them. 4. Reality is recorded for you at close -- code (files changed), each decision, and the twin-review verdict become real activities tied to this initiative and show in the Activity Tracker like a planner run (CAROL-INI-1840). No dummy rows. 5. Keep the initiative status moving; it parks in 'reviewing' and is tagged uat-pending for you at close (CAROL-INI-1836), so the stuck-watchdog leaves it alone until UAT. 6. Close runs the gates (design/architecture compliance + caller-audit). If a gate flags something pre-existing or unrelated to your change, waive it with a clear written rationale -- audit, don't skip. 7. Bypass skips the planner's auto-orchestration, NOT the standards. Same template checklist, same review, same observability as a planner run. (elrond)
  • [status-router] planned -> executing | event=bypass_executing | bypass transition (or-bx-01)
  • CORRECTION to this bypass's status_updates block. It said no app reload was needed because the adapter is loaded fresh by each call path. That is WRONG: shared/llm_adapters/claude.py is imported once per process, so every long-running service held the pre-fix guard in memory — and the reload done earlier this session for CAROL-INI-3882 happened BEFORE this core install, so it did not carry the guard. Consequence was bounded, not nil: the primary cure (callers consulting can_force_tool_call before forcing a call) was already live in those processes, so the stale guard removed only the defence-in-depth refusal, never the fix. Corrected by reloading carol-carol.service and all five chat doors through Radagast AFTER the install; all six came back up. Recorded rather than quietly amended, because a bypass block that misstates what was done is the same class of fault as the check that could not fire. — Caught while reviewing my own recorded blocks. A record that says the estate is consistent when it is not is worse than one that says nothing. (orion)
  • [delivery-check] 5 must-have criteria remain pending at bypass_end — delivery has no mechanical re-performance lane; UAT must grade on live evidence, not checklist silence (CAROL-INI-3020): (no detail) (orion)
  • [status-router] executing -> reviewing | event=bypass_reviewing | bypass transition (or-bx-01)
  • [status-router] reviewing -> closed | event=operator_signoff | Auto-accepted (CAROL-INI-1859): Orion-initiated, >2 days in reviewing with no objection. (el-srac-01)

Success criteria

  • The lane switch module is restored from the last good commit and the tool runs: readiness returns lanes instead of raising AttributeError. (must_have)
  • test_ini3694's twelve checks execute on their merits instead of erroring on missing attributes, and the suite's result is reported honestly whatever it says. (must_have)
  • The dated operator exception mechanism works again, including the expiry check that turns the suite red when an exception has outlived its promise. (must_have)
  • The claude adapter's forced-tool guard fires for the shape callers actually send, proven by a check that passes tool_choice nested in the tools envelope rather than as a keyword argument. (must_have)
  • Both changes go through the core_install lane under Radagast with the replaced files backed up, and no raw sudo is used. (must_have)