@quikit/quikpilot-runner 7.0.2 → 7.0.3

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
@@ -57,6 +57,14 @@ function runTestCommand(command) {
57
57
  return "failure";
58
58
  }
59
59
  }
60
+ function runTestCommandAsync(command) {
61
+ if (!command) return Promise.resolve("success");
62
+ return new Promise((resolve2) => {
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"));
66
+ });
67
+ }
60
68
 
61
69
  // src/git.ts
62
70
  var import_node_child_process2 = require("node:child_process");
@@ -81,6 +89,10 @@ function diffCachedNamesMatching(pattern) {
81
89
  const out = git(["diff", "--cached", "--name-only", "--", `:(glob)${pattern}`]);
82
90
  return out ? out.split("\n").filter(Boolean) : [];
83
91
  }
92
+ function listFiles(pathspec) {
93
+ const out = git(["ls-files", "--", pathspec]);
94
+ return out ? out.split("\n").filter(Boolean) : [];
95
+ }
84
96
  function hasStagedChanges() {
85
97
  try {
86
98
  (0, import_node_child_process2.execFileSync)("git", ["diff", "--cached", "--quiet"]);
@@ -130,6 +142,70 @@ function commitAndPush(branch, runId, installationToken) {
130
142
  return { changed: true, branch };
131
143
  }
132
144
 
145
+ // src/codegen.ts
146
+ var import_node_fs = require("node:fs");
147
+ var import_node_path = require("node:path");
148
+ var FILE_TOO_LARGE_CODE = "CODEGEN_FILE_TOO_LARGE";
149
+ function findNearestSibling(targetPath, workspaceListing) {
150
+ let dir = (0, import_node_path.dirname)(targetPath);
151
+ for (; ; ) {
152
+ const candidate = workspaceListing.find((f) => f !== targetPath && (0, import_node_path.dirname)(f) === dir);
153
+ if (candidate) return candidate;
154
+ const parent = (0, import_node_path.dirname)(dir);
155
+ if (parent === dir) return null;
156
+ dir = parent;
157
+ }
158
+ }
159
+ async function runCodegen(gateway, targets, workspaceListing) {
160
+ const results = [];
161
+ for (const target of targets) {
162
+ const isNewFile = target.kind === "NEW_FILE";
163
+ const currentContent = isNewFile ? "" : (0, import_node_fs.readFileSync)(target.path, "utf8");
164
+ const contextData = {
165
+ targetPath: target.path,
166
+ currentContent,
167
+ planSteps: target.planStepsImplemented,
168
+ kind: target.kind
169
+ };
170
+ if (isNewFile) {
171
+ contextData.workspaceListing = workspaceListing;
172
+ const sibling = findNearestSibling(target.path, workspaceListing);
173
+ if (sibling) contextData.siblingContent = (0, import_node_fs.readFileSync)(sibling, "utf8");
174
+ }
175
+ const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
176
+ method: "POST",
177
+ headers: { "content-type": "application/json", "x-run-token": gateway.token },
178
+ body: JSON.stringify({
179
+ appId: "quiktrack",
180
+ useCase: "pilot.codegen",
181
+ expectedOutputType: "json",
182
+ userPrompt: "",
183
+ contextData
184
+ })
185
+ });
186
+ if (!res.ok) {
187
+ throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);
188
+ }
189
+ const body = await res.json();
190
+ if (body.code === FILE_TOO_LARGE_CODE) {
191
+ throw new Error(`Codegen refused ${target.path}: ${FILE_TOO_LARGE_CODE} (not retried)`);
192
+ }
193
+ if (body.outcome !== "GENERATED" || typeof body.newContent !== "string") {
194
+ throw new Error(
195
+ `Codegen refused ${target.path}${body.message ? `: ${body.message}` : ""}`
196
+ );
197
+ }
198
+ results.push({ targetPath: target.path, newContent: body.newContent });
199
+ }
200
+ return results;
201
+ }
202
+ function flushCodegenResults(results) {
203
+ for (const { targetPath, newContent } of results) {
204
+ (0, import_node_fs.mkdirSync)((0, import_node_path.dirname)(targetPath), { recursive: true });
205
+ (0, import_node_fs.writeFileSync)(targetPath, newContent);
206
+ }
207
+ }
208
+
133
209
  // src/env.ts
