Skip to content

fix(mcp): break the ci-health-check-tool ↔ ci-health-log circular import (#3756)#3811

Merged
williamzujkowski merged 1 commit into
mainfrom
fix/ci-health-circular-import-3756
Jun 9, 2026
Merged

fix(mcp): break the ci-health-check-tool ↔ ci-health-log circular import (#3756)#3811
williamzujkowski merged 1 commit into
mainfrom
fix/ci-health-circular-import-3756

Conversation

@williamzujkowski

Copy link
Copy Markdown
Collaborator

Closes #3756.

Observable bug

Importing the MCP tools barrel (or either ci-health module) under tsx ESM evaluation threw:

ReferenceError: Cannot access 'CiHealthStatusSchema' before initialization

Repro (now fixed): npx tsx -e "import('./packages/nexus-agents/src/mcp/tools/index.js')". This forced a static-parse workaround in the #3687 tool-reference generator.

Cause

A circular dependency with a TDZ trap:

  • ci-health-check-tool.ts defined CiHealthStatusSchema/CiHealthSignal and imported ci-health-log's appenders.
  • ci-health-log.ts imported CiHealthStatusSchema from the tool and used it at module-eval time (inside CiHealthEventSchema).
  • Under tsx ESM, the tool's import of the log ran before the tool defined the schema → the log read it from the TDZ.

Fix (standard leaf-extraction)

New ci-health-types.ts (imports only zod) hosts CiHealthStatusSchema / CiHealthStatus / CiHealthSignal. Both modules import the leaf → check-tool → log → types, check-tool → types (a DAG, no cycle). The tool re-exports the symbols for API compatibility. Verified all three imports load OK under tsx.

Guard + verification

A structural test asserts ci-health-log no longer imports from ci-health-check-tool (cycle stays broken) + a smoke test loads the tool/barrel. 37 ci-health tests pass; typecheck, lint, governance (46 tools), description-drift, docs:tools (47), producer-consumer all green.

🤖 Generated with Claude Code

)

Importing the MCP tools barrel (or ci-health-check-tool / ci-health-log) under tsx
ESM evaluation threw 'ReferenceError: Cannot access CiHealthStatusSchema before
initialization': the tool DEFINED the shared schema/types and imported the log's
appenders, while the log used the schema at module-eval time — the cyclic init
order left CiHealthStatusSchema in the TDZ. (Forced a static-parse workaround in
the #3687 tool-reference generator.)

Fix: extract CiHealthStatusSchema/CiHealthStatus/CiHealthSignal into a leaf
ci-health-types.ts (imports only zod); both modules import the leaf, breaking the
cycle (check-tool -> log -> types, check-tool -> types — a DAG). The tool re-exports
the symbols for API compat. Verified all three imports load OK under tsx.

Guard: a structural test asserts ci-health-log no longer imports from
ci-health-check-tool + a smoke test loads the tool/barrel. 37 ci-health tests pass;
typecheck, lint, governance, producer-consumer clean.

Closes #3756.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@williamzujkowski williamzujkowski merged commit 12608ff into main Jun 9, 2026
41 checks passed
@williamzujkowski williamzujkowski deleted the fix/ci-health-circular-import-3756 branch June 9, 2026 17:35
@github-project-automation github-project-automation Bot moved this from Backlog to Done in nexus-agents project Jun 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Circular import: ci-health-log ↔ ci-health-check-tool breaks tsx ESM import of tools barrel

1 participant