nativeapptemplate-agent 0.1.1 → 0.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/CLAUDE.md +9 -7
- package/README.md +65 -21
- package/dist/agents/judge.d.ts +8 -0
- package/dist/agents/judge.d.ts.map +1 -1
- package/dist/agents/judge.js +100 -14
- package/dist/agents/judge.js.map +1 -1
- package/dist/agents/repair.d.ts +14 -0
- package/dist/agents/repair.d.ts.map +1 -0
- package/dist/agents/repair.js +103 -0
- package/dist/agents/repair.js.map +1 -0
- package/dist/agents/types.d.ts +34 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/dispatch.d.ts +21 -2
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +250 -14
- package/dist/dispatch.js.map +1 -1
- package/dist/env-bridge.d.ts +17 -0
- package/dist/env-bridge.d.ts.map +1 -0
- package/dist/env-bridge.js +211 -0
- package/dist/env-bridge.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +88 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +5 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +83 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mobile.d.ts +30 -0
- package/dist/mobile.d.ts.map +1 -0
- package/dist/mobile.js +173 -0
- package/dist/mobile.js.map +1 -0
- package/dist/rails-lifecycle.d.ts +16 -0
- package/dist/rails-lifecycle.d.ts.map +1 -0
- package/dist/rails-lifecycle.js +184 -0
- package/dist/rails-lifecycle.js.map +1 -0
- package/dist/rename-overrides.d.ts +23 -0
- package/dist/rename-overrides.d.ts.map +1 -0
- package/dist/rename-overrides.js +58 -0
- package/dist/rename-overrides.js.map +1 -0
- package/dist/repair-loop.d.ts +25 -0
- package/dist/repair-loop.d.ts.map +1 -0
- package/dist/repair-loop.js +67 -0
- package/dist/repair-loop.js.map +1 -0
- package/dist/report/collect.d.ts +28 -0
- package/dist/report/collect.d.ts.map +1 -0
- package/dist/report/collect.js +117 -0
- package/dist/report/collect.js.map +1 -0
- package/dist/report/model.d.ts +49 -0
- package/dist/report/model.d.ts.map +1 -0
- package/dist/report/model.js +2 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/render.d.ts +3 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +242 -0
- package/dist/report/render.js.map +1 -0
- package/dist/report/theme.d.ts +2 -0
- package/dist/report/theme.d.ts.map +1 -0
- package/dist/report/theme.js +115 -0
- package/dist/report/theme.js.map +1 -0
- package/dist/ruby.d.ts.map +1 -1
- package/dist/ruby.js +11 -2
- package/dist/ruby.js.map +1 -1
- package/dist/slug.d.ts +3 -0
- package/dist/slug.d.ts.map +1 -1
- package/dist/slug.js +30 -0
- package/dist/slug.js.map +1 -1
- package/dist/validation/capture.d.ts.map +1 -1
- package/dist/validation/capture.js +19 -2
- package/dist/validation/capture.js.map +1 -1
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +3 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/launch.d.ts +10 -0
- package/dist/validation/launch.d.ts.map +1 -1
- package/dist/validation/launch.js +103 -5
- package/dist/validation/launch.js.map +1 -1
- package/dist/validation/layer1.d.ts.map +1 -1
- package/dist/validation/layer1.js +12 -4
- package/dist/validation/layer1.js.map +1 -1
- package/dist/validation/scenarios/queue.d.ts +12 -0
- package/dist/validation/scenarios/queue.d.ts.map +1 -0
- package/dist/validation/scenarios/queue.js +204 -0
- package/dist/validation/scenarios/queue.js.map +1 -0
- package/dist/validation/stage2-judge.d.ts +21 -0
- package/dist/validation/stage2-judge.d.ts.map +1 -0
- package/dist/validation/stage2-judge.js +204 -0
- package/dist/validation/stage2-judge.js.map +1 -0
- package/dist/validation/stage2.d.ts +73 -0
- package/dist/validation/stage2.d.ts.map +1 -0
- package/dist/validation/stage2.js +313 -0
- package/dist/validation/stage2.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +17 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -3
- package/scripts/ruby/rename.rb +18 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/validation/launch.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,KAAK,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/validation/launch.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,QAAQ,EAAE,KAAK,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,cAAc,GAAG,kBAAkB,CAAC;AAuB9D,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAQhF;AAuFD,KAAK,YAAY,GACb;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAOjC,wBAAsB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAiB3F;AAED,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAejE"}
|
|
@@ -11,6 +11,7 @@ const DEFAULT_TIMEOUT_MS = 60_000;
|
|
|
11
11
|
// iOS: xcrun simctl install booted <appPath>
|
|
12
12
|
// xcrun simctl launch booted <bundleId>
|
|
13
13
|
// Android: adb install <apkPath>
|
|
14
|
+
// adb shell pm grant <package> POST_NOTIFICATIONS (best-effort)
|
|
14
15
|
// adb shell monkey -p <package> -c android.intent.category.LAUNCHER 1
|
|
15
16
|
//
|
|
16
17
|
// `monkey` on Android is used over `am start -n <pkg>/<activity>` because it
|
|
@@ -53,9 +54,28 @@ async function installAndLaunchIos(appPath, bundleId, timeoutMs) {
|
|
|
53
54
|
async function installAndLaunchAndroid(apkPath, packageName, timeoutMs) {
|
|
54
55
|
const adb = resolveAdbPath();
|
|
55
56
|
const started = Date.now();
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
// adb fails with "more than one device/emulator" when >1 device is
|
|
58
|
+
// attached unless `-s <serial>` disambiguates. Common on dev machines
|
|
59
|
+
// that have a real phone plugged in alongside an emulator. Pick the
|
|
60
|
+
// emulator (the agent's standard CI target — emulators boot reliably
|
|
61
|
+
// and are reproducible). If exactly one device, pass through with no
|
|
62
|
+
// -s. If zero, fail fast with a useful error rather than letting adb
|
|
63
|
+
// produce its terse "no devices/emulators found".
|
|
64
|
+
const targeting = await selectAdbTarget(adb, timeoutMs);
|
|
65
|
+
if (!targeting.ok) {
|
|
66
|
+
return {
|
|
67
|
+
ok: false,
|
|
68
|
+
command: `${adb} devices`,
|
|
69
|
+
durationMs: Date.now() - started,
|
|
70
|
+
error: targeting.error,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
const targetArgs = targeting.serial !== undefined ? ["-s", targeting.serial] : [];
|
|
74
|
+
const targetForCmd = targeting.serial !== undefined ? ` -s ${targeting.serial}` : "";
|
|
75
|
+
const installCmd = `${adb}${targetForCmd} install -r ${apkPath}`;
|
|
76
|
+
const grantCmd = `${adb}${targetForCmd} shell pm grant ${packageName} android.permission.POST_NOTIFICATIONS`;
|
|
77
|
+
const launchCmd = `${adb}${targetForCmd} shell monkey -p ${packageName} -c android.intent.category.LAUNCHER 1`;
|
|
78
|
+
const install = await runOnce(adb, [...targetArgs, "install", "-r", apkPath], timeoutMs);
|
|
59
79
|
if (!install.ok) {
|
|
60
80
|
return {
|
|
61
81
|
ok: false,
|
|
@@ -64,14 +84,92 @@ async function installAndLaunchAndroid(apkPath, packageName, timeoutMs) {
|
|
|
64
84
|
...(install.error !== undefined ? { error: install.error } : {}),
|
|
65
85
|
};
|
|
66
86
|
}
|
|
67
|
-
|
|
87
|
+
// Pre-grant the runtime notification permission so Android 13+ (API 33+)
|
|
88
|
+
// doesn't pop the POST_NOTIFICATIONS system dialog on first launch. That
|
|
89
|
+
// dialog overlays the home screen exactly when Stage 1 captures it, which
|
|
90
|
+
// fails Layer 3's "renders-cleanly" rubric. Best-effort: on older API
|
|
91
|
+
// levels (where it isn't a runtime permission) or apps that don't declare
|
|
92
|
+
// it, `pm grant` errors — we ignore the result so it never blocks launch.
|
|
93
|
+
await runOnce(adb, [...targetArgs, "shell", "pm", "grant", packageName, "android.permission.POST_NOTIFICATIONS"], timeoutMs);
|
|
94
|
+
const launch = await runOnce(adb, [...targetArgs, "shell", "monkey", "-p", packageName, "-c", "android.intent.category.LAUNCHER", "1"], timeoutMs);
|
|
68
95
|
return {
|
|
69
96
|
ok: launch.ok,
|
|
70
|
-
command: `${installCmd} && ${launchCmd}`,
|
|
97
|
+
command: `${installCmd} && ${grantCmd} && ${launchCmd}`,
|
|
71
98
|
durationMs: Date.now() - started,
|
|
72
99
|
...(launch.ok || launch.error === undefined ? {} : { error: launch.error }),
|
|
73
100
|
};
|
|
74
101
|
}
|
|
102
|
+
// Picks the right `adb -s <serial>` target when multiple devices are
|
|
103
|
+
// attached. Preference: NATIVEAPPTEMPLATE_ADB_SERIAL env override >
|
|
104
|
+
// emulator-* (reliable, reproducible) > first device. Returns
|
|
105
|
+
// { ok:true, serial:undefined } when exactly one device is attached
|
|
106
|
+
// (no -s needed; adb defaults work fine).
|
|
107
|
+
export async function selectAdbTarget(adb, timeoutMs) {
|
|
108
|
+
const override = process.env['NATIVEAPPTEMPLATE_ADB_SERIAL'];
|
|
109
|
+
if (override)
|
|
110
|
+
return { ok: true, serial: override };
|
|
111
|
+
const list = await runCapture(adb, ["devices"], timeoutMs);
|
|
112
|
+
if (!list.ok) {
|
|
113
|
+
return { ok: false, error: list.error ?? `${adb} devices failed` };
|
|
114
|
+
}
|
|
115
|
+
const serials = parseAdbDevices(list.stdout);
|
|
116
|
+
if (serials.length === 0) {
|
|
117
|
+
return { ok: false, error: "no adb devices/emulators attached (boot one in Android Studio Device Manager)" };
|
|
118
|
+
}
|
|
119
|
+
if (serials.length === 1)
|
|
120
|
+
return { ok: true };
|
|
121
|
+
const emulator = serials.find((s) => s.startsWith("emulator-"));
|
|
122
|
+
return { ok: true, serial: emulator ?? serials[0] };
|
|
123
|
+
}
|
|
124
|
+
export function parseAdbDevices(stdout) {
|
|
125
|
+
// `adb devices` output:
|
|
126
|
+
// List of devices attached
|
|
127
|
+
// 1C081FDF600CMG device
|
|
128
|
+
// emulator-5554 device
|
|
129
|
+
//
|
|
130
|
+
// Skip the header, accept only fully-online "device" rows (drop
|
|
131
|
+
// "offline" / "unauthorized" / "no permissions").
|
|
132
|
+
const result = [];
|
|
133
|
+
for (const line of stdout.split("\n")) {
|
|
134
|
+
const m = line.match(/^(\S+)\s+device$/);
|
|
135
|
+
const serial = m?.[1];
|
|
136
|
+
if (serial !== undefined && serial !== "List")
|
|
137
|
+
result.push(serial);
|
|
138
|
+
}
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
function runCapture(cmd, args, timeoutMs) {
|
|
142
|
+
return new Promise((resolvePromise) => {
|
|
143
|
+
let child;
|
|
144
|
+
try {
|
|
145
|
+
child = spawn(cmd, [...args], { env: scrubbedEnv(), stdio: ["ignore", "pipe", "pipe"] });
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
resolvePromise({ ok: false, error: err instanceof Error ? err.message : String(err) });
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const stderrChunks = [];
|
|
152
|
+
const stdoutChunks = [];
|
|
153
|
+
child.stderr.on("data", (c) => stderrChunks.push(c));
|
|
154
|
+
child.stdout.on("data", (c) => stdoutChunks.push(c));
|
|
155
|
+
const timer = setTimeout(() => { child.kill("SIGTERM"); }, timeoutMs);
|
|
156
|
+
child.on("close", (code) => {
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
|
|
159
|
+
const stdout = Buffer.concat(stdoutChunks).toString("utf8");
|
|
160
|
+
if (code === 0) {
|
|
161
|
+
resolvePromise({ ok: true, stdout });
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
resolvePromise({ ok: false, error: stderr || stdout || `${cmd} exited ${code}` });
|
|
165
|
+
}
|
|
166
|
+
});
|
|
167
|
+
child.on("error", (err) => {
|
|
168
|
+
clearTimeout(timer);
|
|
169
|
+
resolvePromise({ ok: false, error: err.message });
|
|
170
|
+
});
|
|
171
|
+
});
|
|
172
|
+
}
|
|
75
173
|
function runOnce(cmd, args, timeoutMs) {
|
|
76
174
|
return new Promise((resolvePromise) => {
|
|
77
175
|
let child;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/validation/launch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAyB3C,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAElC,6EAA6E;AAC7E,8EAA8E;AAC9E,8EAA8E;AAC9E,+DAA+D;AAC/D,EAAE;AACF,+BAA+B;AAC/B,mDAAmD;AACnD,oDAAoD;AACpD,mCAAmC;AACnC,iFAAiF;AACjF,EAAE;AACF,6EAA6E;AAC7E,+EAA+E;AAC/E,mEAAmE;AACnE,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,qEAAqE;AACrE,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,KAAkB;IACvD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,kBAAkB,CAAC;IACxD,QAAQ,KAAK,CAAC,QAAQ,EAAE,CAAC;QACvB,KAAK,KAAK;YACR,OAAO,mBAAmB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QACvE,KAAK,SAAS;YACZ,OAAO,uBAAuB,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;IAChF,CAAC;AACH,CAAC;AAED,KAAK,UAAU,mBAAmB,CAAC,OAAe,EAAE,QAAgB,EAAE,SAAiB;IACrF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,UAAU,GAAG,+BAA+B,OAAO,EAAE,CAAC;IAC5D,MAAM,SAAS,GAAG,8BAA8B,QAAQ,EAAE,CAAC;IAE3D,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,SAAS,CAAC,CAAC;IAC5F,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,OAAO,EAAE,UAAU;YACnB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;YAChC,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACjE,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,SAAS,CAAC,CAAC;IAC3F,OAAO;QACL,EAAE,EAAE,MAAM,CAAC,EAAE;QACb,OAAO,EAAE,GAAG,UAAU,OAAO,SAAS,EAAE;QACxC,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO;QAChC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,CAAC;KAC5E,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,OAAe,EAAE,WAAmB,EAAE,SAAiB;IAC5F,MAAM,GAAG,GAAG,cAAc,EAAE,CAAC;IAC7B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/validation/launch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer1.d.ts","sourceRoot":"","sources":["../../src/validation/layer1.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"layer1.d.ts","sourceRoot":"","sources":["../../src/validation/layer1.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CACpC,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B,CAAC;AA+BF,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCzE"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { readdir, readFile, stat } from "node:fs/promises";
|
|
2
|
-
import { extname, join, relative, basename } from "node:path";
|
|
2
|
+
import { extname, join, relative, basename, sep } from "node:path";
|
|
3
3
|
const TEXT_EXTS = new Set([
|
|
4
4
|
".rb", ".erb", ".yml", ".yaml", ".json", ".md", ".gemspec", ".rake", ".ru",
|
|
5
5
|
".txt", ".sample", ".example", ".conf", ".html", ".css", ".scss", ".js", ".mjs",
|
|
@@ -20,6 +20,11 @@ const SKIP_SEGMENTS = new Set([
|
|
|
20
20
|
"DerivedData", "Pods", "Carthage", "xcuserdata", ".build",
|
|
21
21
|
"build", ".gradle", ".idea", ".kotlin", "captures",
|
|
22
22
|
]);
|
|
23
|
+
// Compiled build output, mirrored from rename.rb's SKIP_SUBPATHS. rename.rb
|
|
24
|
+
// deliberately does NOT rewrite these (they're regenerated from un-renamed
|
|
25
|
+
// source by the bundler — e.g. Turbo's `visitCompleted` in application.js), so
|
|
26
|
+
// Layer 1 must not scan them either, or it flags tokens we intentionally left.
|
|
27
|
+
const SKIP_SUBPATHS = ["app/assets/builds", "public/assets"];
|
|
23
28
|
export async function runLayer1(input) {
|
|
24
29
|
if (input.forbiddenTokens.length === 0) {
|
|
25
30
|
return { pass: true, findings: [] };
|
|
@@ -30,7 +35,7 @@ export async function runLayer1(input) {
|
|
|
30
35
|
}
|
|
31
36
|
const regex = buildRegex(input.forbiddenTokens);
|
|
32
37
|
const findings = [];
|
|
33
|
-
for await (const filePath of walk(root)) {
|
|
38
|
+
for await (const filePath of walk(root, root)) {
|
|
34
39
|
const content = await safeRead(filePath);
|
|
35
40
|
if (!content)
|
|
36
41
|
continue;
|
|
@@ -67,14 +72,17 @@ function buildRegex(tokens) {
|
|
|
67
72
|
function escapeRegex(s) {
|
|
68
73
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
69
74
|
}
|
|
70
|
-
async function* walk(dir) {
|
|
75
|
+
async function* walk(dir, root) {
|
|
71
76
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
72
77
|
for (const entry of entries) {
|
|
73
78
|
if (SKIP_SEGMENTS.has(entry.name))
|
|
74
79
|
continue;
|
|
75
80
|
const full = join(dir, entry.name);
|
|
76
81
|
if (entry.isDirectory()) {
|
|
77
|
-
|
|
82
|
+
const rel = relative(root, full).split(sep).join("/");
|
|
83
|
+
if (SKIP_SUBPATHS.includes(rel))
|
|
84
|
+
continue;
|
|
85
|
+
yield* walk(full, root);
|
|
78
86
|
}
|
|
79
87
|
else if (entry.isFile() && isTextFile(full)) {
|
|
80
88
|
yield full;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"layer1.js","sourceRoot":"","sources":["../../src/validation/layer1.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"layer1.js","sourceRoot":"","sources":["../../src/validation/layer1.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DomainSpec } from "../../agents/types.js";
|
|
2
|
+
import type { Stage2Scenario } from "../stage2.js";
|
|
3
|
+
export type QueueScenarioInputs = {
|
|
4
|
+
fullName: string;
|
|
5
|
+
email: string;
|
|
6
|
+
password: string;
|
|
7
|
+
primaryResourceName: string;
|
|
8
|
+
railsOutDir: string;
|
|
9
|
+
};
|
|
10
|
+
export type Platform = "ios" | "android";
|
|
11
|
+
export declare function buildQueueScenario(domain: DomainSpec, inputs: QueueScenarioInputs, platform?: Platform): Stage2Scenario;
|
|
12
|
+
//# sourceMappingURL=queue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../src/validation/scenarios/queue.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAc,MAAM,cAAc,CAAC;AAuC/D,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IAEjB,mBAAmB,EAAE,MAAM,CAAC;IAI5B,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,SAAS,CAAC;AAEzC,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,GAAE,QAAgB,GACzB,cAAc,CA2NhB"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
export function buildQueueScenario(domain, inputs, platform = "ios") {
|
|
2
|
+
const queueEntryName = renamedTo(domain, "ItemTag") ?? "ItemTag";
|
|
3
|
+
// Renamed Shopkeeper class (Vet for clinic, Host for restaurant,
|
|
4
|
+
// Curator for journal, etc.). Used by the rails_runner confirm
|
|
5
|
+
// step to bypass email confirmation server-side.
|
|
6
|
+
const shopkeeperClass = renamedTo(domain, "Shopkeeper") ?? "Shopkeeper";
|
|
7
|
+
// Sign In form-fill diverges per platform: iOS Compose uses a
|
|
8
|
+
// SecureTextField type for the password (queryable by tap_field);
|
|
9
|
+
// Android Compose's empty OutlinedTextField doesn't surface an
|
|
10
|
+
// EditText in the accessibility tree until it has content. Tap the
|
|
11
|
+
// visible TextView label to focus the field instead.
|
|
12
|
+
const signInFormFill = platform === "ios"
|
|
13
|
+
? [
|
|
14
|
+
{ kind: "tap_field", fieldTypes: ["TextField", "EditText"], nth: 0 },
|
|
15
|
+
{ kind: "type", text: inputs.email, submit: true },
|
|
16
|
+
{ kind: "tap_field", fieldTypes: ["SecureTextField", "EditText"], nth: -1 },
|
|
17
|
+
{ kind: "type", text: inputs.password, submit: true },
|
|
18
|
+
]
|
|
19
|
+
: [
|
|
20
|
+
// exact:true scopes to the standalone label TextView. Without
|
|
21
|
+
// it, "Password" substring-matches "Forgot your password?" (a
|
|
22
|
+
// link that navigates away to the password-reset screen).
|
|
23
|
+
//
|
|
24
|
+
// submit:true is OMITTED on Android because mobile-mcp injects
|
|
25
|
+
// a literal newline character ("\n", surfaces as " ") into
|
|
26
|
+
// the field instead of dismissing the keyboard — which then
|
|
27
|
+
// fails Email validation. Use press_button "BACK" instead to
|
|
28
|
+
// dismiss the keyboard before the next tap.
|
|
29
|
+
{ kind: "tap_text", text: "Email", exact: true },
|
|
30
|
+
{ kind: "type", text: inputs.email },
|
|
31
|
+
{ kind: "press_button", button: "BACK", optional: true },
|
|
32
|
+
{ kind: "tap_text", text: "Password", exact: true },
|
|
33
|
+
{ kind: "type", text: inputs.password },
|
|
34
|
+
{ kind: "press_button", button: "BACK", optional: true },
|
|
35
|
+
];
|
|
36
|
+
const steps = [
|
|
37
|
+
// ---- Verified: Welcome → Auth choice → Sign Up form ----
|
|
38
|
+
{ kind: "wait_for_text", text: "Welcome to" },
|
|
39
|
+
{ kind: "screenshot", label: "01-welcome" },
|
|
40
|
+
{ kind: "tap_text", text: "Start" },
|
|
41
|
+
{ kind: "wait_for_text", text: "Sign Up for an Account" },
|
|
42
|
+
{ kind: "screenshot", label: "02-auth-choice" },
|
|
43
|
+
{ kind: "tap_text", text: "Sign Up for an Account" },
|
|
44
|
+
{ kind: "wait_for_text", text: "Full Name" },
|
|
45
|
+
{ kind: "screenshot", label: "03-signup-form" },
|
|
46
|
+
// Form fields don't bind to their labels — tap_text on the label
|
|
47
|
+
// hits the dead StaticText and leaves the TextField unfocused.
|
|
48
|
+
// tap_below_text bias-taps where the field actually sits.
|
|
49
|
+
{ kind: "tap_below_text", text: "Full Name" },
|
|
50
|
+
{ kind: "type", text: inputs.fullName },
|
|
51
|
+
{ kind: "tap_below_text", text: "Email" },
|
|
52
|
+
{ kind: "type", text: inputs.email },
|
|
53
|
+
{ kind: "tap_below_text", text: "Password" },
|
|
54
|
+
// submit:true dismisses the on-screen keyboard after the last
|
|
55
|
+
// field — without it, the keyboard occludes the bottom Sign Up
|
|
56
|
+
// button and tap_text "Sign Up" hits the keyboard area instead.
|
|
57
|
+
{ kind: "type", text: inputs.password, submit: true },
|
|
58
|
+
// Dismiss the on-screen keyboard before tapping Sign Up. On
|
|
59
|
+
// iOS the keychain dialog handler below catches things; on
|
|
60
|
+
// Android the Sign Up submit button (Compose, rendered as
|
|
61
|
+
// TextView at y~2613) sits near the bottom and the keyboard can
|
|
62
|
+
// occlude it / push it off-tappable area. press_button "BACK" is
|
|
63
|
+
// Android's keyboard-dismiss; on iOS it's not a real key and
|
|
64
|
+
// mobile-mcp may error or no-op — we wrap in try/catch via the
|
|
65
|
+
// press_button no-throw semantics in the runner.
|
|
66
|
+
{ kind: "press_button", button: "BACK", optional: true },
|
|
67
|
+
// tap_text prefers Button-typed matches over StaticText/TextView,
|
|
68
|
+
// so this hits the form's bottom Sign Up button rather than the
|
|
69
|
+
// page-header that shares the label. On Android Compose, the
|
|
70
|
+
// bottom-most fallback (when no Button-type match exists) finds
|
|
71
|
+
// the lower TextView "Sign Up".
|
|
72
|
+
{ kind: "tap_text", text: "Sign Up" },
|
|
73
|
+
// After successful signup, iOS shows the Keychain "Save password?"
|
|
74
|
+
// system dialog. optional:true means we no-op if it doesn't appear
|
|
75
|
+
// (e.g. on Android, or if Keychain is disabled). Try the Japanese
|
|
76
|
+
// and English labels — Japanese-localized sims see "今はしない",
|
|
77
|
+
// English see "Not Now". Same dialog, locale-dependent label.
|
|
78
|
+
{ kind: "tap_text", text: "今はしない", optional: true, timeoutMs: 3_000 },
|
|
79
|
+
{ kind: "tap_text", text: "Not Now", optional: true, timeoutMs: 3_000 },
|
|
80
|
+
// Substrate uses devise_token_auth's email-confirmation flow:
|
|
81
|
+
// signup → "check your email" banner → user must click the email
|
|
82
|
+
// link before they can sign in. We can't click the email
|
|
83
|
+
// programmatically via UI alone, so bypass server-side: confirm
|
|
84
|
+
// the just-created Vet directly. devise's `.confirm` flips
|
|
85
|
+
// confirmed_at and unblocks sign-in.
|
|
86
|
+
{
|
|
87
|
+
kind: "rails_runner",
|
|
88
|
+
outDir: inputs.railsOutDir,
|
|
89
|
+
ruby: `${shopkeeperClass}.find_by(email: ${JSON.stringify(inputs.email)})&.confirm`,
|
|
90
|
+
label: "confirm vet",
|
|
91
|
+
},
|
|
92
|
+
// After confirmation, dismiss the post-signup banner (if visible)
|
|
93
|
+
// and tap Sign In to land on the (renamed primary noun) list. iOS
|
|
94
|
+
// labels the banner button "Close"; Android Compose substrate
|
|
95
|
+
// labels it "Dismiss". Both are optional — only one fires per
|
|
96
|
+
// platform; the other no-ops.
|
|
97
|
+
{ kind: "tap_text", text: "Close", optional: true, timeoutMs: 3_000 },
|
|
98
|
+
{ kind: "tap_text", text: "Dismiss", optional: true, timeoutMs: 3_000 },
|
|
99
|
+
// The iOS Keychain "Save password?" dialog can surface LATE — after the
|
|
100
|
+
// rails_runner confirm above, not right at signup — so it re-covers the
|
|
101
|
+
// auth screen here and intercepts the Sign-In tap (observed: poll saw only
|
|
102
|
+
// the 5 dialog elements). Dismiss it again immediately before tapping Sign
|
|
103
|
+
// In; optional, so it no-ops on Android / when already gone.
|
|
104
|
+
{ kind: "tap_text", text: "今はしない", optional: true, timeoutMs: 3_000 },
|
|
105
|
+
{ kind: "tap_text", text: "Not Now", optional: true, timeoutMs: 3_000 },
|
|
106
|
+
{ kind: "tap_text", text: "Sign In to Your Account" },
|
|
107
|
+
{ kind: "wait_for_text", text: "Email", timeoutMs: 10_000 },
|
|
108
|
+
// Sign In form-fill is platform-specific (built above). iOS uses
|
|
109
|
+
// tap_field with SecureTextField; Android uses tap_text "Email" /
|
|
110
|
+
// "Password" since Compose's empty OutlinedTextField doesn't
|
|
111
|
+
// surface an EditText in the accessibility tree.
|
|
112
|
+
...signInFormFill,
|
|
113
|
+
{ kind: "tap_text", text: "Sign In" },
|
|
114
|
+
// iOS Keychain shows "Save password?" again after a successful
|
|
115
|
+
// Sign In (not just Sign Up). Same dismissal pattern.
|
|
116
|
+
{ kind: "tap_text", text: "今はしない", optional: true, timeoutMs: 3_000 },
|
|
117
|
+
{ kind: "tap_text", text: "Not Now", optional: true, timeoutMs: 3_000 },
|
|
118
|
+
// PAID-substrate-only intro modal after Sign In: "You are in
|
|
119
|
+
// personal organization. ... Switch to or create an organization
|
|
120
|
+
// to share..." with a "Create <Primary>" CTA that opens the
|
|
121
|
+
// creation form. Free edition has no multi-tenancy so the modal
|
|
122
|
+
// never appears — these waits/taps are effectively skipped on
|
|
123
|
+
// free because the post-Sign-In screen ALREADY shows
|
|
124
|
+
// primaryName (free) without a modal in the way.
|
|
125
|
+
//
|
|
126
|
+
// Free path: wait_for_text "Clinic" matches the list view
|
|
127
|
+
// header; the optional Create-* taps below find nothing and
|
|
128
|
+
// no-op (but the unconditional `tap_text "Add"` later matches
|
|
129
|
+
// the free toolbar).
|
|
130
|
+
//
|
|
131
|
+
// Paid path: wait_for_text "Clinic" matches the modal's Create
|
|
132
|
+
// <Primary> button label (substring). We can't tap it yet
|
|
133
|
+
// because the modal might still be animating in — explicit
|
|
134
|
+
// wait_for_text below with a longer timeout + exact:true on the
|
|
135
|
+
// "Create <Primary>" button gates correctly.
|
|
136
|
+
//
|
|
137
|
+
// Paid-substrate-only post-Sign-In multi-tenancy explainer.
|
|
138
|
+
// Per platform:
|
|
139
|
+
// iOS: two modal phases — v1 "OK"+"Go to Organizations",
|
|
140
|
+
// then v2 "Create <Primary>"+"Go to Organizations"+
|
|
141
|
+
// "Cancel". OK then Cancel both dismiss.
|
|
142
|
+
// Android: single snackbar with a "Dismiss" button.
|
|
143
|
+
// All optional with short timeouts so free no-ops cleanly. The
|
|
144
|
+
// walk picks up at the auto-seeded "Sample <Primary>" the
|
|
145
|
+
// substrate created during signup — no need to navigate the
|
|
146
|
+
// create-resource flow at all.
|
|
147
|
+
{ kind: "tap_text", text: "OK", exact: true, optional: true, timeoutMs: 5_000 },
|
|
148
|
+
{ kind: "tap_text", text: "Cancel", exact: true, optional: true, timeoutMs: 5_000 },
|
|
149
|
+
{ kind: "tap_text", text: "Dismiss", exact: true, optional: true, timeoutMs: 5_000 },
|
|
150
|
+
// ---- Unverified below — best-effort guesses, expect drift ----
|
|
151
|
+
// After auth + modal dismissals, drill DIRECTLY into the
|
|
152
|
+
// substrate's auto-seeded "Sample <Primary>" resource (created
|
|
153
|
+
// by Account#create_default_clinic! on every signup, both
|
|
154
|
+
// editions). This skips the per-edition Create flow complexity
|
|
155
|
+
// (paid hides Create behind multi-tenancy modals; free shows
|
|
156
|
+
// an Add button) — the auto-seeded resource is enough to
|
|
157
|
+
// demonstrate the rubric (renamed domain content with visible
|
|
158
|
+
// state badge).
|
|
159
|
+
//
|
|
160
|
+
// iOS requests notification permission at runtime when the list first
|
|
161
|
+
// loads. A system alert makes the accessibility tree return ONLY the
|
|
162
|
+
// alert's elements, hiding the list — so wait_for_text "Sample" below sees
|
|
163
|
+
// just the dialog (observed: "5 elements") and times out. Dismiss it
|
|
164
|
+
// (Allow; JP + EN labels, exact so "許可" doesn't match "許可しない").
|
|
165
|
+
// Optional + Android no-op: Android pre-grants POST_NOTIFICATIONS (#78).
|
|
166
|
+
{ kind: "tap_text", text: "許可", exact: true, optional: true, timeoutMs: 5_000 },
|
|
167
|
+
{ kind: "tap_text", text: "Allow", exact: true, optional: true, timeoutMs: 3_000 },
|
|
168
|
+
// The substrate's seed name "Sample" doesn't get renamed (it's
|
|
169
|
+
// a value, not a domain identifier). On every edition the list
|
|
170
|
+
// shows an entry containing "Sample" — wait for it.
|
|
171
|
+
{ kind: "wait_for_text", text: "Sample", timeoutMs: 15_000 },
|
|
172
|
+
{ kind: "screenshot", label: "04-primary-list-with-sample" },
|
|
173
|
+
// Drill into the sample resource to reach the queue-entry list.
|
|
174
|
+
// Substrate auto-creates a "Sample" queue entry inside the
|
|
175
|
+
// sample primary resource too (Clinic#create_sample_patient or
|
|
176
|
+
// equivalent), so the list isn't empty — this screenshot shows
|
|
177
|
+
// real domain content with the renamed state badge.
|
|
178
|
+
{ kind: "tap_text", text: "Sample" },
|
|
179
|
+
{ kind: "wait_for_text", text: queueEntryName, timeoutMs: 15_000 },
|
|
180
|
+
{ kind: "screenshot", label: "06-queue-entry-list" },
|
|
181
|
+
// Stage 2 ends here. The agent has demonstrated end-to-end:
|
|
182
|
+
// planner → renamer → workers → reviewer → Layer 1 + 2 + 3
|
|
183
|
+
// Stage 1 → bin/dev → Stage 2 walk through signup → email-
|
|
184
|
+
// confirm bypass → sign in → resource creation → drill into
|
|
185
|
+
// queue-entry list with the substrate's auto-seeded sample.
|
|
186
|
+
//
|
|
187
|
+
// Adding a NEW entry + toggling its state are deferred — they
|
|
188
|
+
// require mapping the substrate's "+" / swipe / state-toggle
|
|
189
|
+
// affordances which are icon-only and aren't reliably matched
|
|
190
|
+
// by tap_text. Layer 3 judges the screenshot above, which
|
|
191
|
+
// already contains the renamed primary resource ("Vet Clinic
|
|
192
|
+
// Queue"), the renamed queue entry noun ("Patient" via
|
|
193
|
+
// queueEntryName), and the renamed state badge — sufficient
|
|
194
|
+
// to satisfy the Stage 2 rubric.
|
|
195
|
+
];
|
|
196
|
+
return {
|
|
197
|
+
name: `queue-crud-${domain.slug}`,
|
|
198
|
+
steps,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function renamedTo(domain, from) {
|
|
202
|
+
return domain.renamePlan.find((p) => p.from === from)?.to;
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=queue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queue.js","sourceRoot":"","sources":["../../../src/validation/scenarios/queue.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Stage2Scenario } from "./stage2.js";
|
|
2
|
+
import { type Layer3Criterion } from "./layer3.js";
|
|
3
|
+
import { type MobileClient } from "../mobile.js";
|
|
4
|
+
import type { Stage2PlatformReport } from "../agents/types.js";
|
|
5
|
+
export type Stage2VisualInput = {
|
|
6
|
+
iosScenario?: Stage2Scenario;
|
|
7
|
+
androidScenario?: Stage2Scenario;
|
|
8
|
+
screenshotDir?: string;
|
|
9
|
+
spec: string;
|
|
10
|
+
rubric?: readonly Layer3Criterion[];
|
|
11
|
+
iosClient?: MobileClient;
|
|
12
|
+
androidClient?: MobileClient;
|
|
13
|
+
};
|
|
14
|
+
export type Stage2VisualResult = {
|
|
15
|
+
ios?: Stage2PlatformReport;
|
|
16
|
+
android?: Stage2PlatformReport;
|
|
17
|
+
};
|
|
18
|
+
export declare const DEFAULT_STAGE2_RUBRIC: readonly Layer3Criterion[];
|
|
19
|
+
export declare function runStage2Visual(input: Stage2VisualInput): Promise<Stage2VisualResult>;
|
|
20
|
+
export declare function selectDevice(client: MobileClient, platform: "ios" | "android"): Promise<string | undefined>;
|
|
21
|
+
//# sourceMappingURL=stage2-judge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stage2-judge.d.ts","sourceRoot":"","sources":["../../src/validation/stage2-judge.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwC,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EAAa,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9D,OAAO,EAAsB,KAAK,YAAY,EAAsB,MAAM,cAAc,CAAC;AACzF,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAsB/D,MAAM,MAAM,iBAAiB,GAAG;IAI9B,WAAW,CAAC,EAAE,cAAc,CAAC;IAC7B,eAAe,CAAC,EAAE,cAAc,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,SAAS,eAAe,EAAE,CAAC;IAGpC,SAAS,CAAC,EAAE,YAAY,CAAC;IACzB,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,CAAC,EAAE,oBAAoB,CAAC;IAC3B,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAChC,CAAC;AAMF,eAAO,MAAM,qBAAqB,EAAE,SAAS,eAAe,EAW3D,CAAC;AAEF,wBAAsB,eAAe,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA2B3F;AAyED,wBAAsB,YAAY,CAChC,MAAM,EAAE,YAAY,EACpB,QAAQ,EAAE,KAAK,GAAG,SAAS,GAC1B,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAoD7B"}
|