nativeapptemplate-agent 0.1.2 → 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.
Files changed (96) hide show
  1. package/CLAUDE.md +9 -7
  2. package/README.md +65 -21
  3. package/dist/agents/judge.d.ts +8 -0
  4. package/dist/agents/judge.d.ts.map +1 -1
  5. package/dist/agents/judge.js +100 -14
  6. package/dist/agents/judge.js.map +1 -1
  7. package/dist/agents/repair.d.ts +14 -0
  8. package/dist/agents/repair.d.ts.map +1 -0
  9. package/dist/agents/repair.js +103 -0
  10. package/dist/agents/repair.js.map +1 -0
  11. package/dist/agents/types.d.ts +34 -1
  12. package/dist/agents/types.d.ts.map +1 -1
  13. package/dist/dispatch.d.ts +21 -2
  14. package/dist/dispatch.d.ts.map +1 -1
  15. package/dist/dispatch.js +250 -14
  16. package/dist/dispatch.js.map +1 -1
  17. package/dist/env-bridge.d.ts +17 -0
  18. package/dist/env-bridge.d.ts.map +1 -0
  19. package/dist/env-bridge.js +211 -0
  20. package/dist/env-bridge.js.map +1 -0
  21. package/dist/index.d.ts +11 -0
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +88 -3
  24. package/dist/index.js.map +1 -1
  25. package/dist/mcp.d.ts +5 -0
  26. package/dist/mcp.d.ts.map +1 -0
  27. package/dist/mcp.js +83 -0
  28. package/dist/mcp.js.map +1 -0
  29. package/dist/mobile.d.ts +30 -0
  30. package/dist/mobile.d.ts.map +1 -0
  31. package/dist/mobile.js +173 -0
  32. package/dist/mobile.js.map +1 -0
  33. package/dist/rails-lifecycle.d.ts +16 -0
  34. package/dist/rails-lifecycle.d.ts.map +1 -0
  35. package/dist/rails-lifecycle.js +184 -0
  36. package/dist/rails-lifecycle.js.map +1 -0
  37. package/dist/rename-overrides.d.ts +23 -0
  38. package/dist/rename-overrides.d.ts.map +1 -0
  39. package/dist/rename-overrides.js +58 -0
  40. package/dist/rename-overrides.js.map +1 -0
  41. package/dist/repair-loop.d.ts +25 -0
  42. package/dist/repair-loop.d.ts.map +1 -0
  43. package/dist/repair-loop.js +67 -0
  44. package/dist/repair-loop.js.map +1 -0
  45. package/dist/report/collect.d.ts +28 -0
  46. package/dist/report/collect.d.ts.map +1 -0
  47. package/dist/report/collect.js +117 -0
  48. package/dist/report/collect.js.map +1 -0
  49. package/dist/report/model.d.ts +49 -0
  50. package/dist/report/model.d.ts.map +1 -0
  51. package/dist/report/model.js +2 -0
  52. package/dist/report/model.js.map +1 -0
  53. package/dist/report/render.d.ts +3 -0
  54. package/dist/report/render.d.ts.map +1 -0
  55. package/dist/report/render.js +242 -0
  56. package/dist/report/render.js.map +1 -0
  57. package/dist/report/theme.d.ts +2 -0
  58. package/dist/report/theme.d.ts.map +1 -0
  59. package/dist/report/theme.js +115 -0
  60. package/dist/report/theme.js.map +1 -0
  61. package/dist/slug.d.ts +3 -0
  62. package/dist/slug.d.ts.map +1 -1
  63. package/dist/slug.js +30 -0
  64. package/dist/slug.js.map +1 -1
  65. package/dist/validation/capture.d.ts.map +1 -1
  66. package/dist/validation/capture.js +19 -2
  67. package/dist/validation/capture.js.map +1 -1
  68. package/dist/validation/index.d.ts +6 -0
  69. package/dist/validation/index.d.ts.map +1 -1
  70. package/dist/validation/index.js +3 -0
  71. package/dist/validation/index.js.map +1 -1
  72. package/dist/validation/launch.d.ts +10 -0
  73. package/dist/validation/launch.d.ts.map +1 -1
  74. package/dist/validation/launch.js +103 -5
  75. package/dist/validation/launch.js.map +1 -1
  76. package/dist/validation/layer1.d.ts.map +1 -1
  77. package/dist/validation/layer1.js +12 -4
  78. package/dist/validation/layer1.js.map +1 -1
  79. package/dist/validation/scenarios/queue.d.ts +12 -0
  80. package/dist/validation/scenarios/queue.d.ts.map +1 -0
  81. package/dist/validation/scenarios/queue.js +204 -0
  82. package/dist/validation/scenarios/queue.js.map +1 -0
  83. package/dist/validation/stage2-judge.d.ts +21 -0
  84. package/dist/validation/stage2-judge.d.ts.map +1 -0
  85. package/dist/validation/stage2-judge.js +204 -0
  86. package/dist/validation/stage2-judge.js.map +1 -0
  87. package/dist/validation/stage2.d.ts +73 -0
  88. package/dist/validation/stage2.d.ts.map +1 -0
  89. package/dist/validation/stage2.js +313 -0
  90. package/dist/validation/stage2.js.map +1 -0
  91. package/dist/version.d.ts +2 -0
  92. package/dist/version.d.ts.map +1 -0
  93. package/dist/version.js +17 -0
  94. package/dist/version.js.map +1 -0
  95. package/package.json +6 -3
  96. package/scripts/ruby/rename.rb +7 -3
