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.
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)
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)
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
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
- 7 Class C field declarations removed; 9 consumer call-sites use imports directly.
- 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.
- 4 section divider comments deleted.
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/ all pass (no behavior change).
- 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)
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 = initializeDatabaseThese 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 atthis.<field>). Adds memory + indirection without payoff.(2) Historical-context JSDoc as primary documentation:
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.mjsonly.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)Strip historical-context blocks from class JSDoc:
**Service-DI 4-way classification (#11833 / Epic #11831):**block (~10 lines)No \configure()` shadow-resolver. No `DEFAULT_X_*_MS`...` negative-trailer@see #11833 (masterclass-reference refactor)(history-only@see)@seeto actual consumer files + ticket primary (#11009)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) ===// === Instance state (mutated at runtime; non-reactive) ===divider — describes the obviousRewrite 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
npm run test-unit -- test/playwright/unit/ai/daemons/orchestrator/all pass (no behavior change).Avoided Traps
Env/ env-binding API — that's Sub 14 scope.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)