LearnNewsExamplesServices
Frontmatter
id11854
titleSub 13: Collapse over-engineered Orchestrator Service-DI (Class C field deletion + historical-context comment strip)
stateClosed
labels
enhancementairefactoringarchitecture
assigneesneo-opus-ada
createdAtMay 23, 2026, 7:58 PM
updatedAtMay 23, 2026, 9:31 PM
githubUrlhttps://github.com/neomjs/neo/issues/11854
authorneo-opus-ada
commentsCount1
parentIssue11831
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[]
blocking[x] 11855 Sub 14: Centralize env-binding registry — ai/config/env.mjs + dotenv lift
closedAtMay 23, 2026, 9:31 PM

Sub 13: Collapse over-engineered Orchestrator Service-DI (Class C field deletion + historical-context comment strip)

Closed v13.0.0/archive-v13-0-0-chunk-13 enhancementairefactoringarchitecture
neo-opus-ada
neo-opus-ada commented on May 23, 2026, 7:58 PM

Parent Epic

#11831 — Sub 13. Cleans up Sub 1's (#11833) over-engineering of ai/daemons/orchestrator/Orchestrator.mjs.

Premise

Sub 1 introduced three anti-patterns into Orchestrator.mjs that look like architecture but are dead weight:

(1) "Class C" imported-singleton instance fields:

summarizationCoordinator = SummarizationCoordinatorService
backupCoordinator        = BackupCoordinatorService
primaryRepoSyncService   = PrimaryRepoSyncService
dreamService             = DreamService
swarmHeartbeatService    = SwarmHeartbeatService
goldenPathSynthesizer    = GoldenPathSynthesizer
initializeDatabaseFn     = initializeDatabase

These are pure aliases. Every consumer calls this.<field>.<method>(...) which is identically <Import>.<method>(...). No swap semantics, no test-mock benefit (tests mock at the import edge, not at this.<field>). Adds memory + indirection without payoff.

(2) Historical-context JSDoc as primary documentation:

* **Service-DI 4-way classification (#11833 / Epic #11831):**
* - **(A) Class-system-managed utility collaborator** — ...
* - **(B) Parent-configured child collaborator** — ...
* - **(C) Simple imported collaborator** — ...
* - **(D) Operator policy value** — ...
*
* No `configure()` shadow-resolver. No `DEFAULT_X_*_MS` constants. No
* `parseInterval`/`parseEnabledFlag` helpers. No `processSupervisorService.set(...)` ...

Describes the design debate, not the design intent. Future readers don't need the historical narrative — git log holds that. Same anti-pattern that produced the tombstone comments @tobiu called out during Sub 1.

(3) Section comments // === Service-DI Class A/B/C/D === — same problem, mid-file scope.

The classification itself is over-engineered: it's genuinely 2-way (reactive configs vs direct imports), not 4-way. "Class C" was invented to make the dead-weight singleton fields look like architecture. "Class D" is just "lazy getter."

Prescription

File: ai/daemons/orchestrator/Orchestrator.mjs only.

  1. Delete 7 Class C field declarations (lines ~222-228). Replace consumer references:

    • this.summarizationCoordinator.getDueTask(...)SummarizationCoordinatorService.getDueTask(...)
    • this.backupCoordinator.getDueTask(...)BackupCoordinatorService.getDueTask(...)
    • this.primaryRepoSyncService.getDueTask(...)PrimaryRepoSyncService.getDueTask(...)
    • this.primaryRepoSyncService.runTask(...)PrimaryRepoSyncService.runTask(...)
    • this.dreamService.processUndigestedSessions()DreamService.processUndigestedSessions()
    • this.goldenPathSynthesizer.synthesizeGoldenPath(...)GoldenPathSynthesizer.synthesizeGoldenPath(...)
    • this.swarmHeartbeatService.initAsync(...)SwarmHeartbeatService.initAsync(...)
    • this.swarmHeartbeatService.pulse()SwarmHeartbeatService.pulse()
    • this.initializeDatabaseFn(this.dbPath)initializeDatabase(this.dbPath)
  2. Strip historical-context blocks from class JSDoc:

    • Remove **Service-DI 4-way classification (#11833 / Epic #11831):** block (~10 lines)
    • Remove No \configure()` shadow-resolver. No `DEFAULT_X_*_MS`...` negative-trailer
    • Remove @see #11833 (masterclass-reference refactor) (history-only @see)
    • Keep: @see to actual consumer files + ticket primary (#11009)
  3. Delete 4 section comments:

    • // === Service-DI Class A: class-system-managed utility collaborator ===
    • // === Service-DI Class B: parent-configured child collaborator + propagated parent props ===
    • // === Service-DI Class C: simple imported collaborators (instance fields) === (entire 7-field block goes anyway)
    • // === Service-DI Class D: operator policy values (lazy getters, 2-value chain) ===
    • Plus the // === Instance state (mutated at runtime; non-reactive) === divider — describes the obvious
  4. Rewrite class @summary intent-driven (one paragraph): what the class does (schedule maintenance tasks; per-task failure isolation; reactive cadence + supervisor child for testability/sub-classing; operator-policy getters for env+config). No "Sub N said X", no negative-statements about what was removed.

Acceptance Criteria

  1. 7 Class C field declarations removed; 9 consumer call-sites use imports directly.
  2. JSDoc class @summary describes class intent + 2 reactive slots (cadenceEngine, processSupervisorService) — no "(#11833 / Epic #11831)" parentheticals, no "No X. No Y. No Z." trailers, no Class A/B/C/D enumeration.
  3. 4 section divider comments deleted.
  4. npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/ all pass (no behavior change).
  5. Substrate-size guard does NOT fail (this is a net-reduction PR).

Avoided Traps

  • Don't reintroduce "Class C" as a different name (e.g., "delegate fields"). The pattern itself is the anti-pattern — no instance-field wrapper for singletons. Use the import.
  • Don't preserve the 4-way classification under a different label (e.g., "3-way" after removing C). The classification framework itself is what reduces clarity; collapse to the natural language description.
  • Don't add new tombstone comments explaining what was removed in THIS Sub. Git log holds that.
  • Don't touch Env / env-binding API — that's Sub 14 scope.
  • Don't touch CadenceEngine/ProcessSupervisorService beforeSet logic — those are genuine reactive configs (Class A + B), keep them.

Depends on

Epic #11831 Subs 8-12 (all merged) — required because moves landed first.

Unblocks

Sub 14 (env-binding centralization) — Sub 13 lands first to avoid Orchestrator merge conflicts.

Authored by: [Claude Opus 4.7] (Claude Code)