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,116 @@
1
+ import { cp, lstat, mkdir, rm, stat } from "node:fs/promises";
2
+ import { spawn } from "node:child_process";
3
+ import { scrubbedEnv } from "../../env.js";
4
+ import { resolve } from "node:path";
5
+ import { trace } from "../../trace.js";
6
+ import { isStub } from "../../stub.js";
7
+ import { runRuby } from "../../ruby.js";
8
+ import { slugToPascal } from "../../slug.js";
9
+ const SKIP_SEGMENTS = new Set([
10
+ ".git",
11
+ ".claude",
12
+ "build",
13
+ ".gradle",
14
+ ".idea",
15
+ ".kotlin",
16
+ "captures",
17
+ "node_modules",
18
+ ]);
19
+ export async function runAndroidWorker(domain) {
20
+ if (isStub("android")) {
21
+ return runStubAndroidWorker(domain);
22
+ }
23
+ const substrate = process.env['NATIVEAPPTEMPLATE_ANDROID'];
24
+ if (!substrate) {
25
+ throw new Error("android worker: NATIVEAPPTEMPLATE_ANDROID env var is not set; see CLAUDE.md Substrate section");
26
+ }
27
+ const outDir = resolve(process.cwd(), "out", domain.slug, "android");
28
+ trace("android", `copying substrate from ${substrate} to ${outDir}`);
29
+ await prepareFresh(outDir);
30
+ await copyFiltered(substrate, outDir);
31
+ const productPairs = buildProductRenamePairs(domain.slug);
32
+ const renamePlan = [...productPairs, ...domain.renamePlan].filter((p) => p.from !== p.to);
33
+ const plan = renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
34
+ trace("android", `running scripts/ruby/rename.rb: ${plan}`);
35
+ const renameStats = await runRuby("rename.rb", { renamePlan, root: outDir });
36
+ trace("android", `scanned ${renameStats.files_scanned} files, changed ${renameStats.files_changed}, ${renameStats.substitutions} substitutions, ${renameStats.files_renamed} file/dir renames`);
37
+ await initGit(outDir);
38
+ trace("android", `done (out/${domain.slug}/android)`);
39
+ return {
40
+ platform: "android",
41
+ outDir: `./out/${domain.slug}/android`,
42
+ filesTouched: renameStats.files_changed + renameStats.files_renamed,
43
+ renamedFrom: renamePlan.map((p) => p.from),
44
+ };
45
+ }
46
+ function buildProductRenamePairs(slug) {
47
+ const pascal = slugToPascal(slug);
48
+ return [
49
+ { from: "NativeAppTemplateFree", to: `${pascal}App` },
50
+ { from: "NativeAppTemplate", to: pascal },
51
+ ];
52
+ }
53
+ async function prepareFresh(dir) {
54
+ try {
55
+ await stat(dir);
56
+ await rm(dir, { recursive: true, force: true });
57
+ }
58
+ catch {
59
+ // dest doesn't exist
60
+ }
61
+ await mkdir(dir, { recursive: true });
62
+ }
63
+ async function copyFiltered(src, dest) {
64
+ await cp(src, dest, {
65
+ recursive: true,
66
+ force: true,
67
+ filter: async (source) => {
68
+ const rel = source.slice(src.length);
69
+ const segments = rel.split("/").filter(Boolean);
70
+ if (segments.some((seg) => SKIP_SEGMENTS.has(seg)))
71
+ return false;
72
+ try {
73
+ const s = await lstat(source);
74
+ if (s.isSocket() || s.isFIFO() || s.isBlockDevice() || s.isCharacterDevice())
75
+ return false;
76
+ }
77
+ catch {
78
+ return false;
79
+ }
80
+ return true;
81
+ },
82
+ });
83
+ }
84
+ async function initGit(dir) {
85
+ await new Promise((resolvePromise, rejectPromise) => {
86
+ const child = spawn("git", ["init", "-q", "-b", "main"], { cwd: dir, env: scrubbedEnv() });
87
+ child.on("close", (code) => {
88
+ if (code === 0)
89
+ resolvePromise();
90
+ else
91
+ rejectPromise(new Error(`git init exited ${code}`));
92
+ });
93
+ child.on("error", rejectPromise);
94
+ });
95
+ }
96
+ const delay = (ms) => new Promise((r) => { setTimeout(r, ms); });
97
+ async function runStubAndroidWorker(domain) {
98
+ const plan = domain.renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
99
+ trace("android", "(stub mode)");
100
+ trace("android", `copying Jetpack Compose substrate for ${domain.displayName}`);
101
+ await delay(200);
102
+ trace("android", `renaming Kotlin symbols: ${plan}`);
103
+ await delay(300);
104
+ trace("android", "regenerating data classes + Hilt modules");
105
+ await delay(250);
106
+ trace("android", "updating res/values/strings.xml");
107
+ await delay(200);
108
+ trace("android", `done (out/${domain.slug}/android)`);
109
+ return {
110
+ platform: "android",
111
+ outDir: `./out/${domain.slug}/android`,
112
+ filesTouched: 81,
113
+ renamedFrom: domain.renamePlan.map((p) => p.from),
114
+ };
115
+ }
116
+ //# sourceMappingURL=android.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"android.js","sourceRoot":"","sources":["../../../src/agents/workers/android.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { DomainSpec, WorkerResult } from "../types.js";
2
+ export declare function runIosWorker(domain: DomainSpec): Promise<WorkerResult>;
3
+ //# sourceMappingURL=ios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ios.d.ts","sourceRoot":"","sources":["../../../src/agents/workers/ios.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAc,YAAY,EAAE,MAAM,aAAa,CAAC;AAYxE,wBAAsB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAwC5E"}
@@ -0,0 +1,110 @@
1
+ import { cp, lstat, mkdir, rm, stat } from "node:fs/promises";
2
+ import { spawn } from "node:child_process";
3
+ import { scrubbedEnv } from "../../env.js";
4
+ import { resolve } from "node:path";
5
+ import { trace } from "../../trace.js";
6
+ import { isStub } from "../../stub.js";
7
+ import { runRuby } from "../../ruby.js";
8
+ import { slugToPascal } from "../../slug.js";
9
+ const SKIP_RELATIVE_PATHS = ["/.git", "/.claude", "/DerivedData", "/.build", "/Pods", "/Carthage"];
10
+ const SKIP_DIR_NAMES = new Set(["xcuserdata"]);
11
+ export async function runIosWorker(domain) {
12
+ if (isStub("ios")) {
13
+ return runStubIosWorker(domain);
14
+ }
15
+ const substrate = process.env['NATIVEAPPTEMPLATE_IOS'];
16
+ if (!substrate) {
17
+ throw new Error("ios worker: NATIVEAPPTEMPLATE_IOS env var is not set; see CLAUDE.md Substrate section");
18
+ }
19
+ const outDir = resolve(process.cwd(), "out", domain.slug, "ios");
20
+ trace("ios", `copying substrate from ${substrate} to ${outDir}`);
21
+ await prepareFresh(outDir);
22
+ await copyFiltered(substrate, outDir);
23
+ const productPairs = buildProductRenamePairs(domain.slug);
24
+ const renamePlan = [...productPairs, ...domain.renamePlan].filter((p) => p.from !== p.to);
25
+ const plan = renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
26
+ trace("ios", `running scripts/ruby/rename.rb: ${plan}`);
27
+ const renameStats = await runRuby("rename.rb", { renamePlan, root: outDir });
28
+ trace("ios", `scanned ${renameStats.files_scanned} files, changed ${renameStats.files_changed}, ${renameStats.substitutions} substitutions, ${renameStats.files_renamed} file/dir renames`);
29
+ await initGit(outDir);
30
+ trace("ios", `done (out/${domain.slug}/ios)`);
31
+ return {
32
+ platform: "ios",
33
+ outDir: `./out/${domain.slug}/ios`,
34
+ filesTouched: renameStats.files_changed + renameStats.files_renamed,
35
+ renamedFrom: renamePlan.map((p) => p.from),
36
+ };
37
+ }
38
+ function buildProductRenamePairs(slug) {
39
+ const pascal = slugToPascal(slug);
40
+ return [
41
+ { from: "NativeAppTemplateFree", to: `${pascal}App` },
42
+ { from: "NativeAppTemplate", to: pascal },
43
+ ];
44
+ }
45
+ async function prepareFresh(dir) {
46
+ try {
47
+ await stat(dir);
48
+ await rm(dir, { recursive: true, force: true });
49
+ }
50
+ catch {
51
+ // dest doesn't exist
52
+ }
53
+ await mkdir(dir, { recursive: true });
54
+ }
55
+ async function copyFiltered(src, dest) {
56
+ await cp(src, dest, {
57
+ recursive: true,
58
+ force: true,
59
+ filter: async (source) => {
60
+ const rel = source.slice(src.length);
61
+ if (SKIP_RELATIVE_PATHS.some((p) => rel === p || rel.startsWith(`${p}/`)))
62
+ return false;
63
+ const segments = rel.split("/").filter(Boolean);
64
+ if (segments.some((seg) => SKIP_DIR_NAMES.has(seg)))
65
+ return false;
66
+ try {
67
+ const s = await lstat(source);
68
+ if (s.isSocket() || s.isFIFO() || s.isBlockDevice() || s.isCharacterDevice())
69
+ return false;
70
+ }
71
+ catch {
72
+ return false;
73
+ }
74
+ return true;
75
+ },
76
+ });
77
+ }
78
+ async function initGit(dir) {
79
+ await new Promise((resolvePromise, rejectPromise) => {
80
+ const child = spawn("git", ["init", "-q", "-b", "main"], { cwd: dir, env: scrubbedEnv() });
81
+ child.on("close", (code) => {
82
+ if (code === 0)
83
+ resolvePromise();
84
+ else
85
+ rejectPromise(new Error(`git init exited ${code}`));
86
+ });
87
+ child.on("error", rejectPromise);
88
+ });
89
+ }
90
+ const delay = (ms) => new Promise((r) => { setTimeout(r, ms); });
91
+ async function runStubIosWorker(domain) {
92
+ const plan = domain.renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
93
+ trace("ios", "(stub mode)");
94
+ trace("ios", `copying SwiftUI substrate for ${domain.displayName}`);
95
+ await delay(200);
96
+ trace("ios", `renaming Swift symbols: ${plan}`);
97
+ await delay(300);
98
+ trace("ios", "regenerating @Observable view models");
99
+ await delay(250);
100
+ trace("ios", "updating Localizable.strings");
101
+ await delay(200);
102
+ trace("ios", `done (out/${domain.slug}/ios)`);
103
+ return {
104
+ platform: "ios",
105
+ outDir: `./out/${domain.slug}/ios`,
106
+ filesTouched: 63,
107
+ renamedFrom: domain.renamePlan.map((p) => p.from),
108
+ };
109
+ }
110
+ //# sourceMappingURL=ios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ios.js","sourceRoot":"","sources":["../../../src/agents/workers/ios.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { DomainSpec, WorkerResult } from "../types.js";
2
+ export declare function runRailsWorker(domain: DomainSpec): Promise<WorkerResult>;
3
+ //# sourceMappingURL=rails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails.d.ts","sourceRoot":"","sources":["../../../src/agents/workers/rails.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,UAAU,EAAc,YAAY,EAAE,MAAM,aAAa,CAAC;AAWxE,wBAAsB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAyC9E"}
@@ -0,0 +1,145 @@
1
+ import { cp, lstat, mkdir, rm, stat } from "node:fs/promises";
2
+ import { spawn } from "node:child_process";
3
+ import { scrubbedEnv } from "../../env.js";
4
+ import { resolve } from "node:path";
5
+ import { trace } from "../../trace.js";
6
+ import { isStub } from "../../stub.js";
7
+ import { runRuby } from "../../ruby.js";
8
+ import { slugToPascal, slugToSnake } from "../../slug.js";
9
+ const SKIP_RELATIVE_PATHS = ["/.git", "/.claude", "/node_modules", "/tmp", "/log", "/vendor/bundle"];
10
+ export async function runRailsWorker(domain) {
11
+ if (isStub("rails")) {
12
+ return runStubRailsWorker(domain);
13
+ }
14
+ const substrate = process.env['NATIVEAPPTEMPLATE_API'];
15
+ if (!substrate) {
16
+ throw new Error("rails worker: NATIVEAPPTEMPLATE_API env var is not set; see CLAUDE.md Substrate section");
17
+ }
18
+ const outDir = resolve(process.cwd(), "out", domain.slug, "rails");
19
+ trace("rails", `copying substrate from ${substrate} to ${outDir}`);
20
+ await prepareFresh(outDir);
21
+ await copyFiltered(substrate, outDir);
22
+ const productPairs = buildProductRenamePairs(domain.slug);
23
+ const renamePlan = [...productPairs, ...domain.renamePlan].filter((p) => p.from !== p.to);
24
+ const plan = renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
25
+ trace("rails", `running scripts/ruby/rename.rb: ${plan}`);
26
+ const renameStats = await runRuby("rename.rb", { renamePlan, root: outDir });
27
+ trace("rails", `scanned ${renameStats.files_scanned} files, changed ${renameStats.files_changed}, ${renameStats.substitutions} substitutions, ${renameStats.files_renamed} file/dir renames`);
28
+ await dropSlugDatabases(domain.slug);
29
+ await initGit(outDir);
30
+ trace("rails", `done (out/${domain.slug}/rails)`);
31
+ return {
32
+ platform: "rails",
33
+ outDir: `./out/${domain.slug}/rails`,
34
+ filesTouched: renameStats.files_changed + renameStats.files_renamed,
35
+ renamedFrom: renamePlan.map((p) => p.from),
36
+ };
37
+ }
38
+ function buildProductRenamePairs(slug) {
39
+ const pascal = slugToPascal(slug);
40
+ return [
41
+ { from: "Nativeapptemplateapi", to: `${pascal}Api` },
42
+ { from: "NativeAppTemplate", to: pascal },
43
+ ];
44
+ }
45
+ async function prepareFresh(dir) {
46
+ try {
47
+ await stat(dir);
48
+ await rm(dir, { recursive: true, force: true });
49
+ }
50
+ catch {
51
+ // dest doesn't exist — nothing to clean
52
+ }
53
+ await mkdir(dir, { recursive: true });
54
+ }
55
+ async function copyFiltered(src, dest) {
56
+ await cp(src, dest, {
57
+ recursive: true,
58
+ force: true,
59
+ filter: async (source) => {
60
+ const rel = source.slice(src.length);
61
+ if (SKIP_RELATIVE_PATHS.some((p) => rel === p || rel.startsWith(`${p}/`)))
62
+ return false;
63
+ try {
64
+ const s = await lstat(source);
65
+ if (s.isSocket() || s.isFIFO() || s.isBlockDevice() || s.isCharacterDevice())
66
+ return false;
67
+ }
68
+ catch {
69
+ return false;
70
+ }
71
+ return true;
72
+ },
73
+ });
74
+ }
75
+ async function dropSlugDatabases(slug) {
76
+ const prefix = `${slugToSnake(slug)}_api`;
77
+ const names = await listDatabasesStartingWith(prefix);
78
+ if (names.length === 0) {
79
+ trace("rails", `no stale ${prefix}* databases to drop`);
80
+ return;
81
+ }
82
+ for (const name of names) {
83
+ await execPsql(["-c", `DROP DATABASE IF EXISTS "${name}";`]);
84
+ }
85
+ trace("rails", `dropped ${names.length} stale slug-scoped database(s): ${names.join(", ")}`);
86
+ }
87
+ async function listDatabasesStartingWith(prefix) {
88
+ try {
89
+ const stdout = await execPsql(["-tAc", `SELECT datname FROM pg_database WHERE datname LIKE '${prefix}%' ORDER BY datname;`]);
90
+ return stdout.split("\n").map((s) => s.trim()).filter(Boolean);
91
+ }
92
+ catch {
93
+ trace("rails", "psql unavailable or refused connection — skipping stale-DB cleanup");
94
+ return [];
95
+ }
96
+ }
97
+ async function execPsql(args) {
98
+ return new Promise((resolvePromise, rejectPromise) => {
99
+ const child = spawn("psql", ["-h", "localhost", "-d", "postgres", ...args], { env: scrubbedEnv() });
100
+ const stdoutChunks = [];
101
+ const stderrChunks = [];
102
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
103
+ child.stderr.on("data", (c) => stderrChunks.push(c));
104
+ child.on("close", (code) => {
105
+ if (code === 0)
106
+ resolvePromise(Buffer.concat(stdoutChunks).toString("utf8"));
107
+ else
108
+ rejectPromise(new Error(`psql exited ${code}: ${Buffer.concat(stderrChunks).toString("utf8")}`));
109
+ });
110
+ child.on("error", rejectPromise);
111
+ });
112
+ }
113
+ async function initGit(dir) {
114
+ await new Promise((resolvePromise, rejectPromise) => {
115
+ const child = spawn("git", ["init", "-q", "-b", "main"], { cwd: dir, env: scrubbedEnv() });
116
+ child.on("close", (code) => {
117
+ if (code === 0)
118
+ resolvePromise();
119
+ else
120
+ rejectPromise(new Error(`git init exited ${code}`));
121
+ });
122
+ child.on("error", rejectPromise);
123
+ });
124
+ }
125
+ const delay = (ms) => new Promise((r) => { setTimeout(r, ms); });
126
+ async function runStubRailsWorker(domain) {
127
+ const plan = domain.renamePlan.map((p) => `${p.from}->${p.to}`).join(", ");
128
+ trace("rails", "(stub mode)");
129
+ trace("rails", `copying substrate for ${domain.displayName}`);
130
+ await delay(200);
131
+ trace("rails", `renaming Ruby symbols: ${plan}`);
132
+ await delay(300);
133
+ trace("rails", "regenerating migrations");
134
+ await delay(250);
135
+ trace("rails", "updating routes.rb + JSON:API serializers");
136
+ await delay(200);
137
+ trace("rails", `done (out/${domain.slug}/rails)`);
138
+ return {
139
+ platform: "rails",
140
+ outDir: `./out/${domain.slug}/rails`,
141
+ filesTouched: 47,
142
+ renamedFrom: domain.renamePlan.map((p) => p.from),
143
+ };
144
+ }
145
+ //# sourceMappingURL=rails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails.js","sourceRoot":"","sources":["../../../src/agents/workers/rails.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { JudgeResult } from "./agents/types.js";
2
+ export declare function dispatch(spec: string): Promise<JudgeResult>;
3
+ //# sourceMappingURL=dispatch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA+BjE"}
@@ -0,0 +1,38 @@
1
+ import { resolve } from "node:path";
2
+ import { runPlanner } from "./agents/planner.js";
3
+ import { runRailsWorker } from "./agents/workers/rails.js";
4
+ import { runIosWorker } from "./agents/workers/ios.js";
5
+ import { runAndroidWorker } from "./agents/workers/android.js";
6
+ import { runReviewer } from "./agents/reviewer.js";
7
+ import { runJudge } from "./agents/judge.js";
8
+ export async function dispatch(spec) {
9
+ const domain = await runPlanner(spec);
10
+ const [rails, ios, android] = await Promise.all([
11
+ runRailsWorker(domain),
12
+ runIosWorker(domain),
13
+ runAndroidWorker(domain),
14
+ ]);
15
+ const reviewer = await runReviewer({ domain, rails, ios, android });
16
+ // Stage 1 visual judging is opt-in via NATIVEAPPTEMPLATE_VISUAL=1.
17
+ // It forces Layer 2 build mode (so .app / .apk artifacts exist for the
18
+ // discovery + install + launch + capture chain) and adds 60-180s to a
19
+ // run depending on the substrate's cold-build time. Off by default.
20
+ const visualEnabled = process.env['NATIVEAPPTEMPLATE_VISUAL'] === "1";
21
+ const visual = visualEnabled
22
+ ? {
23
+ iosDir: resolve(process.cwd(), ios.outDir),
24
+ androidDir: resolve(process.cwd(), android.outDir),
25
+ spec: domain.displayName,
26
+ }
27
+ : undefined;
28
+ return runJudge({
29
+ domain,
30
+ rails,
31
+ ios,
32
+ android,
33
+ reviewer,
34
+ ...(visualEnabled ? { layer2Mode: "build" } : {}),
35
+ ...(visual ? { visual } : {}),
36
+ });
37
+ }
38
+ //# sourceMappingURL=dispatch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,EAAE,QAAQ,EAA0B,MAAM,mBAAmB,CAAC;AAGrE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAY;IACzC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,CAAC;IACtC,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC9C,cAAc,CAAC,MAAM,CAAC;QACtB,YAAY,CAAC,MAAM,CAAC;QACpB,gBAAgB,CAAC,MAAM,CAAC;KACzB,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAEpE,mEAAmE;IACnE,uEAAuE;IACvE,sEAAsE;IACtE,oEAAoE;IACpE,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,KAAK,GAAG,CAAC;IACtE,MAAM,MAAM,GAAkC,aAAa;QACzD,CAAC,CAAC;YACE,MAAM,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC;YAC1C,UAAU,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC;YAClD,IAAI,EAAE,MAAM,CAAC,WAAW;SACzB;QACH,CAAC,CAAC,SAAS,CAAC;IAEd,OAAO,QAAQ,CAAC;QACd,MAAM;QACN,KAAK;QACL,GAAG;QACH,OAAO;QACP,QAAQ;QACR,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAgB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC1D,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9B,CAAC,CAAC;AACL,CAAC"}
package/dist/env.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare function scrubbedEnv(extra?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
2
+ export declare function loadDotenvIfPresent(path?: string): void;
3
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAcA,wBAAgB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAIxE;AASD,wBAAgB,mBAAmB,CAAC,IAAI,SAAS,GAAG,IAAI,CAmBvD"}
package/dist/env.js ADDED
@@ -0,0 +1,48 @@
1
+ import { readFileSync } from "node:fs";
2
+ // Subprocesses inherit the agent's full environment by default, including
3
+ // ANTHROPIC_API_KEY. None of the things the agent spawns (ruby, git, psql,
4
+ // xcodebuild, gradlew, bin/rails) need that key, and one of them — eventually
5
+ // the mobile-mcp client — is third-party code. Strip anything that looks like
6
+ // an Anthropic credential before handing env to a child.
7
+ const SENSITIVE_KEYS = [
8
+ "ANTHROPIC_API_KEY",
9
+ "ANTHROPIC_AUTH_TOKEN",
10
+ "NATIVEAPPTEMPLATE_AGENT_ANTHROPIC_KEY",
11
+ ];
12
+ export function scrubbedEnv(extra) {
13
+ const env = { ...process.env };
14
+ for (const key of SENSITIVE_KEYS)
15
+ delete env[key];
16
+ return extra ? { ...env, ...extra } : env;
17
+ }
18
+ // Load `.env` if present, but never overwrite an already-set process.env
19
+ // value. Shell exports (`export FOO=x`) and inline assignment
20
+ // (`FOO=x npm run dev`) win over the file. `.env` is just a convenience
21
+ // for users who don't want to manage shell config.
22
+ //
23
+ // Format: KEY=value per line, comments with `#`, surrounding double or
24
+ // single quotes are stripped. No shell interpolation.
25
+ export function loadDotenvIfPresent(path = ".env") {
26
+ let raw;
27
+ try {
28
+ raw = readFileSync(path, "utf8");
29
+ }
30
+ catch {
31
+ return;
32
+ }
33
+ for (const line of raw.split("\n")) {
34
+ const trimmed = line.trim();
35
+ if (!trimmed || trimmed.startsWith("#"))
36
+ continue;
37
+ const eq = trimmed.indexOf("=");
38
+ if (eq < 1)
39
+ continue;
40
+ const key = trimmed.slice(0, eq).trim();
41
+ const valueRaw = trimmed.slice(eq + 1).trim();
42
+ const value = valueRaw.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
43
+ if (process.env[key] === undefined) {
44
+ process.env[key] = value;
45
+ }
46
+ }
47
+ }
48
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../src/env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,0EAA0E;AAC1E,2EAA2E;AAC3E,8EAA8E;AAC9E,8EAA8E;AAC9E,yDAAyD;AAEzD,MAAM,cAAc,GAAG;IACrB,mBAAmB;IACnB,sBAAsB;IACtB,uCAAuC;CAC/B,CAAC;AAEX,MAAM,UAAU,WAAW,CAAC,KAAyB;IACnD,MAAM,GAAG,GAAsB,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAClD,KAAK,MAAM,GAAG,IAAI,cAAc;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC;IAClD,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED,yEAAyE;AACzE,8DAA8D;AAC9D,wEAAwE;AACxE,mDAAmD;AACnD,EAAE;AACF,uEAAuE;AACvE,sDAAsD;AACtD,MAAM,UAAU,mBAAmB,CAAC,IAAI,GAAG,MAAM;IAC/C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAClD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAChC,IAAI,EAAE,GAAG,CAAC;YAAE,SAAS;QACrB,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC9C,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QAC3E,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QAC3B,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export declare function main(spec?: string): Promise<void>;
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAMA,wBAAsB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBvD"}
package/dist/index.js ADDED
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env node
2
+ import { dispatch } from "./dispatch.js";
3
+ import { loadDotenvIfPresent } from "./env.js";
4
+ loadDotenvIfPresent();
5
+ export async function main(spec) {
6
+ const input = spec ?? process.argv.slice(2).join(" ").trim();
7
+ if (!input) {
8
+ console.error('Usage: nativeapptemplate-agent "your spec here"');
9
+ process.exitCode = 1;
10
+ return;
11
+ }
12
+ console.log(`nativeapptemplate-agent: received spec: ${input}`);
13
+ console.log('(tail tmp/trace/*.log in a tiled view via scripts/demo-tmux.sh)');
14
+ const result = await dispatch(input);
15
+ console.log('');
16
+ console.log('=== run complete ===');
17
+ console.log(`result: ${result.summary}`);
18
+ console.log(`overall: ${result.overallPass ? 'PASS' : 'FAIL'}`);
19
+ }
20
+ if (import.meta.url === `file://${process.argv[1]}`) {
21
+ main().catch((err) => {
22
+ console.error(err);
23
+ process.exitCode = 1;
24
+ });
25
+ }
26
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAE/C,mBAAmB,EAAE,CAAC;AAEtB,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAa;IACtC,MAAM,KAAK,GAAG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,iDAAiD,CAAC,CAAC;QACjE,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;QACrB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2CAA2C,KAAK,EAAE,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,iEAAiE,CAAC,CAAC;IAE/E,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,KAAK,CAAC,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;IACpC,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,UAAU,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;IACpD,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACnB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvB,CAAC,CAAC,CAAC;AACL,CAAC"}
package/dist/ruby.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function runRuby<TInput, TOutput>(scriptName: string, input: TInput): Promise<TOutput>;
2
+ //# sourceMappingURL=ruby.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruby.d.ts","sourceRoot":"","sources":["../src/ruby.ts"],"names":[],"mappings":"AAIA,wBAAsB,OAAO,CAAC,MAAM,EAAE,OAAO,EAC3C,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAqBlB"}
package/dist/ruby.js ADDED
@@ -0,0 +1,21 @@
1
+ import { spawn } from "node:child_process";
2
+ import { resolve } from "node:path";
3
+ import { scrubbedEnv } from "./env.js";
4
+ export async function runRuby(scriptName, input) {
5
+ const scriptPath = resolve(process.cwd(), "scripts/ruby", scriptName);
6
+ const child = spawn("ruby", [scriptPath], { env: scrubbedEnv() });
7
+ const stdoutChunks = [];
8
+ const stderrChunks = [];
9
+ child.stdout.on("data", (c) => stdoutChunks.push(c));
10
+ child.stderr.on("data", (c) => stderrChunks.push(c));
11
+ child.stdin.write(JSON.stringify(input));
12
+ child.stdin.end();
13
+ const code = await new Promise((r) => { child.on("close", r); });
14
+ if (code !== 0) {
15
+ const stderr = Buffer.concat(stderrChunks).toString("utf8");
16
+ throw new Error(`ruby script ${scriptName} exited ${code}: ${stderr}`);
17
+ }
18
+ const stdout = Buffer.concat(stdoutChunks).toString("utf8");
19
+ return JSON.parse(stdout);
20
+ }
21
+ //# sourceMappingURL=ruby.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ruby.js","sourceRoot":"","sources":["../src/ruby.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,UAAkB,EAClB,KAAa;IAEb,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;IACtE,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;IAElE,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,MAAM,YAAY,GAAa,EAAE,CAAC;IAElC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7D,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAE7D,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IACzC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;IAElB,MAAM,IAAI,GAAW,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC5D,MAAM,IAAI,KAAK,CAAC,eAAe,UAAU,WAAW,IAAI,KAAK,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC5D,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAY,CAAC;AACvC,CAAC"}
package/dist/slug.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export declare function slugToPascal(slug: string): string;
2
+ export declare function slugToSnake(slug: string): string;
3
+ //# sourceMappingURL=slug.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEhD"}
package/dist/slug.js ADDED
@@ -0,0 +1,11 @@
1
+ export function slugToPascal(slug) {
2
+ return slug
3
+ .split(/[-_]/)
4
+ .filter(Boolean)
5
+ .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
6
+ .join("");
7
+ }
8
+ export function slugToSnake(slug) {
9
+ return slug.replace(/-/g, "_");
10
+ }
11
+ //# sourceMappingURL=slug.js.map