{
  "$schema_note": "Hand-maintained module registry for the doctor accumulative engine. NOT generated. New organ module = ONE entry here, no engine code change (mirrors data/deployment-surfaces.json's 'new surface = one entry' discipline). The selector in scripts/doctor.cjs (runAccumulativeEngine) walks this array. CADENCE splits how a module runs (Phase 217 Plan-01): cadence 'always' = a per-invocation DIAGNOSTIC whose check() runs on EVERY doctor invocation, watermark-immune (only an upper introduced_version <= running deferred-guard applies, never a lower watermark bound) -- this is what stops a migrated check from going permanently silent after one run; cadence 'once' = a watermark-gated HEAL (umbilical's semantics) that runs when introduced_version is in the (applied_through, running] window and never re-runs once the persisted watermark at ~/.mindrian/doctor-applied.json advances past it. FLAG names the parseArgs flags key that activates the module: null = the module runs on a bare / --all / --fix run when no class flag is active (the class-A/N gate), and a named flag (e.g. 'roomMd') runs the module only when that flag is set. FIX-THEN-RECHECK: under --fix a module with fix_supported true whose check surfaced a warn/error is passed to the runner fix(), then check() re-runs so the reported result reflects the post-fix state; a fixer's recoveries land in the engine recovered[] array. fix_supported MUST be an explicit boolean (D-03) -- never omitted. Both cadence and flag are gated by introduced_version <= running so an install is NEVER faulted for an organ it predates, and a future-version module (introduced_version > running) is DEFERRED (never run) until the user is on that version. Per-entry contract: { id (stable kebab-case identifier), introduced_version (semver string -- the plugin version that shipped this organ; prerelease labels like 1.13.1-beta.4 compare correctly), cadence ('always' | 'once'), flag (parseArgs flags key | null), fix_supported (explicit boolean -- whether the runner offers a --fix remediation, else check-only), runner (a lib/core/doctor/<id>.cjs-style relative path resolved against the plugin root at run time; its module exports a check(ctx) and optionally a fix(ctx) entry), description (one line) }. SEEDED EMPTY: Plan 03 registers module #1 (umbilical). Do NOT invent organ modules here beyond umbilical -- the 15 remaining SCOUT-2 organs backfill in v1.13.1+ (out_of_scope LOCKED decision).",
  "schema_version": 1,
  "phase": "139-doctor-accumulative-engine-skeleton-and-context-fix",
  "canon_parts": [6, 7, 8],
  "modules": [
    {
      "id": "capability-ledger",
      "introduced_version": "2.0.0-beta.12",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/capability-ledger-module.cjs",
      "description": "Capability ledger staleness (Phase 265): warns when data/capability-ledger.json's ledger_covers.to trails the installed claude --version beyond MINDRIAN_LEDGER_MAX_VERSION_LAG. Check-only, cadence always."
    },
    {
      "id": "research-providers",
      "introduced_version": "2.0.0-beta.64",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/research-providers-module.cjs",
      "description": "Research provider reachability matrix (Phase 369.2, HARNESS-03): lens -> provider -> ready, no key, line off or not checked. Check-only, cadence always, zero network."
    },
    {
      "id": "mcp-surface",
      "introduced_version": "2.0.0-beta.12",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/mcp-surface-module.cjs",
      "description": "MCP tool-count and zero-tool check (Phase 265 R-7): spawns both mindrian-os and mindrian-brain over stdio and reports live per-server tool counts, failing on a zero-tool tools/list response or a wedged server. Warns (never caps) when the combined surface exceeds TOTAL_SURFACE_TOKEN_BUDGET. Check-only, cadence always."
    },
    {
      "id": "mcp-write-path",
      "introduced_version": "2.0.0-beta.74",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/mcp-write-path-module.cjs",
      "description": "MCP write-path check (quick 261026-s8c): spawns the mindrian-os server with an unidentified probe client, reads capability_floor from status_read, and warns with the exact MINDRIAN_MCP_FIRST fix text when writes are off. Check-only, cadence always, read-only."
    },
    {
      "id": "umbilical",
      "introduced_version": "1.13.1-beta.4",
      "cadence": "once",
      "flag": null,
      "fix_supported": true,
      "runner": "lib/core/doctor/umbilical-module.cjs",
      "description": "Project .umbilical cords into room.db as AFFILIATED_WITH edges; integrity-check cord<->marker bidirectionality (orphan / removed-marker / unprojected). --fix SUGGESTS orphan cords, never auto-creates."
    },
    {
      "id": "card-fire-health",
      "introduced_version": "1.15.3-beta.12",
      "cadence": "always",
      "flag": "cardFireHealth",
      "fix_supported": false,
      "runner": "lib/core/doctor/card-fire-health-module.cjs",
      "description": "check-card-fire.cjs instrument health: intercept log exists/valid JSONL/fresh, library seams intact, session store parseable"
    },
    {
      "id": "voice-style-log",
      "introduced_version": "2.0.0-beta.28",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/voice-style-log-module.cjs",
      "description": "Voice-style evidence count since the last release plus the evaluatePromotion verdict per voice policy found in the log (D-04). Never returns warn or error; informational only."
    },
    {
      "id": "mode-select-checkpoint",
      "introduced_version": "1.15.3-beta.19",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/mode-select-checkpoint-module.cjs",
      "description": "Session-start mode-selection Decision Gate firing checkpoint: warns when a session has had a user turn but no lane-pick was recorded, a possible silent skip. Check-only, advisory."
    },
    {
      "id": "ui-compliance",
      "introduced_version": "1.12.1-beta.1",
      "cadence": "always",
      "flag": "uiCompliance",
      "fix_supported": false,
      "runner": "lib/core/doctor/ui-compliance-module.cjs",
      "description": "UI Ruling System compliance scan (class F): commands body_shape frontmatter, forbidden box chars / glyphs, renderer Zone 1 + Zone 4 patterns. Check-only (D-13)."
    },
    {
      "id": "stale-first-touch-copy",
      "introduced_version": "1.13.1-beta.4",
      "cadence": "always",
      "flag": "staleFirstTouch",
      "fix_supported": false,
      "runner": "lib/core/doctor/stale-first-touch-copy-module.cjs",
      "description": "First-touch greeting surfaces (class K): stale hardcoded version literals + em-dash violations, via lib/core/stale-copy-scanner.cjs. Check-only."
    },
    {
      "id": "deprecated-usage",
      "introduced_version": "1.13.0-beta.19",
      "cadence": "always",
      "flag": "deprecatedUsage",
      "fix_supported": false,
      "runner": "lib/core/doctor/deprecated-usage-module.cjs",
      "description": "Deprecated /mos:<cmd> usage in recent session transcripts (class L): per-command migration hints. Standard status vocabulary; check-only."
    },
    {
      "id": "plugin-enabled-state",
      "introduced_version": "1.13.1-beta.4",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/plugin-enabled-state-module.cjs",
      "description": "Silent-disable watchdog (class N / DRIFT-12): plugin installed but enabledPlugins key false. Default-gated (bare / --all / --fix). Check-only."
    },
    {
      "id": "cascade-rooms",
      "introduced_version": "1.12.1-beta.1",
      "cadence": "always",
      "flag": "cascadeRooms",
      "fix_supported": true,
      "runner": "lib/core/doctor/cascade-rooms-module.cjs",
      "description": "Room .room-root sentinel presence (class B): every registered room carries its sentinel. --fix CREATES missing sentinels for rooms whose dir exists (dry-run honored; dir-missing rooms suggested, never auto-created)."
    },
    {
      "id": "cascade-rooms-active",
      "introduced_version": "1.12.1-beta.1",
      "cadence": "always",
      "flag": "cascadeRooms",
      "fix_supported": false,
      "runner": "lib/core/doctor/cascade-rooms-active-module.cjs",
      "description": "Active-room guard silence detector (class C): a write to a non-active room would be silenced before the cascade side-channel runs. Shares the --cascade-rooms flag with class B. Check-only."
    },
    {
      "id": "room-md",
      "introduced_version": "1.12.1-beta.1",
      "cadence": "always",
      "flag": "roomMd",
      "fix_supported": true,
      "runner": "lib/core/doctor/room-md-module.cjs",
      "description": "ROOM.md + MINTO.md presence under the active room's .room-root (class E). --fix invokes generate-section-intelligence.cjs --recursive then re-checks."
    },
    {
      "id": "statusline-visibility",
      "introduced_version": "1.12.5",
      "cadence": "always",
      "flag": "statuslineVisibility",
      "fix_supported": true,
      "runner": "lib/core/doctor/statusline-visibility-module.cjs",
      "description": "Statusline invisibility probe (class G): stale user-settings path / broken plugin install / statusline-mos isolated execution / disableAllHooks. --fix removes the stale user-settings statusLine override so plugin-level config takes effect."
    },
    {
      "id": "verify-surface",
      "introduced_version": "1.12.1-beta.1",
      "cadence": "always",
      "flag": "verifySurface",
      "fix_supported": false,
      "runner": "lib/core/doctor/verify-surface-module.cjs",
      "description": "Live cascade side-channel end-to-end verification (class D): spawns tests/test-cascade-surface-e2e.cjs (30s timeout) and asserts the 8-key shape. Self-skips when bash or the harness is absent (never faults an install for a missing dev harness). Check-only."
    },
    {
      "id": "install-state",
      "introduced_version": "1.13.0-beta.13",
      "cadence": "always",
      "flag": "installState",
      "fix_supported": true,
      "runner": "lib/core/doctor/install-state-module.cjs",
      "description": "Install-state record + topology classification + 6-way version-of-record consistency (class I): reads ~/.mindrian/install-state.json, live-spot-checks record.active_version vs installed_plugins.json, detects legacy-config-pin drift (F11) and legacy-clone-alongside-marketplace-cache migration candidates. --fix returns MULTIPLE recovery records (session-start record write, LV rewrite, legacy-config reconcile, legacy-clone backup-verify-remove with the dev-clone safety belt). Runs BEFORE deployment-surfaces so class J reads its result via ctx.checks."
    },
    {
      "id": "deployment-surfaces",
      "introduced_version": "1.13.0-beta.13",
      "cadence": "always",
      "flag": "installState",
      "fix_supported": true,
      "runner": "lib/core/doctor/deployment-surfaces-module.cjs",
      "description": "Deployment-surface manifest reconciliation (class J): reconciles every owned surface in data/deployment-surfaces.json against disk (marker / exact-value / observed-only), honoring topology_scope + token expansion. Reads topology/activeRoot/activeVersion from ctx.checks['install-state'] (self-derives via shared.cjs when absent). Shares the --install-state flag with class I; ordered AFTER it. --fix re-stamps ok:false session-start-owned surfaces + prunes the marketplace cache."
    },
    {
      "id": "room-graph-density",
      "introduced_version": "1.15.3-beta.47",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/room-graph-density-module.cjs",
      "description": "Per-registered-room room.db node-row and edge-row counts, read through the new read-only navigation door so the census never mutates what it measures. Check-only: raw counts and totals, no health or density claim, per SEED-074's hard guard on downstream claims."
    },
    {
      "id": "room-graph-integrity",
      "introduced_version": "2.0.0-beta.40",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/room-graph-integrity-module.cjs",
      "description": "Room-graph integrity counts (Phase 343): edge rows whose source or target id has no node row, claim nodes with no SOURCED_FROM or DERIVED_FROM out-edge, proposed nodes past the review window, edge rows carrying a type outside the writeEdge allowlist, unresolved CONTRADICTS edges and self-referencing edges. Reads through the read-only navigation door; scopes to the active room by default and every registered room plus fleet totals under --cascade-rooms. Check-only: raw counts only, no claim in either direction, per SEED-074's hard guard."
    },
    {
      "id": "graph-derive-health",
      "introduced_version": "1.15.3-beta.49",
      "cadence": "always",
      "flag": "graphDeriveHealth",
      "fix_supported": true,
      "runner": "lib/core/doctor/graph-derive-health-module.cjs",
      "description": "Semantic-edge derivation health per room (RCA 4d): BELONGS_TO present with zero cascade edges (derivation never succeeded), a derive queue entry stuck past 3 days, or a graph-derive-failures.json log. Also reports a derive queue entry abandoned for more than 7 days, a drain or scout lock held by a dead PID or a live PID with a stale heartbeat (a recycled PID or a runaway worker), and an overbroad or invalid artifact scope declaration with its counts. Scopes to the active room, or every room with --cascade-rooms. --fix (sugar: --heal-room) re-enqueues each affected room through the existing dedup-by-roomDir sweep, removes a dead or recycled lock, and drops an abandoned entry with a permanent record."
    },
    {
      "id": "canon-backfill",
      "introduced_version": "2.0.0-beta.56",
      "cadence": "always",
      "flag": null,
      "fix_supported": true,
      "runner": "lib/core/doctor/canon-backfill-module.cjs",
      "description": "Canon handle backfill (Phase 366, D-16): for every registered room, things that resolve to a canon framework through the one resolver (frontmatter framework, methodology, title, ratified room translation) but carry no USES_FRAMEWORK edge, and framework edge targets with no node row. --fix mints the framework node first, then the edge, one transaction per thing, and reports counts per room; a second run changes nothing. Exact matches only: no fuzzy matching, no network."
    },
    {
      "id": "graph-derive-heal-retrofit",
      "introduced_version": "1.15.3-beta.49",
      "cadence": "once",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/graph-derive-heal-retrofit-module.cjs",
      "description": "One-time automatic retrofit (RCA 4c) for rooms whose derive queues were silently cleared before Phase 224-02's keep-on-failure fix. Walks every registered room, reuses graph-derive-health's detectRoomHealth, and re-enqueues each zero-cascade-edge room so the next in-session derive rebuilds its semantic layer. The heal runs inside check() because the ONCE pass is not gated behind --fix; the watermark then advances so it never repeats."
    },
    {
      "id": "eureka-fts-health",
      "introduced_version": "1.15.3-beta.51",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/eureka-fts-health-module.cjs",
      "description": "Per-registered-room eureka_fts (lexical trigger index) presence, population and staleness census, read through the read-only navigation door so the census never mutates what it measures (RESEARCH BLOCKER B-2). An absent index is reported, not failed: absent is the correct default state of every room today. A stale index (rows pointing at deleted nodes) is a real defect and reports status warn."
    },
    {
      "id": "icm-part-wiring",
      "introduced_version": "2.0.0-beta.38",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/icm-part-wiring-module.cjs",
      "description": "Declaration counts for ICM nested parts, producers resolved against the command registry, consumers resolved on disk, per-layer declaring-surface counts, and an opt-in per-room section-contract heading census behind --cascade-rooms. Check-only: raw counts and totals, no health or completeness claim, per SEED-074's hard guard on downstream claims."
    },
    {
      "id": "room-map",
      "introduced_version": "2.0.0-beta.48",
      "cadence": "always",
      "flag": null,
      "fix_supported": true,
      "runner": "lib/core/doctor/room-map-module.cjs",
      "description": "Rebuilds a room's .mindrian/room-map.json from disk and compares it against six drift classes: missing map, stale map fingerprint, a blocked-kind (root/section/structural/sub-room) directory missing ROOM.md, a stale per-node icm_self.fingerprint, an artifact folder wrongly carrying an icm_self block, and a sub-room registry lineage disagreement (report-only, disk wins). No auto_heal key yet (R-353-A; Phase 352 classifies this row and section-ruling together when it lands, proposed TRUE here since a rebuild-from-disk is mechanical and reversible). --fix refuses (recoverable:false) on any room path outside tests/fixtures/icm-rooms/, so a real fleet room is only ever rebuilt as the navigator's explicit act (D-353-9)."
    },
    {
      "id": "section-ruling",
      "introduced_version": "2.0.0-beta.48",
      "cadence": "always",
      "flag": null,
      "fix_supported": true,
      "runner": "lib/core/doctor/section-ruling-module.cjs",
      "description": "Reports five drift classes over a room's section ruling documents: a landed CONTEXT.md ruling_fingerprint disagreeing with a fresh recomputation from data/section-job-canon.json plus the shipped section-command-ledger; a section slug with no job, neither a canon row nor a ratified room declaration (sections_without_job_id); a sub-room node with no declared job_id (subrooms_without_job_id, the parent-fallback case, report-only); claim nodes filed since this module's introduced date with no SOURCED_FROM edge to a jtbd:* anchor (claims_without_anchor, legacy claims out of scope); and an entry of the room's .mindrian/section-jobs.json that the registry rejected (room_declarations_rejected). Room-declared sections (from <room>/.mindrian/section-jobs.json, closed job vocabulary, navigator-ratified, never overriding a canon row) are listed apart from canon sections and are not drift. No auto_heal key yet (R-353-A; Phase 352 classifies this row alongside room-map, proposed FALSE here since regenerating a ruling document can rewrite a file a human authored prose into, a judgment fix). --fix refuses (recoverable:false) on any room path outside tests/fixtures/icm-rooms/, so a real fleet room's ruling documents are only ever regenerated as the navigator's explicit act (D-353-9)."
    },
    {
      "id": "graph-doctor",
      "introduced_version": "2.0.0-beta.65",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/graph-doctor-module.cjs",
      "description": "Local SQL graph doctor (quick 261009-4h4): read-only check of room.db for isolated nodes, duplicate names and open triads; writes a proposal queue pending the navigator gate. Check-only, never writes room.db, no fix."
    },
    {
      "id": "room-runtime",
      "introduced_version": "2.0.0-beta.78",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/room-runtime-module.cjs",
      "description": "Names the bash and the Python that room creation would use (probe by running; the WSL launcher and the Microsoft Store placeholder are rejected), their versions, every candidate tried, and on Windows the shell hooks/run-hook.cmd would pick. Check-only, LOCAL, no fix (Phase 383, SEED-142 direction 4, D-07)."
    },
    {
      "id": "doubled-room-trees",
      "introduced_version": "2.0.0-beta.78",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/doubled-room-trees-module.cjs",
      "description": "Lists the folders that older room births wrote by mistake under the rooms home (a copy of the room path inside the rooms home holding only unchanged seed files ROOM.md, STATE.md, USER.md), with a digest. Check-only in the engine: deletion runs only through --clean-doubled-rooms=<digest> after the navigator approves the F.0 card (Phase 383, D-02, SEED-117)."
    },
    {
      "id": "eureka-engine-readiness",
      "introduced_version": "2.0.0-beta.80",
      "cadence": "always",
      "flag": null,
      "fix_supported": false,
      "runner": "lib/core/doctor/eureka-engine-readiness-module.cjs",
      "description": "Reports whether the Eureka engine (the new mindrian-eureka project) is set up and ready for the graph tools: skip when it is not set up (optional), ok when ready, warn with the cause and one fix line when it is set up but not ready, with each route family that is not ready (encoder group, hmm group, model folder, Node.js 22 or newer) named. A reporter: a machine with no engine never fails the doctor. It reads the engine through the one resolver and the one check function, spawns only uv --version, uv python find and node --version, never starts the engine and uses no network. It reads the installed package groups, never the environment settings file, and reports an unreadable layout as not verified. The engine own health check is the deep check of /mos:eureka enable engine --check --deep (Phase 387 Plan 07)."
    }
  ]
}