134
210
  function required(name, value) {
135
211
  if (!value) {
@@ -219,30 +295,30 @@ async function fetchPacket(packetUrl, runToken, githubRunId) {
219
295
  }
220
296
 
221
297
  // src/phase0.ts
222
- var import_node_fs = require("node:fs");
298
+ var import_node_fs2 = require("node:fs");
223
299
  function writePhase0Marker(runId) {
224
- (0, import_node_fs.mkdirSync)(".quikpilot", { recursive: true });
225
- (0, import_node_fs.appendFileSync)(".quikpilot/phase0-marker.txt", `QuikPilot Phase 0 skeleton marker for run ${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}
226
302
  `);
227
303
  }
228
304
 
229
305
  // src/quiktest.ts
230
- var import_node_fs2 = require("node:fs");
231
- var import_node_path = require("node:path");
306
+ var import_node_fs3 = require("node:fs");
307
+ var import_node_path2 = require("node:path");
232
308
  var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".git"]);
233
309
  function walkForJUnitByName(dir) {
234
310
  let entries;
235
311
  try {
236
- entries = (0, import_node_fs2.readdirSync)(dir);
312
+ entries = (0, import_node_fs3.readdirSync)(dir);
237
313
  } catch {
238
314
  return null;
239
315
  }
240
316
  for (const entry of entries) {
241
317
  if (SKIP_DIRS.has(entry)) continue;
242
- const full = (0, import_node_path.join)(dir, entry);
318
+ const full = (0, import_node_path2.join)(dir, entry);
243
319
  let stat;
244
320
  try {
245
- stat = (0, import_node_fs2.statSync)(full);
321
+ stat = (0, import_node_fs3.statSync)(full);
246
322
  } catch {
247
323
  continue;
248
324
  }
@@ -258,15 +334,15 @@ function walkForJUnitByName(dir) {
258
334
  function firstXmlIn(dir, namePattern) {
259
335
  let entries;
260
336
  try {
261
- entries = (0, import_node_fs2.readdirSync)(dir);
337
+ entries = (0, import_node_fs3.readdirSync)(dir);
262
338
  } catch {
263
339
  return null;
264
340
  }
265
341
  const match = entries.find((e) => namePattern.test(e));
266
- return match ? (0, import_node_path.join)(dir, match) : null;
342
+ return match ? (0, import_node_path2.join)(dir, match) : null;
267
343
  }
268
344
  function findJUnitReport(cwd = process.cwd()) {
269
- return walkForJUnitByName(cwd) ?? firstXmlIn((0, import_node_path.join)(cwd, "test-results"), /\.xml$/) ?? firstXmlIn((0, import_node_path.join)(cwd, "reports"), /^junit.*\.xml$/) ?? firstXmlIn((0, import_node_path.join)(cwd, "target", "surefire-reports"), /\.xml$/);
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$/);
270
346
  }
271
347
  function buildCiUrl(serverUrl, repository, githubRunId) {
272
348
  return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;
@@ -285,8 +361,8 @@ async function reportToQuikTest(params) {
285
361
  try {
286
362
  console.log(`reporting ${report}`);
287
363
  const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);
288
- const { readFileSync } = await import("node:fs");
289
- const body = readFileSync(report);
364
+ const { readFileSync: readFileSync3 } = await import("node:fs");
365
+ const body = readFileSync3(report);
290
366
  const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;
291
367
  const res = await fetch(url, {
292
368
  method: "POST",
@@ -296,12 +372,135 @@ async function reportToQuikTest(params) {
296
372
  if (!res.ok) {
297
373
  throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);
298
374
  }
299
- (0, import_node_fs2.rmSync)(report, { force: true });
375
+ (0, import_node_fs3.rmSync)(report, { force: true });
300
376
  } catch (err) {
301
377
  console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);
302
378
  }
303
379
  }
304
380
 
381
+ // src/regressionCheck.ts
382
+ var import_node_fs4 = require("node:fs");
383
+ var TESTCASE_RE = /<testcase\b([^>]*?)(?:\/>|>([\s\S]*?)<\/testcase>)/g;
384
+ var NAME_ATTR_RE = /\bname="([^"]*)"/;
385
+ var CLASSNAME_ATTR_RE = /\bclassname="([^"]*)"/;
386
+ var FAILURE_CHILD_RE = /<failure\b|<error\b/;
387
+ function parseJUnitOutcomes(xml) {
388
+ const results = /* @__PURE__ */ new Map();
389
+ let match;
390
+ TESTCASE_RE.lastIndex = 0;
391
+ while (match = TESTCASE_RE.exec(xml)) {
392
+ const [, attrs, body = ""] = match;
393
+ const name = NAME_ATTR_RE.exec(attrs)?.[1];
394
+ if (!name) continue;
395
+ const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];
396
+ const id = classname ? `${classname}::${name}` : name;
397
+ results.set(id, !FAILURE_CHILD_RE.test(body));
398
+ }
399
+ return results;
400
+ }
401
+ function readJUnitOutcomes(cwd) {
402
+ const report = findJUnitReport(cwd);
403
+ if (!report) return null;
404
+ try {
405
+ return parseJUnitOutcomes((0, import_node_fs4.readFileSync)(report, "utf8"));
406
+ } catch {
407
+ return null;
408
+ }
409
+ }
410
+ function captureTestSnapshot(command, cwd = process.cwd()) {
411
+ const outcome = runTestCommand(command);
412
+ return { outcome, results: readJUnitOutcomes(cwd) };
413
+ }
414
+ async function captureBaselineSnapshot(command, cwd = process.cwd()) {
415
+ const outcome = await runTestCommandAsync(command);
416
+ return { outcome, results: readJUnitOutcomes(cwd) };
417
+ }
418
+ function checkForRegressions(baseline, after) {
419
+ if (!baseline.results || !after.results) {
420
+ return { blocked: false, regressions: [], newFailures: [], preExisting: [] };
421
+ }
422
+ const regressions = [];
423
+ const newFailures = [];
424
+ const preExisting = [];
425
+ for (const [testId, passed] of after.results) {
426
+ if (passed) continue;
427
+ const before = baseline.results.get(testId);
428
+ if (before === true) regressions.push(testId);
429
+ else if (before === false) preExisting.push(testId);
430
+ else newFailures.push(testId);
431
+ }
432
+ return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };
433
+ }
434
+ function describeRegressions(check) {
435
+ const parts = [];
436
+ if (check.regressions.length > 0) {
437
+ parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(", ")}`);
438
+ }
439
+ if (check.newFailures.length > 0) {
440
+ parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(", ")}`);
441
+ }
442
+ if (check.preExisting.length > 0) {
443
+ parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);
444
+ }
445
+ return parts.join("; ");
446
+ }
447
+
448
+ // src/targeting.ts
449
+ var import_node_path3 = require("node:path");
450
+ function listWorkspaceFiles(workspaceRoot) {
451
+ return listFiles(workspaceRoot ?? ".");
452
+ }
453
+ function validateTarget(target, workspaceRoot, workspaceListing) {
454
+ if (target.kind !== "EXISTING" && target.kind !== "NEW_FILE") {
455
+ throw new Error(`pilot.targeting returned an unknown kind "${target.kind}" for ${target.path}`);
456
+ }
457
+ if (target.kind === "EXISTING") {
458
+ if (!workspaceListing.has(target.path)) {
459
+ throw new Error(
460
+ `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`
461
+ );
462
+ }
463
+ return;
464
+ }
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)) {
468
+ throw new Error(
469
+ `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`
470
+ );
471
+ }
472
+ }
473
+ async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
474
+ const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
475
+ method: "POST",
476
+ headers: { "content-type": "application/json", "x-run-token": gateway.token },
477
+ body: JSON.stringify({
478
+ appId: "quiktrack",
479
+ useCase: "pilot.targeting",
480
+ expectedOutputType: "json",
481
+ userPrompt: "",
482
+ // NESTED, NOT FLATTENED — a second vocabulary for the design shape is exactly what
483
+ // QUIKTR-1034 cost.
484
+ contextData: { workspaceListing, design }
485
+ })
486
+ });
487
+ if (!res.ok) {
488
+ throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);
489
+ }
490
+ const body = await res.json();
491
+ if (body.outcome === "NO_TARGET") {
492
+ return { outcome: "NO_TARGET", reason: body.noTargetReason ?? null };
493
+ }
494
+ if (body.outcome !== "TARGETED" || !Array.isArray(body.targets)) {
495
+ throw new Error(`pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`);
496
+ }
497
+ const listing = new Set(workspaceListing);
498
+ for (const target of body.targets) {
499
+ validateTarget(target, workspaceRoot, listing);
500
+ }
501
+ return { outcome: "TARGETED", targets: body.targets };
502
+ }
503
+
305
504
  // src/tokenExchange.ts
