refactor(daemon): split src/daemon/types.ts into request types and session state - #2346
Open
thymikee wants to merge 3 commits into
Open
refactor(daemon): split src/daemon/types.ts into request types and session state#2346thymikee wants to merge 3 commits into
thymikee wants to merge 3 commits into
Conversation
…e modules `src/daemon/types.ts` served two audiences from one file: the dispatch request shape and the daemon's live session record. It also sat in the only daemon type cycle — it imported `RefFrame` from `ref-frame.ts`, which imported `SessionState` back — so neither file could be read in isolation. Three modules replace it, each importing only downward: - `daemon-request-wire.ts` declares `DaemonWireRequest`: a dispatched request with no `internal` key and no property path to `SessionState` or `DeviceLease`, so a consumer can read a request's command, flags and public metadata without depending on the session record. - `daemon-request.ts` adds the daemon-only half (`DaemonRequestInternal`, which stays unexported) plus the response vocabulary. - `session-state.ts` owns `SessionState` and the shapes only it holds. The cycle is cut by `ref-frame-slot.ts`, declared below both `ref-frame.ts` and `session-state.ts`: it owns the frame VALUE (the class stays unexported, so the type remains nominal and unconstructible from outside), while `ref-frame.ts` keeps every lifetime transition and every `session.refFrame` write. No behavior change: every importer moves to the module owning the symbol it uses, with no re-export shim at the old path. `client-normalizers.ts` takes `SessionRuntimeHints` from `@agent-device/kernel/contracts`, which declares it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ujrc8LYmvM249WY8921J1Y
A type-level walk over `DaemonWireRequest` fails `tsc` if the shape regains an `internal` key or grows a property path back to `SessionState` or `DeviceLease`. Positive controls over `DaemonRequest` prove the walk finds both when they are there, so a walk that never matches anything cannot pass by accident. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ujrc8LYmvM249WY8921J1Y
R7 now locates the `SessionState` declaration by the declaration itself rather than by a recorded path: `sessionStateWritePressure` measures the merge-base tree too, and that tree still declares it in `daemon/types.ts` — a path constant would measure it as zero pressure and bank the headroom. R10's external-importer ratchet covers all three modules that replaced `daemon/types.ts`, so moving a symbol between them cannot reopen the boundary to a new outside zone. The recorded membership is unchanged: `client-normalizers.ts` and `remote/daemon-artifacts.ts` both import `daemon-request.ts` only. The `live-state-shape` and session-resource declaration sites move with `SessionState`; the depgraph lookalike fixture takes a new plausible path now that `daemon/session-state.ts` is the real root. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ujrc8LYmvM249WY8921J1Y
Size Report
Startup median (7 runs, lower is better):
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #2338.
src/daemon/types.tsserved the dispatch request shape and the live session record from one file, and sat in the only daemon type cycle. Three modules replace it:src/daemon/daemon-request-wire.ts—DaemonWireRequest: nointernalkey, no property path toSessionStateorDeviceLease. This is what F1 (refactor(daemon): extract the session event journal into a workspace package #2341) consumes; it carriescommand,flags,meta.requestId,meta.clientArtifactPaths.src/daemon/daemon-request.ts—DaemonRequest= wire +internal(DaemonRequestInternalstays unexported), plusDaemonResponse/DaemonResponseData/DaemonInvokeFn/DaemonArtifact.src/daemon/session-state.ts—SessionState,SessionRef,SessionScope,SessionRuntimeHints, and the interaction-surface shapes.The cycle is cut by
ref-frame-slot.ts, declared below bothref-frame.tsandsession-state.ts. It owns the frame value (class still unexported, so the type stays nominal and unconstructible outside);ref-frame.tskeeps every transition andsession.refFramewrite — R7 rowsrefFrameandsnapshotScopeSourceare unchanged.No behavior change; no re-export shim at the old path. 407 files touched, 386 of them import-line-only — the rename/move exemption applies to the diff budget.
R9 type cycles (production graph): 19 → 18.
src/daemon/ref-frame.ts ↔ src/daemon/types.tsis gone; the other 18 are byte-identical, so no new cycle appeared. Largest cycle unchanged at 6 files (packages/provider-webdriver/*).Production importer split after the change: 197 files — 82 request-only, 42 state-only, 73 both (issue baseline: 79/35/83).
Validation
Tested at
688b1a5(the pushed head) afterpnpm install --frozen-lockfile && pnpm build.pnpm check:affected --run: every stage passes — format, lint, typecheck, layering, di-seams, fallow, gate-manifest, build, package, integration — except 2 pre-existing failures invitest-related:app-log-session-resource.test.ts > unwritable tombstone…anddurable-capture-resource.test.ts > an unconfirmed failed-adoption cleanup…. Both fail identically onorigin/main(27a97ee) in this container: it runs as root, so theirchmod-based unwritable-tombstone setup cannot deny a write. 434/436 files, 3109/3111 tests pass. Verify on CI, where the runner is unprivileged.Layering guard: R7 (31 fields classified, every write inside its owner), R9 (largest cycle 6), R10 (R7 pressure at merge-base, 2 external daemon request/session-state importers →
client/client-normalizers.ts,remote/daemon-artifacts.ts, both ondaemon-request.ts) all green. The type-level test issrc/daemon/__tests__/daemon-request-wire.test.ts; I verified it failstscwhen aninternal/SessionStatepath is reintroduced.🤖 Generated with Claude Code
https://claude.ai/code/session_01Ujrc8LYmvM249WY8921J1Y
Generated by Claude Code