Skip to content

🤖 refactor: segregate the task/workspace seam into role interfaces - #4012

Open
ibetitsmike wants to merge 6 commits into
mainfrom
mike/arch-workspace-host-roles
Open

🤖 refactor: segregate the task/workspace seam into role interfaces#4012
ibetitsmike wants to merge 6 commits into
mainfrom
mike/arch-workspace-host-roles

Conversation

@ibetitsmike

@ibetitsmike ibetitsmike commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Splits the 36-method WorkspaceHost grab-bag on the task/workspace seam into five role interfaces named for what task-side callers do (WorkspaceTurnHost, TurnAdmissionHost, WorkspaceLifecycleHost, WorkspaceProvisioningHost, WorkspaceMetadataHost), keeps WorkspaceHost as their intersection so no call site or wiring changes, and collapses the ~180-line hand-rolled test mock onto one shared makeWorkspaceHostFake.

Background

#3996 cut the taskService/workspaceService dependency cycle at a typed seam, but the seam stayed shallow: one interface mirroring 36 of WorkspaceService's internal mechanics. Every task test stubbed all 36 methods through a ~180-line mock in taskService.test.ts (reached from 318 call sites), and the seam, service, and test harness churned in lockstep on every change. This builds on #3996 rather than reverting it: same seam, deeper interface. Refactor #5 from the 2026-08-29 architecture review (evidence at main @ f04e0f8).

Implementation

  • taskWorkspaceSeam.ts: the five role interfaces group methods by caller intent (turn execution, queue/admission probes, archive/remove lifecycle, child-workspace provisioning, metadata/events). Every method signature is byte-identical to before; WorkspaceHost is now WorkspaceTurnHost & TurnAdmissionHost & WorkspaceLifecycleHost & WorkspaceProvisioningHost & WorkspaceMetadataHost. TaskService (the only production consumer) legitimately uses all five roles, so its single constructor param stays; new narrow consumers can now depend on one role instead of the full host.
  • taskWorkspaceSeam.testUtils.ts: adds framework-free makeWorkspaceHostFake(overrides) beside the existing makeAgentTaskIntegrationFake, carrying the harness's default stub semantics (granted archive hold, "keep"-style snapshot eligibility, sanitizer no-op).
  • taskService.test.ts: createWorkspaceServiceMocks shrinks from ~180 lines to ~55 on top of the shared fake, with a mapped type over keyof WorkspaceHost replacing the hand-written 36-entry overrides list. Returned mock handles and the archive/remove locked-sink aliasing are preserved, so all 318 harness call sites are untouched.

Net LOC delta vs main (f04e0f8)

  • Production (taskWorkspaceSeam.ts): +18 (+103/-85)
  • Tests (taskService.test.ts + taskWorkspaceSeam.testUtils.ts): -76 (+112/-188)
  • Overall: -58

Irreducible production additions: the five role interface declarations plus the intersection type (the point of the refactor), and the archive race-invariant docs on ArchiveWorkspaceOptions, which review feedback correctly required keeping verbatim rather than counting as savings. Test additions are makeWorkspaceHostFake's default bodies (moved from the harness, now reusable by any seam consumer's tests).

Validation

  • Remote dogfood UAT ran against the pushed SHA and passed: sub-agent spawn/report/interrupt/reawaken, workspace turns (new + queued follow-up race), archive/unarchive including interrupt_active and live-activity refusal, heartbeats, tree listing, and monitor wakes. The UAT runner additionally verified the emitted JavaScript is byte-identical between base and feature for the production file.
  • Whole-file bun test of taskService.test.ts, workspaceService.test.ts, heartbeatService.test.ts, tools/task_list.test.ts: the fail set is identical to a clean worktree at base f04e0f8 (3 pre-existing host-environment failures; none branch-attributable).

Risks

Low. The production change is type-only interface restructuring with byte-identical emitted JS; regression surface is the test-harness consolidation, which preserves each mock's default behavior and aliasing semantics.


Generated with xum • Model: anthropic:claude-fable-5 • Thinking: xhigh • Cost: $29.31

@chatgpt-codex-connector

This comment has been minimized.

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7827948180

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/node/services/taskWorkspaceSeam.ts Outdated
@chatgpt-codex-connector

This comment has been minimized.

@ibetitsmike

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. What shall we delve into next?

Reviewed commit: 781165a30c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@chatgpt-codex-connector

This comment has been minimized.

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.

1 participant