nativeapptemplate-agent 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 (106) hide show
  1. package/CLAUDE.md +137 -0
  2. package/LICENSE +21 -0
  3. package/README.md +192 -0
  4. package/dist/adb.d.ts +2 -0
  5. package/dist/adb.d.ts.map +1 -0
  6. package/dist/adb.js +31 -0
  7. package/dist/adb.js.map +1 -0
  8. package/dist/agents/contract-extract.d.ts +26 -0
  9. package/dist/agents/contract-extract.d.ts.map +1 -0
  10. package/dist/agents/contract-extract.js +205 -0
  11. package/dist/agents/contract-extract.js.map +1 -0
  12. package/dist/agents/judge.d.ts +21 -0
  13. package/dist/agents/judge.d.ts.map +1 -0
  14. package/dist/agents/judge.js +119 -0
  15. package/dist/agents/judge.js.map +1 -0
  16. package/dist/agents/planner.d.ts +3 -0
  17. package/dist/agents/planner.d.ts.map +1 -0
  18. package/dist/agents/planner.js +154 -0
  19. package/dist/agents/planner.js.map +1 -0
  20. package/dist/agents/reviewer.d.ts +9 -0
  21. package/dist/agents/reviewer.d.ts.map +1 -0
  22. package/dist/agents/reviewer.js +108 -0
  23. package/dist/agents/reviewer.js.map +1 -0
  24. package/dist/agents/types.d.ts +54 -0
  25. package/dist/agents/types.d.ts.map +1 -0
  26. package/dist/agents/types.js +2 -0
  27. package/dist/agents/types.js.map +1 -0
  28. package/dist/agents/workers/android.d.ts +3 -0
  29. package/dist/agents/workers/android.d.ts.map +1 -0
  30. package/dist/agents/workers/android.js +116 -0
  31. package/dist/agents/workers/android.js.map +1 -0
  32. package/dist/agents/workers/ios.d.ts +3 -0
  33. package/dist/agents/workers/ios.d.ts.map +1 -0
  34. package/dist/agents/workers/ios.js +110 -0
  35. package/dist/agents/workers/ios.js.map +1 -0
  36. package/dist/agents/workers/rails.d.ts +3 -0
  37. package/dist/agents/workers/rails.d.ts.map +1 -0
  38. package/dist/agents/workers/rails.js +145 -0
  39. package/dist/agents/workers/rails.js.map +1 -0
  40. package/dist/dispatch.d.ts +3 -0
  41. package/dist/dispatch.d.ts.map +1 -0
  42. package/dist/dispatch.js +38 -0
  43. package/dist/dispatch.js.map +1 -0
  44. package/dist/env.d.ts +3 -0
  45. package/dist/env.d.ts.map +1 -0
  46. package/dist/env.js +48 -0
  47. package/dist/env.js.map +1 -0
  48. package/dist/index.d.ts +3 -0
  49. package/dist/index.d.ts.map +1 -0
  50. package/dist/index.js +26 -0
  51. package/dist/index.js.map +1 -0
  52. package/dist/ruby.d.ts +2 -0
  53. package/dist/ruby.d.ts.map +1 -0
  54. package/dist/ruby.js +21 -0
  55. package/dist/ruby.js.map +1 -0
  56. package/dist/slug.d.ts +3 -0
  57. package/dist/slug.d.ts.map +1 -0
  58. package/dist/slug.js +11 -0
  59. package/dist/slug.js.map +1 -0
  60. package/dist/stub.d.ts +3 -0
  61. package/dist/stub.d.ts.map +1 -0
  62. package/dist/stub.js +6 -0
  63. package/dist/stub.js.map +1 -0
  64. package/dist/trace.d.ts +3 -0
  65. package/dist/trace.d.ts.map +1 -0
  66. package/dist/trace.js +13 -0
  67. package/dist/trace.js.map +1 -0
  68. package/dist/validation/capture.d.ts +15 -0
  69. package/dist/validation/capture.d.ts.map +1 -0
  70. package/dist/validation/capture.js +141 -0
  71. package/dist/validation/capture.js.map +1 -0
  72. package/dist/validation/discover.d.ts +11 -0
  73. package/dist/validation/discover.d.ts.map +1 -0
  74. package/dist/validation/discover.js +113 -0
  75. package/dist/validation/discover.js.map +1 -0
  76. package/dist/validation/index.d.ts +17 -0
  77. package/dist/validation/index.d.ts.map +1 -0
  78. package/dist/validation/index.js +9 -0
  79. package/dist/validation/index.js.map +1 -0
  80. package/dist/validation/launch.d.ts +21 -0
  81. package/dist/validation/launch.d.ts.map +1 -0
  82. package/dist/validation/launch.js +109 -0
  83. package/dist/validation/launch.js.map +1 -0
  84. package/dist/validation/layer1.d.ts +16 -0
  85. package/dist/validation/layer1.d.ts.map +1 -0
  86. package/dist/validation/layer1.js +98 -0
  87. package/dist/validation/layer1.js.map +1 -0
  88. package/dist/validation/layer2.d.ts +17 -0
  89. package/dist/validation/layer2.d.ts.map +1 -0
  90. package/dist/validation/layer2.js +168 -0
  91. package/dist/validation/layer2.js.map +1 -0
  92. package/dist/validation/layer3.d.ts +22 -0
  93. package/dist/validation/layer3.d.ts.map +1 -0
  94. package/dist/validation/layer3.js +96 -0
  95. package/dist/validation/layer3.js.map +1 -0
  96. package/dist/validation/stage1.d.ts +17 -0
  97. package/dist/validation/stage1.d.ts.map +1 -0
  98. package/dist/validation/stage1.js +71 -0
  99. package/dist/validation/stage1.js.map +1 -0
  100. package/dist/validation/visual-judge.d.ts +25 -0
  101. package/dist/validation/visual-judge.d.ts.map +1 -0
  102. package/dist/validation/visual-judge.js +89 -0
  103. package/dist/validation/visual-judge.js.map +1 -0
  104. package/package.json +69 -0
  105. package/scripts/ruby/.gitkeep +0 -0
  106. package/scripts/ruby/rename.rb +221 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.js","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,KAAK,CAAC,MAAM,CAAC;SACb,MAAM,CAAC,OAAO,CAAC;SACf,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACjC,CAAC"}
