LearnNewsExamplesServices
Frontmatter
id12042
titleReal-resolver smoke for TenantRepoSyncService export-drift escape
stateClosed
labels
bugaitesting
assigneesneo-opus-ada
createdAtMay 26, 2026, 9:38 PM
updatedAtMay 26, 2026, 10:37 PM
githubUrlhttps://github.com/neomjs/neo/issues/12042
authorneo-opus-ada
commentsCount0
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[]
closedAtMay 26, 2026, 10:37 PM

Real-resolver smoke for TenantRepoSyncService export-drift escape

neo-opus-ada
neo-opus-ada commented on May 26, 2026, 9:38 PM

Context

Follow-up captured by @neo-gpt's cycle-1 review of PR #12037 (which fixed Bug B in #12036TenantRepoSyncService.resolveIngestionService looking up the wrong export name).

The [KB_GAP] finding: existing unit coverage in test/playwright/unit/ai/daemons/orchestrator/services/TenantRepoSyncService.spec.mjs stubs knowledgeBaseIngestionService as a constructor option rather than exercising resolveIngestionService. The bug was therefore invisible at unit-test time and only surfaced via the empirical R3 first cloud tenant-ingestion smoke. Same general anti-pattern as feedback_stub_tests_miss_adapter_drift (#11999).

The Problem

When the canonical exported symbol in ai/services.mjs was renamed (or never matched what the resolver code expected), no test caught the drift because the spec injected the dependency directly and never asked the resolver to look up the real one. Future renames of KB_IngestionService would re-introduce the same Day-0 blocker.

The Architectural Reality

The Fix

Add a narrow real-resolver smoke test that:

  1. Imports TenantRepoSyncService without injecting knowledgeBaseIngestionService.
  2. Calls service.resolveIngestionService() directly.
  3. Asserts the return value is non-undefined and structurally matches the KB_IngestionService shape (has ingestSourceFiles method).

This catches:

  • Any future rename of KB_IngestionService in ai/services.mjs without a corresponding update in TenantRepoSyncService.resolveIngestionService.
  • Any future deletion of the export entirely.
  • Any future structural change where the resolved object loses ingestSourceFiles.

The smoke does NOT need to invoke ingestSourceFiles — just verify the resolver returns an object with the expected method-existence contract. Cheap test, high regression-protection ROI.

Decision Record impact

aligned-with ADR 0014 — narrow test-coverage gap fix.

Acceptance Criteria

  • New test case in TenantRepoSyncService.spec.mjs (or a sibling spec) that exercises resolveIngestionService() against the real ai/services.mjs import.
  • Assertion: returned value is non-undefined.
  • Assertion: returned value has typeof .ingestSourceFiles === 'function' (or equivalent structural check).
  • Test fails when services.mjs is mocked to NOT export KB_IngestionService (verifies the test actually catches export-drift, not just runs).
  • Test passes against current dev (services.KB_IngestionService exists).

Out of Scope

  • Broader "real-vs-stub" audit of other orchestrator-side resolvers — separate concern. This ticket is narrow: one resolver, one regression-protection test.
  • Refactoring TenantRepoSyncService.spec.mjs to use the real ingestion service throughout — orthogonal; the existing stub-based tests are fine for orchestration-logic isolation.
  • Architectural redesign of orchestrator→ingestion invocation (in-process vs MCP-call) — separate concern, documented in #12037 body.

Avoided Traps

  • Over-broad real-resolver suite: tempting to add real-resolver tests for every service the orchestrator imports. Restraint — start with the one that actually escaped (resolveIngestionService). Add others only when drift recurs.
  • Mocking services.mjs per-test to simulate the broken state: better is one negative-case test that re-imports services.mjs via a mocking layer (or a snapshot of the original module with the export deleted) — keeps the positive case simple and the negative case isolated.

Related

  • Empirical anchor: @neo-gpt cycle-1 review of PR #12037 [KB_GAP] finding.
  • Parent: #12036 (3 substrate gaps from R3 first cloud tenant-ingestion smoke).
  • Sibling pattern: feedback_stub_tests_miss_adapter_drift (#11999 cycle-1).
  • Empirical session: first real-world cloud Agent OS deployment, 2026-05-26.
tobiu referenced in commit 84758dd - "test(orchestrator): export-drift guard for resolveIngestionService (#12042) (#12044) on May 26, 2026, 10:37 PM
tobiu closed this issue on May 26, 2026, 10:37 PM