diff --git a/docs/adr/0018-unified-event-journal.md b/docs/adr/0018-unified-event-journal.md index b50d18d58b..44a0dbfffa 100644 --- a/docs/adr/0018-unified-event-journal.md +++ b/docs/adr/0018-unified-event-journal.md @@ -59,7 +59,7 @@ redaction discipline, and sink (inventoried 2026-07-24): `phaseCounts` tally, and debug-mode live streaming to the per-request ndjson file (after `createRequestExecutionScope` rebinds `logPath`), `daemon.log`, or stderr. The `traceLogPath` scope option is dead: no call site ever sets it. -2. **Session event log** (`src/daemon/session-event-log.ts`). Append-only per-session +2. **Session event log** (`@agent-device/session-journal/session-event-log`). Append-only per-session `events.ndjson` with kinds `request.started`/`request.finished`/`action.recorded`, written from three request-lifecycle points plus `SessionStore.recordAction`, read only by the public `events` command. `action.recorded` is already a projection of `session.actions` pushes — the diff --git a/package.json b/package.json index 2533eaa41a..dbc19f6288 100644 --- a/package.json +++ b/package.json @@ -167,7 +167,7 @@ "check:unit": "pnpm test:unit && pnpm check:tmpdir-leaks && pnpm test:smoke", "check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit", "prepack": "pnpm check:mcp-metadata && pnpm package:npm", - "typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/host-kit packages/capture-kit packages/managed-allocation packages/provision-kit packages/platform-apple packages/platform-android packages/platform-harmonyos packages/platform-vega packages/platform-linux packages/platform-web packages/ad-script packages/selectors packages/command-registry packages/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json", + "typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/host-kit packages/capture-kit packages/managed-allocation packages/provision-kit packages/platform-apple packages/platform-android packages/platform-harmonyos packages/platform-vega packages/platform-linux packages/platform-web packages/ad-script packages/selectors packages/command-registry packages/session-journal packages/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json", "test-app:install": "pnpm install --dir examples/test-app", "test-app:start": "pnpm --dir examples/test-app start", "test-app:ios": "pnpm --dir examples/test-app ios", @@ -294,6 +294,7 @@ "@agent-device/provision-kit": "workspace:*", "@agent-device/replay-test": "workspace:*", "@agent-device/selectors": "workspace:*", + "@agent-device/session-journal": "workspace:*", "@agent-device/xml": "workspace:*", "@arethetypeswrong/cli": "^0.18.5", "@chenglou/freerange": "^0.0.4", diff --git a/packages/host-kit/src/code-signature.test.ts b/packages/host-kit/src/code-signature.test.ts index 920f555511..83b21dc1cb 100644 --- a/packages/host-kit/src/code-signature.test.ts +++ b/packages/host-kit/src/code-signature.test.ts @@ -134,3 +134,26 @@ test('the daemon source graph stamps the command descriptor registry package', ( assert.ok(labels.includes(owned), `${owned} is missing from the daemon code graph`); } }); + +/** + * The same claim for the ADR 0018 event journal (#2341). The daemon writes and reads + * `events.ndjson` only through this package's workspace subpaths, so a walk that stopped at the + * package boundary would report an unchanged signature after an entry-shape or retention-window + * edit, and a client would keep reusing a daemon writing the superseded journal. The manifest is + * asserted beside the sources because its `exports` map is what chose them. + */ +test('the daemon source graph stamps the session event journal package', () => { + const repoRoot = path.resolve(import.meta.dirname, '..', '..', '..'); + const entryPath = path.join(repoRoot, 'src', 'daemon.ts'); + if (!fs.existsSync(entryPath)) return; + + const labels = labelsOf(entryPath, repoRoot); + for (const owned of [ + 'packages/session-journal/src/session-event-log.ts', + 'packages/session-journal/src/session-event-log-window.ts', + 'packages/session-journal/src/session-event-action.ts', + 'packages/session-journal/package.json', + ]) { + assert.ok(labels.includes(owned), `${owned} is missing from the daemon code graph`); + } +}); diff --git a/packages/session-journal/package.json b/packages/session-journal/package.json new file mode 100644 index 0000000000..d23e2faf8c --- /dev/null +++ b/packages/session-journal/package.json @@ -0,0 +1,44 @@ +{ + "name": "@agent-device/session-journal", + "version": "0.0.0", + "private": true, + "sideEffects": false, + "type": "module", + "description": "The ADR 0018 unified request event journal: the append-only per-session event log, its rotation window and line scanner, and the presentation projections that turn a dispatched request or action into a journal entry.", + "dependencies": { + "@agent-device/command-registry": "workspace:*", + "@agent-device/contracts": "workspace:*", + "@agent-device/host-kit": "workspace:*", + "@agent-device/kernel": "workspace:*" + }, + "exports": { + "./session-event-log": { + "types": "./src/session-event-log.ts", + "default": "./src/session-event-log.ts" + }, + "./session-event-log-lines": { + "types": "./src/session-event-log-lines.ts", + "default": "./src/session-event-log-lines.ts" + }, + "./session-event-log-window": { + "types": "./src/session-event-log-window.ts", + "default": "./src/session-event-log-window.ts" + }, + "./session-event-request": { + "types": "./src/session-event-request.ts", + "default": "./src/session-event-request.ts" + }, + "./session-event-action": { + "types": "./src/session-event-action.ts", + "default": "./src/session-event-action.ts" + }, + "./session-event-action-presentation": { + "types": "./src/session-event-action-presentation.ts", + "default": "./src/session-event-action-presentation.ts" + }, + "./keyboard-actions": { + "types": "./src/keyboard-actions.ts", + "default": "./src/keyboard-actions.ts" + } + } +} diff --git a/packages/session-journal/src/__tests__/journal-request-input.test.ts b/packages/session-journal/src/__tests__/journal-request-input.test.ts new file mode 100644 index 0000000000..742f69c174 --- /dev/null +++ b/packages/session-journal/src/__tests__/journal-request-input.test.ts @@ -0,0 +1,150 @@ +import type { DeviceInfo } from '@agent-device/kernel/device'; +import type { DeviceLease } from '@agent-device/contracts/device'; +import { expectTypeOf, test } from 'vitest'; +import { buildActionEventResult } from '../session-event-action-presentation.ts'; +import { + buildRequestFinishedEvent, + buildRequestStartedEvent, + shouldRecordEventForRequest, +} from '../session-event-log.ts'; +import { + buildRequestSuccessEventPresentation, + readRequestedScreenshotFileName, +} from '../session-event-request.ts'; + +/** + * Every request-shaped parameter this package accepts, read off the real signatures rather than + * restated. Widening any one of them back to the daemon's own `DaemonRequest` — the type that + * carries `internal` with its `SessionState` callbacks and admitted `DeviceLease` — changes this + * union, and the assertions below stop holding. + */ +type JournalRequestInput = + | Parameters[0]['req'] + | Parameters[0]['req'] + | Parameters[0] + | Parameters[0] + | Parameters[0] + | Parameters[0]; + +type Primitive = string | number | boolean | bigint | symbol | null | undefined; + +/** + * Recursion budget. Six is not asserted to be deep enough by inspection: the last assertion in + * this file walks again at twelve and requires the two answers to be identical, so a budget that + * stopped short of some path would show up as a type the deeper walk found and this one did not. + */ +type Budget = [0, 0, 0, 0, 0, 0]; + +/** Twice the budget, for the saturation check. */ +type DoubleBudget = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; + +/** + * `T`'s own declared keys, with index signatures dropped. Keeping `string` would silently absorb + * every literal beside it in a union (`string | 'internal'` reduces to `string`), which would make + * the assertion below vacuous the moment a `Record` appears on a path — and one + * does, at `flags`. A record that could hold an `internal` property is not a declared route to + * session state; a declared `internal` key is. + */ +type DeclaredKeys = keyof { [K in keyof T as string extends K ? never : K]: 0 }; + +/** Every declared property NAME reachable from `T`, arrays entered through their element type. */ +type ReachableKeys< + T, + Cap extends readonly unknown[], + Depth extends readonly unknown[] = [], +> = Depth['length'] extends Cap['length'] + ? never + : [T] extends [Primitive] + ? never + : [T] extends [(...args: never[]) => unknown] + ? never + : T extends readonly (infer Element)[] + ? ReachableKeys + : T extends object + ? + | DeclaredKeys + | { [K in keyof T]-?: ReachableKeys, Cap, [...Depth, 0]> }[keyof T] + : never; + +/** + * Every property TYPE reachable from `T`. Arrays are entered through their element type, and a + * function through its PARAMETERS: that is how the daemon's `internal` actually hands out a live + * session record (`beforeDispatch?: (session: SessionState) => …`), so a walk that treated a + * callback as a leaf would never see the very route this file exists to reject. + */ +type ReachableTypes< + T, + Cap extends readonly unknown[], + Depth extends readonly unknown[] = [], +> = Depth['length'] extends Cap['length'] + ? never + : [T] extends [Primitive] + ? never + : [T] extends [(...args: never[]) => unknown] + ? ReachableTypes, Cap, [...Depth, 0]> + : T extends readonly (infer Element)[] + ? Element | ReachableTypes + : T extends object + ? { + [K in keyof T]-?: + | NonNullable + | ReachableTypes, Cap, [...Depth, 0]>; + }[keyof T] + : never; + +/** + * The structural minimum of `src/daemon/session-state.ts`'s `SessionState`. The package may not + * import that module (R11), so the live session record is named by the three required fields no + * other shape in the public request vocabulary carries together. Anything typed as `SessionState` + * is assignable to this, which is what `Extract` needs. + */ +type LiveSessionRecord = { name: string; device: DeviceInfo; createdAt: number }; + +/** A callback of any arity — the form `SessionState` takes when it reaches a request. */ +type AnyCallback = (...args: never[]) => unknown; + +test('the journal reads a request shape with no route to daemon-private session state', () => { + // ADR 0018's journal is durable and rendered outside the daemon. Its input is the public + // request vocabulary of `@agent-device/kernel/contracts`: `command`, `flags`, `meta.requestId` + // and `meta.clientArtifactPaths`. The daemon's own request type adds `internal`, whose members + // hand out `SessionState` and an admitted `DeviceLease`; taking it here would put a live + // session record on a path the journal could serialize. + expectTypeOf< + Extract, 'internal'> + >().toEqualTypeOf(); + expectTypeOf< + Extract, LiveSessionRecord> + >().toEqualTypeOf(); + expectTypeOf< + Extract, DeviceLease> + >().toEqualTypeOf(); + expectTypeOf< + Extract, AnyCallback> + >().toEqualTypeOf(); +}); + +/** + * The budget is a fixed point, not a guess. Walking again at twice the depth must reveal no key + * and no type the six-deep walk missed; if the public request vocabulary ever grows a path deeper + * than the budget, this fails here rather than quietly narrowing the assertions above. + * + * What the walk deliberately does not see: a route through an index signature. `flags` and `input` + * are `Record`, so a value stashed under a record key is invisible to a type-level + * walk by construction — `DeclaredKeys` drops index signatures precisely so their `string` cannot + * absorb the literal keys beside it. The claim is about DECLARED routes, which is what a type can + * carry; a record that could hold anything is not one. + */ +test('the six-deep walk is saturated: twice the budget finds nothing more', () => { + expectTypeOf< + Exclude< + ReachableKeys, + ReachableKeys + > + >().toEqualTypeOf(); + expectTypeOf< + Exclude< + ReachableTypes, + ReachableTypes + > + >().toEqualTypeOf(); +}); diff --git a/src/daemon/__tests__/session-event-action.test.ts b/packages/session-journal/src/__tests__/session-event-action.test.ts similarity index 100% rename from src/daemon/__tests__/session-event-action.test.ts rename to packages/session-journal/src/__tests__/session-event-action.test.ts diff --git a/src/daemon/__tests__/session-event-log-window.test.ts b/packages/session-journal/src/__tests__/session-event-log-window.test.ts similarity index 99% rename from src/daemon/__tests__/session-event-log-window.test.ts rename to packages/session-journal/src/__tests__/session-event-log-window.test.ts index 57a2fd1325..cd0cd19637 100644 --- a/src/daemon/__tests__/session-event-log-window.test.ts +++ b/packages/session-journal/src/__tests__/session-event-log-window.test.ts @@ -3,7 +3,7 @@ import assert from 'node:assert/strict'; import fs from 'node:fs'; import path from 'node:path'; import { AppError } from '@agent-device/kernel/errors'; -import { mkdtempForTestSync } from '../../__tests__/test-utils/tmp-dir.ts'; +import { mkdtempForTestSync } from './test-utils/tmp-dir.ts'; import { appendSessionEvent, flushSessionEventLogWrites, diff --git a/src/daemon/__tests__/session-event-request.test.ts b/packages/session-journal/src/__tests__/session-event-request.test.ts similarity index 99% rename from src/daemon/__tests__/session-event-request.test.ts rename to packages/session-journal/src/__tests__/session-event-request.test.ts index 1b3c42e5ea..962d4221c5 100644 --- a/src/daemon/__tests__/session-event-request.test.ts +++ b/packages/session-journal/src/__tests__/session-event-request.test.ts @@ -1,7 +1,7 @@ import assert from 'node:assert/strict'; import { test } from 'vitest'; import { buildRequestFinishedEvent, buildRequestStartedEvent } from '../session-event-log.ts'; -import type { DaemonRequest, DaemonResponseData } from '../daemon-request.ts'; +import type { DaemonRequest, DaemonResponseData } from '@agent-device/kernel/contracts'; function buildSuccessEvent( command: string, diff --git a/packages/session-journal/src/__tests__/test-utils/tmp-dir.ts b/packages/session-journal/src/__tests__/test-utils/tmp-dir.ts new file mode 100644 index 0000000000..9a7734edcb --- /dev/null +++ b/packages/session-journal/src/__tests__/test-utils/tmp-dir.ts @@ -0,0 +1,13 @@ +import fs from 'node:fs'; +import os from 'node:os'; +import path from 'node:path'; + +/** + * Creates a fresh scratch directory for one test. Cleanup is automatic: the + * unit suite redirects TMPDIR to a per-run directory (scripts/vitest-tmpdir-global-setup.ts) + * that gets removed in one recursive rm after every worker finishes, so + * individual tests never need their own afterEach/afterAll for this. + */ +export function mkdtempForTestSync(prefix: string): string { + return fs.mkdtempSync(path.join(os.tmpdir(), prefix)); +} diff --git a/src/core/keyboard-actions.ts b/packages/session-journal/src/keyboard-actions.ts similarity index 100% rename from src/core/keyboard-actions.ts rename to packages/session-journal/src/keyboard-actions.ts diff --git a/src/daemon/session-event-action-presentation.ts b/packages/session-journal/src/session-event-action-presentation.ts similarity index 98% rename from src/daemon/session-event-action-presentation.ts rename to packages/session-journal/src/session-event-action-presentation.ts index 956a3c5fff..13d2b569d4 100644 --- a/src/daemon/session-event-action-presentation.ts +++ b/packages/session-journal/src/session-event-action-presentation.ts @@ -3,7 +3,7 @@ import { DEVICE_ROTATIONS } from '@agent-device/contracts/device'; import { BACK_MODES } from '@agent-device/contracts/back-mode'; import { TV_REMOTE_BUTTONS } from '@agent-device/contracts/tv-remote'; import { PUBLIC_COMMANDS } from '@agent-device/command-registry/catalog'; -import { isKeyboardAction } from '../core/keyboard-actions.ts'; +import { isKeyboardAction } from './keyboard-actions.ts'; import { compactSessionEventDetails as compactDetails, readSessionEventBoolean as readBoolean, @@ -14,7 +14,7 @@ import { readSessionEventNumber, readSessionEventString, } from './session-event-request.ts'; -import type { DaemonRequest } from './daemon-request.ts'; +import type { DaemonRequest } from '@agent-device/kernel/contracts'; const SCROLL_DIRECTIONS = ['up', 'down', 'left', 'right'] as const; const SCROLL_EDGES = ['top', 'bottom'] as const; diff --git a/src/daemon/session-event-action.ts b/packages/session-journal/src/session-event-action.ts similarity index 100% rename from src/daemon/session-event-action.ts rename to packages/session-journal/src/session-event-action.ts diff --git a/src/daemon/session-event-log-lines.ts b/packages/session-journal/src/session-event-log-lines.ts similarity index 100% rename from src/daemon/session-event-log-lines.ts rename to packages/session-journal/src/session-event-log-lines.ts diff --git a/src/daemon/session-event-log-window.ts b/packages/session-journal/src/session-event-log-window.ts similarity index 100% rename from src/daemon/session-event-log-window.ts rename to packages/session-journal/src/session-event-log-window.ts diff --git a/src/daemon/session-event-log.ts b/packages/session-journal/src/session-event-log.ts similarity index 99% rename from src/daemon/session-event-log.ts rename to packages/session-journal/src/session-event-log.ts index 84f6c2df9e..5ad29b8247 100644 --- a/src/daemon/session-event-log.ts +++ b/packages/session-journal/src/session-event-log.ts @@ -6,7 +6,7 @@ import { AppError } from '@agent-device/kernel/errors'; import { redactDiagnosticData } from '@agent-device/kernel/redaction'; import { emitDiagnostic, getDiagnosticsMeta } from '@agent-device/host-kit/diagnostics'; import { isRecord } from '@agent-device/kernel/record'; -import type { DaemonRequest, DaemonResponse } from './daemon-request.ts'; +import type { DaemonRequest, DaemonResponse } from '@agent-device/kernel/contracts'; import { buildActionDetails, buildActionSummary } from './session-event-action.ts'; import { buildRequestSuccessEventPresentation } from './session-event-request.ts'; import { scanEventLogLines } from './session-event-log-lines.ts'; diff --git a/src/daemon/session-event-request.ts b/packages/session-journal/src/session-event-request.ts similarity index 99% rename from src/daemon/session-event-request.ts rename to packages/session-journal/src/session-event-request.ts index fa2100d2f0..e686c22f1f 100644 --- a/src/daemon/session-event-request.ts +++ b/packages/session-journal/src/session-event-request.ts @@ -1,6 +1,6 @@ import { PUBLIC_COMMANDS } from '@agent-device/command-registry/catalog'; import { isRecord } from '@agent-device/kernel/record'; -import type { DaemonRequest, DaemonResponseData } from './daemon-request.ts'; +import type { DaemonRequest, DaemonResponseData } from '@agent-device/kernel/contracts'; const EVENT_LIST_PREVIEW_LIMIT = 5; const EVENT_LIST_SUMMARY_LIMIT = 3; diff --git a/packages/session-journal/tsconfig.json b/packages/session-journal/tsconfig.json new file mode 100644 index 0000000000..005119d52e --- /dev/null +++ b/packages/session-journal/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": true, + "noEmit": false, + "emitDeclarationOnly": true, + "declaration": true, + "declarationDir": "./dist-types", + "rootDir": "./src" + }, + // The command-registry sources this package imports read the `__OWNER_FILES__` build-time flag + // declared beside them. The root and examples projects already carry that declaration for the + // same reason; a package program that reaches registry.ts needs it too. + "include": ["src", "../command-registry/src/global.d.ts"] +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bedab6ee19..f6df692202 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -77,6 +77,9 @@ importers: '@agent-device/selectors': specifier: workspace:* version: link:packages/selectors + '@agent-device/session-journal': + specifier: workspace:* + version: link:packages/session-journal '@agent-device/xml': specifier: workspace:* version: link:packages/xml @@ -480,6 +483,21 @@ importers: specifier: ^4.9.0 version: 4.9.0 + packages/session-journal: + dependencies: + '@agent-device/command-registry': + specifier: workspace:* + version: link:../command-registry + '@agent-device/contracts': + specifier: workspace:* + version: link:../contracts + '@agent-device/host-kit': + specifier: workspace:* + version: link:../host-kit + '@agent-device/kernel': + specifier: workspace:* + version: link:../kernel + packages/xml: {} website: diff --git a/scripts/layering/model.ts b/scripts/layering/model.ts index f022be9e76..38134e50ad 100644 --- a/scripts/layering/model.ts +++ b/scripts/layering/model.ts @@ -46,6 +46,7 @@ const TARGET_DAG_RANK = new Map([ ['request', 1], ['screenshot-diff', 1], ['selectors', 1], + ['session-journal', 1], ['snapshot', 1], ['core', 2], ['cli-schema', 3], diff --git a/src/__tests__/command-descriptor-post-action-observation.test.ts b/src/__tests__/command-descriptor-post-action-observation.test.ts index 966a08d0f6..d12ebaeeaa 100644 --- a/src/__tests__/command-descriptor-post-action-observation.test.ts +++ b/src/__tests__/command-descriptor-post-action-observation.test.ts @@ -12,7 +12,7 @@ import { } from '../commands/family/registry.ts'; import type { SettleCapableClientOptionCommands } from '../commands/post-action-observation-client-options.ts'; import { getCliCommandSchema } from '../cli-schema/command-schema.ts'; -import { buildActionDetails } from '../daemon/session-event-action.ts'; +import { buildActionDetails } from '@agent-device/session-journal/session-event-action'; import { COMMAND_OUTPUT_SCHEMAS } from '../mcp/command-output-schemas.ts'; import { commandDescriptors, diff --git a/src/commands/system/runtime/system.ts b/src/commands/system/runtime/system.ts index 96ed707695..f4e9c576e1 100644 --- a/src/commands/system/runtime/system.ts +++ b/src/commands/system/runtime/system.ts @@ -11,7 +11,7 @@ import type { BackMode } from '@agent-device/contracts/back-mode'; import { parseTvRemoteButton } from '@agent-device/contracts/tv-remote'; import { AppError } from '@agent-device/kernel/errors'; import { successText } from '@agent-device/kernel/success-text'; -import { isKeyboardAction } from '../../../core/keyboard-actions.ts'; +import { isKeyboardAction } from '@agent-device/session-journal/keyboard-actions'; import { requireIntInRange } from '../../../core/validation.ts'; import { toBackendResult, diff --git a/src/daemon/__tests__/request-save-script-transports.test.ts b/src/daemon/__tests__/request-save-script-transports.test.ts index 78a90663f4..e750abceb9 100644 --- a/src/daemon/__tests__/request-save-script-transports.test.ts +++ b/src/daemon/__tests__/request-save-script-transports.test.ts @@ -32,7 +32,7 @@ import { skipWhenLoopbackUnavailable, } from '../../__tests__/test-utils/loopback.ts'; import { mkdtempForTestSync } from '../../__tests__/test-utils/tmp-dir.ts'; -import { flushSessionEventLogWrites } from '../session-event-log.ts'; +import { flushSessionEventLogWrites } from '@agent-device/session-journal/session-event-log'; const TOKEN = 'save-script-transport-token'; const SESSION = 'save-script-transport'; diff --git a/src/daemon/__tests__/session-store.test.ts b/src/daemon/__tests__/session-store.test.ts index 37f757e85f..1e02647ff3 100644 --- a/src/daemon/__tests__/session-store.test.ts +++ b/src/daemon/__tests__/session-store.test.ts @@ -6,7 +6,7 @@ import path from 'node:path'; import { AppError } from '@agent-device/kernel/errors'; import { SessionStore } from '../session-store.ts'; import type { SessionState } from '../session-state.ts'; -import { buildRequestFinishedEvent } from '../session-event-log.ts'; +import { buildRequestFinishedEvent } from '@agent-device/session-journal/session-event-log'; import { HEAL_COMPLETE_SENTINEL } from '../session-script-writer.ts'; import { parseReplayScriptDetailed } from '@agent-device/ad-script'; import type { TargetAnnotationV1 } from '@agent-device/contracts/replay'; diff --git a/src/daemon/keyboard-runtime.ts b/src/daemon/keyboard-runtime.ts index 9b0bcfbe20..e35d84970c 100644 --- a/src/daemon/keyboard-runtime.ts +++ b/src/daemon/keyboard-runtime.ts @@ -17,7 +17,10 @@ import type { } from '@agent-device/contracts/platform-runtime'; import type { DeviceInfo } from '@agent-device/kernel/device'; import { AppError } from '@agent-device/kernel/errors'; -import { isKeyboardAction, type KeyboardAction } from '../core/keyboard-actions.ts'; +import { + isKeyboardAction, + type KeyboardAction, +} from '@agent-device/session-journal/keyboard-actions'; import { successText } from '@agent-device/kernel/success-text'; import type { DaemonCommandContext } from './context.ts'; import { diff --git a/src/daemon/replay/internal/session-replay-action-runtime.ts b/src/daemon/replay/internal/session-replay-action-runtime.ts index 65c39bcfbb..bc99182880 100644 --- a/src/daemon/replay/internal/session-replay-action-runtime.ts +++ b/src/daemon/replay/internal/session-replay-action-runtime.ts @@ -7,7 +7,7 @@ import { gesturePayloadFromPositionals, swipePayloadFromPositionals, } from '@agent-device/contracts/gesture-normalization'; -import { buildDisplayPositionals } from '../../session-event-action.ts'; +import { buildDisplayPositionals } from '@agent-device/session-journal/session-event-action'; import { appendReplayTraceEvent } from './session-replay-trace.ts'; import { inferFillText } from '../../action-utils.ts'; import { readRecordedInputVariableName } from '@agent-device/ad-script'; diff --git a/src/daemon/replay/internal/session-replay-runtime-failure-response.ts b/src/daemon/replay/internal/session-replay-runtime-failure-response.ts index 046eeef848..ca347f7cd7 100644 --- a/src/daemon/replay/internal/session-replay-runtime-failure-response.ts +++ b/src/daemon/replay/internal/session-replay-runtime-failure-response.ts @@ -2,7 +2,7 @@ import type { SessionAction } from '@agent-device/contracts/session'; import { scrubReplayVarValues, type ReplayVarScrubEntry } from '../../../core/replay-divergence.ts'; import { formatDivergenceActionLabel } from '@agent-device/ad-script'; import type { SnapshotDiagnosticsSummary } from '@agent-device/contracts/capture'; -import { buildDisplayPositionals } from '../../session-event-action.ts'; +import { buildDisplayPositionals } from '@agent-device/session-journal/session-event-action'; import type { DaemonResponse } from '../../daemon-request.ts'; export type ReplayFailureCause = Extract['error']; diff --git a/src/daemon/request-execution-scope.ts b/src/daemon/request-execution-scope.ts index fd1e01f205..5a5cfdaeb3 100644 --- a/src/daemon/request-execution-scope.ts +++ b/src/daemon/request-execution-scope.ts @@ -35,7 +35,7 @@ import { buildRequestFinishedEvent, buildRequestStartedEvent, shouldRecordEventForRequest, -} from './session-event-log.ts'; +} from '@agent-device/session-journal/session-event-log'; import type { LeaseRegistry } from './lease-registry.ts'; import { resolveSessionRequestLog, diff --git a/src/daemon/request-generic-dispatch.ts b/src/daemon/request-generic-dispatch.ts index 23fd74085a..b19ae38ab1 100644 --- a/src/daemon/request-generic-dispatch.ts +++ b/src/daemon/request-generic-dispatch.ts @@ -21,7 +21,7 @@ import { shouldGuardAndroidBlockingDialog, } from './daemon-command-registry.ts'; import { isActiveProviderDevice } from '../provider-device-runtime.ts'; -import { buildActionEventResult } from './session-event-action-presentation.ts'; +import { buildActionEventResult } from '@agent-device/session-journal/session-event-action-presentation'; import type { AndroidObservationAdapter } from '@agent-device/contracts/android-observation'; export type GenericPlatformExecutionParams = { diff --git a/src/daemon/session-lifecycle/internal/__tests__/session-close-script.test.ts b/src/daemon/session-lifecycle/internal/__tests__/session-close-script.test.ts index ec2b9a1aac..34acf3f61e 100644 --- a/src/daemon/session-lifecycle/internal/__tests__/session-close-script.test.ts +++ b/src/daemon/session-lifecycle/internal/__tests__/session-close-script.test.ts @@ -15,7 +15,7 @@ import { finalizeOrdinaryCloseScript, } from '../session-close-script.ts'; import { mkdtempForTestSync } from '../../../../__tests__/test-utils/tmp-dir.ts'; -import { flushSessionEventLogWrites } from '../../../session-event-log.ts'; +import { flushSessionEventLogWrites } from '@agent-device/session-journal/session-event-log'; const roots: string[] = []; diff --git a/src/daemon/session-store.ts b/src/daemon/session-store.ts index 83b1985704..f0bcf73e6f 100644 --- a/src/daemon/session-store.ts +++ b/src/daemon/session-store.ts @@ -25,7 +25,7 @@ import { resolveSessionEventLogPath, type SessionEventLogInput, type SessionEventLogPage, -} from './session-event-log.ts'; +} from '@agent-device/session-journal/session-event-log'; /** * ADR 0012 decision 6, R7 (C5a): a reaped repair session leaves this bounded