@@ -0,0 +1,184 @@
1
+ import { spawn } from "node:child_process";
2
+ import { setTimeout as sleep } from "node:timers/promises";
3
+ import { readFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import { scrubbedEnv } from "./env.js";
6
+ import { trace } from "./trace.js";
7
+ const DEFAULT_READY_TIMEOUT_MS = 60_000;
8
+ const DEFAULT_SHUTDOWN_GRACE_MS = 5_000;
9
+ export async function startRails(input) {
10
+ const { host, port } = await resolveHostPort(input);
11
+ const url = `http://${host}:${port}`;
12
+ // Two prep steps before bin/dev:
13
+ // 1. bundle install — Layer 2 ran it but gems land in a path
14
+ // bin/rails sees for one-shot CLI; bin/dev needs them again
15
+ // in the same shell context. Idempotent + fast (~1s warm).
16
+ // 2. bin/rails db:prepare — creates+migrates the primary db AND
17
+ // the cable/queue/cache databases the substrate uses
18
+ // (config/database.yml multi-db). Without it, Solid Queue
19
+ // (loaded as a Puma plugin via SOLID_QUEUE_IN_PUMA=true in
20
+ // .env) can't open its queue connection and crashes Puma:
21
+ // "Detected Solid Queue has gone away, stopping Puma".
22
+ trace("dispatch", `rails-lifecycle: bundle install in ${input.outDir}`);
23
+ await runMiseStep(input.outDir, ["bundle", "install"], 180_000, "bundle install");
24
+ trace("dispatch", `rails-lifecycle: bin/rails db:prepare in ${input.outDir}`);
25
+ await runMiseStep(input.outDir, ["bin/rails", "db:prepare"], 60_000, "db:prepare");
26
+ // db:seed_fu — substrate uses the seed-fu gem (NOT standard
27
+ // db:seed). Required because db:prepare only runs seeds on
28
+ // fresh-create; for an already-existing DB it just migrates,
29
+ // leaving PrivacyVersion / TermsVersion empty — which causes
30
+ // signup to 500 in render_create_success when it looks up the
31
+ // current version. seed-fu is idempotent.
32
+ trace("dispatch", `rails-lifecycle: bin/rails db:seed_fu in ${input.outDir}`);
33
+ await runMiseStep(input.outDir, ["bin/rails", "db:seed_fu"], 60_000, "db:seed_fu");
34
+ // Wrap with `mise exec --` so the substrate's pinned Ruby /
35
+ // bundler version activates (substrate's .mise.toml or .tool-versions
36
+ // pins a specific version that may not match system Ruby). Layer 2
37
+ // uses the same wrapper for `bin/rails runner` — match it here so
38
+ // Stage 2's server uses the same toolchain that Layer 2 validated.
39
+ trace("dispatch", `rails-lifecycle: spawning mise exec -- bin/dev in ${input.outDir} (target ${url})`);
40
+ const child = spawn("mise", ["exec", "--", "bin/dev"], {
41
+ cwd: input.outDir,
42
+ env: scrubbedEnv(),
43
+ stdio: ["ignore", "pipe", "pipe"],
44
+ detached: false,
45
+ });
46
+ // Drain stdio so the child doesn't block on backed-up pipes; route
47
+ // a tail to the dispatch trace so silent failures (port already in
48
+ // use, missing gem, etc.) surface in tmp/trace/dispatch.log.
49
+ const tail = [];
50
+ const onData = (c) => {
51
+ const text = c.toString("utf8");
52
+ tail.push(text);
53
+ if (tail.length > 50)
54
+ tail.shift();
55
+ };
56
+ child.stdout?.on("data", onData);
57
+ child.stderr?.on("data", onData);
58
+ // Surface child crash before we time out waiting for ready.
59
+ let exitedEarly = false;
60
+ child.on("exit", (code) => {
61
+ exitedEarly = true;
62
+ trace("dispatch", `rails-lifecycle: child exited early (code=${code}); recent output: ${tail.join("").slice(-500)}`);
63
+ });
64
+ const readyTimeoutMs = input.readyTimeoutMs ?? DEFAULT_READY_TIMEOUT_MS;
65
+ const ready = await waitForReady(host, port, readyTimeoutMs, () => exitedEarly);
66
+ if (!ready) {
67
+ child.kill("SIGTERM");
68
+ const lastOutput = tail.join("").slice(-500);
69
+ throw new Error(`Rails server at ${url} did not become ready within ${readyTimeoutMs}ms` +
70
+ (exitedEarly ? ` (child exited early)` : "") +
71
+ `; recent output: ${lastOutput}`);
72
+ }
73
+ trace("dispatch", `rails-lifecycle: server reachable at ${url}`);
74
+ const shutdownGraceMs = input.shutdownGraceMs ?? DEFAULT_SHUTDOWN_GRACE_MS;
75
+ return {
76
+ child,
77
+ url,
78
+ async stop() {
79
+ if (exitedEarly)
80
+ return;
81
+ trace("dispatch", `rails-lifecycle: stopping ${url}`);
82
+ child.kill("SIGTERM");
83
+ const exit = new Promise((resolve) => {
84
+ if (child.exitCode !== null) {
85
+ resolve();
86
+ }
87
+ else {
88
+ child.on("exit", () => resolve());
89
+ }
90
+ });
91
+ const timeout = sleep(shutdownGraceMs).then(() => {
92
+ if (child.exitCode === null) {
93
+ trace("dispatch", `rails-lifecycle: SIGTERM did not exit in ${shutdownGraceMs}ms; SIGKILL`);
94
+ child.kill("SIGKILL");
95
+ }
96
+ });
97
+ await Promise.race([exit, timeout]);
98
+ },
99
+ };
100
+ }
101
+ export async function waitForReady(host, port, timeoutMs, childExitedEarly) {
102
+ const url = `http://${host}:${port}/`;
103
+ const deadline = Date.now() + timeoutMs;
104
+ while (Date.now() < deadline) {
105
+ if (childExitedEarly?.())
106
+ return false;
107
+ try {
108
+ const res = await fetch(url, { signal: AbortSignal.timeout(2_000) });
109
+ // Any HTTP response (even 404) means Rails is up. Network/connection
110
+ // errors throw; we keep polling.
111
+ if (res.status < 500)
112
+ return true;
113
+ }
114
+ catch {
115
+ // ECONNREFUSED, EHOSTUNREACH, AbortError — not ready, keep polling.
116
+ }
117
+ await sleep(1_000);
118
+ }
119
+ return false;
120
+ }
121
+ async function resolveHostPort(input) {
122
+ if (input.host !== undefined && input.port !== undefined) {
123
+ return { host: input.host, port: input.port };
124
+ }
125
+ // Read from the generated rails dir's .env (which mirrors substrate's
126
+ // .env via the rails worker's verbatim copy).
127
+ const envPath = join(input.outDir, ".env");
128
+ const env = await readDotenv(envPath);
129
+ const host = input.host ?? env["HOST"] ?? "0.0.0.0";
130
+ const portStr = env["PORT"];
131
+ const port = input.port ?? (portStr ? Number.parseInt(portStr, 10) : 3000);
132
+ if (Number.isNaN(port))
133
+ throw new Error(`rails-lifecycle: PORT in ${envPath} is not a number: ${portStr}`);
134
+ return { host, port };
135
+ }
136
+ async function runMiseStep(cwd, args, timeoutMs, label) {
137
+ await new Promise((resolveStep, rejectStep) => {
138
+ const child = spawn("mise", ["exec", "--", ...args], {
139
+ cwd,
140
+ env: scrubbedEnv(),
141
+ stdio: ["ignore", "pipe", "pipe"],
142
+ });
143
+ const out = [];
144
+ child.stdout?.on("data", (c) => out.push(c.toString("utf8")));
145
+ child.stderr?.on("data", (c) => out.push(c.toString("utf8")));
146
+ const timer = setTimeout(() => child.kill("SIGTERM"), timeoutMs);
147
+ child.on("exit", (code) => {
148
+ clearTimeout(timer);
149
+ if (code === 0)
150
+ resolveStep();
151
+ else
152
+ rejectStep(new Error(`${label} exited ${code}: ${out.join("").slice(-800)}`));
153
+ });
154
+ child.on("error", (err) => {
155
+ clearTimeout(timer);
156
+ rejectStep(err);
157
+ });
158
+ });
159
+ }
160
+ async function readDotenv(path) {
161
+ let raw;
162
+ try {
163
+ raw = await readFile(path, "utf8");
164
+ }
165
+ catch {
166
+ return {};
167
+ }
168
+ const out = {};
169
+ for (const line of raw.split("\n")) {
170
+ const trimmed = line.trim();
171
+ if (!trimmed || trimmed.startsWith("#"))
172
+ continue;
173
+ const eq = trimmed.indexOf("=");
174
+ if (eq < 1)
175
+ continue;
176
+ const key = trimmed.slice(0, eq).trim();
177
+ const valueRaw = trimmed.slice(eq + 1).trim();
178
+ const value = valueRaw.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
179
+ if (key && value)
180
+ out[key] = value;
181
+ }
182
+ return out;
183
+ }
184
+ //# sourceMappingURL=rails-lifecycle.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rails-lifecycle.js","sourceRoot":"","sources":["../src/rails-lifecycle.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Entity, RenamePair } from "./agents/types.js";
2
+ export type OverrideOutcome = {
3
+ kind: "changed";
4
+ from: string;
5
+ was: string;
6
+ to: string;
7
+ } | {
8
+ kind: "noop";
9
+ from: string;
10
+ to: string;
11
+ } | {
12
+ kind: "unmatched";
13
+ from: string;
14
+ to: string;
15
+ };
16
+ export type ApplyOverridesResult = {
17
+ plan: RenamePair[];
18
+ outcomes: OverrideOutcome[];
19
+ };
20
+ export declare function parseRenamePair(raw: string | undefined): RenamePair | null;
21
+ export declare function applyRenameOverrides(plan: readonly RenamePair[], overrides: readonly RenamePair[]): ApplyOverridesResult;
22
+ export declare function syncEntityNames(entities: readonly Entity[], outcomes: readonly OverrideOutcome[]): readonly Entity[];
23
+ //# sourceMappingURL=rename-overrides.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-overrides.d.ts","sourceRoot":"","sources":["../src/rename-overrides.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAO5D,MAAM,MAAM,eAAe,GACvB;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpD,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAKF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAQ1E;AAOD,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,SAAS,UAAU,EAAE,EAC3B,SAAS,EAAE,SAAS,UAAU,EAAE,GAC/B,oBAAoB,CAiBtB;AAQD,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,QAAQ,EAAE,SAAS,eAAe,EAAE,GACnC,SAAS,MAAM,EAAE,CAUnB"}
@@ -0,0 +1,58 @@
1
+ // Parse a single `--rename From=To` value. Splits on the first `=` only;
2
+ // returns null for malformed input (missing flag value, empty side) so the
3
+ // caller can warn and skip rather than push a junk pair into the plan.
4
+ export function parseRenamePair(raw) {
5
+ if (raw === undefined)
6
+ return null;
7
+ const eq = raw.indexOf("=");
8
+ if (eq <= 0)
9
+ return null;
10
+ const from = raw.slice(0, eq).trim();
11
+ const to = raw.slice(eq + 1).trim();
12
+ if (!from || !to)
13
+ return null;
14
+ return { from, to };
15
+ }
16
+ // Merge manual overrides onto the planner's rename plan. Semantics are
17
+ // "change a planned target": an override keys on the substrate token (`from`)
18
+ // and replaces the planner's chosen target (`to`). Overrides whose `from`
19
+ // matches no planned rename are reported as `unmatched` and dropped — we don't
20
+ // silently invent new renames. Later overrides for the same `from` win.
21
+ export function applyRenameOverrides(plan, overrides) {
22
+ const merged = plan.map((p) => ({ ...p }));
23
+ const outcomes = [];
24
+ for (const override of overrides) {
25
+ const target = merged.find((p) => p.from === override.from);
26
+ if (!target) {
27
+ outcomes.push({ kind: "unmatched", from: override.from, to: override.to });
28
+ continue;
29
+ }
30
+ if (target.to === override.to) {
31
+ outcomes.push({ kind: "noop", from: override.from, to: override.to });
32
+ continue;
33
+ }
34
+ outcomes.push({ kind: "changed", from: override.from, was: target.to, to: override.to });
35
+ target.to = override.to;
36
+ }
37
+ return { plan: merged, outcomes };
38
+ }
39
+ // Keep entity names in step with rename-plan overrides. The planner names each
40
+ // entity after its rename target (e.g. it emits both `Shopkeeper -> Monitor`
41
+ // and an entity `Monitor` that `replaces` Shopkeeper), so a `--rename` that
42
+ // changes the target must also rename the entity or the report contradicts its
43
+ // own rename plan. Only entities whose name still matches the planner's old
44
+ // target are touched — an entity deliberately named differently is left alone.
45
+ export function syncEntityNames(entities, outcomes) {
46
+ const changes = new Map();
47
+ for (const o of outcomes) {
48
+ if (o.kind === "changed")
49
+ changes.set(o.from, { was: o.was, to: o.to });
50
+ }
51
+ if (changes.size === 0)
52
+ return entities;
53
+ return entities.map((e) => {
54
+ const change = changes.get(e.replaces);
55
+ return change && e.name === change.was ? { ...e, name: change.to } : e;
56
+ });
57
+ }
58
+ //# sourceMappingURL=rename-overrides.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rename-overrides.js","sourceRoot":"","sources":["../src/rename-overrides.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ import type { Platform, PlatformDetail } from "./agents/types.js";
2
+ import type { RepairAttempt } from "./report/model.js";
3
+ import type { RepairLayer } from "./agents/repair.js";
4
+ export type RevalidateResult = Pick<PlatformDetail, "layer1" | "layer2">;
5
+ export type RepairLoopDeps = {
6
+ repair: (platform: Platform, layer: RepairLayer, detail: PlatformDetail) => Promise<{
7
+ action: string;
8
+ }>;
9
+ revalidate: (platform: Platform) => Promise<RevalidateResult>;
10
+ };
11
+ export type RepairLoopInput = {
12
+ platforms: readonly PlatformDetail[];
13
+ reviewerPass: boolean;
14
+ maxIterations: number;
15
+ deps: RepairLoopDeps;
16
+ };
17
+ export type RepairLoopResult = {
18
+ platforms: PlatformDetail[];
19
+ attempts: RepairAttempt[];
20
+ overallPass: boolean;
21
+ summary: string;
22
+ };
23
+ export declare const REPAIR_ITERATION_CAP = 5;
24
+ export declare function runRepairLoop(input: RepairLoopInput): Promise<RepairLoopResult>;
25
+ //# sourceMappingURL=repair-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-loop.d.ts","sourceRoot":"","sources":["../src/repair-loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAKtD,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,cAAc,EAAE,QAAQ,GAAG,QAAQ,CAAC,CAAC;AAEzE,MAAM,MAAM,cAAc,GAAG;IAG3B,MAAM,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAAE,cAAc,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAExG,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;CAC/D,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,cAAc,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAMF,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAYtC,wBAAsB,aAAa,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA4BrF"}
@@ -0,0 +1,67 @@
1
+ // The CLAUDE.md hard cap: never iterate more than this regardless of the
2
+ // requested maxIterations.
3
+ export const REPAIR_ITERATION_CAP = 5;
4
+ // Bounded self-repair: while a code-repairable layer is failing, repair the
5
+ // highest-priority failure, re-validate that platform, and record the
6
+ // attempt — until everything passes or the iteration cap is hit. Pure
7
+ // control flow: all I/O (the repair agent, the validators) is injected via
8
+ // deps, so this is unit-testable without the LLM or a device.
9
+ //
10
+ // Scope: Layer 1 (leftover tokens) then Layer 2 (build) are the
11
+ // code-repairable, cheaply re-checkable layers. Layer 3 (vision) and the
12
+ // contract reviewer are surfaced but not auto-repaired — a Layer 3 miss is
13
+ // often environmental (e.g. a first-launch system dialog), not a source bug.
14
+ export async function runRepairLoop(input) {
15
+ const cap = Math.min(input.maxIterations, REPAIR_ITERATION_CAP);
16
+ const platforms = input.platforms.map((p) => ({ ...p }));
17
+ const attempts = [];
18
+ for (let iteration = 1; iteration <= cap; iteration++) {
19
+ const target = nextTarget(platforms);
20
+ if (!target)
21
+ break; // no code-repairable failure remains
22
+ const detail = platforms.find((p) => p.platform === target.platform);
23
+ const { action } = await input.deps.repair(target.platform, target.layer, detail);
24
+ const revalidated = await input.deps.revalidate(target.platform);
25
+ const idx = platforms.findIndex((p) => p.platform === target.platform);
26
+ platforms[idx] = { ...platforms[idx], layer1: revalidated.layer1, layer2: revalidated.layer2 };
27
+ const resolved = target.layer === "layer1" ? revalidated.layer1.pass : revalidated.layer2.pass;
28
+ attempts.push({ iteration, failingLayer: target.layer, platform: target.platform, action, resolved });
29
+ if (computeOverall(platforms, input.reviewerPass))
30
+ break;
31
+ }
32
+ return {
33
+ platforms,
34
+ attempts,
35
+ overallPass: computeOverall(platforms, input.reviewerPass),
36
+ summary: summarize(platforms, input.reviewerPass),
37
+ };
38
+ }
39
+ // Highest-priority code-repairable failure: all Layer 1 misses before any
40
+ // Layer 2 miss (leftover tokens routinely cause the build error, so fixing
41
+ // structure first avoids chasing a downstream symptom).
42
+ function nextTarget(platforms) {
43
+ for (const p of platforms)
44
+ if (!p.layer1.pass)
45
+ return { platform: p.platform, layer: "layer1" };
46
+ for (const p of platforms)
47
+ if (!p.layer2.pass)
48
+ return { platform: p.platform, layer: "layer2" };
49
+ return undefined;
50
+ }
51
+ function computeOverall(platforms, reviewerPass) {
52
+ const layer1And2 = platforms.every((p) => p.layer1.pass && p.layer2.pass);
53
+ const layer3 = platforms.every((p) => p.layer3 === undefined || p.layer3.pass);
54
+ return layer1And2 && layer3 && reviewerPass;
55
+ }
56
+ // Mirrors the judge's one-line summary so the post-repair report reads
57
+ // identically to a first-pass report.
58
+ function summarize(platforms, reviewerPass) {
59
+ const total = platforms.length;
60
+ const l1 = platforms.filter((p) => p.layer1.pass).length;
61
+ const l2 = platforms.filter((p) => p.layer2.pass).length;
62
+ const l3Plats = platforms.filter((p) => p.layer3 !== undefined);
63
+ const l3 = l3Plats.filter((p) => p.layer3.pass).length;
64
+ const l3Summary = l3Plats.length > 0 ? `Layer 3 ${l3}/${l3Plats.length} pass` : "Layer 3 skipped";
65
+ return `Layer 1 ${l1}/${total} pass · Layer 2 ${l2}/${total} pass · ${l3Summary} · reviewer ${reviewerPass ? "PASS" : "FAIL"}`;
66
+ }
67
+ //# sourceMappingURL=repair-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repair-loop.js","sourceRoot":"","sources":["../src/repair-loop.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
1
+ import type { DomainSpec, JudgeResult, ReviewerResult } from "../agents/types.js";
2
+ import type { RepairAttempt, RunReport } from "./model.js";
3
+ export type ReportFormat = "html" | "json" | "both";
4
+ export type BuildRunReportInput = {
5
+ spec: string;
6
+ domain: DomainSpec;
7
+ judge: JudgeResult;
8
+ reviewer: ReviewerResult;
9
+ agentVersion: string;
10
+ judgeModel: string;
11
+ visualLevel: 0 | 1 | 2;
12
+ startedAt: number;
13
+ finishedAt: number;
14
+ repairAttempts?: readonly RepairAttempt[];
15
+ };
16
+ export declare function buildRunReport(input: BuildRunReportInput): RunReport;
17
+ export type WriteReportOptions = {
18
+ dir: string;
19
+ format?: ReportFormat;
20
+ embed?: boolean;
21
+ };
22
+ export type ReportPaths = {
23
+ jsonPath?: string;
24
+ htmlPath?: string;
25
+ };
26
+ export declare function writeReport(report: RunReport, options: WriteReportOptions): Promise<ReportPaths>;
27
+ export declare function collectScreenshotPaths(report: RunReport): string[];
28
+ //# sourceMappingURL=collect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.d.ts","sourceRoot":"","sources":["../../src/report/collect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,KAAK,EAAY,aAAa,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAErE,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,cAAc,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C,CAAC;AAIF,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,SAAS,CAqCpE;AAED,MAAM,MAAM,kBAAkB,GAAG;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,wBAAsB,WAAW,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,kBAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAqBtG;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,EAAE,CAgBlE"}
@@ -0,0 +1,117 @@
1
+ import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { basename, isAbsolute, join, resolve } from "node:path";
3
+ import { renderReport } from "./render.js";
4
+ // Pure assembly: fold the run's pieces into the single RunReport
5
+ // aggregate. No I/O — writeReport handles disk.
6
+ export function buildRunReport(input) {
7
+ return {
8
+ meta: {
9
+ spec: input.spec,
10
+ slug: input.domain.slug,
11
+ displayName: input.domain.displayName,
12
+ agentVersion: input.agentVersion,
13
+ judgeModel: input.judgeModel,
14
+ visualLevel: input.visualLevel,
15
+ startedAt: new Date(input.startedAt).toISOString(),
16
+ finishedAt: new Date(input.finishedAt).toISOString(),
17
+ durationMs: input.finishedAt - input.startedAt,
18
+ },
19
+ overallPass: input.judge.overallPass,
20
+ summary: input.judge.summary,
21
+ platforms: input.judge.platforms ?? [],
22
+ reviewer: {
23
+ contractParity: input.reviewer.contractParity,
24
+ diffs: input.reviewer.diffs,
25
+ },
26
+ domain: {
27
+ renamePlan: input.domain.renamePlan.map((r) => ({ from: r.from, to: r.to })),
28
+ entities: input.domain.entities.map((e) => ({
29
+ name: e.name,
30
+ replaces: e.replaces,
31
+ fields: e.fields.map((f) => ({
32
+ name: f.name,
33
+ type: f.type,
34
+ ...(f.references !== undefined ? { references: f.references } : {}),
35
+ })),
36
+ ...(e.states !== undefined ? { states: e.states } : {}),
37
+ })),
38
+ },
39
+ ...(input.repairAttempts && input.repairAttempts.length > 0
40
+ ? { repairAttempts: input.repairAttempts }
41
+ : {}),
42
+ };
43
+ }
44
+ export async function writeReport(report, options) {
45
+ const format = options.format ?? "both";
46
+ const embed = options.embed ?? true;
47
+ await mkdir(options.dir, { recursive: true });
48
+ const paths = {};
49
+ if (format === "json" || format === "both") {
50
+ const jsonPath = join(options.dir, "report.json");
51
+ await writeFile(jsonPath, `${JSON.stringify(report, null, 2)}\n`, "utf8");
52
+ paths.jsonPath = jsonPath;
53
+ }
54
+ if (format === "html" || format === "both") {
55
+ const assets = await resolveAssets(report, options.dir, embed);
56
+ const htmlPath = join(options.dir, "validation-report.html");
57
+ await writeFile(htmlPath, renderReport(report, assets), "utf8");
58
+ paths.htmlPath = htmlPath;
59
+ }
60
+ return paths;
61
+ }
62
+ // Every screenshot file path referenced anywhere in the report,
63
+ // de-duplicated and in stable order.
64
+ export function collectScreenshotPaths(report) {
65
+ const seen = new Set();
66
+ const add = (p) => {
67
+ if (p && !seen.has(p))
68
+ seen.add(p);
69
+ };
70
+ for (const platform of report.platforms) {
71
+ const l3 = platform.layer3;
72
+ if (!l3)
73
+ continue;
74
+ add(l3.screenshotPath);
75
+ const s2 = l3.stage2;
76
+ if (s2) {
77
+ add(s2.representativeScreenshot);
78
+ for (const s of s2.screenshots)
79
+ add(s);
80
+ }
81
+ }
82
+ return [...seen];
83
+ }
84
+ // Turn screenshot file paths into render-ready <img src> values. With
85
+ // embed=true each PNG becomes a base64 data: URI (single self-contained
86
+ // file). With embed=false PNGs are copied to <dir>/report-assets/ and
87
+ // referenced by relative path. Unreadable paths are skipped — the
88
+ // renderer shows a placeholder for any path missing from the map.
89
+ async function resolveAssets(report, dir, embed) {
90
+ const paths = collectScreenshotPaths(report);
91
+ if (paths.length === 0)
92
+ return {};
93
+ const map = {};
94
+ const assetsDir = join(dir, "report-assets");
95
+ if (!embed)
96
+ await mkdir(assetsDir, { recursive: true });
97
+ await Promise.all(paths.map(async (p) => {
98
+ const abs = isAbsolute(p) ? p : resolve(process.cwd(), p);
99
+ try {
100
+ if (embed) {
101
+ const buf = await readFile(abs);
102
+ map[p] = `data:image/png;base64,${buf.toString("base64")}`;
103
+ }
104
+ else {
105
+ const name = basename(abs);
106
+ await copyFile(abs, join(assetsDir, name));
107
+ map[p] = `report-assets/${name}`;
108
+ }
109
+ }
110
+ catch {
111
+ // Leave unmapped — renderer renders a "screenshot unavailable"
112
+ // placeholder rather than a broken image.
113
+ }
114
+ }));
115
+ return map;
116
+ }
117
+ //# sourceMappingURL=collect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"collect.js","sourceRoot":"","sources":["../../src/report/collect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import type { PlatformDetail } from "../agents/types.js";
2
+ export type RunReport = {
3
+ meta: RunMeta;
4
+ overallPass: boolean;
5
+ summary: string;
6
+ platforms: readonly PlatformDetail[];
7
+ reviewer: {
8
+ contractParity: "pass" | "fail";
9
+ diffs: readonly string[];
10
+ };
11
+ domain: {
12
+ renamePlan: readonly {
13
+ from: string;
14
+ to: string;
15
+ }[];
16
+ entities: readonly RunReportEntity[];
17
+ };
18
+ repairAttempts?: readonly RepairAttempt[];
19
+ };
20
+ export type RunMeta = {
21
+ spec: string;
22
+ slug: string;
23
+ displayName: string;
24
+ agentVersion: string;
25
+ judgeModel: string;
26
+ visualLevel: 0 | 1 | 2;
27
+ startedAt: string;
28
+ finishedAt: string;
29
+ durationMs: number;
30
+ };
31
+ export type RunReportEntity = {
32
+ name: string;
33
+ replaces: string;
34
+ fields: readonly {
35
+ name: string;
36
+ type: string;
37
+ references?: string;
38
+ }[];
39
+ states?: readonly string[];
40
+ };
41
+ export type RepairAttempt = {
42
+ iteration: number;
43
+ failingLayer: "layer1" | "layer2" | "layer3" | "reviewer";
44
+ platform?: "rails" | "ios" | "android";
45
+ action: string;
46
+ resolved: boolean;
47
+ };
48
+ export type AssetMap = Record<string, string>;
49
+ //# sourceMappingURL=model.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAMzD,MAAM,MAAM,SAAS,GAAG;IACtB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,OAAO,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,cAAc,EAAE,CAAC;IACrC,QAAQ,EAAE;QACR,cAAc,EAAE,MAAM,GAAG,MAAM,CAAC;QAChC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;KAC1B,CAAC;IACF,MAAM,EAAE;QACN,UAAU,EAAE,SAAS;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,EAAE,EAAE,MAAM,CAAA;SAAE,EAAE,CAAC;QACpD,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;KACtC,CAAC;IAGF,cAAc,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,OAAO,GAAG;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACvE,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,QAAQ,GAAG,UAAU,CAAC;IAC1D,QAAQ,CAAC,EAAE,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,OAAO,CAAC;CACnB,CAAC;AAMF,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=model.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model.js","sourceRoot":"","sources":["../../src/report/model.ts"],"names":[],"mappings":""}
@@ -0,0 +1,3 @@
1
+ import type { AssetMap, RunReport } from "./model.js";
2
+ export declare function renderReport(report: RunReport, assets?: AssetMap): string;
3
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/report/render.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAOtD,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,GAAE,QAAa,GAAG,MAAM,CA4B7E"}