nativeapptemplate-agent 0.1.2 → 0.2.1

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 (108) hide show
  1. package/CLAUDE.md +10 -8
  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 +167 -29
  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 +31 -0
  30. package/dist/mobile.d.ts.map +1 -0
  31. package/dist/mobile.js +179 -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/discover.js +1 -1
  69. package/dist/validation/discover.js.map +1 -1
  70. package/dist/validation/index.d.ts +8 -2
  71. package/dist/validation/index.d.ts.map +1 -1
  72. package/dist/validation/index.js +4 -1
  73. package/dist/validation/index.js.map +1 -1
  74. package/dist/validation/launch.d.ts +10 -0
  75. package/dist/validation/launch.d.ts.map +1 -1
  76. package/dist/validation/launch.js +127 -12
  77. package/dist/validation/launch.js.map +1 -1
  78. package/dist/validation/layer1.d.ts.map +1 -1
  79. package/dist/validation/layer1.js +12 -4
  80. package/dist/validation/layer1.js.map +1 -1
  81. package/dist/validation/layer2.js +1 -1
  82. package/dist/validation/layer2.js.map +1 -1
  83. package/dist/validation/scenarios/queue.d.ts +12 -0
  84. package/dist/validation/scenarios/queue.d.ts.map +1 -0
  85. package/dist/validation/scenarios/queue.js +216 -0
  86. package/dist/validation/scenarios/queue.js.map +1 -0
  87. package/dist/validation/stage1.d.ts +2 -0
  88. package/dist/validation/stage1.d.ts.map +1 -1
  89. package/dist/validation/stage1.js +2 -0
  90. package/dist/validation/stage1.js.map +1 -1
  91. package/dist/validation/stage2-judge.d.ts +23 -0
  92. package/dist/validation/stage2-judge.d.ts.map +1 -0
  93. package/dist/validation/stage2-judge.js +225 -0
  94. package/dist/validation/stage2-judge.js.map +1 -0
  95. package/dist/validation/stage2.d.ts +74 -0
  96. package/dist/validation/stage2.d.ts.map +1 -0
  97. package/dist/validation/stage2.js +328 -0
  98. package/dist/validation/stage2.js.map +1 -0
  99. package/dist/validation/visual-judge.d.ts +37 -0
  100. package/dist/validation/visual-judge.d.ts.map +1 -1
  101. package/dist/validation/visual-judge.js +100 -16
  102. package/dist/validation/visual-judge.js.map +1 -1
  103. package/dist/version.d.ts +2 -0
  104. package/dist/version.d.ts.map +1 -0
  105. package/dist/version.js +17 -0
  106. package/dist/version.js.map +1 -0
  107. package/package.json +6 -3
  108. package/scripts/ruby/rename.rb +7 -3
