swipium 1.0.1 → 1.2.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.
- package/README.md +21 -6
- package/THREAT_MODEL.md +59 -0
- package/dist/appMap/codeIndex.js +37 -5
- package/dist/appMap/codeIndex.js.map +1 -1
- package/dist/appMap/diff.js +60 -0
- package/dist/appMap/diff.js.map +1 -0
- package/dist/appMap/query.js +22 -4
- package/dist/appMap/query.js.map +1 -1
- package/dist/automation/capabilities.js +167 -0
- package/dist/automation/capabilities.js.map +1 -0
- package/dist/automation/gestures.js +94 -0
- package/dist/automation/gestures.js.map +1 -0
- package/dist/automation/maestroIr.js +282 -0
- package/dist/automation/maestroIr.js.map +1 -0
- package/dist/automation/plan.js +268 -0
- package/dist/automation/plan.js.map +1 -0
- package/dist/automation/report.js +83 -0
- package/dist/automation/report.js.map +1 -0
- package/dist/automation/selectors.js +201 -0
- package/dist/automation/selectors.js.map +1 -0
- package/dist/automation/types.js +13 -0
- package/dist/automation/types.js.map +1 -0
- package/dist/automation/waits.js +91 -0
- package/dist/automation/waits.js.map +1 -0
- package/dist/automation/webview.js +81 -0
- package/dist/automation/webview.js.map +1 -0
- package/dist/drivers/WdaDriver.js +18 -5
- package/dist/drivers/WdaDriver.js.map +1 -1
- package/dist/explore/candidates.js +17 -0
- package/dist/explore/candidates.js.map +1 -1
- package/dist/explore/runner.js +29 -2
- package/dist/explore/runner.js.map +1 -1
- package/dist/flows/repair.js +363 -0
- package/dist/flows/repair.js.map +1 -0
- package/dist/interop/maestro.js +151 -0
- package/dist/interop/maestro.js.map +1 -0
- package/dist/lib/wda.js +17 -0
- package/dist/lib/wda.js.map +1 -1
- package/dist/mobileAudit/checks.js +251 -0
- package/dist/mobileAudit/checks.js.map +1 -0
- package/dist/mobileAudit/evidence.js +49 -0
- package/dist/mobileAudit/evidence.js.map +1 -0
- package/dist/mobileAudit/profiles.js +73 -0
- package/dist/mobileAudit/profiles.js.map +1 -0
- package/dist/mobileAudit/results.js +41 -0
- package/dist/mobileAudit/results.js.map +1 -0
- package/dist/mobileAudit/runner.js +229 -0
- package/dist/mobileAudit/runner.js.map +1 -0
- package/dist/oracle/failures.js +1 -0
- package/dist/oracle/failures.js.map +1 -1
- package/dist/oracle/locator.js +177 -0
- package/dist/oracle/locator.js.map +1 -0
- package/dist/orchestration/envelope.js.map +1 -1
- package/dist/prompts/index.js +10 -0
- package/dist/prompts/index.js.map +1 -1
- package/dist/report/export.js +3 -1
- package/dist/report/export.js.map +1 -1
- package/dist/server.js +49 -2
- package/dist/server.js.map +1 -1
- package/dist/services/build.js +15 -2
- package/dist/services/build.js.map +1 -1
- package/dist/services/prepareIos.js +34 -4
- package/dist/services/prepareIos.js.map +1 -1
- package/dist/services/report.js +26 -9
- package/dist/services/report.js.map +1 -1
- package/dist/session/store.js.map +1 -1
- package/dist/suite/pom.js +24 -9
- package/dist/suite/pom.js.map +1 -1
- package/dist/testSuite/exporter.js +70 -0
- package/dist/testSuite/exporter.js.map +1 -0
- package/dist/testSuite/lint.js +53 -0
- package/dist/testSuite/lint.js.map +1 -0
- package/dist/tools/act.js +23 -2
- package/dist/tools/act.js.map +1 -1
- package/dist/tools/appControl.js +176 -0
- package/dist/tools/appControl.js.map +1 -0
- package/dist/tools/capabilities.js +75 -4
- package/dist/tools/capabilities.js.map +1 -1
- package/dist/tools/device.js +151 -0
- package/dist/tools/device.js.map +1 -0
- package/dist/tools/flow.js +67 -1
- package/dist/tools/flow.js.map +1 -1
- package/dist/tools/flowRepair.js +66 -0
- package/dist/tools/flowRepair.js.map +1 -0
- package/dist/tools/history.js +56 -0
- package/dist/tools/history.js.map +1 -0
- package/dist/tools/idling.js +104 -0
- package/dist/tools/idling.js.map +1 -0
- package/dist/tools/inputCapabilities.js +30 -0
- package/dist/tools/inputCapabilities.js.map +1 -0
- package/dist/tools/issues.js +218 -0
- package/dist/tools/issues.js.map +1 -0
- package/dist/tools/jobs.js +12 -1
- package/dist/tools/jobs.js.map +1 -1
- package/dist/tools/locator.js +57 -0
- package/dist/tools/locator.js.map +1 -0
- package/dist/tools/maestro.js +78 -0
- package/dist/tools/maestro.js.map +1 -0
- package/dist/tools/metro.js +260 -0
- package/dist/tools/metro.js.map +1 -0
- package/dist/tools/mobileAudit.js +115 -0
- package/dist/tools/mobileAudit.js.map +1 -0
- package/dist/tools/network.js +97 -5
- package/dist/tools/network.js.map +1 -1
- package/dist/tools/permissions.js +149 -0
- package/dist/tools/permissions.js.map +1 -0
- package/dist/tools/screenInfo.js +70 -0
- package/dist/tools/screenInfo.js.map +1 -0
- package/dist/tools/screenRecord.js +215 -6
- package/dist/tools/screenRecord.js.map +1 -1
- package/dist/tools/seed.js +101 -0
- package/dist/tools/seed.js.map +1 -0
- package/dist/tools/state.js +83 -0
- package/dist/tools/state.js.map +1 -1
- package/dist/tools/suite.js +49 -1
- package/dist/tools/suite.js.map +1 -1
- package/dist/tools/testSuite.js +233 -0
- package/dist/tools/testSuite.js.map +1 -0
- package/dist/tools/testThis.js +11 -3
- package/dist/tools/testThis.js.map +1 -1
- package/dist/tools/visual.js +139 -0
- package/dist/tools/visual.js.map +1 -0
- package/dist/tools/visualText.js +61 -0
- package/dist/tools/visualText.js.map +1 -0
- package/dist/tools/wait.js +58 -0
- package/dist/tools/wait.js.map +1 -0
- package/dist/version.js +54 -3
- package/dist/version.js.map +1 -1
- package/docs/README.md +4 -4
- package/docs/mcp-server.md +3 -3
- package/docs/tools.md +111 -2
- package/package.json +3 -2
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// Automation Kernel V2 — Workstream 3: the Action Compiler. Compiles a Flow V2 file into Action IR,
|
|
2
|
+
// then into a backend-specific automation plan WITHOUT touching a device. Every step is classified
|
|
3
|
+
// before execution (native / supported_with_fallback / visual_only / unsupported) and unsupported
|
|
4
|
+
// steps name the exact missing capability and a concrete next step. This is the pure core behind the
|
|
5
|
+
// qa_flow_plan tool; it does not execute or mutate anything.
|
|
6
|
+
import { selectorSupported } from './capabilities.js';
|
|
7
|
+
import { checkSelectorBackend, parseSelector, selectorForCoordinate, selectorForVisual } from './selectors.js';
|
|
8
|
+
import { gestureSupport } from './gestures.js';
|
|
9
|
+
import { isVisualStrategy } from './types.js';
|
|
10
|
+
/** Compile a single Flow V2 step into Action IR. Returns null for steps with no automation action. */
|
|
11
|
+
export function compileStep(step) {
|
|
12
|
+
switch (step.kind) {
|
|
13
|
+
case 'tap':
|
|
14
|
+
return { kind: 'tap', selector: parseSelector(step.selector), expectedChange: 'unknown', note: step.selector };
|
|
15
|
+
case 'tapAt':
|
|
16
|
+
return { kind: 'tap', selector: selectorForCoordinate(`${step.x},${step.y}`), expectedChange: 'unknown', note: `tapAt ${step.x},${step.y}` };
|
|
17
|
+
case 'tapImage':
|
|
18
|
+
return { kind: 'tap', selector: selectorForVisual('image', step.template), expectedChange: 'unknown', note: `tapImage ${step.template}` };
|
|
19
|
+
case 'tapOcrText':
|
|
20
|
+
return { kind: 'tap', selector: selectorForVisual('ocr_text', step.query), expectedChange: 'unknown', note: `tapOcrText ${step.query}` };
|
|
21
|
+
case 'inputText':
|
|
22
|
+
return { kind: 'inputText', selector: step.into ? parseSelector(step.into) : undefined, text: step.value, note: step.into ?? '(focused field)' };
|
|
23
|
+
case 'assertVisible':
|
|
24
|
+
return { kind: 'assertVisible', selector: parseSelector(step.query), note: step.query };
|
|
25
|
+
case 'assertNotVisible':
|
|
26
|
+
return { kind: 'waitForNotVisible', selector: parseSelector(step.query), note: step.query };
|
|
27
|
+
case 'assertImage':
|
|
28
|
+
return { kind: 'assertVisual', selector: selectorForVisual('image', step.template), note: `assertImage ${step.template}` };
|
|
29
|
+
case 'assertOcrText':
|
|
30
|
+
return { kind: 'assertVisual', selector: selectorForVisual('ocr_text', step.query), note: `assertOcrText ${step.query}` };
|
|
31
|
+
case 'assertVisual':
|
|
32
|
+
return { kind: 'assertVisual', note: step.description };
|
|
33
|
+
case 'assertDiff':
|
|
34
|
+
return { kind: 'assertVisual', note: `assertDiff ${step.baseline}` };
|
|
35
|
+
case 'swipe': {
|
|
36
|
+
const gesture = { kind: 'swipe', direction: step.direction, area: step.area };
|
|
37
|
+
return { kind: 'swipe', gesture, note: `swipe ${step.direction}` };
|
|
38
|
+
}
|
|
39
|
+
case 'scrollTo': {
|
|
40
|
+
const selector = parseSelector(step.query);
|
|
41
|
+
const gesture = { kind: 'scroll', target: selector, direction: 'down', visibilityPercentage: 100 };
|
|
42
|
+
return { kind: 'scrollUntilVisible', selector, gesture, note: step.query };
|
|
43
|
+
}
|
|
44
|
+
case 'press':
|
|
45
|
+
return { kind: 'pressKey', text: step.key, note: `press ${step.key}` };
|
|
46
|
+
case 'openUrl':
|
|
47
|
+
return { kind: 'openUrl', text: step.url, note: step.url };
|
|
48
|
+
case 'waitForVisible':
|
|
49
|
+
return { kind: 'waitForVisible', selector: parseSelector(step.query), timeoutMs: step.timeoutMs, note: step.query };
|
|
50
|
+
case 'wait':
|
|
51
|
+
return step.query
|
|
52
|
+
? { kind: 'waitForVisible', selector: parseSelector(step.query), note: step.query }
|
|
53
|
+
: { kind: 'waitForIdle', idleSource: 'heuristic', timeoutMs: step.ms, note: step.ms != null ? `wait ${step.ms}ms` : 'wait' };
|
|
54
|
+
case 'waitForIdle':
|
|
55
|
+
return { kind: 'waitForIdle', idleSource: 'heuristic', timeoutMs: step.timeoutMs, note: 'waitForIdle' };
|
|
56
|
+
// Lifecycle / environment / meta steps — modeled but not selector-targeted.
|
|
57
|
+
case 'prepareTarget':
|
|
58
|
+
case 'restartApp':
|
|
59
|
+
case 'clearOverlay':
|
|
60
|
+
case 'networkOffline':
|
|
61
|
+
case 'networkOnline':
|
|
62
|
+
case 'seed':
|
|
63
|
+
case 'note':
|
|
64
|
+
case 'screenshot':
|
|
65
|
+
return { kind: 'lifecycle', note: step.kind };
|
|
66
|
+
default:
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/** Compile all of a flow's setup + main + teardown steps into Action IR. */
|
|
71
|
+
export function compileActions(flow) {
|
|
72
|
+
return [...flow.setup, ...flow.steps, ...flow.teardown]
|
|
73
|
+
.map(compileStep)
|
|
74
|
+
.filter((a) => a != null);
|
|
75
|
+
}
|
|
76
|
+
const STRUCTURED_ACTIONS = new Set([
|
|
77
|
+
'tap', 'longPress', 'doubleTap', 'inputText', 'clearText', 'scrollUntilVisible',
|
|
78
|
+
'waitForVisible', 'waitForNotVisible', 'assertVisible',
|
|
79
|
+
]);
|
|
80
|
+
function hasNonAscii(text) {
|
|
81
|
+
if (!text)
|
|
82
|
+
return false;
|
|
83
|
+
for (let i = 0; i < text.length; i++)
|
|
84
|
+
if (text.charCodeAt(i) > 127)
|
|
85
|
+
return true;
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Classify a text-input action's backend support. Returns a blocking Classification, or null when the
|
|
90
|
+
* input is fine. ASCII needs textInputAscii; literal non-ASCII text (e.g. "José") additionally needs
|
|
91
|
+
* textInputUnicode — adb `input text` cannot type Unicode reliably, so Android direct is blocked.
|
|
92
|
+
*/
|
|
93
|
+
function inputTextSupport(action, caps) {
|
|
94
|
+
if (!caps.textInputAscii)
|
|
95
|
+
return { support: 'unsupported', reason: `text input is unsupported on ${caps.backend}.`, requiredCapability: 'textInputAscii' };
|
|
96
|
+
if (hasNonAscii(action.text) && !caps.textInputUnicode) {
|
|
97
|
+
return {
|
|
98
|
+
support: 'unsupported',
|
|
99
|
+
reason: `text "${action.text}" contains non-ASCII characters; ${caps.backend} cannot input Unicode reliably.`,
|
|
100
|
+
requiredCapability: 'textInputUnicode',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
function classifyAction(action, caps) {
|
|
106
|
+
// Lifecycle / control actions: available wherever lifecycle is (launch is our proxy).
|
|
107
|
+
if (action.kind === 'lifecycle' || action.kind === 'openUrl' || action.kind === 'pressKey') {
|
|
108
|
+
if (action.kind === 'openUrl' && !caps.openUrl) {
|
|
109
|
+
return { support: 'unsupported', reason: `openUrl is not supported on ${caps.backend}.`, requiredCapability: 'openUrl' };
|
|
110
|
+
}
|
|
111
|
+
return { support: 'native', reason: `${action.note ?? action.kind} runs as a lifecycle/control step on ${caps.backend}.` };
|
|
112
|
+
}
|
|
113
|
+
if (action.kind === 'waitForIdle') {
|
|
114
|
+
if (action.idleSource === 'app_declared' && !caps.appDeclaredIdling) {
|
|
115
|
+
return { support: 'supported_with_fallback', reason: `app-declared idling is unavailable on ${caps.backend}; will fall back to heuristic settling (not app proof).` };
|
|
116
|
+
}
|
|
117
|
+
return { support: 'native', reason: `waitForIdle uses ${caps.wdaIdling ? 'backend' : 'heuristic'} settling on ${caps.backend}.` };
|
|
118
|
+
}
|
|
119
|
+
if (action.kind === 'waitForAnimationToEnd') {
|
|
120
|
+
return { support: 'native', reason: `animation wait is honored heuristically on ${caps.backend}.` };
|
|
121
|
+
}
|
|
122
|
+
if (action.kind === 'swipe' && action.gesture) {
|
|
123
|
+
const g = gestureSupport(action.gesture, caps);
|
|
124
|
+
return g.supported
|
|
125
|
+
? { support: 'native', reason: g.reason }
|
|
126
|
+
: { support: 'unsupported', reason: g.reason, requiredCapability: g.requiredCapability };
|
|
127
|
+
}
|
|
128
|
+
if (action.kind === 'pinch' || action.kind === 'drag' || action.kind === 'longPress' || action.kind === 'doubleTap') {
|
|
129
|
+
const g = gestureSupport(action.gesture ?? { kind: action.kind === 'pinch' ? 'pinch' : action.kind === 'drag' ? 'drag' : action.kind === 'longPress' ? 'longPress' : 'doubleTap' }, caps);
|
|
130
|
+
if (!g.supported && (STRUCTURED_ACTIONS.has(action.kind) || action.kind === 'pinch' || action.kind === 'drag')) {
|
|
131
|
+
return { support: 'unsupported', reason: g.reason, requiredCapability: g.requiredCapability };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const selector = action.selector;
|
|
135
|
+
// Visual-strategy targets are candidate evidence only.
|
|
136
|
+
if (selector && isVisualStrategy(selector.strategy)) {
|
|
137
|
+
const ok = selectorSupported(caps, selector.strategy);
|
|
138
|
+
return ok
|
|
139
|
+
? { support: 'visual_only', reason: `${action.kind} uses a ${selector.strategy} target — visual/OCR candidate evidence, not a structured locator proof.` }
|
|
140
|
+
: { support: 'unsupported', reason: `${selector.strategy} fallback is unavailable on ${caps.backend}.`, requiredCapability: selector.strategy };
|
|
141
|
+
}
|
|
142
|
+
// assertVisual with no selector is always visual-only candidate evidence.
|
|
143
|
+
if (action.kind === 'assertVisual') {
|
|
144
|
+
return { support: 'visual_only', reason: 'assertVisual records visual candidate evidence; it is not a structured assertion.' };
|
|
145
|
+
}
|
|
146
|
+
// Coordinate targets work anywhere we can screenshot, but are a fallback (brittle).
|
|
147
|
+
if (selector && selector.strategy === 'coordinate') {
|
|
148
|
+
return selectorSupported(caps, 'coordinate')
|
|
149
|
+
? { support: 'supported_with_fallback', reason: `${action.kind} by coordinate is a brittle fallback on ${caps.backend}; prefer a durable selector.` }
|
|
150
|
+
: { support: 'unsupported', reason: `coordinate targeting needs screenshot support on ${caps.backend}.`, requiredCapability: 'screenshot' };
|
|
151
|
+
}
|
|
152
|
+
// Structured selector actions: the backend must support the selector strategy.
|
|
153
|
+
if (selector && STRUCTURED_ACTIONS.has(action.kind)) {
|
|
154
|
+
const check = checkSelectorBackend(selector, caps);
|
|
155
|
+
if (!check.supported) {
|
|
156
|
+
// If the backend has no structured tree at all (e.g. iOS raw sim), surface the structural blocker.
|
|
157
|
+
if (!caps.structuredTree) {
|
|
158
|
+
return {
|
|
159
|
+
support: 'unsupported',
|
|
160
|
+
reason: `${caps.backend} cannot run structured ${action.kind}; ${check.detail}`,
|
|
161
|
+
requiredCapability: 'structuredTree',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { support: 'unsupported', reason: check.detail ?? `${selector.strategy} unsupported on ${caps.backend}.`, requiredCapability: selector.strategy };
|
|
165
|
+
}
|
|
166
|
+
// Text input also needs the right input capability (ASCII, and Unicode for non-ASCII text).
|
|
167
|
+
if (action.kind === 'inputText') {
|
|
168
|
+
const t = inputTextSupport(action, caps);
|
|
169
|
+
if (t)
|
|
170
|
+
return t;
|
|
171
|
+
}
|
|
172
|
+
return { support: 'native', reason: `${action.kind} via ${selector.strategy} is native on ${caps.backend}.` };
|
|
173
|
+
}
|
|
174
|
+
// inputText into the focused field (no selector).
|
|
175
|
+
if (action.kind === 'inputText') {
|
|
176
|
+
const t = inputTextSupport(action, caps);
|
|
177
|
+
if (t)
|
|
178
|
+
return t;
|
|
179
|
+
return { support: 'native', reason: `text input into the focused field is native on ${caps.backend}.` };
|
|
180
|
+
}
|
|
181
|
+
return { support: 'native', reason: `${action.kind} is supported on ${caps.backend}.` };
|
|
182
|
+
}
|
|
183
|
+
function nextStepForRequirement(requiredCapability, backend) {
|
|
184
|
+
switch (requiredCapability) {
|
|
185
|
+
case 'structuredTree':
|
|
186
|
+
return 'Attach WDA or Appium for structured selectors, or rewrite the step as a visual/OCR check.';
|
|
187
|
+
case 'pinch':
|
|
188
|
+
return 'Attach Appium UiAutomator2/XCUITest, or replace the pinch with a swipe/scroll.';
|
|
189
|
+
case 'textInputAscii':
|
|
190
|
+
return 'Use a backend that supports text input (WDA/Appium), or drive the field another way.';
|
|
191
|
+
case 'textInputUnicode':
|
|
192
|
+
return 'Use WDA or Appium for Unicode text, or change the fixture value to ASCII (adb input text cannot type Unicode reliably).';
|
|
193
|
+
case 'accessibility_id':
|
|
194
|
+
case 'resource_id':
|
|
195
|
+
return 'Attach a structured backend, or add a durable accessibility id / resource id.';
|
|
196
|
+
case 'ios_predicate':
|
|
197
|
+
case 'ios_class_chain':
|
|
198
|
+
return 'Use iOS WDA or Appium XCUITest, or replace it with an accessibility id.';
|
|
199
|
+
case 'ocr_text':
|
|
200
|
+
case 'image':
|
|
201
|
+
return 'Enable visual/OCR fallback, or attach a structured backend.';
|
|
202
|
+
default:
|
|
203
|
+
return `Attach a backend on which this step is supported (current: ${backend}).`;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Compile a Flow V2 file into a backend-specific automation plan. Pure — no device, no mutation.
|
|
208
|
+
*/
|
|
209
|
+
export function compileAutomationPlan(flow, caps) {
|
|
210
|
+
const actions = compileActions(flow);
|
|
211
|
+
const steps = [];
|
|
212
|
+
const blockers = [];
|
|
213
|
+
const warnings = [];
|
|
214
|
+
actions.forEach((action, index) => {
|
|
215
|
+
const cls = classifyAction(action, caps);
|
|
216
|
+
const step = { index, action, support: cls.support, reason: cls.reason, requiredCapability: cls.requiredCapability };
|
|
217
|
+
steps.push(step);
|
|
218
|
+
if (cls.support === 'unsupported') {
|
|
219
|
+
blockers.push({
|
|
220
|
+
code: cls.requiredCapability === 'structuredTree' ? 'BACKEND_UNSUPPORTED' : 'STEP_UNSUPPORTED',
|
|
221
|
+
detail: `step ${index} (${action.note ?? action.kind}): ${cls.reason}`,
|
|
222
|
+
nextStep: nextStepForRequirement(cls.requiredCapability, caps.backend),
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
else if (cls.support === 'visual_only') {
|
|
226
|
+
warnings.push({
|
|
227
|
+
code: 'VISUAL_ONLY',
|
|
228
|
+
detail: `step ${index} (${action.note ?? action.kind}): ${cls.reason}`,
|
|
229
|
+
nextStep: 'This is candidate-level evidence; add a structured selector for CI-grade proof.',
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
else if (cls.support === 'supported_with_fallback') {
|
|
233
|
+
warnings.push({
|
|
234
|
+
code: 'FALLBACK_USED',
|
|
235
|
+
detail: `step ${index} (${action.note ?? action.kind}): ${cls.reason}`,
|
|
236
|
+
nextStep: 'Prefer a durable selector to avoid the fallback.',
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
const executable = steps.every((s) => s.support !== 'unsupported');
|
|
241
|
+
const visualOnly = steps.filter((s) => s.support === 'visual_only').length;
|
|
242
|
+
const supported = steps.filter((s) => s.support === 'native' || s.support === 'supported_with_fallback').length;
|
|
243
|
+
const agentMessage = buildAgentMessage(caps.backend, executable, supported, visualOnly, blockers);
|
|
244
|
+
const developerMessage = buildDeveloperMessage(caps, steps, blockers, warnings);
|
|
245
|
+
return { backend: caps.backend, executable, steps, blockers, warnings, agentMessage, developerMessage };
|
|
246
|
+
}
|
|
247
|
+
function buildAgentMessage(backend, executable, supported, visualOnly, blockers) {
|
|
248
|
+
if (!executable) {
|
|
249
|
+
const first = blockers[0];
|
|
250
|
+
return `This flow is not runnable on ${backend}: ${first?.detail ?? 'an unsupported step blocks it'}. ${first?.nextStep ?? ''}`.trim();
|
|
251
|
+
}
|
|
252
|
+
if (supported === 0 && visualOnly > 0) {
|
|
253
|
+
return `This flow is candidate-only on ${backend}: ${visualOnly} visual/OCR step(s) and no structured locators. It produces candidate evidence, not structured proof.`;
|
|
254
|
+
}
|
|
255
|
+
const visualPart = visualOnly ? ` and ${visualOnly} visual fallback step(s)` : '';
|
|
256
|
+
return `This flow is runnable on ${backend} with ${supported} structured step(s)${visualPart}.`;
|
|
257
|
+
}
|
|
258
|
+
function buildDeveloperMessage(caps, steps, blockers, warnings) {
|
|
259
|
+
const lines = [`Backend: ${caps.backend}. ${steps.length} step(s) planned.`];
|
|
260
|
+
for (const b of blockers)
|
|
261
|
+
lines.push(`BLOCKER ${b.code}: ${b.detail} → ${b.nextStep}`);
|
|
262
|
+
for (const w of warnings)
|
|
263
|
+
lines.push(`WARNING ${w.code}: ${w.detail} → ${w.nextStep}`);
|
|
264
|
+
if (caps.notes.length)
|
|
265
|
+
lines.push(`Backend notes: ${caps.notes.join(' ')}`);
|
|
266
|
+
return lines.join('\n');
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/automation/plan.ts"],"names":[],"mappings":"AAAA,oGAAoG;AACpG,mGAAmG;AACnG,kGAAkG;AAClG,qGAAqG;AACrG,6DAA6D;AAI7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAC/G,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAU/C,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,sGAAsG;AACtG,MAAM,UAAU,WAAW,CAAC,IAAc;IACxC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,KAAK;YACR,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACjH,KAAK,OAAO;YACV,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,qBAAqB,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QAC/I,KAAK,UAAU;YACb,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,YAAY,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC5I,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,cAAc,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAC3I,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,iBAAiB,EAAE,CAAC;QACnJ,KAAK,eAAe;YAClB,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC1F,KAAK,kBAAkB;YACrB,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9F,KAAK,aAAa;YAChB,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,eAAe,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC7H,KAAK,eAAe;YAClB,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,QAAQ,EAAE,iBAAiB,CAAC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,iBAAiB,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;QAC5H,KAAK,cAAc;YACjB,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1D,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,cAAc,IAAI,CAAC,QAAQ,EAAE,EAAE,CAAC;QACvE,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,MAAM,OAAO,GAAc,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;YACzF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACrE,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,MAAM,QAAQ,GAAG,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC3C,MAAM,OAAO,GAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,oBAAoB,EAAE,GAAG,EAAE,CAAC;YAC9G,OAAO,EAAE,IAAI,EAAE,oBAAoB,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QAC7E,CAAC;QACD,KAAK,OAAO;YACV,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,SAAS,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;QACzE,KAAK,SAAS;YACZ,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC;QAC7D,KAAK,gBAAgB;YACnB,OAAO,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC;QACtH,KAAK,MAAM;YACT,OAAO,IAAI,CAAC,KAAK;gBACf,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,EAAE,QAAQ,EAAE,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE;gBACnF,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;QACjI,KAAK,aAAa;YAChB,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAC1G,4EAA4E;QAC5E,KAAK,eAAe,CAAC;QACrB,KAAK,YAAY,CAAC;QAClB,KAAK,cAAc,CAAC;QACpB,KAAK,gBAAgB,CAAC;QACtB,KAAK,eAAe,CAAC;QACrB,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM,CAAC;QACZ,KAAK,YAAY;YACf,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC;QAChD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,cAAc,CAAC,IAAU;IACvC,OAAO,CAAC,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC;SACpD,GAAG,CAAC,WAAW,CAAC;SAChB,MAAM,CAAC,CAAC,CAAC,EAAiB,EAAE,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAmB;IACnD,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,oBAAoB;IAC/E,gBAAgB,EAAE,mBAAmB,EAAE,eAAe;CACvD,CAAC,CAAC;AAQH,SAAS,WAAW,CAAC,IAAa;IAChC,IAAI,CAAC,IAAI;QAAE,OAAO,KAAK,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;QAAE,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,GAAG;YAAE,OAAO,IAAI,CAAC;IAChF,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,MAAgB,EAAE,IAAyB;IACnE,IAAI,CAAC,IAAI,CAAC,cAAc;QAAE,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,gCAAgC,IAAI,CAAC,OAAO,GAAG,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;IAC3J,IAAI,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACvD,OAAO;YACL,OAAO,EAAE,aAAa;YACtB,MAAM,EAAE,SAAS,MAAM,CAAC,IAAI,oCAAoC,IAAI,CAAC,OAAO,iCAAiC;YAC7G,kBAAkB,EAAE,kBAAkB;SACvC,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,cAAc,CAAC,MAAgB,EAAE,IAAyB;IACjE,sFAAsF;IACtF,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;QAC3F,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAC/C,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,+BAA+B,IAAI,CAAC,OAAO,GAAG,EAAE,kBAAkB,EAAE,SAAS,EAAE,CAAC;QAC3H,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,wCAAwC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IAC7H,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,UAAU,KAAK,cAAc,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YACpE,OAAO,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,EAAE,yCAAyC,IAAI,CAAC,OAAO,yDAAyD,EAAE,CAAC;QACxK,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,gBAAgB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpI,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,uBAAuB,EAAE,CAAC;QAC5C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,8CAA8C,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACtG,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC,SAAS;YAChB,CAAC,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE;YACzC,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,EAAE,CAAC;IAC7F,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QACpH,MAAM,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,CAAC;QAC1L,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,CAAC;YAC/G,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,EAAE,CAAC;QAChG,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;IAEjC,uDAAuD;IACvD,IAAI,QAAQ,IAAI,gBAAgB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpD,MAAM,EAAE,GAAG,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACtD,OAAO,EAAE;YACP,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,WAAW,QAAQ,CAAC,QAAQ,0EAA0E,EAAE;YAC1J,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,QAAQ,CAAC,QAAQ,+BAA+B,IAAI,CAAC,OAAO,GAAG,EAAE,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;IACpJ,CAAC;IAED,0EAA0E;IAC1E,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACnC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,mFAAmF,EAAE,CAAC;IACjI,CAAC;IAED,oFAAoF;IACpF,IAAI,QAAQ,IAAI,QAAQ,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QACnD,OAAO,iBAAiB,CAAC,IAAI,EAAE,YAAY,CAAC;YAC1C,CAAC,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,2CAA2C,IAAI,CAAC,OAAO,8BAA8B,EAAE;YACrJ,CAAC,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,oDAAoD,IAAI,CAAC,OAAO,GAAG,EAAE,kBAAkB,EAAE,YAAY,EAAE,CAAC;IAChJ,CAAC;IAED,+EAA+E;IAC/E,IAAI,QAAQ,IAAI,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACpD,MAAM,KAAK,GAAG,oBAAoB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACnD,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACrB,mGAAmG;YACnG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACzB,OAAO;oBACL,OAAO,EAAE,aAAa;oBACtB,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,0BAA0B,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE;oBAC/E,kBAAkB,EAAE,gBAAgB;iBACrC,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,mBAAmB,IAAI,CAAC,OAAO,GAAG,EAAE,kBAAkB,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAC3J,CAAC;QACD,4FAA4F;QAC5F,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChC,MAAM,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACzC,IAAI,CAAC;gBAAE,OAAO,CAAC,CAAC;QAClB,CAAC;QACD,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,QAAQ,QAAQ,CAAC,QAAQ,iBAAiB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IAChH,CAAC;IAED,kDAAkD;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;QAChB,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,kDAAkD,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IAC1G,CAAC;IAED,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,oBAAoB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;AAC1F,CAAC;AAED,SAAS,sBAAsB,CAAC,kBAAsC,EAAE,OAAe;IACrF,QAAQ,kBAAkB,EAAE,CAAC;QAC3B,KAAK,gBAAgB;YACnB,OAAO,2FAA2F,CAAC;QACrG,KAAK,OAAO;YACV,OAAO,gFAAgF,CAAC;QAC1F,KAAK,gBAAgB;YACnB,OAAO,sFAAsF,CAAC;QAChG,KAAK,kBAAkB;YACrB,OAAO,yHAAyH,CAAC;QACnI,KAAK,kBAAkB,CAAC;QACxB,KAAK,aAAa;YAChB,OAAO,+EAA+E,CAAC;QACzF,KAAK,eAAe,CAAC;QACrB,KAAK,iBAAiB;YACpB,OAAO,yEAAyE,CAAC;QACnF,KAAK,UAAU,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,6DAA6D,CAAC;QACvE;YACE,OAAO,8DAA8D,OAAO,IAAI,CAAC;IACrF,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAU,EAAE,IAAyB;IACzE,MAAM,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACrC,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,MAAM,QAAQ,GAAqB,EAAE,CAAC;IAEtC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChC,MAAM,GAAG,GAAG,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACzC,MAAM,IAAI,GAAa,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,CAAC,kBAAkB,EAAE,CAAC;QAC/H,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEjB,IAAI,GAAG,CAAC,OAAO,KAAK,aAAa,EAAE,CAAC;YAClC,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,GAAG,CAAC,kBAAkB,KAAK,gBAAgB,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,kBAAkB;gBAC9F,MAAM,EAAE,QAAQ,KAAK,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE;gBACtE,QAAQ,EAAE,sBAAsB,CAAC,GAAG,CAAC,kBAAkB,EAAE,IAAI,CAAC,OAAO,CAAC;aACvE,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,KAAK,aAAa,EAAE,CAAC;YACzC,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,aAAa;gBACnB,MAAM,EAAE,QAAQ,KAAK,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE;gBACtE,QAAQ,EAAE,iFAAiF;aAC5F,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,GAAG,CAAC,OAAO,KAAK,yBAAyB,EAAE,CAAC;YACrD,QAAQ,CAAC,IAAI,CAAC;gBACZ,IAAI,EAAE,eAAe;gBACrB,MAAM,EAAE,QAAQ,KAAK,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,MAAM,GAAG,CAAC,MAAM,EAAE;gBACtE,QAAQ,EAAE,kDAAkD;aAC7D,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,aAAa,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,aAAa,CAAC,CAAC,MAAM,CAAC;IAC3E,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,KAAK,yBAAyB,CAAC,CAAC,MAAM,CAAC;IAEhH,MAAM,YAAY,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,UAAU,EAAE,QAAQ,CAAC,CAAC;IAClG,MAAM,gBAAgB,GAAG,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAEhF,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAC1G,CAAC;AAED,SAAS,iBAAiB,CAAC,OAAe,EAAE,UAAmB,EAAE,SAAiB,EAAE,UAAkB,EAAE,QAA0B;IAChI,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC1B,OAAO,gCAAgC,OAAO,KAAK,KAAK,EAAE,MAAM,IAAI,+BAA+B,KAAK,KAAK,EAAE,QAAQ,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC;IACzI,CAAC;IACD,IAAI,SAAS,KAAK,CAAC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,kCAAkC,OAAO,KAAK,UAAU,uGAAuG,CAAC;IACzK,CAAC;IACD,MAAM,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,UAAU,0BAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;IAClF,OAAO,4BAA4B,OAAO,SAAS,SAAS,sBAAsB,UAAU,GAAG,CAAC;AAClG,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAyB,EAAE,KAAiB,EAAE,QAA0B,EAAE,QAA0B;IACjI,MAAM,KAAK,GAAG,CAAC,YAAY,IAAI,CAAC,OAAO,KAAK,KAAK,CAAC,MAAM,mBAAmB,CAAC,CAAC;IAC7E,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvF,KAAK,MAAM,CAAC,IAAI,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,MAAM,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;IACvF,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
// Automation Kernel V2 — Workstream 9: Automation Readiness Output. Turns an AutomationPlan into one
|
|
2
|
+
// consistent response shape with natural-language messages a coding agent can repeat verbatim to the
|
|
3
|
+
// user. The canonical phrases below match the plan's required wording for each backend/fallback case.
|
|
4
|
+
import { isVisualStrategy } from './types.js';
|
|
5
|
+
// Canonical phrases (plan Workstream 9 — "Required phrases").
|
|
6
|
+
const PHRASE = {
|
|
7
|
+
iosRawSimulator: 'I can launch and inspect the app in the iOS simulator, but this backend cannot run structured taps. Attach WDA or Appium for selector-based automation.',
|
|
8
|
+
androidDirect: 'I can run this on Android using resource-id/accessibility/text selectors. Unicode text input needs a stronger backend or fixture adjustment.',
|
|
9
|
+
appiumRequired: 'This flow needs an Appium backend because it uses a WebView context or gesture that the current backend cannot perform.',
|
|
10
|
+
visualFallback: 'I can continue with visual/OCR evidence, but that is candidate-level evidence and not a structured locator proof.',
|
|
11
|
+
};
|
|
12
|
+
// Structured interaction/assertion kinds — the ones that produce structured-locator proof. Lifecycle
|
|
13
|
+
// and control steps (openUrl, pressKey, waitForIdle, lifecycle) do NOT make a flow "ready" on their own.
|
|
14
|
+
const STRUCTURED_PROOF_KINDS = new Set([
|
|
15
|
+
'tap', 'longPress', 'doubleTap', 'inputText', 'clearText', 'scrollUntilVisible',
|
|
16
|
+
'swipe', 'drag', 'pinch', 'waitForVisible', 'waitForNotVisible', 'assertVisible',
|
|
17
|
+
]);
|
|
18
|
+
function providesStructuredProof(step) {
|
|
19
|
+
if (step.support !== 'native' && step.support !== 'supported_with_fallback')
|
|
20
|
+
return false;
|
|
21
|
+
if (!STRUCTURED_PROOF_KINDS.has(step.action.kind))
|
|
22
|
+
return false;
|
|
23
|
+
const sel = step.action.selector;
|
|
24
|
+
if (sel && (isVisualStrategy(sel.strategy) || sel.strategy === 'coordinate'))
|
|
25
|
+
return false;
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
function statusFor(plan) {
|
|
29
|
+
if (!plan.executable)
|
|
30
|
+
return 'blocked';
|
|
31
|
+
const hasStructured = plan.steps.some(providesStructuredProof);
|
|
32
|
+
const hasVisualOnly = plan.steps.some((s) => s.support === 'visual_only');
|
|
33
|
+
if (!hasStructured && hasVisualOnly)
|
|
34
|
+
return 'candidate';
|
|
35
|
+
return 'ready';
|
|
36
|
+
}
|
|
37
|
+
function fallbackUsed(plan) {
|
|
38
|
+
if (plan.backend === 'ios-raw-simulator' && statusFor(plan) !== 'ready')
|
|
39
|
+
return 'ios-raw-simulator';
|
|
40
|
+
if (plan.blockers.some((b) => /appium|webview|context/i.test(`${b.detail} ${b.nextStep}`)))
|
|
41
|
+
return 'appium-required';
|
|
42
|
+
if (plan.steps.some((s) => s.support === 'visual_only'))
|
|
43
|
+
return 'visual-only';
|
|
44
|
+
return 'none';
|
|
45
|
+
}
|
|
46
|
+
function headlineFor(status, backend) {
|
|
47
|
+
const label = status === 'ready' ? 'Ready' : status === 'candidate' ? 'Candidate-only' : 'Blocked';
|
|
48
|
+
return `${label} on ${backend}`;
|
|
49
|
+
}
|
|
50
|
+
/** Build the natural-language agent message, preferring the plan's required canonical phrasing. */
|
|
51
|
+
function agentMessageFor(plan, status) {
|
|
52
|
+
const fallback = fallbackUsed(plan);
|
|
53
|
+
const parts = [plan.agentMessage];
|
|
54
|
+
if (plan.backend === 'ios-raw-simulator' && status !== 'ready')
|
|
55
|
+
parts.push(PHRASE.iosRawSimulator);
|
|
56
|
+
if (plan.backend === 'android-direct')
|
|
57
|
+
parts.push(PHRASE.androidDirect);
|
|
58
|
+
if (fallback === 'appium-required')
|
|
59
|
+
parts.push(PHRASE.appiumRequired);
|
|
60
|
+
if (fallback === 'visual-only' || status === 'candidate')
|
|
61
|
+
parts.push(PHRASE.visualFallback);
|
|
62
|
+
// De-duplicate while preserving order.
|
|
63
|
+
return [...new Set(parts.filter(Boolean))].join(' ');
|
|
64
|
+
}
|
|
65
|
+
export function buildReadiness(plan) {
|
|
66
|
+
const status = statusFor(plan);
|
|
67
|
+
const supportedSteps = plan.steps.filter((s) => s.support !== 'unsupported').length;
|
|
68
|
+
const unsupportedSteps = plan.steps.filter((s) => s.support === 'unsupported').length;
|
|
69
|
+
return {
|
|
70
|
+
status,
|
|
71
|
+
headline: headlineFor(status, plan.backend),
|
|
72
|
+
agentMessage: agentMessageFor(plan, status),
|
|
73
|
+
developerMessage: plan.developerMessage,
|
|
74
|
+
backend: plan.backend,
|
|
75
|
+
supportedSteps,
|
|
76
|
+
unsupportedSteps,
|
|
77
|
+
blockers: plan.blockers,
|
|
78
|
+
warnings: plan.warnings,
|
|
79
|
+
fallbackUsed: fallbackUsed(plan),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export { PHRASE as READINESS_PHRASES };
|
|
83
|
+
//# sourceMappingURL=report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../../src/automation/report.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
// Automation Kernel V2 — Workstream 2: Selector IR V2. One normalized selector model shared by
|
|
2
|
+
// Flow V2, Maestro import/export, the Appium audit, and flow repair. Parses the existing Swipium
|
|
3
|
+
// selector string grammar, normalizes Android resource ids, scores risk/portability, preserves
|
|
4
|
+
// provenance, and refuses unsupported strategies per backend. NEVER generates XPath.
|
|
5
|
+
import { selectorSupported } from './capabilities.js';
|
|
6
|
+
import { isVisualStrategy } from './types.js';
|
|
7
|
+
const PLATFORM_FOR_STRATEGY = {
|
|
8
|
+
resource_id: 'android',
|
|
9
|
+
ios_predicate: 'ios',
|
|
10
|
+
ios_class_chain: 'ios',
|
|
11
|
+
};
|
|
12
|
+
const PORTABLE_STRATEGIES = ['accessibility_id', 'text', 'ocr_text', 'image'];
|
|
13
|
+
/** Normalize the many Android resource-id spellings to a bare id (last `/` segment). */
|
|
14
|
+
export function normalizeResourceId(value) {
|
|
15
|
+
const trimmed = value.trim();
|
|
16
|
+
const slash = trimmed.lastIndexOf('/');
|
|
17
|
+
return slash >= 0 ? trimmed.slice(slash + 1) : trimmed;
|
|
18
|
+
}
|
|
19
|
+
function riskFor(strategy, value, hints) {
|
|
20
|
+
switch (strategy) {
|
|
21
|
+
case 'accessibility_id':
|
|
22
|
+
case 'resource_id':
|
|
23
|
+
return 'low';
|
|
24
|
+
case 'ios_predicate':
|
|
25
|
+
case 'ios_class_chain':
|
|
26
|
+
return 'medium';
|
|
27
|
+
case 'text': {
|
|
28
|
+
// Plain text is CI-brittle (copy/localization). Stable structural hints lower the risk.
|
|
29
|
+
const hasStableHint = !!(hints?.boundsBucket || hints?.screenSignature || hints?.className);
|
|
30
|
+
return hasStableHint ? 'medium' : 'high';
|
|
31
|
+
}
|
|
32
|
+
case 'ocr_text':
|
|
33
|
+
case 'image':
|
|
34
|
+
return 'high';
|
|
35
|
+
case 'coordinate':
|
|
36
|
+
return 'high';
|
|
37
|
+
default:
|
|
38
|
+
return 'high';
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parse one Swipium selector string into Selector IR. Recognizes the existing grammar:
|
|
43
|
+
* `id=foo`, `id/foo`, `com.example:id/foo`, `accessibility id=foo`, `name=foo`,
|
|
44
|
+
* `predicate string=...`, `class chain=...`, and bare text.
|
|
45
|
+
* OCR / image selectors come from dedicated flow steps, not this string grammar — see selectorForVisual().
|
|
46
|
+
*/
|
|
47
|
+
export function parseSelector(raw, opts = {}) {
|
|
48
|
+
const source = opts.source ?? 'flow';
|
|
49
|
+
const hints = opts.hints;
|
|
50
|
+
const s = raw.trim();
|
|
51
|
+
const make = (strategy, value) => ({
|
|
52
|
+
strategy,
|
|
53
|
+
value,
|
|
54
|
+
platform: opts.platform ?? PLATFORM_FOR_STRATEGY[strategy] ?? 'cross_platform',
|
|
55
|
+
source,
|
|
56
|
+
hints,
|
|
57
|
+
risk: riskFor(strategy, value, hints),
|
|
58
|
+
portable: PORTABLE_STRATEGIES.includes(strategy),
|
|
59
|
+
});
|
|
60
|
+
let m;
|
|
61
|
+
if ((m = s.match(/^id\s*=\s*(.+)$/i)))
|
|
62
|
+
return make('resource_id', normalizeResourceId(m[1]));
|
|
63
|
+
if ((m = s.match(/^accessibility id\s*=\s*(.+)$/i)))
|
|
64
|
+
return make('accessibility_id', m[1].trim());
|
|
65
|
+
if ((m = s.match(/^name\s*=\s*(.+)$/i)))
|
|
66
|
+
return make('text', m[1].trim());
|
|
67
|
+
if ((m = s.match(/^predicate string\s*=\s*(.+)$/i)))
|
|
68
|
+
return make('ios_predicate', m[1].trim());
|
|
69
|
+
if ((m = s.match(/^class chain\s*=\s*(.+)$/i)))
|
|
70
|
+
return make('ios_class_chain', m[1].trim());
|
|
71
|
+
// `com.example:id/foo` or `id/foo` without an explicit `id=` prefix is still an Android resource id.
|
|
72
|
+
if (/^[\w.]*:id\//.test(s) || /^id\//.test(s))
|
|
73
|
+
return make('resource_id', normalizeResourceId(s));
|
|
74
|
+
return make('text', s);
|
|
75
|
+
}
|
|
76
|
+
/** Build a visual (OCR/image) Selector IR from a dedicated visual flow step. */
|
|
77
|
+
export function selectorForVisual(strategy, value, opts = {}) {
|
|
78
|
+
return {
|
|
79
|
+
strategy,
|
|
80
|
+
value,
|
|
81
|
+
platform: 'cross_platform',
|
|
82
|
+
source: opts.source ?? 'flow',
|
|
83
|
+
hints: opts.hints,
|
|
84
|
+
risk: 'high',
|
|
85
|
+
portable: true,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
/** A coordinate selector (tapAt) — always last-resort, non-portable, high risk. */
|
|
89
|
+
export function selectorForCoordinate(value, source = 'flow') {
|
|
90
|
+
return { strategy: 'coordinate', value, platform: 'cross_platform', source, risk: 'high', portable: false };
|
|
91
|
+
}
|
|
92
|
+
/** Refuse selectors a backend cannot honor (e.g. an iOS predicate on Android DirectDriver). */
|
|
93
|
+
export function checkSelectorBackend(ir, caps) {
|
|
94
|
+
if (selectorSupported(caps, ir.strategy))
|
|
95
|
+
return { supported: true };
|
|
96
|
+
return {
|
|
97
|
+
supported: false,
|
|
98
|
+
code: 'BACKEND_UNSUPPORTED',
|
|
99
|
+
detail: `${ir.strategy} selector is not supported on ${caps.backend}.`,
|
|
100
|
+
nextStep: nextStepForUnsupportedSelector(ir.strategy, caps),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function nextStepForUnsupportedSelector(strategy, caps) {
|
|
104
|
+
if (strategy === 'ios_predicate' || strategy === 'ios_class_chain') {
|
|
105
|
+
return 'Use an iOS WDA or Appium XCUITest backend, or replace it with an accessibility id.';
|
|
106
|
+
}
|
|
107
|
+
if ((strategy === 'accessibility_id' || strategy === 'resource_id' || strategy === 'text') && !caps.structuredTree) {
|
|
108
|
+
return 'Attach WDA or Appium for structured selectors, or rewrite the step as a visual/OCR check.';
|
|
109
|
+
}
|
|
110
|
+
return `Attach a backend that supports ${strategy}.`;
|
|
111
|
+
}
|
|
112
|
+
/** CI-readiness check: plain text without stable hints is high risk and flagged. */
|
|
113
|
+
export function checkSelectorCiRisk(ir) {
|
|
114
|
+
if (ir.strategy === 'text' && ir.risk === 'high') {
|
|
115
|
+
return {
|
|
116
|
+
risk: 'high',
|
|
117
|
+
code: 'HIGH_RISK_SELECTOR',
|
|
118
|
+
detail: 'Plain-text selector with no stable hints is brittle under copy/localization changes.',
|
|
119
|
+
nextStep: 'Pair it with a stable accessibility id / resource id, or add structural hints (boundsBucket, screenSignature).',
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
return { risk: ir.risk };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Resolve a (resource_id | accessibility_id) selector against parsed candidates. Duplicate matches
|
|
126
|
+
* are AMBIGUOUS_SELECTOR unless the IR's hints (boundsBucket / screenSignature) disambiguate to one.
|
|
127
|
+
*/
|
|
128
|
+
export function resolveSelector(ir, candidates) {
|
|
129
|
+
const key = (c) => ir.strategy === 'resource_id' ? (c.resourceId ? normalizeResourceId(c.resourceId) : undefined)
|
|
130
|
+
: ir.strategy === 'accessibility_id' ? c.accessibilityId
|
|
131
|
+
: ir.strategy === 'text' ? c.text
|
|
132
|
+
: undefined;
|
|
133
|
+
let matches = candidates.filter((c) => key(c) === ir.value);
|
|
134
|
+
if (matches.length === 0) {
|
|
135
|
+
return { ok: false, code: 'SELECTOR_NOT_FOUND', detail: `No element matches ${ir.strategy}=${ir.value}.`, matches: 0 };
|
|
136
|
+
}
|
|
137
|
+
if (matches.length === 1)
|
|
138
|
+
return { ok: true, match: matches[0] };
|
|
139
|
+
// Try to disambiguate by hints.
|
|
140
|
+
if (ir.hints?.boundsBucket) {
|
|
141
|
+
const narrowed = matches.filter((c) => c.boundsBucket === ir.hints.boundsBucket);
|
|
142
|
+
if (narrowed.length === 1)
|
|
143
|
+
return { ok: true, match: narrowed[0] };
|
|
144
|
+
if (narrowed.length)
|
|
145
|
+
matches = narrowed;
|
|
146
|
+
}
|
|
147
|
+
if (ir.hints?.screenSignature) {
|
|
148
|
+
const narrowed = matches.filter((c) => c.screenSignature === ir.hints.screenSignature);
|
|
149
|
+
if (narrowed.length === 1)
|
|
150
|
+
return { ok: true, match: narrowed[0] };
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
code: 'AMBIGUOUS_SELECTOR',
|
|
155
|
+
detail: `${matches.length} elements match ${ir.strategy}=${ir.value}; add a disambiguating hint (boundsBucket/screenSignature) or a unique testID.`,
|
|
156
|
+
matches: matches.length,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Export a Selector IR to an Appium native locator strategy. NEVER returns XPath — visual/coordinate
|
|
161
|
+
* strategies have no Appium native locator and return null (the caller must mark them manual_review).
|
|
162
|
+
*/
|
|
163
|
+
export function selectorToAppium(ir) {
|
|
164
|
+
switch (ir.strategy) {
|
|
165
|
+
case 'resource_id':
|
|
166
|
+
return { using: 'id', value: ir.value };
|
|
167
|
+
case 'accessibility_id':
|
|
168
|
+
return { using: 'accessibility id', value: ir.value };
|
|
169
|
+
case 'ios_predicate':
|
|
170
|
+
return { using: '-ios predicate string', value: ir.value };
|
|
171
|
+
case 'ios_class_chain':
|
|
172
|
+
return { using: '-ios class chain', value: ir.value };
|
|
173
|
+
case 'text':
|
|
174
|
+
// Prefer a UiAutomator native text matcher over XPath for Android.
|
|
175
|
+
return { using: '-android uiautomator', value: `new UiSelector().text("${ir.value.replace(/"/g, '\\"')}")` };
|
|
176
|
+
default:
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** Convert a Maestro selector block (string | { id|text|... }) to Selector IR without semantic loss. */
|
|
181
|
+
export function selectorFromMaestro(value, source = 'maestro_import') {
|
|
182
|
+
if (typeof value === 'string')
|
|
183
|
+
return parseSelector(value, { source });
|
|
184
|
+
if (!value || typeof value !== 'object')
|
|
185
|
+
return null;
|
|
186
|
+
const v = value;
|
|
187
|
+
if (typeof v.id === 'string')
|
|
188
|
+
return parseSelector(`id=${v.id}`, { source });
|
|
189
|
+
if (typeof v['accessibility id'] === 'string')
|
|
190
|
+
return parseSelector(`accessibility id=${v['accessibility id']}`, { source });
|
|
191
|
+
if (typeof v.label === 'string')
|
|
192
|
+
return parseSelector(`accessibility id=${v.label}`, { source });
|
|
193
|
+
if (typeof v.text === 'string')
|
|
194
|
+
return parseSelector(v.text, { source });
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
/** True when the strategy is a structured (non-visual) locator. */
|
|
198
|
+
export function isStructuredSelector(ir) {
|
|
199
|
+
return !isVisualStrategy(ir.strategy) && ir.strategy !== 'coordinate';
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=selectors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"selectors.js","sourceRoot":"","sources":["../../src/automation/selectors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Automation Kernel V2 — shared types (Developer 3 lane). A backend-neutral automation model that
|
|
2
|
+
// lets a Flow V2 file be compiled into a deterministic, capability-checked plan *before* a device
|
|
3
|
+
// is touched. Everything here is pure data: no I/O, no driver calls. The runner, the planning
|
|
4
|
+
// tools, Maestro interop, and the Appium audit all share these types so "the same flow means the
|
|
5
|
+
// same thing" regardless of backend.
|
|
6
|
+
//
|
|
7
|
+
// See SWIPIUM-DEVELOPER-3-AUTOMATION-KERNEL-V2-PLAN-2026-05-29.md (Workstreams 1-5, 9).
|
|
8
|
+
/** Visual selector strategies never claim structured-locator proof; they are candidate evidence only. */
|
|
9
|
+
export const VISUAL_STRATEGIES = ['ocr_text', 'image'];
|
|
10
|
+
export function isVisualStrategy(strategy) {
|
|
11
|
+
return VISUAL_STRATEGIES.includes(strategy);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/automation/types.ts"],"names":[],"mappings":"AAAA,kGAAkG;AAClG,kGAAkG;AAClG,8FAA8F;AAC9F,iGAAiG;AACjG,qCAAqC;AACrC,EAAE;AACF,wFAAwF;AA0CxF,yGAAyG;AACzG,MAAM,CAAC,MAAM,iBAAiB,GAAgC,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;AAEpF,MAAM,UAAU,gBAAgB,CAAC,QAA0B;IACzD,OAAO,iBAAiB,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;AAC9C,CAAC"}
|