306
505
  async function exchangeForRunToken(tokenUrl, oidcToken) {
307
506
  const res = await fetch(tokenUrl, {
@@ -328,10 +527,34 @@ async function run(env = readRunnerEnv()) {
328
527
  runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());
329
528
  packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);
330
529
  checkoutTargetBranch(packet.targetBranch);
331
- writePhase0Marker(env.runId);
332
- runCommand(packet.commands.setup, "Setup");
333
- runCommand(packet.commands.lint, "Lint");
334
- runTestCommand(packet.commands.test);
530
+ const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);
531
+ const targeting = await runTargeting(
532
+ packet.gateway,
533
+ packet.design,
534
+ packet.workspaceRoot,
535
+ workspaceListing
536
+ );
537
+ if (targeting.outcome === "NO_TARGET") {
538
+ writePhase0Marker(env.runId);
539
+ runCommand(packet.commands.setup, "Setup");
540
+ runCommand(packet.commands.lint, "Lint");
541
+ runTestCommand(packet.commands.test);
542
+ } else {
543
+ runCommand(packet.commands.setup, "Setup");
544
+ const [baseline, results] = await Promise.all([
545
+ captureBaselineSnapshot(packet.commands.test),
546
+ runCodegen(packet.gateway, targeting.targets, workspaceListing)
547
+ ]);
548
+ flushCodegenResults(results);
549
+ runCommand(packet.commands.lint, "Lint");
550
+ const after = captureTestSnapshot(packet.commands.test);
551
+ const check = checkForRegressions(baseline, after);
552
+ if (check.blocked) {
553
+ throw new Error(
554
+ `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`
555
+ );
556
+ }
557
+ }
335
558
  } catch (err) {
336
559
  hardFailure = true;
337
560
  console.error(err instanceof Error ? err.message : String(err));
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/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.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 } 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. */\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", "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\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", "/** 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 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 maxRunUsd: string;\n maxWallClockMinutes: number;\n };\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", "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 { 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 { 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 writePhase0Marker(env.runId);\n runCommand(packet.commands.setup, \"Setup\");\n runCommand(packet.commands.lint, \"Lint\");\n runTestCommand(packet.commands.test);\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": ";;;;;;;;;;;;;;;;;;;;;;;;;;AAKA,eAAsB,WAAW,QAKf;AAChB,QAAM,EAAE,aAAa,UAAU,QAAQ,OAAO,IAAI;AAClD,QAAM,OAA+B,EAAE,OAAO;AAC9C,MAAI,OAAQ,MAAK,SAAS;AAC1B,QAAM,MAAM,MAAM,MAAM,aAAa;AAAA,IACnC,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,QAAQ,IAAI,gBAAgB,mBAAmB;AAAA,IACnF,MAAM,KAAK,UAAU,IAAI;AAAA,EAC3B,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,oCAAoC,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EACpF;AACF;;;ACtBA,gCAAyB;AAKlB,SAAS,WAAW,SAAwB,OAAqB;AACtE,MAAI,CAAC,QAAS;AACd,MAAI;AACF,4CAAS,SAAS,EAAE,OAAO,aAAa,OAAO,UAAU,CAAC;AAAA,EAC5D,SAAS,KAAK;AACZ,UAAM,IAAI,MAAM,GAAG,KAAK,YAAY,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EACxF;AACF;AAOO,SAAS,eAAe,SAAqC;AAClE,MAAI,CAAC,QAAS,QAAO;AACrB,MAAI;AACF,4CAAS,SAAS,EAAE,OAAO,aAAa,OAAO,UAAU,CAAC;AAC1D,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AC3BA,IAAAA,6BAA6B;AAM7B,SAAS,IAAI,MAAgB,WAA8B,CAAC,GAAW;AACrE,aAAO,yCAAa,OAAO,MAAM;AAAA,IAC/B,UAAU;AAAA,IACV,KAAK,EAAE,GAAG,QAAQ,KAAK,GAAG,SAAS;AAAA,EACrC,CAAC,EAAE,KAAK;AACV;AAEO,SAAS,gBAAwB;AACtC,SAAO,IAAI,CAAC,aAAa,gBAAgB,MAAM,CAAC;AAClD;AAKO,SAAS,qBAAqB,cAAmC;AACtE,MAAI,CAAC,gBAAgB,iBAAiB,cAAc,EAAG;AACvD,MAAI,CAAC,SAAS,UAAU,YAAY,CAAC;AACrC,MAAI,CAAC,YAAY,YAAY,CAAC;AAChC;AAEO,SAAS,SAAe;AAC7B,MAAI,CAAC,OAAO,IAAI,CAAC;AACnB;AAIO,SAAS,wBAAwB,SAA2B;AACjE,QAAM,MAAM,IAAI,CAAC,QAAQ,YAAY,eAAe,MAAM,UAAU,OAAO,EAAE,CAAC;AAC9E,SAAO,MAAM,IAAI,MAAM,IAAI,EAAE,OAAO,OAAO,IAAI,CAAC;AAClD;AAEO,SAAS,mBAA4B;AAC1C,MAAI;AACF,iDAAa,OAAO,CAAC,QAAQ,YAAY,SAAS,CAAC;AACnD,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,0BAAgC;AAC9C,MAAI,CAAC,UAAU,aAAa,gBAAgB,CAAC;AAC7C,MAAI,CAAC,UAAU,cAAc,oCAAoC,CAAC;AACpE;AAEO,SAAS,kBAAkB,QAAsB;AACtD,MAAI,CAAC,YAAY,MAAM,MAAM,CAAC;AAChC;AAEO,SAAS,OAAO,SAAuB;AAC5C,MAAI,CAAC,UAAU,MAAM,OAAO,CAAC;AAC/B;AA2BA,SAAS,2BAAiC;AACxC,MAAI;AACF,QAAI,CAAC,UAAU,eAAe,sCAAsC,CAAC;AAAA,EACvE,SAAS,KAAc;AACrB,UAAM,SAAU,IAA4B;AAC5C,QAAI,WAAW,EAAG,OAAM;AAAA,EAC1B;AACF;AAEO,SAAS,KAAK,QAAgB,mBAAiC;AACpE,2BAAyB;AACzB,QAAM,YAAY,OAAO,KAAK,kBAAkB,iBAAiB,EAAE,EAAE,SAAS,QAAQ;AACtF,MAAI,CAAC,QAAQ,kBAAkB,UAAU,MAAM,GAAG;AAAA,IAChD,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,oBAAoB,wBAAwB,SAAS;AAAA,EACvD,CAAC;AACH;;;AClFO,SAAS,cACd,QACA,OACA,mBACc;AACd,MAAI,CAAC,iBAAiB,EAAG,QAAO,EAAE,SAAS,MAAM;AACjD,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,+BAA+B;AAAA,EACjD;AACA,0BAAwB;AACxB,oBAAkB,MAAM;AACxB,SAAO,mCAAmC,KAAK,GAAG;AAClD,OAAK,QAAQ,iBAAiB;AAC9B,SAAO,EAAE,SAAS,MAAM,OAAO;AACjC;;;ACbO,SAAS,SAAS,MAAc,OAAmC;AACxE,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,0CAA0C,IAAI,EAAE;AAAA,EAClE;AACA,SAAO;AACT;AAEO,SAAS,cAAc,MAAyB,QAAQ,KAAgB;AAC7E,SAAO;AAAA,IACL,OAAO,SAAS,UAAU,IAAI,MAAM;AAAA,IACpC,aAAa,SAAS,gBAAgB,IAAI,YAAY;AAAA,IACtD,WAAW,SAAS,cAAc,IAAI,UAAU;AAAA,IAChD,UAAU,SAAS,aAAa,IAAI,SAAS;AAAA,IAC7C,sBAAsB,SAAS,0BAA0B,IAAI,sBAAsB;AAAA,IACnF,aAAa,SAAS,iBAAiB,IAAI,aAAa;AAAA,IACxD,iBAAiB,IAAI,qBAAqB;AAAA,IAC1C,kBAAkB,SAAS,qBAAqB,IAAI,iBAAiB;AAAA,EACvE;AACF;;;ACjCO,SAAS,eAAe,aAA6B;AAC1D,SAAO;AACP,QAAM,aAAa,YAAY,QAAQ,CAAC,YAAY,wBAAwB,OAAO,CAAC;AACpF,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,IAAI,MAAM;AAAA,EAAoC,WAAW,KAAK,IAAI,CAAC,EAAE;AAAA,EAC7E;AACF;;;ACHA,eAAsB,6BACpB,sBACA,UACiB;AACjB,QAAM,MAAM,MAAM,MAAM,sBAAsB;AAAA,IAC5C,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,QAAQ,GAAG;AAAA,EACjD,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,uCAAuC,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EACvF;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,KAAK,YAAY,MAAM;AACzB,UAAM,IAAI,MAAM,yEAAyE;AAAA,EAC3F;AACA,SAAO,KAAK,KAAK;AACnB;;;AClBA,IAAM,0BAA0B;AAUhC,eAAsB,qBACpB,MAAyB,QAAQ,KAChB;AACjB,QAAM,aAAa;AAAA,IACjB;AAAA,IACA,IAAI;AAAA,EACN;AACA,QAAM,eAAe;AAAA,IACnB;AAAA,IACA,IAAI;AAAA,EACN;AACA,QAAM,YAAY,WAAW,SAAS,GAAG,IAAI,MAAM;AACnD,QAAM,MAAM,GAAG,UAAU,GAAG,SAAS,YAAY,mBAAmB,uBAAuB,CAAC;AAC5F,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,eAAe,UAAU,YAAY,GAAG;AAAA,EACrD,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,mCAAmC,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EACnF;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,CAAC,KAAK,OAAO;AACf,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO,KAAK;AACd;;;ACVA,eAAsB,YACpB,WACA,UACA,aACsB;AACtB,QAAM,MAAM,GAAG,SAAS,gBAAgB,mBAAmB,WAAW,CAAC;AACvE,QAAM,MAAM,MAAM,MAAM,KAAK;AAAA,IAC3B,SAAS,EAAE,eAAe,UAAU,QAAQ,GAAG;AAAA,EACjD,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,6BAA6B,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EAC7E;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,KAAK,YAAY,MAAM;AACzB,UAAM,IAAI,MAAM,+DAA+D;AAAA,EACjF;AACA,SAAO,KAAK;AACd;;;AC/CA,qBAA0C;AAKnC,SAAS,kBAAkB,OAAqB;AACrD,gCAAU,cAAc,EAAE,WAAW,KAAK,CAAC;AAC3C,qCAAe,gCAAgC,6CAA6C,KAAK;AAAA,CAAI;AACvG;;;ACRA,IAAAC,kBAA8C;AAC9C,uBAAqB;AAErB,IAAM,YAAY,oBAAI,IAAI,CAAC,gBAAgB,MAAM,CAAC;AAElD,SAAS,mBAAmB,KAA4B;AACtD,MAAI;AACJ,MAAI;AACF,kBAAU,6BAAY,GAAG;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,aAAW,SAAS,SAAS;AAC3B,QAAI,UAAU,IAAI,KAAK,EAAG;AAC1B,UAAM,WAAO,uBAAK,KAAK,KAAK;AAC5B,QAAI;AACJ,QAAI;AACF,iBAAO,0BAAS,IAAI;AAAA,IACtB,QAAQ;AACN;AAAA,IACF;AACA,QAAI,KAAK,YAAY,GAAG;AACtB,YAAM,QAAQ,mBAAmB,IAAI;AACrC,UAAI,MAAO,QAAO;AAAA,IACpB,WAAW,iBAAiB,KAAK,KAAK,GAAG;AACvC,aAAO;AAAA,IACT;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,WAAW,KAAa,aAAoC;AACnE,MAAI;AACJ,MAAI;AACF,kBAAU,6BAAY,GAAG;AAAA,EAC3B,QAAQ;AACN,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,QAAQ,KAAK,CAAC,MAAM,YAAY,KAAK,CAAC,CAAC;AACrD,SAAO,YAAQ,uBAAK,KAAK,KAAK,IAAI;AACpC;AAOO,SAAS,gBAAgB,MAAM,QAAQ,IAAI,GAAkB;AAClE,SACE,mBAAmB,GAAG,KACtB,eAAW,uBAAK,KAAK,cAAc,GAAG,QAAQ,KAC9C,eAAW,uBAAK,KAAK,SAAS,GAAG,gBAAgB,KACjD,eAAW,uBAAK,KAAK,UAAU,kBAAkB,GAAG,QAAQ;AAEhE;AAEA,SAAS,WAAW,WAAmB,YAAoB,aAA6B;AACtF,SAAO,GAAG,SAAS,IAAI,UAAU,iBAAiB,WAAW;AAC/D;AAMA,eAAsB,iBAAiB,QAOrB;AAChB,QAAM,EAAE,YAAY,UAAU,iBAAiB,kBAAkB,aAAa,IAAI,IAAI;AACtF,MAAI,CAAC,YAAY;AACf,YAAQ,IAAI,6EAAwE;AACpF;AAAA,EACF;AACA,QAAM,SAAS,gBAAgB,GAAG;AAClC,MAAI,CAAC,QAAQ;AACX,YAAQ,KAAK,oFAA+E;AAC5F;AAAA,EACF;AACA,MAAI;AACF,YAAQ,IAAI,aAAa,MAAM,EAAE;AACjC,UAAM,QAAQ,WAAW,iBAAiB,kBAAkB,WAAW;AACvE,UAAM,EAAE,aAAa,IAAI,MAAM,OAAO,SAAS;AAC/C,UAAM,OAAO,aAAa,MAAM;AAChC,UAAM,MAAM,GAAG,UAAU,UAAU,mBAAmB,KAAK,CAAC;AAC5D,UAAM,MAAM,MAAM,MAAM,KAAK;AAAA,MAC3B,QAAQ;AAAA,MACR,SAAS,EAAE,eAAe,UAAU,QAAQ,IAAI,gBAAgB,WAAW;AAAA,MAC3E;AAAA,IACF,CAAC;AACD,QAAI,CAAC,IAAI,IAAI;AACX,YAAM,IAAI,MAAM,gCAAgC,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,IAChF;AACA,gCAAO,QAAQ,EAAE,OAAO,KAAK,CAAC;AAAA,EAChC,SAAS,KAAK;AACZ,YAAQ,KAAK,8DAA8D,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC,EAAE;AAAA,EAC/H;AACF;;;AC7FA,eAAsB,oBAAoB,UAAkB,WAAoC;AAC9F,QAAM,MAAM,MAAM,MAAM,UAAU;AAAA,IAChC,QAAQ;AAAA,IACR,SAAS,EAAE,eAAe,UAAU,SAAS,GAAG;AAAA,EAClD,CAAC;AACD,MAAI,CAAC,IAAI,IAAI;AACX,UAAM,IAAI,MAAM,8BAA8B,IAAI,MAAM,IAAI,IAAI,UAAU,EAAE;AAAA,EAC9E;AACA,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,MAAI,KAAK,YAAY,MAAM;AACzB,UAAM,IAAI,MAAM,gEAAgE;AAAA,EAClF;AACA,SAAO,KAAK,KAAK;AACnB;;;ACeA,eAAsB,IAAI,MAAM,cAAc,GAAsC;AAClF,MAAI,cAAc;AAClB,MAAI;AACJ,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,eAAW,MAAM,oBAAoB,IAAI,UAAU,MAAM,qBAAqB,CAAC;AAC/E,aAAS,MAAM,YAAY,IAAI,WAAW,UAAU,IAAI,WAAW;AACnE,yBAAqB,OAAO,YAAY;AACxC,sBAAkB,IAAI,KAAK;AAC3B,eAAW,OAAO,SAAS,OAAO,OAAO;AACzC,eAAW,OAAO,SAAS,MAAM,MAAM;AACvC,mBAAe,OAAO,SAAS,IAAI;AAAA,EACrC,SAAS,KAAK;AACZ,kBAAc;AACd,YAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EAChE;AAEA,MAAI,CAAC,UAAU;AACb,YAAQ,MAAM,iFAA4E;AAC1F,WAAO,EAAE,aAAa,KAAK;AAAA,EAC7B;AAEA,QAAM,iBAAiB;AAAA,IACrB,YAAY,QAAQ,UAAU;AAAA,IAC9B;AAAA,IACA,iBAAiB,IAAI;AAAA,IACrB,kBAAkB,IAAI;AAAA,IACtB,aAAa,IAAI;AAAA,EACnB,CAAC;AAED,MAAI,CAAC,eAAe,QAAQ;AAC1B,QAAI;AACF,qBAAe,OAAO,WAAW,WAAW;AAC5C,YAAM,oBAAoB,MAAM;AAAA,QAC9B,IAAI;AAAA,QACJ;AAAA,MACF;AACA,YAAM,SAAS,cAAc,OAAO,QAAQ,IAAI,OAAO,iBAAiB;AACxE,eAAS,OAAO;AAAA,IAClB,SAAS,KAAK;AACZ,oBAAc;AACd,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,IAChE;AAAA,EACF;AAEA,QAAM,WAAW;AAAA,IACf,aAAa,IAAI;AAAA,IACjB;AAAA,IACA,QAAQ,cAAc,WAAW;AAAA,IACjC;AAAA,EACF,CAAC;AAED,SAAO,EAAE,YAAY;AACvB;;;ACxFA,IAAI,EACD,KAAK,CAAC,EAAE,YAAY,MAAM;AACzB,UAAQ,WAAW,cAAc,IAAI;AACvC,CAAC,EACA,MAAM,CAAC,QAAQ;AAGd,UAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,UAAQ,WAAW;AACrB,CAAC;",
6
- "names": ["import_node_child_process", "import_node_fs"]
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"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quikit/quikpilot-runner",
3
- "version": "7.0.2",
3
+ "version": "7.0.3",
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"