@@ -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"}
@@ -0,0 +1,242 @@
1
+ import { REPORT_CSS } from "./theme.js";
2
+ // Pure: RunReport (+ a resolved screenshot AssetMap) -> a complete,
3
+ // self-contained HTML document string. No filesystem, no network, no
4
+ // clock — every dynamic value comes from the inputs, so the output is
5
+ // deterministic and golden-file testable.
6
+ export function renderReport(report, assets = {}) {
7
+ const body = [
8
+ head(report),
9
+ gates(report),
10
+ matrix(report),
11
+ layer1Section(report),
12
+ layer2Section(report),
13
+ layer3Section(report, assets),
14
+ reviewerSection(report),
15
+ repairSection(report),
16
+ domainSection(report),
17
+ footer(report),
18
+ ].join("\n");
19
+ return `<!doctype html>
20
+ <html lang="en">
21
+ <head>
22
+ <meta charset="utf-8">
23
+ <meta name="viewport" content="width=device-width, initial-scale=1">
24
+ <title>Validation report — ${esc(report.meta.displayName)}</title>
25
+ <style>${REPORT_CSS}</style>
26
+ </head>
27
+ <body>
28
+ <div class="wrap">
29
+ ${body}
30
+ </div>
31
+ </body>
32
+ </html>`;
33
+ }
34
+ function head(report) {
35
+ const m = report.meta;
36
+ const badge = report.overallPass
37
+ ? `<span class="badge pass">✓ Pass</span>`
38
+ : `<span class="badge fail">✗ Fail</span>`;
39
+ const visual = m.visualLevel === 0 ? "off" : `level ${m.visualLevel}`;
40
+ return `<header class="report-head">
41
+ ${badge}
42
+ <h1>${esc(m.displayName)}</h1>
43
+ <p class="spec">spec: <b>${esc(m.spec)}</b></p>
44
+ <div class="meta">
45
+ <span>slug: ${esc(m.slug)}</span>
46
+ <span>agent v${esc(m.agentVersion)}</span>
47
+ <span>judge: ${esc(m.judgeModel)}</span>
48
+ <span>visual: ${visual}</span>
49
+ <span>${fmtDuration(m.durationMs)}</span>
50
+ <span>${esc(m.finishedAt)}</span>
51
+ </div>
52
+ </header>`;
53
+ }
54
+ function computeGates(report) {
55
+ const plats = report.platforms;
56
+ if (plats.length === 0)
57
+ return null;
58
+ const l1 = plats.filter((p) => p.layer1.pass).length;
59
+ const l2 = plats.filter((p) => p.layer2.pass).length;
60
+ const l3plats = plats.filter((p) => p.layer3 !== undefined);
61
+ const l3 = l3plats.filter((p) => p.layer3.pass).length;
62
+ const reviewerPass = report.reviewer.contractParity === "pass";
63
+ return [
64
+ gateOf("Layer 1 · structural", l1, plats.length),
65
+ gateOf("Layer 2 · runtime", l2, plats.length),
66
+ l3plats.length > 0
67
+ ? gateOf("Layer 3 · semantic", l3, l3plats.length)
68
+ : { label: "Layer 3 · semantic", value: "skipped", cls: "muted" },
69
+ { label: "Reviewer · contract", value: reviewerPass ? "Pass" : "Fail", cls: reviewerPass ? "pass" : "fail" },
70
+ ];
71
+ }
72
+ function gateOf(label, pass, total) {
73
+ return { label, value: `${pass}/${total} pass`, cls: pass === total ? "pass" : "fail" };
74
+ }
75
+ function gates(report) {
76
+ const gs = computeGates(report);
77
+ const cards = gs
78
+ ? gs.map((g) => `<div class="gate ${g.cls}"><div class="label">${esc(g.label)}</div><div class="value">${esc(g.value)}</div></div>`).join("")
79
+ // Stub / detail-less runs: fall back to the one-line summary.
80
+ : `<div class="gate ${report.overallPass ? "pass" : "fail"}"><div class="label">Summary</div><div class="value" style="font-size:15px">${esc(report.summary)}</div></div>`;
81
+ return `<section><h2>Gates</h2><div class="gates">${cards}</div></section>`;
82
+ }
83
+ function matrix(report) {
84
+ if (report.platforms.length === 0)
85
+ return "";
86
+ const rows = report.platforms
87
+ .map((p) => {
88
+ const l3 = p.platform === "rails" ? markNa() : p.layer3 ? mark(p.layer3.pass) : markNa();
89
+ return `<tr><td>${esc(p.platform)}</td><td>${mark(p.layer1.pass)}</td><td>${mark(p.layer2.pass)}</td><td>${l3}</td></tr>`;
90
+ })
91
+ .join("");
92
+ return `<section><h2>Platform × layer</h2>
93
+ <table class="matrix">
94
+ <thead><tr><th>Platform</th><th>Layer 1</th><th>Layer 2</th><th>Layer 3</th></tr></thead>
95
+ <tbody>${rows}</tbody>
96
+ </table></section>`;
97
+ }
98
+ function layer1Section(report) {
99
+ if (report.platforms.length === 0)
100
+ return "";
101
+ const cards = report.platforms.map((p) => {
102
+ const findings = p.layer1.findings;
103
+ const inner = findings.length === 0
104
+ ? `<p class="empty">No leftover substrate tokens.</p>`
105
+ : `<table class="findings">
106
+ <thead><tr><th>Token</th><th>Location</th><th>Line</th></tr></thead>
107
+ <tbody>${findings.map((f) => `<tr><td><code>${esc(f.token)}</code></td><td>${esc(f.file)}:${f.line}</td><td><code>${esc(f.text)}</code></td></tr>`).join("")}</tbody>
108
+ </table>`;
109
+ return card(p.platform, p.layer1.pass, inner);
110
+ }).join("");
111
+ return `<section><h2>Layer 1 — structural (leftover token scan)</h2>${cards}</section>`;
112
+ }
113
+ function layer2Section(report) {
114
+ if (report.platforms.length === 0)
115
+ return "";
116
+ const cards = report.platforms.map((p) => {
117
+ const l2 = p.layer2;
118
+ const kv = `<p class="kv">command: <b>${esc(l2.command)}</b><br>mode: <b>${esc(l2.mode)}</b> · exit: <b>${l2.exitCode === null ? "—" : l2.exitCode}</b> · <b>${fmtDuration(l2.durationMs)}</b></p>`;
119
+ const stderr = l2.stderrTail && !l2.pass
120
+ ? `<details><summary>stderr tail</summary><pre>${esc(l2.stderrTail)}</pre></details>`
121
+ : "";
122
+ return card(p.platform, l2.pass, kv + stderr);
123
+ }).join("");
124
+ return `<section><h2>Layer 2 — runtime (toolchain build/boot)</h2>${cards}</section>`;
125
+ }
126
+ function layer3Section(report, assets) {
127
+ const plats = report.platforms.filter((p) => p.layer3 !== undefined);
128
+ if (plats.length === 0)
129
+ return "";
130
+ const cards = plats.map((p) => {
131
+ const l3 = p.layer3;
132
+ const parts = [];
133
+ if (l3.error)
134
+ parts.push(`<p class="empty">error: ${esc(l3.error)}</p>`);
135
+ if (l3.screenshotPath)
136
+ parts.push(`<div class="shots">${shot(l3.screenshotPath, "home screen", assets)}</div>`);
137
+ if (l3.scores && l3.scores.length > 0) {
138
+ parts.push(scoreTable("Stage 1 rubric (median of 3 samples)", l3.scores));
139
+ }
140
+ if (l3.stage2) {
141
+ const s2 = l3.stage2;
142
+ parts.push(`<p class="kv" style="margin-top:14px">Stage 2: <b>${esc(s2.scenarioName)}</b> · steps <b>${s2.stepsPassed}/${s2.stepCount}</b></p>`);
143
+ if (s2.error)
144
+ parts.push(`<p class="empty">error: ${esc(s2.error)}</p>`);
145
+ if (s2.screenshots.length > 0) {
146
+ parts.push(`<div class="shots">${s2.screenshots.map((sp) => shot(sp, capOf(sp), assets)).join("")}</div>`);
147
+ }
148
+ if (s2.layer3Scores && s2.layer3Scores.length > 0) {
149
+ parts.push(scoreTable("Stage 2 rubric (post-toggle screen)", s2.layer3Scores));
150
+ }
151
+ }
152
+ return card(p.platform, l3.pass, parts.join("\n"));
153
+ }).join("");
154
+ return `<section><h2>Layer 3 — semantic (Opus 4.7 vision judge)</h2>${cards}</section>`;
155
+ }
156
+ function reviewerSection(report) {
157
+ const pass = report.reviewer.contractParity === "pass";
158
+ const diffs = report.reviewer.diffs;
159
+ const inner = diffs.length === 0
160
+ ? `<p class="empty">No contract drift across Rails ↔ iOS ↔ Android.</p>`
161
+ : `<details open><summary>${diffs.length} contract difference(s)</summary><pre>${esc(diffs.join("\n"))}</pre></details>`;
162
+ return `<section><h2>Reviewer — contract parity</h2>${card("Rails ↔ iOS ↔ Android", pass, inner)}</section>`;
163
+ }
164
+ function repairSection(report) {
165
+ const attempts = report.repairAttempts;
166
+ if (!attempts || attempts.length === 0)
167
+ return "";
168
+ const rows = attempts.map((a) => `<tr><td>${a.iteration}</td><td>${esc(a.failingLayer)}${a.platform ? ` (${esc(a.platform)})` : ""}</td><td>${esc(a.action)}</td><td>${a.resolved ? `<span class="mark pass">✓</span>` : `<span class="mark fail">✗</span>`}</td></tr>`).join("");
169
+ return `<section><h2>Self-repair (≤5 iterations)</h2>
170
+ <table class="findings">
171
+ <thead><tr><th>#</th><th>Failing layer</th><th>Action</th><th>Resolved</th></tr></thead>
172
+ <tbody>${rows}</tbody>
173
+ </table></section>`;
174
+ }
175
+ function domainSection(report) {
176
+ const { renamePlan, entities } = report.domain;
177
+ const rename = renamePlan.length === 0
178
+ ? `<p class="empty">No rename pairs.</p>`
179
+ : `<table class="rename"><tbody>${renamePlan.map((r) => `<tr><td><code class="inline">${esc(r.from)}</code></td><td class="arrow">→</td><td><code class="inline">${esc(r.to)}</code></td></tr>`).join("")}</tbody></table>`;
180
+ const ents = entities.length === 0
181
+ ? ""
182
+ : entities.map((e) => {
183
+ const fields = e.fields.map((f) => `<code class="inline">${esc(f.name)}:${esc(f.type)}${f.references ? `→${esc(f.references)}` : ""}</code>`).join(" · ");
184
+ const states = e.states && e.states.length > 0 ? `<br><span class="kv">states: ${e.states.map((s) => esc(s)).join(" ↔ ")}</span>` : "";
185
+ return `<div class="card"><h3>${esc(e.name)} <span class="kv">(replaces ${esc(e.replaces)})</span></h3><p class="kv">${fields || "no fields"}</p>${states}</div>`;
186
+ }).join("");
187
+ return `<section><h2>Domain plan</h2>
188
+ <div class="card"><h3>Rename plan</h3>${rename}</div>
189
+ ${ents}</section>`;
190
+ }
191
+ function footer(report) {
192
+ const visualPrefix = report.meta.visualLevel > 0 ? `NATIVEAPPTEMPLATE_VISUAL=${report.meta.visualLevel} ` : "";
193
+ const cmd = `${visualPrefix}npx nativeapptemplate-agent ${JSON.stringify(report.meta.spec)}`;
194
+ return `<footer>
195
+ <p>Reproduce this run:</p>
196
+ <pre>${esc(cmd)}</pre>
197
+ <p>Raw per-agent logs: <code class="inline">tmp/trace/*.log</code> · Generated by nativeapptemplate-agent v${esc(report.meta.agentVersion)}.</p>
198
+ </footer>`;
199
+ }
200
+ // --- helpers ---
201
+ function card(title, pass, inner) {
202
+ const pill = pass ? `<span class="pill pass">pass</span>` : `<span class="pill fail">fail</span>`;
203
+ return `<div class="card"><h3>${esc(title)} ${pill}</h3>${inner}</div>`;
204
+ }
205
+ function scoreTable(title, scores) {
206
+ const rows = scores.map((s) => `<tr><td><code>${esc(s.criterionId)}</code></td><td>${s.pass ? `<span class="mark pass">✓</span>` : `<span class="mark fail">✗</span>`}</td><td>${esc(s.rationale)}</td></tr>`).join("");
207
+ return `<table class="scores"><thead><tr><th colspan="3">${esc(title)}</th></tr><tr><th>Criterion</th><th>Verdict</th><th>Rationale</th></tr></thead><tbody>${rows}</tbody></table>`;
208
+ }
209
+ function shot(path, caption, assets) {
210
+ const src = assets[path];
211
+ if (!src) {
212
+ return `<div class="shot missing">screenshot unavailable<br><code>${esc(caption)}</code></div>`;
213
+ }
214
+ return `<figure class="shot"><img src="${esc(src)}" alt="${esc(caption)}"><figcaption class="cap">${esc(caption)}</figcaption></figure>`;
215
+ }
216
+ function mark(pass) {
217
+ return pass ? `<span class="mark pass">✓</span>` : `<span class="mark fail">✗</span>`;
218
+ }
219
+ function markNa() {
220
+ return `<span class="mark na">—</span>`;
221
+ }
222
+ function capOf(path) {
223
+ const name = path.split("/").pop() ?? path;
224
+ return name.replace(/\.png$/i, "");
225
+ }
226
+ function fmtDuration(ms) {
227
+ if (ms < 1000)
228
+ return `${ms}ms`;
229
+ const s = ms / 1000;
230
+ if (s < 60)
231
+ return `${s.toFixed(1)}s`;
232
+ const m = Math.floor(s / 60);
233
+ return `${m}m ${Math.round(s % 60)}s`;
234
+ }
235
+ function esc(value) {
236
+ return value
237
+ .replace(/&/g, "&amp;")
238
+ .replace(/</g, "&lt;")
239
+ .replace(/>/g, "&gt;")
240
+ .replace(/"/g, "&quot;");
241
+ }
242
+ //# sourceMappingURL=render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/report/render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const REPORT_CSS = "\n:root {\n --bg: #1f2933;\n --bg-2: #0b69a3;\n --panel: #243441;\n --panel-2: #1b2a38;\n --border: #3e4c59;\n --text: #f5f7fa;\n --muted: #9aa5b1;\n --accent: #40c3f7;\n --accent-2: #2bb0ed;\n --pass: #34d399;\n --fail: #f87171;\n --na: #52606d;\n}\n* { box-sizing: border-box; }\nbody {\n margin: 0;\n font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n background: linear-gradient(160deg, var(--bg) 0%, #14202a 60%, #0e1820 100%);\n color: var(--text);\n line-height: 1.5;\n padding: 32px 20px 80px;\n}\n.wrap { max-width: 1100px; margin: 0 auto; }\na { color: var(--accent); }\nheader.report-head {\n border-bottom: 1px solid var(--border);\n padding-bottom: 20px;\n margin-bottom: 28px;\n}\n.badge {\n display: inline-block;\n font-size: 13px;\n font-weight: 700;\n letter-spacing: 1px;\n padding: 6px 14px;\n border-radius: 20px;\n text-transform: uppercase;\n}\n.badge.pass { background: rgba(52,211,153,0.16); color: var(--pass); border: 1px solid rgba(52,211,153,0.4); }\n.badge.fail { background: rgba(248,113,113,0.16); color: var(--fail); border: 1px solid rgba(248,113,113,0.4); }\nh1 { font-size: 30px; font-weight: 800; letter-spacing: -0.5px; margin: 14px 0 4px; }\n.spec { color: var(--muted); font-size: 16px; margin: 0 0 12px; }\n.spec b { color: var(--text); font-weight: 600; }\n.meta { color: var(--muted); font-size: 13px; font-family: \"SF Mono\", Menlo, monospace; }\n.meta span { margin-right: 16px; white-space: nowrap; }\nsection { margin: 30px 0; }\nh2 {\n font-size: 13px; text-transform: uppercase; letter-spacing: 1.2px;\n color: var(--accent); margin: 0 0 14px; font-weight: 700;\n}\n.gates { display: flex; flex-wrap: wrap; gap: 12px; }\n.gate {\n flex: 1 1 160px; background: var(--panel); border: 1px solid var(--border);\n border-radius: 12px; padding: 14px 16px;\n}\n.gate .label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; }\n.gate .value { font-size: 22px; font-weight: 800; margin-top: 4px; }\n.gate.pass .value { color: var(--pass); }\n.gate.fail .value { color: var(--fail); }\n.gate.muted .value { color: var(--muted); font-size: 15px; font-weight: 600; }\ntable { width: 100%; border-collapse: collapse; font-size: 14px; }\n.matrix th, .matrix td { padding: 10px 12px; text-align: center; border: 1px solid var(--border); }\n.matrix th:first-child, .matrix td:first-child { text-align: left; font-weight: 600; }\n.matrix thead th { background: var(--panel-2); color: var(--muted); font-weight: 600; text-transform: uppercase; font-size: 12px; letter-spacing: 0.5px; }\n.mark { font-weight: 800; font-size: 16px; }\n.mark.pass { color: var(--pass); }\n.mark.fail { color: var(--fail); }\n.mark.na { color: var(--na); }\n.card {\n background: var(--panel); border: 1px solid var(--border);\n border-radius: 12px; padding: 16px 18px; margin-bottom: 14px;\n}\n.card h3 { margin: 0 0 10px; font-size: 16px; display: flex; align-items: center; gap: 10px; }\n.pill { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 10px; text-transform: uppercase; letter-spacing: 0.5px; }\n.pill.pass { background: rgba(52,211,153,0.16); color: var(--pass); }\n.pill.fail { background: rgba(248,113,113,0.16); color: var(--fail); }\n.findings th, .findings td { padding: 7px 10px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: top; }\n.findings th { color: var(--muted); font-weight: 600; }\n.findings code, code.inline { font-family: \"SF Mono\", Menlo, monospace; font-size: 12px; color: var(--accent); }\n.kv { font-family: \"SF Mono\", Menlo, monospace; font-size: 13px; color: var(--muted); }\n.kv b { color: var(--text); font-weight: 600; }\n.empty { color: var(--muted); font-style: italic; font-size: 13px; }\ndetails { margin-top: 10px; }\nsummary { cursor: pointer; color: var(--accent); font-size: 13px; }\npre {\n background: #0d1820; border: 1px solid var(--border); border-radius: 8px;\n padding: 12px; overflow-x: auto; font-size: 12px; color: #cbd2d9; margin: 10px 0 0;\n}\n.shots { display: flex; flex-wrap: wrap; gap: 14px; margin: 12px 0; }\n.shot { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--panel-2); }\n.shot img { display: block; max-width: 240px; height: auto; }\n.shot .cap { font-size: 11px; color: var(--muted); padding: 6px 8px; font-family: \"SF Mono\", Menlo, monospace; }\n.shot.missing { padding: 24px; color: var(--muted); font-size: 12px; font-style: italic; max-width: 240px; }\n.scores th, .scores td { padding: 7px 10px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: top; }\n.scores th { color: var(--muted); font-weight: 600; }\n.rename td { padding: 7px 10px; border-bottom: 1px solid var(--border); font-size: 13px; }\n.rename .arrow { color: var(--muted); padding: 0 8px; }\nfooter { margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--border); color: var(--muted); font-size: 13px; }\nfooter pre { color: var(--text); }\n@media (max-width: 640px) {\n .gate { flex-basis: 100%; }\n .shot img { max-width: 100%; }\n}\n@media print {\n body { background: #fff; color: #111; }\n .card, .gate { break-inside: avoid; }\n}\n";
2
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/report/theme.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,UAAU,0pKA6GtB,CAAC"}
@@ -0,0 +1,115 @@
1
+ // Inline stylesheet for the validation report. Palette matches
2
+ // docs/social-preview.svg (light-blue vivid) for brand coherence.
3
+ // No web fonts, no external assets — the report is a single portable
4
+ // file. Kept as a plain string so render.ts stays pure.
5
+ export const REPORT_CSS = `
6
+ :root {
7
+ --bg: #1f2933;
8
+ --bg-2: #0b69a3;
9
+ --panel: #243441;
10
+ --panel-2: #1b2a38;
11
+ --border: #3e4c59;
12
+ --text: #f5f7fa;
13
+ --muted: #9aa5b1;
14
+ --accent: #40c3f7;
15
+ --accent-2: #2bb0ed;
16
+ --pass: #34d399;
17
+ --fail: #f87171;
18
+ --na: #52606d;
19
+ }
20
+ * { box-sizing: border-box; }
21
+ body {
22
+ margin: 0;
23
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
24
+ background: linear-gradient(160deg, var(--bg) 0%, #14202a 60%, #0e1820 100%);
25
+ color: var(--text);
26
+ line-height: 1.5;
27
+ padding: 32px 20px 80px;
28
+ }
29
+ .wrap { max-width: 1100px; margin: 0 auto; }
30
+ a { color: var(--accent); }
31
+ header.report-head {
32
+ border-bottom: 1px solid var(--border);
33
+ padding-bottom: 20px;
34
+ margin-bottom: 28px;
35
+ }
36
+ .badge {
37
+ display: inline-block;
38
+ font-size: 13px;
39
+ font-weight: 700;
40
+ letter-spacing: 1px;
41
+ padding: 6px 14px;
42
+ border-radius: 20px;
43
+ text-transform: uppercase;
44
+ }
45
+ .badge.pass { background: rgba(52,211,153,0.16); color: var(--pass); border: 1px solid rgba(52,211,153,0.4); }
46
+ .badge.fail { background: rgba(248,113,113,0.16); color: var(--fail); border: 1px solid rgba(248,113,113,0.4); }
47
+ h1 { font-size: 30px; font-weight: 800; letter-spacing: -0.5px; margin: 14px 0 4px; }
48
+ .spec { color: var(--muted); font-size: 16px; margin: 0 0 12px; }
49
+ .spec b { color: var(--text); font-weight: 600; }
50
+ .meta { color: var(--muted); font-size: 13px; font-family: "SF Mono", Menlo, monospace; }
51
+ .meta span { margin-right: 16px; white-space: nowrap; }
52
+ section { margin: 30px 0; }
53
+ h2 {
54
+ font-size: 13px; text-transform: uppercase; letter-spacing: 1.2px;
55
+ color: var(--accent); margin: 0 0 14px; font-weight: 700;
56
+ }
57
+ .gates { display: flex; flex-wrap: wrap; gap: 12px; }
58
+ .gate {
59
+ flex: 1 1 160px; background: var(--panel); border: 1px solid var(--border);
60
+ border-radius: 12px; padding: 14px 16px;
61
+ }
62
+ .gate .label { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; }
63
+ .gate .value { font-size: 22px; font-weight: 800; margin-top: 4px; }
64
+ .gate.pass .value { color: var(--pass); }
65
+ .gate.fail .value { color: var(--fail); }
66
+ .gate.muted .value { color: var(--muted); font-size: 15px; font-weight: 600; }
67
+ table { width: 100%; border-collapse: collapse; font-size: 14px; }
68
+ .matrix th, .matrix td { padding: 10px 12px; text-align: center; border: 1px solid var(--border); }
69
+ .matrix th:first-child, .matrix td:first-child { text-align: left; font-weight: 600; }
70
+ .matrix thead th { background: var(--panel-2); color: var(--muted); font-weight: 600; text-transform: uppercase; font-size: 12px; letter-spacing: 0.5px; }
71
+ .mark { font-weight: 800; font-size: 16px; }
72
+ .mark.pass { color: var(--pass); }
73
+ .mark.fail { color: var(--fail); }
74
+ .mark.na { color: var(--na); }
75
+ .card {
76
+ background: var(--panel); border: 1px solid var(--border);
77
+ border-radius: 12px; padding: 16px 18px; margin-bottom: 14px;
78
+ }
79
+ .card h3 { margin: 0 0 10px; font-size: 16px; display: flex; align-items: center; gap: 10px; }
80
+ .pill { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 10px; text-transform: uppercase; letter-spacing: 0.5px; }
81
+ .pill.pass { background: rgba(52,211,153,0.16); color: var(--pass); }
82
+ .pill.fail { background: rgba(248,113,113,0.16); color: var(--fail); }
83
+ .findings th, .findings td { padding: 7px 10px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: top; }
84
+ .findings th { color: var(--muted); font-weight: 600; }
85
+ .findings code, code.inline { font-family: "SF Mono", Menlo, monospace; font-size: 12px; color: var(--accent); }
86
+ .kv { font-family: "SF Mono", Menlo, monospace; font-size: 13px; color: var(--muted); }
87
+ .kv b { color: var(--text); font-weight: 600; }
88
+ .empty { color: var(--muted); font-style: italic; font-size: 13px; }
89
+ details { margin-top: 10px; }
90
+ summary { cursor: pointer; color: var(--accent); font-size: 13px; }
91
+ pre {
92
+ background: #0d1820; border: 1px solid var(--border); border-radius: 8px;
93
+ padding: 12px; overflow-x: auto; font-size: 12px; color: #cbd2d9; margin: 10px 0 0;
94
+ }
95
+ .shots { display: flex; flex-wrap: wrap; gap: 14px; margin: 12px 0; }
96
+ .shot { border: 1px solid var(--border); border-radius: 10px; overflow: hidden; background: var(--panel-2); }
97
+ .shot img { display: block; max-width: 240px; height: auto; }
98
+ .shot .cap { font-size: 11px; color: var(--muted); padding: 6px 8px; font-family: "SF Mono", Menlo, monospace; }
99
+ .shot.missing { padding: 24px; color: var(--muted); font-size: 12px; font-style: italic; max-width: 240px; }
100
+ .scores th, .scores td { padding: 7px 10px; text-align: left; border-bottom: 1px solid var(--border); font-size: 13px; vertical-align: top; }
101
+ .scores th { color: var(--muted); font-weight: 600; }
102
+ .rename td { padding: 7px 10px; border-bottom: 1px solid var(--border); font-size: 13px; }
103
+ .rename .arrow { color: var(--muted); padding: 0 8px; }
104
+ footer { margin-top: 48px; padding-top: 20px; border-top: 1px solid var(--border); color: var(--muted); font-size: 13px; }
105
+ footer pre { color: var(--text); }
106
+ @media (max-width: 640px) {
107
+ .gate { flex-basis: 100%; }
108
+ .shot img { max-width: 100%; }
109
+ }
110
+ @media print {
111
+ body { background: #fff; color: #111; }
112
+ .card, .gate { break-inside: avoid; }
113
+ }
114
+ `;
115
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/report/theme.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,kEAAkE;AAClE,qEAAqE;AACrE,wDAAwD;AACxD,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6GzB,CAAC"}
package/dist/slug.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export declare function slugToPascal(slug: string): string;
2
2
  export declare function slugToSnake(slug: string): string;
3
+ export declare function isValidSlug(slug: string): boolean;
4
+ export declare function projectNameToSlug(name: string): string;
5
+ export declare function projectNameToDisplayName(name: string): string;
3
6
  //# sourceMappingURL=slug.d.ts.map
@@ -1 +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"}
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;AAMD,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAgBD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAID,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7D"}