Skip to content

[Refactor] Extract @clawwork/core package with port-based DI#178

Merged
samzong merged 1 commit intomainfrom
refactor/extract-core
Mar 26, 2026
Merged

[Refactor] Extract @clawwork/core package with port-based DI#178
samzong merged 1 commit intomainfrom
refactor/extract-core

Conversation

@samzong
Copy link
Copy Markdown
Collaborator

@samzong samzong commented Mar 26, 2026

Summary

Extract a new @clawwork/core package that holds all platform-agnostic business logic — stores, session sync, gateway event dispatching, protocol parsing, and error classification. Desktop stores become thin re-exports wired through an ElectronPlatformAdapter. This is the foundation for a future PWA package that can share core logic without reimplementing it.

Type of change

  • [Refactor] internal cleanup

Why is this needed?

ClawWork's renderer code directly calls window.clawwork.* from stores, hooks, and services. This couples all business logic to Electron, making it impossible to reuse in a PWA or test without mocking the entire bridge. This refactor introduces port-based dependency injection so core defines interfaces (ports) and desktop implements them (adapters).

What changed?

  • New packages/core/ with port interfaces (PersistencePort, GatewayTransportPort, SettingsPort, NotificationsPort)
  • Store factory functions: createMessageStore, createTaskStore, createUiStore accepting port deps
  • createSessionSync factory replacing direct window.clawwork calls in session-sync
  • createGatewayDispatcher factory with reset() for clean remount lifecycle
  • Protocol pure functions extracted from duplicated code in useGatewayDispatcher and session-sync (extractText, normalizeAssistantTurns, etc.)
  • ElectronPlatformAdapter mapping window.clawwork to port interfaces with lazy init (Proxy-based, test-safe)
  • Desktop store files reduced to thin re-exports — zero changes to 28+ consumer components
  • Main process ws-handlers.ts imports parseToolArgs from core (eliminates duplication)
  • Preload clawwork.d.ts derives IpcResult/ChatAttachment from @clawwork/shared
  • check-architecture.mjs and check-i18n.mjs updated to scan core package
  • knip.json, pnpm-workspace.yaml, root package.json typecheck script updated

Architecture impact

  • Owning layer: new packages/core (platform-agnostic), changes in renderer + main + preload
  • Cross-layer impact: yes — main process now imports parseToolArgs from @clawwork/core; electron.vite.config.ts updated to bundle core for main/preload
  • Invariants touched from docs/architecture-invariants.md:
    • Single-writer-per-role for message persistence: preserved — assistant messages still written only by session-sync's persistMessage calls
    • window.clawwork access boundary: now concentrated in platform/electron-adapter.ts and platform/index.ts (two escape hatches: rebuildMenu, getDeviceId)
  • Why those invariants remain protected: factory functions accept persistence deps via ports; no new DB write paths were introduced

Linked issues

Part of PWA preparation. Next PR: extract chat composer service, then create packages/pwa.

Validation

  • pnpm lint
  • pnpm test
  • pnpm check:ui-contract
  • pnpm check (full suite: lint + architecture + ui-contract + renderer-copy + i18n + dead-code + format + typecheck + test)
  • pnpm --filter @clawwork/desktop build
  • Manual smoke test
  • Not run

Commands, screenshots, or notes:

pnpm check — all 98 tests pass (6 shared + 92 desktop), all guardrails green
pnpm --filter @clawwork/desktop build — passes

Screenshots or recordings

No UI changes. All existing component imports unchanged.

Release note

  • No user-facing change. Release note is NONE.
NONE

Checklist

  • The PR title uses at least one approved prefix: [Refactor]
  • The summary explains both what changed and why
  • Validation reflects the commands actually run for this PR
  • Architecture impact is described and references any touched invariants
  • Cross-layer changes are explicitly justified
  • The release note block is accurate

Move stores, session sync, gateway dispatcher, protocol parsing, and
error classification into a new @clawwork/core package. Desktop stores
become thin re-exports wired through an ElectronPlatformAdapter.

- Port interfaces: PersistencePort, GatewayTransportPort, SettingsPort,
  NotificationsPort
- Factory functions: createMessageStore, createTaskStore, createUiStore,
  createSessionSync, createGatewayDispatcher
- Protocol pure functions extracted from useGatewayDispatcher and
  session-sync (extractText, normalizeAssistantTurns, etc.)
- Main process ws-handlers imports parseToolArgs from core
- Preload types derive IpcResult/ChatAttachment from @clawwork/shared
- Zero consumer file changes (28+ component imports unchanged)
- Viewport-based panel width defaults preserved via getViewportWidth dep
- Dispatcher reset() on unmount preserves remount/HMR lifecycle semantics
@github-actions
Copy link
Copy Markdown
Contributor

Hi @samzong,
Thanks for your pull request!
If the PR is ready, use the /auto-cc command to assign Reviewer to Review.
We will review it shortly.

Details

Instructions for interacting with me using comments are available here.
If you have questions or suggestions related to my behavior, please file an issue against the gh-ci-bot repository.

@samzong
Copy link
Copy Markdown
Collaborator Author

samzong commented Mar 26, 2026

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. You're on a roll.

ℹ️ 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".

@samzong samzong merged commit ba589e9 into main Mar 26, 2026
7 checks passed
@samzong samzong deleted the refactor/extract-core branch March 29, 2026 14:11
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