Skip to content

refactor(desktop): share the feature services context and pass bridge namespaces through - #4590

Open
chihumyum wants to merge 1 commit into
apache:mainfrom
chihumyum:refactor/feature-services-context
Open

refactor(desktop): share the feature services context and pass bridge namespaces through#4590
chihumyum wants to merge 1 commit into
apache:mainfrom
chihumyum:refactor/feature-services-context

Conversation

@chihumyum

Copy link
Copy Markdown
Contributor

Summary

Nine feature slices each restate the same twenty-line services context and hand-write Desktop adapter forwarders whose signatures equal the bridge methods they forward to (the per-slice join cost Astro-Han measured on #3439: identical services-context.tsx files, and adapters equivalent to { sessions: bridge.sessions }). This PR removes the restatement without changing any port, consumer, or behavior.

  • application/contracts/feature-services.tsx exports createServicesContext<S>(providerName), returning the Provider/hook pair. application/contracts is the one renderer zone every feature may import. Each slice's services-context.tsx is now four lines; every exported name, type, and error message (<Feature>ServicesProvider is missing) is unchanged, and connection-settings keeps its two extra components.
  • Desktop adapters hand a bridge namespace through where the port is a structural subset of it: sessions: bridge.sessions (Session Navigation), catalog: bridge.newTasks (Task Entry), scheduledTasks: bridge.scheduledTasks (Module Hub), and terminal: bridge.shellRuns, todo: bridge.todo, attachments: bridge.attachments (Workbar) — 33 identity forwarders gone. Blocks that rename, guard, filter, or translate (goal, skills, dailyReview, browser, artifacts, inspector, review, sideChat, sessionCollaboration, peerMesh) stay hand-written. I tried { ...bridge.ns, <adaptation> } for those and backed it out: the adapter tests drive Proxy-based bridge recorders that have no own keys, so a spread copies nothing, and the same would hold for any bridge double built that way. Passing the namespace object itself keeps late binding and works with every double.
  • Preload bridge namespaces are plain objects with no this usage, so passing one through is runtime-safe, and the port types stay narrow, so nothing new is reachable from feature code.
    Net: 91 lines removed across 17 files. composition/desktop-feature-services.tsx is deliberately untouched; the tenth slice from refactor(desktop): move App Update controller below AppShell #4498 can adopt the factory after it lands.

Refs #4582

Verification

On the exact head, under Node 24, all green:

  • npm --workspace @maka/desktop run test:dist — 1969/1969
  • npm --workspace @maka/desktop run typecheck — preload, main, renderer, storybook
  • npm run lint, npm run format:check
  • npm run check:renderer-architecture -- --base upstream/main, npm run check:app-shell-hooks (42 hooks / 78 call sites, unchanged)
  • npm run astryx:surface-inventory (regenerated for the new file), npx knip --workspace apps/desktop, npm run check:asf-headers, git diff --check
  • npm --workspace @maka/desktop run build:renderer

renderer-architecture.json needed no regeneration beyond the rebase: application/contracts is an explicit owner zone, so the new file is governed by zone rules rather than recorded as debt.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Claude Code — implementation and local validation. The commit carries a Generated-by: Claude Code trailer.

Checklist

  • Tests cover the change and fail without it — the existing adapter and boundary suites are the contract; no new tests, because the change removes restatement rather than adding behavior
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No

@github-actions github-actions Bot added the effort/M Under 500 readable lines label Sep 2, 2026
… namespaces through

Add application/contracts/feature-services.tsx with createServicesContext,
and derive every feature slice's ServicesProvider/useServices pair from it
instead of restating the same createContext boilerplate nine times; every
exported name, type, and error message is unchanged.

Where a Desktop adapter's port is a structural subset of one bridge
namespace, hand the namespace through (sessions, newTasks, scheduledTasks,
shellRuns, todo, attachments) instead of restating each method. Blocks that
rename, guard, filter, or translate stay hand-written: the adapter tests
drive Proxy-based bridge recorders without own keys, so a spread would copy
nothing there, and passing the object keeps late binding everywhere.

Generated-by: Claude Code
@chihumyum
chihumyum force-pushed the refactor/feature-services-context branch from 512b255 to ccc75c1 Compare September 2, 2026 20:08
@chihumyum

Copy link
Copy Markdown
Contributor Author

The first CI run failed only in Desktop e2e, on streaming-remount.spec.ts:133 (the streaming bubble did not appear within 10s after the first send). That spec exercises the send and transcript path, which this PR does not touch, and it passed locally on this head three times in a row (--repeat-each 3, 12/12). The same e2e job has flaked on unrelated PRs today: transcript-scroll.spec.ts:251 on #4440 and #4577's neighbours, streaming-remount.spec.ts:142 and send-message.spec.ts:35 on #4577, code-scroll.spec.ts:22 and transcript-measure.spec.ts:22 elsewhere. I cannot re-run the job from this account, so this push (same content, exact head ccc75c135973c3a4af9b69ae30ce5480a86e73ee) re-runs it.

Automated update from Claude Code on behalf of the PR author.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

effort/M Under 500 readable lines

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant