|
| 1 | +# Investigation: DEBUG flag runtime behavior |
| 2 | + |
| 3 | +## Summary |
| 4 | +The `debug` flag is a runtime configuration value (from config/env/overrides), not a compile-time constant. Enabling it mainly changes **tool/workflow visibility** (doctor workflow + bridge debug tools), adds a limited **CLI daemon log-level override**, and tags telemetry context; it does **not** broadly switch core execution paths. |
| 5 | + |
| 6 | +## Symptoms |
| 7 | +- It was unclear whether `DEBUG` means logging-only or broader behavior changes. |
| 8 | +- Docs mention debug logging and doctor exposure, but runtime impact was not clearly mapped end-to-end. |
| 9 | + |
| 10 | +## Investigation Log |
| 11 | + |
| 12 | +### 2026-02-28 / Phase 2 - Config source and precedence |
| 13 | +**Hypothesis:** `debug` comes from multiple sources with precedence rules. |
| 14 | +**Findings:** `debug` is parsed from `XCODEBUILDMCP_DEBUG`, accepted in config schema, and resolved via layered precedence: overrides > config file > env > defaults. |
| 15 | +**Evidence:** `src/utils/config-store.ts:172`, `src/utils/config-store.ts:255-263`, `src/utils/config-store.ts:384`, `src/utils/runtime-config-schema.ts:9`, `src/utils/__tests__/config-store.test.ts:44-91` |
| 16 | +**Conclusion:** Confirmed. |
| 17 | + |
| 18 | +### 2026-02-28 / Phase 3 - Predicate wiring and exposure filtering |
| 19 | +**Hypothesis:** `debug` drives predicate-based workflow/tool visibility. |
| 20 | +**Findings:** `debugEnabled` predicate is `ctx.config.debug`; workflow and tool visibility both run predicate evaluation; MCP registration and CLI/daemon catalogs use that exposure filtering. |
| 21 | +**Evidence:** `src/visibility/predicate-registry.ts:16`, `src/visibility/exposure.ts:39`, `src/visibility/exposure.ts:64`, `src/utils/tool-registry.ts:85`, `src/utils/tool-registry.ts:100`, `src/runtime/tool-catalog.ts:143`, `src/runtime/tool-catalog.ts:159`, `src/server/bootstrap.ts:84-91`, `src/visibility/__tests__/exposure.test.ts:86-112,273-328`, `src/visibility/__tests__/predicate-registry.test.ts:42-55` |
| 22 | +**Conclusion:** Confirmed. |
| 23 | + |
| 24 | +### 2026-02-28 / Phase 3 - Which workflows/tools are actually gated |
| 25 | +**Hypothesis:** Only specific surfaces are debug-gated. |
| 26 | +**Findings:** |
| 27 | +- `doctor` workflow is `autoInclude: true` + `debugEnabled` predicate. |
| 28 | +- `xcode_tools_bridge_{status,sync,disconnect}` tools are debug-gated. |
| 29 | +- `xcode-ide` workflow itself is not debug-gated (uses `hideWhenXcodeAgentMode`). |
| 30 | +**Evidence:** `manifests/workflows/doctor.yaml:5-8`, `manifests/tools/xcode_tools_bridge_status.yaml:7-8`, `manifests/tools/xcode_tools_bridge_sync.yaml:7-8`, `manifests/tools/xcode_tools_bridge_disconnect.yaml:7-8`, `manifests/workflows/xcode-ide.yaml:6-13`, `src/core/manifest/__tests__/load-manifest.test.ts:79-106` |
| 31 | +**Conclusion:** Confirmed. |
| 32 | + |
| 33 | +### 2026-02-28 / Phase 3 - Doctor tool vs doctor resource behavior |
| 34 | +**Hypothesis:** DEBUG gates the doctor tool but not the doctor resource. |
| 35 | +**Findings:** |
| 36 | +- Tool `doctor` is attached to debug-gated `doctor` workflow. |
| 37 | +- Resource registry includes `doctor` resource unconditionally. |
| 38 | +- Doctor resource directly calls doctor logic without debug predicate check. |
| 39 | +**Evidence:** `manifests/workflows/doctor.yaml:8-10`, `manifests/tools/doctor.yaml:1-9`, `src/core/resources.ts:39-43`, `src/core/resources.ts:79-103`, `src/mcp/resources/doctor.ts:19`, `src/mcp/resources/doctor.ts:64-71` |
| 40 | +**Conclusion:** Confirmed. |
| 41 | + |
| 42 | +### 2026-02-28 / Phase 3 - Logging and telemetry effects |
| 43 | +**Hypothesis:** DEBUG also affects logging and telemetry context. |
| 44 | +**Findings:** |
| 45 | +- CLI passes `logLevel: 'info'` to daemon-backed bridge discovery when `config.debug` is true. |
| 46 | +- That maps to env override `XCODEBUILDMCP_DAEMON_LOG_LEVEL`. |
| 47 | +- MCP server log level defaults to `info` regardless of debug. |
| 48 | +- MCP + daemon include `debugEnabled` in Sentry runtime context; Sentry stores it as tag `config.debug_enabled`. |
| 49 | +**Evidence:** `src/cli.ts:136`, `src/cli/cli-tool-catalog.ts:57`, `src/server/start-mcp-server.ts:39`, `src/server/start-mcp-server.ts:67`, `src/daemon.ts:155`, `src/daemon.ts:211`, `src/utils/sentry.ts:219` |
| 50 | +**Conclusion:** Confirmed (logging effect is scoped; telemetry effect is tagging only). |
| 51 | + |
| 52 | +### 2026-02-28 / Phase 4 - Compile-time vs runtime mechanism |
| 53 | +**Hypothesis:** There may be a compile-time DEBUG constant. |
| 54 | +**Findings:** No `process.env.DEBUG`, no `debug` package usage, and no tsup `define` replacement for DEBUG; `debug` is runtime config plumbing. |
| 55 | +**Evidence:** `tsup.config.ts:1-61`, `package.json:1-108`, repository search results for `process.env.DEBUG` and `from 'debug'` returned no matches. |
| 56 | +**Conclusion:** Compile-time hypothesis eliminated. |
| 57 | + |
| 58 | +### 2026-02-28 / Phase 4 - Historical drift and docs mismatch |
| 59 | +**Hypothesis:** Some docs are stale relative to current predicate-based system. |
| 60 | +**Findings:** |
| 61 | +- `TOOL_DISCOVERY_LOGIC.md` still references `shouldExposeTool` and `src/utils/tool-visibility.ts` (not present in current src search). |
| 62 | +- Current code uses predicate registry/exposure pipeline. |
| 63 | +- Other docs phrase DEBUG as logging-only, which is incomplete (it also changes visibility and telemetry tags). |
| 64 | +**Evidence:** `docs/dev/TOOL_DISCOVERY_LOGIC.md:47,75,105,116`, src search for `shouldExposeTool` returned no runtime matches, `docs/CONFIGURATION.md:191`, `server.json:52`, `docs/dev/CONTRIBUTING.md:223`, `src/visibility/predicate-registry.ts:16`, `src/visibility/exposure.ts:39-64` |
| 65 | +**Conclusion:** Confirmed doc/code drift in at least one dev doc and minor wording incompleteness in public metadata/docs. |
| 66 | + |
| 67 | +## Root Cause |
| 68 | +`debug` is currently a **visibility/diagnostic feature flag** implemented via manifest predicates and runtime config layering. Confusion stems from mixed documentation language (often “debug logging”) while code uses `debug` for broader concerns: auto-including debug-gated workflows/tools and tagging runtime telemetry context. |
| 69 | + |
| 70 | +## Eliminated Hypotheses |
| 71 | +- **Compile-time DEBUG constant:** Eliminated (no bundler define/substitution path found). |
| 72 | +- **Global behavior switch affecting core tool execution semantics:** Not supported by evidence; effects are primarily registration/visibility + scoped logging override + telemetry tag. |
| 73 | + |
| 74 | +## Recommendations |
| 75 | +1. Update docs to explicitly state that `debug` affects **tool/workflow exposure** in addition to diagnostics/logging wording. |
| 76 | +2. Clarify in docs the distinction between: |
| 77 | + - debug-gated `doctor` **tool** |
| 78 | + - always-registered `xcodebuildmcp://doctor` **resource** |
| 79 | +3. Update `docs/dev/TOOL_DISCOVERY_LOGIC.md` to current predicate-based architecture (remove stale `shouldExposeTool` references). |
| 80 | +4. If desired product behavior is logging-only, decouple visibility gating from `debug` into a separately named config flag. |
| 81 | + |
| 82 | +## Preventive Measures |
| 83 | +- Add/maintain a single “DEBUG semantics” section in `docs/CONFIGURATION.md` and link it from `server.json` description text. |
| 84 | +- Add a doc consistency test or lint check for known-removed APIs/paths (`shouldExposeTool`, `tool-visibility.ts`). |
| 85 | +- Keep manifest predicate changes paired with docs updates in the same PR checklist. |
0 commit comments