Skip to content

refactor(collaboration): enforce one-way Org2Cloud → collaboration-core dependencies #890

Description

@Harry19081

Problem / Motivation

Priority: P0 architecture debt. Org2Cloud and TeamCollaboration currently depend directly on each other. The file graph is acyclic today, but the feature graph is bidirectional, so ownership is unclear and changes to cloud transport, fork/import behavior, session tags, or repo-scope rules regularly cross both feature trees.

A direct source scan excluding *.test.* and *.spec.* currently finds:

  • 62 direct Org2Cloud → TeamCollaboration imports across 32 source files
  • 36 direct TeamCollaboration → Org2Cloud imports across 12 source files

Representative examples:

  • src/features/Org2Cloud/org2CloudSyncEngine.ts imports project-sync bridges, fork provenance, repo-scope resolution, and session-org tags from TeamCollaboration.
  • src/features/Org2Cloud/org2CloudBackendAdapter.ts correctly adapts managed-cloud transport to backend-agnostic collaboration contracts/codecs.
  • src/features/TeamCollaboration/forkSession.ts imports Org2Cloud access settings and org atoms, coupling otherwise backend-agnostic fork behavior to the managed-cloud implementation.
  • src/features/TeamCollaboration/cloudSessionFork.ts imports the Org2Cloud backend adapter and sync client.
  • src/features/TeamCollaboration/sessionOrgTagsAtom.ts imports the cloud org selector codec.
  • Cloud-specific UI/orchestration under TeamCollaboration (MoveToOrgDialog, CreateCollabOrgView, useForkImportedSession, autoTagNewSession) reads Org2Cloud auth, roster, endpoint, sync-engine, and client state directly.

This does not currently fail check:circular, because it is a package/ownership cycle rather than necessarily a file cycle. It nevertheless makes independent testing and replacement difficult, encourages deep imports, and makes it ambiguous whether managed-cloud policy or backend-agnostic collaboration logic owns a behavior.

Historical architecture guidance already defines the intended boundary: managed-cloud wire/auth/endpoint behavior belongs to Org2Cloud; backend-agnostic fork/import assembly and collaboration contracts belong to the collaboration domain.

Proposed Solution

Enforce this dependency direction:

higher-level composition (only where needed)
                 |
                 v
Org2Cloud adapters / policy / UI
                 |
                 v
backend-agnostic collaboration core

In concrete terms:

  1. Define a backend-agnostic collaboration core surface for fork/import contracts, segment codecs, provenance/event-id helpers, repo-scope matching, project-sync contracts, and tag vocabulary.
  2. Keep managed-cloud authentication, endpoint routing, remote clients, access policy, sync scheduling, and cloud-specific UI/orchestration in Org2Cloud.
  3. Move cloud-specific modules currently under TeamCollaboration into Org2Cloud or a higher composition layer.
  4. Replace core reads of Org2Cloud atoms/singletons with explicit inputs or narrow capability interfaces supplied by the Org2Cloud adapter.
  5. Preserve a single canonical implementation for codecs, fork integrity, provenance, repo-scope matching, and tag parsing; do not duplicate them while moving ownership.
  6. Add an automated import-boundary rule so TeamCollaboration core cannot import Org2Cloud again.

Do not solve this by introducing an unowned generic shared directory. The extracted surface must have an explicit collaboration-domain owner.

Acceptance Criteria

  • Every current cross-feature import is inventoried and classified as keep in core, move to Org2Cloud/composition, or replace with injected capability.
  • No production module under the backend-agnostic TeamCollaboration core imports src/features/Org2Cloud/**.
  • Org2Cloud consumes collaboration behavior through a documented, stable core surface instead of component-local or incidental deep imports.
  • Managed-cloud clients, auth, endpoint routing, access policy, sync-engine scheduling, and cloud-only UI do not move into the collaboration core.
  • Fork/import, snapshot-integrity, session-tag, repo-scope, comment-target, project-sync, and replay-codec behavior remain covered at their owning boundaries.
  • Existing persistence keys and persisted value formats remain compatible, or any unavoidable change includes an explicit migration and rollback plan.
  • Existing cloud wire payloads and error-code mapping remain unchanged unless separately reviewed and documented.
  • A CI-enforced boundary check rejects new TeamCollaboration core → Org2Cloud imports.
  • pnpm typecheck passes.
  • Focused Org2Cloud and TeamCollaboration tests pass.
  • pnpm check:circular passes.
  • Changed-file lint passes.

Risks

  • Moving modules can silently break Vitest mocks, lazy imports, or registration/bootstrap entry points even when TypeScript passes.
  • Fork/import behavior spans remote fetch, local persistence, execution setup, and one-shot handoff state; partial moves could create two sources of truth.
  • Session tag and fork provenance storage keys are durable local contracts and must not be accidentally reset by relocation.
  • Cloud sync admission is security/privacy-sensitive: repo-scope candidacy, explicit share intent, and access floors must retain their current order and fail-closed behavior.
  • A broad barrel may technically remove deep imports while preserving the same coupling. The boundary should be capability/domain-based, not just an index-file facade.

Non-goals

  • Merging Org2Cloud and TeamCollaboration into one feature.
  • Changing collaboration UX, cloud sync policy, sharing semantics, or retention behavior.
  • Redesigning cloud RPC/wire schemas.
  • Combining unrelated component cleanup, dead-export removal, or dependency upgrades into this work.

Verification Notes

Before implementation, capture a baseline import inventory and focused test list. After each independently mergeable phase, rerun the affected tests plus typecheck and the boundary check. The final verification should demonstrate both behavioral parity and a one-way feature dependency graph; compilation alone is insufficient.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions