Skip to content

refactor(runtime-host): derive dispatcher operation groups from spec objects - #4402

Merged
Astro-Han merged 2 commits into
apache:mainfrom
liuxiaocs7:liuxiaocs7/derive-dispatcher-operation-groups-from-the-spec
Sep 1, 2026
Merged

refactor(runtime-host): derive dispatcher operation groups from spec objects#4402
Astro-Han merged 2 commits into
apache:mainfrom
liuxiaocs7:liuxiaocs7/derive-dispatcher-operation-groups-from-the-spec

Conversation

@liuxiaocs7

@liuxiaocs7 liuxiaocs7 commented Aug 31, 2026

Copy link
Copy Markdown
Member

Summary

HOST_OPERATION_SPECS is assembled by merging per-domain spec objects, so the domain of every operation is already established by which object declares it. operation-dispatcher.ts then declared that same grouping a second time by hand, as literal Extract/Exclude lists — while three host-core groups already derived their keys with keyof typeof …_OPERATION_SPECS. This converges every group on that existing form.

  • Each group key type is now keyof typeof <DOMAIN>_OPERATION_SPECS.
  • The two groupings that had already drifted are named explicitly: SessionContinuityOperationKey = continuity + transcript spec objects; SessionCatalogOperationKey = catalog + turns (session-turns previously reached its coordinator only because the Exclude subtraction swept it there — it had no group of its own).
  • The Exclude subtraction is deleted, so a spec object that no coordinator claims is now a compile error instead of a silent reassignment into Catalog.
  • The hand-written 16-handler unavailable access/collaboration map is replaced by a loop over its two spec objects, parameterised by message (mirroring createUnavailableDomainOperationHandlers, including its operation_unavailable assertion).
  • Both HostCoreOperationKey (type) and the runtime host-core partition are driven from a single HOST_CORE_SPEC_OBJECTS declaration.

Protocol domain and coordinator ownership remain free to differ permanently; the difference is now declared once, on the server side, by naming the spec objects each coordinator serves — never the reverse.

Split-group exhaustiveness (second commit)

For the ~33 groups served by a single coordinator, the derived group type is a total OperationHandlerMap, so omitting a handler is already a compile error. Turn is the one group split across three coordinators (turn-control, interactive-turn, root-turn), each Pick-ing a fixed subset. Because composeRuntimeHostDomainHandlers seeds every domain operation with the operation_unavailable fallback, a Turn operation that none of the three claimed compiled and silently kept the fallback — the exact "coordinator serves only part of a spec object" case the issue's step 3 flags.

The second commit closes that gap with a satisfies TurnOperationHandlerMap completeness assertion where the three coordinators are already merged (execution-composition.ts). An unclaimed Turn operation is now a typecheck error at the composition site, so the issue's step‑5 guarantee ("removing its handler is a compile error") holds for the split group too.

Fixes #4395

Verification

All run locally in packages/runtime-host:

  • npm run typecheck — pass (exit 0)
  • npm run build — pass (exit 0)
  • npx biome lint / biome format on the changed files — clean
  • npm run test:dist1467 pass, 12 skipped, 0 fail (1479 tests)

Followed the issue's suggested method: added temporary per-group AssertEqual<oldForm, derivedForm> instantiations and typechecked to confirm each derived form is exactly equal to the hand-written one, then removed them. For the split-group fix I ran the reviewer's own probe — temporarily adding turn.review-probe to TURN_OPERATION_SPECS — and confirmed the Runtime Host typecheck now fails with TS2741 ("turn.review-probe" missing but required in TurnOperationHandlerMap) at the composition site, then reverted the probe.

Review response

Addresses the P2 finding on the first revision (split Turn coordinators could omit a newly declared operation without a type error). The compile-time assertion is added in the second commit; the earlier over-claim in this description is corrected above.

Rebase & CI note

Rebased onto latest main. The only code conflict was in operation-dispatcher.ts: main had added a new plugin.* operation group in the region this PR rewrites — resolved by converging that group to the same derived form (keyof typeof PLUGIN_PLATFORM_OPERATION_SPECS). The two changed files are operation-dispatcher.ts and execution-composition.ts; no other files are touched.

AI use

Select exactly one:

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

Tool(s) and scope: Claude Code — implemented the refactor (deriving the group types, removing the subtraction, the two loop/single-source collapses) and the split-group exhaustiveness assertion, and ran the verification above. Reviewed by me before submitting. Both commits carry a Generated-by: Claude Code trailer.

Checklist

  • Tests cover the change and fail without it
  • 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 Aug 31, 2026

@hqhq1025 hqhq1025 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I found one non-blocking correctness gap in the claimed compile-time ownership guarantee. The derived domain aliases match the current protocol, but split coordinators can still omit a newly declared operation without a type error; details are inline.

Validation completed on this exact head: clean install, npm run build:test, full repository typecheck, lint, format, git diff --check, focused dispatcher key-set probes, and a clean synthetic merge with current main. The full Runtime Host suite reported 1466 pass / 1 fail / 12 skip; the sole managed-sandbox failure reproduces on the exact merge base and is not attributable to this change. The hosted test check is still running.

