@quikit/quikpilot-runner 7.0.4 → 7.0.6

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
@@ -25,9 +25,10 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/callback.ts
27
27
  async function reportBack(params) {
28
- const { callbackUrl, runToken, status, branch } = params;
28
+ const { callbackUrl, runToken, status, branch, warnings } = params;
29
29
  const body = { status };
30
30
  if (branch) body.branch = branch;
31
+ if (warnings && warnings.length > 0) body.warnings = warnings;
31
32
  const res = await fetch(callbackUrl, {
32
33
  method: "POST",
33
34
  headers: { Authorization: `Bearer ${runToken}`, "Content-Type": "application/json" },
@@ -130,14 +131,21 @@ function push(branch, installationToken) {
130
131
  }
131
132
 
132
133
  // src/commit.ts
133
- function commitAndPush(branch, runId, installationToken) {
134
+ function buildCommitMessage(runId, targeted, issueKey, issueTitle) {
135
+ if (!targeted) return `QuikPilot Phase 0 skeleton (run ${runId})`;
136
+ if (issueKey && issueTitle) return `${issueKey}: ${issueTitle}
137
+
138
+ QuikPilot run ${runId}`;
139
+ return `QuikPilot generated changes (run ${runId})`;
140
+ }
141
+ function commitAndPush(branch, runId, installationToken, targeted, issueKey, issueTitle) {
134
142
  if (!hasStagedChanges()) return { changed: false };
135
143
  if (!branch) {
136
144
  throw new Error("packet carried no branch name");
137
145
  }
138
146
  configureCommitIdentity();
139
147
  checkoutNewBranch(branch);
140
- commit(`QuikPilot Phase 0 skeleton (run ${runId})`);
148
+ commit(buildCommitMessage(runId, targeted, issueKey, issueTitle));
141
149
  push(branch, installationToken);
142
150
  return { changed: true, branch };
143
151
  }
@@ -145,32 +153,48 @@ function commitAndPush(branch, runId, installationToken) {
145
153
  // src/codegen.ts
146
154
  var import_node_fs = require("node:fs");
147
155
  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;
156
+
157
+ // src/envelope.ts
158
+ function unwrapExecute(envelope, useCase) {
159
+ if (envelope?.success === false) {
160
+ throw new Error(
161
+ `${useCase} failed: ${envelope.errorCode ?? "UNKNOWN"} \u2014 ${envelope.error ?? envelope.normalizedText ?? "no message"}`
162
+ );
163
+ }
164
+ if (!envelope?.structuredJson || typeof envelope.structuredJson !== "object") {
165
+ throw new Error(`${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`);
157
166
  }
167
+ return envelope.structuredJson;
158
168
  }
169
+
170
+ // src/codegen.ts
171
+ var FILE_TOO_LARGE_CODE = "CODEGEN_FILE_TOO_LARGE";
172
+ var CONTEXT_TOO_LARGE_CODE = "CODEGEN_CONTEXT_TOO_LARGE";
173
+ var NOT_RETRIED_CODES = /* @__PURE__ */ new Set([FILE_TOO_LARGE_CODE, CONTEXT_TOO_LARGE_CODE]);
159
174
  async function runCodegen(gateway, targets, workspaceListing) {
160
175
  const results = [];
176
+ const listing = new Set(workspaceListing);
161
177
  for (const target of targets) {
162
178
  const isNewFile = target.kind === "NEW_FILE";
163
179
  const currentContent = isNewFile ? "" : (0, import_node_fs.readFileSync)(target.path, "utf8");
180
+ const contextPaths = target.contextPaths ?? [];
181
+ for (const contextPath of contextPaths) {
182
+ if (!listing.has(contextPath)) {
183
+ throw new Error(
184
+ `pilot.codegen contextPaths named a file not found in the checkout: ${contextPath} (target ${target.path})`
185
+ );
186
+ }
187
+ }
188
+ const contextContents = contextPaths.map((path) => ({ path, content: (0, import_node_fs.readFileSync)(path, "utf8") }));
164
189
  const contextData = {
165
190
  targetPath: target.path,
166
191
  currentContent,
167
192
  planSteps: target.planStepsImplemented,
168
- kind: target.kind
193
+ kind: target.kind,
194
+ contextContents
169
195
  };
170
196
  if (isNewFile) {
171
197
  contextData.workspaceListing = workspaceListing;
172
- const sibling = findNearestSibling(target.path, workspaceListing);
173
- if (sibling) contextData.siblingContent = (0, import_node_fs.readFileSync)(sibling, "utf8");
174
198
  }
175
199
  const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
176
200
  method: "POST",
@@ -186,13 +210,15 @@ async function runCodegen(gateway, targets, workspaceListing) {
186
210
  if (!res.ok) {
187
211
  throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);
188
212
  }
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)`);
213
+ const envelope = await res.json();
214
+ if (typeof envelope?.errorCode === "string" && NOT_RETRIED_CODES.has(envelope.errorCode)) {
215
+ const detail = envelope.error ? `: ${envelope.error}` : "";
216
+ throw new Error(`Codegen refused ${target.path}: ${envelope.errorCode} (not retried)${detail}`);
192
217
  }
218
+ const body = unwrapExecute(envelope, "pilot.codegen");
193
219
  if (body.outcome !== "GENERATED" || typeof body.newContent !== "string") {
194
220
  throw new Error(
195
- `Codegen refused ${target.path}${body.message ? `: ${body.message}` : ""}`
221
+ `Codegen refused ${target.path}${body.refusalReason ? `: ${body.refusalReason}` : ""}`
196
222
  );
197
223
  }
198
224
  results.push({ targetPath: target.path, newContent: body.newContent });
@@ -249,30 +275,32 @@ var NODE_BUILTINS = /* @__PURE__ */ new Set([
249
275
  "inspector",
250
276
  "async_hooks"
251
277
  ]);
252
- function packageNameFromSpecifier(specifier) {
278
+ var DEFAULT_ALIAS_PREFIXES = ["@/", "~/"];
279
+ function packageNameFromSpecifier(specifier, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
253
280
  if (specifier.startsWith(".") || specifier.startsWith("/")) return null;
254
281
  if (specifier.startsWith("node:")) return null;
282
+ if (aliasPrefixes.some((prefix) => specifier.startsWith(prefix))) return null;
255
283
  const segments = specifier.split("/");
256
284
  const name = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
257
285
  if (NODE_BUILTINS.has(name)) return null;
258
286
  return name;
259
287
  }
260
- function scanImports(source) {
288
+ function scanImports(source, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
261
289
  const found = /* @__PURE__ */ new Set();
262
290
  let match;
263
291
  IMPORT_RE.lastIndex = 0;
264
292
  while (match = IMPORT_RE.exec(source)) {
265
- const name = packageNameFromSpecifier(match[2]);
293
+ const name = packageNameFromSpecifier(match[2], aliasPrefixes);
266
294
  if (name) found.add(name);
267
295
  }
268
296
  return [...found];
269
297
  }
270
- function checkImportDependencies(results, declaredDependencies) {
298
+ function checkImportDependencies(results, declaredDependencies, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
271
299
  if (!declaredDependencies) return { blocked: false, violations: [] };
272
300
  const violations = [];
273
301
  for (const { targetPath, newContent } of results) {
274
302
  if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;
275
- const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));
303
+ const invented = scanImports(newContent, aliasPrefixes).filter((pkg) => !declaredDependencies.has(pkg));
276
304
  if (invented.length > 0) violations.push({ file: targetPath, packages: invented });
277
305
  }
278
306
  return { blocked: violations.length > 0, violations };
@@ -304,6 +332,84 @@ function readDeclaredDependencies(results, workspaceRoot) {
304
332
  return null;
305
333
  }
306
334
  }
335
+ function stripJsonComments(text) {
336
+ let out = "";
337
+ let inString = false;
338
+ let inLineComment = false;
339
+ let inBlockComment = false;
340
+ for (let i = 0; i < text.length; i++) {
341
+ const c = text[i];
342
+ const next = text[i + 1];
343
+ if (inLineComment) {
344
+ if (c === "\n") {
345
+ inLineComment = false;
346
+ out += c;
347
+ }
348
+ continue;
349
+ }
350
+ if (inBlockComment) {
351
+ if (c === "*" && next === "/") {
352
+ inBlockComment = false;
353
+ i++;
354
+ }
355
+ continue;
356
+ }
357
+ if (inString) {
358
+ out += c;
359
+ if (c === "\\") {
360
+ out += next;
361
+ i++;
362
+ continue;
363
+ }
364
+ if (c === '"') inString = false;
365
+ continue;
366
+ }
367
+ if (c === '"') {
368
+ inString = true;
369
+ out += c;
370
+ continue;
371
+ }
372
+ if (c === "/" && next === "/") {
373
+ inLineComment = true;
374
+ i++;
375
+ continue;
376
+ }
377
+ if (c === "/" && next === "*") {
378
+ inBlockComment = true;
379
+ i++;
380
+ continue;
381
+ }
382
+ out += c;
383
+ }
384
+ return out.replace(/,(\s*[}\]])/g, "$1");
385
+ }
386
+ function resolveAliasPrefixes(results, workspaceRoot) {
387
+ const root = (0, import_node_path2.resolve)(workspaceRoot ?? ".");
388
+ for (const filename of ["tsconfig.json", "jsconfig.json"]) {
389
+ const configPath = (0, import_node_path2.join)(root, filename);
390
+ const generated = results.find((r) => (0, import_node_path2.resolve)(r.targetPath) === configPath);
391
+ let raw;
392
+ if (generated) {
393
+ raw = generated.newContent;
394
+ } else {
395
+ try {
396
+ raw = (0, import_node_fs2.readFileSync)(configPath, "utf8");
397
+ } catch {
398
+ raw = null;
399
+ }
400
+ }
401
+ if (raw === null) continue;
402
+ try {
403
+ const parsed = JSON.parse(stripJsonComments(raw));
404
+ const paths = parsed.compilerOptions?.paths;
405
+ const fromConfig = paths && typeof paths === "object" ? Object.keys(paths).map((k) => k.endsWith("*") ? k.slice(0, -1) : k) : [];
406
+ return [.../* @__PURE__ */ new Set([...DEFAULT_ALIAS_PREFIXES, ...fromConfig])];
407
+ } catch {
408
+ continue;
409
+ }
410
+ }
411
+ return DEFAULT_ALIAS_PREFIXES;
412
+ }
307
413
  function describeDependencyViolations(check) {
308
414
  return check.violations.map((v) => `${v.file} imports ${v.packages.join(", ")}, not a dependency of this repository`).join("; ");
309
415
  }
@@ -380,6 +486,99 @@ async function fetchGithubOidcToken(env = process.env) {
380
486
  return body.value;
381
487
  }
382
488
 
489
+ // src/overlapCheck.ts
490
+ var STOPWORDS = /* @__PURE__ */ new Set([
491
+ "a",
492
+ "an",
493
+ "the",
494
+ "is",
495
+ "are",
496
+ "was",
497
+ "were",
498
+ "be",
499
+ "been",
500
+ "being",
501
+ "of",
502
+ "to",
503
+ "in",
504
+ "on",
505
+ "for",
506
+ "with",
507
+ "at",
508
+ "by",
509
+ "from",
510
+ "as",
511
+ "and",
512
+ "or",
513
+ "not",
514
+ "no",
515
+ "nor",
516
+ "this",
517
+ "that",
518
+ "these",
519
+ "those",
520
+ "it",
521
+ "its",
522
+ "cannot",
523
+ "can't",
524
+ "should",
525
+ "must",
526
+ "may",
527
+ "will",
528
+ "shall",
529
+ "when",
530
+ "if",
531
+ "than",
532
+ "then",
533
+ "so",
534
+ "do",
535
+ "does",
536
+ "did"
537
+ ]);
538
+ var MIN_WORD_LENGTH = 3;
539
+ function significantWords(step) {
540
+ return new Set(
541
+ step.toLowerCase().replace(/[^a-z0-9\s]/g, " ").split(/\s+/).filter((w) => w.length >= MIN_WORD_LENGTH && !STOPWORDS.has(w))
542
+ );
543
+ }
544
+ function jaccard(a, b) {
545
+ if (a.size === 0 || b.size === 0) return 0;
546
+ let intersection = 0;
547
+ for (const w of a) if (b.has(w)) intersection++;
548
+ const union = a.size + b.size - intersection;
549
+ return intersection / union;
550
+ }
551
+ var OVERLAP_THRESHOLD = 0.5;
552
+ function findOverlappingSteps(targets) {
553
+ const items = targets.flatMap(
554
+ (target) => target.planStepsImplemented.map((step) => ({
555
+ target: target.path,
556
+ step,
557
+ words: significantWords(step)
558
+ }))
559
+ );
560
+ const warnings = [];
561
+ for (let i = 0; i < items.length; i++) {
562
+ for (let j = i + 1; j < items.length; j++) {
563
+ if (items[i].target === items[j].target) continue;
564
+ if (jaccard(items[i].words, items[j].words) >= OVERLAP_THRESHOLD) {
565
+ warnings.push({
566
+ targetA: items[i].target,
567
+ stepA: items[i].step,
568
+ targetB: items[j].target,
569
+ stepB: items[j].step
570
+ });
571
+ }
572
+ }
573
+ }
574
+ return warnings;
575
+ }
576
+ function describeOverlapWarnings(warnings) {
577
+ return warnings.map(
578
+ (w) => `${w.targetA} and ${w.targetB} both implement what looks like the same rule \u2014 "${w.stepA}" / "${w.stepB}". Check these aren't two independent implementations of the same behavior.`
579
+ );
580
+ }
581
+
383
582
  // src/packet.ts
384
583
  async function fetchPacket(packetUrl, runToken, githubRunId) {
385
584
  const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;
@@ -572,7 +771,7 @@ function validateTarget(target, workspaceRoot, workspaceListing) {
572
771
  );
573
772
  }
574
773
  }
575
- async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
774
+ async function runTargeting(gateway, design, workspaceRoot, workspaceListing, requiredTests) {
576
775
  const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
577
776
  method: "POST",
578
777
  headers: { "content-type": "application/json", "x-run-token": gateway.token },
@@ -583,13 +782,17 @@ async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
583
782
  userPrompt: "",
584
783
  // NESTED, NOT FLATTENED — a second vocabulary for the design shape is exactly what
585
784
  // QUIKTR-1034 cost.
586
- contextData: { workspaceListing, design }
785
+ // QUIKTR-1065 — requiredTests carried through so targeting CAN propose a test-file
786
+ // target naming which cases it covers. The AI Runtime prompt doesn't read this yet
787
+ // (that half is theirs, not this package's) — sending it now is what makes it possible.
788
+ contextData: { workspaceListing, design, requiredTests }
587
789
  })
588
790
  });
