nativeapptemplate-agent 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +9 -7
- package/README.md +65 -21
- package/dist/agents/judge.d.ts +8 -0
- package/dist/agents/judge.d.ts.map +1 -1
- package/dist/agents/judge.js +100 -14
- package/dist/agents/judge.js.map +1 -1
- package/dist/agents/repair.d.ts +14 -0
- package/dist/agents/repair.d.ts.map +1 -0
- package/dist/agents/repair.js +103 -0
- package/dist/agents/repair.js.map +1 -0
- package/dist/agents/types.d.ts +34 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/dispatch.d.ts +21 -2
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +250 -14
- package/dist/dispatch.js.map +1 -1
- package/dist/env-bridge.d.ts +17 -0
- package/dist/env-bridge.d.ts.map +1 -0
- package/dist/env-bridge.js +211 -0
- package/dist/env-bridge.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +88 -3
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +5 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +83 -0
- package/dist/mcp.js.map +1 -0
- package/dist/mobile.d.ts +30 -0
- package/dist/mobile.d.ts.map +1 -0
- package/dist/mobile.js +173 -0
- package/dist/mobile.js.map +1 -0
- package/dist/rails-lifecycle.d.ts +16 -0
- package/dist/rails-lifecycle.d.ts.map +1 -0
- package/dist/rails-lifecycle.js +184 -0
- package/dist/rails-lifecycle.js.map +1 -0
- package/dist/rename-overrides.d.ts +23 -0
- package/dist/rename-overrides.d.ts.map +1 -0
- package/dist/rename-overrides.js +58 -0
- package/dist/rename-overrides.js.map +1 -0
- package/dist/repair-loop.d.ts +25 -0
- package/dist/repair-loop.d.ts.map +1 -0
- package/dist/repair-loop.js +67 -0
- package/dist/repair-loop.js.map +1 -0
- package/dist/report/collect.d.ts +28 -0
- package/dist/report/collect.d.ts.map +1 -0
- package/dist/report/collect.js +117 -0
- package/dist/report/collect.js.map +1 -0
- package/dist/report/model.d.ts +49 -0
- package/dist/report/model.d.ts.map +1 -0
- package/dist/report/model.js +2 -0
- package/dist/report/model.js.map +1 -0
- package/dist/report/render.d.ts +3 -0
- package/dist/report/render.d.ts.map +1 -0
- package/dist/report/render.js +242 -0
- package/dist/report/render.js.map +1 -0
- package/dist/report/theme.d.ts +2 -0
- package/dist/report/theme.d.ts.map +1 -0
- package/dist/report/theme.js +115 -0
- package/dist/report/theme.js.map +1 -0
- package/dist/ruby.d.ts.map +1 -1
- package/dist/ruby.js +11 -2
- package/dist/ruby.js.map +1 -1
- package/dist/slug.d.ts +3 -0
- package/dist/slug.d.ts.map +1 -1
- package/dist/slug.js +30 -0
- package/dist/slug.js.map +1 -1
- package/dist/validation/capture.d.ts.map +1 -1
- package/dist/validation/capture.js +19 -2
- package/dist/validation/capture.js.map +1 -1
- package/dist/validation/index.d.ts +6 -0
- package/dist/validation/index.d.ts.map +1 -1
- package/dist/validation/index.js +3 -0
- package/dist/validation/index.js.map +1 -1
- package/dist/validation/launch.d.ts +10 -0
- package/dist/validation/launch.d.ts.map +1 -1
- package/dist/validation/launch.js +103 -5
- package/dist/validation/launch.js.map +1 -1
- package/dist/validation/layer1.d.ts.map +1 -1
- package/dist/validation/layer1.js +12 -4
- package/dist/validation/layer1.js.map +1 -1
- package/dist/validation/scenarios/queue.d.ts +12 -0
- package/dist/validation/scenarios/queue.d.ts.map +1 -0
- package/dist/validation/scenarios/queue.js +204 -0
- package/dist/validation/scenarios/queue.js.map +1 -0
- package/dist/validation/stage2-judge.d.ts +21 -0
- package/dist/validation/stage2-judge.d.ts.map +1 -0
- package/dist/validation/stage2-judge.js +204 -0
- package/dist/validation/stage2-judge.js.map +1 -0
- package/dist/validation/stage2.d.ts +73 -0
- package/dist/validation/stage2.d.ts.map +1 -0
- package/dist/validation/stage2.js +313 -0
- package/dist/validation/stage2.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +17 -0
- package/dist/version.js.map +1 -0
- package/package.json +6 -3
- package/scripts/ruby/rename.rb +18 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,UAAU,EAAE,SAAS,UAAU,EAAE,CAAC;IAClC,eAAe,EAAE,OAAO,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,MAAM,GAAG;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,SAAS,KAAK,EAAE,CAAC;IACzB,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,KAAK,GAAG;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;CACZ,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"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"}
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
import type
|
|
2
|
-
|
|
1
|
+
import { type ReportFormat, type ReportPaths } from "./report/collect.js";
|
|
2
|
+
import type { RunReport } from "./report/model.js";
|
|
3
|
+
import type { JudgeResult, RenamePair } from "./agents/types.js";
|
|
4
|
+
import { type OverrideOutcome } from "./rename-overrides.js";
|
|
5
|
+
export type DispatchReportOptions = {
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
format?: ReportFormat;
|
|
8
|
+
embed?: boolean;
|
|
9
|
+
dir?: string;
|
|
10
|
+
};
|
|
11
|
+
export type DispatchOptions = {
|
|
12
|
+
report?: DispatchReportOptions;
|
|
13
|
+
renameOverrides?: readonly RenamePair[];
|
|
14
|
+
projectName?: string;
|
|
15
|
+
};
|
|
16
|
+
export type DispatchResult = JudgeResult & {
|
|
17
|
+
report: RunReport;
|
|
18
|
+
reportPaths: ReportPaths;
|
|
19
|
+
renameOverrideOutcomes: readonly OverrideOutcome[];
|
|
20
|
+
};
|
|
21
|
+
export declare function dispatch(spec: string, options?: DispatchOptions): Promise<DispatchResult>;
|
|
3
22
|
//# sourceMappingURL=dispatch.d.ts.map
|
package/dist/dispatch.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"AAWA,OAAO,EAA+B,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAMvG,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAA4B,UAAU,EAAgB,MAAM,mBAAmB,CAAC;AACzG,OAAO,EAAyC,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGpG,MAAM,MAAM,qBAAqB,GAAG;IAClC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAG/B,eAAe,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAKxC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG;IACzC,MAAM,EAAE,SAAS,CAAC;IAClB,WAAW,EAAE,WAAW,CAAC;IACzB,sBAAsB,EAAE,SAAS,eAAe,EAAE,CAAC;CACpD,CAAC;AAEF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,cAAc,CAAC,CA+OnG"}
|
package/dist/dispatch.js
CHANGED
|
@@ -5,34 +5,270 @@ import { runIosWorker } from "./agents/workers/ios.js";
|
|
|
5
5
|
import { runAndroidWorker } from "./agents/workers/android.js";
|
|
6
6
|
import { runReviewer } from "./agents/reviewer.js";
|
|
7
7
|
import { runJudge } from "./agents/judge.js";
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import { applyBridgeToProcessEnv, buildBridgeValues, syncGradleProperties } from "./env-bridge.js";
|
|
9
|
+
import { startRails } from "./rails-lifecycle.js";
|
|
10
|
+
import { isStub } from "./stub.js";
|
|
11
|
+
import { trace } from "./trace.js";
|
|
12
|
+
import { buildRunReport, writeReport } from "./report/collect.js";
|
|
13
|
+
import { readPackageVersion } from "./version.js";
|
|
14
|
+
import { runRepairLoop, REPAIR_ITERATION_CAP } from "./repair-loop.js";
|
|
15
|
+
import { runRepair } from "./agents/repair.js";
|
|
16
|
+
import { runLayer1 } from "./validation/layer1.js";
|
|
17
|
+
import { runLayer2 } from "./validation/layer2.js";
|
|
18
|
+
import { applyRenameOverrides, syncEntityNames } from "./rename-overrides.js";
|
|
19
|
+
import { isValidSlug, slugToPascal, projectNameToSlug, projectNameToDisplayName } from "./slug.js";
|
|
20
|
+
export async function dispatch(spec, options = {}) {
|
|
21
|
+
const startedAt = Date.now();
|
|
22
|
+
let domain = await runPlanner(spec);
|
|
23
|
+
// Manual project name (CLI --project-name). Derive the slug + display name
|
|
24
|
+
// from it and override the planner's. The slug drives the output dir, DB
|
|
25
|
+
// prefix, env-bridge token, and the Pascal project name — so it must land
|
|
26
|
+
// before the env-bridge and workers read domain.slug. A name that yields no
|
|
27
|
+
// valid slug is traced and ignored rather than corrupting paths downstream.
|
|
28
|
+
const projectName = options.projectName;
|
|
29
|
+
if (projectName !== undefined) {
|
|
30
|
+
const slug = projectNameToSlug(projectName);
|
|
31
|
+
if (isValidSlug(slug)) {
|
|
32
|
+
const displayName = projectNameToDisplayName(projectName);
|
|
33
|
+
trace("dispatch", `project name: "${projectName}" -> ${slugToPascal(slug)} (slug ${slug}, display "${displayName}")`);
|
|
34
|
+
domain = { ...domain, slug, displayName };
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
trace("dispatch", `project name ignored: "${projectName}" yields no valid slug`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Manual overrides take precedence over the planner's noun choices, but only
|
|
41
|
+
// for renames the planner actually scheduled — unmatched overrides are traced
|
|
42
|
+
// and dropped, not silently added. Apply before workers/reviewer/judge/report
|
|
43
|
+
// so every downstream consumer sees the final plan.
|
|
44
|
+
const renameOverrides = options.renameOverrides ?? [];
|
|
45
|
+
let renameOverrideOutcomes = [];
|
|
46
|
+
if (renameOverrides.length > 0) {
|
|
47
|
+
const merged = applyRenameOverrides(domain.renamePlan, renameOverrides);
|
|
48
|
+
renameOverrideOutcomes = merged.outcomes;
|
|
49
|
+
for (const o of merged.outcomes) {
|
|
50
|
+
if (o.kind === "changed")
|
|
51
|
+
trace("dispatch", `rename override: ${o.from} ${o.was}->${o.to} (overrode planner's pick)`);
|
|
52
|
+
else if (o.kind === "noop")
|
|
53
|
+
trace("dispatch", `rename override: ${o.from}=${o.to} already the planned target — no change`);
|
|
54
|
+
else
|
|
55
|
+
trace("dispatch", `rename override ignored: no planned rename for "${o.from}" (got ${o.from}=${o.to})`);
|
|
56
|
+
}
|
|
57
|
+
// Carry the override into entity names too, so the report's entity cards
|
|
58
|
+
// agree with its rename plan (the planner names entities after their
|
|
59
|
+
// targets). Code generation keys off renamePlan, not entities — this is
|
|
60
|
+
// metadata coherence, not a code-affecting change.
|
|
61
|
+
const entities = syncEntityNames(domain.entities, merged.outcomes);
|
|
62
|
+
domain = { ...domain, renamePlan: merged.plan, entities };
|
|
63
|
+
}
|
|
64
|
+
// Mirror the substrate's NATIVEAPPTEMPLATE_API_* config to the
|
|
65
|
+
// renamed product equivalents (<PRODUCT>_API_*) so the agent's auto-
|
|
66
|
+
// validation runs see the right values without forcing the user to
|
|
67
|
+
// hand-set per-app env vars. See src/env-bridge.ts.
|
|
68
|
+
const bridge = await buildBridgeValues(domain);
|
|
69
|
+
if (Object.keys(bridge.values).length > 0) {
|
|
70
|
+
applyBridgeToProcessEnv(bridge);
|
|
71
|
+
const sync = await syncGradleProperties(bridge);
|
|
72
|
+
const keys = Object.keys(bridge.values).sort().join(", ");
|
|
73
|
+
trace("dispatch", `env-bridge: mirrored ${keys}`);
|
|
74
|
+
switch (sync.mode) {
|
|
75
|
+
case "wrote":
|
|
76
|
+
trace("dispatch", `env-bridge: wrote sentinel block to ${sync.path}`);
|
|
77
|
+
break;
|
|
78
|
+
case "skipped":
|
|
79
|
+
trace("dispatch", `env-bridge: file write skipped (NATIVEAPPTEMPLATE_BRIDGE=off); process.env still injected`);
|
|
80
|
+
break;
|
|
81
|
+
case "dry-run":
|
|
82
|
+
trace("dispatch", `env-bridge: DRY RUN — would write to ${sync.path}:`);
|
|
83
|
+
for (const line of (sync.preview ?? "").split("\n"))
|
|
84
|
+
trace("dispatch", ` ${line}`);
|
|
85
|
+
break;
|
|
86
|
+
case "noop":
|
|
87
|
+
// Same content already in place — nothing to log.
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// No substrate values to mirror — clean up any stale sentinel block
|
|
93
|
+
// from a prior run so we don't leave dangling values behind.
|
|
94
|
+
await syncGradleProperties(bridge);
|
|
95
|
+
trace("dispatch", "env-bridge: no HOST/PORT in $NATIVEAPPTEMPLATE_API/.env; nothing to mirror");
|
|
96
|
+
}
|
|
10
97
|
const [rails, ios, android] = await Promise.all([
|
|
11
98
|
runRailsWorker(domain),
|
|
12
99
|
runIosWorker(domain),
|
|
13
100
|
runAndroidWorker(domain),
|
|
14
101
|
]);
|
|
15
102
|
const reviewer = await runReviewer({ domain, rails, ios, android });
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
|
|
103
|
+
// Visual judging is opt-in via NATIVEAPPTEMPLATE_VISUAL:
|
|
104
|
+
// =1 Stage 1 only — post-launch home screen rubric (substrate-leak
|
|
105
|
+
// detection + render sanity). Adds 60-180s for build mode.
|
|
106
|
+
// =2 Stage 1 + Stage 2 — same plus a scripted-CRUD walk via
|
|
107
|
+
// mobile-mcp (sign up → create resource → toggle state) with
|
|
108
|
+
// Layer 3 scoring on the post-toggle screen. Adds another
|
|
109
|
+
// 60-120s and requires a sim/emulator booted with the app
|
|
110
|
+
// already launched after Stage 1. Off by default.
|
|
111
|
+
const visualLevelRaw = process.env['NATIVEAPPTEMPLATE_VISUAL'] ?? "";
|
|
112
|
+
const visualLevel = visualLevelRaw === "2" ? 2 : visualLevelRaw === "1" ? 1 : 0;
|
|
113
|
+
// Visual levels force build mode so Stage 1 has an artifact to launch;
|
|
114
|
+
// level 0 stays in the cheaper fast mode. The repair loop re-validates
|
|
115
|
+
// Layer 2 in the same mode the judge used.
|
|
116
|
+
const layer2Mode = visualLevel >= 1 ? "build" : "fast";
|
|
117
|
+
const visual = visualLevel >= 1
|
|
22
118
|
? {
|
|
23
119
|
iosDir: resolve(process.cwd(), ios.outDir),
|
|
24
120
|
androidDir: resolve(process.cwd(), android.outDir),
|
|
25
121
|
spec: domain.displayName,
|
|
122
|
+
...(visualLevel >= 2
|
|
123
|
+
? {
|
|
124
|
+
stage2: {
|
|
125
|
+
primaryResourceName: domain.displayName,
|
|
126
|
+
fullName: "Stage Two Test",
|
|
127
|
+
// Unique per-run email so re-runs don't collide on
|
|
128
|
+
// "email already taken". The substrate's signup
|
|
129
|
+
// accepts "+tag" addresses as distinct identities.
|
|
130
|
+
email: `stage2+${Date.now()}@example.com`,
|
|
131
|
+
password: "ValidPassword1!",
|
|
132
|
+
railsOutDir: resolve(process.cwd(), rails.outDir),
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
: {}),
|
|
26
136
|
}
|
|
27
137
|
: undefined;
|
|
28
|
-
|
|
138
|
+
// For NATIVEAPPTEMPLATE_VISUAL=2, Stage 2 needs a live Rails server
|
|
139
|
+
// to talk to (the iOS/Android apps make real HTTP calls during
|
|
140
|
+
// signup, resource create, etc.). Layer 2 build mode validates that
|
|
141
|
+
// rails *boots*; we own keeping it *running* during Stage 2 here.
|
|
142
|
+
// Skip in judge-stub mode (smoke tests) — there's no real judge to
|
|
143
|
+
// serve, so spawning Rails would be useless and require `mise` in
|
|
144
|
+
// the test environment.
|
|
145
|
+
let railsServer;
|
|
146
|
+
if (visualLevel >= 2 && !isStub("judge")) {
|
|
147
|
+
railsServer = await startRails({ outDir: resolve(process.cwd(), rails.outDir) });
|
|
148
|
+
trace("dispatch", `rails-lifecycle: live at ${railsServer.url} for Stage 2`);
|
|
149
|
+
}
|
|
150
|
+
let judge;
|
|
151
|
+
try {
|
|
152
|
+
judge = await runJudge({
|
|
153
|
+
domain,
|
|
154
|
+
rails,
|
|
155
|
+
ios,
|
|
156
|
+
android,
|
|
157
|
+
reviewer,
|
|
158
|
+
layer2Mode,
|
|
159
|
+
...(visual ? { visual } : {}),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
finally {
|
|
163
|
+
if (railsServer) {
|
|
164
|
+
await railsServer.stop().catch((err) => {
|
|
165
|
+
trace("dispatch", `rails-lifecycle: stop() error: ${err instanceof Error ? err.message : String(err)}`);
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Self-repair loop (opt-in via NATIVEAPPTEMPLATE_REPAIR). When the first
|
|
170
|
+
// judge pass fails on a code-repairable layer (Layer 1 leftover tokens or
|
|
171
|
+
// Layer 2 build errors), iterate: patch the failing platform with the
|
|
172
|
+
// repair agent, re-validate, record the attempt — bounded by the cap. Off
|
|
173
|
+
// by default; skipped in stub mode (no real judge/agent to drive).
|
|
174
|
+
let repairAttempts = [];
|
|
175
|
+
const repairMax = parseRepairMax(process.env['NATIVEAPPTEMPLATE_REPAIR']);
|
|
176
|
+
if (repairMax > 0 && !judge.overallPass && judge.platforms && judge.platforms.length > 0 && !isStub("judge")) {
|
|
177
|
+
const workers = { rails, ios, android };
|
|
178
|
+
const deps = {
|
|
179
|
+
repair: async (platform, layer, detail) => {
|
|
180
|
+
const w = workers[platform];
|
|
181
|
+
const outDir = resolve(process.cwd(), w.outDir);
|
|
182
|
+
const detailStr = layer === "layer1"
|
|
183
|
+
? formatFindings(detail.layer1.findings)
|
|
184
|
+
: detail.layer2.stderrTail ?? "(no stderr captured)";
|
|
185
|
+
return runRepair({
|
|
186
|
+
platform,
|
|
187
|
+
outDir,
|
|
188
|
+
layer,
|
|
189
|
+
detail: detailStr,
|
|
190
|
+
...(layer === "layer1" ? { forbiddenTokens: w.renamedFrom } : {}),
|
|
191
|
+
}, domain);
|
|
192
|
+
},
|
|
193
|
+
revalidate: async (platform) => {
|
|
194
|
+
const w = workers[platform];
|
|
195
|
+
const outDir = resolve(process.cwd(), w.outDir);
|
|
196
|
+
const [layer1, layer2] = await Promise.all([
|
|
197
|
+
runLayer1({ projectDir: outDir, forbiddenTokens: w.renamedFrom }),
|
|
198
|
+
runLayer2({ platform, outDir, mode: layer2Mode }),
|
|
199
|
+
]);
|
|
200
|
+
return {
|
|
201
|
+
layer1: { pass: layer1.pass, findings: layer1.findings },
|
|
202
|
+
layer2: {
|
|
203
|
+
pass: layer2.pass,
|
|
204
|
+
command: layer2.command,
|
|
205
|
+
mode: layer2Mode,
|
|
206
|
+
exitCode: layer2.exitCode,
|
|
207
|
+
durationMs: layer2.durationMs,
|
|
208
|
+
...(layer2.stderrTail !== undefined ? { stderrTail: layer2.stderrTail } : {}),
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
trace("dispatch", `self-repair: enabled (cap ${repairMax}); first pass failed — entering loop`);
|
|
214
|
+
const loop = await runRepairLoop({
|
|
215
|
+
platforms: judge.platforms,
|
|
216
|
+
reviewerPass: reviewer.contractParity === "pass",
|
|
217
|
+
maxIterations: repairMax,
|
|
218
|
+
deps,
|
|
219
|
+
});
|
|
220
|
+
repairAttempts = loop.attempts;
|
|
221
|
+
judge = { ...judge, overallPass: loop.overallPass, summary: loop.summary, platforms: loop.platforms };
|
|
222
|
+
const resolved = loop.attempts.filter((a) => a.resolved).length;
|
|
223
|
+
trace("dispatch", `self-repair: ${loop.attempts.length} attempt(s), ${resolved} resolved — overall now ${loop.overallPass ? "PASS" : "FAIL"}`);
|
|
224
|
+
}
|
|
225
|
+
const report = buildRunReport({
|
|
226
|
+
spec,
|
|
29
227
|
domain,
|
|
30
|
-
|
|
31
|
-
ios,
|
|
32
|
-
android,
|
|
228
|
+
judge,
|
|
33
229
|
reviewer,
|
|
34
|
-
|
|
35
|
-
|
|
230
|
+
agentVersion: readPackageVersion(),
|
|
231
|
+
judgeModel: "claude-opus-4-7",
|
|
232
|
+
visualLevel: visualLevel,
|
|
233
|
+
startedAt,
|
|
234
|
+
finishedAt: Date.now(),
|
|
235
|
+
repairAttempts,
|
|
36
236
|
});
|
|
237
|
+
// Default off in stub mode so the test suite never writes into ./out.
|
|
238
|
+
const reportOpts = options.report ?? {};
|
|
239
|
+
const reportEnabled = reportOpts.enabled ?? !isStub("dispatch");
|
|
240
|
+
let reportPaths = {};
|
|
241
|
+
if (reportEnabled) {
|
|
242
|
+
const dir = reportOpts.dir ?? resolve(process.cwd(), "out", domain.slug);
|
|
243
|
+
reportPaths = await writeReport(report, {
|
|
244
|
+
dir,
|
|
245
|
+
...(reportOpts.format !== undefined ? { format: reportOpts.format } : {}),
|
|
246
|
+
...(reportOpts.embed !== undefined ? { embed: reportOpts.embed } : {}),
|
|
247
|
+
});
|
|
248
|
+
const written = Object.values(reportPaths).filter(Boolean);
|
|
249
|
+
if (written.length > 0)
|
|
250
|
+
trace("dispatch", `report: wrote ${written.join(", ")}`);
|
|
251
|
+
}
|
|
252
|
+
return { ...judge, report, reportPaths, renameOverrideOutcomes };
|
|
253
|
+
}
|
|
254
|
+
// NATIVEAPPTEMPLATE_REPAIR control: unset / "0" / "off" / "false" → disabled;
|
|
255
|
+
// "on" / "true" → run up to the cap; a positive integer N → up to min(N, cap).
|
|
256
|
+
function parseRepairMax(raw) {
|
|
257
|
+
if (!raw)
|
|
258
|
+
return 0;
|
|
259
|
+
const lowered = raw.trim().toLowerCase();
|
|
260
|
+
if (lowered === "" || lowered === "0" || lowered === "off" || lowered === "false")
|
|
261
|
+
return 0;
|
|
262
|
+
if (lowered === "on" || lowered === "true")
|
|
263
|
+
return REPAIR_ITERATION_CAP;
|
|
264
|
+
const n = Number.parseInt(lowered, 10);
|
|
265
|
+
if (Number.isFinite(n) && n > 0)
|
|
266
|
+
return Math.min(n, REPAIR_ITERATION_CAP);
|
|
267
|
+
return 0;
|
|
268
|
+
}
|
|
269
|
+
function formatFindings(findings) {
|
|
270
|
+
if (findings.length === 0)
|
|
271
|
+
return "(no findings recorded)";
|
|
272
|
+
return findings.map((f) => `${f.token} · ${f.file}:${f.line} · ${f.text}`).join("\n");
|
|
37
273
|
}
|
|
38
274
|
//# sourceMappingURL=dispatch.js.map
|
package/dist/dispatch.js.map
CHANGED
|
@@ -1 +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"}
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../src/dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { DomainSpec } from "./agents/types.js";
|
|
2
|
+
export type BridgeValues = {
|
|
3
|
+
readonly values: Readonly<Record<string, string>>;
|
|
4
|
+
};
|
|
5
|
+
export declare function productTokenFor(domain: DomainSpec): string;
|
|
6
|
+
export declare function readSubstrateApiVars(): Promise<Readonly<Record<string, string>>>;
|
|
7
|
+
export declare function buildBridgeValues(domain: DomainSpec): Promise<BridgeValues>;
|
|
8
|
+
export declare function applyBridgeToProcessEnv(bridge: BridgeValues): void;
|
|
9
|
+
export type SyncMode = "wrote" | "skipped" | "dry-run" | "noop";
|
|
10
|
+
export type SyncResult = {
|
|
11
|
+
path: string;
|
|
12
|
+
mode: SyncMode;
|
|
13
|
+
removedStale: boolean;
|
|
14
|
+
preview?: string;
|
|
15
|
+
};
|
|
16
|
+
export declare function syncGradleProperties(bridge: BridgeValues): Promise<SyncResult>;
|
|
17
|
+
//# sourceMappingURL=env-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-bridge.d.ts","sourceRoot":"","sources":["../src/env-bridge.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAsCpD,MAAM,MAAM,YAAY,GAAG;IAGzB,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACnD,CAAC;AAEF,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAE1D;AAKD,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,CAyBtF;AAkBD,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,CAQjF;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAKlE;AAED,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,OAAO,CAAC;IAGtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC;AAoBF,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,UAAU,CAAC,CA8BpF"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { slugToPascal } from "./slug.js";
|
|
5
|
+
// Bridges substrate-named API config (NATIVEAPPTEMPLATE_API_*) to the
|
|
6
|
+
// renamed-product equivalents (<PRODUCT>_API_*) so the agent's auto-
|
|
7
|
+
// validation runs see the right values without forcing the user to
|
|
8
|
+
// hand-set N env vars per generated app.
|
|
9
|
+
//
|
|
10
|
+
// Three sinks the agent has to feed:
|
|
11
|
+
// 1. ~/.gradle/gradle.properties (so Android Studio + manual ./gradlew
|
|
12
|
+
// see the value when the user opens the generated project later)
|
|
13
|
+
// 2. ORG_GRADLE_PROJECT_<KEY>=<value> in the child env when the agent
|
|
14
|
+
// itself spawns ./gradlew (Layer 2 build mode, defensive — works
|
|
15
|
+
// even if gradle.properties is mid-write or the user hasn't saved)
|
|
16
|
+
// 3. SIMCTL_CHILD_<KEY>=<value> in the child env when the agent spawns
|
|
17
|
+
// `xcrun simctl launch` (so the env var reaches the running iOS
|
|
18
|
+
// app via simctl's child-env passthrough convention)
|
|
19
|
+
//
|
|
20
|
+
// Source of truth, by suffix:
|
|
21
|
+
// API_DOMAIN ← $NATIVEAPPTEMPLATE_API/.env HOST
|
|
22
|
+
// API_PORT ← $NATIVEAPPTEMPLATE_API/.env PORT
|
|
23
|
+
// API_SCHEME ← shell env NATIVEAPPTEMPLATE_API_SCHEME, fall back to
|
|
24
|
+
// ~/.gradle/gradle.properties (since the substrate's
|
|
25
|
+
// Rails .env doesn't carry SCHEME)
|
|
26
|
+
//
|
|
27
|
+
// Single source of truth: the substrate's own Rails .env (where Rails
|
|
28
|
+
// actually binds). The mobile clients connect to exactly that host:port,
|
|
29
|
+
// so reading from .env eliminates the drift risk of a parallel shell
|
|
30
|
+
// export. User maintains one file, .env, for their dev-network setup.
|
|
31
|
+
// The three keys we mirror. Adding a new one here automatically threads
|
|
32
|
+
// it through all three sinks. Listed in the same order they appear in
|
|
33
|
+
// the substrate's gradle.properties / .env.sample so diffs read
|
|
34
|
+
// naturally.
|
|
35
|
+
const MIRRORED_SUFFIXES = ["API_DOMAIN", "API_PORT", "API_SCHEME"];
|
|
36
|
+
const SENTINEL_BEGIN = "# BEGIN nativeapptemplate-agent (mirrored API config — do not edit by hand)";
|
|
37
|
+
const SENTINEL_END = "# END nativeapptemplate-agent";
|
|
38
|
+
export function productTokenFor(domain) {
|
|
39
|
+
return slugToPascal(domain.slug).toUpperCase();
|
|
40
|
+
}
|
|
41
|
+
// Read the substrate side of the bridge. Returns only the keys whose
|
|
42
|
+
// source-of-truth carries a non-empty value — silently omits anything
|
|
43
|
+
// missing. Caller decides what to do with empty results.
|
|
44
|
+
export async function readSubstrateApiVars() {
|
|
45
|
+
const result = {};
|
|
46
|
+
// DOMAIN + PORT come from the substrate's Rails .env (HOST + PORT —
|
|
47
|
+
// where Rails actually binds). Mobile clients must connect to that
|
|
48
|
+
// exact host:port, so this is the single source of truth.
|
|
49
|
+
const substratePath = process.env['NATIVEAPPTEMPLATE_API'];
|
|
50
|
+
if (substratePath) {
|
|
51
|
+
const env = await readDotenv(join(substratePath, ".env"));
|
|
52
|
+
if (env['HOST'])
|
|
53
|
+
result['API_DOMAIN'] = env['HOST'];
|
|
54
|
+
if (env['PORT'])
|
|
55
|
+
result['API_PORT'] = env['PORT'];
|
|
56
|
+
}
|
|
57
|
+
// SCHEME isn't in the Rails .env — pull it from the user's shell
|
|
58
|
+
// env, fall back to ~/.gradle/gradle.properties, fall back to nothing
|
|
59
|
+
// (caller treats missing as "use the app's compiled-in default").
|
|
60
|
+
const shellScheme = process.env['NATIVEAPPTEMPLATE_API_SCHEME'];
|
|
61
|
+
if (shellScheme) {
|
|
62
|
+
result['API_SCHEME'] = shellScheme;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
const gradleScheme = (await readGradleProperties())['NATIVEAPPTEMPLATE_API_SCHEME'];
|
|
66
|
+
if (gradleScheme)
|
|
67
|
+
result['API_SCHEME'] = gradleScheme;
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
async function readDotenv(path) {
|
|
72
|
+
const raw = await readFileOrEmpty(path);
|
|
73
|
+
const out = {};
|
|
74
|
+
for (const line of raw.split("\n")) {
|
|
75
|
+
const trimmed = line.trim();
|
|
76
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
77
|
+
continue;
|
|
78
|
+
const eq = trimmed.indexOf("=");
|
|
79
|
+
if (eq < 1)
|
|
80
|
+
continue;
|
|
81
|
+
const key = trimmed.slice(0, eq).trim();
|
|
82
|
+
const valueRaw = trimmed.slice(eq + 1).trim();
|
|
83
|
+
const value = valueRaw.replace(/^"(.*)"$/, "$1").replace(/^'(.*)'$/, "$1");
|
|
84
|
+
if (key && value)
|
|
85
|
+
out[key] = value;
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
export async function buildBridgeValues(domain) {
|
|
90
|
+
const product = productTokenFor(domain);
|
|
91
|
+
const substrate = await readSubstrateApiVars();
|
|
92
|
+
const values = {};
|
|
93
|
+
for (const [suffix, value] of Object.entries(substrate)) {
|
|
94
|
+
values[`${product}_${suffix}`] = value;
|
|
95
|
+
}
|
|
96
|
+
return { values };
|
|
97
|
+
}
|
|
98
|
+
// Set ORG_GRADLE_PROJECT_<KEY> and SIMCTL_CHILD_<KEY> entries in the
|
|
99
|
+
// agent's own process.env so any subsequent child spawn that inherits
|
|
100
|
+
// process.env (via env.ts's scrubbedEnv) sees them. Idempotent — calling
|
|
101
|
+
// twice with the same domain is a no-op.
|
|
102
|
+
export function applyBridgeToProcessEnv(bridge) {
|
|
103
|
+
for (const [key, value] of Object.entries(bridge.values)) {
|
|
104
|
+
process.env[`ORG_GRADLE_PROJECT_${key}`] = value;
|
|
105
|
+
process.env[`SIMCTL_CHILD_${key}`] = value;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Write a sentinel block to ~/.gradle/gradle.properties containing the
|
|
109
|
+
// mirrored keys. Replaces an existing block from a prior run; preserves
|
|
110
|
+
// every line outside the block. If gradle.properties doesn't exist,
|
|
111
|
+
// creates it. If the bridge has no values (substrate vars unset),
|
|
112
|
+
// removes the existing block (so stale values from a prior run don't
|
|
113
|
+
// linger) and writes nothing else.
|
|
114
|
+
//
|
|
115
|
+
// Safety knobs (env vars, both default to off):
|
|
116
|
+
// NATIVEAPPTEMPLATE_BRIDGE=off — skip the file write entirely;
|
|
117
|
+
// process.env injection still
|
|
118
|
+
// runs for the agent's own
|
|
119
|
+
// child-spawn paths.
|
|
120
|
+
// NATIVEAPPTEMPLATE_BRIDGE_DRY_RUN=1 — log what would be written
|
|
121
|
+
// instead of writing. Useful for
|
|
122
|
+
// users who want to inspect the
|
|
123
|
+
// bridge's behavior before
|
|
124
|
+
// giving it write access to
|
|
125
|
+
// their user-global gradle.
|
|
126
|
+
export async function syncGradleProperties(bridge) {
|
|
127
|
+
const path = join(homedir(), ".gradle", "gradle.properties");
|
|
128
|
+
if (process.env['NATIVEAPPTEMPLATE_BRIDGE'] === "off") {
|
|
129
|
+
return { path, mode: "skipped", removedStale: false };
|
|
130
|
+
}
|
|
131
|
+
const existing = await readFileOrEmpty(path);
|
|
132
|
+
const stripped = removeSentinelBlock(existing);
|
|
133
|
+
const hasValues = Object.keys(bridge.values).length > 0;
|
|
134
|
+
const removedStale = stripped !== existing && !hasValues;
|
|
135
|
+
let next;
|
|
136
|
+
if (!hasValues) {
|
|
137
|
+
next = stripped;
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
const block = formatSentinelBlock(bridge.values);
|
|
141
|
+
next = ensureTrailingNewline(stripped) + block + "\n";
|
|
142
|
+
}
|
|
143
|
+
const dryRun = process.env['NATIVEAPPTEMPLATE_BRIDGE_DRY_RUN'] === "1";
|
|
144
|
+
if (next === existing) {
|
|
145
|
+
return { path, mode: "noop", removedStale };
|
|
146
|
+
}
|
|
147
|
+
if (dryRun) {
|
|
148
|
+
return { path, mode: "dry-run", removedStale, preview: next };
|
|
149
|
+
}
|
|
150
|
+
await writeFile(path, next);
|
|
151
|
+
return { path, mode: hasValues ? "wrote" : "noop", removedStale };
|
|
152
|
+
}
|
|
153
|
+
async function readGradleProperties() {
|
|
154
|
+
const path = join(homedir(), ".gradle", "gradle.properties");
|
|
155
|
+
const raw = await readFileOrEmpty(path);
|
|
156
|
+
const out = {};
|
|
157
|
+
for (const line of raw.split("\n")) {
|
|
158
|
+
const trimmed = line.trim();
|
|
159
|
+
if (!trimmed || trimmed.startsWith("#"))
|
|
160
|
+
continue;
|
|
161
|
+
const eq = trimmed.indexOf("=");
|
|
162
|
+
if (eq < 1)
|
|
163
|
+
continue;
|
|
164
|
+
const key = trimmed.slice(0, eq).trim();
|
|
165
|
+
const value = trimmed.slice(eq + 1).trim();
|
|
166
|
+
if (key && value)
|
|
167
|
+
out[key] = value;
|
|
168
|
+
}
|
|
169
|
+
return out;
|
|
170
|
+
}
|
|
171
|
+
async function readFileOrEmpty(path) {
|
|
172
|
+
try {
|
|
173
|
+
return await readFile(path, "utf8");
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return "";
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function removeSentinelBlock(content) {
|
|
180
|
+
const beginIdx = content.indexOf(SENTINEL_BEGIN);
|
|
181
|
+
if (beginIdx === -1)
|
|
182
|
+
return content;
|
|
183
|
+
const endIdx = content.indexOf(SENTINEL_END, beginIdx);
|
|
184
|
+
if (endIdx === -1)
|
|
185
|
+
return content;
|
|
186
|
+
const after = endIdx + SENTINEL_END.length;
|
|
187
|
+
// Also consume the newline after END if present, so removing leaves
|
|
188
|
+
// no orphan blank line.
|
|
189
|
+
const trailing = content[after] === "\n" ? after + 1 : after;
|
|
190
|
+
// And consume one preceding blank-separator newline so we don't
|
|
191
|
+
// accumulate blanks across cycles.
|
|
192
|
+
let before = beginIdx;
|
|
193
|
+
if (before > 0 && content[before - 1] === "\n" && content[before - 2] === "\n") {
|
|
194
|
+
before -= 1;
|
|
195
|
+
}
|
|
196
|
+
return content.slice(0, before) + content.slice(trailing);
|
|
197
|
+
}
|
|
198
|
+
function formatSentinelBlock(values) {
|
|
199
|
+
const lines = [SENTINEL_BEGIN];
|
|
200
|
+
for (const key of Object.keys(values).sort()) {
|
|
201
|
+
lines.push(`${key}=${values[key]}`);
|
|
202
|
+
}
|
|
203
|
+
lines.push(SENTINEL_END);
|
|
204
|
+
return lines.join("\n");
|
|
205
|
+
}
|
|
206
|
+
function ensureTrailingNewline(s) {
|
|
207
|
+
if (s === "")
|
|
208
|
+
return "";
|
|
209
|
+
return s.endsWith("\n") ? s : s + "\n";
|
|
210
|
+
}
|
|
211
|
+
//# sourceMappingURL=env-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"env-bridge.js","sourceRoot":"","sources":["../src/env-bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { type DispatchReportOptions } from "./dispatch.js";
|
|
3
|
+
import type { RenamePair } from "./agents/types.js";
|
|
4
|
+
export type ParsedArgs = {
|
|
5
|
+
spec: string;
|
|
6
|
+
report: DispatchReportOptions;
|
|
7
|
+
open: boolean;
|
|
8
|
+
exitZero: boolean;
|
|
9
|
+
renameOverrides: RenamePair[];
|
|
10
|
+
projectName?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare function parseArgs(argv: readonly string[]): ParsedArgs;
|
|
2
13
|
export declare function main(spec?: string): Promise<void>;
|
|
3
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAY,KAAK,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAIrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAIpD,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,qBAAqB,CAAC;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,OAAO,CAAC;IAClB,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,UAAU,CAmC7D;AAED,wBAAsB,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDvD"}
|