Automated review notice: This comment was posted by an automated review agent operated by hqhq1025. It is not an independent human review and does not replace one.

Comment thread packages/runtime-host/src/server/operation-dispatcher.ts
@liuxiaocs7
liuxiaocs7 force-pushed the liuxiaocs7/derive-dispatcher-operation-groups-from-the-spec branch from 6976844 to bcf9e70 Compare September 1, 2026 06:35
…objects

The operation dispatcher declared each coordinator's operation grouping a
second time by hand — as literal Extract/Exclude lists — even though the
per-domain spec objects that compose HOST_OPERATION_SPECS already establish
which operations belong together. Converge on the derived form the file's
host-core groups already use.

- Every group key type is now `keyof typeof <DOMAIN>_OPERATION_SPECS`.
- Name the two groupings that already spanned/omitted spec objects:
  SessionContinuity = continuity + transcript; SessionCatalog = catalog +
  turns (previously reached its coordinator only via the subtraction sweep).
- Delete the `Exclude` subtraction, so a spec object no coordinator claims is
  a compile error rather than a silent reassignment into Catalog.
- Replace the hand-written unavailable access/collaboration handler map with a
  loop over its two spec objects, parameterised by message.
- Drive both `HostCoreOperationKey` and the runtime host-core partition from a
  single `HOST_CORE_SPEC_OBJECTS` declaration.

Protocol domain and coordinator ownership remain free to differ; the
difference is now declared once, on the server side, by naming the spec
objects each coordinator serves.

Fixes apache#4395

Generated-by: Claude Code
…he spec

The Turn spec object is served by three coordinators that each Pick a fixed
subset of TurnOperationHandlerMap. Because domain composition seeds every
domain operation with the operation_unavailable fallback, a Turn operation
added to TURN_OPERATION_SPECS that no coordinator claims compiled and silently
kept the fallback rather than failing.

Add a `satisfies TurnOperationHandlerMap` completeness assertion where the
three coordinators are already merged, so an unclaimed Turn operation is a
typecheck error at the composition site. Verified: adding a probe key to
TURN_OPERATION_SPECS now fails the Runtime Host typecheck (TS2741) instead of
passing.

Refs apache#4395

Generated-by: Claude Code
@liuxiaocs7
liuxiaocs7 force-pushed the liuxiaocs7/derive-dispatcher-operation-groups-from-the-spec branch from 4318f87 to d282588 Compare September 1, 2026 11:05

@hqhq1025 hqhq1025 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The previous Turn ownership finding is fixed on d282588c56a24883e745a9541fbee85eda9da359; I did not find any remaining P0-P3 issue in this revision.

The new completeness assertion covers the same three handler maps used by the production execution module. A temporary added Turn operation now fails the Runtime Host build with TS2741 at execution-composition.ts:1194, instead of silently retaining the unavailable fallback. I also checked the complete dispatcher-group refactor, unavailable-handler key partition, and the current-main synthetic merge.

Validation completed: clean install, npm run build:test, full repository typecheck, changed-file lint/format, ASF headers, git diff --check, focused dispatcher/host/execution composition tests (25/25), and a clean synthetic merge with current main. The full Runtime Host suite reported 1541 pass / 1 fail / 12 skip; the sole live-sandbox failure reproduces on the current-main synthetic merge and is not attributable to this PR. Hosted plan, heavy, and windows_recovery are green; the final hosted test job is still queued, so this review does not claim that merge gates are complete.

Automated review notice: This comment was posted by an automated review agent operated by hqhq1025. It is not an independent human review and does not replace one.

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks — reviewed d282588c. No findings.

@hqhq1025 already covered the split-Turn gap and confirmed the satisfies TurnOperationHandlerMap fix with a probe, so I checked the thing a type-level regrouping is most likely to get wrong silently: whether routing is preserved.

The old SessionCatalogOperationKey was a residue — all session.* minus five groups — and the new one is an explicit union of the catalog and turns spec objects. Those agree only if every session.* key lives in one of the seven named spec objects. It does: the keys are distributed across session-catalog (6), session-revision (3), session-retirement (3), session-transcript (2), session-continuity (2), session-turns (1), session-todo (1), session-effects (1), with nothing declared elsewhere. So the residue and the union are the same set and no operation changes coordinator. The description's claim that session-turns previously reached its coordinator only by being swept into the residue is accurate, and it now lands in the same place by name.

The 36 new imports are the honest price of deriving from the spec objects rather than restating them, and the file still comes out 78 lines lighter on a form the codebase already used in three places. Deleting the Exclude so an unclaimed spec object becomes a compile error rather than a silent reassignment into Catalog is the part that actually pays.

Evidence boundary: I read the dispatcher diff and enumerated the session.*/subscription.* key distribution across the protocol directory on this head. I did not re-run the suites or repeat @hqhq1025's Turn probe.


AI-assisted review: drafted with Maka; I verified the key distribution and the old/new set equivalence against the branch source myself.

@Astro-Han
Astro-Han merged commit 5c1bbe3 into apache:main Sep 1, 2026
4 checks passed
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.

Derive dispatcher operation groups from the spec objects that already define them

3 participants