Repository navigation
Commit df028fe
authored
🤖 refactor: segregate the task/workspace seam into role interfaces (#4012)
## 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`_
<!-- mux-attribution: model=anthropic:claude-fable-5 thinking=xhigh
costs=29.31 -->
## Stack
Layer 4/10 of the architecture refactor stack (net -5,101 LOC overall).
This PR's diff is only this layer, against
`mike/arch-peer-message-broker`.1 parent ad7f569 commit df028fe
3 files changed
Lines changed: 215 additions & 273 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
81 | 81 | | |
82 | 82 | | |
83 | 83 | | |
84 | | - | |
| 84 | + | |
85 | 85 | | |
86 | 86 | | |
| 87 | + | |
87 | 88 | | |
88 | 89 | | |
89 | 90 | | |
| |||
519 | 520 | | |
520 | 521 | | |
521 | 522 | | |
522 | | - | |
523 | | - | |
524 | | - | |
525 | | - | |
526 | | - | |
527 | | - | |
528 | | - | |
529 | | - | |
530 | | - | |
531 | | - | |
532 | | - | |
533 | | - | |
534 | | - | |
535 | | - | |
536 | | - | |
537 | | - | |
538 | | - | |
539 | | - | |
540 | | - | |
541 | | - | |
542 | | - | |
543 | | - | |
544 | | - | |
545 | | - | |
546 | | - | |
547 | | - | |
548 | | - | |
549 | | - | |
550 | | - | |
551 | | - | |
552 | | - | |
553 | | - | |
554 | | - | |
555 | | - | |
556 | | - | |
557 | | - | |
558 | | - | |
559 | | - | |
560 | | - | |
561 | | - | |
562 | | - | |
563 | | - | |
564 | | - | |
565 | | - | |
566 | | - | |
567 | | - | |
568 | | - | |
569 | | - | |
570 | | - | |
571 | | - | |
572 | | - | |
573 | | - | |
574 | | - | |
575 | | - | |
576 | | - | |
577 | | - | |
578 | | - | |
579 | | - | |
580 | | - | |
581 | | - | |
582 | | - | |
583 | | - | |
584 | | - | |
585 | | - | |
586 | | - | |
587 | | - | |
588 | | - | |
589 | | - | |
590 | | - | |
591 | | - | |
592 | | - | |
593 | | - | |
594 | | - | |
595 | | - | |
596 | | - | |
597 | | - | |
598 | | - | |
599 | | - | |
600 | | - | |
601 | | - | |
602 | | - | |
603 | | - | |
604 | | - | |
605 | | - | |
606 | | - | |
607 | | - | |
608 | | - | |
609 | | - | |
610 | | - | |
611 | | - | |
612 | | - | |
613 | | - | |
614 | | - | |
615 | | - | |
616 | | - | |
617 | | - | |
618 | | - | |
619 | | - | |
620 | | - | |
621 | | - | |
622 | | - | |
623 | | - | |
624 | | - | |
625 | | - | |
626 | | - | |
627 | | - | |
628 | | - | |
629 | | - | |
630 | | - | |
631 | | - | |
632 | | - | |
633 | | - | |
634 | | - | |
635 | | - | |
636 | | - | |
637 | | - | |
638 | | - | |
639 | | - | |
640 | | - | |
641 | | - | |
642 | | - | |
643 | | - | |
644 | | - | |
645 | | - | |
646 | | - | |
647 | | - | |
648 | | - | |
649 | | - | |
650 | | - | |
651 | | - | |
652 | | - | |
653 | | - | |
654 | | - | |
655 | | - | |
656 | | - | |
657 | | - | |
658 | | - | |
659 | | - | |
660 | | - | |
661 | | - | |
662 | | - | |
663 | | - | |
664 | | - | |
665 | | - | |
666 | | - | |
667 | | - | |
668 | | - | |
669 | | - | |
670 | | - | |
671 | | - | |
672 | | - | |
673 | | - | |
674 | | - | |
675 | | - | |
676 | | - | |
677 | | - | |
678 | | - | |
679 | | - | |
680 | | - | |
681 | | - | |
682 | | - | |
683 | | - | |
684 | | - | |
685 | | - | |
686 | | - | |
687 | | - | |
688 | | - | |
689 | | - | |
690 | | - | |
691 | | - | |
692 | | - | |
693 | | - | |
694 | | - | |
695 | | - | |
696 | | - | |
697 | | - | |
698 | | - | |
699 | | - | |
700 | | - | |
701 | | - | |
702 | | - | |
703 | | - | |
704 | | - | |
705 | | - | |
706 | | - | |
707 | | - | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
| 531 | + | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
| 541 | + | |
| 542 | + | |
| 543 | + | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
708 | 565 | | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
| 577 | + | |
709 | 578 | | |
710 | 579 | | |
711 | 580 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
2 | 57 | | |
3 | 58 | | |
4 | 59 | | |
| |||
0 commit comments