package/dist/stub.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ import type { AgentName } from "./agents/types.js";
2
+ export declare function isStub(agent: AgentName): boolean;
3
+ //# sourceMappingURL=stub.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stub.d.ts","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAEnD,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAGhD"}
package/dist/stub.js ADDED
@@ -0,0 +1,6 @@
1
+ export function isStub(agent) {
2
+ if (process.env['NATIVEAPPTEMPLATE_STUB_ALL'] === "1")
3
+ return true;
4
+ return process.env[`NATIVEAPPTEMPLATE_STUB_${agent.toUpperCase()}`] === "1";
5
+ }
6
+ //# sourceMappingURL=stub.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stub.js","sourceRoot":"","sources":["../src/stub.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,MAAM,CAAC,KAAgB;IACrC,IAAI,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,GAAG;QAAE,OAAO,IAAI,CAAC;IACnE,OAAO,OAAO,CAAC,GAAG,CAAC,0BAA0B,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC;AAC9E,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AgentName } from "./agents/types.js";
2
+ export declare function trace(agent: AgentName, text: string): void;
3
+ //# sourceMappingURL=trace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.d.ts","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAKnD,wBAAgB,KAAK,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAO1D"}
package/dist/trace.js ADDED
@@ -0,0 +1,13 @@
1
+ import { appendFileSync, mkdirSync } from "node:fs";
2
+ import { resolve } from "node:path";
3
+ const traceDir = resolve(process.cwd(), "tmp/trace");
4
+ let dirEnsured = false;
5
+ export function trace(agent, text) {
6
+ if (!dirEnsured) {
7
+ mkdirSync(traceDir, { recursive: true });
8
+ dirEnsured = true;
9
+ }
10
+ const ts = new Date().toISOString().slice(11, 19);
11
+ appendFileSync(resolve(traceDir, `${agent}.log`), `[${ts}] ${text}\n`);
12
+ }
13
+ //# sourceMappingURL=trace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"trace.js","sourceRoot":"","sources":["../src/trace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;AACrD,IAAI,UAAU,GAAG,KAAK,CAAC;AAEvB,MAAM,UAAU,KAAK,CAAC,KAAgB,EAAE,IAAY;IAClD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACzC,UAAU,GAAG,IAAI,CAAC;IACpB,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;IAClD,cAAc,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,KAAK,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,CAAC;AACzE,CAAC"}
@@ -0,0 +1,15 @@
1
+ export type CapturePlatform = "ios" | "android";
2
+ export type CaptureResult = {
3
+ ok: boolean;
4
+ path: string;
5
+ command: string;
6
+ durationMs: number;
7
+ error?: string;
8
+ };
9
+ export type CaptureInput = {
10
+ platform: CapturePlatform;
11
+ outPath: string;
12
+ timeoutMs?: number;
13
+ };
14
+ export declare function captureScreenshot(input: CaptureInput): Promise<CaptureResult>;
15
+ //# sourceMappingURL=capture.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.d.ts","sourceRoot":"","sources":["../../src/validation/capture.ts"],"names":[],"mappings":"AAOA,MAAM,MAAM,eAAe,GAAG,KAAK,GAAG,SAAS,CAAC;AAEhD,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAaF,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC,CAUnF"}
@@ -0,0 +1,141 @@
1
+ import { spawn } from "node:child_process";
2
+ import { createWriteStream } from "node:fs";
3
+ import { mkdir } from "node:fs/promises";
4
+ import { dirname } from "node:path";
5
+ import { scrubbedEnv } from "../env.js";
6
+ import { resolveAdbPath } from "../adb.js";
7
+ const DEFAULT_TIMEOUT_MS = 15_000;
8
+ // Capture the home screen of whatever's currently booted on the iOS Simulator
9
+ // or Android emulator. The agent does NOT boot the sim/emulator itself —
10
+ // that's a developer-environment concern (per memory: user runs Android Studio
11
+ // Device Manager for AVDs; iOS Simulator started via Xcode). This function
12
+ // assumes one is already running and the target app is on its home screen.
13
+ //
14
+ // Install + launch + screen-readiness polling are separate concerns; they'll
15
+ // land in follow-up PRs that wire post-Layer-2-build → install → launch →
16
+ // captureScreenshot → runLayer3 together.
17
+ export async function captureScreenshot(input) {
18
+ const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
19
+ await mkdir(dirname(input.outPath), { recursive: true });
20
+ switch (input.platform) {
21
+ case "ios":
22
+ return captureIos(input.outPath, timeoutMs);
23
+ case "android":
24
+ return captureAndroid(input.outPath, timeoutMs);
25
+ }
26
+ }
27
+ async function captureIos(outPath, timeoutMs) {
28
+ const command = `xcrun simctl io booted screenshot ${outPath}`;
29
+ const started = Date.now();
30
+ return new Promise((resolvePromise) => {
31
+ let child;
32
+ try {
33
+ child = spawn("xcrun", ["simctl", "io", "booted", "screenshot", outPath], {
34
+ env: scrubbedEnv(),
35
+ stdio: ["ignore", "pipe", "pipe"],
36
+ });
37
+ }
38
+ catch (err) {
39
+ resolvePromise({
40
+ ok: false,
41
+ path: outPath,
42
+ command,
43
+ durationMs: Date.now() - started,
44
+ error: err instanceof Error ? err.message : String(err),
45
+ });
46
+ return;
47
+ }
48
+ const stderrChunks = [];
49
+ child.stderr.on("data", (c) => stderrChunks.push(c));
50
+ const timer = setTimeout(() => { child.kill("SIGTERM"); }, timeoutMs);
51
+ child.on("close", (code) => {
52
+ clearTimeout(timer);
53
+ const durationMs = Date.now() - started;
54
+ const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
55
+ if (code === 0) {
56
+ resolvePromise({ ok: true, path: outPath, command, durationMs });
57
+ }
58
+ else {
59
+ resolvePromise({
60
+ ok: false,
61
+ path: outPath,
62
+ command,
63
+ durationMs,
64
+ error: stderr || `xcrun simctl exited ${code}`,
65
+ });
66
+ }
67
+ });
68
+ child.on("error", (err) => {
69
+ clearTimeout(timer);
70
+ resolvePromise({
71
+ ok: false,
72
+ path: outPath,
73
+ command,
74
+ durationMs: Date.now() - started,
75
+ error: err.message,
76
+ });
77
+ });
78
+ });
79
+ }
80
+ async function captureAndroid(outPath, timeoutMs) {
81
+ const adb = resolveAdbPath();
82
+ const command = `${adb} exec-out screencap -p > ${outPath}`;
83
+ const started = Date.now();
84
+ return new Promise((resolvePromise) => {
85
+ let child;
86
+ try {
87
+ child = spawn(adb, ["exec-out", "screencap", "-p"], {
88
+ env: scrubbedEnv(),
89
+ stdio: ["ignore", "pipe", "pipe"],
90
+ });
91
+ }
92
+ catch (err) {
93
+ resolvePromise({
94
+ ok: false,
95
+ path: outPath,
96
+ command,
97
+ durationMs: Date.now() - started,
98
+ error: err instanceof Error ? err.message : String(err),
99
+ });
100
+ return;
101
+ }
102
+ const out = createWriteStream(outPath);
103
+ let pipeError = null;
104
+ out.on("error", (err) => { pipeError = err; });
105
+ child.stdout.pipe(out);
106
+ const stderrChunks = [];
107
+ child.stderr.on("data", (c) => stderrChunks.push(c));
108
+ const timer = setTimeout(() => { child.kill("SIGTERM"); }, timeoutMs);
109
+ child.on("close", (code) => {
110
+ clearTimeout(timer);
111
+ out.end(() => {
112
+ const durationMs = Date.now() - started;
113
+ const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
114
+ if (code === 0 && !pipeError) {
115
+ resolvePromise({ ok: true, path: outPath, command, durationMs });
116
+ }
117
+ else {
118
+ resolvePromise({
119
+ ok: false,
120
+ path: outPath,
121
+ command,
122
+ durationMs,
123
+ error: pipeError?.message ?? stderr ?? `adb exited ${code}`,
124
+ });
125
+ }
126
+ });
127
+ });
128
+ child.on("error", (err) => {
129
+ clearTimeout(timer);
130
+ out.end();
131
+ resolvePromise({
132
+ ok: false,
133
+ path: outPath,
134
+ command,
135
+ durationMs: Date.now() - started,
136
+ error: err.message,
137
+ });
138
+ });
139
+ });
140
+ }
141
+ //# sourceMappingURL=capture.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture.js","sourceRoot":"","sources":["../../src/validation/capture.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export type IosArtifact = {
2
+ appPath: string;
3
+ bundleId: string;
4
+ };
5
+ export type AndroidArtifact = {
6
+ apkPath: string;
7
+ packageName: string;
8
+ };
9
+ export declare function discoverIosArtifact(iosDir: string): Promise<IosArtifact | null>;
10
+ export declare function discoverAndroidArtifact(androidDir: string): Promise<AndroidArtifact | null>;
11
+ //# sourceMappingURL=discover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/validation/discover.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAChE,MAAM,MAAM,eAAe,GAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAWvE,wBAAsB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAoBrF;AAKD,wBAAsB,uBAAuB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAgBjG"}
@@ -0,0 +1,113 @@
1
+ import { spawn } from "node:child_process";
2
+ import { readFile, readdir, stat } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { scrubbedEnv } from "../env.js";
5
+ // Matches Layer 2 build mode's IOS_DESTINATION so showBuildSettings sees the
6
+ // same SDK/configuration that `xcodebuild build` produced.
7
+ const IOS_DESTINATION = "platform=iOS Simulator,name=iPhone 17,OS=26.2";
8
+ // After Layer 2 build mode has built the iOS .app, ask xcodebuild where it
9
+ // landed and read the bundle identifier from the built Info.plist (so any
10
+ // $(VAR) interpolations are already resolved). Returns null if the build
11
+ // hasn't happened, the project layout doesn't match expectations, or the
12
+ // build settings query fails.
13
+ export async function discoverIosArtifact(iosDir) {
14
+ const entries = await readdir(iosDir).catch(() => []);
15
+ const xcodeproj = entries.find((e) => e.endsWith(".xcodeproj"));
16
+ if (!xcodeproj)
17
+ return null;
18
+ const scheme = xcodeproj.replace(/\.xcodeproj$/, "");
19
+ const settings = await runShowBuildSettings(iosDir, xcodeproj, scheme);
20
+ if (!settings)
21
+ return null;
22
+ const builtProductsDir = settings["BUILT_PRODUCTS_DIR"];
23
+ const wrapperName = settings["WRAPPER_NAME"];
24
+ if (!builtProductsDir || !wrapperName)
25
+ return null;
26
+ const appPath = join(builtProductsDir, wrapperName);
27
+ const appExists = await stat(appPath).then(() => true).catch(() => false);
28
+ if (!appExists)
29
+ return null;
30
+ const bundleId = await readBundleId(join(appPath, "Info.plist"));
31
+ if (!bundleId)
32
+ return null;
33
+ return { appPath, bundleId };
34
+ }
35
+ // Android `applicationId` lives in `app/build.gradle.kts`; the APK path is
36
+ // predictable. Returns null if the build hasn't happened or the gradle file
37
+ // doesn't have an `applicationId = "..."` line.
38
+ export async function discoverAndroidArtifact(androidDir) {
39
+ const apkPath = join(androidDir, "app", "build", "outputs", "apk", "debug", "app-debug.apk");
40
+ const apkExists = await stat(apkPath).then(() => true).catch(() => false);
41
+ if (!apkExists)
42
+ return null;
43
+ const gradlePath = join(androidDir, "app", "build.gradle.kts");
44
+ let gradle;
45
+ try {
46
+ gradle = await readFile(gradlePath, "utf8");
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ const match = gradle.match(/applicationId\s*=\s*"([^"]+)"/);
52
+ if (!match || !match[1])
53
+ return null;
54
+ return { apkPath, packageName: match[1] };
55
+ }
56
+ async function runShowBuildSettings(cwd, xcodeproj, scheme) {
57
+ return new Promise((resolvePromise) => {
58
+ let child;
59
+ try {
60
+ child = spawn("xcodebuild", [
61
+ "-project", xcodeproj,
62
+ "-scheme", scheme,
63
+ "-destination", IOS_DESTINATION,
64
+ "-showBuildSettings",
65
+ "-json",
66
+ ], { cwd, env: scrubbedEnv(), stdio: ["ignore", "pipe", "pipe"] });
67
+ }
68
+ catch {
69
+ resolvePromise(null);
70
+ return;
71
+ }
72
+ const stdoutChunks = [];
73
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
74
+ child.on("close", (code) => {
75
+ if (code !== 0) {
76
+ resolvePromise(null);
77
+ return;
78
+ }
79
+ try {
80
+ const arr = JSON.parse(Buffer.concat(stdoutChunks).toString("utf8"));
81
+ resolvePromise(arr[0]?.buildSettings ?? null);
82
+ }
83
+ catch {
84
+ resolvePromise(null);
85
+ }
86
+ });
87
+ child.on("error", () => resolvePromise(null));
88
+ });
89
+ }
90
+ async function readBundleId(infoPlistPath) {
91
+ return new Promise((resolvePromise) => {
92
+ let child;
93
+ try {
94
+ child = spawn("plutil", ["-extract", "CFBundleIdentifier", "raw", "-o", "-", infoPlistPath], { env: scrubbedEnv(), stdio: ["ignore", "pipe", "pipe"] });
95
+ }
96
+ catch {
97
+ resolvePromise(null);
98
+ return;
99
+ }
100
+ const stdoutChunks = [];
101
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
102
+ child.on("close", (code) => {
103
+ if (code !== 0) {
104
+ resolvePromise(null);
105
+ return;
106
+ }
107
+ const out = Buffer.concat(stdoutChunks).toString("utf8").trim();
108
+ resolvePromise(out || null);
109
+ });
110
+ child.on("error", () => resolvePromise(null));
111
+ });
112
+ }
113
+ //# sourceMappingURL=discover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/validation/discover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export { runLayer1 } from "./layer1.js";
2
+ export type { Layer1Input, Layer1Finding, Layer1Result } from "./layer1.js";
3
+ export { runLayer2 } from "./layer2.js";
4
+ export type { Layer2Input, Layer2Result } from "./layer2.js";
5
+ export { runLayer3 } from "./layer3.js";
6
+ export type { Layer3Criterion, Layer3Input, Layer3Score, Layer3Result } from "./layer3.js";
7
+ export { captureScreenshot } from "./capture.js";
8
+ export type { CapturePlatform, CaptureInput, CaptureResult } from "./capture.js";
9
+ export { installAndLaunch } from "./launch.js";
10
+ export type { LaunchInput, IosLaunchInput, AndroidLaunchInput, LaunchResult } from "./launch.js";
11
+ export { runVisualJudge, DEFAULT_STAGE1_RUBRIC } from "./visual-judge.js";
12
+ export type { VisualJudgeInput, VisualJudgeResult } from "./visual-judge.js";
13
+ export { discoverIosArtifact, discoverAndroidArtifact } from "./discover.js";
14
+ export type { IosArtifact, AndroidArtifact } from "./discover.js";
15
+ export { runStage1Visual } from "./stage1.js";
16
+ export type { Stage1VisualInput, Stage1VisualResult } from "./stage1.js";
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE5E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3F,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AACjD,YAAY,EAAE,eAAe,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAEjF,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,YAAY,EAAE,WAAW,EAAE,cAAc,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEjG,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC1E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE7E,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAC7E,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAElE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { runLayer1 } from "./layer1.js";
2
+ export { runLayer2 } from "./layer2.js";
3
+ export { runLayer3 } from "./layer3.js";
4
+ export { captureScreenshot } from "./capture.js";
5
+ export { installAndLaunch } from "./launch.js";
6
+ export { runVisualJudge, DEFAULT_STAGE1_RUBRIC } from "./visual-judge.js";
7
+ export { discoverIosArtifact, discoverAndroidArtifact } from "./discover.js";
8
+ export { runStage1Visual } from "./stage1.js";
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/validation/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAG1E,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AAG7E,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ export type LaunchResult = {
2
+ ok: boolean;
3
+ command: string;
4
+ durationMs: number;
5
+ error?: string;
6
+ };
7
+ export type IosLaunchInput = {
8
+ platform: "ios";
9
+ appPath: string;
10
+ bundleId: string;
11
+ timeoutMs?: number;
12
+ };
13
+ export type AndroidLaunchInput = {
14
+ platform: "android";
15
+ apkPath: string;
16
+ packageName: string;
17
+ timeoutMs?: number;
18
+ };
19
+ export type LaunchInput = IosLaunchInput | AndroidLaunchInput;
20
+ export declare function installAndLaunch(input: LaunchInput): Promise<LaunchResult>;
21
+ //# sourceMappingURL=launch.d.ts.map
@@ -0,0 +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;AAsB9D,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAQhF"}
@@ -0,0 +1,109 @@
1
+ import { spawn } from "node:child_process";
2
+ import { scrubbedEnv } from "../env.js";
3
+ import { resolveAdbPath } from "../adb.js";
4
+ const DEFAULT_TIMEOUT_MS = 60_000;
5
+ // Install and launch the generated app on whatever sim/emulator is currently
6
+ // booted. Discovery (finding the .app / .apk artifact, deriving the bundle ID
7
+ // / package name from the slug) is the caller's concern — this function takes
8
+ // already-resolved inputs and runs the install + launch chain.
9
+ //
10
+ // Two-step chain per platform:
11
+ // iOS: xcrun simctl install booted <appPath>
12
+ // xcrun simctl launch booted <bundleId>
13
+ // Android: adb install <apkPath>
14
+ // adb shell monkey -p <package> -c android.intent.category.LAUNCHER 1
15
+ //
16
+ // `monkey` on Android is used over `am start -n <pkg>/<activity>` because it
17
+ // only needs the package name — the caller doesn't have to know which activity
18
+ // is the entry point, just the rename plan's slug-derived package.
19
+ //
20
+ // Screen-readiness polling is NOT done here; the caller should sleep briefly
21
+ // before captureScreenshot() so the home screen has rendered. A future PR may
22
+ // add an explicit ready-poll using accessibility tree or pixel diff.
23
+ export async function installAndLaunch(input) {
24
+ const timeoutMs = input.timeoutMs ?? DEFAULT_TIMEOUT_MS;
25
+ switch (input.platform) {
26
+ case "ios":
27
+ return installAndLaunchIos(input.appPath, input.bundleId, timeoutMs);
28
+ case "android":
29
+ return installAndLaunchAndroid(input.apkPath, input.packageName, timeoutMs);
30
+ }
31
+ }
32
+ async function installAndLaunchIos(appPath, bundleId, timeoutMs) {
33
+ const started = Date.now();
34
+ const installCmd = `xcrun simctl install booted ${appPath}`;
35
+ const launchCmd = `xcrun simctl launch booted ${bundleId}`;
36
+ const install = await runOnce("xcrun", ["simctl", "install", "booted", appPath], timeoutMs);
37
+ if (!install.ok) {
38
+ return {
39
+ ok: false,
40
+ command: installCmd,
41
+ durationMs: Date.now() - started,
42
+ ...(install.error !== undefined ? { error: install.error } : {}),
43
+ };
44
+ }
45
+ const launch = await runOnce("xcrun", ["simctl", "launch", "booted", bundleId], timeoutMs);
46
+ return {
47
+ ok: launch.ok,
48
+ command: `${installCmd} && ${launchCmd}`,
49
+ durationMs: Date.now() - started,
50
+ ...(launch.ok || launch.error === undefined ? {} : { error: launch.error }),
51
+ };
52
+ }
53
+ async function installAndLaunchAndroid(apkPath, packageName, timeoutMs) {
54
+ const adb = resolveAdbPath();
55
+ const started = Date.now();
56
+ const installCmd = `${adb} install -r ${apkPath}`;
57
+ const launchCmd = `${adb} shell monkey -p ${packageName} -c android.intent.category.LAUNCHER 1`;
58
+ const install = await runOnce(adb, ["install", "-r", apkPath], timeoutMs);
59
+ if (!install.ok) {
60
+ return {
61
+ ok: false,
62
+ command: installCmd,
63
+ durationMs: Date.now() - started,
64
+ ...(install.error !== undefined ? { error: install.error } : {}),
65
+ };
66
+ }
67
+ const launch = await runOnce(adb, ["shell", "monkey", "-p", packageName, "-c", "android.intent.category.LAUNCHER", "1"], timeoutMs);
68
+ return {
69
+ ok: launch.ok,
70
+ command: `${installCmd} && ${launchCmd}`,
71
+ durationMs: Date.now() - started,
72
+ ...(launch.ok || launch.error === undefined ? {} : { error: launch.error }),
73
+ };
74
+ }
75
+ function runOnce(cmd, args, timeoutMs) {
76
+ return new Promise((resolvePromise) => {
77
+ let child;
78
+ try {
79
+ child = spawn(cmd, [...args], { env: scrubbedEnv(), stdio: ["ignore", "pipe", "pipe"] });
80
+ }
81
+ catch (err) {
82
+ resolvePromise({ ok: false, error: err instanceof Error ? err.message : String(err) });
83
+ return;
84
+ }
85
+ const stderrChunks = [];
86
+ const stdoutChunks = [];
87
+ child.stderr.on("data", (c) => stderrChunks.push(c));
88
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
89
+ const timer = setTimeout(() => { child.kill("SIGTERM"); }, timeoutMs);
90
+ child.on("close", (code) => {
91
+ clearTimeout(timer);
92
+ const stderr = Buffer.concat(stderrChunks).toString("utf8").trim();
93
+ const stdout = Buffer.concat(stdoutChunks).toString("utf8").trim();
94
+ // adb install prints success/failure on stdout; non-zero exit alone
95
+ // isn't always the right signal. Check for explicit failure markers.
96
+ if (code === 0 && !stdout.toLowerCase().includes("failure")) {
97
+ resolvePromise({ ok: true });
98
+ }
99
+ else {
100
+ resolvePromise({ ok: false, error: stderr || stdout || `${cmd} exited ${code}` });
101
+ }
102
+ });
103
+ child.on("error", (err) => {
104
+ clearTimeout(timer);
105
+ resolvePromise({ ok: false, error: err.message });
106
+ });
107
+ });
108
+ }
109
+ //# sourceMappingURL=launch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/validation/launch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export type Layer1Input = {
2
+ projectDir: string;
3
+ forbiddenTokens: readonly string[];
4
+ };
5
+ export type Layer1Finding = {
6
+ token: string;
7
+ file: string;
8
+ line: number;
9
+ text: string;
10
+ };
11
+ export type Layer1Result = {
12
+ pass: boolean;
13
+ findings: Layer1Finding[];
14
+ };
15
+ export declare function runLayer1(input: Layer1Input): Promise<Layer1Result>;
16
+ //# sourceMappingURL=layer1.d.ts.map
@@ -0,0 +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;AAyBF,wBAAsB,SAAS,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,YAAY,CAAC,CAiCzE"}