comber 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. package/LICENSE +18 -0
  2. package/README.md +732 -0
  3. package/action.yml +279 -0
  4. package/comber.config.example.json +64 -0
  5. package/dist/api/classify.js +99 -0
  6. package/dist/api/classify.js.map +1 -0
  7. package/dist/api/driver.js +235 -0
  8. package/dist/api/driver.js.map +1 -0
  9. package/dist/api/graphql-driver.js +150 -0
  10. package/dist/api/graphql-driver.js.map +1 -0
  11. package/dist/api/graphql.js +115 -0
  12. package/dist/api/graphql.js.map +1 -0
  13. package/dist/api/har-driver.js +167 -0
  14. package/dist/api/har-driver.js.map +1 -0
  15. package/dist/api/har.js +100 -0
  16. package/dist/api/har.js.map +1 -0
  17. package/dist/api/load.js +83 -0
  18. package/dist/api/load.js.map +1 -0
  19. package/dist/api/openapi.js +159 -0
  20. package/dist/api/openapi.js.map +1 -0
  21. package/dist/api/request.js +141 -0
  22. package/dist/api/request.js.map +1 -0
  23. package/dist/api/schema.js +126 -0
  24. package/dist/api/schema.js.map +1 -0
  25. package/dist/cli.js +352 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/comment.js +164 -0
  28. package/dist/comment.js.map +1 -0
  29. package/dist/config.js +664 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/connectors/builtin/discord.js +55 -0
  32. package/dist/connectors/builtin/github-checks.js +53 -0
  33. package/dist/connectors/builtin/junit.js +70 -0
  34. package/dist/connectors/builtin/linear.js +58 -0
  35. package/dist/connectors/builtin/slack.js +60 -0
  36. package/dist/connectors/builtin/webhook.js +39 -0
  37. package/dist/connectors/index.js +3 -0
  38. package/dist/connectors/loader.js +72 -0
  39. package/dist/connectors/registry.js +28 -0
  40. package/dist/connectors/types.js +23 -0
  41. package/dist/core/action-gate.js +48 -0
  42. package/dist/core/baseline.js +85 -0
  43. package/dist/core/baseline.js.map +1 -0
  44. package/dist/core/blind-spots.js +22 -0
  45. package/dist/core/blind-spots.js.map +1 -0
  46. package/dist/core/contract-extras.js +1 -0
  47. package/dist/core/contract-extras.js.map +1 -0
  48. package/dist/core/contract.js +1 -0
  49. package/dist/core/contract.js.map +1 -0
  50. package/dist/core/coverage.js +70 -0
  51. package/dist/core/coverage.js.map +1 -0
  52. package/dist/core/crawl.js +229 -0
  53. package/dist/core/crawl.js.map +1 -0
  54. package/dist/core/egress.js +128 -0
  55. package/dist/core/egress.js.map +1 -0
  56. package/dist/core/ledger.js +41 -0
  57. package/dist/core/ledger.js.map +1 -0
  58. package/dist/core/net.js +39 -0
  59. package/dist/core/pipeline.js +191 -0
  60. package/dist/core/pipeline.js.map +1 -0
  61. package/dist/core/plan.js +121 -0
  62. package/dist/core/plan.js.map +1 -0
  63. package/dist/core/redact.js +240 -0
  64. package/dist/core/redact.js.map +1 -0
  65. package/dist/core/replay.js +263 -0
  66. package/dist/core/replay.js.map +1 -0
  67. package/dist/core/report.js +253 -0
  68. package/dist/core/report.js.map +1 -0
  69. package/dist/core/safety-judge.js +116 -0
  70. package/dist/core/safety.js +92 -0
  71. package/dist/core/safety.js.map +1 -0
  72. package/dist/core/signal-normalize.js +190 -0
  73. package/dist/core/signal-normalize.js.map +1 -0
  74. package/dist/core/signals.js +5 -0
  75. package/dist/core/signals.js.map +1 -0
  76. package/dist/core/triage.js +104 -0
  77. package/dist/core/triage.js.map +1 -0
  78. package/dist/core/types.js +1 -0
  79. package/dist/core/types.js.map +1 -0
  80. package/dist/desktop/desktop-profile.js +6 -0
  81. package/dist/desktop/desktop-profile.js.map +1 -0
  82. package/dist/desktop/driver.js +433 -0
  83. package/dist/desktop/driver.js.map +1 -0
  84. package/dist/desktop/evidence.js +206 -0
  85. package/dist/desktop/evidence.js.map +1 -0
  86. package/dist/desktop/macos/accessibility-runner.js +118 -0
  87. package/dist/desktop/macos/accessibility-runner.js.map +1 -0
  88. package/dist/desktop/macos/types.js +1 -0
  89. package/dist/desktop/macos/types.js.map +1 -0
  90. package/dist/desktop/preflight.js +107 -0
  91. package/dist/desktop/preflight.js.map +1 -0
  92. package/dist/desktop/proxy-proof.js +185 -0
  93. package/dist/desktop/proxy-proof.js.map +1 -0
  94. package/dist/desktop/view.js +348 -0
  95. package/dist/desktop/view.js.map +1 -0
  96. package/dist/desktop/windows/types.js +1 -0
  97. package/dist/desktop/windows/types.js.map +1 -0
  98. package/dist/desktop/windows/uia-runner.js +127 -0
  99. package/dist/desktop/windows/uia-runner.js.map +1 -0
  100. package/dist/native/apple.js +14 -0
  101. package/dist/native/apple.js.map +1 -0
  102. package/dist/native/device-profile.js +6 -0
  103. package/dist/native/device-profile.js.map +1 -0
  104. package/dist/native/driver.js +416 -0
  105. package/dist/native/driver.js.map +1 -0
  106. package/dist/native/evidence.js +164 -0
  107. package/dist/native/evidence.js.map +1 -0
  108. package/dist/native/load.js +9 -0
  109. package/dist/native/load.js.map +1 -0
  110. package/dist/native/maestro.js +153 -0
  111. package/dist/native/maestro.js.map +1 -0
  112. package/dist/native/preflight.js +72 -0
  113. package/dist/native/preflight.js.map +1 -0
  114. package/dist/native/proxy-proof.js +182 -0
  115. package/dist/native/proxy-proof.js.map +1 -0
  116. package/dist/native/samsung.js +34 -0
  117. package/dist/native/samsung.js.map +1 -0
  118. package/dist/native/signals.js +50 -0
  119. package/dist/native/signals.js.map +1 -0
  120. package/dist/native/view.js +139 -0
  121. package/dist/native/view.js.map +1 -0
  122. package/dist/profile.js +237 -0
  123. package/dist/profile.js.map +1 -0
  124. package/dist/sink.js +134 -0
  125. package/dist/sink.js.map +1 -0
  126. package/dist/sinks/file.js +49 -0
  127. package/dist/sinks/file.js.map +1 -0
  128. package/dist/sinks/http.js +38 -0
  129. package/dist/sinks/http.js.map +1 -0
  130. package/dist/sinks/index.js +5 -0
  131. package/dist/sinks/index.js.map +1 -0
  132. package/dist/sinks/multi.js +40 -0
  133. package/dist/sinks/multi.js.map +1 -0
  134. package/dist/sinks/paths.js +32 -0
  135. package/dist/sinks/paths.js.map +1 -0
  136. package/dist/sinks/record.js +58 -0
  137. package/dist/sinks/record.js.map +1 -0
  138. package/dist/sinks/types.js +1 -0
  139. package/dist/sinks/types.js.map +1 -0
  140. package/dist/web/breakage.js +210 -0
  141. package/dist/web/breakage.js.map +1 -0
  142. package/dist/web/controls.js +102 -0
  143. package/dist/web/controls.js.map +1 -0
  144. package/dist/web/driver.js +803 -0
  145. package/dist/web/driver.js.map +1 -0
  146. package/dist/web/elements.js +151 -0
  147. package/dist/web/elements.js.map +1 -0
  148. package/dist/web/fingerprint.js +13 -0
  149. package/dist/web/fingerprint.js.map +1 -0
  150. package/dist/web/forms.js +74 -0
  151. package/dist/web/forms.js.map +1 -0
  152. package/dist/web/links.js +194 -0
  153. package/dist/web/links.js.map +1 -0
  154. package/dist/web/types.js +1 -0
  155. package/dist/web/types.js.map +1 -0
  156. package/package.json +80 -0
  157. package/runtime/macos-accessibility-runner.js +275 -0
  158. package/runtime/windows-uia-runner.ps1 +539 -0
