Skip to content

Commit fccf8c1

Browse files
committed
refactor: split generic host mechanics into @agent-device/host-kit
capture-kit's generic host modules move to a new host-kit package that sits between kernel and capture-kit, exported behind four deep seams — exec, fs, values, request — with explicit named re-exports and internals sealed under src/internal/. capture-kit keeps capture, snapshot, and recording behavior and now depends on host-kit; tar-stream/yauzl move with the archive mechanics. The layering model, platform-package policy, package pins, eager-closure budgets, and the ADR-0019 substrate amendment now describe this layout, and the remaining alias-source narration is removed. Seam merging also surfaced tests whose per-module mocks became same-seam duplicates (the later factory silently replaced the earlier one) and mocks that internal relative imports now bypass; those factories are merged and pinned at the injection points instead. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018VngeKZH6zBuJzNBk5YzUH
1 parent 134f6d4 commit fccf8c1

497 files changed

Lines changed: 1085 additions & 963 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.fallowrc.json‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,13 @@
217217
"rules": {
218218
"unused-types": "off"
219219
}
220+
},
221+
{
222+
"comment": "Host-kit seam façades: same false-positive shape as the contracts façades above — each seam names every type its re-exported functions put in a public signature, and callers use those types structurally without importing the name. unused-exports (the VALUE check) stays on.",
223+
"files": ["packages/host-kit/src/*.ts"],
224+
"rules": {
225+
"unused-types": "off"
226+
}
220227
}
221228
],
222229
"production": {

‎docs/adr/0019-request-bound-platform-runtime.md‎

Lines changed: 11 additions & 7 deletions

‎package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@
161161
"check:unit": "pnpm test:unit && pnpm check:tmpdir-leaks && pnpm test:smoke",
162162
"check": "pnpm check:tooling && pnpm check:fallow && pnpm check:unit",
163163
"prepack": "pnpm check:mcp-metadata && pnpm package:npm",
164-
"typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/capture-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/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
164+
"typecheck": "tsc -b packages/xml packages/kernel packages/contracts packages/host-kit packages/capture-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/ad-replay packages/maestro packages/replay-test packages/provider-webdriver packages/provider-limrun && tsc -p tsconfig.json && tsc -p examples/sdk/tsconfig.json",
165165
"test-app:install": "pnpm install --dir examples/test-app",
166166
"test-app:start": "pnpm --dir examples/test-app start",
167167
"test-app:ios": "pnpm --dir examples/test-app ios",
@@ -278,6 +278,7 @@
278278
"@agent-device/ad-script": "workspace:*",
279279
"@agent-device/capture-kit": "workspace:*",
280280
"@agent-device/contracts": "workspace:*",
281+
"@agent-device/host-kit": "workspace:*",
281282
"@agent-device/kernel": "workspace:*",
282283
"@agent-device/maestro": "workspace:*",
283284
"@agent-device/platform-android": "workspace:*",

‎packages/capture-kit/package.json‎

Lines changed: 2 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -6,87 +6,18 @@
66
"description": "Private host and durable-capture mechanics shared by platform runtimes, providers, and daemon orchestration: process execution, diagnostics, archives, PNG tooling, and request-scoped plumbing.",
77
"dependencies": {
88
"@agent-device/contracts": "workspace:*",
9-
"@agent-device/kernel": "workspace:*",
10-
"tar-stream": "^3.2.0",
11-
"yauzl": "^3.4.0"
9+
"@agent-device/host-kit": "workspace:*",
10+
"@agent-device/kernel": "workspace:*"
1211
},
1312
"exports": {
1413
".": {
1514
"types": "./src/index.ts",
1615
"default": "./src/index.ts"
1716
},
18-
"./archive-extraction": {
19-
"types": "./src/archive-extraction.ts",
20-
"default": "./src/archive-extraction.ts"
21-
},
22-
"./archive-safety": {
23-
"types": "./src/archive-safety.ts",
24-
"default": "./src/archive-safety.ts"
25-
},
26-
"./artifact-limits": {
27-
"types": "./src/artifact-limits.ts",
28-
"default": "./src/artifact-limits.ts"
29-
},
30-
"./atomic-file": {
31-
"types": "./src/atomic-file.ts",
32-
"default": "./src/atomic-file.ts"
33-
},
34-
"./byte-limit-stream": {
35-
"types": "./src/byte-limit-stream.ts",
36-
"default": "./src/byte-limit-stream.ts"
37-
},
38-
"./device-isolation": {
39-
"types": "./src/device-isolation.ts",
40-
"default": "./src/device-isolation.ts"
41-
},
42-
"./diagnostics": {
43-
"types": "./src/diagnostics.ts",
44-
"default": "./src/diagnostics.ts"
45-
},
46-
"./env-map": {
47-
"types": "./src/env-map.ts",
48-
"default": "./src/env-map.ts"
49-
},
50-
"./exec": {
51-
"types": "./src/exec.ts",
52-
"default": "./src/exec.ts"
53-
},
54-
"./host-process": {
55-
"types": "./src/host-process.ts",
56-
"default": "./src/host-process.ts"
57-
},
58-
"./location-coordinates": {
59-
"types": "./src/location-coordinates.ts",
60-
"default": "./src/location-coordinates.ts"
61-
},
62-
"./method-scope": {
63-
"types": "./src/method-scope.ts",
64-
"default": "./src/method-scope.ts"
65-
},
6617
"./mobile-snapshot-semantics": {
6718
"types": "./src/mobile-snapshot-semantics.ts",
6819
"default": "./src/mobile-snapshot-semantics.ts"
6920
},
70-
"./owned-process-reaper": {
71-
"types": "./src/owned-process-reaper.ts",
72-
"default": "./src/owned-process-reaper.ts"
73-
},
74-
"./owned-process-record": {
75-
"types": "./src/owned-process-record.ts",
76-
"default": "./src/owned-process-record.ts"
77-
},
78-
"./owner-identity": {
79-
"types": "./src/owner-identity.ts",
80-
"default": "./src/owner-identity.ts"
81-
},
82-
"./parsing": {
83-
"types": "./src/parsing.ts",
84-
"default": "./src/parsing.ts"
85-
},
86-
"./path-resolution": {
87-
"types": "./src/path-resolution.ts",
88-
"default": "./src/path-resolution.ts"
89-
},
9021
"./png": {
9122
"types": "./src/png.ts",
9223
"default": "./src/png.ts"
@@ -107,26 +38,6 @@
10738
"types": "./src/png-worker-client.ts",
10839
"default": "./src/png-worker-client.ts"
10940
},
110-
"./process-lock": {
111-
"types": "./src/process-lock.ts",
112-
"default": "./src/process-lock.ts"
113-
},
114-
"./request-cancel": {
115-
"types": "./src/request-cancel.ts",
116-
"default": "./src/request-cancel.ts"
117-
},
118-
"./request-progress": {
119-
"types": "./src/request-progress.ts",
120-
"default": "./src/request-progress.ts"
121-
},
122-
"./retry": {
123-
"types": "./src/retry.ts",
124-
"default": "./src/retry.ts"
125-
},
126-
"./scoped-provider": {
127-
"types": "./src/scoped-provider.ts",
128-
"default": "./src/scoped-provider.ts"
129-
},
13041
"./screenshot-density": {
13142
"types": "./src/screenshot-density.ts",
13243
"default": "./src/screenshot-density.ts"
@@ -135,10 +46,6 @@
13546
"types": "./src/screenshot-diff-pixels.ts",
13647
"default": "./src/screenshot-diff-pixels.ts"
13748
},
138-
"./shell-quote": {
139-
"types": "./src/shell-quote.ts",
140-
"default": "./src/shell-quote.ts"
141-
},
14249
"./snapshot-occlusion": {
14350
"types": "./src/snapshot-occlusion.ts",
14451
"default": "./src/snapshot-occlusion.ts"
@@ -150,32 +57,10 @@
15057
"./snapshot-quality-verdict": {
15158
"types": "./src/snapshot-quality-verdict.ts",
15259
"default": "./src/snapshot-quality-verdict.ts"
153-
},
154-
"./source-value": {
155-
"types": "./src/source-value.ts",
156-
"default": "./src/source-value.ts"
157-
},
158-
"./success-text": {
159-
"types": "./src/success-text.ts",
160-
"default": "./src/success-text.ts"
161-
},
162-
"./timeouts": {
163-
"types": "./src/timeouts.ts",
164-
"default": "./src/timeouts.ts"
165-
},
166-
"./ttl-memo": {
167-
"types": "./src/ttl-memo.ts",
168-
"default": "./src/ttl-memo.ts"
169-
},
170-
"./version": {
171-
"types": "./src/version.ts",
172-
"default": "./src/version.ts"
17360
}
17461
},
17562
"devDependencies": {
17663
"@types/pngjs": "^6.0.5",
177-
"@types/tar-stream": "^3.1.4",
178-
"@types/yauzl": "^3.4.0",
17964
"pngjs": "^7.0.0"
18065
}
18166
}

‎packages/capture-kit/src/png-worker-client.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Worker } from 'node:worker_threads';
2-
import { emitDiagnostic } from './diagnostics.ts';
2+
import { emitDiagnostic } from '@agent-device/host-kit/exec';
33
import { AppError, toAppErrorCode } from '@agent-device/kernel/errors';
44
import { resolveInternalEntryModulePath } from './internal-entry.ts';
55
import { decodePng, PNG } from './png.ts';