589
791
  if (!res.ok) {
590
792
  throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);
591
793
  }
592
- const body = await res.json();
794
+ const envelope = await res.json();
795
+ const body = unwrapExecute(envelope, "pilot.targeting");
593
796
  if (body.outcome === "NO_TARGET") {
594
797
  return { outcome: "NO_TARGET", reason: body.noTargetReason ?? null };
595
798
  }
@@ -625,6 +828,8 @@ async function run(env = readRunnerEnv()) {
625
828
  let packet;
626
829
  let branch;
627
830
  let runToken;
831
+ let warnings = [];
832
+ let targeted = false;
628
833
  try {
629
834
  runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());
630
835
  packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);
@@ -634,7 +839,8 @@ async function run(env = readRunnerEnv()) {
634
839
  packet.gateway,
635
840
  packet.design,
636
841
  packet.workspaceRoot,
637
- workspaceListing
842
+ workspaceListing,
843
+ packet.requiredTests
638
844
  );
639
845
  if (targeting.outcome === "NO_TARGET") {
640
846
  writePhase0Marker(env.runId);
@@ -642,6 +848,14 @@ async function run(env = readRunnerEnv()) {
642
848
  runCommand(packet.commands.lint, "Lint");
643
849
  runTestCommand(packet.commands.test);
644
850
  } else {
851
+ targeted = true;
852
+ const overlaps = findOverlappingSteps(targeting.targets);
853
+ if (overlaps.length > 0) {
854
+ warnings = describeOverlapWarnings(overlaps);
855
+ for (const w of warnings) {
856
+ console.warn(`QuikPilot targeting warning (not blocking): ${w}`);
857
+ }
858
+ }
645
859
  runCommand(packet.commands.setup, "Setup");
646
860
  const [baseline, results] = await Promise.all([
647
861
  captureBaselineSnapshot(packet.commands.test),
@@ -649,7 +863,8 @@ async function run(env = readRunnerEnv()) {
649
863
  ]);
650
864
  const depCheck = checkImportDependencies(
651
865
  results,
652
- readDeclaredDependencies(results, packet.workspaceRoot)
866
+ readDeclaredDependencies(results, packet.workspaceRoot),
867
+ resolveAliasPrefixes(results, packet.workspaceRoot)
653
868
  );
654
869
  if (depCheck.blocked) {
655
870
  throw new Error(
@@ -693,7 +908,14 @@ async function run(env = readRunnerEnv()) {
693
908
  env.installationTokenUrl,
694
909
  runToken
695
910
  );
696
- const result = commitAndPush(packet.branch, env.runId, installationToken);
911
+ const result = commitAndPush(
912
+ packet.branch,
913
+ env.runId,
914
+ installationToken,
915
+ targeted,
916
+ packet.issueKey,
917
+ packet.issueTitle
918
+ );
697
919
  branch = result.branch;
698
920
  } catch (err) {
699
921
  hardFailure = true;
@@ -704,7 +926,8 @@ async function run(env = readRunnerEnv()) {
704
926
  callbackUrl: env.callbackUrl,
705
927
  runToken,
706
928
  status: hardFailure ? "failed" : "completed",
707
- branch
929
+ branch,
930
+ warnings
708
931
  });
709
932
  return { hardFailure };
710
933
  }
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/dependencyCheck.ts", "../src/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/regressionCheck.ts", "../src/targeting.ts", "../src/tokenExchange.ts", "../src/run.ts", "../src/index.ts"],
4
- "sourcesContent": ["export type RunStatus = \"completed\" | \"failed\";\n\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. */\nexport async function reportBack(params: {\n callbackUrl: string;\n runToken: string;\n status: RunStatus;\n branch?: string;\n}): Promise<void> {\n const { callbackUrl, runToken, status, branch } = params;\n const body: Record<string, string> = { status };\n if (branch) body.branch = branch;\n const res = await fetch(callbackUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`Report back to QuikTrack failed: ${res.status} ${res.statusText}`);\n }\n}\n", "import { execSync, spawn } from \"node:child_process\";\n\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\nexport function runCommand(command: string | null, label: string): void {\n if (!command) return;\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nexport type TestOutcome = \"success\" | \"failure\";\n\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\nexport function runTestCommand(command: string | null): TestOutcome {\n if (!command) return \"success\";\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n return \"success\";\n } catch {\n return \"failure\";\n }\n}\n\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\n if (!command) return Promise.resolve(\"success\");\n return new Promise((resolve) => {\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\n child.on(\"error\", () => resolve(\"failure\"));\n });\n}\n", "import { execFileSync } from \"node:child_process\";\n\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\n * on top of the inherited environment; every existing call site is unaffected since it defaults\n * to empty. */\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\n return execFileSync(\"git\", args, {\n encoding: \"utf8\",\n env: { ...process.env, ...extraEnv },\n }).trim();\n}\n\nexport function currentBranch(): string {\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n}\n\n/** Only fetches + checks out when the packet names a target branch different from the one the\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\nexport function checkoutTargetBranch(targetBranch: string | null): void {\n if (!targetBranch || targetBranch === currentBranch()) return;\n git([\"fetch\", \"origin\", targetBranch]);\n git([\"checkout\", targetBranch]);\n}\n\nexport function addAll(): void {\n git([\"add\", \"-A\"]);\n}\n\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\n * getting wrong. */\nexport function diffCachedNamesMatching(pattern: string): string[] {\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\n * targeting.ts's workspaceRoot concept, not a generic git one. */\nexport function listFiles(pathspec: string): string[] {\n const out = git([\"ls-files\", \"--\", pathspec]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\nexport function hasStagedChanges(): boolean {\n try {\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\n return false;\n } catch {\n return true;\n }\n}\n\nexport function configureCommitIdentity(): void {\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\n}\n\nexport function checkoutNewBranch(branch: string): void {\n git([\"checkout\", \"-b\", branch]);\n}\n\nexport function commit(message: string): void {\n git([\"commit\", \"-m\", message]);\n}\n\n/**\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\n * documented scheme for installation tokens over HTTPS git.\n *\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\n * runner's other credential. Scoped to this one invocation only; never persisted.\n *\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\n *\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\n */\nfunction clearCheckoutExtraHeader(): void {\n try {\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\n } catch (err: unknown) {\n const status = (err as { status?: number }).status;\n if (status !== 5) throw err;\n }\n}\n\nexport function push(branch: string, installationToken: string): void {\n clearCheckoutExtraHeader();\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\n GIT_CONFIG_COUNT: \"1\",\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\n });\n}\n", "import {\n checkoutNewBranch,\n commit,\n configureCommitIdentity,\n hasStagedChanges,\n push,\n} from \"./git\";\n\nexport interface CommitResult {\n changed: boolean;\n branch?: string;\n}\n\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\n * already computed and stored it, and two sources for one value will eventually disagree.\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\n * with \u2014 see git.ts's `push` for why. */\nexport function commitAndPush(\n branch: string | null,\n runId: string,\n installationToken: string,\n): CommitResult {\n if (!hasStagedChanges()) return { changed: false };\n if (!branch) {\n throw new Error(\"packet carried no branch name\");\n }\n configureCommitIdentity();\n checkoutNewBranch(branch);\n commit(`QuikPilot Phase 0 skeleton (run ${runId})`);\n push(branch, installationToken);\n return { changed: true, branch };\n}\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport 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", "import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport type { CodegenFileResult } from \"./codegen\";\n\n/**\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\n *\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\n *\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\n */\nexport interface DependencyViolation {\n file: string;\n packages: string[];\n}\n\nexport interface DependencyCheck {\n blocked: boolean;\n violations: DependencyViolation[];\n}\n\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\n\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\n\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\nconst NODE_BUILTINS = new Set([\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\n]);\n\nfunction packageNameFromSpecifier(specifier: string): string | null {\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\n const segments = specifier.split(\"/\");\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\n if (NODE_BUILTINS.has(name)) return null;\n return name;\n}\n\nfunction scanImports(source: string): string[] {\n const found = new Set<string>();\n let match: RegExpExecArray | null;\n IMPORT_RE.lastIndex = 0;\n while ((match = IMPORT_RE.exec(source))) {\n const name = packageNameFromSpecifier(match[2]);\n if (name) found.add(name);\n }\n return [...found];\n}\n\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\n * blocking on a question it can't actually answer. */\nexport function checkImportDependencies(\n results: CodegenFileResult[],\n declaredDependencies: Set<string> | null,\n): DependencyCheck {\n if (!declaredDependencies) return { blocked: false, violations: [] };\n\n const violations: DependencyViolation[] = [];\n for (const { targetPath, newContent } of results) {\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\n const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\n }\n return { blocked: violations.length > 0, violations };\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nfunction dependencyNames(pkg: PackageJson): Set<string> {\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\n return new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]);\n}\n\n/**\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\n */\nexport function readDeclaredDependencies(\n results: CodegenFileResult[],\n workspaceRoot: string | null,\n): Set<string> | null {\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\n\n let raw: string | null;\n if (generated) {\n raw = generated.newContent;\n } else {\n try {\n raw = readFileSync(packageJsonPath, \"utf8\");\n } catch {\n raw = null;\n }\n }\n if (raw === null) return null;\n\n try {\n return dependencyNames(JSON.parse(raw) as PackageJson);\n } catch {\n return null;\n }\n}\n\n/** Regressions and new failures named separately elsewhere in this package for the same reason\n * this exists at all: conflating diagnoses wastes someone's morning. */\nexport function describeDependencyViolations(check: DependencyCheck): string {\n return check.violations\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\n .join(\"; \");\n}\n", "/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\n * generated workflow file still passes them through as job-level env vars under these exact\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\nexport interface RunnerEnv {\n runId: string;\n callbackUrl: string;\n packetUrl: string;\n tokenUrl: string;\n installationTokenUrl: string;\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\n * individually. */\n githubRunId: string;\n githubServerUrl: string;\n githubRepository: string;\n}\n\nexport function required(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\n return {\n runId: required(\"RUN_ID\", env.RUN_ID),\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\n githubRunId: required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID),\n githubServerUrl: env.GITHUB_SERVER_URL ?? \"https://github.com\",\n githubRepository: required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY),\n };\n}\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\n\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\nexport function checkGuardrail(deniedPaths: string[]): void {\n addAll();\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\n if (violations.length > 0) {\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\n }\n}\n", "interface InstallationTokenResponse {\n success: boolean;\n data: { token: string; expiresAt: string };\n}\n\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\n * envelope, same error-message style. */\nexport async function exchangeForInstallationToken(\n installationTokenUrl: string,\n runToken: string,\n): Promise<string> {\n const res = await fetch(installationTokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange installation token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as InstallationTokenResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\n }\n return body.data.token;\n}\n", "import { required } from \"./env\";\n\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\n * verifies the token this package requests. Duplicated because this package is published outside\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\n * duplicating `PilotPacket`'s shape. */\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\n\ninterface OidcTokenResponse {\n value: string;\n}\n\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\nexport async function fetchGithubOidcToken(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n const requestUrl = required(\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\n );\n const requestToken = required(\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\n );\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${requestToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as OidcTokenResponse;\n if (!body.value) {\n throw new Error(\"GitHub OIDC token response carried no value\");\n }\n return body.value;\n}\n", "/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\nexport interface PilotPacket {\n runId: string;\n issueKey: string | null;\n branch: string | null;\n targetBranch: string | null;\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\n * repository root, as null \u2014 never normalised to \".\". */\n workspaceRoot: string | null;\n commands: {\n setup: string | null;\n test: string | null;\n e2e: string | null;\n lint: string | null;\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\n format: string | null;\n };\n guardrails: {\n deniedPaths: string[];\n maxHealIterations: number;\n maxWallClockMinutes: number;\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\n };\n /** Where to call for AI codegen, and the credential that authorizes it. */\n gateway: {\n baseUrl: string;\n token: string;\n };\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\n design: {\n rootCause: string;\n approach: string;\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\n apiChanges: { surface: string; change: string; reason: string }[];\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\n riskRationale: string;\n } | null;\n quikTest: { testRunId: string; resultsUrl: string } | null;\n}\n\ninterface PacketResponse {\n success: boolean;\n data: PilotPacket;\n}\n\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\n * invisible to `ps`, so no equivalent trick is needed here. */\nexport async function fetchPacket(\n packetUrl: string,\n runToken: string,\n githubRunId: string,\n): Promise<PilotPacket> {\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch work packet failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as PacketResponse;\n if (body.success !== true) {\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\n }\n return body.data;\n}\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\n\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\nexport function writePhase0Marker(runId: string): void {\n mkdirSync(\".quikpilot\", { recursive: true });\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\n}\n", "import { readdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\n\nfunction walkForJUnitByName(dir: string): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry)) continue;\n const full = join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n const found = walkForJUnitByName(full);\n if (found) return found;\n } else if (/^junit.*\\.xml$/.test(entry)) {\n return full;\n }\n }\n return null;\n}\n\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n const match = entries.find((e) => namePattern.test(e));\n return match ? join(dir, match) : null;\n}\n\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\n * common locations rather than a configurable setting. A project that writes its report elsewhere\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\n * in the same priority the original `find` clause listed them, though exact traversal order was\n * never guaranteed there either. */\nexport function findJUnitReport(cwd = process.cwd()): string | null {\n return (\n walkForJUnitByName(cwd) ??\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\n );\n}\n\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\n}\n\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. */\nexport async function reportToQuikTest(params: {\n resultsUrl: string | null | undefined;\n runToken: string;\n githubServerUrl: string;\n githubRepository: string;\n githubRunId: string;\n cwd?: string;\n}): Promise<void> {\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, cwd } = params;\n if (!resultsUrl) {\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\n return;\n }\n const report = findJUnitReport(cwd);\n if (!report) {\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\n return;\n }\n try {\n console.log(`reporting ${report}`);\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\n const { readFileSync } = await import(\"node:fs\");\n const body = readFileSync(report);\n const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\n body,\n });\n if (!res.ok) {\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\n }\n rmSync(report, { force: true });\n } catch (err) {\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n", "import { readFileSync } from \"node:fs\";\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\nimport { findJUnitReport } from \"./quiktest\";\n\n/**\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\n * passed before, fails now -> regression, block\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\n * common case, not an edge case \u2014 a different diagnosis from a\n * regression, so it's reported separately)\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\n *\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\n * automationIdFormat.\n */\nexport interface TestSnapshot {\n outcome: TestOutcome;\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\n * with no way to name what broke would contradict the whole point of the classification. */\n results: Map<string, boolean> | null;\n}\n\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\n\nfunction parseJUnitOutcomes(xml: string): Map<string, boolean> {\n const results = new Map<string, boolean>();\n let match: RegExpExecArray | null;\n TESTCASE_RE.lastIndex = 0;\n while ((match = TESTCASE_RE.exec(xml))) {\n const [, attrs, body = \"\"] = match;\n const name = NAME_ATTR_RE.exec(attrs)?.[1];\n if (!name) continue;\n const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\n const id = classname ? `${classname}::${name}` : name;\n results.set(id, !FAILURE_CHILD_RE.test(body));\n }\n return results;\n}\n\nfunction readJUnitOutcomes(cwd: string): Map<string, boolean> | null {\n const report = findJUnitReport(cwd);\n if (!report) return null;\n try {\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\n const outcome = runTestCommand(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport async function captureBaselineSnapshot(\n command: string | null,\n cwd = process.cwd(),\n): Promise<TestSnapshot> {\n const outcome = await runTestCommandAsync(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport interface RegressionCheck {\n blocked: boolean;\n regressions: string[];\n newFailures: string[];\n preExisting: string[];\n}\n\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\n if (!baseline.results || !after.results) {\n return { blocked: false, regressions: [], newFailures: [], preExisting: [] };\n }\n\n const regressions: string[] = [];\n const newFailures: string[] = [];\n const preExisting: string[] = [];\n\n for (const [testId, passed] of after.results) {\n if (passed) continue;\n const before = baseline.results.get(testId);\n if (before === true) regressions.push(testId);\n else if (before === false) preExisting.push(testId);\n else newFailures.push(testId);\n }\n\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };\n}\n\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\n * someone's morning (they're different diagnoses: one means the generated code broke something\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\n * noted, not hidden, so the message doesn't read as if they were silently dropped. */\nexport function describeRegressions(check: RegressionCheck): string {\n const parts: string[] = [];\n if (check.regressions.length > 0) {\n parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(\", \")}`);\n }\n if (check.newFailures.length > 0) {\n parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(\", \")}`);\n }\n if (check.preExisting.length > 0) {\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\n }\n return parts.join(\"; \");\n}\n", "import { resolve, relative, isAbsolute } from \"node:path\";\nimport { listFiles } from \"./git\";\nimport 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 { checkImportDependencies, describeDependencyViolations, readDeclaredDependencies } from \"./dependencyCheck\";\nimport { readRunnerEnv } from \"./env\";\nimport { checkGuardrail } from \"./guardrail\";\nimport { checkoutTargetBranch } from \"./git\";\nimport { exchangeForInstallationToken } from \"./installationToken\";\nimport { fetchGithubOidcToken } from \"./oidc\";\nimport { fetchPacket, type PilotPacket } from \"./packet\";\nimport { writePhase0Marker } from \"./phase0\";\nimport { reportToQuikTest } from \"./quiktest\";\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\nimport { listWorkspaceFiles, runTargeting } from \"./targeting\";\nimport { exchangeForRunToken } from \"./tokenExchange\";\n\n/**\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\n *\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\n *\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\n *\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\n * reportToQuikTest/reportBack fire normally either way.\n */\nexport async function run(env = readRunnerEnv()): Promise<{ hardFailure: boolean }> {\n let hardFailure = false;\n let packet: PilotPacket | undefined;\n let branch: string | undefined;\n let runToken: string | undefined;\n\n try {\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\n checkoutTargetBranch(packet.targetBranch);\n\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\n const targeting = await runTargeting(\n packet.gateway,\n packet.design,\n packet.workspaceRoot,\n workspaceListing,\n );\n if (targeting.outcome === \"NO_TARGET\") {\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\n writePhase0Marker(env.runId);\n runCommand(packet.commands.setup, \"Setup\");\n runCommand(packet.commands.lint, \"Lint\");\n runTestCommand(packet.commands.test);\n } else {\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\n // dependencies doesn't depend on which application source files exist, so this is safe, and\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\n runCommand(packet.commands.setup, \"Setup\");\n\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\n // until flushCodegenResults, so there's nothing for the baseline to race against.\n const [baseline, results] = await Promise.all([\n captureBaselineSnapshot(packet.commands.test),\n runCodegen(packet.gateway, targeting.targets, workspaceListing),\n ]);\n\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\n // written: an invented import is never written to disk at all, matching\n // the same all-or-nothing treatment every other codegen failure already\n // gets here. Hard failure \u2014 a generation that imports a package this\n // repository doesn't have can't be trusted.\n const depCheck = checkImportDependencies(\n results,\n readDeclaredDependencies(results, packet.workspaceRoot),\n );\n if (depCheck.blocked) {\n throw new Error(\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\n );\n }\n\n flushCodegenResults(results);\n try {\n runCommand(packet.commands.format, \"Format\");\n } catch (err) {\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\n }\n runCommand(packet.commands.lint, \"Lint\");\n\n const after = captureTestSnapshot(packet.commands.test);\n const check = checkForRegressions(baseline, after);\n if (check.blocked) {\n throw new Error(\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\n );\n }\n }\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n\n if (!runToken) {\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\n return { hardFailure: true };\n }\n\n await reportToQuikTest({\n resultsUrl: packet?.quikTest?.resultsUrl,\n runToken,\n githubServerUrl: env.githubServerUrl,\n githubRepository: env.githubRepository,\n githubRunId: env.githubRunId,\n });\n\n if (!hardFailure && packet) {\n try {\n checkGuardrail(packet.guardrails.deniedPaths);\n const installationToken = await exchangeForInstallationToken(\n env.installationTokenUrl,\n runToken,\n );\n const result = commitAndPush(packet.branch, env.runId, installationToken);\n branch = result.branch;\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n }\n\n await reportBack({\n callbackUrl: env.callbackUrl,\n runToken,\n status: hardFailure ? \"failed\" : \"completed\",\n branch,\n });\n\n return { hardFailure };\n}\n", "import { run } from \"./run\";\n\nrun()\n .then(({ hardFailure }) => {\n process.exitCode = hardFailure ? 1 : 0;\n })\n .catch((err) => {\n // reportBack itself throwing is the one failure mode `run()` can't recover from internally \u2014\n // still exit non-zero so the raw Actions UI shows the run as failed.\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n });\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/envelope.ts", "../src/dependencyCheck.ts", "../src/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/overlapCheck.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 != \"\"))`. Same\n * treatment for `warnings` (QUIKTR-1064) \u2014 non-fatal findings like a targeting overlap, omitted\n * when there are none rather than sent as an empty array. */\nexport async function reportBack(params: {\n callbackUrl: string;\n runToken: string;\n status: RunStatus;\n branch?: string;\n warnings?: string[];\n}): Promise<void> {\n const { callbackUrl, runToken, status, branch, warnings } = params;\n const body: Record<string, unknown> = { status };\n if (branch) body.branch = branch;\n if (warnings && warnings.length > 0) body.warnings = warnings;\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/**\n * QUIKTR-1067 \u2014 \"QuikPilot Phase 0 skeleton\" used to be hardcoded for every commit, including one\n * carrying a real generated fix (PR #19) \u2014 indistinguishable from the genuinely-empty NO_TARGET\n * marker commit without opening the diff, and git history is permanent. `targeted: false` is the\n * one case that message is still accurate for. `issueKey`/`issueTitle` null with `targeted: true`\n * is defensive only \u2014 dispatch never reaches commit before Gate 1, which always attaches an issue.\n */\nexport function buildCommitMessage(\n runId: string,\n targeted: boolean,\n issueKey: string | null,\n issueTitle: string | null,\n): string {\n if (!targeted) return `QuikPilot Phase 0 skeleton (run ${runId})`;\n if (issueKey && issueTitle) return `${issueKey}: ${issueTitle}\\n\\nQuikPilot run ${runId}`;\n return `QuikPilot generated changes (run ${runId})`;\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 targeted: boolean,\n issueKey: string | null,\n issueTitle: string | null,\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(buildCommitMessage(runId, targeted, issueKey, issueTitle));\n push(branch, installationToken);\n return { changed: true, branch };\n}\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\nimport type { PilotTarget } from \"./targeting\";\n\n/**\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\n *\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\n * per-target: the route file and the service file need different instructions.\n *\n * \u2500\u2500 ALL-OR-NOTHING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\n * failed file instead of discarding the rest is the better long-run answer and belongs with\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\n *\n * `CODEGEN_FILE_TOO_LARGE` and `CODEGEN_CONTEXT_TOO_LARGE` are the AI Runtime's own distinct error\n * codes, checked on their side before dispatch \u2014 retrying hits the identical wall every time, so\n * both are deliberately not retried, same as every other failure here.\n *\n * \u2500\u2500 CONTEXT CONTRACT (contextPaths \u2192 contextContents) \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 * pilot.targeting now names, per target, which other files pilot.codegen should read\n * (`target.contextPaths`) \u2014 replacing the old `siblingContent` guess (nearest file by directory),\n * which only ever ran for NEW_FILE targets and was never more than a stated assumption about this\n * repo's own layout. `contextContents: [{ path, content }]` is now sent for EXISTING targets too,\n * not just NEW_FILE. Empty/absent contextPaths means empty contextContents \u2014 no fallback.\n * `workspaceListing` still goes out for NEW_FILE only, unchanged.\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\";\nconst CONTEXT_TOO_LARGE_CODE = \"CODEGEN_CONTEXT_TOO_LARGE\";\nconst NOT_RETRIED_CODES = new Set([FILE_TOO_LARGE_CODE, CONTEXT_TOO_LARGE_CODE]);\n\n/** The shape at `envelope.structuredJson` for `pilot.codegen` \u2014 NOT the envelope itself. A\n * refusal's reason is `refusalReason`; the envelope has no `code`/`message` fields (those were\n * never real \u2014 see envelope.ts). */\ninterface CodegenResult {\n outcome?: \"GENERATED\" | \"REFUSED\";\n newContent?: string;\n summary?: string;\n refusalReason?: string;\n}\n\nexport interface CodegenFileResult {\n targetPath: string;\n newContent: string;\n}\n\n/**\n * 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 const listing = new Set(workspaceListing);\n\n for (const target of targets) {\n const isNewFile = target.kind === \"NEW_FILE\";\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\n\n // targeting names its own context needs per target \u2014 an invented contextPath is the same\n // class of bug as an invented EXISTING target (targeting.ts's validateTarget): fail loudly\n // rather than silently sending less context than the model asked for.\n const contextPaths = target.contextPaths ?? [];\n for (const contextPath of contextPaths) {\n if (!listing.has(contextPath)) {\n throw new Error(\n `pilot.codegen contextPaths named a file not found in the checkout: ${contextPath} (target ${target.path})`,\n );\n }\n }\n const contextContents = contextPaths.map((path) => ({ path, content: readFileSync(path, \"utf8\") }));\n\n const contextData: Record<string, unknown> = {\n targetPath: target.path,\n currentContent,\n planSteps: target.planStepsImplemented,\n kind: target.kind,\n contextContents,\n };\n if (isNewFile) {\n // Bounds WHAT EXISTS \u2014 stops an invented import like hooks/useGroups \u2014 only meaningful for\n // a file that doesn't exist yet to compare against.\n contextData.workspaceListing = workspaceListing;\n }\n\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.codegen\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n contextData,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n // CODEGEN_FILE_TOO_LARGE / CODEGEN_CONTEXT_TOO_LARGE are checked on the RAW envelope, before\n // unwrapping: they arrive as a failure (success:false), so unwrapping first would throw the\n // generic envelope error and lose the not-retried distinction this check exists to preserve.\n const envelope: any = await res.json();\n if (typeof envelope?.errorCode === \"string\" && NOT_RETRIED_CODES.has(envelope.errorCode)) {\n const detail = envelope.error ? `: ${envelope.error}` : \"\";\n throw new Error(`Codegen refused ${target.path}: ${envelope.errorCode} (not retried)${detail}`);\n }\n\n const body = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\n\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\n throw new Error(\n `Codegen refused ${target.path}${body.refusalReason ? `: ${body.refusalReason}` : \"\"}`,\n );\n }\n\n results.push({ targetPath: target.path, newContent: body.newContent });\n }\n\n return results;\n}\n\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\n for (const { targetPath, newContent } of results) {\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, newContent);\n }\n}\n", "/**\n * QUIKTR-1046 \u2014 `/ai/execute` wraps every use-case result in an envelope; the use-case's own result\n * lives at `envelope.structuredJson`, not at the top level. Both `targeting.ts` and `codegen.ts`\n * read the raw response directly and have never worked against a real reply \u2014 this is the one\n * place that unwraps it, so there is exactly one place to get it right.\n *\n * A failed call can arrive as `success: false` in an HTTP 200 body \u2014 `res.ok` alone is not enough.\n * Observed live 2026-09-18/19/21, including a real RUN_CREDENTIAL_SCOPE refusal shaped exactly\n * like this.\n */\nexport function unwrapExecute<T>(envelope: any, useCase: string): T {\n if (envelope?.success === false) {\n throw new Error(\n `${useCase} failed: ${envelope.errorCode ?? \"UNKNOWN\"} \u2014 ` +\n `${envelope.error ?? envelope.normalizedText ?? \"no message\"}`,\n );\n }\n if (!envelope?.structuredJson || typeof envelope.structuredJson !== \"object\") {\n throw new Error(`${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`);\n }\n return envelope.structuredJson as T;\n}\n", "import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport type { CodegenFileResult } from \"./codegen\";\n\n/**\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\n *\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\n *\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\n */\nexport interface DependencyViolation {\n file: string;\n packages: string[];\n}\n\nexport interface DependencyCheck {\n blocked: boolean;\n violations: DependencyViolation[];\n}\n\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\n\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\n\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\nconst NODE_BUILTINS = new Set([\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\n]);\n\n// QUIKTR-1063 \u2014 the two path-alias conventions common enough to assume even\n// when a repo's tsconfig can't be read or parsed: \"@/...\" (QuikTrack,\n// QuikChat, and most of this monorepo's own apps) and \"~/...\". Without this,\n// \"@/lib/x\" was parsed as the scoped package \"@/lib\" \u2014 a real package.json\n// entry it could never actually match \u2014 and every aliased import in a repo\n// using either convention was reported as an invented dependency.\n//\n// QUIKTR-1068 \u2014 this is now a FLOOR, not the whole answer: `resolveAliasPrefixes`\n// below adds whatever a real tsconfig.json/jsconfig.json actually declares in\n// `compilerOptions.paths`, for repos using some other convention entirely.\n// Always unioned in regardless of what a config says, so a repo with no\n// config (or an unparseable one) keeps exactly today's behavior.\nconst DEFAULT_ALIAS_PREFIXES = [\"@/\", \"~/\"];\n\nfunction packageNameFromSpecifier(specifier: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string | null {\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\n if (aliasPrefixes.some((prefix) => specifier.startsWith(prefix))) return null; // path alias\n const segments = specifier.split(\"/\");\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\n if (NODE_BUILTINS.has(name)) return null;\n return name;\n}\n\nfunction scanImports(source: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string[] {\n const found = new Set<string>();\n let match: RegExpExecArray | null;\n IMPORT_RE.lastIndex = 0;\n while ((match = IMPORT_RE.exec(source))) {\n const name = packageNameFromSpecifier(match[2], aliasPrefixes);\n if (name) found.add(name);\n }\n return [...found];\n}\n\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\n * blocking on a question it can't actually answer. `aliasPrefixes` defaults to the floor above;\n * callers with a real tsconfig read (see `resolveAliasPrefixes`) pass the fuller list. */\nexport function checkImportDependencies(\n results: CodegenFileResult[],\n declaredDependencies: Set<string> | null,\n aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES,\n): DependencyCheck {\n if (!declaredDependencies) return { blocked: false, violations: [] };\n\n const violations: DependencyViolation[] = [];\n for (const { targetPath, newContent } of results) {\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\n const invented = scanImports(newContent, aliasPrefixes).filter((pkg) => !declaredDependencies.has(pkg));\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\n }\n return { blocked: violations.length > 0, violations };\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nfunction dependencyNames(pkg: PackageJson): Set<string> {\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\n return new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]);\n}\n\n/**\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\n */\nexport function readDeclaredDependencies(\n results: CodegenFileResult[],\n workspaceRoot: string | null,\n): Set<string> | null {\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\n\n let raw: string | null;\n if (generated) {\n raw = generated.newContent;\n } else {\n try {\n raw = readFileSync(packageJsonPath, \"utf8\");\n } catch {\n raw = null;\n }\n }\n if (raw === null) return null;\n\n try {\n return dependencyNames(JSON.parse(raw) as PackageJson);\n } catch {\n return null;\n }\n}\n\n/**\n * QUIKTR-1068 \u2014 strips line and block comments plus trailing commas from a JSON(C) string, best\n * effort. Not a real JSONC parser: a character scanner rather than a regex replace (a regex would\n * corrupt a string VALUE containing `//`, e.g. a URL), but anything it can't cleanly handle just\n * fails `JSON.parse` afterward \u2014 `resolveAliasPrefixes` below treats that the same as no config at\n * all and falls back to the floor. Never throws itself.\n */\nfunction stripJsonComments(text: string): string {\n let out = \"\";\n let inString = false;\n let inLineComment = false;\n let inBlockComment = false;\n for (let i = 0; i < text.length; i++) {\n const c = text[i];\n const next = text[i + 1];\n if (inLineComment) {\n if (c === \"\\n\") {\n inLineComment = false;\n out += c;\n }\n continue;\n }\n if (inBlockComment) {\n if (c === \"*\" && next === \"/\") {\n inBlockComment = false;\n i++;\n }\n continue;\n }\n if (inString) {\n out += c;\n if (c === \"\\\\\") {\n out += next;\n i++;\n continue;\n }\n if (c === '\"') inString = false;\n continue;\n }\n if (c === '\"') {\n inString = true;\n out += c;\n continue;\n }\n if (c === \"/\" && next === \"/\") {\n inLineComment = true;\n i++;\n continue;\n }\n if (c === \"/\" && next === \"*\") {\n inBlockComment = true;\n i++;\n continue;\n }\n out += c;\n }\n return out.replace(/,(\\s*[}\\]])/g, \"$1\");\n}\n\ninterface TsOrJsConfig {\n compilerOptions?: { paths?: Record<string, unknown> };\n}\n\n/**\n * QUIKTR-1068 \u2014 `DEFAULT_ALIAS_PREFIXES` is a floor, not the whole answer: a repo may declare its\n * own alias conventions in `compilerOptions.paths`. Tries `tsconfig.json` then `jsconfig.json` at\n * the workspace root (same results-first-then-disk precedence as `readDeclaredDependencies` \u2014 a\n * generated config this run legitimately wrote should win over a stale on-disk one), unions any\n * `paths` keys (wildcard stripped: `\"@/*\"` \u2192 `\"@/\"`) with the floor, and dedupes. Never throws and\n * never returns fewer than the floor \u2014 an unreadable or malformed config is exactly the same as no\n * config, not a reason to block a run that could otherwise pass.\n *\n * Does NOT follow `extends` \u2014 only the root config's own `paths`, same \"minimal, not exhaustive\"\n * boundary this file already draws elsewhere (see the module docblock).\n */\nexport function resolveAliasPrefixes(\n results: CodegenFileResult[],\n workspaceRoot: string | null,\n): string[] {\n const root = resolve(workspaceRoot ?? \".\");\n\n for (const filename of [\"tsconfig.json\", \"jsconfig.json\"]) {\n const configPath = join(root, filename);\n const generated = results.find((r) => resolve(r.targetPath) === configPath);\n\n let raw: string | null;\n if (generated) {\n raw = generated.newContent;\n } else {\n try {\n raw = readFileSync(configPath, \"utf8\");\n } catch {\n raw = null;\n }\n }\n if (raw === null) continue;\n\n try {\n const parsed = JSON.parse(stripJsonComments(raw)) as TsOrJsConfig;\n const paths = parsed.compilerOptions?.paths;\n const fromConfig =\n paths && typeof paths === \"object\"\n ? Object.keys(paths).map((k) => (k.endsWith(\"*\") ? k.slice(0, -1) : k))\n : [];\n return [...new Set([...DEFAULT_ALIAS_PREFIXES, ...fromConfig])];\n } catch {\n continue; // malformed \u2014 try the next config file, or fall through to the floor\n }\n }\n\n return DEFAULT_ALIAS_PREFIXES;\n}\n\n/** Regressions and new failures named separately elsewhere in this package for the same reason\n * this exists at all: conflating diagnoses wastes someone's morning. */\nexport function describeDependencyViolations(check: DependencyCheck): string {\n return check.violations\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\n .join(\"; \");\n}\n", "/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\n * generated workflow file still passes them through as job-level env vars under these exact\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\nexport interface RunnerEnv {\n runId: string;\n callbackUrl: string;\n packetUrl: string;\n tokenUrl: string;\n installationTokenUrl: string;\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\n * individually. */\n githubRunId: string;\n githubServerUrl: string;\n githubRepository: string;\n}\n\nexport function required(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\n return {\n runId: required(\"RUN_ID\", env.RUN_ID),\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\n githubRunId: required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID),\n githubServerUrl: env.GITHUB_SERVER_URL ?? \"https://github.com\",\n githubRepository: required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY),\n };\n}\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\n\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\nexport function checkGuardrail(deniedPaths: string[]): void {\n addAll();\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\n if (violations.length > 0) {\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\n }\n}\n", "interface InstallationTokenResponse {\n success: boolean;\n data: { token: string; expiresAt: string };\n}\n\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\n * envelope, same error-message style. */\nexport async function exchangeForInstallationToken(\n installationTokenUrl: string,\n runToken: string,\n): Promise<string> {\n const res = await fetch(installationTokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange installation token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as InstallationTokenResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\n }\n return body.data.token;\n}\n", "import { required } from \"./env\";\n\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\n * verifies the token this package requests. Duplicated because this package is published outside\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\n * duplicating `PilotPacket`'s shape. */\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\n\ninterface OidcTokenResponse {\n value: string;\n}\n\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\nexport async function fetchGithubOidcToken(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n const requestUrl = required(\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\n );\n const requestToken = required(\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\n );\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${requestToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as OidcTokenResponse;\n if (!body.value) {\n throw new Error(\"GitHub OIDC token response carried no value\");\n }\n return body.value;\n}\n", "import type { PilotTarget } from \"./targeting\";\n\n/**\n * QUIKTR-1064 \u2014 QUIKSP-3's first live run implemented \"reject negative amounts\" twice: once in\n * src/server.js against raw input, once in src/validation.js against parsed minor units. Targeting\n * split the work across two files and gave each its own planStepsImplemented describing the same\n * rule; codegen faithfully built both. Per-target steps are meant to be DISJOINT (QUIKTR-1035) \u2014\n * nothing checked that they are.\n *\n * The real fix is `pilot.targeting`'s prompt \u2014 an AI Runtime change, not this package's. This is\n * the cheap half the ticket assigns here: a non-blocking warning, not semantic analysis. A\n * significant-word overlap between two steps in DIFFERENT targets is treated as the same rule\n * described twice. Same-target steps are never compared \u2014 one file legitimately implementing\n * several related steps is normal and not what this looks for.\n */\nexport interface OverlapWarning {\n targetA: string;\n stepA: string;\n targetB: string;\n stepB: string;\n}\n\nconst STOPWORDS = new Set([\n \"a\", \"an\", \"the\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\n \"of\", \"to\", \"in\", \"on\", \"for\", \"with\", \"at\", \"by\", \"from\", \"as\",\n \"and\", \"or\", \"not\", \"no\", \"nor\",\n \"this\", \"that\", \"these\", \"those\", \"it\", \"its\",\n \"cannot\", \"can't\", \"should\", \"must\", \"may\", \"will\", \"shall\",\n \"when\", \"if\", \"than\", \"then\", \"so\", \"do\", \"does\", \"did\",\n]);\n\n// Ignore words this short too \u2014 they add noise to the overlap without carrying meaning (\"id\",\n// \"an\", two-letter fragments from punctuation stripping).\nconst MIN_WORD_LENGTH = 3;\n\nfunction significantWords(step: string): Set<string> {\n return new Set(\n step\n .toLowerCase()\n .replace(/[^a-z0-9\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length >= MIN_WORD_LENGTH && !STOPWORDS.has(w)),\n );\n}\n\nfunction jaccard(a: Set<string>, b: Set<string>): number {\n if (a.size === 0 || b.size === 0) return 0;\n let intersection = 0;\n for (const w of a) if (b.has(w)) intersection++;\n const union = a.size + b.size - intersection;\n return intersection / union;\n}\n\n// Cheap and deliberately generous \u2014 a false positive here costs a reviewer one glance at a warning\n// line; a false negative is exactly the bug this exists to catch.\nconst OVERLAP_THRESHOLD = 0.5;\n\n/** Every cross-target pair of plan steps whose significant words overlap enough to plausibly be the\n * same rule described twice. Steps within the same target are never compared. */\nexport function findOverlappingSteps(targets: PilotTarget[]): OverlapWarning[] {\n const items = targets.flatMap((target) =>\n target.planStepsImplemented.map((step) => ({\n target: target.path,\n step,\n words: significantWords(step),\n })),\n );\n\n const warnings: OverlapWarning[] = [];\n for (let i = 0; i < items.length; i++) {\n for (let j = i + 1; j < items.length; j++) {\n if (items[i].target === items[j].target) continue;\n if (jaccard(items[i].words, items[j].words) >= OVERLAP_THRESHOLD) {\n warnings.push({\n targetA: items[i].target,\n stepA: items[i].step,\n targetB: items[j].target,\n stepB: items[j].step,\n });\n }\n }\n }\n return warnings;\n}\n\nexport function describeOverlapWarnings(warnings: OverlapWarning[]): string[] {\n return warnings.map(\n (w) =>\n `${w.targetA} and ${w.targetB} both implement what looks like the same rule \u2014 \"${w.stepA}\" / \"${w.stepB}\". Check these aren't two independent implementations of the same behavior.`,\n );\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 /** QUIKTR-1067 \u2014 same nullability as issueKey, for the same reason: the commit message needs\n * both to say what actually changed instead of the hardcoded \"Phase 0 skeleton\" placeholder. */\n issueTitle: string | null;\n branch: string | null;\n targetBranch: string | null;\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\n * repository root, as null \u2014 never normalised to \".\". */\n workspaceRoot: string | null;\n commands: {\n setup: string | null;\n test: string | null;\n e2e: string | null;\n lint: string | null;\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\n format: string | null;\n };\n guardrails: {\n deniedPaths: string[];\n maxHealIterations: number;\n maxWallClockMinutes: number;\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\n };\n /** Where to call for AI codegen, and the credential that authorizes it. */\n gateway: {\n baseUrl: string;\n token: string;\n };\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\n design: {\n rootCause: string;\n approach: string;\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\n apiChanges: { surface: string; change: string; reason: string }[];\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\n riskRationale: string;\n } | null;\n quikTest: { testRunId: string; resultsUrl: string } | null;\n /** QUIKTR-1065 \u2014 the approved test cases codegen still owes real test code for. Sent to\n * pilot.targeting so it can propose a test-file target naming which cases it covers; today\n * nothing reads this field yet (the AI Runtime side isn't built), so it always arrives as `[]`\n * or is silently unused once wired up here. */\n requiredTests: {\n automationId: string;\n title: string;\n covers: string[];\n given: string | null;\n when: string | null;\n then: string | null;\n }[];\n}\n\ninterface PacketResponse {\n success: boolean;\n data: PilotPacket;\n}\n\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\n * invisible to `ps`, so no equivalent trick is needed here. */\nexport async function fetchPacket(\n packetUrl: string,\n runToken: string,\n githubRunId: string,\n): Promise<PilotPacket> {\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch work packet failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as PacketResponse;\n if (body.success !== true) {\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\n }\n return body.data;\n}\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\n\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\nexport function writePhase0Marker(runId: string): void {\n mkdirSync(\".quikpilot\", { recursive: true });\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\n}\n", "import { readdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\n\nfunction walkForJUnitByName(dir: string): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry)) continue;\n const full = join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n const found = walkForJUnitByName(full);\n if (found) return found;\n } else if (/^junit.*\\.xml$/.test(entry)) {\n return full;\n }\n }\n return null;\n}\n\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n const match = entries.find((e) => namePattern.test(e));\n return match ? join(dir, match) : null;\n}\n\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\n * common locations rather than a configurable setting. A project that writes its report elsewhere\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\n * in the same priority the original `find` clause listed them, though exact traversal order was\n * never guaranteed there either. */\nexport function findJUnitReport(cwd = process.cwd()): string | null {\n return (\n walkForJUnitByName(cwd) ??\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\n );\n}\n\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\n}\n\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. */\nexport async function reportToQuikTest(params: {\n resultsUrl: string | null | undefined;\n runToken: string;\n githubServerUrl: string;\n githubRepository: string;\n githubRunId: string;\n cwd?: string;\n}): Promise<void> {\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, cwd } = params;\n if (!resultsUrl) {\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\n return;\n }\n const report = findJUnitReport(cwd);\n if (!report) {\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\n return;\n }\n try {\n console.log(`reporting ${report}`);\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\n const { readFileSync } = await import(\"node:fs\");\n const body = readFileSync(report);\n const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\n body,\n });\n if (!res.ok) {\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\n }\n rmSync(report, { force: true });\n } catch (err) {\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n", "import { readFileSync } from \"node:fs\";\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\nimport { findJUnitReport } from \"./quiktest\";\n\n/**\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\n * passed before, fails now -> regression, block\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\n * common case, not an edge case \u2014 a different diagnosis from a\n * regression, so it's reported separately)\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\n *\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\n * automationIdFormat.\n */\nexport interface TestSnapshot {\n outcome: TestOutcome;\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\n * with no way to name what broke would contradict the whole point of the classification. */\n results: Map<string, boolean> | null;\n}\n\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\n\nfunction parseJUnitOutcomes(xml: string): Map<string, boolean> {\n const results = new Map<string, boolean>();\n let match: RegExpExecArray | null;\n TESTCASE_RE.lastIndex = 0;\n while ((match = TESTCASE_RE.exec(xml))) {\n const [, attrs, body = \"\"] = match;\n const name = NAME_ATTR_RE.exec(attrs)?.[1];\n if (!name) continue;\n const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\n const id = classname ? `${classname}::${name}` : name;\n results.set(id, !FAILURE_CHILD_RE.test(body));\n }\n return results;\n}\n\nfunction readJUnitOutcomes(cwd: string): Map<string, boolean> | null {\n const report = findJUnitReport(cwd);\n if (!report) return null;\n try {\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\n const outcome = runTestCommand(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport async function captureBaselineSnapshot(\n command: string | null,\n cwd = process.cwd(),\n): Promise<TestSnapshot> {\n const outcome = await runTestCommandAsync(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport interface RegressionCheck {\n blocked: boolean;\n regressions: string[];\n newFailures: string[];\n preExisting: string[];\n}\n\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\n if (!baseline.results || !after.results) {\n return { blocked: false, regressions: [], newFailures: [], preExisting: [] };\n }\n\n const regressions: string[] = [];\n const newFailures: string[] = [];\n const preExisting: string[] = [];\n\n for (const [testId, passed] of after.results) {\n if (passed) continue;\n const before = baseline.results.get(testId);\n if (before === true) regressions.push(testId);\n else if (before === false) preExisting.push(testId);\n else newFailures.push(testId);\n }\n\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };\n}\n\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\n * someone's morning (they're different diagnoses: one means the generated code broke something\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\n * noted, not hidden, so the message doesn't read as if they were silently dropped. */\nexport function describeRegressions(check: RegressionCheck): string {\n const parts: string[] = [];\n if (check.regressions.length > 0) {\n parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(\", \")}`);\n }\n if (check.newFailures.length > 0) {\n parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(\", \")}`);\n }\n if (check.preExisting.length > 0) {\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\n }\n return parts.join(\"; \");\n}\n", "import { resolve, relative, isAbsolute } from \"node:path\";\nimport { listFiles } from \"./git\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\n\n/**\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\n * Runtime against a real 624-file QuikChat listing before this was wired in.\n */\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\n\nexport interface PilotTarget {\n path: string;\n kind: TargetKind;\n planStepsImplemented: string[];\n // Context contract change \u2014 pilot.targeting now names, per target, which other files\n // pilot.codegen should read before writing this one (\"to write this file, read these\").\n // codegen.ts validates and reads these; absent/empty means no context, no fallback.\n contextPaths?: 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[]; contextPaths?: 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 requiredTests: PilotPacket[\"requiredTests\"],\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 // QUIKTR-1065 \u2014 requiredTests carried through so targeting CAN propose a test-file\n // target naming which cases it covers. The AI Runtime prompt doesn't read this yet\n // (that half is theirs, not this package's) \u2014 sending it now is what makes it possible.\n contextData: { workspaceListing, design, requiredTests },\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n const envelope = await res.json();\n const body = unwrapExecute<TargetingResponse>(envelope, \"pilot.targeting\");\n\n if (body.outcome === \"NO_TARGET\") {\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\n }\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\n throw new Error(`pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`);\n }\n\n const listing = new Set(workspaceListing);\n for (const target of body.targets) {\n validateTarget(target, workspaceRoot, listing);\n }\n\n return { outcome: \"TARGETED\", targets: body.targets as PilotTarget[] };\n}\n", "interface TokenExchangeResponse {\n success: boolean;\n data: { runToken: string; expiresAt: string };\n}\n\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\n const res = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${oidcToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange run token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as TokenExchangeResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\n }\n return body.data.runToken;\n}\n", "import { reportBack } from \"./callback\";\nimport { runCommand, runTestCommand } from \"./commands\";\nimport { commitAndPush } from \"./commit\";\nimport { flushCodegenResults, runCodegen } from \"./codegen\";\nimport {\n checkImportDependencies,\n describeDependencyViolations,\n readDeclaredDependencies,\n resolveAliasPrefixes,\n} from \"./dependencyCheck\";\nimport { readRunnerEnv } from \"./env\";\nimport { checkGuardrail } from \"./guardrail\";\nimport { checkoutTargetBranch } from \"./git\";\nimport { exchangeForInstallationToken } from \"./installationToken\";\nimport { fetchGithubOidcToken } from \"./oidc\";\nimport { describeOverlapWarnings, findOverlappingSteps } from \"./overlapCheck\";\nimport { fetchPacket, type PilotPacket } from \"./packet\";\nimport { writePhase0Marker } from \"./phase0\";\nimport { reportToQuikTest } from \"./quiktest\";\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\nimport { listWorkspaceFiles, runTargeting } from \"./targeting\";\nimport { exchangeForRunToken } from \"./tokenExchange\";\n\n/**\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\n *\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\n *\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\n *\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\n * reportToQuikTest/reportBack fire normally either way.\n */\nexport async function run(env = readRunnerEnv()): Promise<{ hardFailure: boolean }> {\n let hardFailure = false;\n let packet: PilotPacket | undefined;\n let branch: string | undefined;\n let runToken: string | undefined;\n let warnings: string[] = [];\n // QUIKTR-1067 \u2014 hoisted out of the try block's TARGETED branch: commitAndPush\n // needs it later, outside that scope, to build a real commit message instead\n // of the \"Phase 0 skeleton\" placeholder. Defaults false \u2014 correct for\n // NO_TARGET and for any early hard failure, both of which skip commitAndPush\n // or must fall back to the marker message anyway.\n let targeted = false;\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 packet.requiredTests,\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 targeted = true;\n // QUIKTR-1064 \u2014 cheap, non-blocking: two targets whose planStepsImplemented describe the\n // same rule (the real fix is pilot.targeting's prompt, an AI Runtime change, not this\n // package's \u2014 see overlapCheck.ts). Logged and reported back; never sets hardFailure.\n const overlaps = findOverlappingSteps(targeting.targets);\n if (overlaps.length > 0) {\n warnings = describeOverlapWarnings(overlaps);\n for (const w of warnings) {\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\n }\n }\n\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\n // dependencies doesn't depend on which application source files exist, so this is safe, and\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\n runCommand(packet.commands.setup, \"Setup\");\n\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\n // until flushCodegenResults, so there's nothing for the baseline to race against.\n const [baseline, results] = await Promise.all([\n captureBaselineSnapshot(packet.commands.test),\n runCodegen(packet.gateway, targeting.targets, workspaceListing),\n ]);\n\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\n // written: an invented import is never written to disk at all, matching\n // the same all-or-nothing treatment every other codegen failure already\n // gets here. Hard failure \u2014 a generation that imports a package this\n // repository doesn't have can't be trusted.\n const depCheck = checkImportDependencies(\n results,\n readDeclaredDependencies(results, packet.workspaceRoot),\n resolveAliasPrefixes(results, packet.workspaceRoot),\n );\n if (depCheck.blocked) {\n throw new Error(\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\n );\n }\n\n flushCodegenResults(results);\n try {\n runCommand(packet.commands.format, \"Format\");\n } catch (err) {\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\n }\n runCommand(packet.commands.lint, \"Lint\");\n\n const after = captureTestSnapshot(packet.commands.test);\n const check = checkForRegressions(baseline, after);\n if (check.blocked) {\n throw new Error(\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\n );\n }\n }\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n\n if (!runToken) {\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\n return { hardFailure: true };\n }\n\n await reportToQuikTest({\n resultsUrl: packet?.quikTest?.resultsUrl,\n runToken,\n githubServerUrl: env.githubServerUrl,\n githubRepository: env.githubRepository,\n githubRunId: env.githubRunId,\n });\n\n if (!hardFailure && packet) {\n try {\n checkGuardrail(packet.guardrails.deniedPaths);\n const installationToken = await exchangeForInstallationToken(\n env.installationTokenUrl,\n runToken,\n );\n const result = commitAndPush(\n packet.branch,\n env.runId,\n installationToken,\n targeted,\n packet.issueKey,\n packet.issueTitle,\n );\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 warnings,\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
6
  "names": ["resolve", "import_node_child_process", "import_node_fs", "import_node_path", "import_node_fs", "import_node_fs", "import_node_path", "readFileSync", "import_node_fs", "import_node_path"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quikit/quikpilot-runner",
3
- "version": "7.0.4",
3
+ "version": "7.0.6",
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"