@quikit/quikpilot-runner 7.0.3 → 7.0.5

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/dist/index.js CHANGED
@@ -59,10 +59,10 @@ function runTestCommand(command) {
59
59
  }
60
60
  function runTestCommandAsync(command) {
61
61
  if (!command) return Promise.resolve("success");
62
- return new Promise((resolve2) => {
62
+ return new Promise((resolve3) => {
63
63
  const child = (0, import_node_child_process.spawn)(command, { shell: "/bin/bash", stdio: "inherit" });
64
- child.on("exit", (code) => resolve2(code === 0 ? "success" : "failure"));
65
- child.on("error", () => resolve2("failure"));
64
+ child.on("exit", (code) => resolve3(code === 0 ? "success" : "failure"));
65
+ child.on("error", () => resolve3("failure"));
66
66
  });
67
67
  }
68
68
 
@@ -145,6 +145,21 @@ function commitAndPush(branch, runId, installationToken) {
145
145
  // src/codegen.ts
146
146
  var import_node_fs = require("node:fs");
147
147
  var import_node_path = require("node:path");
148
+
149
+ // src/envelope.ts
150
+ function unwrapExecute(envelope, useCase) {
151
+ if (envelope?.success === false) {
152
+ throw new Error(
153
+ `${useCase} failed: ${envelope.errorCode ?? "UNKNOWN"} \u2014 ${envelope.error ?? envelope.normalizedText ?? "no message"}`
154
+ );
155
+ }
156
+ if (!envelope?.structuredJson || typeof envelope.structuredJson !== "object") {
157
+ throw new Error(`${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`);
158
+ }
159
+ return envelope.structuredJson;
160
+ }
161
+
162
+ // src/codegen.ts
148
163
  var FILE_TOO_LARGE_CODE = "CODEGEN_FILE_TOO_LARGE";
149
164
  function findNearestSibling(targetPath, workspaceListing) {
150
165
  let dir = (0, import_node_path.dirname)(targetPath);
@@ -186,13 +201,14 @@ async function runCodegen(gateway, targets, workspaceListing) {
186
201
  if (!res.ok) {
187
202
  throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);
188
203
  }
189
- const body = await res.json();
190
- if (body.code === FILE_TOO_LARGE_CODE) {
204
+ const envelope = await res.json();
205
+ if (envelope?.errorCode === FILE_TOO_LARGE_CODE) {
191
206
  throw new Error(`Codegen refused ${target.path}: ${FILE_TOO_LARGE_CODE} (not retried)`);
192
207
  }
208
+ const body = unwrapExecute(envelope, "pilot.codegen");
193
209
  if (body.outcome !== "GENERATED" || typeof body.newContent !== "string") {
194
210
  throw new Error(
195
- `Codegen refused ${target.path}${body.message ? `: ${body.message}` : ""}`
211
+ `Codegen refused ${target.path}${body.refusalReason ? `: ${body.refusalReason}` : ""}`
196
212
  );
197
213
  }
198
214
  results.push({ targetPath: target.path, newContent: body.newContent });
@@ -206,6 +222,108 @@ function flushCodegenResults(results) {
206
222
  }
207
223
  }
208
224
 
225
+ // src/dependencyCheck.ts
226
+ var import_node_fs2 = require("node:fs");
227
+ var import_node_path2 = require("node:path");
228
+ var SCANNABLE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".mts", ".cts"];
229
+ var IMPORT_RE = /(?:\bimport\b[^'"]*?\bfrom\s*|\bimport\s*\(\s*|\bexport\b[^'"]*?\bfrom\s*|\brequire\s*\(\s*|\bimport\s+)(['"])([^'"]+)\1/g;
230
+ var NODE_BUILTINS = /* @__PURE__ */ new Set([
231
+ "assert",
232
+ "buffer",
233
+ "child_process",
234
+ "cluster",
235
+ "crypto",
236
+ "dgram",
237
+ "dns",
238
+ "domain",
239
+ "events",
240
+ "fs",
241
+ "http",
242
+ "http2",
243
+ "https",
244
+ "net",
245
+ "os",
246
+ "path",
247
+ "perf_hooks",
248
+ "process",
249
+ "punycode",
250
+ "querystring",
251
+ "readline",
252
+ "repl",
253
+ "stream",
254
+ "string_decoder",
255
+ "sys",
256
+ "timers",
257
+ "tls",
258
+ "tty",
259
+ "url",
260
+ "util",
261
+ "v8",
262
+ "vm",
263
+ "worker_threads",
264
+ "zlib",
265
+ "inspector",
266
+ "async_hooks"
267
+ ]);
268
+ function packageNameFromSpecifier(specifier) {
269
+ if (specifier.startsWith(".") || specifier.startsWith("/")) return null;
270
+ if (specifier.startsWith("node:")) return null;
271
+ const segments = specifier.split("/");
272
+ const name = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
273
+ if (NODE_BUILTINS.has(name)) return null;
274
+ return name;
275
+ }
276
+ function scanImports(source) {
277
+ const found = /* @__PURE__ */ new Set();
278
+ let match;
279
+ IMPORT_RE.lastIndex = 0;
280
+ while (match = IMPORT_RE.exec(source)) {
281
+ const name = packageNameFromSpecifier(match[2]);
282
+ if (name) found.add(name);
283
+ }
284
+ return [...found];
285
+ }
286
+ function checkImportDependencies(results, declaredDependencies) {
287
+ if (!declaredDependencies) return { blocked: false, violations: [] };
288
+ const violations = [];
289
+ for (const { targetPath, newContent } of results) {
290
+ if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;
291
+ const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));
292
+ if (invented.length > 0) violations.push({ file: targetPath, packages: invented });
293
+ }
294
+ return { blocked: violations.length > 0, violations };
295
+ }
296
+ function dependencyNames(pkg) {
297
+ return /* @__PURE__ */ new Set([
298
+ ...Object.keys(pkg.dependencies ?? {}),
299
+ ...Object.keys(pkg.devDependencies ?? {}),
300
+ ...Object.keys(pkg.peerDependencies ?? {})
301
+ ]);
302
+ }
303
+ function readDeclaredDependencies(results, workspaceRoot) {
304
+ const packageJsonPath = (0, import_node_path2.join)((0, import_node_path2.resolve)(workspaceRoot ?? "."), "package.json");
305
+ const generated = results.find((r) => (0, import_node_path2.resolve)(r.targetPath) === packageJsonPath);
306
+ let raw;
307
+ if (generated) {
308
+ raw = generated.newContent;
309
+ } else {
310
+ try {
311
+ raw = (0, import_node_fs2.readFileSync)(packageJsonPath, "utf8");
312
+ } catch {
313
+ raw = null;
314
+ }
315
+ }
316
+ if (raw === null) return null;
317
+ try {
318
+ return dependencyNames(JSON.parse(raw));
319
+ } catch {
320
+ return null;
321
+ }
322
+ }
323
+ function describeDependencyViolations(check) {
324
+ return check.violations.map((v) => `${v.file} imports ${v.packages.join(", ")}, not a dependency of this repository`).join("; ");
325
+ }
326
+
209
327
  // src/env.ts
210
328
  function required(name, value) {
211
329
  if (!value) {
@@ -295,30 +413,30 @@ async function fetchPacket(packetUrl, runToken, githubRunId) {
295
413
  }
296
414
 
297
415
  // src/phase0.ts
298
- var import_node_fs2 = require("node:fs");
416
+ var import_node_fs3 = require("node:fs");
299
417
  function writePhase0Marker(runId) {
300
- (0, import_node_fs2.mkdirSync)(".quikpilot", { recursive: true });
301
- (0, import_node_fs2.appendFileSync)(".quikpilot/phase0-marker.txt", `QuikPilot Phase 0 skeleton marker for run ${runId}
418
+ (0, import_node_fs3.mkdirSync)(".quikpilot", { recursive: true });
419
+ (0, import_node_fs3.appendFileSync)(".quikpilot/phase0-marker.txt", `QuikPilot Phase 0 skeleton marker for run ${runId}
302
420
  `);
303
421
  }
304
422
 
305
423
  // src/quiktest.ts
306
- var import_node_fs3 = require("node:fs");
307
- var import_node_path2 = require("node:path");
424
+ var import_node_fs4 = require("node:fs");
425
+ var import_node_path3 = require("node:path");
308
426
  var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
309
427
  function walkForJUnitByName(dir) {
310
428
  let entries;
311
429
  try {
312
- entries = (0, import_node_fs3.readdirSync)(dir);
430
+ entries = (0, import_node_fs4.readdirSync)(dir);
313
431
  } catch {
314
432
  return null;
315
433
  }
316
434
  for (const entry of entries) {
317
435
  if (SKIP_DIRS.has(entry)) continue;
318
- const full = (0, import_node_path2.join)(dir, entry);
436
+ const full = (0, import_node_path3.join)(dir, entry);
319
437
  let stat;
320
438
  try {
321
- stat = (0, import_node_fs3.statSync)(full);
439
+ stat = (0, import_node_fs4.statSync)(full);
322
440
  } catch {
323
441
  continue;
324
442
  }
@@ -334,15 +452,15 @@ function walkForJUnitByName(dir) {
334
452
  function firstXmlIn(dir, namePattern) {
335
453
  let entries;
336
454
  try {
337
- entries = (0, import_node_fs3.readdirSync)(dir);
455
+ entries = (0, import_node_fs4.readdirSync)(dir);
338
456
  } catch {
339
457
  return null;
340
458
  }
341
459
  const match = entries.find((e) => namePattern.test(e));
342
- return match ? (0, import_node_path2.join)(dir, match) : null;
460
+ return match ? (0, import_node_path3.join)(dir, match) : null;
343
461
  }
344
462
  function findJUnitReport(cwd = process.cwd()) {
345
- return walkForJUnitByName(cwd) ?? firstXmlIn((0, import_node_path2.join)(cwd, "test-results"), /\.xml$/) ?? firstXmlIn((0, import_node_path2.join)(cwd, "reports"), /^junit.*\.xml$/) ?? firstXmlIn((0, import_node_path2.join)(cwd, "target", "surefire-reports"), /\.xml$/);
463
+ return walkForJUnitByName(cwd) ?? firstXmlIn((0, import_node_path3.join)(cwd, "test-results"), /\.xml$/) ?? firstXmlIn((0, import_node_path3.join)(cwd, "reports"), /^junit.*\.xml$/) ?? firstXmlIn((0, import_node_path3.join)(cwd, "target", "surefire-reports"), /\.xml$/);
346
464
  }
347
465
  function buildCiUrl(serverUrl, repository, githubRunId) {
348
466
  return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;
@@ -361,8 +479,8 @@ async function reportToQuikTest(params) {
361
479
  try {
362
480
  console.log(`reporting ${report}`);
363
481
  const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);
364
- const { readFileSync: readFileSync3 } = await import("node:fs");
365
- const body = readFileSync3(report);
482
+ const { readFileSync: readFileSync4 } = await import("node:fs");
483
+ const body = readFileSync4(report);
366
484
  const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;
367
485
  const res = await fetch(url, {
368
486
  method: "POST",
@@ -372,14 +490,14 @@ async function reportToQuikTest(params) {
372
490
  if (!res.ok) {
373
491
  throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);
374
492
  }
375
- (0, import_node_fs3.rmSync)(report, { force: true });
493
+ (0, import_node_fs4.rmSync)(report, { force: true });
376
494
  } catch (err) {
377
495
  console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);
378
496
  }
379
497
  }
380
498
 
381
499
  // src/regressionCheck.ts
382
- var import_node_fs4 = require("node:fs");
500
+ var import_node_fs5 = require("node:fs");
383
501
  var TESTCASE_RE = /<testcase\b([^>]*?)(?:\/>|>([\s\S]*?)<\/testcase>)/g;
384
502
  var NAME_ATTR_RE = /\bname="([^"]*)"/;
385
503
  var CLASSNAME_ATTR_RE = /\bclassname="([^"]*)"/;
@@ -402,7 +520,7 @@ function readJUnitOutcomes(cwd) {
402
520
  const report = findJUnitReport(cwd);
403
521
  if (!report) return null;
404
522
  try {
405
- return parseJUnitOutcomes((0, import_node_fs4.readFileSync)(report, "utf8"));
523
+ return parseJUnitOutcomes((0, import_node_fs5.readFileSync)(report, "utf8"));
406
524
  } catch {
407
525
  return null;
408
526
  }
@@ -446,7 +564,7 @@ function describeRegressions(check) {
446
564
  }
447
565
 
448
566
  // src/targeting.ts
449
- var import_node_path3 = require("node:path");
567
+ var import_node_path4 = require("node:path");
450
568
  function listWorkspaceFiles(workspaceRoot) {
451
569
  return listFiles(workspaceRoot ?? ".");
452
570
  }
@@ -462,9 +580,9 @@ function validateTarget(target, workspaceRoot, workspaceListing) {
462
580
  }
463
581
  return;
464
582
  }
465
- const root = (0, import_node_path3.resolve)(workspaceRoot ?? ".");
466
- const rel = (0, import_node_path3.relative)(root, (0, import_node_path3.resolve)(target.path));
467
- if (rel.startsWith("..") || (0, import_node_path3.isAbsolute)(rel)) {
583
+ const root = (0, import_node_path4.resolve)(workspaceRoot ?? ".");
584
+ const rel = (0, import_node_path4.relative)(root, (0, import_node_path4.resolve)(target.path));
585
+ if (rel.startsWith("..") || (0, import_node_path4.isAbsolute)(rel)) {
468
586
  throw new Error(
469
587
  `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`
470
588
  );
@@ -487,7 +605,8 @@ async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
487
605
  if (!res.ok) {
488
606
  throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);
489
607
  }
490
- const body = await res.json();
608
+ const envelope = await res.json();
609
+ const body = unwrapExecute(envelope, "pilot.targeting");
491
610
  if (body.outcome === "NO_TARGET") {
492
611
  return { outcome: "NO_TARGET", reason: body.noTargetReason ?? null };
493
612
  }
@@ -545,7 +664,21 @@ async function run(env = readRunnerEnv()) {
545
664
  captureBaselineSnapshot(packet.commands.test),
546
665
  runCodegen(packet.gateway, targeting.targets, workspaceListing)
547
666
  ]);
667
+ const depCheck = checkImportDependencies(
668
+ results,
669
+ readDeclaredDependencies(results, packet.workspaceRoot)
670
+ );
671
+ if (depCheck.blocked) {
672
+ throw new Error(
673
+ `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`
674
+ );
675
+ }
548
676
  flushCodegenResults(results);
677
+ try {
678
+ runCommand(packet.commands.format, "Format");
679
+ } catch (err) {
680
+ console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);
681
+ }
549
682
  runCommand(packet.commands.lint, "Lint");
550
683
  const after = captureTestSnapshot(packet.commands.test);
551
684
  const check = checkForRegressions(baseline, after);
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/regressionCheck.ts", "../src/targeting.ts", "../src/tokenExchange.ts", "../src/run.ts", "../src/index.ts"],
4
- "sourcesContent": ["export type RunStatus = \"completed\" | \"failed\";\n\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. */\nexport async function reportBack(params: {\n callbackUrl: string;\n runToken: string;\n status: RunStatus;\n branch?: string;\n}): Promise<void> {\n const { callbackUrl, runToken, status, branch } = params;\n const body: Record<string, string> = { status };\n if (branch) body.branch = branch;\n const res = await fetch(callbackUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`Report back to QuikTrack failed: ${res.status} ${res.statusText}`);\n }\n}\n", "import { execSync, spawn } from \"node:child_process\";\n\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\nexport function runCommand(command: string | null, label: string): void {\n if (!command) return;\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nexport type TestOutcome = \"success\" | \"failure\";\n\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\nexport function runTestCommand(command: string | null): TestOutcome {\n if (!command) return \"success\";\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n return \"success\";\n } catch {\n return \"failure\";\n }\n}\n\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\n if (!command) return Promise.resolve(\"success\");\n return new Promise((resolve) => {\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\n child.on(\"error\", () => resolve(\"failure\"));\n });\n}\n", "import { execFileSync } from \"node:child_process\";\n\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\n * on top of the inherited environment; every existing call site is unaffected since it defaults\n * to empty. */\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\n return execFileSync(\"git\", args, {\n encoding: \"utf8\",\n env: { ...process.env, ...extraEnv },\n }).trim();\n}\n\nexport function currentBranch(): string {\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n}\n\n/** Only fetches + checks out when the packet names a target branch different from the one the\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\nexport function checkoutTargetBranch(targetBranch: string | null): void {\n if (!targetBranch || targetBranch === currentBranch()) return;\n git([\"fetch\", \"origin\", targetBranch]);\n git([\"checkout\", targetBranch]);\n}\n\nexport function addAll(): void {\n git([\"add\", \"-A\"]);\n}\n\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\n * getting wrong. */\nexport function diffCachedNamesMatching(pattern: string): string[] {\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\n * targeting.ts's workspaceRoot concept, not a generic git one. */\nexport function listFiles(pathspec: string): string[] {\n const out = git([\"ls-files\", \"--\", pathspec]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\nexport function hasStagedChanges(): boolean {\n try {\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\n return false;\n } catch {\n return true;\n }\n}\n\nexport function configureCommitIdentity(): void {\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\n}\n\nexport function checkoutNewBranch(branch: string): void {\n git([\"checkout\", \"-b\", branch]);\n}\n\nexport function commit(message: string): void {\n git([\"commit\", \"-m\", message]);\n}\n\n/**\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\n * documented scheme for installation tokens over HTTPS git.\n *\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\n * runner's other credential. Scoped to this one invocation only; never persisted.\n *\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\n *\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\n */\nfunction clearCheckoutExtraHeader(): void {\n try {\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\n } catch (err: unknown) {\n const status = (err as { status?: number }).status;\n if (status !== 5) throw err;\n }\n}\n\nexport function push(branch: string, installationToken: string): void {\n clearCheckoutExtraHeader();\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\n GIT_CONFIG_COUNT: \"1\",\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\n });\n}\n", "import {\n checkoutNewBranch,\n commit,\n configureCommitIdentity,\n hasStagedChanges,\n push,\n} from \"./git\";\n\nexport interface CommitResult {\n changed: boolean;\n branch?: string;\n}\n\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\n * already computed and stored it, and two sources for one value will eventually disagree.\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\n * with \u2014 see git.ts's `push` for why. */\nexport function commitAndPush(\n branch: string | null,\n runId: string,\n installationToken: string,\n): CommitResult {\n if (!hasStagedChanges()) return { changed: false };\n if (!branch) {\n throw new Error(\"packet carried no branch name\");\n }\n configureCommitIdentity();\n checkoutNewBranch(branch);\n commit(`QuikPilot Phase 0 skeleton (run ${runId})`);\n push(branch, installationToken);\n return { changed: true, branch };\n}\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport type { PilotPacket } from \"./packet\";\nimport type { PilotTarget } from \"./targeting\";\n\n/**\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\n *\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\n * per-target: the route file and the service file need different instructions.\n *\n * \u2500\u2500 ALL-OR-NOTHING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\n * failed file instead of discarding the rest is the better long-run answer and belongs with\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\n *\n * `CODEGEN_FILE_TOO_LARGE` is the AI Runtime's own distinct error code, checked on their side\n * before dispatch \u2014 retrying hits the identical wall every time, so it is deliberately not\n * retried, same as every other failure here.\n *\n * \u2500\u2500 BUFFERED WRITES (QUIKTR-1035) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * `runCodegen` no longer writes anything \u2014 it collects `{targetPath, newContent}` in memory and\n * `flushCodegenResults` writes them all, only once every call has succeeded. Two independent\n * reasons: it makes all-or-nothing literally true for the working tree, not just the pull request\n * (today a failure on file 3 leaves files 1-2 already written even though the throw stops the\n * commit); and it lets the test baseline run against an untouched tree while codegen's network-\n * bound calls are still in flight (QUIKTR-1036 is what actually wires that concurrency up \u2014 this\n * only makes it possible).\n */\nconst FILE_TOO_LARGE_CODE = \"CODEGEN_FILE_TOO_LARGE\";\n\ninterface CodegenResponse {\n outcome?: \"GENERATED\" | \"REFUSED\";\n newContent?: string;\n summary?: string;\n code?: string;\n message?: string;\n}\n\nexport interface CodegenFileResult {\n targetPath: string;\n newContent: string;\n}\n\n/**\n * Nearest existing file by directory, walking from the target's own directory up toward the\n * workspace root. Stated assumption, not a general solution: this teaches the model HOW code is\n * written here (imports, relative paths, test framework) by proximity alone \u2014 a repo with\n * genuinely mixed per-directory conventions would need something smarter than \"nearest neighbor.\"\n */\nfunction findNearestSibling(targetPath: string, workspaceListing: string[]): string | null {\n let dir = dirname(targetPath);\n for (;;) {\n const candidate = workspaceListing.find((f) => f !== targetPath && dirname(f) === dir);\n if (candidate) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Run codegen for exactly the targets named, in order, stopping at the first failure. Throws\n * rather than returning a partial result \u2014 see the ALL-OR-NOTHING note above; a caller that wants\n * to know how far it got before failing should catch and inspect the message, not branch on a\n * return value that implies partial success is a valid state. Writes nothing \u2014 call\n * `flushCodegenResults` with the return value once this resolves.\n */\nexport async function runCodegen(\n gateway: PilotPacket[\"gateway\"],\n targets: PilotTarget[],\n workspaceListing: string[],\n): Promise<CodegenFileResult[]> {\n const results: CodegenFileResult[] = [];\n\n for (const target of targets) {\n const isNewFile = target.kind === \"NEW_FILE\";\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\n\n const contextData: Record<string, unknown> = {\n targetPath: target.path,\n currentContent,\n planSteps: target.planStepsImplemented,\n kind: target.kind,\n };\n if (isNewFile) {\n // Bounds WHAT EXISTS (stops an invented import like hooks/useGroups) and teaches HOW code is\n // written (siblingContent) \u2014 neither alone is enough, and both are only meaningful for a\n // file that doesn't exist yet to compare against.\n contextData.workspaceListing = workspaceListing;\n const sibling = findNearestSibling(target.path, workspaceListing);\n if (sibling) contextData.siblingContent = readFileSync(sibling, \"utf8\");\n }\n\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.codegen\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n contextData,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\n }\n\n const body = (await res.json()) as CodegenResponse;\n\n if (body.code === FILE_TOO_LARGE_CODE) {\n throw new Error(`Codegen refused ${target.path}: ${FILE_TOO_LARGE_CODE} (not retried)`);\n }\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\n throw new Error(\n `Codegen refused ${target.path}${body.message ? `: ${body.message}` : \"\"}`,\n );\n }\n\n results.push({ targetPath: target.path, newContent: body.newContent });\n }\n\n return results;\n}\n\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\n for (const { targetPath, newContent } of results) {\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, newContent);\n }\n}\n", "/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\n * generated workflow file still passes them through as job-level env vars under these exact\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\nexport interface RunnerEnv {\n runId: string;\n callbackUrl: string;\n packetUrl: string;\n tokenUrl: string;\n installationTokenUrl: string;\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\n * individually. */\n githubRunId: string;\n githubServerUrl: string;\n githubRepository: string;\n}\n\nexport function required(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\n return {\n runId: required(\"RUN_ID\", env.RUN_ID),\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\n githubRunId: required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID),\n githubServerUrl: env.GITHUB_SERVER_URL ?? \"https://github.com\",\n githubRepository: required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY),\n };\n}\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\n\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\nexport function checkGuardrail(deniedPaths: string[]): void {\n addAll();\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\n if (violations.length > 0) {\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\n }\n}\n", "interface InstallationTokenResponse {\n success: boolean;\n data: { token: string; expiresAt: string };\n}\n\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\n * envelope, same error-message style. */\nexport async function exchangeForInstallationToken(\n installationTokenUrl: string,\n runToken: string,\n): Promise<string> {\n const res = await fetch(installationTokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange installation token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as InstallationTokenResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\n }\n return body.data.token;\n}\n", "import { required } from \"./env\";\n\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\n * verifies the token this package requests. Duplicated because this package is published outside\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\n * duplicating `PilotPacket`'s shape. */\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\n\ninterface OidcTokenResponse {\n value: string;\n}\n\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\nexport async function fetchGithubOidcToken(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n const requestUrl = required(\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\n );\n const requestToken = required(\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\n );\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${requestToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as OidcTokenResponse;\n if (!body.value) {\n throw new Error(\"GitHub OIDC token response carried no value\");\n }\n return body.value;\n}\n", "/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\nexport interface PilotPacket {\n runId: string;\n issueKey: string | null;\n branch: string | null;\n targetBranch: string | null;\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\n * repository root, as null \u2014 never normalised to \".\". */\n workspaceRoot: string | null;\n commands: {\n setup: string | null;\n test: string | null;\n e2e: string | null;\n lint: string | null;\n };\n guardrails: {\n deniedPaths: string[];\n maxHealIterations: number;\n maxWallClockMinutes: number;\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\n };\n /** Where to call for AI codegen, and the credential that authorizes it. */\n gateway: {\n baseUrl: string;\n token: string;\n };\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\n design: {\n rootCause: string;\n approach: string;\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\n apiChanges: { surface: string; change: string; reason: string }[];\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\n riskRationale: string;\n } | null;\n quikTest: { testRunId: string; resultsUrl: string } | null;\n}\n\ninterface PacketResponse {\n success: boolean;\n data: PilotPacket;\n}\n\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\n * invisible to `ps`, so no equivalent trick is needed here. */\nexport async function fetchPacket(\n packetUrl: string,\n runToken: string,\n githubRunId: string,\n): Promise<PilotPacket> {\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch work packet failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as PacketResponse;\n if (body.success !== true) {\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\n }\n return body.data;\n}\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\n\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\nexport function writePhase0Marker(runId: string): void {\n mkdirSync(\".quikpilot\", { recursive: true });\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\n}\n", "import { readdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\n\nfunction walkForJUnitByName(dir: string): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry)) continue;\n const full = join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n const found = walkForJUnitByName(full);\n if (found) return found;\n } else if (/^junit.*\\.xml$/.test(entry)) {\n return full;\n }\n }\n return null;\n}\n\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n const match = entries.find((e) => namePattern.test(e));\n return match ? join(dir, match) : null;\n}\n\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\n * common locations rather than a configurable setting. A project that writes its report elsewhere\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\n * in the same priority the original `find` clause listed them, though exact traversal order was\n * never guaranteed there either. */\nexport function findJUnitReport(cwd = process.cwd()): string | null {\n return (\n walkForJUnitByName(cwd) ??\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\n );\n}\n\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\n}\n\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. */\nexport async function reportToQuikTest(params: {\n resultsUrl: string | null | undefined;\n runToken: string;\n githubServerUrl: string;\n githubRepository: string;\n githubRunId: string;\n cwd?: string;\n}): Promise<void> {\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, cwd } = params;\n if (!resultsUrl) {\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\n return;\n }\n const report = findJUnitReport(cwd);\n if (!report) {\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\n return;\n }\n try {\n console.log(`reporting ${report}`);\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\n const { readFileSync } = await import(\"node:fs\");\n const body = readFileSync(report);\n const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\n body,\n });\n if (!res.ok) {\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\n }\n rmSync(report, { force: true });\n } catch (err) {\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n", "import { readFileSync } from \"node:fs\";\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\nimport { findJUnitReport } from \"./quiktest\";\n\n/**\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\n * passed before, fails now -> regression, block\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\n * common case, not an edge case \u2014 a different diagnosis from a\n * regression, so it's reported separately)\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\n *\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\n * automationIdFormat.\n */\nexport interface TestSnapshot {\n outcome: TestOutcome;\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\n * with no way to name what broke would contradict the whole point of the classification. */\n results: Map<string, boolean> | null;\n}\n\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\n\nfunction parseJUnitOutcomes(xml: string): Map<string, boolean> {\n const results = new Map<string, boolean>();\n let match: RegExpExecArray | null;\n TESTCASE_RE.lastIndex = 0;\n while ((match = TESTCASE_RE.exec(xml))) {\n const [, attrs, body = \"\"] = match;\n const name = NAME_ATTR_RE.exec(attrs)?.[1];\n if (!name) continue;\n const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\n const id = classname ? `${classname}::${name}` : name;\n results.set(id, !FAILURE_CHILD_RE.test(body));\n }\n return results;\n}\n\nfunction readJUnitOutcomes(cwd: string): Map<string, boolean> | null {\n const report = findJUnitReport(cwd);\n if (!report) return null;\n try {\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\n const outcome = runTestCommand(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport async function captureBaselineSnapshot(\n command: string | null,\n cwd = process.cwd(),\n): Promise<TestSnapshot> {\n const outcome = await runTestCommandAsync(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport interface RegressionCheck {\n blocked: boolean;\n regressions: string[];\n newFailures: string[];\n preExisting: string[];\n}\n\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\n if (!baseline.results || !after.results) {\n return { blocked: false, regressions: [], newFailures: [], preExisting: [] };\n }\n\n const regressions: string[] = [];\n const newFailures: string[] = [];\n const preExisting: string[] = [];\n\n for (const [testId, passed] of after.results) {\n if (passed) continue;\n const before = baseline.results.get(testId);\n if (before === true) regressions.push(testId);\n else if (before === false) preExisting.push(testId);\n else newFailures.push(testId);\n }\n\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };\n}\n\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\n * someone's morning (they're different diagnoses: one means the generated code broke something\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\n * noted, not hidden, so the message doesn't read as if they were silently dropped. */\nexport function describeRegressions(check: RegressionCheck): string {\n const parts: string[] = [];\n if (check.regressions.length > 0) {\n parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(\", \")}`);\n }\n if (check.newFailures.length > 0) {\n parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(\", \")}`);\n }\n if (check.preExisting.length > 0) {\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\n }\n return parts.join(\"; \");\n}\n", "import { resolve, relative, isAbsolute } from \"node:path\";\nimport { listFiles } from \"./git\";\nimport type { PilotPacket } from \"./packet\";\n\n/**\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\n * Runtime against a real 624-file QuikChat listing before this was wired in.\n */\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\n\nexport interface PilotTarget {\n path: string;\n kind: TargetKind;\n planStepsImplemented: string[];\n}\n\nexport type TargetingResult =\n | { outcome: \"TARGETED\"; targets: PilotTarget[] }\n | { outcome: \"NO_TARGET\"; reason: string | null };\n\ninterface TargetingResponse {\n outcome?: \"TARGETED\" | \"NO_TARGET\";\n targets?: { path: string; kind: string; planStepsImplemented: string[] }[];\n noTargetReason?: string;\n}\n\n/**\n * Tracked files under the packet's workspace root, or the whole checkout when it's null\n * (QUIKTR-1033) \u2014 never normalised to \".\" at the packet layer itself, only here where a concrete\n * pathspec is actually needed. An unscoped listing on a large monorepo is ~210k tokens, which fits\n * one provider and breaks the fallback chain \u2014 see workspaceRoot's own doc comment on PilotPacket.\n */\nexport function listWorkspaceFiles(workspaceRoot: string | null): string[] {\n return listFiles(workspaceRoot ?? \".\");\n}\n\n/**\n * VALIDATION IS OURS \u2014 the AI Runtime's schema doesn't guarantee a path is actually safe to write.\n * An EXISTING target must already be in the checkout; a NEW_FILE target must resolve inside the\n * workspace root. Either failure throws \u2014 a dropped target is a plan half-executed, and run.ts's\n * existing top-level try/catch already turns this into the same hard failure any other pre-setup\n * step gets.\n */\nfunction validateTarget(\n target: { path: string; kind: string },\n workspaceRoot: string | null,\n workspaceListing: Set<string>,\n): void {\n if (target.kind !== \"EXISTING\" && target.kind !== \"NEW_FILE\") {\n throw new Error(`pilot.targeting returned an unknown kind \"${target.kind}\" for ${target.path}`);\n }\n if (target.kind === \"EXISTING\") {\n if (!workspaceListing.has(target.path)) {\n throw new Error(\n `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`,\n );\n }\n return;\n }\n const root = resolve(workspaceRoot ?? \".\");\n const rel = relative(root, resolve(target.path));\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(\n `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`,\n );\n }\n}\n\nexport async function runTargeting(\n gateway: PilotPacket[\"gateway\"],\n design: PilotPacket[\"design\"],\n workspaceRoot: string | null,\n workspaceListing: string[],\n): Promise<TargetingResult> {\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.targeting\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n // NESTED, NOT FLATTENED \u2014 a second vocabulary for the design shape is exactly what\n // QUIKTR-1034 cost.\n contextData: { workspaceListing, design },\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);\n }\n\n const body = (await res.json()) as TargetingResponse;\n\n if (body.outcome === \"NO_TARGET\") {\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\n }\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\n throw new Error(`pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`);\n }\n\n const listing = new Set(workspaceListing);\n for (const target of body.targets) {\n validateTarget(target, workspaceRoot, listing);\n }\n\n return { outcome: \"TARGETED\", targets: body.targets as PilotTarget[] };\n}\n", "interface TokenExchangeResponse {\n success: boolean;\n data: { runToken: string; expiresAt: string };\n}\n\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\n const res = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${oidcToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange run token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as TokenExchangeResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\n }\n return body.data.runToken;\n}\n", "import { reportBack } from \"./callback\";\nimport { runCommand, runTestCommand } from \"./commands\";\nimport { commitAndPush } from \"./commit\";\nimport { flushCodegenResults, runCodegen } from \"./codegen\";\nimport { readRunnerEnv } from \"./env\";\nimport { checkGuardrail } from \"./guardrail\";\nimport { checkoutTargetBranch } from \"./git\";\nimport { exchangeForInstallationToken } from \"./installationToken\";\nimport { fetchGithubOidcToken } from \"./oidc\";\nimport { fetchPacket, type PilotPacket } from \"./packet\";\nimport { writePhase0Marker } from \"./phase0\";\nimport { reportToQuikTest } from \"./quiktest\";\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\nimport { listWorkspaceFiles, runTargeting } from \"./targeting\";\nimport { exchangeForRunToken } from \"./tokenExchange\";\n\n/**\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\n *\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\n *\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\n * reportToQuikTest/reportBack fire normally either way.\n */\nexport async function run(env = readRunnerEnv()): Promise<{ hardFailure: boolean }> {\n let hardFailure = false;\n let packet: PilotPacket | undefined;\n let branch: string | undefined;\n let runToken: string | undefined;\n\n try {\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\n checkoutTargetBranch(packet.targetBranch);\n\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\n const targeting = await runTargeting(\n packet.gateway,\n packet.design,\n packet.workspaceRoot,\n workspaceListing,\n );\n if (targeting.outcome === \"NO_TARGET\") {\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\n writePhase0Marker(env.runId);\n runCommand(packet.commands.setup, \"Setup\");\n runCommand(packet.commands.lint, \"Lint\");\n runTestCommand(packet.commands.test);\n } else {\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\n // dependencies doesn't depend on which application source files exist, so this is safe, and\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\n runCommand(packet.commands.setup, \"Setup\");\n\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\n // until flushCodegenResults, so there's nothing for the baseline to race against.\n const [baseline, results] = await Promise.all([\n captureBaselineSnapshot(packet.commands.test),\n runCodegen(packet.gateway, targeting.targets, workspaceListing),\n ]);\n\n flushCodegenResults(results);\n runCommand(packet.commands.lint, \"Lint\");\n\n const after = captureTestSnapshot(packet.commands.test);\n const check = checkForRegressions(baseline, after);\n if (check.blocked) {\n throw new Error(\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\n );\n }\n }\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n\n if (!runToken) {\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\n return { hardFailure: true };\n }\n\n await reportToQuikTest({\n resultsUrl: packet?.quikTest?.resultsUrl,\n runToken,\n githubServerUrl: env.githubServerUrl,\n githubRepository: env.githubRepository,\n githubRunId: env.githubRunId,\n });\n\n if (!hardFailure && packet) {\n try {\n checkGuardrail(packet.guardrails.deniedPaths);\n const installationToken = await exchangeForInstallationToken(\n env.installationTokenUrl,\n runToken,\n );\n const result = commitAndPush(packet.branch, env.runId, installationToken);\n branch = result.branch;\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n }\n\n await reportBack({\n callbackUrl: env.callbackUrl,\n runToken,\n status: hardFailure ? \"failed\" : \"completed\",\n branch,\n });\n\n return { hardFailure };\n}\n", "import { run } from \"./run\";\n\nrun()\n .then(({ hardFailure }) => {\n process.exitCode = hardFailure ? 1 : 0;\n })\n .catch((err) => {\n // reportBack itself throwing is the one failure mode `run()` can't recover from internally \u2014\n // still exit non-zero so the raw Actions UI shows the run as failed.\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n });\n"],
5
- "mappings": "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",
6
- "names": ["resolve", "import_node_child_process", "import_node_fs", "import_node_fs", "import_node_path", "readFileSync", "import_node_fs", "import_node_path"]
3
+ "sources": ["../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/envelope.ts", "../src/dependencyCheck.ts", "../src/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/regressionCheck.ts", "../src/targeting.ts", "../src/tokenExchange.ts", "../src/run.ts", "../src/index.ts"],
4
+ "sourcesContent": ["export type RunStatus = \"completed\" | \"failed\";\n\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. */\nexport async function reportBack(params: {\n callbackUrl: string;\n runToken: string;\n status: RunStatus;\n branch?: string;\n}): Promise<void> {\n const { callbackUrl, runToken, status, branch } = params;\n const body: Record<string, string> = { status };\n if (branch) body.branch = branch;\n const res = await fetch(callbackUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`Report back to QuikTrack failed: ${res.status} ${res.statusText}`);\n }\n}\n", "import { execSync, spawn } from \"node:child_process\";\n\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\nexport function runCommand(command: string | null, label: string): void {\n if (!command) return;\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nexport type TestOutcome = \"success\" | \"failure\";\n\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\nexport function runTestCommand(command: string | null): TestOutcome {\n if (!command) return \"success\";\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n return \"success\";\n } catch {\n return \"failure\";\n }\n}\n\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\n if (!command) return Promise.resolve(\"success\");\n return new Promise((resolve) => {\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\n child.on(\"error\", () => resolve(\"failure\"));\n });\n}\n", "import { execFileSync } from \"node:child_process\";\n\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\n * on top of the inherited environment; every existing call site is unaffected since it defaults\n * to empty. */\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\n return execFileSync(\"git\", args, {\n encoding: \"utf8\",\n env: { ...process.env, ...extraEnv },\n }).trim();\n}\n\nexport function currentBranch(): string {\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n}\n\n/** Only fetches + checks out when the packet names a target branch different from the one the\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\nexport function checkoutTargetBranch(targetBranch: string | null): void {\n if (!targetBranch || targetBranch === currentBranch()) return;\n git([\"fetch\", \"origin\", targetBranch]);\n git([\"checkout\", targetBranch]);\n}\n\nexport function addAll(): void {\n git([\"add\", \"-A\"]);\n}\n\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\n * getting wrong. */\nexport function diffCachedNamesMatching(pattern: string): string[] {\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\n * targeting.ts's workspaceRoot concept, not a generic git one. */\nexport function listFiles(pathspec: string): string[] {\n const out = git([\"ls-files\", \"--\", pathspec]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\nexport function hasStagedChanges(): boolean {\n try {\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\n return false;\n } catch {\n return true;\n }\n}\n\nexport function configureCommitIdentity(): void {\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\n}\n\nexport function checkoutNewBranch(branch: string): void {\n git([\"checkout\", \"-b\", branch]);\n}\n\nexport function commit(message: string): void {\n git([\"commit\", \"-m\", message]);\n}\n\n/**\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\n * documented scheme for installation tokens over HTTPS git.\n *\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\n * runner's other credential. Scoped to this one invocation only; never persisted.\n *\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\n *\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\n */\nfunction clearCheckoutExtraHeader(): void {\n try {\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\n } catch (err: unknown) {\n const status = (err as { status?: number }).status;\n if (status !== 5) throw err;\n }\n}\n\nexport function push(branch: string, installationToken: string): void {\n clearCheckoutExtraHeader();\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\n GIT_CONFIG_COUNT: \"1\",\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\n });\n}\n", "import {\n checkoutNewBranch,\n commit,\n configureCommitIdentity,\n hasStagedChanges,\n push,\n} from \"./git\";\n\nexport interface CommitResult {\n changed: boolean;\n branch?: string;\n}\n\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\n * already computed and stored it, and two sources for one value will eventually disagree.\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\n * with \u2014 see git.ts's `push` for why. */\nexport function commitAndPush(\n branch: string | null,\n runId: string,\n installationToken: string,\n): CommitResult {\n if (!hasStagedChanges()) return { changed: false };\n if (!branch) {\n throw new Error(\"packet carried no branch name\");\n }\n configureCommitIdentity();\n checkoutNewBranch(branch);\n commit(`QuikPilot Phase 0 skeleton (run ${runId})`);\n push(branch, installationToken);\n return { changed: true, branch };\n}\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\nimport type { PilotTarget } from \"./targeting\";\n\n/**\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\n *\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\n * per-target: the route file and the service file need different instructions.\n *\n * \u2500\u2500 ALL-OR-NOTHING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\n * failed file instead of discarding the rest is the better long-run answer and belongs with\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\n *\n * `CODEGEN_FILE_TOO_LARGE` is the AI Runtime's own distinct error code, checked on their side\n * before dispatch \u2014 retrying hits the identical wall every time, so it is deliberately not\n * retried, same as every other failure here.\n *\n * \u2500\u2500 BUFFERED WRITES (QUIKTR-1035) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * `runCodegen` no longer writes anything \u2014 it collects `{targetPath, newContent}` in memory and\n * `flushCodegenResults` writes them all, only once every call has succeeded. Two independent\n * reasons: it makes all-or-nothing literally true for the working tree, not just the pull request\n * (today a failure on file 3 leaves files 1-2 already written even though the throw stops the\n * commit); and it lets the test baseline run against an untouched tree while codegen's network-\n * bound calls are still in flight (QUIKTR-1036 is what actually wires that concurrency up \u2014 this\n * only makes it possible).\n */\nconst FILE_TOO_LARGE_CODE = \"CODEGEN_FILE_TOO_LARGE\";\n\n/** The shape at `envelope.structuredJson` for `pilot.codegen` \u2014 NOT the envelope itself. A\n * refusal's reason is `refusalReason`; the envelope has no `code`/`message` fields (those were\n * never real \u2014 see envelope.ts). */\ninterface CodegenResult {\n outcome?: \"GENERATED\" | \"REFUSED\";\n newContent?: string;\n summary?: string;\n refusalReason?: string;\n}\n\nexport interface CodegenFileResult {\n targetPath: string;\n newContent: string;\n}\n\n/**\n * Nearest existing file by directory, walking from the target's own directory up toward the\n * workspace root. Stated assumption, not a general solution: this teaches the model HOW code is\n * written here (imports, relative paths, test framework) by proximity alone \u2014 a repo with\n * genuinely mixed per-directory conventions would need something smarter than \"nearest neighbor.\"\n */\nfunction findNearestSibling(targetPath: string, workspaceListing: string[]): string | null {\n let dir = dirname(targetPath);\n for (;;) {\n const candidate = workspaceListing.find((f) => f !== targetPath && dirname(f) === dir);\n if (candidate) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Run codegen for exactly the targets named, in order, stopping at the first failure. Throws\n * rather than returning a partial result \u2014 see the ALL-OR-NOTHING note above; a caller that wants\n * to know how far it got before failing should catch and inspect the message, not branch on a\n * return value that implies partial success is a valid state. Writes nothing \u2014 call\n * `flushCodegenResults` with the return value once this resolves.\n */\nexport async function runCodegen(\n gateway: PilotPacket[\"gateway\"],\n targets: PilotTarget[],\n workspaceListing: string[],\n): Promise<CodegenFileResult[]> {\n const results: CodegenFileResult[] = [];\n\n for (const target of targets) {\n const isNewFile = target.kind === \"NEW_FILE\";\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\n\n const contextData: Record<string, unknown> = {\n targetPath: target.path,\n currentContent,\n planSteps: target.planStepsImplemented,\n kind: target.kind,\n };\n if (isNewFile) {\n // Bounds WHAT EXISTS (stops an invented import like hooks/useGroups) and teaches HOW code is\n // written (siblingContent) \u2014 neither alone is enough, and both are only meaningful for a\n // file that doesn't exist yet to compare against.\n contextData.workspaceListing = workspaceListing;\n const sibling = findNearestSibling(target.path, workspaceListing);\n if (sibling) contextData.siblingContent = readFileSync(sibling, \"utf8\");\n }\n\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.codegen\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n contextData,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n // CODEGEN_FILE_TOO_LARGE is checked on the RAW envelope, before unwrapping: it arrives as a\n // failure (success:false), so unwrapping first would throw the generic envelope error and\n // lose the not-retried distinction this check exists to preserve.\n const envelope: any = await res.json();\n if (envelope?.errorCode === FILE_TOO_LARGE_CODE) {\n throw new Error(`Codegen refused ${target.path}: ${FILE_TOO_LARGE_CODE} (not retried)`);\n }\n\n const body = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\n\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\n throw new Error(\n `Codegen refused ${target.path}${body.refusalReason ? `: ${body.refusalReason}` : \"\"}`,\n );\n }\n\n results.push({ targetPath: target.path, newContent: body.newContent });\n }\n\n return results;\n}\n\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\n for (const { targetPath, newContent } of results) {\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, newContent);\n }\n}\n", "/**\n * QUIKTR-1046 \u2014 `/ai/execute` wraps every use-case result in an envelope; the use-case's own result\n * lives at `envelope.structuredJson`, not at the top level. Both `targeting.ts` and `codegen.ts`\n * read the raw response directly and have never worked against a real reply \u2014 this is the one\n * place that unwraps it, so there is exactly one place to get it right.\n *\n * A failed call can arrive as `success: false` in an HTTP 200 body \u2014 `res.ok` alone is not enough.\n * Observed live 2026-09-18/19/21, including a real RUN_CREDENTIAL_SCOPE refusal shaped exactly\n * like this.\n */\nexport function unwrapExecute<T>(envelope: any, useCase: string): T {\n if (envelope?.success === false) {\n throw new Error(\n `${useCase} failed: ${envelope.errorCode ?? \"UNKNOWN\"} \u2014 ` +\n `${envelope.error ?? envelope.normalizedText ?? \"no message\"}`,\n );\n }\n if (!envelope?.structuredJson || typeof envelope.structuredJson !== \"object\") {\n throw new Error(`${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`);\n }\n return envelope.structuredJson as T;\n}\n", "import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport type { CodegenFileResult } from \"./codegen\";\n\n/**\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\n *\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\n *\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\n */\nexport interface DependencyViolation {\n file: string;\n packages: string[];\n}\n\nexport interface DependencyCheck {\n blocked: boolean;\n violations: DependencyViolation[];\n}\n\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\n\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\n\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\nconst NODE_BUILTINS = new Set([\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\n]);\n\nfunction packageNameFromSpecifier(specifier: string): string | null {\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\n const segments = specifier.split(\"/\");\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\n if (NODE_BUILTINS.has(name)) return null;\n return name;\n}\n\nfunction scanImports(source: string): string[] {\n const found = new Set<string>();\n let match: RegExpExecArray | null;\n IMPORT_RE.lastIndex = 0;\n while ((match = IMPORT_RE.exec(source))) {\n const name = packageNameFromSpecifier(match[2]);\n if (name) found.add(name);\n }\n return [...found];\n}\n\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\n * blocking on a question it can't actually answer. */\nexport function checkImportDependencies(\n results: CodegenFileResult[],\n declaredDependencies: Set<string> | null,\n): DependencyCheck {\n if (!declaredDependencies) return { blocked: false, violations: [] };\n\n const violations: DependencyViolation[] = [];\n for (const { targetPath, newContent } of results) {\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\n const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\n }\n return { blocked: violations.length > 0, violations };\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nfunction dependencyNames(pkg: PackageJson): Set<string> {\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\n return new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]);\n}\n\n/**\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\n */\nexport function readDeclaredDependencies(\n results: CodegenFileResult[],\n workspaceRoot: string | null,\n): Set<string> | null {\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\n\n let raw: string | null;\n if (generated) {\n raw = generated.newContent;\n } else {\n try {\n raw = readFileSync(packageJsonPath, \"utf8\");\n } catch {\n raw = null;\n }\n }\n if (raw === null) return null;\n\n try {\n return dependencyNames(JSON.parse(raw) as PackageJson);\n } catch {\n return null;\n }\n}\n\n/** Regressions and new failures named separately elsewhere in this package for the same reason\n * this exists at all: conflating diagnoses wastes someone's morning. */\nexport function describeDependencyViolations(check: DependencyCheck): string {\n return check.violations\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\n .join(\"; \");\n}\n", "/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\n * generated workflow file still passes them through as job-level env vars under these exact\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\nexport interface RunnerEnv {\n runId: string;\n callbackUrl: string;\n packetUrl: string;\n tokenUrl: string;\n installationTokenUrl: string;\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\n * individually. */\n githubRunId: string;\n githubServerUrl: string;\n githubRepository: string;\n}\n\nexport function required(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\n return {\n runId: required(\"RUN_ID\", env.RUN_ID),\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\n githubRunId: required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID),\n githubServerUrl: env.GITHUB_SERVER_URL ?? \"https://github.com\",\n githubRepository: required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY),\n };\n}\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\n\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\nexport function checkGuardrail(deniedPaths: string[]): void {\n addAll();\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\n if (violations.length > 0) {\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\n }\n}\n", "interface InstallationTokenResponse {\n success: boolean;\n data: { token: string; expiresAt: string };\n}\n\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\n * envelope, same error-message style. */\nexport async function exchangeForInstallationToken(\n installationTokenUrl: string,\n runToken: string,\n): Promise<string> {\n const res = await fetch(installationTokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange installation token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as InstallationTokenResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\n }\n return body.data.token;\n}\n", "import { required } from \"./env\";\n\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\n * verifies the token this package requests. Duplicated because this package is published outside\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\n * duplicating `PilotPacket`'s shape. */\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\n\ninterface OidcTokenResponse {\n value: string;\n}\n\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\nexport async function fetchGithubOidcToken(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n const requestUrl = required(\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\n );\n const requestToken = required(\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\n );\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${requestToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as OidcTokenResponse;\n if (!body.value) {\n throw new Error(\"GitHub OIDC token response carried no value\");\n }\n return body.value;\n}\n", "/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\nexport interface PilotPacket {\n runId: string;\n issueKey: string | null;\n branch: string | null;\n targetBranch: string | null;\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\n * repository root, as null \u2014 never normalised to \".\". */\n workspaceRoot: string | null;\n commands: {\n setup: string | null;\n test: string | null;\n e2e: string | null;\n lint: string | null;\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\n format: string | null;\n };\n guardrails: {\n deniedPaths: string[];\n maxHealIterations: number;\n maxWallClockMinutes: number;\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\n };\n /** Where to call for AI codegen, and the credential that authorizes it. */\n gateway: {\n baseUrl: string;\n token: string;\n };\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\n design: {\n rootCause: string;\n approach: string;\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\n apiChanges: { surface: string; change: string; reason: string }[];\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\n riskRationale: string;\n } | null;\n quikTest: { testRunId: string; resultsUrl: string } | null;\n}\n\ninterface PacketResponse {\n success: boolean;\n data: PilotPacket;\n}\n\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\n * invisible to `ps`, so no equivalent trick is needed here. */\nexport async function fetchPacket(\n packetUrl: string,\n runToken: string,\n githubRunId: string,\n): Promise<PilotPacket> {\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch work packet failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as PacketResponse;\n if (body.success !== true) {\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\n }\n return body.data;\n}\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\n\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\nexport function writePhase0Marker(runId: string): void {\n mkdirSync(\".quikpilot\", { recursive: true });\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\n}\n", "import { readdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\n\nfunction walkForJUnitByName(dir: string): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry)) continue;\n const full = join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n const found = walkForJUnitByName(full);\n if (found) return found;\n } else if (/^junit.*\\.xml$/.test(entry)) {\n return full;\n }\n }\n return null;\n}\n\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n const match = entries.find((e) => namePattern.test(e));\n return match ? join(dir, match) : null;\n}\n\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\n * common locations rather than a configurable setting. A project that writes its report elsewhere\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\n * in the same priority the original `find` clause listed them, though exact traversal order was\n * never guaranteed there either. */\nexport function findJUnitReport(cwd = process.cwd()): string | null {\n return (\n walkForJUnitByName(cwd) ??\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\n );\n}\n\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\n}\n\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. */\nexport async function reportToQuikTest(params: {\n resultsUrl: string | null | undefined;\n runToken: string;\n githubServerUrl: string;\n githubRepository: string;\n githubRunId: string;\n cwd?: string;\n}): Promise<void> {\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, cwd } = params;\n if (!resultsUrl) {\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\n return;\n }\n const report = findJUnitReport(cwd);\n if (!report) {\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\n return;\n }\n try {\n console.log(`reporting ${report}`);\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\n const { readFileSync } = await import(\"node:fs\");\n const body = readFileSync(report);\n const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\n body,\n });\n if (!res.ok) {\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\n }\n rmSync(report, { force: true });\n } catch (err) {\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n", "import { readFileSync } from \"node:fs\";\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\nimport { findJUnitReport } from \"./quiktest\";\n\n/**\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\n * passed before, fails now -> regression, block\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\n * common case, not an edge case \u2014 a different diagnosis from a\n * regression, so it's reported separately)\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\n *\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\n * automationIdFormat.\n */\nexport interface TestSnapshot {\n outcome: TestOutcome;\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\n * with no way to name what broke would contradict the whole point of the classification. */\n results: Map<string, boolean> | null;\n}\n\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\n\nfunction parseJUnitOutcomes(xml: string): Map<string, boolean> {\n const results = new Map<string, boolean>();\n let match: RegExpExecArray | null;\n TESTCASE_RE.lastIndex = 0;\n while ((match = TESTCASE_RE.exec(xml))) {\n const [, attrs, body = \"\"] = match;\n const name = NAME_ATTR_RE.exec(attrs)?.[1];\n if (!name) continue;\n const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\n const id = classname ? `${classname}::${name}` : name;\n results.set(id, !FAILURE_CHILD_RE.test(body));\n }\n return results;\n}\n\nfunction readJUnitOutcomes(cwd: string): Map<string, boolean> | null {\n const report = findJUnitReport(cwd);\n if (!report) return null;\n try {\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\n const outcome = runTestCommand(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport async function captureBaselineSnapshot(\n command: string | null,\n cwd = process.cwd(),\n): Promise<TestSnapshot> {\n const outcome = await runTestCommandAsync(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport interface RegressionCheck {\n blocked: boolean;\n regressions: string[];\n newFailures: string[];\n preExisting: string[];\n}\n\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\n if (!baseline.results || !after.results) {\n return { blocked: false, regressions: [], newFailures: [], preExisting: [] };\n }\n\n const regressions: string[] = [];\n const newFailures: string[] = [];\n const preExisting: string[] = [];\n\n for (const [testId, passed] of after.results) {\n if (passed) continue;\n const before = baseline.results.get(testId);\n if (before === true) regressions.push(testId);\n else if (before === false) preExisting.push(testId);\n else newFailures.push(testId);\n }\n\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };\n}\n\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\n * someone's morning (they're different diagnoses: one means the generated code broke something\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\n * noted, not hidden, so the message doesn't read as if they were silently dropped. */\nexport function describeRegressions(check: RegressionCheck): string {\n const parts: string[] = [];\n if (check.regressions.length > 0) {\n parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(\", \")}`);\n }\n if (check.newFailures.length > 0) {\n parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(\", \")}`);\n }\n if (check.preExisting.length > 0) {\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\n }\n return parts.join(\"; \");\n}\n", "import { resolve, relative, isAbsolute } from \"node:path\";\nimport { listFiles } from \"./git\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\n\n/**\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\n * Runtime against a real 624-file QuikChat listing before this was wired in.\n */\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\n\nexport interface PilotTarget {\n path: string;\n kind: TargetKind;\n planStepsImplemented: string[];\n}\n\nexport type TargetingResult =\n | { outcome: \"TARGETED\"; targets: PilotTarget[] }\n | { outcome: \"NO_TARGET\"; reason: string | null };\n\ninterface TargetingResponse {\n outcome?: \"TARGETED\" | \"NO_TARGET\";\n targets?: { path: string; kind: string; planStepsImplemented: string[] }[];\n noTargetReason?: string;\n}\n\n/**\n * Tracked files under the packet's workspace root, or the whole checkout when it's null\n * (QUIKTR-1033) \u2014 never normalised to \".\" at the packet layer itself, only here where a concrete\n * pathspec is actually needed. An unscoped listing on a large monorepo is ~210k tokens, which fits\n * one provider and breaks the fallback chain \u2014 see workspaceRoot's own doc comment on PilotPacket.\n */\nexport function listWorkspaceFiles(workspaceRoot: string | null): string[] {\n return listFiles(workspaceRoot ?? \".\");\n}\n\n/**\n * VALIDATION IS OURS \u2014 the AI Runtime's schema doesn't guarantee a path is actually safe to write.\n * An EXISTING target must already be in the checkout; a NEW_FILE target must resolve inside the\n * workspace root. Either failure throws \u2014 a dropped target is a plan half-executed, and run.ts's\n * existing top-level try/catch already turns this into the same hard failure any other pre-setup\n * step gets.\n */\nfunction validateTarget(\n target: { path: string; kind: string },\n workspaceRoot: string | null,\n workspaceListing: Set<string>,\n): void {\n if (target.kind !== \"EXISTING\" && target.kind !== \"NEW_FILE\") {\n throw new Error(`pilot.targeting returned an unknown kind \"${target.kind}\" for ${target.path}`);\n }\n if (target.kind === \"EXISTING\") {\n if (!workspaceListing.has(target.path)) {\n throw new Error(\n `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`,\n );\n }\n return;\n }\n const root = resolve(workspaceRoot ?? \".\");\n const rel = relative(root, resolve(target.path));\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(\n `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`,\n );\n }\n}\n\nexport async function runTargeting(\n gateway: PilotPacket[\"gateway\"],\n design: PilotPacket[\"design\"],\n workspaceRoot: string | null,\n workspaceListing: string[],\n): Promise<TargetingResult> {\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.targeting\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n // NESTED, NOT FLATTENED \u2014 a second vocabulary for the design shape is exactly what\n // QUIKTR-1034 cost.\n contextData: { workspaceListing, design },\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n const envelope = await res.json();\n const body = unwrapExecute<TargetingResponse>(envelope, \"pilot.targeting\");\n\n if (body.outcome === \"NO_TARGET\") {\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\n }\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\n throw new Error(`pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`);\n }\n\n const listing = new Set(workspaceListing);\n for (const target of body.targets) {\n validateTarget(target, workspaceRoot, listing);\n }\n\n return { outcome: \"TARGETED\", targets: body.targets as PilotTarget[] };\n}\n", "interface TokenExchangeResponse {\n success: boolean;\n data: { runToken: string; expiresAt: string };\n}\n\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\n const res = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${oidcToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange run token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as TokenExchangeResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\n }\n return body.data.runToken;\n}\n", "import { reportBack } from \"./callback\";\nimport { runCommand, runTestCommand } from \"./commands\";\nimport { commitAndPush } from \"./commit\";\nimport { flushCodegenResults, runCodegen } from \"./codegen\";\nimport { checkImportDependencies, describeDependencyViolations, readDeclaredDependencies } from \"./dependencyCheck\";\nimport { readRunnerEnv } from \"./env\";\nimport { checkGuardrail } from \"./guardrail\";\nimport { checkoutTargetBranch } from \"./git\";\nimport { exchangeForInstallationToken } from \"./installationToken\";\nimport { fetchGithubOidcToken } from \"./oidc\";\nimport { fetchPacket, type PilotPacket } from \"./packet\";\nimport { writePhase0Marker } from \"./phase0\";\nimport { reportToQuikTest } from \"./quiktest\";\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\nimport { listWorkspaceFiles, runTargeting } from \"./targeting\";\nimport { exchangeForRunToken } from \"./tokenExchange\";\n\n/**\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\n *\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\n *\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\n *\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\n * reportToQuikTest/reportBack fire normally either way.\n */\nexport async function run(env = readRunnerEnv()): Promise<{ hardFailure: boolean }> {\n let hardFailure = false;\n let packet: PilotPacket | undefined;\n let branch: string | undefined;\n let runToken: string | undefined;\n\n try {\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\n checkoutTargetBranch(packet.targetBranch);\n\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\n const targeting = await runTargeting(\n packet.gateway,\n packet.design,\n packet.workspaceRoot,\n workspaceListing,\n );\n if (targeting.outcome === \"NO_TARGET\") {\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\n writePhase0Marker(env.runId);\n runCommand(packet.commands.setup, \"Setup\");\n runCommand(packet.commands.lint, \"Lint\");\n runTestCommand(packet.commands.test);\n } else {\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\n // dependencies doesn't depend on which application source files exist, so this is safe, and\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\n runCommand(packet.commands.setup, \"Setup\");\n\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\n // until flushCodegenResults, so there's nothing for the baseline to race against.\n const [baseline, results] = await Promise.all([\n captureBaselineSnapshot(packet.commands.test),\n runCodegen(packet.gateway, targeting.targets, workspaceListing),\n ]);\n\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\n // written: an invented import is never written to disk at all, matching\n // the same all-or-nothing treatment every other codegen failure already\n // gets here. Hard failure \u2014 a generation that imports a package this\n // repository doesn't have can't be trusted.\n const depCheck = checkImportDependencies(\n results,\n readDeclaredDependencies(results, packet.workspaceRoot),\n );\n if (depCheck.blocked) {\n throw new Error(\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\n );\n }\n\n flushCodegenResults(results);\n try {\n runCommand(packet.commands.format, \"Format\");\n } catch (err) {\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\n }\n runCommand(packet.commands.lint, \"Lint\");\n\n const after = captureTestSnapshot(packet.commands.test);\n const check = checkForRegressions(baseline, after);\n if (check.blocked) {\n throw new Error(\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\n );\n }\n }\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n\n if (!runToken) {\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\n return { hardFailure: true };\n }\n\n await reportToQuikTest({\n resultsUrl: packet?.quikTest?.resultsUrl,\n runToken,\n githubServerUrl: env.githubServerUrl,\n githubRepository: env.githubRepository,\n githubRunId: env.githubRunId,\n });\n\n if (!hardFailure && packet) {\n try {\n checkGuardrail(packet.guardrails.deniedPaths);\n const installationToken = await exchangeForInstallationToken(\n env.installationTokenUrl,\n runToken,\n );\n const result = commitAndPush(packet.branch, env.runId, installationToken);\n branch = result.branch;\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n }\n\n await reportBack({\n callbackUrl: env.callbackUrl,\n runToken,\n status: hardFailure ? \"failed\" : \"completed\",\n branch,\n });\n\n return { hardFailure };\n}\n", "import { run } from \"./run\";\n\nrun()\n .then(({ hardFailure }) => {\n process.exitCode = hardFailure ? 1 : 0;\n })\n .catch((err) => {\n // reportBack itself throwing is the one failure mode `run()` can't recover from internally \u2014\n // still exit non-zero so the raw Actions UI shows the run as failed.\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n });\n"],
5
+ "mappings": "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",
6
+ "names": ["resolve", "import_node_child_process", "import_node_fs", "import_node_path", "import_node_fs", "import_node_fs", "import_node_path", "readFileSync", "import_node_fs", "import_node_path"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quikit/quikpilot-runner",
3
- "version": "7.0.3",
3
+ "version": "7.0.5",
4
4
  "description": "QuikPilot's CI runner. Fetches the run's work packet, runs setup/lint/test, reports results to QuikTest, enforces path guardrails, commits and pushes, and reports back to QuikTrack. Published publicly (Q12): the workflow file that invokes it lives in the customer's own repository, so this package is how a fix ships without a new pull request into every onboarded repo.",
5
5
  "bin": {
6
6
  "quikpilot-runner": "./dist/index.js"