‎packages/host-kit/package.json‎

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
{
2+
"name": "@agent-device/host-kit",
3+
"version": "0.0.0",
4+
"private": true,
5+
"type": "module",
6+
"description": "Private generic host mechanics behind four deep seams: process execution and supervision (exec), filesystem and archive guards (fs), pure value helpers (values), and request-scoped plumbing (request). Internal workspace package bundled into the published agent-device artifact.",
7+
"dependencies": {
8+
"@agent-device/contracts": "workspace:*",
9+
"@agent-device/kernel": "workspace:*",
10+
"tar-stream": "^3.2.0",
11+
"yauzl": "^3.4.0"
12+
},
13+
"devDependencies": {
14+
"@types/tar-stream": "^3.1.4",
15+
"@types/yauzl": "^3.4.0"
16+
},
17+
"exports": {
18+
"./exec": {
19+
"types": "./src/exec.ts",
20+
"default": "./src/exec.ts"
21+
},
22+
"./fs": {
23+
"types": "./src/fs.ts",
24+
"default": "./src/fs.ts"
25+
},
26+
"./request": {
27+
"types": "./src/request.ts",
28+
"default": "./src/request.ts"
29+
},
30+
"./values": {
31+
"types": "./src/values.ts",
32+
"default": "./src/values.ts"
33+
}
34+
}
35+
}