@@ -0,0 +1,433 @@
1
+ import { writeFile } from "node:fs/promises";
2
+ import { join } from "node:path";
3
+ import { buildDesktopEvidence } from "./evidence.js";
4
+ import { evaluateDesktopReadiness } from "./preflight.js";
5
+ import { blindSpotDetailsOf, macosAccessibilityBlindSpotDetailsOf, macosAccessibilityScreenNameOf, macosAccessibilityScreenSignature, macosAccessibilityViewToSurfaceNodes, viewToSurfaceNodes, windowsScreenNameOf, windowsScreenSignature, } from "./view.js";
6
+ const LAUNCH_ID = "launch";
7
+ const UIA_PATH_PREFIX = "uiapath:";
8
+ const AX_PATH_PREFIX = "axpath:";
9
+ const BASE_SEP = "::";
10
+ const ACTION_SEP = ">>";
11
+ const PROBE_TEXT = "comber-probe";
12
+ const NOOP_COVERAGE = { skip() { }, bumpExtra() { } };
13
+ export class DesktopDriver {
14
+ name = "desktop";
15
+ capabilities = {
16
+ screenshot: false,
17
+ probes: [
18
+ { name: "session", slot: "after-goto" },
19
+ { name: "dom", slot: "after-snapshot" },
20
+ { name: "crash", slot: "after-exercise" },
21
+ ],
22
+ };
23
+ platform;
24
+ runner;
25
+ launchTarget;
26
+ desktopProfile;
27
+ cov = NOOP_COVERAGE;
28
+ signals = [];
29
+ anchor = { id: LAUNCH_ID, scope: LAUNCH_ID, label: "launch" };
30
+ baseAnchorId = LAUNCH_ID;
31
+ currentActions = [];
32
+ drifted = false;
33
+ justWentTo = false;
34
+ anchorFp = "";
35
+ currentScope = LAUNCH_ID;
36
+ lastTree;
37
+ controlsExercised = 0;
38
+ desktopEvidenceGapsReported = false;
39
+ observedAutomationTreeArtifacts = new Set();
40
+ runDir;
41
+ snapshotArtifactCount = 0;
42
+ constructor(opts) {
43
+ const windowsTargetFields = {};
44
+ if (opts.platform === "windows") {
45
+ if (opts.processId !== undefined)
46
+ windowsTargetFields.processId = opts.processId;
47
+ if (opts.windowTitle !== undefined)
48
+ windowsTargetFields.windowTitle = opts.windowTitle;
49
+ }
50
+ this.platform = opts.platform;
51
+ this.runner = opts.runner;
52
+ this.launchTarget = {
53
+ ...(opts.appId !== undefined ? { appId: opts.appId } : {}),
54
+ ...(opts.appPath !== undefined ? { appPath: opts.appPath } : {}),
55
+ ...(opts.processName !== undefined ? { processName: opts.processName } : {}),
56
+ ...windowsTargetFields,
57
+ };
58
+ this.desktopProfile =
59
+ opts.desktopProfile ?? {
60
+ platform: opts.platform,
61
+ ...(opts.appId !== undefined ? { appId: opts.appId } : {}),
62
+ ...(opts.appPath !== undefined ? { appPath: opts.appPath } : {}),
63
+ ...(opts.processName !== undefined ? { processName: opts.processName } : {}),
64
+ ...windowsTargetFields,
65
+ automationBackend: opts.platform === "windows" ? "uia" : "accessibility",
66
+ };
67
+ this.capabilities = {
68
+ ...this.capabilities,
69
+ screenshot: typeof this.runner.screenshot === "function",
70
+ };
71
+ }
72
+ attachCoverage(sink) {
73
+ this.cov = sink;
74
+ }
75
+ attachRunDir(runDir) {
76
+ this.runDir = runDir;
77
+ }
78
+ async start() {
79
+ /* Session establishment is done by goto(), matching the native driver's relaunch model. */
80
+ }
81
+ async close() {
82
+ await this.runner.close().catch(() => { });
83
+ }
84
+ entryAddress() {
85
+ return { id: LAUNCH_ID, scope: LAUNCH_ID, label: "launch" };
86
+ }
87
+ currentAddress() {
88
+ if (!this.drifted)
89
+ return this.anchor;
90
+ return { id: `${this.anchor.id}#drifted`, scope: this.anchor.scope, label: "(navigated away)" };
91
+ }
92
+ inScope(addr) {
93
+ return addr.id === LAUNCH_ID || addr.id.startsWith(this.pathPrefix());
94
+ }
95
+ async goto(addr) {
96
+ if (addr.id.startsWith(this.pathPrefix())) {
97
+ const parsed = parseActionPath(addr.id, this.pathPrefix());
98
+ await this.relaunch();
99
+ for (const action of parsed.actions) {
100
+ await this.runner.perform(action).catch((error) => {
101
+ this.signals.push(desktopSignal("frozen", parsed.base, `desktop replay action failed: ${errMessage(error)}`, action.kind));
102
+ });
103
+ }
104
+ this.anchor = { id: addr.id, scope: addr.scope, ...(addr.label !== undefined ? { label: addr.label } : {}) };
105
+ this.baseAnchorId = parsed.base;
106
+ this.currentActions = parsed.actions;
107
+ }
108
+ else {
109
+ await this.relaunch();
110
+ this.anchor = { id: LAUNCH_ID, scope: LAUNCH_ID, label: "launch" };
111
+ this.baseAnchorId = LAUNCH_ID;
112
+ this.currentActions = [];
113
+ }
114
+ this.drifted = false;
115
+ this.justWentTo = true;
116
+ this.anchorFp = "";
117
+ }
118
+ async relaunch() {
119
+ try {
120
+ await this.runner.launch(this.launchTarget);
121
+ }
122
+ catch (error) {
123
+ this.signals.push(desktopSignal("crash", this.anchor.scope, `desktop launch failed: ${errMessage(error)}`, "launch"));
124
+ }
125
+ }
126
+ async snapshot() {
127
+ let tree = null;
128
+ try {
129
+ tree = await this.runner.snapshot();
130
+ }
131
+ catch (error) {
132
+ this.signals.push(desktopSignal("frozen", this.anchor.scope, `${this.automationLabel()} snapshot failed: ${errMessage(error)}`));
133
+ }
134
+ if (!tree) {
135
+ const details = this.takeDesktopEvidenceGaps(this.anchor.scope);
136
+ details.unshift({
137
+ kind: this.platform === "macos" ? "desktop-accessibility-unavailable" : "desktop-automation-unavailable",
138
+ severity: "blocker-for-exhaustive",
139
+ scope: this.anchor.scope,
140
+ message: `${this.automationLabel()} tree was unavailable`,
141
+ });
142
+ return {
143
+ address: { ...this.anchor },
144
+ title: this.anchor.label,
145
+ nodes: [],
146
+ blindSpots: details.length,
147
+ blindSpotDetails: details,
148
+ };
149
+ }
150
+ tree = await this.persistAutomationTree(tree);
151
+ this.lastTree = tree;
152
+ if (tree.artifactPath) {
153
+ this.observedAutomationTreeArtifacts.add(tree.artifactPath);
154
+ }
155
+ if (this.justWentTo) {
156
+ this.anchorFp = this.screenSignature(tree);
157
+ this.justWentTo = false;
158
+ }
159
+ const label = this.screenNameOf(tree, this.anchor.label ?? this.anchor.scope);
160
+ const address = { id: this.anchor.id, scope: this.anchor.scope, label };
161
+ this.currentScope = address.scope;
162
+ const blindSpotDetails = [...this.blindSpotDetailsOf(tree, address.scope), ...this.takeDesktopEvidenceGaps(address.scope)];
163
+ return {
164
+ address,
165
+ title: label,
166
+ nodes: this.surfaceNodesOf(tree),
167
+ blindSpots: blindSpotDetails.length,
168
+ blindSpotDetails,
169
+ };
170
+ }
171
+ async exercise(node) {
172
+ const action = this.actionForNode(node);
173
+ const scope = this.currentScope;
174
+ const signals = [];
175
+ try {
176
+ await this.runner.perform(action);
177
+ this.controlsExercised++;
178
+ this.cov.bumpExtra("desktopControlsExercised");
179
+ }
180
+ catch (error) {
181
+ this.drifted = true;
182
+ signals.push(desktopSignal("frozen", scope, `${node.kind} "${node.label}" did not respond: ${errMessage(error)}`, node.label, node.id));
183
+ return { signals };
184
+ }
185
+ const foreground = await this.runner.foregroundProcess().catch(() => expectedProcessName(this.launchTarget));
186
+ const expectedProcess = expectedProcessName(this.launchTarget);
187
+ if (expectedProcess && foreground && normalizeProcessName(foreground) !== normalizeProcessName(expectedProcess)) {
188
+ this.drifted = true;
189
+ signals.push(desktopSignal("crash", scope, `desktop app left foreground after "${node.label}" (now: ${foreground})`, node.label, node.id));
190
+ }
191
+ let after = null;
192
+ try {
193
+ after = await this.runner.snapshot();
194
+ }
195
+ catch (error) {
196
+ this.drifted = true;
197
+ signals.push(desktopSignal("frozen", scope, `screen unresponsive after "${node.label}": ${errMessage(error)}`, node.label, node.id));
198
+ }
199
+ if (after) {
200
+ if (after.artifactPath) {
201
+ this.observedAutomationTreeArtifacts.add(after.artifactPath);
202
+ }
203
+ const afterFp = this.screenSignature(after);
204
+ if (this.anchorFp && afterFp !== this.anchorFp) {
205
+ this.drifted = true;
206
+ return { signals, discovered: [this.actionPathAddress(after, [...this.currentActions, action])] };
207
+ }
208
+ }
209
+ return { signals };
210
+ }
211
+ async probe(phase) {
212
+ if (phase === "session") {
213
+ const signals = [];
214
+ const expectedProcess = expectedProcessName(this.launchTarget);
215
+ const foreground = await this.runner.foregroundProcess().catch(() => "");
216
+ if (expectedProcess && foreground && normalizeProcessName(foreground) !== normalizeProcessName(expectedProcess)) {
217
+ signals.push(desktopSignal("crash", this.anchor.scope, `desktop app not foreground after launch (now: ${foreground})`, "launch"));
218
+ }
219
+ try {
220
+ await this.runner.snapshot();
221
+ }
222
+ catch (error) {
223
+ signals.push(desktopSignal("frozen", this.anchor.scope, `${this.automationLabel()} tree unavailable: ${errMessage(error)}`, "snapshot"));
224
+ }
225
+ return signals;
226
+ }
227
+ if (phase === "dom") {
228
+ return this.lastTree ? firstErrorText(this.lastTree, this.currentScope) : [];
229
+ }
230
+ if (phase === "crash") {
231
+ const expectedProcess = expectedProcessName(this.launchTarget);
232
+ const foreground = await this.runner.foregroundProcess().catch(() => expectedProcess);
233
+ return expectedProcess && foreground && normalizeProcessName(foreground) !== normalizeProcessName(expectedProcess)
234
+ ? [desktopSignal("crash", this.currentScope, `desktop app not foreground (now: ${foreground})`, "after-exercise")]
235
+ : [];
236
+ }
237
+ return [];
238
+ }
239
+ async softReset() {
240
+ /* Windows UIA v1 has no generic, safe reset key. The core escalates to goto() when needed. */
241
+ }
242
+ drainSignals() {
243
+ const out = this.signals;
244
+ this.signals = [];
245
+ return out;
246
+ }
247
+ async screenshot() {
248
+ return (await this.runner.screenshot?.().catch(() => Buffer.alloc(0))) ?? Buffer.alloc(0);
249
+ }
250
+ auditExtra() {
251
+ return {
252
+ desktopAudit: {
253
+ platform: this.platform,
254
+ automationBackend: this.automationBackend(),
255
+ appId: this.launchTarget.appId,
256
+ appPath: this.launchTarget.appPath,
257
+ processName: this.launchTarget.processName,
258
+ controlsExercised: this.controlsExercised,
259
+ egressEnforced: hasCompleteDesktopEgressProxyEvidence(this.currentDesktopEvidence().egressProxy),
260
+ },
261
+ desktopEvidence: this.currentDesktopEvidence(),
262
+ desktopReadiness: this.currentDesktopReadiness(),
263
+ };
264
+ }
265
+ actionPathAddress(after, actions) {
266
+ const fingerprint = this.screenSignature(after);
267
+ const label = this.screenNameOf(after, "");
268
+ const scope = label ? label.toLowerCase().replace(/[^a-z0-9/_-]+/g, "-") : `desktop/${fingerprint.slice(0, 8)}`;
269
+ return {
270
+ id: encodeActionPath(this.pathPrefix(), this.baseAnchorId, actions),
271
+ scope,
272
+ dedupeKey: `${this.platform}:${fingerprint}`,
273
+ label: label || scope,
274
+ };
275
+ }
276
+ takeDesktopEvidenceGaps(scope) {
277
+ if (this.desktopEvidenceGapsReported)
278
+ return [];
279
+ this.desktopEvidenceGapsReported = true;
280
+ return this.currentDesktopEvidence().gaps.map((gap) => ({ ...gap, scope }));
281
+ }
282
+ currentDesktopEvidence() {
283
+ return buildDesktopEvidence(this.currentDesktopProfile());
284
+ }
285
+ currentDesktopReadiness() {
286
+ return evaluateDesktopReadiness(this.currentDesktopProfile());
287
+ }
288
+ currentDesktopProfile() {
289
+ const existingArtifacts = this.desktopProfile.evidenceArtifacts ?? [];
290
+ const artifactPaths = new Set(existingArtifacts.map((artifact) => `${artifact.kind}:${artifact.path}`));
291
+ const evidenceArtifacts = existingArtifacts.map((artifact) => ({ ...artifact }));
292
+ for (const path of this.observedAutomationTreeArtifacts) {
293
+ const kind = this.platform === "macos" ? "accessibility-tree" : "automation-tree";
294
+ const key = `${kind}:${path}`;
295
+ if (artifactPaths.has(key))
296
+ continue;
297
+ evidenceArtifacts.push({ kind, path });
298
+ }
299
+ return {
300
+ ...this.desktopProfile,
301
+ platform: this.platform,
302
+ automationBackend: this.automationBackend(),
303
+ ...(this.platform === "windows"
304
+ ? { uiAutomationTreeAvailable: this.observedAutomationTreeArtifacts.size > 0 || this.desktopProfile.uiAutomationTreeAvailable === true }
305
+ : { accessibilityPermissionVerified: this.observedAutomationTreeArtifacts.size > 0 || this.desktopProfile.accessibilityPermissionVerified === true }),
306
+ evidenceArtifacts,
307
+ };
308
+ }
309
+ async persistAutomationTree(tree) {
310
+ if (tree.artifactPath || this.runDir === undefined)
311
+ return tree;
312
+ this.snapshotArtifactCount++;
313
+ const prefix = this.platform === "macos" ? "desktop-ax-state" : "desktop-uia-state";
314
+ const artifactPath = join(this.runDir, `${prefix}-${this.snapshotArtifactCount}.json`);
315
+ try {
316
+ await writeFile(artifactPath, JSON.stringify(tree, null, 2), "utf8");
317
+ return { ...tree, artifactPath };
318
+ }
319
+ catch (error) {
320
+ this.signals.push(desktopSignal("desktop-evidence", this.anchor.scope, `failed to write desktop tree artifact: ${errMessage(error)}`));
321
+ return tree;
322
+ }
323
+ }
324
+ pathPrefix() {
325
+ return this.platform === "macos" ? AX_PATH_PREFIX : UIA_PATH_PREFIX;
326
+ }
327
+ automationBackend() {
328
+ return this.platform === "macos" ? "accessibility" : "uia";
329
+ }
330
+ automationLabel() {
331
+ return this.platform === "macos" ? "macOS Accessibility" : "Windows UI Automation";
332
+ }
333
+ surfaceNodesOf(tree) {
334
+ return this.platform === "macos"
335
+ ? macosAccessibilityViewToSurfaceNodes(tree)
336
+ : viewToSurfaceNodes(tree);
337
+ }
338
+ screenNameOf(tree, fallback) {
339
+ return this.platform === "macos"
340
+ ? macosAccessibilityScreenNameOf(tree, fallback)
341
+ : windowsScreenNameOf(tree, fallback);
342
+ }
343
+ screenSignature(tree) {
344
+ return this.platform === "macos"
345
+ ? macosAccessibilityScreenSignature(tree)
346
+ : windowsScreenSignature(tree);
347
+ }
348
+ blindSpotDetailsOf(tree, scope) {
349
+ return this.platform === "macos"
350
+ ? macosAccessibilityBlindSpotDetailsOf(tree, scope)
351
+ : blindSpotDetailsOf(tree, scope);
352
+ }
353
+ actionForNode(node) {
354
+ if (this.platform === "macos") {
355
+ return macosActionForHandle(node.handle);
356
+ }
357
+ return windowsActionForHandle(node.handle);
358
+ }
359
+ }
360
+ function windowsActionForHandle(handle) {
361
+ if (handle.actionKind === "set-value") {
362
+ return { kind: "set-value", selector: handle.selector, value: PROBE_TEXT };
363
+ }
364
+ if (handle.actionKind === "range") {
365
+ return { kind: "range", selector: handle.selector, delta: 1 };
366
+ }
367
+ return { kind: handle.actionKind, selector: handle.selector };
368
+ }
369
+ function macosActionForHandle(handle) {
370
+ if (handle.actionKind === "set-value") {
371
+ return { kind: "set-value", selector: handle.selector, value: PROBE_TEXT };
372
+ }
373
+ if (handle.actionKind === "increment" || handle.actionKind === "decrement") {
374
+ return { kind: handle.actionKind, selector: handle.selector, delta: 1 };
375
+ }
376
+ return { kind: handle.actionKind, selector: handle.selector };
377
+ }
378
+ function hasCompleteDesktopEgressProxyEvidence(proxy) {
379
+ return proxy?.verified === true && Boolean(proxy.provider && proxy.command && proxy.artifactPath);
380
+ }
381
+ function expectedProcessName(target) {
382
+ if (target.processId !== undefined)
383
+ return "";
384
+ const processName = target.processName ?? target.appPath?.split(/[\\/]/).pop() ?? "";
385
+ return processName.replace(/\.exe$/i, "").replace(/\.app$/i, "");
386
+ }
387
+ function normalizeProcessName(value) {
388
+ return value.replace(/\.exe$/i, "").toLowerCase();
389
+ }
390
+ function encodeActionPath(prefix, base, actions) {
391
+ const tokens = actions.map((action) => Buffer.from(JSON.stringify(action), "utf8").toString("base64url"));
392
+ return `${prefix}${base}${BASE_SEP}${tokens.join(ACTION_SEP)}`;
393
+ }
394
+ function parseActionPath(id, prefix) {
395
+ const body = id.slice(prefix.length);
396
+ const sep = body.indexOf(BASE_SEP);
397
+ const base = sep < 0 ? body : body.slice(0, sep);
398
+ const actionText = sep < 0 ? "" : body.slice(sep + BASE_SEP.length);
399
+ const actions = actionText
400
+ ? actionText.split(ACTION_SEP).map((token) => JSON.parse(Buffer.from(token, "base64url").toString("utf8")))
401
+ : [];
402
+ return { base, actions };
403
+ }
404
+ function errMessage(error) {
405
+ return (error instanceof Error ? error.message : String(error)).slice(0, 160);
406
+ }
407
+ function desktopSignal(kind, scope, message, action, discriminator) {
408
+ return {
409
+ kind,
410
+ severity: kind === "crash" ? "fail" : "warn",
411
+ message,
412
+ url: scope,
413
+ signature: `desktop:${kind}:${scope}:${action ?? ""}:${discriminator ?? ""}:${message.slice(0, 80)}`,
414
+ ...(action !== undefined ? { action } : {}),
415
+ };
416
+ }
417
+ function isWindowsUiaNode(node) {
418
+ return "controlType" in node || "automationId" in node || "name" in node;
419
+ }
420
+ function firstErrorText(tree, scope) {
421
+ const stack = [tree.root];
422
+ while (stack.length > 0) {
423
+ const node = stack.pop();
424
+ const text = isWindowsUiaNode(node) ? (node.name ?? "").trim() : `${node.title ?? ""} ${node.value ?? ""}`.trim();
425
+ if (/\b(error|failed|exception|not responding|crash|fatal)\b/i.test(text)) {
426
+ return [desktopSignal("error-text", scope, `on-screen desktop error: ${text.slice(0, 120)}`)];
427
+ }
428
+ for (const child of node.children ?? []) {
429
+ stack.push(child);
430
+ }
431
+ }
432
+ return [];
433
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../../src/desktop/driver.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,206 @@
1
+ import { normalizeDesktopProfile } from "./desktop-profile.js";
2
+ const VALID_ARTIFACT_KINDS = new Set([
3
+ "screenshot",
4
+ "video",
5
+ "log",
6
+ "crash-log",
7
+ "accessibility-tree",
8
+ "automation-tree",
9
+ ]);
10
+ const VALID_AUTOMATION_BACKENDS = new Set([
11
+ "accessibility",
12
+ "xctest",
13
+ "uia",
14
+ "unknown",
15
+ ]);
16
+ function isRecord(value) {
17
+ return typeof value === "object" && value !== null && !Array.isArray(value);
18
+ }
19
+ function isNonEmptyString(value) {
20
+ return typeof value === "string" && value.trim().length > 0;
21
+ }
22
+ function hasAppIdentity(profile) {
23
+ return isNonEmptyString(profile.appId) || isNonEmptyString(profile.appPath) || isNonEmptyString(profile.processName);
24
+ }
25
+ function isPlatform(value) {
26
+ return value === "macos" || value === "windows";
27
+ }
28
+ function isAutomationBackend(value) {
29
+ return typeof value === "string" && VALID_AUTOMATION_BACKENDS.has(value);
30
+ }
31
+ function isArtifactKind(value) {
32
+ return typeof value === "string" && VALID_ARTIFACT_KINDS.has(value);
33
+ }
34
+ function hasPathTraversal(value) {
35
+ return value.replace(/\\/g, "/").split("/").includes("..");
36
+ }
37
+ function addValidationIssue(errors, code, field, message) {
38
+ errors.push({ code, field, message });
39
+ }
40
+ function validateEvidenceArtifacts(errors, artifactsValue) {
41
+ const artifacts = Array.isArray(artifactsValue) ? artifactsValue : [];
42
+ for (let index = 0; index < artifacts.length; index++) {
43
+ const artifact = artifacts[index];
44
+ const field = `evidenceArtifacts[${index}]`;
45
+ if (!isRecord(artifact)) {
46
+ addValidationIssue(errors, "evidence-artifact-kind-invalid", `${field}.kind`, "Evidence artifact must be an object");
47
+ continue;
48
+ }
49
+ if (!isArtifactKind(artifact.kind)) {
50
+ addValidationIssue(errors, "evidence-artifact-kind-invalid", `${field}.kind`, "Evidence artifact kind must be screenshot, video, log, crash-log, accessibility-tree, or automation-tree");
51
+ }
52
+ if (!isNonEmptyString(artifact.path)) {
53
+ addValidationIssue(errors, "evidence-artifact-path-missing", `${field}.path`, "Evidence artifact path must be non-empty");
54
+ }
55
+ else if (hasPathTraversal(artifact.path)) {
56
+ addValidationIssue(errors, "evidence-artifact-path-traversal", `${field}.path`, "Evidence artifact path must not contain '..'");
57
+ }
58
+ }
59
+ }
60
+ function validateEgressProxy(errors, proxy) {
61
+ if (proxy?.verified !== true)
62
+ return;
63
+ if (!isNonEmptyString(proxy.provider)) {
64
+ addValidationIssue(errors, "egress-proxy-provider-missing", "egressProxy.provider", "Verified proxy evidence requires a provider");
65
+ }
66
+ if (!isNonEmptyString(proxy.command)) {
67
+ addValidationIssue(errors, "egress-proxy-command-missing", "egressProxy.command", "Verified proxy evidence requires the proxy command");
68
+ }
69
+ if (!isNonEmptyString(proxy.artifactPath)) {
70
+ addValidationIssue(errors, "egress-proxy-artifact-missing", "egressProxy.artifactPath", "Verified proxy evidence requires an artifact path");
71
+ }
72
+ }
73
+ export function validateDesktopAppProfile(input) {
74
+ const profile = normalizeDesktopProfile(input);
75
+ const errors = [];
76
+ if (!hasAppIdentity(profile)) {
77
+ addValidationIssue(errors, "app-identity-missing", "appId", "Desktop evidence requires an app id, path, or process name");
78
+ }
79
+ if (!isPlatform(profile.platform)) {
80
+ addValidationIssue(errors, "platform-invalid", "platform", "Desktop evidence platform must be macos or windows");
81
+ }
82
+ if (!isAutomationBackend(profile.automationBackend)) {
83
+ addValidationIssue(errors, "automation-backend-invalid", "automationBackend", "Desktop automation backend must be accessibility, xctest, uia, or unknown");
84
+ }
85
+ validateEvidenceArtifacts(errors, profile.evidenceArtifacts);
86
+ if (profile.providerRunId !== undefined && !isNonEmptyString(profile.provider)) {
87
+ addValidationIssue(errors, "provider-required-for-run-id", "provider", "Provider run id requires provider metadata");
88
+ }
89
+ validateEgressProxy(errors, profile.egressProxy);
90
+ return { errors };
91
+ }
92
+ function validEvidenceArtifacts(profile) {
93
+ const artifacts = Array.isArray(profile.evidenceArtifacts) ? profile.evidenceArtifacts : [];
94
+ const out = [];
95
+ for (const artifact of artifacts) {
96
+ if (!isRecord(artifact))
97
+ continue;
98
+ if (!isArtifactKind(artifact.kind))
99
+ continue;
100
+ if (!isNonEmptyString(artifact.path))
101
+ continue;
102
+ if (hasPathTraversal(artifact.path))
103
+ continue;
104
+ out.push({ kind: artifact.kind, path: artifact.path });
105
+ }
106
+ return out;
107
+ }
108
+ function pathsForKind(artifacts, kind) {
109
+ const out = [];
110
+ for (const artifact of artifacts) {
111
+ if (artifact.kind === kind)
112
+ out.push(artifact.path);
113
+ }
114
+ return out;
115
+ }
116
+ function hasCompleteDesktopEgressProxyEvidence(proxy) {
117
+ return proxy?.verified === true && Boolean(proxy.provider && proxy.command && proxy.artifactPath);
118
+ }
119
+ function desktopEgressGap(profile) {
120
+ if (hasCompleteDesktopEgressProxyEvidence(profile.egressProxy))
121
+ return undefined;
122
+ if (profile.egressProxy?.verified === true) {
123
+ return {
124
+ kind: "desktop-egress-unenforced",
125
+ severity: "blocker-for-exhaustive",
126
+ scope: profile.platform,
127
+ message: "Desktop network egress proxy was marked verified, but verified proxy evidence is incomplete; provide provider, command, and artifact",
128
+ };
129
+ }
130
+ return {
131
+ kind: "desktop-egress-unenforced",
132
+ severity: "blocker-for-exhaustive",
133
+ scope: profile.platform,
134
+ message: "Desktop network egress is not enforced without verified OS-level proxy evidence",
135
+ };
136
+ }
137
+ function platformEvidenceGaps(profile, artifacts) {
138
+ const gaps = [];
139
+ if (profile.platform === "macos") {
140
+ const hasAccessibilityTree = pathsForKind(artifacts, "accessibility-tree").length > 0;
141
+ if (profile.accessibilityPermissionVerified !== true || !hasAccessibilityTree) {
142
+ gaps.push({
143
+ kind: "desktop-accessibility-unavailable",
144
+ severity: "blocker-for-exhaustive",
145
+ scope: "macos",
146
+ message: "macOS desktop coverage requires verified Accessibility permission and an accessibility-tree artifact",
147
+ });
148
+ }
149
+ }
150
+ if (profile.platform === "windows") {
151
+ const hasAutomationTree = profile.uiAutomationTreeAvailable === true || pathsForKind(artifacts, "automation-tree").length > 0;
152
+ if (!hasAutomationTree) {
153
+ gaps.push({
154
+ kind: "desktop-automation-unavailable",
155
+ severity: "blocker-for-exhaustive",
156
+ scope: "windows",
157
+ message: "Windows desktop coverage requires UI Automation tree evidence",
158
+ });
159
+ }
160
+ }
161
+ return gaps;
162
+ }
163
+ export function buildDesktopEvidence(input) {
164
+ const profile = normalizeDesktopProfile(input);
165
+ const validation = validateDesktopAppProfile(profile);
166
+ const evidenceArtifacts = validEvidenceArtifacts(profile);
167
+ const egressGap = desktopEgressGap(profile);
168
+ const validationGaps = validation.errors.length > 0
169
+ ? [
170
+ {
171
+ kind: "desktop-evidence-invalid",
172
+ severity: "blocker-for-exhaustive",
173
+ scope: profile.platform,
174
+ message: `Desktop evidence validation failed: ${validation.errors.map((error) => error.code).join(", ")}`,
175
+ },
176
+ ]
177
+ : [];
178
+ const gaps = [
179
+ ...(egressGap ? [egressGap] : []),
180
+ ...validationGaps,
181
+ ...platformEvidenceGaps(profile, evidenceArtifacts),
182
+ ];
183
+ return {
184
+ platform: profile.platform,
185
+ ...(profile.appId !== undefined ? { appId: profile.appId } : {}),
186
+ ...(profile.appPath !== undefined ? { appPath: profile.appPath } : {}),
187
+ ...(profile.processName !== undefined ? { processName: profile.processName } : {}),
188
+ ...(profile.appVersion !== undefined ? { appVersion: profile.appVersion } : {}),
189
+ ...(profile.osVersion !== undefined ? { osVersion: profile.osVersion } : {}),
190
+ automationBackend: profile.automationBackend ?? "unknown",
191
+ ...(profile.provider !== undefined ? { provider: profile.provider } : {}),
192
+ ...(profile.providerRunId !== undefined ? { providerRunId: profile.providerRunId } : {}),
193
+ ...(profile.launchCommand !== undefined ? { launchCommand: profile.launchCommand } : {}),
194
+ ...(profile.verificationCommand !== undefined ? { verificationCommand: profile.verificationCommand } : {}),
195
+ evidenceArtifacts: evidenceArtifacts.map((artifact) => ({ ...artifact })),
196
+ screenshots: pathsForKind(evidenceArtifacts, "screenshot"),
197
+ videos: pathsForKind(evidenceArtifacts, "video"),
198
+ logs: pathsForKind(evidenceArtifacts, "log"),
199
+ crashLogs: pathsForKind(evidenceArtifacts, "crash-log"),
200
+ accessibilityTrees: pathsForKind(evidenceArtifacts, "accessibility-tree"),
201
+ automationTrees: pathsForKind(evidenceArtifacts, "automation-tree"),
202
+ ...(profile.egressProxy !== undefined ? { egressProxy: { ...profile.egressProxy } } : {}),
203
+ validationErrors: validation.errors.map((error) => ({ ...error })),
204
+ gaps,
205
+ };
206
+ }