@quikit/quikpilot-runner 7.0.5 → 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 +235 -29
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
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
|
|
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(
|
|
148
|
+
commit(buildCommitMessage(runId, targeted, issueKey, issueTitle));
|
|
141
149
|
push(branch, installationToken);
|
|
142
150
|
return { changed: true, branch };
|
|
143
151
|
}
|
|
@@ -161,31 +169,32 @@ function unwrapExecute(envelope, useCase) {
|
|
|
161
169
|
|
|
162
170
|
// src/codegen.ts
|
|
163
171
|
var FILE_TOO_LARGE_CODE = "CODEGEN_FILE_TOO_LARGE";
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
for (; ; ) {
|
|
167
|
-
const candidate = workspaceListing.find((f) => f !== targetPath && (0, import_node_path.dirname)(f) === dir);
|
|
168
|
-
if (candidate) return candidate;
|
|
169
|
-
const parent = (0, import_node_path.dirname)(dir);
|
|
170
|
-
if (parent === dir) return null;
|
|
171
|
-
dir = parent;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
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]);
|
|
174
174
|
async function runCodegen(gateway, targets, workspaceListing) {
|
|
175
175
|
const results = [];
|
|
176
|
+
const listing = new Set(workspaceListing);
|
|
176
177
|
for (const target of targets) {
|
|
177
178
|
const isNewFile = target.kind === "NEW_FILE";
|
|
178
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") }));
|
|
179
189
|
const contextData = {
|
|
180
190
|
targetPath: target.path,
|
|
181
191
|
currentContent,
|
|
182
192
|
planSteps: target.planStepsImplemented,
|
|
183
|
-
kind: target.kind
|
|
193
|
+
kind: target.kind,
|
|
194
|
+
contextContents
|
|
184
195
|
};
|
|
185
196
|
if (isNewFile) {
|
|
186
197
|
contextData.workspaceListing = workspaceListing;
|
|
187
|
-
const sibling = findNearestSibling(target.path, workspaceListing);
|
|
188
|
-
if (sibling) contextData.siblingContent = (0, import_node_fs.readFileSync)(sibling, "utf8");
|
|
189
198
|
}
|
|
190
199
|
const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
|
|
191
200
|
method: "POST",
|
|
@@ -202,8 +211,9 @@ async function runCodegen(gateway, targets, workspaceListing) {
|
|
|
202
211
|
throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);
|
|
203
212
|
}
|
|
204
213
|
const envelope = await res.json();
|
|
205
|
-
if (envelope?.errorCode ===
|
|
206
|
-
|
|
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}`);
|
|
207
217
|
}
|
|
208
218
|
const body = unwrapExecute(envelope, "pilot.codegen");
|
|
209
219
|
if (body.outcome !== "GENERATED" || typeof body.newContent !== "string") {
|
|
@@ -265,30 +275,32 @@ var NODE_BUILTINS = /* @__PURE__ */ new Set([
|
|
|
265
275
|
"inspector",
|
|
266
276
|
"async_hooks"
|
|
267
277
|
]);
|
|
268
|
-
|
|
278
|
+
var DEFAULT_ALIAS_PREFIXES = ["@/", "~/"];
|
|
279
|
+
function packageNameFromSpecifier(specifier, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
|
|
269
280
|
if (specifier.startsWith(".") || specifier.startsWith("/")) return null;
|
|
270
281
|
if (specifier.startsWith("node:")) return null;
|
|
282
|
+
if (aliasPrefixes.some((prefix) => specifier.startsWith(prefix))) return null;
|
|
271
283
|
const segments = specifier.split("/");
|
|
272
284
|
const name = specifier.startsWith("@") ? segments.slice(0, 2).join("/") : segments[0];
|
|
273
285
|
if (NODE_BUILTINS.has(name)) return null;
|
|
274
286
|
return name;
|
|
275
287
|
}
|
|
276
|
-
function scanImports(source) {
|
|
288
|
+
function scanImports(source, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
|
|
277
289
|
const found = /* @__PURE__ */ new Set();
|
|
278
290
|
let match;
|
|
279
291
|
IMPORT_RE.lastIndex = 0;
|
|
280
292
|
while (match = IMPORT_RE.exec(source)) {
|
|
281
|
-
const name = packageNameFromSpecifier(match[2]);
|
|
293
|
+
const name = packageNameFromSpecifier(match[2], aliasPrefixes);
|
|
282
294
|
if (name) found.add(name);
|
|
283
295
|
}
|
|
284
296
|
return [...found];
|
|
285
297
|
}
|
|
286
|
-
function checkImportDependencies(results, declaredDependencies) {
|
|
298
|
+
function checkImportDependencies(results, declaredDependencies, aliasPrefixes = DEFAULT_ALIAS_PREFIXES) {
|
|
287
299
|
if (!declaredDependencies) return { blocked: false, violations: [] };
|
|
288
300
|
const violations = [];
|
|
289
301
|
for (const { targetPath, newContent } of results) {
|
|
290
302
|
if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;
|
|
291
|
-
const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));
|
|
303
|
+
const invented = scanImports(newContent, aliasPrefixes).filter((pkg) => !declaredDependencies.has(pkg));
|
|
292
304
|
if (invented.length > 0) violations.push({ file: targetPath, packages: invented });
|
|
293
305
|
}
|
|
294
306
|
return { blocked: violations.length > 0, violations };
|
|
@@ -320,6 +332,84 @@ function readDeclaredDependencies(results, workspaceRoot) {
|
|
|
320
332
|
return null;
|
|
321
333
|
}
|
|
322
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
|
+
}
|
|
323
413
|
function describeDependencyViolations(check) {
|
|
324
414
|
return check.violations.map((v) => `${v.file} imports ${v.packages.join(", ")}, not a dependency of this repository`).join("; ");
|
|
325
415
|
}
|
|
@@ -396,6 +486,99 @@ async function fetchGithubOidcToken(env = process.env) {
|
|
|
396
486
|
return body.value;
|
|
397
487
|
}
|
|
398
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
|
+
|
|
399
582
|
// src/packet.ts
|
|
400
583
|
async function fetchPacket(packetUrl, runToken, githubRunId) {
|
|
401
584
|
const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;
|
|
@@ -588,7 +771,7 @@ function validateTarget(target, workspaceRoot, workspaceListing) {
|
|
|
588
771
|
);
|
|
589
772
|
}
|
|
590
773
|
}
|
|
591
|
-
async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
|
|
774
|
+
async function runTargeting(gateway, design, workspaceRoot, workspaceListing, requiredTests) {
|
|
592
775
|
const res = await fetch(`${gateway.baseUrl}/ai/execute`, {
|
|
593
776
|
method: "POST",
|
|
594
777
|
headers: { "content-type": "application/json", "x-run-token": gateway.token },
|
|
@@ -599,7 +782,10 @@ async function runTargeting(gateway, design, workspaceRoot, workspaceListing) {
|
|
|
599
782
|
userPrompt: "",
|
|
600
783
|
// NESTED, NOT FLATTENED — a second vocabulary for the design shape is exactly what
|
|
601
784
|
// QUIKTR-1034 cost.
|
|
602
|
-
|
|
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 }
|
|
603
789
|
})
|
|
604
790
|
});
|
|
605
791
|
if (!res.ok) {
|
|
@@ -642,6 +828,8 @@ async function run(env = readRunnerEnv()) {
|
|
|
642
828
|
let packet;
|
|
643
829
|
let branch;
|
|
644
830
|
let runToken;
|
|
831
|
+
let warnings = [];
|
|
832
|
+
let targeted = false;
|
|
645
833
|
try {
|
|
646
834
|
runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());
|
|
647
835
|
packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);
|
|
@@ -651,7 +839,8 @@ async function run(env = readRunnerEnv()) {
|
|
|
651
839
|
packet.gateway,
|
|
652
840
|
packet.design,
|
|
653
841
|
packet.workspaceRoot,
|
|
654
|
-
workspaceListing
|
|
842
|
+
workspaceListing,
|
|
843
|
+
packet.requiredTests
|
|
655
844
|
);
|
|
656
845
|
if (targeting.outcome === "NO_TARGET") {
|
|
657
846
|
writePhase0Marker(env.runId);
|
|
@@ -659,6 +848,14 @@ async function run(env = readRunnerEnv()) {
|
|
|
659
848
|
runCommand(packet.commands.lint, "Lint");
|
|
660
849
|
runTestCommand(packet.commands.test);
|
|
661
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
|
+
}
|
|
662
859
|
runCommand(packet.commands.setup, "Setup");
|
|
663
860
|
const [baseline, results] = await Promise.all([
|
|
664
861
|
captureBaselineSnapshot(packet.commands.test),
|
|
@@ -666,7 +863,8 @@ async function run(env = readRunnerEnv()) {
|
|
|
666
863
|
]);
|
|
667
864
|
const depCheck = checkImportDependencies(
|
|
668
865
|
results,
|
|
669
|
-
readDeclaredDependencies(results, packet.workspaceRoot)
|
|
866
|
+
readDeclaredDependencies(results, packet.workspaceRoot),
|
|
867
|
+
resolveAliasPrefixes(results, packet.workspaceRoot)
|
|
670
868
|
);
|
|
671
869
|
if (depCheck.blocked) {
|
|
672
870
|
throw new Error(
|
|
@@ -710,7 +908,14 @@ async function run(env = readRunnerEnv()) {
|
|
|
710
908
|
env.installationTokenUrl,
|
|
711
909
|
runToken
|
|
712
910
|
);
|
|
713
|
-
const result = commitAndPush(
|
|
911
|
+
const result = commitAndPush(
|
|
912
|
+
packet.branch,
|
|
913
|
+
env.runId,
|
|
914
|
+
installationToken,
|
|
915
|
+
targeted,
|
|
916
|
+
packet.issueKey,
|
|
917
|
+
packet.issueTitle
|
|
918
|
+
);
|
|
714
919
|
branch = result.branch;
|
|
715
920
|
} catch (err) {
|
|
716
921
|
hardFailure = true;
|
|
@@ -721,7 +926,8 @@ async function run(env = readRunnerEnv()) {
|
|
|
721
926
|
callbackUrl: env.callbackUrl,
|
|
722
927
|
runToken,
|
|
723
928
|
status: hardFailure ? "failed" : "completed",
|
|
724
|
-
branch
|
|
929
|
+
branch,
|
|
930
|
+
warnings
|
|
725
931
|
});
|
|
726
932
|
return { hardFailure };
|
|
727
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/envelope.ts", "../src/dependencyCheck.ts", "../src/env.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/regressionCheck.ts", "../src/targeting.ts", "../src/tokenExchange.ts", "../src/run.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["export type RunStatus = \"completed\" | \"failed\";\n\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. */\nexport async function reportBack(params: {\n callbackUrl: string;\n runToken: string;\n status: RunStatus;\n branch?: string;\n}): Promise<void> {\n const { callbackUrl, runToken, status, branch } = params;\n const body: Record<string, string> = { status };\n if (branch) body.branch = branch;\n const res = await fetch(callbackUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) {\n throw new Error(`Report back to QuikTrack failed: ${res.status} ${res.statusText}`);\n }\n}\n", "import { execSync, spawn } from \"node:child_process\";\n\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\nexport function runCommand(command: string | null, label: string): void {\n if (!command) return;\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n } catch (err) {\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n\nexport type TestOutcome = \"success\" | \"failure\";\n\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\nexport function runTestCommand(command: string | null): TestOutcome {\n if (!command) return \"success\";\n try {\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n return \"success\";\n } catch {\n return \"failure\";\n }\n}\n\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\n if (!command) return Promise.resolve(\"success\");\n return new Promise((resolve) => {\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\n child.on(\"error\", () => resolve(\"failure\"));\n });\n}\n", "import { execFileSync } from \"node:child_process\";\n\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\n * on top of the inherited environment; every existing call site is unaffected since it defaults\n * to empty. */\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\n return execFileSync(\"git\", args, {\n encoding: \"utf8\",\n env: { ...process.env, ...extraEnv },\n }).trim();\n}\n\nexport function currentBranch(): string {\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n}\n\n/** Only fetches + checks out when the packet names a target branch different from the one the\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\nexport function checkoutTargetBranch(targetBranch: string | null): void {\n if (!targetBranch || targetBranch === currentBranch()) return;\n git([\"fetch\", \"origin\", targetBranch]);\n git([\"checkout\", targetBranch]);\n}\n\nexport function addAll(): void {\n git([\"add\", \"-A\"]);\n}\n\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\n * getting wrong. */\nexport function diffCachedNamesMatching(pattern: string): string[] {\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\n * targeting.ts's workspaceRoot concept, not a generic git one. */\nexport function listFiles(pathspec: string): string[] {\n const out = git([\"ls-files\", \"--\", pathspec]);\n return out ? out.split(\"\\n\").filter(Boolean) : [];\n}\n\nexport function hasStagedChanges(): boolean {\n try {\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\n return false;\n } catch {\n return true;\n }\n}\n\nexport function configureCommitIdentity(): void {\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\n}\n\nexport function checkoutNewBranch(branch: string): void {\n git([\"checkout\", \"-b\", branch]);\n}\n\nexport function commit(message: string): void {\n git([\"commit\", \"-m\", message]);\n}\n\n/**\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\n * documented scheme for installation tokens over HTTPS git.\n *\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\n * runner's other credential. Scoped to this one invocation only; never persisted.\n *\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\n *\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\n */\nfunction clearCheckoutExtraHeader(): void {\n try {\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\n } catch (err: unknown) {\n const status = (err as { status?: number }).status;\n if (status !== 5) throw err;\n }\n}\n\nexport function push(branch: string, installationToken: string): void {\n clearCheckoutExtraHeader();\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\n GIT_CONFIG_COUNT: \"1\",\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\n });\n}\n", "import {\n checkoutNewBranch,\n commit,\n configureCommitIdentity,\n hasStagedChanges,\n push,\n} from \"./git\";\n\nexport interface CommitResult {\n changed: boolean;\n branch?: string;\n}\n\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\n * already computed and stored it, and two sources for one value will eventually disagree.\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\n * with \u2014 see git.ts's `push` for why. */\nexport function commitAndPush(\n branch: string | null,\n runId: string,\n installationToken: string,\n): CommitResult {\n if (!hasStagedChanges()) return { changed: false };\n if (!branch) {\n throw new Error(\"packet carried no branch name\");\n }\n configureCommitIdentity();\n checkoutNewBranch(branch);\n commit(`QuikPilot Phase 0 skeleton (run ${runId})`);\n push(branch, installationToken);\n return { changed: true, branch };\n}\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { dirname } from \"node:path\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\nimport type { PilotTarget } from \"./targeting\";\n\n/**\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\n *\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\n * per-target: the route file and the service file need different instructions.\n *\n * \u2500\u2500 ALL-OR-NOTHING \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\n * failed file instead of discarding the rest is the better long-run answer and belongs with\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\n *\n * `CODEGEN_FILE_TOO_LARGE` is the AI Runtime's own distinct error code, checked on their side\n * before dispatch \u2014 retrying hits the identical wall every time, so it is deliberately not\n * retried, same as every other failure here.\n *\n * \u2500\u2500 BUFFERED WRITES (QUIKTR-1035) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n *\n * `runCodegen` no longer writes anything \u2014 it collects `{targetPath, newContent}` in memory and\n * `flushCodegenResults` writes them all, only once every call has succeeded. Two independent\n * reasons: it makes all-or-nothing literally true for the working tree, not just the pull request\n * (today a failure on file 3 leaves files 1-2 already written even though the throw stops the\n * commit); and it lets the test baseline run against an untouched tree while codegen's network-\n * bound calls are still in flight (QUIKTR-1036 is what actually wires that concurrency up \u2014 this\n * only makes it possible).\n */\nconst FILE_TOO_LARGE_CODE = \"CODEGEN_FILE_TOO_LARGE\";\n\n/** The shape at `envelope.structuredJson` for `pilot.codegen` \u2014 NOT the envelope itself. A\n * refusal's reason is `refusalReason`; the envelope has no `code`/`message` fields (those were\n * never real \u2014 see envelope.ts). */\ninterface CodegenResult {\n outcome?: \"GENERATED\" | \"REFUSED\";\n newContent?: string;\n summary?: string;\n refusalReason?: string;\n}\n\nexport interface CodegenFileResult {\n targetPath: string;\n newContent: string;\n}\n\n/**\n * Nearest existing file by directory, walking from the target's own directory up toward the\n * workspace root. Stated assumption, not a general solution: this teaches the model HOW code is\n * written here (imports, relative paths, test framework) by proximity alone \u2014 a repo with\n * genuinely mixed per-directory conventions would need something smarter than \"nearest neighbor.\"\n */\nfunction findNearestSibling(targetPath: string, workspaceListing: string[]): string | null {\n let dir = dirname(targetPath);\n for (;;) {\n const candidate = workspaceListing.find((f) => f !== targetPath && dirname(f) === dir);\n if (candidate) return candidate;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * Run codegen for exactly the targets named, in order, stopping at the first failure. Throws\n * rather than returning a partial result \u2014 see the ALL-OR-NOTHING note above; a caller that wants\n * to know how far it got before failing should catch and inspect the message, not branch on a\n * return value that implies partial success is a valid state. Writes nothing \u2014 call\n * `flushCodegenResults` with the return value once this resolves.\n */\nexport async function runCodegen(\n gateway: PilotPacket[\"gateway\"],\n targets: PilotTarget[],\n workspaceListing: string[],\n): Promise<CodegenFileResult[]> {\n const results: CodegenFileResult[] = [];\n\n for (const target of targets) {\n const isNewFile = target.kind === \"NEW_FILE\";\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\n\n const contextData: Record<string, unknown> = {\n targetPath: target.path,\n currentContent,\n planSteps: target.planStepsImplemented,\n kind: target.kind,\n };\n if (isNewFile) {\n // Bounds WHAT EXISTS (stops an invented import like hooks/useGroups) and teaches HOW code is\n // written (siblingContent) \u2014 neither alone is enough, and both are only meaningful for a\n // file that doesn't exist yet to compare against.\n contextData.workspaceListing = workspaceListing;\n const sibling = findNearestSibling(target.path, workspaceListing);\n if (sibling) contextData.siblingContent = readFileSync(sibling, \"utf8\");\n }\n\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.codegen\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n contextData,\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n // CODEGEN_FILE_TOO_LARGE is checked on the RAW envelope, before unwrapping: it arrives as a\n // failure (success:false), so unwrapping first would throw the generic envelope error and\n // lose the not-retried distinction this check exists to preserve.\n const envelope: any = await res.json();\n if (envelope?.errorCode === FILE_TOO_LARGE_CODE) {\n throw new Error(`Codegen refused ${target.path}: ${FILE_TOO_LARGE_CODE} (not retried)`);\n }\n\n const body = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\n\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\n throw new Error(\n `Codegen refused ${target.path}${body.refusalReason ? `: ${body.refusalReason}` : \"\"}`,\n );\n }\n\n results.push({ targetPath: target.path, newContent: body.newContent });\n }\n\n return results;\n}\n\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\n for (const { targetPath, newContent } of results) {\n mkdirSync(dirname(targetPath), { recursive: true });\n writeFileSync(targetPath, newContent);\n }\n}\n", "/**\n * QUIKTR-1046 \u2014 `/ai/execute` wraps every use-case result in an envelope; the use-case's own result\n * lives at `envelope.structuredJson`, not at the top level. Both `targeting.ts` and `codegen.ts`\n * read the raw response directly and have never worked against a real reply \u2014 this is the one\n * place that unwraps it, so there is exactly one place to get it right.\n *\n * A failed call can arrive as `success: false` in an HTTP 200 body \u2014 `res.ok` alone is not enough.\n * Observed live 2026-09-18/19/21, including a real RUN_CREDENTIAL_SCOPE refusal shaped exactly\n * like this.\n */\nexport function unwrapExecute<T>(envelope: any, useCase: string): T {\n if (envelope?.success === false) {\n throw new Error(\n `${useCase} failed: ${envelope.errorCode ?? \"UNKNOWN\"} \u2014 ` +\n `${envelope.error ?? envelope.normalizedText ?? \"no message\"}`,\n );\n }\n if (!envelope?.structuredJson || typeof envelope.structuredJson !== \"object\") {\n throw new Error(`${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`);\n }\n return envelope.structuredJson as T;\n}\n", "import { readFileSync } from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport type { CodegenFileResult } from \"./codegen\";\n\n/**\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\n *\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\n *\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\n */\nexport interface DependencyViolation {\n file: string;\n packages: string[];\n}\n\nexport interface DependencyCheck {\n blocked: boolean;\n violations: DependencyViolation[];\n}\n\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\n\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\n\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\nconst NODE_BUILTINS = new Set([\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\n]);\n\nfunction packageNameFromSpecifier(specifier: string): string | null {\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\n const segments = specifier.split(\"/\");\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\n if (NODE_BUILTINS.has(name)) return null;\n return name;\n}\n\nfunction scanImports(source: string): string[] {\n const found = new Set<string>();\n let match: RegExpExecArray | null;\n IMPORT_RE.lastIndex = 0;\n while ((match = IMPORT_RE.exec(source))) {\n const name = packageNameFromSpecifier(match[2]);\n if (name) found.add(name);\n }\n return [...found];\n}\n\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\n * blocking on a question it can't actually answer. */\nexport function checkImportDependencies(\n results: CodegenFileResult[],\n declaredDependencies: Set<string> | null,\n): DependencyCheck {\n if (!declaredDependencies) return { blocked: false, violations: [] };\n\n const violations: DependencyViolation[] = [];\n for (const { targetPath, newContent } of results) {\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\n const invented = scanImports(newContent).filter((pkg) => !declaredDependencies.has(pkg));\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\n }\n return { blocked: violations.length > 0, violations };\n}\n\ninterface PackageJson {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n peerDependencies?: Record<string, string>;\n}\n\nfunction dependencyNames(pkg: PackageJson): Set<string> {\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\n return new Set([\n ...Object.keys(pkg.dependencies ?? {}),\n ...Object.keys(pkg.devDependencies ?? {}),\n ...Object.keys(pkg.peerDependencies ?? {}),\n ]);\n}\n\n/**\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\n */\nexport function readDeclaredDependencies(\n results: CodegenFileResult[],\n workspaceRoot: string | null,\n): Set<string> | null {\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\n\n let raw: string | null;\n if (generated) {\n raw = generated.newContent;\n } else {\n try {\n raw = readFileSync(packageJsonPath, \"utf8\");\n } catch {\n raw = null;\n }\n }\n if (raw === null) return null;\n\n try {\n return dependencyNames(JSON.parse(raw) as PackageJson);\n } catch {\n return null;\n }\n}\n\n/** Regressions and new failures named separately elsewhere in this package for the same reason\n * this exists at all: conflating diagnoses wastes someone's morning. */\nexport function describeDependencyViolations(check: DependencyCheck): string {\n return check.violations\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\n .join(\"; \");\n}\n", "/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\n * generated workflow file still passes them through as job-level env vars under these exact\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\nexport interface RunnerEnv {\n runId: string;\n callbackUrl: string;\n packetUrl: string;\n tokenUrl: string;\n installationTokenUrl: string;\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\n * individually. */\n githubRunId: string;\n githubServerUrl: string;\n githubRepository: string;\n}\n\nexport function required(name: string, value: string | undefined): string {\n if (!value) {\n throw new Error(`Missing required environment variable: ${name}`);\n }\n return value;\n}\n\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\n return {\n runId: required(\"RUN_ID\", env.RUN_ID),\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\n githubRunId: required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID),\n githubServerUrl: env.GITHUB_SERVER_URL ?? \"https://github.com\",\n githubRepository: required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY),\n };\n}\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\n\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\nexport function checkGuardrail(deniedPaths: string[]): void {\n addAll();\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\n if (violations.length > 0) {\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\n }\n}\n", "interface InstallationTokenResponse {\n success: boolean;\n data: { token: string; expiresAt: string };\n}\n\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\n * envelope, same error-message style. */\nexport async function exchangeForInstallationToken(\n installationTokenUrl: string,\n runToken: string,\n): Promise<string> {\n const res = await fetch(installationTokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange installation token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as InstallationTokenResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\n }\n return body.data.token;\n}\n", "import { required } from \"./env\";\n\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\n * verifies the token this package requests. Duplicated because this package is published outside\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\n * duplicating `PilotPacket`'s shape. */\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\n\ninterface OidcTokenResponse {\n value: string;\n}\n\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\nexport async function fetchGithubOidcToken(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<string> {\n const requestUrl = required(\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\n );\n const requestToken = required(\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\n );\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${requestToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as OidcTokenResponse;\n if (!body.value) {\n throw new Error(\"GitHub OIDC token response carried no value\");\n }\n return body.value;\n}\n", "/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\nexport interface PilotPacket {\n runId: string;\n issueKey: string | null;\n branch: string | null;\n targetBranch: string | null;\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\n * repository root, as null \u2014 never normalised to \".\". */\n workspaceRoot: string | null;\n commands: {\n setup: string | null;\n test: string | null;\n e2e: string | null;\n lint: string | null;\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\n format: string | null;\n };\n guardrails: {\n deniedPaths: string[];\n maxHealIterations: number;\n maxWallClockMinutes: number;\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\n };\n /** Where to call for AI codegen, and the credential that authorizes it. */\n gateway: {\n baseUrl: string;\n token: string;\n };\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\n design: {\n rootCause: string;\n approach: string;\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\n apiChanges: { surface: string; change: string; reason: string }[];\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\n riskRationale: string;\n } | null;\n quikTest: { testRunId: string; resultsUrl: string } | null;\n}\n\ninterface PacketResponse {\n success: boolean;\n data: PilotPacket;\n}\n\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\n * invisible to `ps`, so no equivalent trick is needed here. */\nexport async function fetchPacket(\n packetUrl: string,\n runToken: string,\n githubRunId: string,\n): Promise<PilotPacket> {\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\n const res = await fetch(url, {\n headers: { Authorization: `Bearer ${runToken}` },\n });\n if (!res.ok) {\n throw new Error(`Fetch work packet failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as PacketResponse;\n if (body.success !== true) {\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\n }\n return body.data;\n}\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\n\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\nexport function writePhase0Marker(runId: string): void {\n mkdirSync(\".quikpilot\", { recursive: true });\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\n}\n", "import { readdirSync, rmSync, statSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\n\nfunction walkForJUnitByName(dir: string): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n for (const entry of entries) {\n if (SKIP_DIRS.has(entry)) continue;\n const full = join(dir, entry);\n let stat;\n try {\n stat = statSync(full);\n } catch {\n continue;\n }\n if (stat.isDirectory()) {\n const found = walkForJUnitByName(full);\n if (found) return found;\n } else if (/^junit.*\\.xml$/.test(entry)) {\n return full;\n }\n }\n return null;\n}\n\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\n let entries: string[];\n try {\n entries = readdirSync(dir);\n } catch {\n return null;\n }\n const match = entries.find((e) => namePattern.test(e));\n return match ? join(dir, match) : null;\n}\n\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\n * common locations rather than a configurable setting. A project that writes its report elsewhere\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\n * in the same priority the original `find` clause listed them, though exact traversal order was\n * never guaranteed there either. */\nexport function findJUnitReport(cwd = process.cwd()): string | null {\n return (\n walkForJUnitByName(cwd) ??\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\n );\n}\n\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\n}\n\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. */\nexport async function reportToQuikTest(params: {\n resultsUrl: string | null | undefined;\n runToken: string;\n githubServerUrl: string;\n githubRepository: string;\n githubRunId: string;\n cwd?: string;\n}): Promise<void> {\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, cwd } = params;\n if (!resultsUrl) {\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\n return;\n }\n const report = findJUnitReport(cwd);\n if (!report) {\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\n return;\n }\n try {\n console.log(`reporting ${report}`);\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\n const { readFileSync } = await import(\"node:fs\");\n const body = readFileSync(report);\n const url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}`;\n const res = await fetch(url, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\n body,\n });\n if (!res.ok) {\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\n }\n rmSync(report, { force: true });\n } catch (err) {\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\n }\n}\n", "import { readFileSync } from \"node:fs\";\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\nimport { findJUnitReport } from \"./quiktest\";\n\n/**\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\n * passed before, fails now -> regression, block\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\n * common case, not an edge case \u2014 a different diagnosis from a\n * regression, so it's reported separately)\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\n *\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\n * automationIdFormat.\n */\nexport interface TestSnapshot {\n outcome: TestOutcome;\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\n * with no way to name what broke would contradict the whole point of the classification. */\n results: Map<string, boolean> | null;\n}\n\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\n\nfunction parseJUnitOutcomes(xml: string): Map<string, boolean> {\n const results = new Map<string, boolean>();\n let match: RegExpExecArray | null;\n TESTCASE_RE.lastIndex = 0;\n while ((match = TESTCASE_RE.exec(xml))) {\n const [, attrs, body = \"\"] = match;\n const name = NAME_ATTR_RE.exec(attrs)?.[1];\n if (!name) continue;\n const classname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\n const id = classname ? `${classname}::${name}` : name;\n results.set(id, !FAILURE_CHILD_RE.test(body));\n }\n return results;\n}\n\nfunction readJUnitOutcomes(cwd: string): Map<string, boolean> | null {\n const report = findJUnitReport(cwd);\n if (!report) return null;\n try {\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\n const outcome = runTestCommand(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport async function captureBaselineSnapshot(\n command: string | null,\n cwd = process.cwd(),\n): Promise<TestSnapshot> {\n const outcome = await runTestCommandAsync(command);\n return { outcome, results: readJUnitOutcomes(cwd) };\n}\n\nexport interface RegressionCheck {\n blocked: boolean;\n regressions: string[];\n newFailures: string[];\n preExisting: string[];\n}\n\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\n if (!baseline.results || !after.results) {\n return { blocked: false, regressions: [], newFailures: [], preExisting: [] };\n }\n\n const regressions: string[] = [];\n const newFailures: string[] = [];\n const preExisting: string[] = [];\n\n for (const [testId, passed] of after.results) {\n if (passed) continue;\n const before = baseline.results.get(testId);\n if (before === true) regressions.push(testId);\n else if (before === false) preExisting.push(testId);\n else newFailures.push(testId);\n }\n\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting };\n}\n\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\n * someone's morning (they're different diagnoses: one means the generated code broke something\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\n * noted, not hidden, so the message doesn't read as if they were silently dropped. */\nexport function describeRegressions(check: RegressionCheck): string {\n const parts: string[] = [];\n if (check.regressions.length > 0) {\n parts.push(`${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.join(\", \")}`);\n }\n if (check.newFailures.length > 0) {\n parts.push(`${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.join(\", \")}`);\n }\n if (check.preExisting.length > 0) {\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\n }\n return parts.join(\"; \");\n}\n", "import { resolve, relative, isAbsolute } from \"node:path\";\nimport { listFiles } from \"./git\";\nimport { unwrapExecute } from \"./envelope\";\nimport type { PilotPacket } from \"./packet\";\n\n/**\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\n * Runtime against a real 624-file QuikChat listing before this was wired in.\n */\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\n\nexport interface PilotTarget {\n path: string;\n kind: TargetKind;\n planStepsImplemented: string[];\n}\n\nexport type TargetingResult =\n | { outcome: \"TARGETED\"; targets: PilotTarget[] }\n | { outcome: \"NO_TARGET\"; reason: string | null };\n\ninterface TargetingResponse {\n outcome?: \"TARGETED\" | \"NO_TARGET\";\n targets?: { path: string; kind: string; planStepsImplemented: string[] }[];\n noTargetReason?: string;\n}\n\n/**\n * Tracked files under the packet's workspace root, or the whole checkout when it's null\n * (QUIKTR-1033) \u2014 never normalised to \".\" at the packet layer itself, only here where a concrete\n * pathspec is actually needed. An unscoped listing on a large monorepo is ~210k tokens, which fits\n * one provider and breaks the fallback chain \u2014 see workspaceRoot's own doc comment on PilotPacket.\n */\nexport function listWorkspaceFiles(workspaceRoot: string | null): string[] {\n return listFiles(workspaceRoot ?? \".\");\n}\n\n/**\n * VALIDATION IS OURS \u2014 the AI Runtime's schema doesn't guarantee a path is actually safe to write.\n * An EXISTING target must already be in the checkout; a NEW_FILE target must resolve inside the\n * workspace root. Either failure throws \u2014 a dropped target is a plan half-executed, and run.ts's\n * existing top-level try/catch already turns this into the same hard failure any other pre-setup\n * step gets.\n */\nfunction validateTarget(\n target: { path: string; kind: string },\n workspaceRoot: string | null,\n workspaceListing: Set<string>,\n): void {\n if (target.kind !== \"EXISTING\" && target.kind !== \"NEW_FILE\") {\n throw new Error(`pilot.targeting returned an unknown kind \"${target.kind}\" for ${target.path}`);\n }\n if (target.kind === \"EXISTING\") {\n if (!workspaceListing.has(target.path)) {\n throw new Error(\n `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`,\n );\n }\n return;\n }\n const root = resolve(workspaceRoot ?? \".\");\n const rel = relative(root, resolve(target.path));\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\n throw new Error(\n `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`,\n );\n }\n}\n\nexport async function runTargeting(\n gateway: PilotPacket[\"gateway\"],\n design: PilotPacket[\"design\"],\n workspaceRoot: string | null,\n workspaceListing: string[],\n): Promise<TargetingResult> {\n const res = await fetch(`${gateway.baseUrl}/ai/execute`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\n body: JSON.stringify({\n appId: \"quiktrack\",\n useCase: \"pilot.targeting\",\n expectedOutputType: \"json\",\n userPrompt: \"\",\n // NESTED, NOT FLATTENED \u2014 a second vocabulary for the design shape is exactly what\n // QUIKTR-1034 cost.\n contextData: { workspaceListing, design },\n }),\n });\n\n if (!res.ok) {\n throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);\n }\n\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\n const envelope = await res.json();\n const body = unwrapExecute<TargetingResponse>(envelope, \"pilot.targeting\");\n\n if (body.outcome === \"NO_TARGET\") {\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\n }\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\n throw new Error(`pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`);\n }\n\n const listing = new Set(workspaceListing);\n for (const target of body.targets) {\n validateTarget(target, workspaceRoot, listing);\n }\n\n return { outcome: \"TARGETED\", targets: body.targets as PilotTarget[] };\n}\n", "interface TokenExchangeResponse {\n success: boolean;\n data: { runToken: string; expiresAt: string };\n}\n\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\n const res = await fetch(tokenUrl, {\n method: \"POST\",\n headers: { Authorization: `Bearer ${oidcToken}` },\n });\n if (!res.ok) {\n throw new Error(`Exchange run token failed: ${res.status} ${res.statusText}`);\n }\n const body = (await res.json()) as TokenExchangeResponse;\n if (body.success !== true) {\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\n }\n return body.data.runToken;\n}\n", "import { reportBack } from \"./callback\";\nimport { runCommand, runTestCommand } from \"./commands\";\nimport { commitAndPush } from \"./commit\";\nimport { flushCodegenResults, runCodegen } from \"./codegen\";\nimport { checkImportDependencies, describeDependencyViolations, readDeclaredDependencies } from \"./dependencyCheck\";\nimport { readRunnerEnv } from \"./env\";\nimport { checkGuardrail } from \"./guardrail\";\nimport { checkoutTargetBranch } from \"./git\";\nimport { exchangeForInstallationToken } from \"./installationToken\";\nimport { fetchGithubOidcToken } from \"./oidc\";\nimport { fetchPacket, type PilotPacket } from \"./packet\";\nimport { writePhase0Marker } from \"./phase0\";\nimport { reportToQuikTest } from \"./quiktest\";\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\nimport { listWorkspaceFiles, runTargeting } from \"./targeting\";\nimport { exchangeForRunToken } from \"./tokenExchange\";\n\n/**\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\n *\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\n *\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\n *\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\n * reportToQuikTest/reportBack fire normally either way.\n */\nexport async function run(env = readRunnerEnv()): Promise<{ hardFailure: boolean }> {\n let hardFailure = false;\n let packet: PilotPacket | undefined;\n let branch: string | undefined;\n let runToken: string | undefined;\n\n try {\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\n checkoutTargetBranch(packet.targetBranch);\n\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\n const targeting = await runTargeting(\n packet.gateway,\n packet.design,\n packet.workspaceRoot,\n workspaceListing,\n );\n if (targeting.outcome === \"NO_TARGET\") {\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\n writePhase0Marker(env.runId);\n runCommand(packet.commands.setup, \"Setup\");\n runCommand(packet.commands.lint, \"Lint\");\n runTestCommand(packet.commands.test);\n } else {\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\n // dependencies doesn't depend on which application source files exist, so this is safe, and\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\n runCommand(packet.commands.setup, \"Setup\");\n\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\n // until flushCodegenResults, so there's nothing for the baseline to race against.\n const [baseline, results] = await Promise.all([\n captureBaselineSnapshot(packet.commands.test),\n runCodegen(packet.gateway, targeting.targets, workspaceListing),\n ]);\n\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\n // written: an invented import is never written to disk at all, matching\n // the same all-or-nothing treatment every other codegen failure already\n // gets here. Hard failure \u2014 a generation that imports a package this\n // repository doesn't have can't be trusted.\n const depCheck = checkImportDependencies(\n results,\n readDeclaredDependencies(results, packet.workspaceRoot),\n );\n if (depCheck.blocked) {\n throw new Error(\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\n );\n }\n\n flushCodegenResults(results);\n try {\n runCommand(packet.commands.format, \"Format\");\n } catch (err) {\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\n }\n runCommand(packet.commands.lint, \"Lint\");\n\n const after = captureTestSnapshot(packet.commands.test);\n const check = checkForRegressions(baseline, after);\n if (check.blocked) {\n throw new Error(\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\n );\n }\n }\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n\n if (!runToken) {\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\n return { hardFailure: true };\n }\n\n await reportToQuikTest({\n resultsUrl: packet?.quikTest?.resultsUrl,\n runToken,\n githubServerUrl: env.githubServerUrl,\n githubRepository: env.githubRepository,\n githubRunId: env.githubRunId,\n });\n\n if (!hardFailure && packet) {\n try {\n checkGuardrail(packet.guardrails.deniedPaths);\n const installationToken = await exchangeForInstallationToken(\n env.installationTokenUrl,\n runToken,\n );\n const result = commitAndPush(packet.branch, env.runId, installationToken);\n branch = result.branch;\n } catch (err) {\n hardFailure = true;\n console.error(err instanceof Error ? err.message : String(err));\n }\n }\n\n await reportBack({\n callbackUrl: env.callbackUrl,\n runToken,\n status: hardFailure ? \"failed\" : \"completed\",\n branch,\n });\n\n return { hardFailure };\n}\n", "import { run } from \"./run\";\n\nrun()\n .then(({ hardFailure }) => {\n process.exitCode = hardFailure ? 1 : 0;\n })\n .catch((err) => {\n // reportBack itself throwing is the one failure mode `run()` can't recover from internally \u2014\n // still exit non-zero so the raw Actions UI shows the run as failed.\n console.error(err instanceof Error ? err.message : String(err));\n process.exitCode = 1;\n });\n"],
|
|
5
|
-
"mappings": "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",
|
|
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.
|
|
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"
|