‎packages/host-kit/src/exec.ts‎

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
export {
2+
coerceExecResult,
3+
execFailureDetails,
4+
isExecutablePath,
5+
requireExecSuccess,
6+
resolveExecutableOverridePath,
7+
resolveFileOverridePath,
8+
runCmd,
9+
runCmdBackground,
10+
runCmdDetached,
11+
runCmdDetachedMonitored,
12+
runCmdStreaming,
13+
runCmdSync,
14+
whichCmd,
15+
withCommandExecutorOverride,
16+
withoutCommandExecutorOverride,
17+
type CommandExecutorOverride,
18+
type ExecBackgroundOptions,
19+
type ExecBackgroundResult,
20+
type ExecDetachedExit,
21+
type ExecDetachedProcess,
22+
type ExecOptions,
23+
type ExecResult,
24+
} from './internal/exec.ts';
25+
export {
26+
countDiagnosticEventsByPhase,
27+
createRequestId,
28+
emitDiagnostic,
29+
flushDiagnosticsToSessionFile,
30+
getDiagnosticsMeta,
31+
registerDiagnosticSensitiveValue,
32+
updateDiagnosticsScope,
33+
withDiagnosticTimer,
34+
withDiagnosticsScope,
35+
type FlushedDiagnosticsRecord,
36+
} from './internal/diagnostics.ts';
37+
export {
38+
expandProcessTree,
39+
isProcessAlive,
40+
isProcessGroupAlive,
41+
isProcessZombie,
42+
listHostProcesses,
43+
readHostProcessIdentityObservations,
44+
readProcessCommand,
45+
readProcessStartTime,
46+
signalPidsBestEffort,
47+
signalProcessGroupBestEffort,
48+
stopPidsWithEscalation,
49+
uniquePositivePids,
50+
waitForProcessExit,
51+
type HostProcessIdentityObservation,
52+
type HostProcessInfo,
53+
type ListHostProcessesOptions,
54+
type StopPidsWithEscalationOptions,
55+
} from './internal/host-process.ts';
56+
export {
57+
reapOwnedProcessRecordsAtStartup,
58+
type OwnedProcessReapSummary,
59+
} from './internal/owned-process-reaper.ts';
60+
export {
61+
createOwnedProcessRecordStore,
62+
readOwnedProcessRecordFile,
63+
type OwnedProcessRecordRead,
64+
type OwnedProcessRecordStore,
65+
} from './internal/owned-process-record.ts';
66+
export {
67+
classifyOwnerLiveness,
68+
classifyOwnerLivenessFromObservation,
69+
ownerIdentityDiffers,
70+
ownerIdentityMatches,
71+
readCurrentOwnerIdentity,
72+
type OwnerIdentity,
73+
type OwnerLiveness,
74+
} from './internal/owner-identity.ts';
75+
export { shellQuote, shellQuoteIfNeeded } from './internal/shell-quote.ts';
76+
export { sleep } from './internal/timeouts.ts';
77+
export { Deadline, isEnvTruthy, retryWithPolicy } from './internal/retry.ts';

‎packages/host-kit/src/fs.ts‎

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
export {
2+
archiveTypeFromPath,
3+
extractArchiveSafely,
4+
type ExtractArchiveOptions,
5+
type SupportedArchiveType,
6+
} from './internal/archive-extraction.ts';
7+
export { ArchiveBudget, type ArchiveManifestEntry } from './internal/archive-safety.ts';
8+
export { MAX_ARTIFACT_COMPRESSED_BYTES } from './internal/artifact-limits.ts';
9+
export {
10+
isAtomicPublishTemporaryPath,
11+
publishFileSync,
12+
withAtomicPublishTempPathSync,
13+
type AtomicPublishMode,
14+
} from './internal/atomic-file.ts';
15+
export { createByteLimitStream, type ByteLimitStream } from './internal/byte-limit-stream.ts';
16+
export {
17+
parseSerialAllowlist,
18+
resolveAndroidSerialAllowlist,
19+
resolveIosSimulatorDeviceSetPath,
20+
} from './internal/device-isolation.ts';
21+
export { expandUserHomePath, resolveUserPath } from './internal/path-resolution.ts';
22+
export { acquireProcessLock, type ProcessLockOwner } from './internal/process-lock.ts';

packages/capture-kit/src/archive-extraction-tar.test.ts renamed to packages/host-kit/src/internal/archive-extraction-tar.test.ts

File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)