@quikit/quikpilot-runner 9.1.0 → 9.2.0-rc.2
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/README.md +17 -0
- package/dist/index.js +811 -26
- package/dist/index.js.map +4 -4
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/env.ts", "../src/quiktrackError.ts", "../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/deniedPaths.ts", "../src/editsApply.ts", "../src/runtimeReplyError.ts", "../src/envelope.ts", "../src/importContext.ts", "../src/retryFetch.ts", "../src/dependencyCheck.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/overlapCheck.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/baselineCheck.ts", "../src/regressionCheck.ts", "../src/failureArtifact.ts", "../src/failureReason.ts", "../src/scopeCheck.ts", "../src/targeting.ts", "../src/targetingRecord.ts", "../src/testPlacementCheck.ts", "../src/tokenExchange.ts", "../src/vanishedTests.ts", "../src/run.ts", "../src/readinessCheck.ts", "../src/index.ts"],
|
|
4
|
-
"sourcesContent": ["/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\r\n * generated workflow file still passes them through as job-level env vars under these exact\r\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\r\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\r\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\r\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\r\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\r\nexport interface PilotRunEnv {\r\n mode: \"run\";\r\n runId: string;\r\n callbackUrl: string;\r\n packetUrl: string;\r\n tokenUrl: string;\r\n installationTokenUrl: string;\r\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\r\n * individually. */\r\n githubRunId: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n}\r\n\r\n/**\r\n * QUIKTR-1084 \u2014 the readiness dry-run branch. Deliberately carries none of `PilotRunEnv`'s\r\n * fields: no packet fetch, no OIDC/run-token exchange, no design/codegen/commit/push. It only\r\n * needs the two commands to run and where to report the result.\r\n *\r\n * `readinessToken`/`READINESS_TOKEN` travels as a plain dispatch input, unlike the pilot-run\r\n * token \u2014 deliberately. QUIKTR-805 stopped doing that for the run token because a leaked one\r\n * could spend money through the LLM gateway; this token can only POST a\r\n * `{ junitFound, junitPath }` result for the one `QtPilotConfig` it was minted for (see\r\n * `readiness-dispatch.ts`), which is the same blast radius the pre-805 run token had. Splitting\r\n * out a second OIDC-exchange endpoint to protect a credential this narrow isn't worth the new\r\n * surface.\r\n */\r\nexport interface ReadinessCheckEnv {\r\n mode: \"readiness_check\";\r\n readinessToken: string;\r\n readinessCallbackUrl: string;\r\n setupCmd: string;\r\n testCmd: string;\r\n githubRunId: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n}\r\n\r\nexport type RunnerEnv = PilotRunEnv | ReadinessCheckEnv;\r\n\r\nexport function required(name: string, value: string | undefined): string {\r\n if (!value) {\r\n throw new Error(`Missing required environment variable: ${name}`);\r\n }\r\n return value;\r\n}\r\n\r\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\r\n const githubRunId = required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID);\r\n const githubServerUrl = env.GITHUB_SERVER_URL ?? \"https://github.com\";\r\n const githubRepository = required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY);\r\n\r\n if (env.MODE === \"readiness_check\") {\r\n return {\r\n mode: \"readiness_check\",\r\n readinessToken: required(\"READINESS_TOKEN\", env.READINESS_TOKEN),\r\n readinessCallbackUrl: required(\"READINESS_CALLBACK_URL\", env.READINESS_CALLBACK_URL),\r\n setupCmd: env.SETUP_CMD ?? \"\",\r\n testCmd: required(\"TEST_CMD\", env.TEST_CMD),\r\n githubRunId,\r\n githubServerUrl,\r\n githubRepository,\r\n };\r\n }\r\n\r\n return {\r\n mode: \"run\",\r\n runId: required(\"RUN_ID\", env.RUN_ID),\r\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\r\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\r\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\r\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\r\n githubRunId,\r\n githubServerUrl,\r\n githubRepository,\r\n };\r\n}\r\n", "/**\r\n * QUIKTR-1080 \u2014 QuikTrack's internal pilot routes return a stable `reason_code` in the body on\r\n * every `pilotError()`-shaped failure (401/403/409/429); the generic 500 catch-all has none, and a\r\n * non-2xx response isn't guaranteed to be JSON at all (a proxy/gateway error can produce a\r\n * non-JSON body). Best effort: falls back to bare status/statusText when `reason_code` is absent\r\n * or the body doesn't parse \u2014 never throws itself.\r\n *\r\n * Unrelated to envelope.ts's `errorCode` \u2014 that's the AI Runtime's own, separate `/ai/execute`\r\n * contract. Two different services, two different field names; not to be conflated.\r\n */\r\nexport async function describeQuikTrackFailure(res: Response): Promise<string> {\r\n try {\r\n const body = await res.json();\r\n if (body && typeof body === \"object\" && typeof (body as Record<string, unknown>).reason_code === \"string\") {\r\n return `${res.status} ${res.statusText} (${(body as Record<string, unknown>).reason_code})`;\r\n }\r\n } catch {\r\n // not JSON, no json() method at all, or already consumed \u2014 fall back below\r\n }\r\n return `${res.status} ${res.statusText}`;\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\nimport type { BaselineFindings } from \"./baselineCheck\";\r\nimport type { TargetingRecord } from \"./targetingRecord\";\r\nimport type { VanishedTests } from \"./vanishedTests\";\r\n\r\nexport type RunStatus = \"completed\" | \"failed\";\r\n\r\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\r\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\r\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. Same\r\n * treatment for `warnings` (QUIKTR-1064) \u2014 non-fatal findings like a targeting overlap, omitted\r\n * when there are none rather than sent as an empty array. */\r\nexport async function reportBack(params: {\r\n callbackUrl: string;\r\n runToken: string;\r\n status: RunStatus;\r\n branch?: string;\r\n warnings?: string[];\r\n /** QUIKTR-1421 \u2014 what pilot.targeting decided (paths and case ids only). Omitted when targeting never\r\n * produced a result; an older QuikTrack strips the unknown key silently. */\r\n targeting?: TargetingRecord;\r\n /** QUIKTR-1402 \u2014 test cases that passed against the unmodified code (ids only). Omitted when the check\r\n * flagged nothing or did not run; QuikTrack validates it separately and drops a bad one. */\r\n baselineFindings?: BaselineFindings;\r\n /** QUIKTR-1448 \u2014 tests that ran before the change and are missing from the final report. Test titles are the\r\n * customer's own text, so QuikTrack puts them in the pull request description only and stores none. Omitted when\r\n * nothing is missing; an older QuikTrack ignores the unknown key. */\r\n vanishedTests?: VanishedTests;\r\n /** Why a failed run stopped (already written on one line, cut and scrubbed of credentials). Omitted when there is\r\n * nothing to say; an older QuikTrack accepts it and ignores it for a failed run. */\r\n unresolved?: string[];\r\n}): Promise<void> {\r\n const { callbackUrl, runToken, status, branch, warnings, targeting, baselineFindings, vanishedTests, unresolved } = params;\r\n const body: Record<string, unknown> = { status };\r\n if (branch) body.branch = branch;\r\n if (warnings && warnings.length > 0) body.warnings = warnings;\r\n if (unresolved && unresolved.length > 0) body.unresolved = unresolved;\r\n if (targeting) body.targeting = targeting;\r\n if (baselineFindings) body.baselineFindings = baselineFindings;\r\n if (vanishedTests) body.vanishedTests = vanishedTests;\r\n const res = await fetch(callbackUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(body),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Report back to QuikTrack failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n}\r\n", "import { execSync, spawn } from \"node:child_process\";\r\n\r\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\r\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\r\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\r\nexport function runCommand(command: string | null, label: string): void {\r\n if (!command) return;\r\n try {\r\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n } catch (err) {\r\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n}\r\n\r\nexport type TestOutcome = \"success\" | \"failure\";\r\n\r\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\r\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\r\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\r\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\r\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\r\nexport function runTestCommand(command: string | null): TestOutcome {\r\n if (!command) return \"success\";\r\n try {\r\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n return \"success\";\r\n } catch {\r\n return \"failure\";\r\n }\r\n}\r\n\r\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\r\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\r\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\r\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\r\n if (!command) return Promise.resolve(\"success\");\r\n return new Promise((resolve) => {\r\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\r\n child.on(\"error\", () => resolve(\"failure\"));\r\n });\r\n}\r\n\r\nexport type TimedRunOutcome = \"exited\" | \"timeout\" | \"error\";\r\n\r\n/**\r\n * QUIKTR-1402 \u2014 runs a command through bash with a hard time limit, for the baseline check's single-file\r\n * run. A command that HANGS produces no error, so \"any failure means no flag\" cannot cover it: without a\r\n * limit it would hold the run until the job's own limit and look like QuikPilot being slow. The exit code\r\n * is deliberately not reported \u2014 a failing test is the normal outcome of running a generated test against\r\n * code that does not have the change yet; only \"finished\", \"timed out\" and \"could not start\" matter.\r\n *\r\n * The command runs in its own process group (`detached`) so a timeout can kill the test runner AND\r\n * whatever it started; killing only the shell would leave the runner holding the job open.\r\n */\r\nexport function runCommandWithTimeout(command: string, timeoutMs: number): Promise<TimedRunOutcome> {\r\n return new Promise((resolve) => {\r\n let settled = false;\r\n const finish = (outcome: TimedRunOutcome) => {\r\n if (settled) return;\r\n settled = true;\r\n clearTimeout(timer);\r\n resolve(outcome);\r\n };\r\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\", detached: true });\r\n const timer = setTimeout(() => {\r\n try {\r\n if (child.pid !== undefined) process.kill(-child.pid, \"SIGKILL\");\r\n else child.kill(\"SIGKILL\");\r\n } catch {\r\n try {\r\n child.kill(\"SIGKILL\");\r\n } catch {\r\n // already gone\r\n }\r\n }\r\n finish(\"timeout\");\r\n }, timeoutMs);\r\n child.on(\"exit\", () => finish(\"exited\"));\r\n child.on(\"error\", () => finish(\"error\"));\r\n });\r\n}\r\n", "import { execFileSync } from \"node:child_process\";\r\n\r\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\r\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\r\n * on top of the inherited environment; every existing call site is unaffected since it defaults\r\n * to empty. */\r\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\r\n return execFileSync(\"git\", args, {\r\n encoding: \"utf8\",\r\n env: { ...process.env, ...extraEnv },\r\n }).trim();\r\n}\r\n\r\nexport function currentBranch(): string {\r\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\r\n}\r\n\r\n/** Only fetches + checks out when the packet names a target branch different from the one the\r\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\r\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\r\nexport function checkoutTargetBranch(targetBranch: string | null): void {\r\n if (!targetBranch || targetBranch === currentBranch()) return;\r\n git([\"fetch\", \"origin\", targetBranch]);\r\n git([\"checkout\", targetBranch]);\r\n}\r\n\r\nexport function addAll(): void {\r\n git([\"add\", \"-A\"]);\r\n}\r\n\r\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\r\n * getting wrong. */\r\nexport function diffCachedNamesMatching(pattern: string): string[] {\r\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\r\n return out ? out.split(\"\\n\").filter(Boolean) : [];\r\n}\r\n\r\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\r\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\r\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\r\n * targeting.ts's workspaceRoot concept, not a generic git one. */\r\nexport function listFiles(pathspec: string): string[] {\r\n const out = git([\"ls-files\", \"--\", pathspec]);\r\n return out ? out.split(\"\\n\").filter(Boolean) : [];\r\n}\r\n\r\nexport function hasStagedChanges(): boolean {\r\n try {\r\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\r\n return false;\r\n } catch {\r\n return true;\r\n }\r\n}\r\n\r\nexport function configureCommitIdentity(): void {\r\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\r\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\r\n}\r\n\r\nexport function checkoutNewBranch(branch: string): void {\r\n git([\"checkout\", \"-b\", branch]);\r\n}\r\n\r\nexport function commit(message: string): void {\r\n git([\"commit\", \"-m\", message]);\r\n}\r\n\r\n/**\r\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\r\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\r\n * documented scheme for installation tokens over HTTPS git.\r\n *\r\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\r\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\r\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\r\n * runner's other credential. Scoped to this one invocation only; never persisted.\r\n *\r\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\r\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\r\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\r\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\r\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\r\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\r\n *\r\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\r\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\r\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\r\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\r\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\r\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\r\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\r\n */\r\nfunction clearCheckoutExtraHeader(): void {\r\n try {\r\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\r\n } catch (err: unknown) {\r\n const status = (err as { status?: number }).status;\r\n if (status !== 5) throw err;\r\n }\r\n}\r\n\r\nexport function push(branch: string, installationToken: string): void {\r\n clearCheckoutExtraHeader();\r\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\r\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\r\n GIT_CONFIG_COUNT: \"1\",\r\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\r\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\r\n });\r\n}\r\n", "import {\r\n checkoutNewBranch,\r\n commit,\r\n configureCommitIdentity,\r\n hasStagedChanges,\r\n push,\r\n} from \"./git\";\r\n\r\nexport interface CommitResult {\r\n changed: boolean;\r\n branch?: string;\r\n}\r\n\r\n/**\r\n * QUIKTR-1067 \u2014 \"QuikPilot Phase 0 skeleton\" used to be hardcoded for every commit, including one\r\n * carrying a real generated fix (PR #19) \u2014 indistinguishable from the genuinely-empty NO_TARGET\r\n * marker commit without opening the diff, and git history is permanent. `targeted: false` is the\r\n * one case that message is still accurate for. `issueKey`/`issueTitle` null with `targeted: true`\r\n * is defensive only \u2014 dispatch never reaches commit before Gate 1, which always attaches an issue.\r\n */\r\nexport function buildCommitMessage(\r\n runId: string,\r\n targeted: boolean,\r\n issueKey: string | null,\r\n issueTitle: string | null,\r\n): string {\r\n if (!targeted) return `QuikPilot Phase 0 skeleton (run ${runId})`;\r\n if (issueKey && issueTitle) return `${issueKey}: ${issueTitle}\\n\\nQuikPilot run ${runId}`;\r\n return `QuikPilot generated changes (run ${runId})`;\r\n}\r\n\r\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\r\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\r\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\r\n * already computed and stored it, and two sources for one value will eventually disagree.\r\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\r\n * with \u2014 see git.ts's `push` for why. */\r\nexport function commitAndPush(\r\n branch: string | null,\r\n runId: string,\r\n installationToken: string,\r\n targeted: boolean,\r\n issueKey: string | null,\r\n issueTitle: string | null,\r\n): CommitResult {\r\n if (!hasStagedChanges()) return { changed: false };\r\n if (!branch) {\r\n throw new Error(\"packet carried no branch name\");\r\n }\r\n configureCommitIdentity();\r\n checkoutNewBranch(branch);\r\n commit(buildCommitMessage(runId, targeted, issueKey, issueTitle));\r\n push(branch, installationToken);\r\n return { changed: true, branch };\r\n}\r\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\r\nimport { dirname } from \"node:path\";\r\nimport { findDeniedContextPath, matchesDeniedPath } from \"./deniedPaths\";\r\nimport { applyEdits, detectLineEnding, fromLf, toLf, type AnchorRefusal, type LineEnding } from \"./editsApply\";\r\nimport { checkHardFailure, unwrapExecute } from \"./envelope\";\r\nimport { ACTIONABLE_IMPORT_SKIPS, collectImportContext } from \"./importContext\";\r\nimport { RuntimeReplyError } from \"./runtimeReplyError\";\r\nimport type { PilotPacket } from \"./packet\";\r\nimport { fetchWithRetry } from \"./retryFetch\";\r\nimport type { CodegenContextRecord } from \"./targetingRecord\";\r\nimport type { PilotTarget, SkippedCase } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\r\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\r\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\r\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\r\n *\r\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\r\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\r\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\r\n * per-target: the route file and the service file need different instructions.\r\n *\r\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\r\n *\r\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\r\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\r\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\r\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\r\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\r\n * failed file instead of discarding the rest is the better long-run answer and belongs with\r\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\r\n *\r\n * `CODEGEN_FILE_TOO_LARGE` and `CODEGEN_CONTEXT_TOO_LARGE` are the AI Runtime's own distinct error\r\n * codes, checked on their side before dispatch \u2014 retrying hits the identical wall every time, so\r\n * both are deliberately not retried, same as every other failure here.\r\n *\r\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\r\n *\r\n * pilot.targeting now names, per target, which other files pilot.codegen should read\r\n * (`target.contextPaths`) \u2014 replacing the old `siblingContent` guess (nearest file by directory),\r\n * which only ever ran for NEW_FILE targets and was never more than a stated assumption about this\r\n * repo's own layout. `contextContents: [{ path, content }]` is now sent for EXISTING targets too,\r\n * not just NEW_FILE. Empty/absent contextPaths means empty contextContents \u2014 no fallback.\r\n * `workspaceListing` still goes out for NEW_FILE only, unchanged.\r\n *\r\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\r\n *\r\n * `runCodegen` no longer writes anything \u2014 it collects `{targetPath, newContent}` in memory and\r\n * `flushCodegenResults` writes them all, only once every call has succeeded. Two independent\r\n * reasons: it makes all-or-nothing literally true for the working tree, not just the pull request\r\n * (today a failure on file 3 leaves files 1-2 already written even though the throw stops the\r\n * commit); and it lets the test baseline run against an untouched tree while codegen's network-\r\n * bound calls are still in flight (QUIKTR-1036 is what actually wires that concurrency up \u2014 this\r\n * only makes it possible).\r\n */\r\nconst FILE_TOO_LARGE_CODE = \"CODEGEN_FILE_TOO_LARGE\";\r\nconst CONTEXT_TOO_LARGE_CODE = \"CODEGEN_CONTEXT_TOO_LARGE\";\r\n/** \u00A716.7 \u2014 the AI Runtime's OWN output-cap guard telling us directly, distinct from\r\n * `looksLikeTruncatedRewrite` below (this file's interim heuristic guess at the same problem). */\r\nconst OUTPUT_TOO_LARGE_CODE = \"CODEGEN_OUTPUT_TOO_LARGE\";\r\nconst NOT_RETRIED_CODES = new Set([FILE_TOO_LARGE_CODE, CONTEXT_TOO_LARGE_CODE, OUTPUT_TOO_LARGE_CODE]);\r\n/** \u00A718.8.1 \u2014 the ONE retried refusal in this file, deliberately not in `NOT_RETRIED_CODES` above:\r\n * unlike the three sibling TOO_LARGE codes (which hit the identical wall on any retry), this one\r\n * is retried exactly once, with `judgedBy` narrowed to only the cases a test target's own\r\n * `contextPaths` ties to this code target \u2014 see `narrowJudgedByForTarget` below. */\r\nconst JUDGED_BY_TOO_LARGE_CODE = \"CODEGEN_JUDGED_BY_TOO_LARGE\";\r\n\r\n/**\r\n * QUIKTR-1419 \u2014 a test target is written against whatever files pilot.targeting listed for it (model\r\n * output), so it can be handed nothing of the code the run is changing. The runner therefore also gives it\r\n * the run's OTHER existing code targets. Bounded on purpose (Suyash): files changed in this run only, never\r\n * the files THEY import.\r\n *\r\n * QUIKTR-1454 \u2014 separately, EVERY existing target is also shown the files IT imports, one hop (importContext.ts).\r\n * That is a different rule from the one above, not an exception to it: an import is a fact the file states,\r\n * so it is parsed rather than left to targeting's judgement (the first real 9.0.0 run failed twice on a file\r\n * targeting never listed). Suyash, 5 Oct: one hop, what was added and skipped is logged with the reason, and\r\n * targeting's own list is never replaced. The run files above still never bring THEIR imports with them.\r\n *\r\n * The contract states no numeric limit for CODEGEN_CONTEXT_TOO_LARGE (only 200,000 chars for\r\n * `currentContent`), and that budget is shared with `currentContent` and `workspaceListing`. These are our\r\n * own conservative numbers, in characters like every other runner number (real targets seen: ~38.5k and\r\n * ~39.5k). Going over skips a file; it never fails the run.\r\n */\r\nconst MAX_ADDED_FILE_CHARS = 40_000;\r\nconst MAX_ADDED_CONTEXT_CHARS = 60_000;\r\n\r\nexport interface AddedContext {\r\n entries: { path: string; content: string }[];\r\n skipped: { path: string; reason: \"too large\" | \"over budget\" | \"unreadable\" }[];\r\n}\r\n\r\n/**\r\n * The extra `contextContents` entries for one target. Empty unless it is a TEST target (one with\r\n * `automationIds`); a code target's context stays exactly what targeting asked for. Candidates are the run's\r\n * other EXISTING targets that are not tests: a NEW_FILE has nothing on disk yet, and another test file adds\r\n * size for no help. `alreadyNamed` are the paths targeting already listed, so nothing is sent twice.\r\n *\r\n * Content is what is on disk NOW, i.e. before this run's edit \u2014 writes are buffered until every call has\r\n * succeeded. A route the change is adding is therefore visible to the test only through the plan steps.\r\n */\r\nexport function collectRunContext(\r\n target: PilotTarget,\r\n targets: PilotTarget[],\r\n alreadyNamed: Set<string>,\r\n deniedPaths: string[],\r\n readFile: (path: string) => string = (p) => readFileSync(p, \"utf8\"),\r\n): AddedContext {\r\n const added: AddedContext = { entries: [], skipped: [] };\r\n if (!target.automationIds?.length) return added;\r\n\r\n const seen = new Set(alreadyNamed);\r\n seen.add(target.path);\r\n let total = 0;\r\n for (const candidate of targets) {\r\n if (candidate.kind !== \"EXISTING\" || candidate.automationIds?.length) continue;\r\n if (seen.has(candidate.path)) continue;\r\n seen.add(candidate.path);\r\n // validateTarget already rejects a denied target, so this is defence in depth: a path in context is\r\n // read and sent to the LLM provider.\r\n if (matchesDeniedPath(candidate.path, deniedPaths)) continue;\r\n\r\n let content: string;\r\n try {\r\n content = readFile(candidate.path);\r\n } catch {\r\n added.skipped.push({ path: candidate.path, reason: \"unreadable\" });\r\n continue;\r\n }\r\n if (content.length > MAX_ADDED_FILE_CHARS) {\r\n added.skipped.push({ path: candidate.path, reason: \"too large\" });\r\n } else if (total + content.length > MAX_ADDED_CONTEXT_CHARS) {\r\n added.skipped.push({ path: candidate.path, reason: \"over budget\" });\r\n } else {\r\n total += content.length;\r\n added.entries.push({ path: candidate.path, content });\r\n }\r\n }\r\n return added;\r\n}\r\n\r\n/**\r\n * \u00A716.7 \u2014 interim runner-side guard, live under \u00A715 today (not gated on self-heal or on the AI\r\n * Runtime's own `CODEGEN_OUTPUT_TOO_LARGE` check, which isn't deployed yet). Codegen's output is\r\n * capped around 8,192 tokens; `CODEGEN_FILE_TOO_LARGE` only checks the ~200k-char *input*, so a\r\n * rewrite of a file well under that can still get truncated on the way out. The dangerous case is\r\n * a retry that comes back as valid, `success: true` JSON with the file quietly abbreviated \u2014\r\n * codegen's contract is that anything missing from `newContent` is deleted, so that reads as a\r\n * clean success while silently destroying code. \u00A716.7 names this exact heuristic as QuikTrack's\r\n * own stopgap until the real guard (a pre-dispatch prediction plus a finish-reason check) ships on\r\n * the runtime side.\r\n */\r\nconst SUSPECT_PLACEHOLDER_RE =\r\n /rest(?: of the)? (?:file|code) unchanged|remainder unchanged|\\/\\/\\s*\\.\\.\\.\\s*(?:rest|remaining)/i;\r\n/** Below 60% of its original length, an EXISTING rewrite is suspect rather than a real edit \u2014 a\r\n * targeted fix (planStepsImplemented) trims, it doesn't gut a file to a stub. Raised from 0.5 to\r\n * 0.6 after the AI Runtime's 2026-09-24 incident: a real pilot-chat.ts rewrite came back 38,500 ->\r\n * 22,585 chars (58.67% remaining) with success: true and no placeholder text \u2014 the old 0.5 ratio\r\n * only fires below 50% remaining, so that exact silent deletion sailed through undetected. */\r\nconst SUSPECT_LENGTH_DROP_RATIO = 0.6;\r\n/** A drop in character count can hide behind reformatting (fewer, longer lines) \u2014 this catches\r\n * the opposite failure: a rewrite that removes a large share of *lines* without a matching drop\r\n * in characters. 30% is a deliberately conservative starting point, not a calibrated number \u2014 no\r\n * incident has been observed on this signal alone yet. Tighten once real call metrics exist. */\r\nconst SUSPECT_REMOVED_LINE_RATIO = 0.3;\r\n/** Below this many lines, the multiset diff's \"changed line looks like removed+added\" blind spot\r\n * makes the ratio check unreliable \u2014 skip it rather than false-positive on small/single-line files. */\r\nconst MIN_LINES_FOR_REMOVED_LINE_CHECK = 10;\r\n/** Exported symbols removed silently are exactly the \"code vanishes, response still looks valid\"\r\n * failure mode \u2014 TS/JS only, since this parses no grammar beyond an `export` declaration. */\r\nconst JS_TS_EXTENSION_RE = /\\.(?:ts|tsx|js|jsx|mjs|cjs)$/;\r\nconst EXPORTED_SYMBOL_RE =\r\n /^export\\s+(?:default\\s+)?(?:async\\s+)?(?:function\\*?|class|const|let|var|interface|type|enum)\\s+([A-Za-z_$][\\w$]*)/gm;\r\n\r\n/** Language-neutral, line-based multiset diff \u2014 not an LCS/AST diff. Counts lines present in\r\n * `currentContent` with no matching occurrence left in `newContent`; good enough to flag \"lines\r\n * vanished\" without claiming to be a minimal diff. */\r\nfunction countRemovedLines(currentContent: string, newContent: string): number {\r\n const remaining = new Map<string, number>();\r\n for (const line of newContent.split(\"\\n\")) {\r\n remaining.set(line, (remaining.get(line) ?? 0) + 1);\r\n }\r\n let removed = 0;\r\n for (const line of currentContent.split(\"\\n\")) {\r\n const count = remaining.get(line) ?? 0;\r\n if (count > 0) {\r\n remaining.set(line, count - 1);\r\n } else {\r\n removed++;\r\n }\r\n }\r\n return removed;\r\n}\r\n\r\nfunction extractExportedSymbols(content: string): Set<string> {\r\n const symbols = new Set<string>();\r\n for (const match of content.matchAll(EXPORTED_SYMBOL_RE)) {\r\n symbols.add(match[1]);\r\n }\r\n return symbols;\r\n}\r\n\r\n/** Symbols removed by the rewrite that the plan text never names \u2014 a naive substring check, not a\r\n * reference-tracking one: it undercounts (a symbol renamed to match a plan word would slip past)\r\n * rather than overcounts, which is the right side to err on for a hard-failing guard. */\r\nfunction removedUnexplainedSymbols(targetPath: string, planText: string, currentContent: string, newContent: string): string[] {\r\n if (!JS_TS_EXTENSION_RE.test(targetPath)) return [];\r\n const before = extractExportedSymbols(currentContent);\r\n const after = extractExportedSymbols(newContent);\r\n const lowerPlan = planText.toLowerCase();\r\n return [...before].filter((symbol) => !after.has(symbol) && !lowerPlan.includes(symbol.toLowerCase()));\r\n}\r\n\r\nfunction looksLikeTruncatedRewrite(target: PilotTarget, currentContent: string, newContent: string): string | null {\r\n if (SUSPECT_PLACEHOLDER_RE.test(newContent)) {\r\n return \"contains placeholder text suggesting an abbreviated rewrite\";\r\n }\r\n if (currentContent.length > 0 && newContent.length < currentContent.length * SUSPECT_LENGTH_DROP_RATIO) {\r\n return `sharp length drop (${currentContent.length} -> ${newContent.length} chars)`;\r\n }\r\n\r\n // A multiset line diff can't tell \"line changed\" from \"line removed\" \u2014 on a short/single-line\r\n // file, one edited line reads as 100% removed. Require a real line count before trusting it.\r\n const currentLineCount = currentContent.length > 0 ? currentContent.split(\"\\n\").length : 0;\r\n if (currentLineCount >= MIN_LINES_FOR_REMOVED_LINE_CHECK) {\r\n const removedLines = countRemovedLines(currentContent, newContent);\r\n if (removedLines > currentLineCount * SUSPECT_REMOVED_LINE_RATIO) {\r\n const pct = ((removedLines / currentLineCount) * 100).toFixed(0);\r\n return `removed ${removedLines} of ${currentLineCount} lines (${pct}%) without a matching drop in character count`;\r\n }\r\n }\r\n\r\n const planText = target.planStepsImplemented.join(\" \");\r\n const unexplainedSymbols = removedUnexplainedSymbols(target.path, planText, currentContent, newContent);\r\n if (unexplainedSymbols.length > 0) {\r\n return `removed exported symbol(s) the plan steps don't mention: ${unexplainedSymbols.join(\", \")}`;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** QUIKTR-1083 (\u00A715.6) \u2014 sent on every codegen call, same reasoning as targeting.ts's own constant. */\r\nconst CONTRACT_VERSION = \"test-targets-1\";\r\n/** 9.0.0, Doc 62 \u00A72 \u2014 cumulative over test-targets-1. For an EXISTING target the reply is anchored `edits` the runner\r\n * applies, not a whole file. A NEW_FILE target has nothing to anchor against and never asks for it. */\r\nconst CONTRACT_VERSION_EDITS = \"edits-1\";\r\n/** The runtime's code for anchors the ONE regeneration still could not place (Doc 62 \u00A72.1). Our remedy is our own:\r\n * re-request the whole file without edits-1. The fallback is the runner's, so it shows in the run trail. */\r\nconst ANCHOR_REFUSED_CODE = \"CODEGEN_ANCHOR_REFUSED\";\r\n\r\n/** The shape at `envelope.structuredJson` for `pilot.codegen` \u2014 NOT the envelope itself. A\r\n * refusal's reason is `refusalReason`; the envelope has no `code`/`message` fields (those were\r\n * never real \u2014 see envelope.ts). Under edits-1 an EXISTING target's GENERATED reply carries `edits`, not `newContent`. */\r\ninterface CodegenResult {\r\n outcome?: \"GENERATED\" | \"REFUSED\";\r\n newContent?: string;\r\n edits?: unknown;\r\n summary?: string;\r\n refusalReason?: string;\r\n}\r\n\r\n/** Which way a call went, for the one log line per call. `edits`: anchored edits applied. `fallback`: edits were\r\n * refused or did not place, so the whole file was requested. `whole_file`: no edits were asked for, or the reply was\r\n * a whole file anyway. */\r\ntype EditsPath = \"edits\" | \"fallback\" | \"whole_file\";\r\n\r\n/** What a refusal may say about itself: counts and kinds, never the text of an anchor. These strings end up in the\r\n * run's warnings, which reach QuikTrack. */\r\ninterface RefusalSummary {\r\n text: string;\r\n matchCounts: number[];\r\n}\r\n\r\nfunction summariseLocalRefusals(refusals: AnchorRefusal[]): RefusalSummary {\r\n const parts: string[] = [];\r\n const matchCounts: number[] = [];\r\n for (const r of refusals) {\r\n if (r.kind === \"ambiguous\") {\r\n parts.push(`an anchor matched ${r.matchCount} times`);\r\n if (r.matchCount !== null) matchCounts.push(r.matchCount);\r\n } else if (r.kind === \"no_match\") {\r\n parts.push(\"an anchor matched nothing\");\r\n } else if (r.kind === \"overlap\") {\r\n parts.push(`edits ${r.edits.join(\" and \")} overlap`);\r\n } else if (r.kind === \"no_edits\") {\r\n parts.push(\"the reply had no edits\");\r\n } else {\r\n parts.push(\"an edit was missing its anchor or replacement\");\r\n }\r\n }\r\n return { text: [...new Set(parts)].join(\"; \"), matchCounts };\r\n}\r\n\r\n/** The runtime's own refusal text quotes the anchor (\"The anchor was: \u2026\"), so it is read for its counts and never passed on. */\r\nfunction summariseRuntimeRefusal(error: unknown): RefusalSummary {\r\n const text = typeof error === \"string\" ? error : \"\";\r\n const matchCounts = [...text.matchAll(/anchor matched (\\d+) times/g)].map((m) => Number(m[1]));\r\n const parts: string[] = matchCounts.map((n) => `an anchor matched ${n} times`);\r\n if (/no match/i.test(text)) parts.push(\"an anchor matched nothing\");\r\n if (/overlap/i.test(text)) parts.push(\"edits overlapped\");\r\n if (/empty anchor|missing a string/i.test(text)) parts.push(\"an edit was missing its anchor or replacement\");\r\n return { text: parts.length > 0 ? [...new Set(parts)].join(\"; \") : \"the runtime could not place the edits\", matchCounts };\r\n}\r\n\r\n/** The two hard stops a reply can carry after any retry: a code that is never retried, and a judgedBy overflow that is\r\n * still too large after narrowing. One place so the whole-file fallback holds the same line as the first call. */\r\nfunction throwOnTerminalRefusal(envelope: any, targetPath: string): void {\r\n if (typeof envelope?.errorCode === \"string\" && NOT_RETRIED_CODES.has(envelope.errorCode)) {\r\n const detail = envelope.error ? `: ${envelope.error}` : \"\";\r\n throw new RuntimeReplyError(\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (not retried)${detail}`,\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (not retried)`,\r\n );\r\n }\r\n if (envelope?.errorCode === JUDGED_BY_TOO_LARGE_CODE) {\r\n // Still too large after narrowing (or the retry hit some other JUDGED_BY_TOO_LARGE cause) \u2014\r\n // no further retry, same all-or-nothing posture as every other codegen failure here.\r\n const detail = envelope.error ? `: ${envelope.error}` : \"\";\r\n throw new RuntimeReplyError(\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (after narrowing)${detail}`,\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (after narrowing)`,\r\n );\r\n }\r\n}\r\n\r\nfunction codegenRefusedError(targetPath: string, body: CodegenResult): RuntimeReplyError {\r\n return new RuntimeReplyError(\r\n `Codegen refused ${targetPath}${body.refusalReason ? `: ${body.refusalReason}` : \"\"}`,\r\n `Codegen refused ${targetPath}`,\r\n );\r\n}\r\n\r\nexport interface CodegenFileResult {\r\n targetPath: string;\r\n newContent: string;\r\n}\r\n\r\n/** \u00A718 `judgedBy` \u2014 the internal (runner-only) shape, keeping `automationId` for the\r\n * overflow-narrowing filter below; stripped down to `{title, given, when, then}` only when\r\n * actually serialized onto the wire (\u00A718.9 refuses any other key on an entry). */\r\nexport interface JudgedByCase {\r\n automationId: string;\r\n title: string;\r\n given: string;\r\n when: string;\r\n then: string;\r\n}\r\n\r\n/**\r\n * \u00A718 \u2014 every case claimed by SOME target in this run (not scoped to `contextPaths` matches \u2014\r\n * that's `narrowJudgedByForTarget`'s overflow-fallback job only, not the primary rule), minus\r\n * targeting's own `skippedCases` (\u00A715.3's `NO_BEHAVIOUR` skip), minus any entry still missing\r\n * given/when/then \u2014 defensive: a non-skipped case should already have all three by construction,\r\n * but \u00A718.9 refuses `CONTRACT_REJECTED` on any entry outside the declared shape, so this never\r\n * trusts that invariant blindly. Built once per run, in `run.ts`, and passed into `runCodegen`.\r\n */\r\nexport function buildJudgedByPool(\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n targets: PilotTarget[],\r\n skippedCases: SkippedCase[],\r\n): JudgedByCase[] {\r\n const claimedIds = new Set<string>();\r\n for (const t of targets) {\r\n for (const id of t.automationIds ?? []) claimedIds.add(id);\r\n }\r\n const skippedIds = new Set(skippedCases.map((s) => s.automationId));\r\n\r\n const pool: JudgedByCase[] = [];\r\n for (const tc of requiredTests) {\r\n if (!claimedIds.has(tc.automationId) || skippedIds.has(tc.automationId)) continue;\r\n if (!tc.given || !tc.when || !tc.then) continue;\r\n pool.push({ automationId: tc.automationId, title: tc.title, given: tc.given, when: tc.when, then: tc.then });\r\n }\r\n return pool;\r\n}\r\n\r\n/** \u00A718.8.1's overflow fallback \u2014 narrow the full pool down to only cases claimed by a test target\r\n * whose own `contextPaths` names this code target's path. Not the primary rule (a claiming test\r\n * target's `contextPaths` is model output and can be missing/wrong), only the retry narrowing. */\r\nfunction narrowJudgedByForTarget(pool: JudgedByCase[], targets: PilotTarget[], codeTargetPath: string): JudgedByCase[] {\r\n const narrowedIds = new Set<string>();\r\n for (const t of targets) {\r\n if (!t.automationIds?.length || !t.contextPaths?.includes(codeTargetPath)) continue;\r\n for (const id of t.automationIds) narrowedIds.add(id);\r\n }\r\n return pool.filter((c) => narrowedIds.has(c.automationId));\r\n}\r\n\r\n/** Strips `automationId` for the wire \u2014 \u00A718.9 refuses any key outside `{title, given, when, then}`. */\r\nfunction toWireJudgedBy(pool: JudgedByCase[]): { title: string; given: string; when: string; then: string }[] {\r\n return pool.map(({ automationId: _automationId, ...rest }) => rest);\r\n}\r\n\r\n/**\r\n * Run codegen for exactly the targets named, in order, stopping at the first failure. Throws\r\n * rather than returning a partial result \u2014 see the ALL-OR-NOTHING note above; a caller that wants\r\n * to know how far it got before failing should catch and inspect the message, not branch on a\r\n * return value that implies partial success is a valid state. Writes nothing \u2014 call\r\n * `flushCodegenResults` with the return value once this resolves.\r\n *\r\n * `warnings` is a shared, mutable array \u2014 same convention `run.ts` already uses for\r\n * QUIKTR-1064/1374's non-blocking findings \u2014 pushed into directly rather than returned, so this\r\n * function's return type stays `CodegenFileResult[]`.\r\n */\r\nexport async function runCodegen(\r\n gateway: PilotPacket[\"gateway\"],\r\n targets: PilotTarget[],\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n judgedByPool: JudgedByCase[],\r\n warnings: string[],\r\n /** QUIKTR-1421 \u2014 a caller-owned array this fills with one entry per call (what targeting named, what the\r\n * runner added, what it skipped), so run.ts can report it to QuikTrack. Optional and last: every existing\r\n * caller is unchanged. Entries are pushed BEFORE the call, so they survive a later throw. */\r\n contextLog?: CodegenContextRecord[],\r\n /** QUIKTR-1401 (\u00A720) \u2014 what the reviewer approved the change must NOT touch, sent on every call (code and test\r\n * targets alike) when non-empty. Optional and last: every existing caller is unchanged. */\r\n outOfScope: string[] = [],\r\n): Promise<CodegenFileResult[]> {\r\n const results: CodegenFileResult[] = [];\r\n const listing = new Set(workspaceListing);\r\n\r\n for (const target of targets) {\r\n const isNewFile = target.kind === \"NEW_FILE\";\r\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\r\n // 9.0.0, Doc 62 \u00A72 \u2014 an EXISTING file asks for anchored edits against its LF form, and gets its own convention back\r\n // when written. A file with BOTH conventions cannot be restored faithfully, so it keeps the whole-file path.\r\n const lineEnding: LineEnding = isNewFile ? \"LF\" : detectLineEnding(currentContent);\r\n const wantsEdits = !isNewFile && lineEnding !== \"mixed\";\r\n\r\n // targeting names its own context needs per target \u2014 an invented contextPath is the same\r\n // class of bug as an invented EXISTING target (targeting.ts's validateTarget): fail loudly\r\n // rather than silently sending less context than the model asked for.\r\n const contextPaths = target.contextPaths ?? [];\r\n // QUIKTR-1420 \u2014 the egress point: this is where a context file is READ and put in the request.\r\n // runTargeting re-checks too; this holds even for a target that did not come through it, and it runs\r\n // before the not-found check so a denied path is never reported as merely missing.\r\n const deniedContext = findDeniedContextPath(contextPaths, deniedPaths);\r\n if (deniedContext) {\r\n throw new Error(\r\n `pilot.codegen contextPaths cited a denied path (${deniedContext.pattern}): ${deniedContext.path} (target ${target.path})`,\r\n );\r\n }\r\n for (const contextPath of contextPaths) {\r\n if (!listing.has(contextPath)) {\r\n throw new Error(\r\n `pilot.codegen contextPaths named a file not found in the checkout: ${contextPath} (target ${target.path})`,\r\n );\r\n }\r\n }\r\n const namedContents = contextPaths.map((path) => ({ path, content: readFileSync(path, \"utf8\") }));\r\n\r\n // QUIKTR-1419 \u2014 for a test target, also the run's other existing code files (see collectRunContext).\r\n const runFiles = collectRunContext(target, targets, new Set(contextPaths), deniedPaths);\r\n for (const s of runFiles.skipped) {\r\n warnings.push(`not shown to the test for ${target.path}: ${s.path} (${s.reason})`);\r\n }\r\n // QUIKTR-1454 \u2014 and the files this target itself imports, one hop. Added AFTER what targeting named and what the\r\n // run's files brought, never instead of them. A NEW_FILE has no content to read imports from.\r\n const imports = isNewFile\r\n ? { entries: [], skipped: [], importedPaths: [], aliasImports: 0 }\r\n : collectImportContext({\r\n targetPath: target.path,\r\n source: currentContent,\r\n alreadyNamed: new Set([...contextPaths, ...runFiles.entries.map((e) => e.path)]),\r\n deniedPaths,\r\n listing,\r\n readFile: (p) => readFileSync(p, \"utf8\"),\r\n maxFileChars: MAX_ADDED_FILE_CHARS,\r\n maxTotalChars: MAX_ADDED_CONTEXT_CHARS,\r\n spentChars: runFiles.entries.reduce((n, e) => n + e.content.length, 0),\r\n });\r\n for (const s of imports.skipped) {\r\n if (ACTIONABLE_IMPORT_SKIPS.has(s.reason)) {\r\n warnings.push(`not shown with ${target.path}: ${s.path} (imported by it; ${s.reason.replace(/^import: /, \"\")})`);\r\n }\r\n }\r\n const added: Pick<AddedContext, \"entries\"> & { skipped: { path: string; reason: string }[] } = {\r\n entries: [...runFiles.entries, ...imports.entries],\r\n skipped: [...runFiles.skipped, ...imports.skipped],\r\n };\r\n const contextContents = [...namedContents, ...added.entries];\r\n // One line per call: which files targeting named and which the runner added. Without it, \"was the\r\n // file even in front of the model?\" cannot be answered from this runner's own log (run 25). QUIKTR-1454: and\r\n // which of those came from imports, what was skipped and why, and how many path aliases were not followed.\r\n const contextRecord: CodegenContextRecord = {\r\n targetPath: target.path,\r\n contextPaths,\r\n addedPaths: added.entries.map((e) => e.path),\r\n skipped: added.skipped,\r\n ...(imports.importedPaths.length > 0 ? { importedPaths: imports.importedPaths } : {}),\r\n ...(imports.aliasImports > 0 ? { aliasImports: imports.aliasImports } : {}),\r\n };\r\n console.log(JSON.stringify({ event: \"codegen.context\", ...contextRecord }));\r\n // QUIKTR-1421 \u2014 the same facts, handed back so they reach QuikTrack's run trail, not just this job's log.\r\n contextLog?.push(contextRecord);\r\n\r\n const contextData: Record<string, unknown> = {\r\n targetPath: target.path,\r\n // Every anchor and replacement is LF, always (Doc 62 \u00A72), so the file is sent as LF.\r\n currentContent: wantsEdits ? toLf(currentContent) : currentContent,\r\n planSteps: target.planStepsImplemented,\r\n kind: target.kind,\r\n contextContents,\r\n // QUIKTR-1083 (\u00A715.6) \u2014 required on every call on the versioned path.\r\n contractVersion: wantsEdits ? CONTRACT_VERSION_EDITS : CONTRACT_VERSION,\r\n };\r\n if (isNewFile) {\r\n // Bounds WHAT EXISTS \u2014 stops an invented import like hooks/useGroups \u2014 only meaningful for\r\n // a file that doesn't exist yet to compare against.\r\n contextData.workspaceListing = workspaceListing;\r\n }\r\n if (deniedPaths.length > 0) {\r\n contextData.deniedPaths = deniedPaths;\r\n }\r\n // QUIKTR-1401, \u00A720 \u2014 omitted rather than sent empty, same as deniedPaths. Free text: told, never checked.\r\n if (outOfScope.length > 0) {\r\n contextData.outOfScope = outOfScope;\r\n }\r\n // QUIKTR-1083 (\u00A715.4) \u2014 only for a test target (one targeting named automationIds for), and\r\n // only that target's own subset \u2014 never the full list, and never for a code target at all.\r\n if (target.automationIds && target.automationIds.length > 0) {\r\n const wanted = new Set(target.automationIds);\r\n contextData.requiredTests = requiredTests.filter((tc) => wanted.has(tc.automationId));\r\n } else if (judgedByPool.length > 0) {\r\n // \u00A718 \u2014 a code target (no automationIds of its own) gets the run's claimed cases as\r\n // judging context instead. Mutually exclusive with requiredTests per call, by construction:\r\n // this is the else branch of the exact same condition. Omitted entirely when the pool is\r\n // empty, never sent as `[]`.\r\n contextData.judgedBy = toWireJudgedBy(judgedByPool);\r\n }\r\n\r\n // QUIKTR-1069 \u2014 retries a transport-level failure only (502/503/504, a dropped connection);\r\n // a real refusal always arrives as a 200 with the refusal inside the envelope, below.\r\n const callCodegen = () =>\r\n fetchWithRetry(`${gateway.baseUrl}/ai/execute`, {\r\n method: \"POST\",\r\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\r\n body: JSON.stringify({\r\n appId: \"quiktrack\",\r\n useCase: \"pilot.codegen\",\r\n expectedOutputType: \"json\",\r\n userPrompt: \"\",\r\n contextData,\r\n }),\r\n });\r\n\r\n let res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n\r\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\r\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\r\n // CODEGEN_FILE_TOO_LARGE / CODEGEN_CONTEXT_TOO_LARGE are checked on the RAW envelope, before\r\n // unwrapping: they arrive as a failure (success:false), so unwrapping first would throw the\r\n // generic envelope error and lose the not-retried distinction this check exists to preserve.\r\n let envelope: any = await res.json();\r\n // QUIKTR-1083 \u2014 SEMANTIC_MISMATCH/CONTRACT_REJECTED, same \"raw envelope, before unwrap\" point\r\n // as the CODEGEN_* check right below.\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n\r\n // \u00A718.8.1 \u2014 the one retried refusal here: narrow judgedBy to only the cases a test target's\r\n // own contextPaths ties to this file, then retry ONCE. Recorded on the run's trail either way\r\n // (even if the retry still fails) so the trail shows what was attempted.\r\n if (envelope?.errorCode === JUDGED_BY_TOO_LARGE_CODE && contextData.judgedBy) {\r\n const before = (contextData.judgedBy as unknown[]).length;\r\n const narrowed = narrowJudgedByForTarget(judgedByPool, targets, target.path);\r\n if (narrowed.length > 0) {\r\n contextData.judgedBy = toWireJudgedBy(narrowed);\r\n } else {\r\n delete contextData.judgedBy;\r\n }\r\n warnings.push(`judgedBy narrowed for ${target.path}: ${before} \u2192 ${narrowed.length} cases`);\r\n\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n }\r\n\r\n // QUIKTR-1419 \u2014 the runner's own additions must never turn a run that would have passed into a\r\n // failure. If the runtime refuses the context as too large AND we added files, retry ONCE with only\r\n // what targeting named; if it still refuses, that overflow is real and falls through to the throw below.\r\n if (envelope?.errorCode === CONTEXT_TOO_LARGE_CODE && added.entries.length > 0) {\r\n contextData.contextContents = namedContents;\r\n warnings.push(`context for ${target.path} was too large with the run's other files; retried without them`);\r\n // QUIKTR-1421 \u2014 the record must not claim files were shown that the retry dropped. The same object is\r\n // already in `contextLog`, so mutating it updates what gets reported.\r\n contextRecord.addedPaths = [];\r\n delete contextRecord.importedPaths;\r\n contextRecord.retriedWithoutAdded = true;\r\n\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n }\r\n\r\n throwOnTerminalRefusal(envelope, target.path);\r\n\r\n // 9.0.0, Doc 62 \u00A72/\u00A72.1 \u2014 what became of the edits. `newContent` is the file to write; `failedEdits` is set when the\r\n // edits could not be used, and there is exactly ONE answer to that: ask again for the whole file, without edits-1.\r\n let newContent: string | null = null;\r\n let failedEdits: { reason: \"anchor_refused\" | \"local_refusal\"; summary: RefusalSummary } | null = null;\r\n let editCount: number | undefined;\r\n let path: EditsPath = \"whole_file\";\r\n let reason: string | undefined = isNewFile ? \"new_file\" : wantsEdits ? undefined : \"mixed_line_endings\";\r\n\r\n if (wantsEdits && envelope?.errorCode === ANCHOR_REFUSED_CODE) {\r\n // Arrives only after the runtime's own ONE regeneration, so \"this was already retried\" is unambiguous.\r\n failedEdits = { reason: \"anchor_refused\", summary: summariseRuntimeRefusal(envelope.error) };\r\n } else {\r\n const body = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\r\n if (wantsEdits) {\r\n // A genuine refusal is the runtime's answer, not a malformed one: it ends the run exactly as it always has.\r\n if (body.outcome === \"REFUSED\") throw codegenRefusedError(target.path, body);\r\n // We asked for edits-1, so check we GOT edits-1 before using anything (Suyash, 5 Oct). `newContent` is valid under\r\n // test-targets-1, which is exactly why it must not be applied here: the call would succeed having asked for edits\r\n // and silently got something else. The runtime turns a malformed reply into SCHEMA_MISMATCH, so this should never\r\n // arrive; if it does it is a failure, not a candidate for the fallback, which is for anchors only (Suyash).\r\n if (body.outcome !== \"GENERATED\" || typeof body.newContent === \"string\") {\r\n throw new RuntimeReplyError(\r\n `Codegen reply for ${target.path} was not in the edits-1 shape and was not applied`,\r\n `Codegen reply for ${target.path} was not in the edits-1 shape`,\r\n );\r\n }\r\n // Every anchor is resolved against the content we sent, by the same rules the runtime held: exactly once, no\r\n // overlap. The runner writes the file, so it does not take the runtime's word for it.\r\n const applied = applyEdits(toLf(currentContent), body.edits);\r\n if (applied.ok) {\r\n newContent = fromLf(applied.content, lineEnding);\r\n path = \"edits\";\r\n editCount = applied.editCount;\r\n } else if (applied.refusals.some((r) => r.kind === \"no_edits\")) {\r\n // GENERATED with nothing to apply: a model that changed nothing while saying it did. The runtime's own answer to\r\n // that is SEMANTIC_MISMATCH, which is never retried; asking again here would only spend a bigger call on it.\r\n throw new RuntimeReplyError(\r\n `Codegen reply for ${target.path} carried no edits (not retried)`,\r\n `Codegen reply for ${target.path} carried no edits`,\r\n );\r\n } else {\r\n // Anchors that could not be placed: the one thing the whole-file fallback is for.\r\n failedEdits = { reason: \"local_refusal\", summary: summariseLocalRefusals(applied.refusals) };\r\n }\r\n } else {\r\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\r\n throw codegenRefusedError(target.path, body);\r\n }\r\n newContent = body.newContent;\r\n }\r\n }\r\n\r\n if (failedEdits) {\r\n // The saving is lost on this call; the run survives, so edits-1 is never a new way to fail. It is also VISIBLE: this\r\n // warning reaches QuikTrack's run trail, which a runtime-side fallback could not do. Counts only, never an anchor.\r\n warnings.push(\r\n `edits for ${target.path} could not be placed (${failedEdits.summary.text}); asked again for the whole file`,\r\n );\r\n contextData.currentContent = currentContent;\r\n contextData.contractVersion = CONTRACT_VERSION;\r\n try {\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n throwOnTerminalRefusal(envelope, target.path);\r\n const whole = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\r\n if (whole.outcome !== \"GENERATED\" || typeof whole.newContent !== \"string\") {\r\n throw codegenRefusedError(target.path, whole);\r\n }\r\n newContent = whole.newContent;\r\n } catch (error: unknown) {\r\n // Honest, not a retry: the whole file is a BIGGER request, so where the provider cannot serve a large one\r\n // (AI_UNAVAILABLE) this can only fail the same way, and that is not transient. Say what happened and in which\r\n // order, so the failure is not read as a plain provider hiccup. Names and codes only in the reported summary.\r\n if (error instanceof RuntimeReplyError) {\r\n throw new RuntimeReplyError(\r\n `${error.message} (this was the whole-file request made after the edits for ${target.path} were refused: ${failedEdits.summary.text})`,\r\n `${error.summary} (the whole-file request, made after the edits were refused)`,\r\n );\r\n }\r\n throw error;\r\n }\r\n path = \"fallback\";\r\n reason = failedEdits.reason;\r\n }\r\n\r\n if (newContent === null) throw new Error(`Codegen produced no content for ${target.path}`);\r\n\r\n if (!isNewFile) {\r\n // Which path each call took (Doc 62 \u00A72.1): without it nobody can tell whether the retry earns its place, and the\r\n // measurement is free if collected from the start. Counts and outcomes only: no anchor, no replacement.\r\n console.log(\r\n JSON.stringify({\r\n event: \"codegen.edits_path\",\r\n targetPath: target.path,\r\n path,\r\n ...(reason ? { reason } : {}),\r\n ...(editCount !== undefined ? { editCount } : {}),\r\n ...(failedEdits && failedEdits.summary.matchCounts.length > 0 ? { matchCounts: failedEdits.summary.matchCounts } : {}),\r\n lineEnding,\r\n }),\r\n );\r\n }\r\n\r\n if (!isNewFile) {\r\n const suspectReason = looksLikeTruncatedRewrite(target, currentContent, newContent);\r\n if (suspectReason) {\r\n throw new Error(\r\n `Codegen output for ${target.path} looks like a truncated/abbreviated rewrite (${suspectReason}) ` +\r\n `\u2014 refusing to apply it. Interim guard per \u00A716.7; the AI Runtime's own output-cap check is not live yet.`,\r\n );\r\n }\r\n }\r\n\r\n // AI Runtime, 2026-09-24 \u2014 one structured line per call, to build the input/output/removed-line\r\n // distribution SUSPECT_LENGTH_DROP_RATIO and SUSPECT_REMOVED_LINE_RATIO were guessed without.\r\n // Not itself a safety check \u2014 plain data collection for calibrating the two guards above.\r\n console.log(\r\n JSON.stringify({\r\n event: \"codegen.metrics\",\r\n targetPath: target.path,\r\n kind: target.kind,\r\n inputLength: currentContent.length,\r\n outputLength: newContent.length,\r\n removedLines: isNewFile ? null : countRemovedLines(currentContent, newContent),\r\n }),\r\n );\r\n\r\n results.push({ targetPath: target.path, newContent });\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\r\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\r\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\r\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\r\n for (const { targetPath, newContent } of results) {\r\n mkdirSync(dirname(targetPath), { recursive: true });\r\n writeFileSync(targetPath, newContent);\r\n }\r\n}\r\n", "/**\r\n * QUIKTR-1083 (\u00A715.3) \u2014 layer 2 of the three denied-path layers the contract describes: after\r\n * `pilot.targeting` responds, every proposed target's path is checked against `deniedPaths` here,\r\n * before any codegen spend. (Layer 1 is the AI Runtime's own targeting validator; layer 3 is\r\n * `guardrail.ts`'s post-commit check on the actually-staged diff.)\r\n *\r\n * Hand-rolled rather than a `minimatch`/`picomatch` dependency: this package is published\r\n * publicly and carries no secrets or heavy deps on purpose (see workflow-template.ts's own\r\n * docblock), and the denied-path patterns in real use (a dotfile glob under a double-star prefix,\r\n * a workflows directory suffixed with a double star, a bare lockfile name under a double-star\r\n * prefix) never need brace expansion, character classes, or `?` \u2014 only a double star (any depth,\r\n * including none) and a single star (anything but a path separator). A dependency for two glob\r\n * tokens is not worth the weight.\r\n */\r\nfunction globToRegExp(pattern: string): RegExp {\r\n const escaped = pattern\r\n .split(\"\")\r\n .map((c) => (/[.+^${}()|[\\]\\\\]/.test(c) ? `\\\\${c}` : c))\r\n .join(\"\");\r\n // Order matters: the more specific `**/` token first, so the generic `**`/`*` passes below\r\n // don't consume it first and lose the \"zero directories is also a match\" behaviour every\r\n // default pattern (`**/*.env*`, `**/package-lock.json`, ...) actually depends on \u2014 a repo-root\r\n // `.env` must match `**/*.env*` exactly as a nested one does, the same way `.gitignore`'s own\r\n // `**/` prefix works.\r\n const withGlobs = escaped\r\n .replace(/\\*\\*\\//g, \" SLASH \")\r\n .replace(/\\*\\*/g, \" STAR \")\r\n .replace(/\\*/g, \"[^/]*\")\r\n .replace(/ SLASH /g, \"(?:.*/)?\")\r\n .replace(/ STAR /g, \".*\");\r\n return new RegExp(`^${withGlobs}$`);\r\n}\r\n\r\n/** The first pattern `path` matches, or `null`. `path` is repo-relative, matching how every\r\n * `deniedPaths` entry and every target's `path` are already written elsewhere in this package. */\r\nexport function matchesDeniedPath(path: string, patterns: string[]): string | null {\r\n for (const pattern of patterns) {\r\n if (globToRegExp(pattern).test(path)) return pattern;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * QUIKTR-1420 \u2014 the first path in a list that matches a denied pattern, with the pattern it matched, or\r\n * `null`. For `contextPaths`: the runner reads each one and puts its content in the request to the model\r\n * provider, so a protected file cited as context is the same egress as one named as a target. The AI Runtime\r\n * refuses these itself (pilot_targeting.py:374, per Suyash), but for targets this package deliberately\r\n * re-checks rather than trusting that, and context was the one gap.\r\n */\r\nexport function findDeniedContextPath(\r\n contextPaths: string[],\r\n patterns: string[],\r\n): { path: string; pattern: string } | null {\r\n for (const path of contextPaths) {\r\n const pattern = matchesDeniedPath(path, patterns);\r\n if (pattern) return { path, pattern };\r\n }\r\n return null;\r\n}\r\n", "/**\r\n * Doc 62 \u00A72 / \u00A72.1 (\"edits-1\") \u2014 applying the AI Runtime's anchored edits to a file the runner is about to write.\r\n *\r\n * The runtime validates anchors against the content it was sent and splices only to measure the result; the RUNNER\r\n * writes the real file, so it applies the edits itself and holds the same rules rather than trusting the reply:\r\n * - every `find` matches the ORIGINAL content exactly once. Zero or several is a refusal, never a guess;\r\n * - every range is resolved before anything is applied, so a whole response is validated or refused;\r\n * - overlapping ranges refuse the WHOLE response; adjacent ranges do not overlap;\r\n * - application is order-independent, because ranges are spliced by position, not applied in sequence.\r\n *\r\n * Line endings: the content handed to `applyEdits` is LF. `toLf` / `detectLineEnding` / `fromLf` normalise a file before it\r\n * is sent and restore its own convention when it is written. Nothing else is normalised: in Python and YAML whitespace is\r\n * semantics, not formatting.\r\n *\r\n * Refusal messages carry counts and edit numbers only, never the text of an anchor or a replacement: they end up in the\r\n * run's warnings, which reach QuikTrack, and customer code does not.\r\n */\r\n\r\nexport type LineEnding = \"LF\" | \"CRLF\" | \"mixed\";\r\n\r\n/** The convention of `text` as read from disk. A lone CR is not a line ending, so it is counted neither way. */\r\nexport function detectLineEnding(text: string): LineEnding {\r\n const crlf = text.split(\"\\r\\n\").length - 1;\r\n const bareLf = text.split(\"\\n\").length - 1 - crlf;\r\n if (crlf > 0 && bareLf > 0) return \"mixed\";\r\n return crlf > 0 ? \"CRLF\" : \"LF\";\r\n}\r\n\r\nexport function toLf(text: string): string {\r\n return text.replace(/\\r\\n/g, \"\\n\");\r\n}\r\n\r\n/** Restores a convention on LF text. `mixed` cannot be restored faithfully, so callers never ask for it. */\r\nexport function fromLf(text: string, ending: LineEnding): string {\r\n return ending === \"CRLF\" ? text.replace(/\\n/g, \"\\r\\n\") : text;\r\n}\r\n\r\nexport type AnchorRefusalKind = \"ambiguous\" | \"no_match\" | \"empty\" | \"overlap\" | \"no_edits\";\r\n\r\nexport interface AnchorRefusal {\r\n kind: AnchorRefusalKind;\r\n /** 1-based numbers of the edits involved: one, or two for an overlap; empty for `no_edits`. */\r\n edits: number[];\r\n /** How many times the anchor matched; null when that does not apply. */\r\n matchCount: number | null;\r\n message: string;\r\n}\r\n\r\nexport type EditsOutcome =\r\n | { ok: true; content: string; editCount: number }\r\n | { ok: false; refusals: AnchorRefusal[]; editCount: number };\r\n\r\n/** Every start index of `needle` in `haystack`, overlapping occurrences included: \"aa\" occurs twice in \"aaa\", and an\r\n * anchor that can be placed two ways identifies no place. */\r\nfunction occurrences(haystack: string, needle: string): number[] {\r\n const found: number[] = [];\r\n let index = haystack.indexOf(needle);\r\n while (index !== -1) {\r\n found.push(index);\r\n index = haystack.indexOf(needle, index + 1);\r\n }\r\n return found;\r\n}\r\n\r\ninterface PlacedRange {\r\n start: number;\r\n end: number;\r\n number: number;\r\n replace: string;\r\n}\r\n\r\n/** Resolve every edit against `originalLf`, then either refuse the whole response or splice. Pure. */\r\nexport function applyEdits(originalLf: string, edits: unknown): EditsOutcome {\r\n if (!Array.isArray(edits) || edits.length === 0) {\r\n return {\r\n ok: false,\r\n editCount: 0,\r\n refusals: [{ kind: \"no_edits\", edits: [], matchCount: null, message: \"the response carried no edits\" }],\r\n };\r\n }\r\n\r\n const refusals: AnchorRefusal[] = [];\r\n const ranges: PlacedRange[] = [];\r\n\r\n edits.forEach((edit: unknown, index: number) => {\r\n const number = index + 1;\r\n const record = edit !== null && typeof edit === \"object\" ? (edit as Record<string, unknown>) : null;\r\n const find = record?.find;\r\n const replace = record?.replace;\r\n if (typeof find !== \"string\" || typeof replace !== \"string\") {\r\n refusals.push({\r\n kind: \"empty\",\r\n edits: [number],\r\n matchCount: null,\r\n message: `edit ${number} is missing a string find or replace`,\r\n });\r\n return;\r\n }\r\n if (find === \"\") {\r\n refusals.push({ kind: \"empty\", edits: [number], matchCount: null, message: `edit ${number} has an empty anchor` });\r\n return;\r\n }\r\n const starts = occurrences(originalLf, find);\r\n if (starts.length === 0) {\r\n refusals.push({ kind: \"no_match\", edits: [number], matchCount: 0, message: `edit ${number}: the anchor matched nothing` });\r\n } else if (starts.length > 1) {\r\n refusals.push({\r\n kind: \"ambiguous\",\r\n edits: [number],\r\n matchCount: starts.length,\r\n message: `edit ${number}: the anchor matched ${starts.length} times`,\r\n });\r\n } else {\r\n ranges.push({ start: starts[0]!, end: starts[0]! + find.length, number, replace });\r\n }\r\n });\r\n\r\n // Every overlapping pair, among the anchors that did place. Adjacent ranges (one ends where the next starts) are fine.\r\n for (let i = 0; i < ranges.length; i++) {\r\n for (let j = i + 1; j < ranges.length; j++) {\r\n const a = ranges[i]!;\r\n const b = ranges[j]!;\r\n if (a.start < b.end && b.start < a.end) {\r\n const [first, second] = a.number < b.number ? [a.number, b.number] : [b.number, a.number];\r\n refusals.push({\r\n kind: \"overlap\",\r\n edits: [first, second],\r\n matchCount: null,\r\n message: `edits ${first} and ${second} overlap`,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (refusals.length > 0) return { ok: false, refusals, editCount: edits.length };\r\n\r\n const pieces: string[] = [];\r\n let cursor = 0;\r\n for (const range of [...ranges].sort((x, y) => x.start - y.start)) {\r\n pieces.push(originalLf.slice(cursor, range.start), range.replace);\r\n cursor = range.end;\r\n }\r\n pieces.push(originalLf.slice(cursor));\r\n return { ok: true, content: pieces.join(\"\"), editCount: edits.length };\r\n}\r\n", "/** An error whose message quotes something the AI Runtime sent back: its explanation, a refusal reason, or the reply\r\n * itself. That text can carry case text or generated code, so the full `message` stays in the job log (where it has\r\n * always gone) and only `summary` \u2014 the error's name and code \u2014 may leave the job in the failed callback. Truncating\r\n * the message would bound its size, not its kind. */\r\nexport class RuntimeReplyError extends Error {\r\n readonly summary: string;\r\n\r\n constructor(message: string, summary: string) {\r\n super(message);\r\n this.name = \"RuntimeReplyError\";\r\n this.summary = summary;\r\n }\r\n}\r\n", "import { RuntimeReplyError } from \"./runtimeReplyError\";\r\n\r\n/**\r\n * QUIKTR-1046 \u2014 `/ai/execute` wraps every use-case result in an envelope; the use-case's own result\r\n * lives at `envelope.structuredJson`, not at the top level. Both `targeting.ts` and `codegen.ts`\r\n * read the raw response directly and have never worked against a real reply \u2014 this is the one\r\n * place that unwraps it, so there is exactly one place to get it right.\r\n *\r\n * A failed call can arrive as `success: false` in an HTTP 200 body \u2014 `res.ok` alone is not enough.\r\n * Observed live 2026-09-18/19/21, including a real RUN_CREDENTIAL_SCOPE refusal shaped exactly\r\n * like this.\r\n */\r\n/**\r\n * QUIKTR-1083 (\u00A715 of the spec-phase contract) \u2014 two hard-failure codes the AI Runtime raises on\r\n * the versioned `pilot.targeting`/`pilot.codegen` path, neither ever retried: `SEMANTIC_MISMATCH`\r\n * (the JSON shape was valid, a rule failed \u2014 e.g. a generated test file missing its\r\n * `[<automationId>]` marker) and `CONTRACT_REJECTED` (the request itself was refused \u2014 an unknown\r\n * or removed `contextData` key, or an unrecognised `contractVersion`). Both carry the explanation\r\n * in `envelope.error`.\r\n *\r\n * Checked on the RAW envelope, before `unwrapExecute` \u2014 same reason codegen.ts's existing\r\n * `CODEGEN_FILE_TOO_LARGE`/`CODEGEN_CONTEXT_TOO_LARGE` check already runs there: unwrapping first\r\n * would throw `unwrapExecute`'s generic `success:false` error and lose the distinction. No custom\r\n * error class \u2014 `run.ts`'s top-level catch already prints any thrown error's message, and\r\n * `fetchWithRetry` never retries a 200 response regardless of body, so \"print the violation list\"\r\n * and \"never retried\" both already hold once this throws a message that names the code and detail.\r\n */\r\nconst HARD_FAILURE_CODES = new Set([\"SEMANTIC_MISMATCH\", \"CONTRACT_REJECTED\"]);\r\n\r\n/** `target`, when the call is scoped to one file (codegen), is named in the message: the AI\r\n * Runtime's explanation says what broke but not in which file. */\r\nexport function checkHardFailure(envelope: any, useCase: string, target?: string): void {\r\n const code = envelope?.errorCode;\r\n if (typeof code === \"string\" && HARD_FAILURE_CODES.has(code)) {\r\n const detail = envelope.error ?? envelope.normalizedText ?? \"no detail\";\r\n const where = target ? ` for ${target}` : \"\";\r\n throw new RuntimeReplyError(\r\n `${useCase} failed${where} (${code}, not retried): ${detail}`,\r\n `${useCase} failed${where} (${code}, not retried)`,\r\n );\r\n }\r\n}\r\n\r\n/** Every error below quotes the AI Runtime's reply in its message (the job log keeps it); `RuntimeReplyError.summary`\r\n * is the name and code only, which is all that may be reported to QuikTrack. */\r\nexport function unwrapExecute<T>(envelope: any, useCase: string): T {\r\n if (envelope?.success === false) {\r\n const code = envelope.errorCode ?? \"UNKNOWN\";\r\n throw new RuntimeReplyError(\r\n `${useCase} failed: ${code} \u2014 ${envelope.error ?? envelope.normalizedText ?? \"no message\"}`,\r\n `${useCase} failed: ${code}`,\r\n );\r\n }\r\n if (!envelope?.structuredJson || typeof envelope.structuredJson !== \"object\") {\r\n throw new RuntimeReplyError(\r\n `${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`,\r\n `${useCase} returned no structuredJson`,\r\n );\r\n }\r\n return envelope.structuredJson as T;\r\n}\r\n", "import { posix } from \"node:path\";\r\nimport { matchesDeniedPath } from \"./deniedPaths\";\r\n\r\n/**\r\n * QUIKTR-1454 \u2014 the files a changed file imports, shown to the code-writing step alongside the ones targeting\r\n * named. First real 9.0.0 run (QUIKSPL-35): `validation.js` imports from `exchange.js`, targeting did not list\r\n * it, and the model invented a name that file does not export. An import is a fact the file states, so it is\r\n * parsed here rather than asked of a model (Suyash, 5 Oct). Three rules from him: ONE hop (never what an\r\n * imported file imports), what was added and skipped is logged with the reason, and targeting's own list is\r\n * never replaced \u2014 this only adds to it.\r\n *\r\n * Pure: the caller hands over the repo listing and a reader. JavaScript/TypeScript only for now; any other kind\r\n * of file simply yields nothing.\r\n */\r\n\r\n// \u2500\u2500 reading imports out of source \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\ntype Token = { k: \"id\" | \"str\" | \"num\" | \"p\" | \"tpl\"; v: string };\r\n\r\nconst REGEX_PRECEDING_KEYWORDS = new Set([\r\n \"return\", \"typeof\", \"instanceof\", \"in\", \"of\", \"new\", \"delete\", \"void\", \"throw\", \"case\", \"do\", \"else\", \"yield\", \"await\",\r\n]);\r\n\r\n/** ASCII space characters plus the Unicode ones editors leave in files: byte-order mark, no-break space, line and\r\n * paragraph separators. A leading BOM read as part of the word \"import\" hid the first import of 72 repository files. */\r\nconst SPACE_CODES = new Set([0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0xa0, 0x1680, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, 0xfeff]);\r\nconst isSpace = (c: string) => {\r\n const code = c.charCodeAt(0);\r\n return SPACE_CODES.has(code) || (code >= 0x2000 && code <= 0x200a);\r\n};\r\nconst isIdStart = (c: string) => !isSpace(c) && (/[A-Za-z_$]/.test(c) || c.charCodeAt(0) > 0x7f);\r\nconst isIdPart = (c: string) => !isSpace(c) && (/[A-Za-z0-9_$]/.test(c) || c.charCodeAt(0) > 0x7f);\r\n\r\n/**\r\n * Splits source into the tokens that matter and drops what must not be mistaken for code: comments, string\r\n * contents, template text and regular-expression literals. A quote that never closes on its line ends at the\r\n * line break, as a real scanner reports it \u2014 a JSX apostrophe (\"Don't\") must not swallow the rest of the file.\r\n * `${ \u2026 }` inside a template is code and is scanned (an `import()` can sit there).\r\n */\r\nfunction tokenize(src: string): Token[] {\r\n const out: Token[] = [];\r\n const n = src.length;\r\n\r\n function regexAllowed(): boolean {\r\n const prev = out[out.length - 1];\r\n if (!prev) return true;\r\n if (prev.k === \"p\") return prev.v !== \")\" && prev.v !== \"]\" && prev.v !== \"}\";\r\n if (prev.k === \"id\") return REGEX_PRECEDING_KEYWORDS.has(prev.v);\r\n return false;\r\n }\r\n\r\n /** Scans code from `i`; when `inSubstitution`, stops after the `}` that closes the `${`. Returns the next index. */\r\n function scan(start: number, inSubstitution: boolean): number {\r\n let i = start;\r\n let depth = 0;\r\n while (i < n) {\r\n const c = src[i]!;\r\n if (isSpace(c)) {\r\n i++;\r\n continue;\r\n }\r\n if (c === \"/\" && src[i + 1] === \"/\") {\r\n while (i < n && src[i] !== \"\\n\") i++;\r\n continue;\r\n }\r\n if (c === \"/\" && src[i + 1] === \"*\") {\r\n const end = src.indexOf(\"*/\", i + 2);\r\n i = end === -1 ? n : end + 2;\r\n continue;\r\n }\r\n if (c === \"'\" || c === '\"') {\r\n let j = i + 1;\r\n let closed = false;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === c) {\r\n closed = true;\r\n break;\r\n }\r\n if (d === \"\\n\" || d === \"\\r\") break;\r\n j++;\r\n }\r\n if (closed) out.push({ k: \"str\", v: src.slice(i + 1, j) });\r\n i = closed ? j + 1 : j;\r\n continue;\r\n }\r\n if (c === \"`\") {\r\n let j = i + 1;\r\n let hasSubstitution = false;\r\n let closed = false;\r\n const textStart = j;\r\n let textEnd = j;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === \"`\") {\r\n closed = true;\r\n textEnd = hasSubstitution ? textEnd : j;\r\n break;\r\n }\r\n if (d === \"$\" && src[j + 1] === \"{\") {\r\n hasSubstitution = true;\r\n j = scan(j + 2, true);\r\n continue;\r\n }\r\n j++;\r\n }\r\n if (closed) out.push(hasSubstitution ? { k: \"tpl\", v: \"\" } : { k: \"str\", v: src.slice(textStart, textEnd) });\r\n i = closed ? j + 1 : n;\r\n continue;\r\n }\r\n if (c === \"/\" && regexAllowed()) {\r\n let j = i + 1;\r\n let inClass = false;\r\n let closed = false;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === \"\\n\" || d === \"\\r\") break;\r\n if (d === \"[\") inClass = true;\r\n else if (d === \"]\") inClass = false;\r\n else if (d === \"/\" && !inClass) {\r\n closed = true;\r\n break;\r\n }\r\n j++;\r\n }\r\n if (closed) {\r\n j++;\r\n while (j < n && /[a-z]/i.test(src[j]!)) j++;\r\n out.push({ k: \"num\", v: \"/re/\" });\r\n i = j;\r\n continue;\r\n }\r\n out.push({ k: \"p\", v: \"/\" });\r\n i++;\r\n continue;\r\n }\r\n if (/[0-9]/.test(c)) {\r\n let j = i + 1;\r\n while (j < n && /[0-9A-Za-z_.]/.test(src[j]!)) j++;\r\n out.push({ k: \"num\", v: src.slice(i, j) });\r\n i = j;\r\n continue;\r\n }\r\n if (isIdStart(c)) {\r\n let j = i + 1;\r\n while (j < n && isIdPart(src[j]!)) j++;\r\n out.push({ k: \"id\", v: src.slice(i, j) });\r\n i = j;\r\n continue;\r\n }\r\n if (inSubstitution) {\r\n if (c === \"{\") depth++;\r\n else if (c === \"}\") {\r\n if (depth === 0) return i + 1;\r\n depth--;\r\n }\r\n }\r\n out.push({ k: \"p\", v: c });\r\n i++;\r\n }\r\n return n;\r\n }\r\n\r\n scan(0, false);\r\n return out;\r\n}\r\n\r\n/**\r\n * The module specifiers a JavaScript/TypeScript file names, in order of first appearance, each once: static\r\n * `import \u2026 from`, side-effect `import \"x\"`, `export \u2026 from`, `import(\"x\")`, `require(\"x\")` and\r\n * `import x = require(\"x\")`. Only string literals (or a template with no substitution) count; an expression is\r\n * ignored, as are comments, text inside strings and a method that merely happens to be called `require`.\r\n */\r\nexport function extractImportSpecifiers(source: string): string[] {\r\n const t = tokenize(source);\r\n const found: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (s: string) => {\r\n if (!seen.has(s)) {\r\n seen.add(s);\r\n found.push(s);\r\n }\r\n };\r\n const isP = (tok: Token | undefined, v: string) => tok?.k === \"p\" && tok.v === v;\r\n\r\n for (let i = 0; i < t.length; i++) {\r\n const tok = t[i]!;\r\n if (tok.k !== \"id\") continue;\r\n if (isP(t[i - 1], \".\")) continue; // obj.import / obj.require \u2014 a property, not the keyword\r\n\r\n if (tok.v === \"require\") {\r\n if (isP(t[i + 1], \"(\") && t[i + 2]?.k === \"str\" && isP(t[i + 3], \")\")) add(t[i + 2]!.v);\r\n continue;\r\n }\r\n if (tok.v !== \"import\" && tok.v !== \"export\") continue;\r\n\r\n const next = t[i + 1];\r\n if (tok.v === \"import\") {\r\n if (next?.k === \"str\") {\r\n add(next.v);\r\n continue;\r\n }\r\n if (isP(next, \"(\")) {\r\n if (t[i + 2]?.k === \"str\" && (isP(t[i + 3], \")\") || isP(t[i + 3], \",\"))) add(t[i + 2]!.v);\r\n continue;\r\n }\r\n }\r\n // import <clause> from \"x\" / export <clause> from \"x\". The scan ends at the next import or export, so a long\r\n // chain of back-to-back statements (`export{a}export{b}\u2026`, no semicolons) is read once, not once per statement.\r\n for (let j = i + 1; j < t.length; j++) {\r\n const c = t[j]!;\r\n if (c.k === \"id\") {\r\n if (c.v === \"import\" || c.v === \"export\") break;\r\n if (c.v === \"from\" && t[j + 1]?.k === \"str\") {\r\n add(t[j + 1]!.v);\r\n break;\r\n }\r\n continue;\r\n }\r\n if (c.k === \"p\" && (c.v === \"{\" || c.v === \"}\" || c.v === \",\" || c.v === \"*\")) continue;\r\n break;\r\n }\r\n }\r\n return found;\r\n}\r\n\r\n/** Files the scanner understands. */\r\nexport function supportsImportScan(path: string): boolean {\r\n return /\\.(?:[cm]?[jt]sx?)$/i.test(path);\r\n}\r\n\r\n// \u2500\u2500 turning a specifier into a file in the repository \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport type ResolvedImport =\r\n | { kind: \"repo\"; path: string }\r\n | { kind: \"external\" }\r\n | { kind: \"unresolved\"; reason: \"alias\" | \"not found\" | \"asset\"; attempted?: string };\r\n\r\nconst CODE_EXTS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\", \".json\"];\r\nconst ASSET_EXTS = new Set([\r\n \".css\", \".scss\", \".sass\", \".less\", \".svg\", \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".avif\", \".ico\", \".bmp\",\r\n \".woff\", \".woff2\", \".ttf\", \".otf\", \".eot\", \".mp3\", \".mp4\", \".webm\", \".wav\", \".pdf\", \".zip\", \".wasm\",\r\n]);\r\n/** TypeScript's ESM habit: `./x.js` written in source, `x.ts` on disk. */\r\nconst TS_SIBLINGS: Record<string, string[]> = { \".js\": [\".ts\", \".tsx\"], \".jsx\": [\".tsx\"], \".mjs\": [\".mts\"], \".cjs\": [\".cts\"] };\r\n\r\n/**\r\n * Where a specifier points. `listing` is the repository's file list (the same notion of \"what exists\" targeting's\r\n * context paths are checked against), so nothing is probed on disk and nothing outside it is ever followed.\r\n */\r\nexport function resolveImport(fromPath: string, specifier: string, listing: ReadonlySet<string>): ResolvedImport {\r\n if (/^(?:@\\/|~\\/|#|\\$|\\/)/.test(specifier)) return { kind: \"unresolved\", reason: \"alias\" };\r\n const clean = specifier.replace(/[?#].*$/, \"\");\r\n const relative = clean === \".\" || clean === \"..\" || clean.startsWith(\"./\") || clean.startsWith(\"../\");\r\n if (!relative) return { kind: \"external\" };\r\n\r\n const base = posix.normalize(posix.join(posix.dirname(fromPath), clean));\r\n if (base === \"..\" || base.startsWith(\"../\") || posix.isAbsolute(base)) return { kind: \"unresolved\", reason: \"not found\" };\r\n\r\n const ext = posix.extname(base);\r\n if (ASSET_EXTS.has(ext.toLowerCase())) return { kind: \"unresolved\", reason: \"asset\" };\r\n\r\n const candidates: string[] = [];\r\n if (CODE_EXTS.includes(ext)) {\r\n candidates.push(base);\r\n for (const sibling of TS_SIBLINGS[ext] ?? []) candidates.push(base.slice(0, -ext.length) + sibling);\r\n }\r\n for (const e of CODE_EXTS) candidates.push(base + e);\r\n candidates.push(base + \".d.ts\");\r\n for (const e of CODE_EXTS) candidates.push(`${base}/index${e}`);\r\n\r\n for (const candidate of candidates) {\r\n if (listing.has(candidate)) return { kind: \"repo\", path: candidate };\r\n }\r\n return { kind: \"unresolved\", reason: \"not found\", attempted: base };\r\n}\r\n\r\n// \u2500\u2500 what gets added \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport interface ImportContextParams {\r\n targetPath: string;\r\n /** The target's content on disk now. */\r\n source: string;\r\n /** Paths already in front of the model for this call (targeting's list and the run's other files). */\r\n alreadyNamed: ReadonlySet<string>;\r\n deniedPaths: string[];\r\n listing: ReadonlySet<string>;\r\n readFile: (path: string) => string;\r\n maxFileChars: number;\r\n maxTotalChars: number;\r\n /** Characters the run's other added files already spent against `maxTotalChars`. */\r\n spentChars: number;\r\n}\r\n\r\nexport interface ImportContext {\r\n entries: { path: string; content: string }[];\r\n skipped: { path: string; reason: string }[];\r\n /** The paths of `entries`, for the context log. */\r\n importedPaths: string[];\r\n /** Path-alias imports (`@/x`) seen and not followed. Counted, not listed: they can be many. */\r\n aliasImports: number;\r\n}\r\n\r\n/** Skips worth a line in the run's notes: the file mattered and could not be shown. The rest stay in the log. */\r\nexport const ACTIONABLE_IMPORT_SKIPS = new Set([\"import: too large\", \"import: over budget\", \"import: unreadable\"]);\r\n\r\n/**\r\n * The direct imports of one target, read and sized like the run's other added files (same per-file and total\r\n * limits, shared). Order is first appearance in the file. A path already named, already added, or the target\r\n * itself is never repeated; a denied path is never read.\r\n */\r\nexport function collectImportContext(p: ImportContextParams): ImportContext {\r\n const out: ImportContext = { entries: [], skipped: [], importedPaths: [], aliasImports: 0 };\r\n if (!supportsImportScan(p.targetPath)) return out;\r\n\r\n const seen = new Set<string>(p.alreadyNamed);\r\n seen.add(p.targetPath);\r\n let total = p.spentChars;\r\n\r\n for (const specifier of extractImportSpecifiers(p.source)) {\r\n const resolved = resolveImport(p.targetPath, specifier, p.listing);\r\n if (resolved.kind === \"external\") continue;\r\n if (resolved.kind === \"unresolved\") {\r\n if (resolved.reason === \"alias\") out.aliasImports++;\r\n else if (resolved.reason === \"not found\") {\r\n const path = resolved.attempted ?? specifier;\r\n if (!seen.has(path)) {\r\n seen.add(path);\r\n out.skipped.push({ path, reason: \"import: not in workspace\" });\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n const path = resolved.path;\r\n if (seen.has(path)) continue;\r\n seen.add(path);\r\n // Defence in depth, like the run-file collector: a path in context is read and sent to the model provider.\r\n if (matchesDeniedPath(path, p.deniedPaths)) {\r\n out.skipped.push({ path, reason: \"import: denied\" });\r\n continue;\r\n }\r\n let content: string;\r\n try {\r\n content = p.readFile(path);\r\n } catch {\r\n out.skipped.push({ path, reason: \"import: unreadable\" });\r\n continue;\r\n }\r\n if (content.length > p.maxFileChars) {\r\n out.skipped.push({ path, reason: \"import: too large\" });\r\n } else if (total + content.length > p.maxTotalChars) {\r\n out.skipped.push({ path, reason: \"import: over budget\" });\r\n } else {\r\n total += content.length;\r\n out.entries.push({ path, content });\r\n out.importedPaths.push(path);\r\n }\r\n }\r\n return out;\r\n}\r\n", "/**\r\n * QUIKTR-1069 \u2014 a gateway timeout in front of the AI Runtime is not a refusal: the demo rehearsal\r\n * hit a 504 from a devtunnel/load balancer, not the runtime, and the same call succeeded on retry.\r\n * Retries ONLY transport-level signals \u2014 HTTP 502/503/504, or a thrown network error\r\n * (ECONNRESET/ETIMEDOUT) \u2014 twice, with a short fixed backoff. Every other failure (a real refusal,\r\n * CODEGEN_FILE_TOO_LARGE, success:false+errorCode, any 4xx) arrives as a normal HTTP 200 with the\r\n * refusal inside the envelope body, or a genuine non-transient 4xx \u2014 neither ever matches this\r\n * function's retry condition, so nothing here needs to special-case them.\r\n *\r\n * Spend: a retried call the runtime actually completed has been paid for twice. maxRunUsd already\r\n * caps the run (enforced at the gateway, per packet.ts's own comment), so this fails safe \u2014 the\r\n * worst case is hitting the budget wall slightly sooner, never an uncapped spend.\r\n */\r\nconst RETRYABLE_STATUS_CODES = new Set([502, 503, 504]);\r\nconst RETRYABLE_NETWORK_ERROR_CODES = new Set([\"ECONNRESET\", \"ETIMEDOUT\"]);\r\n\r\nfunction isRetryableNetworkError(err: unknown): boolean {\r\n const code =\r\n (err as { cause?: { code?: string } } | undefined)?.cause?.code ??\r\n (err as { code?: string } | undefined)?.code;\r\n return typeof code === \"string\" && RETRYABLE_NETWORK_ERROR_CODES.has(code);\r\n}\r\n\r\nexport async function fetchWithRetry(\r\n url: string,\r\n init: RequestInit,\r\n { retries = 2, backoffMs = 250 }: { retries?: number; backoffMs?: number } = {},\r\n): Promise<Response> {\r\n for (let attempt = 0; ; attempt++) {\r\n try {\r\n const res = await fetch(url, init);\r\n if (RETRYABLE_STATUS_CODES.has(res.status) && attempt < retries) {\r\n await new Promise((r) => setTimeout(r, backoffMs));\r\n continue;\r\n }\r\n return res;\r\n } catch (err) {\r\n if (isRetryableNetworkError(err) && attempt < retries) {\r\n await new Promise((r) => setTimeout(r, backoffMs));\r\n continue;\r\n }\r\n throw err;\r\n }\r\n }\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport { resolve, join } from \"node:path\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\n\r\n/**\r\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\r\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\r\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\r\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\r\n *\r\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\r\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\r\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\r\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\r\n *\r\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\r\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\r\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\r\n */\r\nexport interface DependencyViolation {\r\n file: string;\r\n packages: string[];\r\n}\r\n\r\nexport interface DependencyCheck {\r\n blocked: boolean;\r\n violations: DependencyViolation[];\r\n}\r\n\r\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\r\n\r\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\r\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\r\n\r\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\r\nconst NODE_BUILTINS = new Set([\r\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\r\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\r\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\r\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\r\n]);\r\n\r\n// QUIKTR-1063 \u2014 the two path-alias conventions common enough to assume even\r\n// when a repo's tsconfig can't be read or parsed: \"@/...\" (QuikTrack,\r\n// QuikChat, and most of this monorepo's own apps) and \"~/...\". Without this,\r\n// \"@/lib/x\" was parsed as the scoped package \"@/lib\" \u2014 a real package.json\r\n// entry it could never actually match \u2014 and every aliased import in a repo\r\n// using either convention was reported as an invented dependency.\r\n//\r\n// QUIKTR-1068 \u2014 this is now a FLOOR, not the whole answer: `resolveAliasPrefixes`\r\n// below adds whatever a real tsconfig.json/jsconfig.json actually declares in\r\n// `compilerOptions.paths`, for repos using some other convention entirely.\r\n// Always unioned in regardless of what a config says, so a repo with no\r\n// config (or an unparseable one) keeps exactly today's behavior.\r\nconst DEFAULT_ALIAS_PREFIXES = [\"@/\", \"~/\"];\r\n\r\nfunction packageNameFromSpecifier(specifier: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string | null {\r\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\r\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\r\n if (aliasPrefixes.some((prefix) => specifier.startsWith(prefix))) return null; // path alias\r\n const segments = specifier.split(\"/\");\r\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\r\n if (NODE_BUILTINS.has(name)) return null;\r\n return name;\r\n}\r\n\r\nfunction scanImports(source: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string[] {\r\n const found = new Set<string>();\r\n let match: RegExpExecArray | null;\r\n IMPORT_RE.lastIndex = 0;\r\n while ((match = IMPORT_RE.exec(source))) {\r\n const name = packageNameFromSpecifier(match[2], aliasPrefixes);\r\n if (name) found.add(name);\r\n }\r\n return [...found];\r\n}\r\n\r\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\r\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\r\n * blocking on a question it can't actually answer. `aliasPrefixes` defaults to the floor above;\r\n * callers with a real tsconfig read (see `resolveAliasPrefixes`) pass the fuller list. */\r\nexport function checkImportDependencies(\r\n results: CodegenFileResult[],\r\n declaredDependencies: Set<string> | null,\r\n aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES,\r\n): DependencyCheck {\r\n if (!declaredDependencies) return { blocked: false, violations: [] };\r\n\r\n const violations: DependencyViolation[] = [];\r\n for (const { targetPath, newContent } of results) {\r\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\r\n const invented = scanImports(newContent, aliasPrefixes).filter((pkg) => !declaredDependencies.has(pkg));\r\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\r\n }\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\ninterface PackageJson {\r\n dependencies?: Record<string, string>;\r\n devDependencies?: Record<string, string>;\r\n peerDependencies?: Record<string, string>;\r\n}\r\n\r\nfunction dependencyNames(pkg: PackageJson): Set<string> {\r\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\r\n return new Set([\r\n ...Object.keys(pkg.dependencies ?? {}),\r\n ...Object.keys(pkg.devDependencies ?? {}),\r\n ...Object.keys(pkg.peerDependencies ?? {}),\r\n ]);\r\n}\r\n\r\n/**\r\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\r\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\r\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\r\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\r\n */\r\nexport function readDeclaredDependencies(\r\n results: CodegenFileResult[],\r\n workspaceRoot: string | null,\r\n): Set<string> | null {\r\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\r\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\r\n\r\n let raw: string | null;\r\n if (generated) {\r\n raw = generated.newContent;\r\n } else {\r\n try {\r\n raw = readFileSync(packageJsonPath, \"utf8\");\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n if (raw === null) return null;\r\n\r\n try {\r\n return dependencyNames(JSON.parse(raw) as PackageJson);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * QUIKTR-1068 \u2014 strips line and block comments plus trailing commas from a JSON(C) string, best\r\n * effort. Not a real JSONC parser: a character scanner rather than a regex replace (a regex would\r\n * corrupt a string VALUE containing `//`, e.g. a URL), but anything it can't cleanly handle just\r\n * fails `JSON.parse` afterward \u2014 `resolveAliasPrefixes` below treats that the same as no config at\r\n * all and falls back to the floor. Never throws itself.\r\n */\r\nfunction stripJsonComments(text: string): string {\r\n let out = \"\";\r\n let inString = false;\r\n let inLineComment = false;\r\n let inBlockComment = false;\r\n for (let i = 0; i < text.length; i++) {\r\n const c = text[i];\r\n const next = text[i + 1];\r\n if (inLineComment) {\r\n if (c === \"\\n\") {\r\n inLineComment = false;\r\n out += c;\r\n }\r\n continue;\r\n }\r\n if (inBlockComment) {\r\n if (c === \"*\" && next === \"/\") {\r\n inBlockComment = false;\r\n i++;\r\n }\r\n continue;\r\n }\r\n if (inString) {\r\n out += c;\r\n if (c === \"\\\\\") {\r\n out += next;\r\n i++;\r\n continue;\r\n }\r\n if (c === '\"') inString = false;\r\n continue;\r\n }\r\n if (c === '\"') {\r\n inString = true;\r\n out += c;\r\n continue;\r\n }\r\n if (c === \"/\" && next === \"/\") {\r\n inLineComment = true;\r\n i++;\r\n continue;\r\n }\r\n if (c === \"/\" && next === \"*\") {\r\n inBlockComment = true;\r\n i++;\r\n continue;\r\n }\r\n out += c;\r\n }\r\n return out.replace(/,(\\s*[}\\]])/g, \"$1\");\r\n}\r\n\r\ninterface TsOrJsConfig {\r\n compilerOptions?: { paths?: Record<string, unknown> };\r\n}\r\n\r\n/**\r\n * QUIKTR-1068 \u2014 `DEFAULT_ALIAS_PREFIXES` is a floor, not the whole answer: a repo may declare its\r\n * own alias conventions in `compilerOptions.paths`. Tries `tsconfig.json` then `jsconfig.json` at\r\n * the workspace root (same results-first-then-disk precedence as `readDeclaredDependencies` \u2014 a\r\n * generated config this run legitimately wrote should win over a stale on-disk one), unions any\r\n * `paths` keys (wildcard stripped: `\"@/*\"` \u2192 `\"@/\"`) with the floor, and dedupes. Never throws and\r\n * never returns fewer than the floor \u2014 an unreadable or malformed config is exactly the same as no\r\n * config, not a reason to block a run that could otherwise pass.\r\n *\r\n * Does NOT follow `extends` \u2014 only the root config's own `paths`, same \"minimal, not exhaustive\"\r\n * boundary this file already draws elsewhere (see the module docblock).\r\n */\r\nexport function resolveAliasPrefixes(\r\n results: CodegenFileResult[],\r\n workspaceRoot: string | null,\r\n): string[] {\r\n const root = resolve(workspaceRoot ?? \".\");\r\n\r\n for (const filename of [\"tsconfig.json\", \"jsconfig.json\"]) {\r\n const configPath = join(root, filename);\r\n const generated = results.find((r) => resolve(r.targetPath) === configPath);\r\n\r\n let raw: string | null;\r\n if (generated) {\r\n raw = generated.newContent;\r\n } else {\r\n try {\r\n raw = readFileSync(configPath, \"utf8\");\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n if (raw === null) continue;\r\n\r\n try {\r\n const parsed = JSON.parse(stripJsonComments(raw)) as TsOrJsConfig;\r\n const paths = parsed.compilerOptions?.paths;\r\n const fromConfig =\r\n paths && typeof paths === \"object\"\r\n ? Object.keys(paths).map((k) => (k.endsWith(\"*\") ? k.slice(0, -1) : k))\r\n : [];\r\n return [...new Set([...DEFAULT_ALIAS_PREFIXES, ...fromConfig])];\r\n } catch {\r\n continue; // malformed \u2014 try the next config file, or fall through to the floor\r\n }\r\n }\r\n\r\n return DEFAULT_ALIAS_PREFIXES;\r\n}\r\n\r\n/** Regressions and new failures named separately elsewhere in this package for the same reason\r\n * this exists at all: conflating diagnoses wastes someone's morning. */\r\nexport function describeDependencyViolations(check: DependencyCheck): string {\r\n return check.violations\r\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\r\n .join(\"; \");\r\n}\r\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\r\n\r\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\r\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\r\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\r\nexport function checkGuardrail(deniedPaths: string[]): void {\r\n addAll();\r\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\r\n if (violations.length > 0) {\r\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\r\n }\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\ninterface InstallationTokenResponse {\r\n success: boolean;\r\n data: { token: string; expiresAt: string };\r\n}\r\n\r\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\r\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\r\n * envelope, same error-message style. */\r\nexport async function exchangeForInstallationToken(\r\n installationTokenUrl: string,\r\n runToken: string,\r\n): Promise<string> {\r\n const res = await fetch(installationTokenUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Exchange installation token failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as InstallationTokenResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\r\n }\r\n return body.data.token;\r\n}\r\n", "import { required } from \"./env\";\r\n\r\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\r\n * verifies the token this package requests. Duplicated because this package is published outside\r\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\r\n * duplicating `PilotPacket`'s shape. */\r\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\r\n\r\ninterface OidcTokenResponse {\r\n value: string;\r\n}\r\n\r\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\r\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\r\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\r\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\r\nexport async function fetchGithubOidcToken(\r\n env: NodeJS.ProcessEnv = process.env,\r\n): Promise<string> {\r\n const requestUrl = required(\r\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\r\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\r\n );\r\n const requestToken = required(\r\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\r\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\r\n );\r\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\r\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${requestToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\r\n }\r\n const body = (await res.json()) as OidcTokenResponse;\r\n if (!body.value) {\r\n throw new Error(\"GitHub OIDC token response carried no value\");\r\n }\r\n return body.value;\r\n}\r\n", "import type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1064 \u2014 QUIKSP-3's first live run implemented \"reject negative amounts\" twice: once in\r\n * src/server.js against raw input, once in src/validation.js against parsed minor units. Targeting\r\n * split the work across two files and gave each its own planStepsImplemented describing the same\r\n * rule; codegen faithfully built both. Per-target steps are meant to be DISJOINT (QUIKTR-1035) \u2014\r\n * nothing checked that they are.\r\n *\r\n * The real fix is `pilot.targeting`'s prompt \u2014 an AI Runtime change, not this package's. This is\r\n * the cheap half the ticket assigns here: a non-blocking warning, not semantic analysis. A\r\n * significant-word overlap between two steps in DIFFERENT targets is treated as the same rule\r\n * described twice. Same-target steps are never compared \u2014 one file legitimately implementing\r\n * several related steps is normal and not what this looks for.\r\n */\r\nexport interface OverlapWarning {\r\n targetA: string;\r\n stepA: string;\r\n targetB: string;\r\n stepB: string;\r\n /** QUIKTR-1081 \u2014 \"identical\" (the exact same instruction, modulo case/whitespace) is blocking;\r\n * \"similar\" (the existing Jaccard-threshold match, reworded but not the same text) stays a\r\n * warning. Two legitimate halves of one change never share the literal same instruction. */\r\n severity: \"identical\" | \"similar\";\r\n}\r\n\r\n// QUIKTR-1081 \u2014 a path-convention heuristic, not a real \"is this a test\" signal: nothing in this\r\n// package (or apps/quiktrack/lib/services/pilot) tags a PilotTarget as covering a test today. A\r\n// behaviour appearing in both a file and its test is correct, so a pair is exempt from this check\r\n// entirely \u2014 not merely from blocking \u2014 whenever either side looks like a test file.\r\nconst TEST_PATH_RE = /(\\.(test|spec)\\.[jt]sx?$)|(^|\\/)(__tests__|tests?)\\//i;\r\n\r\nexport function isTestTarget(path: string): boolean {\r\n return TEST_PATH_RE.test(path);\r\n}\r\n\r\nconst STOPWORDS = new Set([\r\n \"a\", \"an\", \"the\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\r\n \"of\", \"to\", \"in\", \"on\", \"for\", \"with\", \"at\", \"by\", \"from\", \"as\",\r\n \"and\", \"or\", \"not\", \"no\", \"nor\",\r\n \"this\", \"that\", \"these\", \"those\", \"it\", \"its\",\r\n \"cannot\", \"can't\", \"should\", \"must\", \"may\", \"will\", \"shall\",\r\n \"when\", \"if\", \"than\", \"then\", \"so\", \"do\", \"does\", \"did\",\r\n]);\r\n\r\n// Ignore words this short too \u2014 they add noise to the overlap without carrying meaning (\"id\",\r\n// \"an\", two-letter fragments from punctuation stripping).\r\nconst MIN_WORD_LENGTH = 3;\r\n\r\nfunction significantWords(step: string): Set<string> {\r\n return new Set(\r\n step\r\n .toLowerCase()\r\n .replace(/[^a-z0-9\\s]/g, \" \")\r\n .split(/\\s+/)\r\n .filter((w) => w.length >= MIN_WORD_LENGTH && !STOPWORDS.has(w)),\r\n );\r\n}\r\n\r\nfunction jaccard(a: Set<string>, b: Set<string>): number {\r\n if (a.size === 0 || b.size === 0) return 0;\r\n let intersection = 0;\r\n for (const w of a) if (b.has(w)) intersection++;\r\n const union = a.size + b.size - intersection;\r\n return intersection / union;\r\n}\r\n\r\n// QUIKTR-1081 \u2014 stricter than significantWords' normalization (which drops stopwords/short words\r\n// entirely): this only ignores case and incidental whitespace, so \"identical\" means the actual\r\n// same instruction, not merely \"shares enough meaningful words.\"\r\nfunction normalizedStep(step: string): string {\r\n return step.trim().toLowerCase().replace(/\\s+/g, \" \");\r\n}\r\n\r\n// Cheap and deliberately generous \u2014 a false positive here costs a reviewer one glance at a warning\r\n// line; a false negative is exactly the bug this exists to catch.\r\nconst OVERLAP_THRESHOLD = 0.5;\r\n\r\n/** Every cross-target pair of plan steps whose significant words overlap enough to plausibly be the\r\n * same rule described twice. Steps within the same target are never compared. */\r\nexport function findOverlappingSteps(targets: PilotTarget[]): OverlapWarning[] {\r\n const items = targets.flatMap((target) =>\r\n target.planStepsImplemented.map((step) => ({\r\n target: target.path,\r\n step,\r\n words: significantWords(step),\r\n })),\r\n );\r\n\r\n const warnings: OverlapWarning[] = [];\r\n for (let i = 0; i < items.length; i++) {\r\n for (let j = i + 1; j < items.length; j++) {\r\n if (items[i].target === items[j].target) continue;\r\n if (isTestTarget(items[i].target) || isTestTarget(items[j].target)) continue;\r\n if (jaccard(items[i].words, items[j].words) >= OVERLAP_THRESHOLD) {\r\n warnings.push({\r\n targetA: items[i].target,\r\n stepA: items[i].step,\r\n targetB: items[j].target,\r\n stepB: items[j].step,\r\n severity: normalizedStep(items[i].step) === normalizedStep(items[j].step) ? \"identical\" : \"similar\",\r\n });\r\n }\r\n }\r\n }\r\n return warnings;\r\n}\r\n\r\nexport function describeOverlapWarnings(warnings: OverlapWarning[]): string[] {\r\n return warnings.map(\r\n (w) =>\r\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.`,\r\n );\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\n/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\r\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\r\nexport interface PilotPacket {\r\n runId: string;\r\n issueKey: string | null;\r\n /** QUIKTR-1067 \u2014 same nullability as issueKey, for the same reason: the commit message needs\r\n * both to say what actually changed instead of the hardcoded \"Phase 0 skeleton\" placeholder. */\r\n issueTitle: string | null;\r\n branch: string | null;\r\n targetBranch: string | null;\r\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\r\n * repository root, as null \u2014 never normalised to \".\". */\r\n workspaceRoot: string | null;\r\n commands: {\r\n setup: string | null;\r\n test: string | null;\r\n e2e: string | null;\r\n lint: string | null;\r\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\r\n format: string | null;\r\n /** QUIKTR-1402 \u2014 runs ONE test file (path appended, or substituted for `{file}`) against the untouched\r\n * code, for the baseline check. Optional: an older QuikTrack omits it. Null/absent turns the check off. */\r\n testFile?: string | null;\r\n };\r\n guardrails: {\r\n deniedPaths: string[];\r\n maxHealIterations: number;\r\n maxWallClockMinutes: number;\r\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\r\n };\r\n /** Where to call for AI codegen, and the credential that authorizes it. */\r\n gateway: {\r\n baseUrl: string;\r\n token: string;\r\n };\r\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\r\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\r\n design: {\r\n rootCause: string;\r\n approach: string;\r\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\r\n apiChanges: { surface: string; change: string; reason: string }[];\r\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\r\n riskRationale: string;\r\n } | null;\r\n quikTest: { testRunId: string; resultsUrl: string } | null;\r\n /** QUIKTR-1065 \u2014 the approved test cases codegen still owes real test code for. Sent to\r\n * pilot.targeting so it can propose a test-file target naming which cases it covers; today\r\n * nothing reads this field yet (the AI Runtime side isn't built), so it always arrives as `[]`\r\n * or is silently unused once wired up here. */\r\n requiredTests: {\r\n automationId: string;\r\n title: string;\r\n covers: string[];\r\n given: string | null;\r\n when: string | null;\r\n then: string | null;\r\n }[];\r\n /** QUIKTR-1402 \u2014 automationId -> the case's current type (FUNCTIONAL, NEGATIVE, REGRESSION, \u2026), only for\r\n * cases whose AI-assigned label QuikTrack recorded. Optional: an older QuikTrack omits it. A case that is\r\n * absent here is UNKNOWN and is never checked; REGRESSION is exempt. DELIBERATELY not a field of\r\n * `requiredTests`: those objects are forwarded to the AI Runtime as-is, and an unknown key on the\r\n * versioned path is refused CONTRACT_REJECTED. Nothing in this map may ever be sent to the runtime. */\r\n requiredTestTypes?: Record<string, string>;\r\n /** QUIKTR-1401 \u2014 the reviewer's approved \"things QuikPilot must not change\" list. Optional: a\r\n * QuikTrack that predates the field omits it. Forwarded to pilot.targeting and pilot.codegen (\u00A720,\r\n * deployed by the AI Runtime 2026-10-01) when non-empty, never to pilot.design. Free text, so unlike\r\n * `deniedPaths` it can only be told to the model, not checked. */\r\n outOfScope?: string[];\r\n /** QUIKTR-1315, \u00A719 of the AI Runtime contract (AGREED, final tagged shape) \u2014 the repo-relative\r\n * files the last DONE run's own ingested JUnit report named, sourced from stored QuikTest data,\r\n * not a live baseline capture here. Always present (never undefined) \u2014 \u00A719.12: a project with no\r\n * prior DONE run's report is `{ report: \"ABSENT\" }`, not an omitted field. `{ report: \"PRESENT\" }`\r\n * with an empty `discoveredTestFiles` is a different, real fact: a report was ingested but\r\n * nothing in it was path-shaped. See targeting.ts for how this is forwarded. */\r\n testDiscovery:\r\n | { report: \"PRESENT\"; discoveredTestFiles: string[]; unmappedEntries: number }\r\n | { report: \"ABSENT\" };\r\n}\r\n\r\ninterface PacketResponse {\r\n success: boolean;\r\n data: PilotPacket;\r\n}\r\n\r\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\r\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\r\n * invisible to `ps`, so no equivalent trick is needed here. */\r\nexport async function fetchPacket(\r\n packetUrl: string,\r\n runToken: string,\r\n githubRunId: string,\r\n): Promise<PilotPacket> {\r\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${runToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Fetch work packet failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as PacketResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\r\n }\r\n return body.data;\r\n}\r\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\r\n\r\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\r\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\r\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\r\nexport function writePhase0Marker(runId: string): void {\r\n mkdirSync(\".quikpilot\", { recursive: true });\r\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\r\n}\r\n", "import { readFileSync, readdirSync, rmSync, statSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\r\n\r\nfunction walkForJUnitByName(dir: string): string | null {\r\n let entries: string[];\r\n try {\r\n entries = readdirSync(dir);\r\n } catch {\r\n return null;\r\n }\r\n for (const entry of entries) {\r\n if (SKIP_DIRS.has(entry)) continue;\r\n const full = join(dir, entry);\r\n let stat;\r\n try {\r\n stat = statSync(full);\r\n } catch {\r\n continue;\r\n }\r\n if (stat.isDirectory()) {\r\n const found = walkForJUnitByName(full);\r\n if (found) return found;\r\n } else if (/^junit.*\\.xml$/.test(entry)) {\r\n return full;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\r\n let entries: string[];\r\n try {\r\n entries = readdirSync(dir);\r\n } catch {\r\n return null;\r\n }\r\n const match = entries.find((e) => namePattern.test(e));\r\n return match ? join(dir, match) : null;\r\n}\r\n\r\n/** The test report as bytes, or null when there is none or it cannot be read. QUIKTR-1447 takes a copy for a failed\r\n * run BEFORE `reportToQuikTest` sends and deletes it. */\r\nexport function readTestReportBytes(cwd = process.cwd()): Buffer | null {\r\n try {\r\n const report = findJUnitReport(cwd);\r\n return report ? readFileSync(report) : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\r\n * common locations rather than a configurable setting. A project that writes its report elsewhere\r\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\r\n * in the same priority the original `find` clause listed them, though exact traversal order was\r\n * never guaranteed there either. */\r\nexport function findJUnitReport(cwd = process.cwd()): string | null {\r\n return (\r\n walkForJUnitByName(cwd) ??\r\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\r\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\r\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\r\n );\r\n}\r\n\r\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\r\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\r\n}\r\n\r\n/** The ingest route's summary of automationIds present in the JUnit report that matched no\r\n * `QtTestCase` \u2014 computed and returned by QuikTrack's own ingest today (`IngestSummary.unmatched`\r\n * in `apps/quiktrack/lib/services/testIngest.ts`), but silently discarded here until QUIKTR-1374:\r\n * a bracket/format mismatch (or any other ingest failure) produced zero matches on every run with\r\n * nothing on screen to say why. */\r\nexport interface ReportToQuikTestResult {\r\n unmatched: Array<{ automationId: string; count: number }>;\r\n}\r\n\r\n/** One warning naming every unmatched id and its count \u2014 `null` when there's nothing to report,\r\n * so the caller can push straight into `warnings` without an extra length check. */\r\nexport function describeUnmatchedAutomationIds(unmatched: ReportToQuikTestResult[\"unmatched\"]): string | null {\r\n if (unmatched.length === 0) return null;\r\n const named = unmatched.map((u) => `${u.automationId} (\u00D7${u.count})`).join(\", \");\r\n return `${unmatched.length} generated test result(s) did not match any test case: ${named} \u2014 check the automationId format.`;\r\n}\r\n\r\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\r\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\r\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\r\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. Returns\r\n * `null` whenever nothing was actually reported (no results URL, no report found, or the POST\r\n * itself failed) \u2014 the caller folds a non-null `unmatched` array into the run's warnings. */\r\nexport async function reportToQuikTest(params: {\r\n resultsUrl: string | null | undefined;\r\n runToken: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n githubRunId: string;\r\n /** QUIKTR-1333 \u2014 the files QuikPilot actually generated or edited this run. Scopes QuikTrack's\r\n * unmatched-automationId warning to just these, so a repository's own pre-existing tests (which\r\n * can never carry a QuikPilot id) stop being reported as unmatched on every single run.\r\n * `undefined` = no scoping information (the server keeps its unfiltered behavior). An EMPTY\r\n * array is a real answer \u2014 codegen produced nothing (it failed, or there was no target) \u2014 and is\r\n * sent as an empty parameter so the server scopes to nothing instead of falling back. */\r\n generatedFiles?: string[];\r\n cwd?: string;\r\n}): Promise<ReportToQuikTestResult | null> {\r\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, generatedFiles, cwd } = params;\r\n if (!resultsUrl) {\r\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\r\n return null;\r\n }\r\n const report = findJUnitReport(cwd);\r\n if (!report) {\r\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\r\n return null;\r\n }\r\n try {\r\n console.log(`reporting ${report}`);\r\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\r\n const { readFileSync } = await import(\"node:fs\");\r\n const body = readFileSync(report);\r\n // QUIKTR-1082 \u2014 this runner is the only caller QuikPilot controls; requesting \"bracket\"\r\n // explicitly here changes nothing for any other QuikTest customer's own ingestion.\r\n let url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}&automationIdFormat=bracket`;\r\n // QUIKTR-1333 \u2014 optional: an old runner or a human's manual upload (the sibling route) never\r\n // sends this, and the server falls back to today's unfiltered behavior either way. Sent even\r\n // when empty: \"generated nothing\" must not be mistaken for \"no information\".\r\n if (generatedFiles) {\r\n url += `&generatedFiles=${encodeURIComponent(generatedFiles.join(\",\"))}`;\r\n }\r\n const res = await fetch(url, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\r\n body,\r\n });\r\n if (!res.ok) {\r\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\r\n }\r\n rmSync(report, { force: true });\r\n // QUIKTR-1374 \u2014 read the ingest summary instead of discarding it. Best-effort: the POST\r\n // itself already succeeded (res.ok), so a body that isn't the expected JSON shape must never\r\n // turn a working report into a failure \u2014 it just means no warning can be derived from it.\r\n let unmatched: ReportToQuikTestResult[\"unmatched\"] = [];\r\n try {\r\n const json = (await res.json()) as { data?: { unmatched?: ReportToQuikTestResult[\"unmatched\"] } };\r\n unmatched = json.data?.unmatched ?? [];\r\n } catch {\r\n // Not JSON, or not the expected shape \u2014 leave unmatched empty.\r\n }\r\n return { unmatched };\r\n } catch (err) {\r\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n}\r\n", "import { execFileSync } from \"node:child_process\";\r\nimport { existsSync, mkdirSync, readFileSync, rmSync, rmdirSync, statSync, writeFileSync } from \"node:fs\";\r\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\nimport { runCommandWithTimeout, type TimedRunOutcome } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\nimport { readAutomationIdResults } from \"./regressionCheck\";\r\nimport type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1402 \u2014 the baseline check.\r\n *\r\n * A spec can contain a case that asserts something ALREADY TRUE before any change (\"the server route\r\n * remains unchanged\"); no test can satisfy it, and a phrase list cannot catch the next phrasing. What every\r\n * such case shares is not wording but behaviour: its generated test PASSES on the unmodified code. So,\r\n * after codegen and before anything is written for real, this writes ONLY the generated test files, runs\r\n * each one alone against the untouched code, flags a non-Regression case whose test passed, and puts\r\n * everything back. A Regression case is meant to pass there, so it is exempt.\r\n *\r\n * It FLAGS and never blocks: a no-op change is legitimate, and an unsatisfiable case is a spec problem a\r\n * person should see rather than a run that dies. Every uncertain outcome therefore means \"no flag\", and\r\n * every one of them is said out loud (a silent timeout would look exactly like a check that found nothing).\r\n *\r\n * Unknown is never flagged: only a case whose label QuikTrack recorded (`requiredTestTypes`) is checked,\r\n * so anything approved before the label was kept, and any label we did not recognise, is left alone.\r\n */\r\n\r\n/**\r\n * How long one single-file run may take before it is stopped. A constant, not a setting (Suyash): one more\r\n * knob is one more thing to get wrong, and nobody has the information to tune it. Measured on QuikTrack and\r\n * QuikChat, one file takes 2 to 5 seconds warm and up to ~14 seconds on a cold start; two minutes is far\r\n * outside that and only ever reached by a command that hangs, which produces no error and would otherwise\r\n * hold the run until the job's own limit while looking like QuikPilot being slow.\r\n */\r\nexport const BASELINE_CHECK_TIMEOUT_MS = 120_000;\r\n\r\nexport interface BaselineFindings {\r\n /** ALREADY_TRUE: the change altered the code but the case still passed before it. NO_OP: every file the\r\n * change edited came out unchanged. The check cannot tell the two apart for certain; the wording hedges. */\r\n cause: \"ALREADY_TRUE\" | \"NO_OP\";\r\n /** Case ids only \u2014 QuikTrack looks the titles up itself, so case text never travels. */\r\n automationIds: string[];\r\n}\r\n\r\nexport interface BaselineCheckResult {\r\n findings: BaselineFindings | null;\r\n /** Run-record sentences: a finding, or a reason the check could not give an answer. */\r\n warnings: string[];\r\n}\r\n\r\nexport interface BaselineCheckParams {\r\n targets: PilotTarget[];\r\n results: CodegenFileResult[];\r\n testFileCmd: string | null | undefined;\r\n /** automationId -> the case's current type, only for cases whose label is known. */\r\n requiredTestTypes: Record<string, string> | undefined;\r\n cwd?: string;\r\n /** Test seam: the real one spawns bash with a hard time limit. */\r\n runFile?: (command: string, timeoutMs: number) => Promise<TimedRunOutcome>;\r\n}\r\n\r\n/** POSIX single-quoting: the path is chosen by the model, so it must never be able to inject a command. */\r\nexport function shellQuote(value: string): string {\r\n return `'${value.split(\"'\").join(\"'\\\\''\")}'`;\r\n}\r\n\r\n/** `{file}` is replaced wherever it appears; with no placeholder the path is appended as the last argument. */\r\nexport function buildSingleFileCommand(command: string, path: string): string {\r\n const quoted = shellQuote(path);\r\n return command.includes(\"{file}\") ? command.split(\"{file}\").join(quoted) : `${command} ${quoted}`;\r\n}\r\n\r\nconst isTestTarget = (t: PilotTarget): boolean => (t.automationIds?.length ?? 0) > 0;\r\n\r\n/** A case is checked only if its label is KNOWN and is not Regression (which is supposed to pass). */\r\nfunction checkableIds(ids: string[], types: Record<string, string> | undefined): string[] {\r\n if (!types) return [];\r\n return ids.filter((id) => {\r\n if (!Object.prototype.hasOwnProperty.call(types, id)) return false;\r\n const type = types[id];\r\n return typeof type === \"string\" && type.trim() !== \"\" && type.trim().toUpperCase() !== \"REGRESSION\";\r\n });\r\n}\r\n\r\n/** Absolute path inside the checkout, or null when the target would land outside it. */\r\nfunction insideCheckout(cwd: string, path: string): string | null {\r\n const abs = resolve(cwd, path);\r\n const rel = relative(cwd, abs);\r\n return rel === \"\" || rel.startsWith(\"..\") || isAbsolute(rel) ? null : abs;\r\n}\r\n\r\ninterface WrittenFile {\r\n abs: string;\r\n /** null when the file did not exist before. */\r\n original: Buffer | null;\r\n /** Directories this check had to create, outermost first. */\r\n createdDirs: string[];\r\n}\r\n\r\nfunction writeForCheck(abs: string, content: string): WrittenFile {\r\n const original = existsSync(abs) ? readFileSync(abs) : null;\r\n const createdDirs: string[] = [];\r\n if (original === null) {\r\n const missing: string[] = [];\r\n for (let d = dirname(abs); !existsSync(d); d = dirname(d)) missing.push(d);\r\n for (const d of missing.reverse()) {\r\n mkdirSync(d);\r\n createdDirs.push(d);\r\n }\r\n }\r\n writeFileSync(abs, content);\r\n return { abs, original, createdDirs };\r\n}\r\n\r\nfunction restore(written: WrittenFile[]): void {\r\n for (const file of [...written].reverse()) {\r\n try {\r\n if (file.original !== null) writeFileSync(file.abs, file.original);\r\n else rmSync(file.abs, { force: true });\r\n for (const d of [...file.createdDirs].reverse()) {\r\n try {\r\n rmdirSync(d);\r\n } catch {\r\n // not empty or already gone \u2014 leave it\r\n }\r\n }\r\n } catch (err) {\r\n console.error(`Baseline check could not restore ${file.abs}: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n}\r\n\r\n/** Untracked, non-ignored files \u2014 exactly what the guardrail's `git add -A` would commit. `null` when git\r\n * cannot say, in which case nothing is cleaned up rather than guessing. */\r\nfunction untrackedFiles(cwd: string): Set<string> | null {\r\n try {\r\n const out = execFileSync(\"git\", [\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"], {\r\n cwd,\r\n encoding: \"utf8\",\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n maxBuffer: 64 * 1024 * 1024,\r\n });\r\n return new Set(out.split(\"\\0\").filter(Boolean));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nconst mtimeOf = (path: string): number | null => {\r\n try {\r\n return statSync(path).mtimeMs;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\n/** NO_OP only when there is code to compare and every file the change edits came out exactly as it was. */\r\nfunction decideCause(targets: PilotTarget[], results: Map<string, string>, cwd: string): BaselineFindings[\"cause\"] {\r\n const codeTargets = targets.filter((t) => !isTestTarget(t));\r\n if (codeTargets.length === 0) return \"ALREADY_TRUE\";\r\n for (const t of codeTargets) {\r\n if (t.kind === \"NEW_FILE\") return \"ALREADY_TRUE\";\r\n const next = results.get(t.path);\r\n const abs = insideCheckout(cwd, t.path);\r\n if (next === undefined || abs === null) return \"ALREADY_TRUE\";\r\n try {\r\n if (readFileSync(abs, \"utf8\") !== next) return \"ALREADY_TRUE\";\r\n } catch {\r\n return \"ALREADY_TRUE\";\r\n }\r\n }\r\n return \"NO_OP\";\r\n}\r\n\r\nexport async function runBaselineCheck(params: BaselineCheckParams): Promise<BaselineCheckResult> {\r\n const { targets, results, testFileCmd, requiredTestTypes } = params;\r\n const cwd = params.cwd ?? process.cwd();\r\n const runFile = params.runFile ?? runCommandWithTimeout;\r\n const nothing: BaselineCheckResult = { findings: null, warnings: [] };\r\n\r\n if (!testFileCmd || testFileCmd.trim() === \"\") return nothing;\r\n const testTargets = targets.filter(isTestTarget);\r\n const toCheck = testTargets\r\n .map((target) => ({ target, ids: checkableIds(target.automationIds ?? [], requiredTestTypes) }))\r\n .filter((entry) => entry.ids.length > 0);\r\n if (toCheck.length === 0) {\r\n console.log(\"Baseline check: no case with a known, non-Regression label \u2014 nothing to check.\");\r\n return nothing;\r\n }\r\n\r\n const warnings: string[] = [];\r\n const flagged: string[] = [];\r\n const written: WrittenFile[] = [];\r\n const unsafe = new Set<string>();\r\n const skip = (path: string, why: string) => {\r\n const message = `Baseline check skipped for ${path}: ${why}`;\r\n console.warn(`::warning::${message}`);\r\n warnings.push(message);\r\n };\r\n\r\n try {\r\n const contentByPath = new Map(results.map((r) => [r.targetPath, r.newContent]));\r\n const cause = decideCause(targets, contentByPath, cwd);\r\n\r\n // Only the generated TEST files are written; the code under test stays exactly as it is.\r\n for (const target of testTargets) {\r\n const content = contentByPath.get(target.path);\r\n if (content === undefined) continue;\r\n const abs = insideCheckout(cwd, target.path);\r\n if (abs === null) {\r\n unsafe.add(target.path);\r\n continue;\r\n }\r\n written.push(writeForCheck(abs, content));\r\n }\r\n\r\n for (const { target, ids } of toCheck) {\r\n if (unsafe.has(target.path)) {\r\n skip(target.path, \"the path is outside the checkout, so the file was not written or run.\");\r\n continue;\r\n }\r\n if (!contentByPath.has(target.path)) continue;\r\n\r\n const reportBefore = findJUnitReport(cwd);\r\n const mtimeBefore = reportBefore ? mtimeOf(reportBefore) : null;\r\n const untrackedBefore = untrackedFiles(cwd);\r\n\r\n const outcome = await runFile(buildSingleFileCommand(testFileCmd, target.path), BASELINE_CHECK_TIMEOUT_MS);\r\n\r\n if (outcome === \"timeout\") {\r\n skip(\r\n target.path,\r\n `the single-file command did not finish within ${BASELINE_CHECK_TIMEOUT_MS / 1000} seconds and was stopped. ` +\r\n \"No test case from this file was flagged.\",\r\n );\r\n } else if (outcome === \"error\") {\r\n skip(target.path, \"the single-file command could not be started. No test case from this file was flagged.\");\r\n } else {\r\n const reportAfter = findJUnitReport(cwd);\r\n const fresh = reportAfter !== null && (reportAfter !== reportBefore || mtimeOf(reportAfter) !== mtimeBefore);\r\n if (!fresh) {\r\n skip(\r\n target.path,\r\n \"the single-file command wrote no new JUnit report (it must write the same JUnit report as the test \" +\r\n \"command), so nothing could be checked.\",\r\n );\r\n } else {\r\n const byId = readAutomationIdResults(cwd);\r\n for (const id of ids) if (byId?.get(id) === \"pass\") flagged.push(id);\r\n }\r\n }\r\n\r\n // The report has been read; now remove whatever this run left behind that the guardrail would commit\r\n // (a snapshot file written against the OLD behaviour would make the real run fail). Never anything\r\n // that existed before this run.\r\n const untrackedAfter = untrackedFiles(cwd);\r\n if (untrackedBefore && untrackedAfter) {\r\n for (const file of untrackedAfter) {\r\n if (untrackedBefore.has(file)) continue;\r\n const abs = insideCheckout(cwd, file);\r\n if (abs) rmSync(abs, { force: true });\r\n }\r\n }\r\n }\r\n\r\n if (flagged.length === 0) return { findings: null, warnings };\r\n\r\n const automationIds = [...new Set(flagged)].slice(0, 200);\r\n const list = automationIds.join(\", \");\r\n warnings.push(\r\n cause === \"NO_OP\"\r\n ? `Baseline check: ${automationIds.length} test case(s) passed against the unmodified code, and every file the ` +\r\n `generated change edited came out unchanged, so the change itself may have been a no-op: ${list}.`\r\n : `Baseline check: ${automationIds.length} test case(s) passed against the unmodified code, so they may assert ` +\r\n `something already true: ${list}. This check cannot tell that from a change that did nothing.`,\r\n );\r\n return { findings: { cause, automationIds }, warnings };\r\n } catch (err) {\r\n const message = `Baseline check could not run: ${err instanceof Error ? err.message : String(err)}`;\r\n console.warn(`::warning::${message}`);\r\n return { findings: null, warnings: [...warnings, message] };\r\n } finally {\r\n restore(written);\r\n }\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\n\r\n/**\r\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\r\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\r\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\r\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\r\n * passed before, fails now -> regression, block\r\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\r\n * common case, not an edge case \u2014 a different diagnosis from a\r\n * regression, so it's reported separately)\r\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\r\n *\r\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\r\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\r\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\r\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\r\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\r\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\r\n * automationIdFormat.\r\n */\r\nexport interface TestSnapshot {\r\n outcome: TestOutcome;\r\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\r\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\r\n * with no way to name what broke would contradict the whole point of the classification. */\r\n results: Map<string, boolean> | null;\r\n /**\r\n * QUIKTR-1029 self-heal prerequisite 1 (Suyash, 2026-09-22 \u2014 \"buildable now and useful on its\r\n * own: today a regression blocks the push without saying why the test failed\"). testId -> a\r\n * bounded failure message, only for tests that failed IN THIS SNAPSHOT. Deliberately a second,\r\n * optional map rather than widening `results`'s value type: `checkForRegressions`'s diffing\r\n * logic (and every existing test constructing a `TestSnapshot` fixture directly) stays untouched\r\n * \u2014 this is additive context, not a new signal the diff itself reasons about.\r\n */\r\n failureText?: Map<string, string>;\r\n /**\r\n * QUIKTR-1315 \u2014 the file paths the test runner itself discovered, read from each `<testsuite>`'s\r\n * `file` attribute and each `<testcase>`'s `file`/`classname` attributes, verbatim (backslashes\r\n * normalised to forward slashes only). `null` when no report was found \u2014 same \"can't tell, don't\r\n * block\" posture as `results`. An empty (non-null) set means a report existed but carried no\r\n * file-shaped attribution at all \u2014 also treated as \"can't tell\" by `testPlacementCheck.ts`, not as\r\n * \"nothing was discovered.\" Best-effort only: `classname` is a real file path for Vitest and\r\n * derivable for pytest, but not guaranteed for Jest (depends on `jest-junit` config) or Go\r\n * (typically package-, not file-, scoped) \u2014 see `testPlacementCheck.ts`'s own docblock for how\r\n * this is matched loosely rather than exactly for that reason.\r\n */\r\n discoveredFiles?: Set<string> | null;\r\n /**\r\n * QUIKTR-1315 \u2014 every `[<automationId>]` leading-bracket token found in a `<testcase>` name,\r\n * duplicating `apps/quiktrack/lib/test/resultParser.ts`'s `LEADING_BRACKET_RE` convention (this\r\n * package can't import that file \u2014 published outside the monorepo). `null` when no report was\r\n * found, same as `discoveredFiles`.\r\n */\r\n discoveredAutomationIds?: Set<string> | null;\r\n}\r\n\r\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\r\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\r\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\r\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\r\nconst SKIPPED_CHILD_RE = /<skipped\\b/;\r\n\r\n// QUIKTR-1315 \u2014 `<testsuite>` open tags only (not self-closed the way an empty `<testcase/>` can\r\n// be): a suite always wraps at least its own attributes even with zero testcases inside.\r\nconst TESTSUITE_OPEN_RE = /<testsuite\\b([^>]*?)>/g;\r\nconst FILE_ATTR_RE = /\\bfile=\"([^\"]*)\"/;\r\n// QUIKTR-1082/1374's convention, duplicated \u2014 see this file's module docblock and\r\n// `TestSnapshot`'s `discoveredAutomationIds` field for why this can't just import\r\n// resultParser.ts instead. Matches QuikPilot's own token shape (QP-<PROJECT-KEY>-<issue>-<n>)\r\n// anywhere in the name rather than requiring it at the start \u2014 a bare \"[Smoke]\"-style tag can\r\n// never satisfy this shape, so QUIKTR-1082's \"don't match an unrelated bracketed tag\" safety\r\n// property holds without depending on position, which Vitest's JUnit reporter doesn't preserve.\r\nconst QP_TOKEN_BRACKET_RE = /\\[(QP-[A-Z][A-Z0-9]*-\\d+-\\d+)\\]/;\r\n\r\nfunction normalizeSlashes(path: string): string {\r\n return path.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/** The `<failure>`/`<error>` child itself, within one `<testcase>`'s already-isolated body. */\r\nconst FAILURE_TAG_RE = /<(?:failure|error)\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/(?:failure|error)>)/;\r\nconst FAILURE_MESSAGE_ATTR_RE = /\\bmessage=\"([^\"]*)\"/;\r\n\r\n/** Console/PR-message budget, not a data-integrity bound \u2014 this is display text, never re-parsed. */\r\nconst MAX_FAILURE_TEXT = 500;\r\n\r\n/** The five entities the JUnit writers in real use (Vitest, Jest, pytest, go-junit-report) all\r\n * produce \u2014 not a general XML-unescape, same \"minimal scanner, not a parser\" posture as the rest\r\n * of this file. Literal `"`/`&` reaching a console log or a PR body reads as broken. */\r\nfunction unescapeXmlEntities(s: string): string {\r\n return s.replace(/</g, \"<\").replace(/>/g, \">\").replace(/"/g, '\"').replace(/'/g, \"'\").replace(/&/g, \"&\");\r\n}\r\n\r\n/** A file Vite cannot parse is reported with one generic message whatever the file or the syntax error;\r\n * only a `File: <path>:<line>[:<col>]` line in the body says which file and where (Vitest 4.1.11). */\r\nconst FAILURE_FILE_LINE_RE = /^[ \\t]*File:[ \\t]*(\\S[^\\r\\n]*?:\\d+(?::\\d+)?)[ \\t]*$/m;\r\nconst MAX_FAILURE_LOCATION = 300;\r\n\r\nfunction parseFailureLocation(body: string): string | null {\r\n const found = FAILURE_FILE_LINE_RE.exec(unescapeXmlEntities(body));\r\n if (!found) return null;\r\n const path = normalizeSlashes(found[1]);\r\n const root = `${normalizeSlashes(process.cwd()).replace(/\\/+$/, \"\")}/`;\r\n const shown = path.startsWith(root) ? path.slice(root.length) : path;\r\n return shown.length > MAX_FAILURE_LOCATION ? `${shown.slice(0, MAX_FAILURE_LOCATION)}\u2026` : shown;\r\n}\r\n\r\n/** `message=\"...\"` when present (short, what every framework puts the assertion diff in);\r\n * otherwise the tag's own body text (stack trace), truncated \u2014 never both, never neither if\r\n * either exists. `null` when the testcase body has no `<failure>`/`<error>` at all, or the tag\r\n * carries no text either way (both attrs and body empty \u2014 seen from at least one Go harness).\r\n *\r\n * Exception: when the message attribute is used and the body names a file and position (a file that\r\n * failed to parse), that location is appended, because the message alone cannot say which file. */\r\nfunction extractFailureText(testcaseBody: string): string | null {\r\n const tag = FAILURE_TAG_RE.exec(testcaseBody);\r\n if (!tag) return null;\r\n const [, attrs = \"\", inner = \"\"] = tag;\r\n const messageAttr = FAILURE_MESSAGE_ATTR_RE.exec(attrs)?.[1];\r\n const raw = (messageAttr ?? inner).trim();\r\n if (!raw) return null;\r\n const text = unescapeXmlEntities(raw);\r\n const shortened = text.length > MAX_FAILURE_TEXT ? `${text.slice(0, MAX_FAILURE_TEXT)}\u2026` : text;\r\n const location = messageAttr === undefined ? null : parseFailureLocation(inner);\r\n return location ? `${shortened} [at ${location}]` : shortened;\r\n}\r\n\r\n/** QUIKTR-1402 \u2014 one QuikPilot case's result in a report. `skipped` is its own answer, NOT a pass: a test\r\n * that did not run shows nothing about the case, and the baseline check must never read it as \"passed\". */\r\nexport type AutomationIdResult = \"pass\" | \"fail\" | \"skipped\";\r\n\r\n/** When several tests carry one case's id, the worst answer wins: fail > skipped > pass. */\r\nconst RESULT_RANK: Record<AutomationIdResult, number> = { pass: 0, skipped: 1, fail: 2 };\r\n\r\ninterface JUnitParseResult {\r\n outcomes: Map<string, boolean>;\r\n automationIdResults: Map<string, AutomationIdResult>;\r\n failureText: Map<string, string>;\r\n discoveredFiles: Set<string>;\r\n discoveredAutomationIds: Set<string>;\r\n}\r\n\r\nfunction parseJUnitOutcomes(xml: string): JUnitParseResult {\r\n const outcomes = new Map<string, boolean>();\r\n const automationIdResults = new Map<string, AutomationIdResult>();\r\n const failureText = new Map<string, string>();\r\n const discoveredFiles = new Set<string>();\r\n const discoveredAutomationIds = new Set<string>();\r\n\r\n TESTSUITE_OPEN_RE.lastIndex = 0;\r\n let suiteMatch: RegExpExecArray | null;\r\n while ((suiteMatch = TESTSUITE_OPEN_RE.exec(xml))) {\r\n const file = FILE_ATTR_RE.exec(suiteMatch[1])?.[1];\r\n if (file) discoveredFiles.add(normalizeSlashes(file));\r\n }\r\n\r\n let match: RegExpExecArray | null;\r\n TESTCASE_RE.lastIndex = 0;\r\n while ((match = TESTCASE_RE.exec(xml))) {\r\n const [, attrs, body = \"\"] = match;\r\n // A test's identity is its title as a person reads it. JUnit writers escape it (\"describe > test\" arrives as\r\n // \"describe > test\"), and the identity is what a failed run's reason names, so it is unescaped here once.\r\n const rawName = NAME_ATTR_RE.exec(attrs)?.[1];\r\n if (!rawName) continue;\r\n const name = unescapeXmlEntities(rawName);\r\n const rawClassname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\r\n const classname = rawClassname === undefined ? undefined : unescapeXmlEntities(rawClassname);\r\n const id = classname ? `${classname}::${name}` : name;\r\n const failed = FAILURE_CHILD_RE.test(body);\r\n outcomes.set(id, !failed);\r\n if (failed) {\r\n const text = extractFailureText(body);\r\n if (text) failureText.set(id, text);\r\n }\r\n const file = FILE_ATTR_RE.exec(attrs)?.[1];\r\n if (file) discoveredFiles.add(normalizeSlashes(file));\r\n if (classname) discoveredFiles.add(normalizeSlashes(classname));\r\n const bracket = QP_TOKEN_BRACKET_RE.exec(name)?.[1];\r\n if (bracket) {\r\n discoveredAutomationIds.add(bracket);\r\n const result: AutomationIdResult = failed ? \"fail\" : SKIPPED_CHILD_RE.test(body) ? \"skipped\" : \"pass\";\r\n const seen = automationIdResults.get(bracket);\r\n if (!seen || RESULT_RANK[result] > RESULT_RANK[seen]) automationIdResults.set(bracket, result);\r\n }\r\n }\r\n return { outcomes, automationIdResults, failureText, discoveredFiles, discoveredAutomationIds };\r\n}\r\n\r\nfunction readJUnitOutcomes(cwd: string): JUnitParseResult | null {\r\n const report = findJUnitReport(cwd);\r\n if (!report) return null;\r\n try {\r\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** QUIKTR-1402 \u2014 per-case results from whatever JUnit report is on disk now; `null` when none is found or\r\n * it cannot be parsed (\"could not tell\", which the baseline check must treat differently from \"nothing\r\n * passed\"). Deliberately not part of TestSnapshot: only the baseline check reads it. */\r\nexport function readAutomationIdResults(cwd = process.cwd()): Map<string, AutomationIdResult> | null {\r\n return readJUnitOutcomes(cwd)?.automationIdResults ?? null;\r\n}\r\n\r\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\r\n const outcome = runTestCommand(command);\r\n const parsed = readJUnitOutcomes(cwd);\r\n return {\r\n outcome,\r\n results: parsed?.outcomes ?? null,\r\n failureText: parsed?.failureText,\r\n discoveredFiles: parsed?.discoveredFiles ?? null,\r\n discoveredAutomationIds: parsed?.discoveredAutomationIds ?? null,\r\n };\r\n}\r\n\r\nexport async function captureBaselineSnapshot(\r\n command: string | null,\r\n cwd = process.cwd(),\r\n): Promise<TestSnapshot> {\r\n const outcome = await runTestCommandAsync(command);\r\n const parsed = readJUnitOutcomes(cwd);\r\n return {\r\n outcome,\r\n results: parsed?.outcomes ?? null,\r\n failureText: parsed?.failureText,\r\n discoveredFiles: parsed?.discoveredFiles ?? null,\r\n discoveredAutomationIds: parsed?.discoveredAutomationIds ?? null,\r\n };\r\n}\r\n\r\nexport interface RegressionCheck {\r\n blocked: boolean;\r\n regressions: string[];\r\n newFailures: string[];\r\n preExisting: string[];\r\n /** testId -> bounded failure text, for whichever `regressions`/`newFailures` entries had one in\r\n * the AFTER snapshot (the failure that actually blocks the push \u2014 the baseline's own failure\r\n * text, if any, is irrelevant here). Always present, possibly empty \u2014 never omitted, so a\r\n * caller never has to guard its absence the way `results` itself still requires. */\r\n failureText: Map<string, string>;\r\n}\r\n\r\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\r\n if (!baseline.results || !after.results) {\r\n return { blocked: false, regressions: [], newFailures: [], preExisting: [], failureText: new Map() };\r\n }\r\n\r\n const regressions: string[] = [];\r\n const newFailures: string[] = [];\r\n const preExisting: string[] = [];\r\n const failureText = new Map<string, string>();\r\n const afterFailureText = after.failureText;\r\n\r\n for (const [testId, passed] of after.results) {\r\n if (passed) continue;\r\n const before = baseline.results.get(testId);\r\n if (before === true) {\r\n regressions.push(testId);\r\n const text = afterFailureText?.get(testId);\r\n if (text) failureText.set(testId, text);\r\n } else if (before === false) {\r\n preExisting.push(testId);\r\n } else {\r\n newFailures.push(testId);\r\n const text = afterFailureText?.get(testId);\r\n if (text) failureText.set(testId, text);\r\n }\r\n }\r\n\r\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting, failureText };\r\n}\r\n\r\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\r\n * someone's morning (they're different diagnoses: one means the generated code broke something\r\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\r\n * noted, not hidden, so the message doesn't read as if they were silently dropped.\r\n *\r\n * QUIKTR-1029 self-heal prerequisite 1 \u2014 each named test now carries its failure text inline\r\n * when one was captured, so a run that blocks says WHY, not only WHAT. */\r\nexport function describeRegressions(check: RegressionCheck): string {\r\n const withText = (id: string) => {\r\n const text = check.failureText.get(id);\r\n return text ? `${id} (${text})` : id;\r\n };\r\n const parts: string[] = [];\r\n if (check.regressions.length > 0) {\r\n parts.push(\r\n `${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.map(withText).join(\", \")}`,\r\n );\r\n }\r\n if (check.newFailures.length > 0) {\r\n parts.push(\r\n `${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.map(withText).join(\", \")}`,\r\n );\r\n }\r\n if (check.preExisting.length > 0) {\r\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\r\n }\r\n return parts.join(\"; \");\r\n}\r\n", "import { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\r\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\r\nimport { scrubSecrets } from \"./failureReason\";\r\n\r\n/**\r\n * QUIKTR-1447 \u2014 what a failed run leaves behind for a person: the files QuikPilot wrote, the last test report and a short\r\n * manifest, in a folder the workflow uploads as an Actions artifact (kept 7 days, readable by whoever can see the repo's\r\n * Actions). Nothing goes to a branch or a pull request, and QuikTrack stores none of it.\r\n *\r\n * Written only after code generation finished, and never able to change how the run ends: the caller wraps it, and it\r\n * reports `written: false` instead of throwing.\r\n */\r\n\r\n/** Relative to the checkout root, which is where the workflow's upload step looks. */\r\nexport const FAILURE_ARTIFACT_DIR = \"quikpilot-failure\";\r\n\r\n/** Not named `junit*.xml`: the runner's own report finder walks the checkout for that pattern and would pick the copy up. */\r\nconst REPORT_COPY = \"final-test-report.xml\";\r\nconst MAX_REPORT_BYTES = 5 * 1024 * 1024;\r\nconst MAX_FILES = 200;\r\n\r\n// Replaced at build time (build.mjs); absent under vitest.\r\ndeclare const __RUNNER_VERSION__: string | undefined;\r\nconst RUNNER_VERSION = typeof __RUNNER_VERSION__ === \"string\" ? __RUNNER_VERSION__ : \"dev\";\r\n\r\nexport interface FailureArtifactInput {\r\n cwd: string;\r\n runId: string;\r\n issueKey: string | null;\r\n targets: ReadonlyArray<{ path: string; kind: string; automationIds?: string[] }>;\r\n results: ReadonlyArray<{ targetPath: string; newContent: string }>;\r\n /** The test report from the run after code generation, or null if no such run happened. A report from before\r\n * generation (the baseline) must never be passed. */\r\n testReport: Buffer | null;\r\n /** Already scrubbed and cut by the caller; scrubbed again here as the manifest is written. */\r\n failureReasons: readonly string[];\r\n /** Values that must not appear anywhere in the manifest, such as the run token. */\r\n secrets: readonly string[];\r\n}\r\n\r\n/** A path from the model must resolve inside the folder: absolute and parent-directory paths are refused. */\r\nfunction safeDestination(base: string, repoPath: string): string | null {\r\n if (!repoPath || isAbsolute(repoPath)) return null;\r\n const destination = resolve(base, repoPath);\r\n const rel = relative(base, destination);\r\n if (!rel || rel.startsWith(\"..\") || isAbsolute(rel)) return null;\r\n return destination;\r\n}\r\n\r\nexport function writeFailureArtifact(input: FailureArtifactInput): { written: boolean } {\r\n if (input.results.length === 0) return { written: false };\r\n try {\r\n const base = resolve(input.cwd, FAILURE_ARTIFACT_DIR);\r\n // A folder from an earlier call must not mix with this one.\r\n rmSync(base, { recursive: true, force: true });\r\n mkdirSync(base, { recursive: true });\r\n\r\n const files: Array<{ path: string; bytes: number }> = [];\r\n const skipped: string[] = [];\r\n for (const result of input.results) {\r\n const destination = files.length < MAX_FILES ? safeDestination(base, result.targetPath) : null;\r\n if (!destination) {\r\n skipped.push(result.targetPath);\r\n continue;\r\n }\r\n mkdirSync(dirname(destination), { recursive: true });\r\n writeFileSync(destination, result.newContent);\r\n files.push({ path: result.targetPath, bytes: Buffer.byteLength(result.newContent) });\r\n }\r\n\r\n let testReport: \"included\" | \"none\" | \"too-large\" = \"none\";\r\n if (input.testReport) {\r\n if (input.testReport.byteLength > MAX_REPORT_BYTES) {\r\n testReport = \"too-large\";\r\n } else {\r\n writeFileSync(join(base, REPORT_COPY), input.testReport);\r\n testReport = \"included\";\r\n }\r\n }\r\n\r\n const manifest = {\r\n runId: input.runId,\r\n issueKey: input.issueKey,\r\n runnerVersion: RUNNER_VERSION,\r\n generatedAt: new Date().toISOString(),\r\n targets: input.targets.map((t) => ({\r\n path: t.path,\r\n kind: t.kind,\r\n ...(t.automationIds && t.automationIds.length > 0 ? { automationIds: t.automationIds } : {}),\r\n })),\r\n files,\r\n skipped,\r\n testReport,\r\n failureReasons: input.failureReasons,\r\n };\r\n // Every string is scrubbed as the manifest is written, so a token that reached any field is taken out.\r\n const text = JSON.stringify(manifest, (_key, value) => (typeof value === \"string\" ? scrubSecrets(value, input.secrets) : value), 2);\r\n writeFileSync(join(base, \"manifest.json\"), text);\r\n return { written: existsSync(join(base, \"manifest.json\")) };\r\n } catch (err: unknown) {\r\n console.warn(`::warning::Could not keep the failed run's files: ${err instanceof Error ? err.message : String(err)}`);\r\n return { written: false };\r\n }\r\n}\r\n", "import { RuntimeReplyError } from \"./runtimeReplyError\";\r\n\r\n/** What a failed run tells QuikTrack about why. The message a hard failure threw used to go to the CI job log and\r\n * nowhere else; it is now sent, so it is written on one line, cut to a safe length, and has anything that looks like\r\n * a credential taken out first (an error from a failed push or request can carry one). */\r\nexport const MAX_FAILURE_REASON = 1000;\r\n\r\n/** Anything shorter than this is not treated as a secret to search for: replacing a three-letter \"token\" would wreck\r\n * every word that contains it. */\r\nconst MIN_SECRET_LENGTH = 8;\r\n\r\nconst CREDENTIAL_PATTERNS: RegExp[] = [\r\n /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}/g,\r\n /\\bgithub_pat_[A-Za-z0-9_]{20,}/g,\r\n /x-access-token:[^@\\s'\"]+/gi,\r\n // Only the header form (\"Authorization: basic <token>\"), or a bearer value that contains a digit: a bare\r\n // \"basic authentication\" or \"bearer of the news\" is prose, not a credential.\r\n /\\bauthorization:\\s*(?:basic|bearer|token)\\s+[^\\s'\"]{8,}/gi,\r\n /\\bbearer\\s+(?=[A-Za-z0-9._~+/=-]*\\d)[A-Za-z0-9._~+/=-]{12,}/gi,\r\n // A signed JWT is three dot-separated segments; QuikPilot's own run token is an encrypted JWT (alg dir) of five, the\r\n // second one empty. The run token is also matched by exact value, but one that has expired or rotated is not the\r\n // current value, so its shape has to catch it.\r\n /\\beyJ[A-Za-z0-9_-]{8,}(?:\\.[A-Za-z0-9_-]*){2,4}/g,\r\n];\r\n\r\n/** What may leave the job for a thrown error: the summary when the error quotes the AI Runtime's reply, otherwise its\r\n * message. The full message is still printed to the job log by the caller. */\r\nexport function failureSummary(err: unknown): string {\r\n if (err instanceof RuntimeReplyError) return err.summary;\r\n return err instanceof Error ? err.message : String(err);\r\n}\r\n\r\n/** Takes known secrets (by value) and anything shaped like a credential out of a piece of text. Does not change the\r\n * text otherwise: no line folding, no cutting. */\r\nexport function scrubSecrets(message: string, secrets: readonly string[] = []): string {\r\n let text = message;\r\n for (const secret of secrets) {\r\n if (secret.length >= MIN_SECRET_LENGTH) text = text.split(secret).join(\"***\");\r\n }\r\n for (const pattern of CREDENTIAL_PATTERNS) text = text.replace(pattern, \"***\");\r\n return text;\r\n}\r\n\r\nexport function describeFailureReason(message: string, secrets: readonly string[] = []): string {\r\n let text = scrubSecrets(message, secrets);\r\n text = text.replace(/\\s*\\n\\s*/g, \" | \").trim();\r\n return text.length > MAX_FAILURE_REASON ? `${text.slice(0, MAX_FAILURE_REASON)}\u2026` : text;\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\nimport type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1081 \u2014 QUIKSPL-5's PR #22 fixed the reported bug in src/validation.js and also silently\r\n * added an undeclared PUT endpoint to src/server.js that returned success while updating nothing.\r\n * Tests passed, the dependency check passed, and nothing compared what codegen actually added\r\n * against the design's own declared `apiChanges` \u2014 because nothing did.\r\n *\r\n * Same \"minimal, not exhaustive\" standard as dependencyCheck.ts's import scanner and\r\n * regressionCheck.ts's JUnit scanner, for the same reason: this package is dependency-free,\r\n * bundled into a single CLI file with no externals, published outside the monorepo, and the\r\n * target repository is arbitrary \u2014 no real per-framework route parser is on the table. This is a\r\n * same-line METHOD+PATH text heuristic, a tripwire against the ticket's own incident (method and\r\n * path both named on the documenting comment's line), not a route parser for every framework a\r\n * customer repo might use. It will not catch a Next.js-style `export function PUT(...)` whose path\r\n * comes from file location rather than an in-file string \u2014 ROUTE_EXPORT_RE below covers that one\r\n * export shape specifically, matched by method presence alone since it has no in-file path to\r\n * compare.\r\n *\r\n * \"Exported symbols\" (the ticket's own words) is deliberately narrowed to route-handler-shaped\r\n * exports here, not any new exported symbol: an arbitrary new exported helper is routine,\r\n * legitimate refactoring, and checking every export against free-text `apiChanges` would produce\r\n * exactly the kind of false-positive noise this package's checks otherwise avoid.\r\n */\r\nexport interface ScopeViolation {\r\n file: string;\r\n method: string;\r\n path: string;\r\n}\r\n\r\nexport interface ScopeCheck {\r\n blocked: boolean;\r\n violations: ScopeViolation[];\r\n}\r\n\r\ninterface RouteMention {\r\n method: string;\r\n path: string;\r\n}\r\n\r\nconst ROUTE_METHOD_RE = /\\b(GET|POST|PUT|PATCH|DELETE)\\b/i;\r\nconst ROUTE_PATH_RE = /\\/[A-Za-z0-9_\\-{}[\\]]+(?:\\/[A-Za-z0-9_\\-:{}[\\]]+)+/;\r\nconst ROUTE_EXPORT_RE = /\\bexport\\s+(?:async\\s+)?function\\s+(GET|POST|PUT|PATCH|DELETE)\\s*\\(/;\r\n\r\n/** No in-file path \u2014 a Next.js-style route handler's path comes from where the file lives, not a\r\n * string in it. Matched against `apiChanges` by method presence alone (see `surfaceCovers`). */\r\nconst NO_PATH = \"(this file's route)\";\r\n\r\nfunction detectMentions(text: string): RouteMention[] {\r\n const found: RouteMention[] = [];\r\n for (const line of text.split(\"\\n\")) {\r\n const methodMatch = ROUTE_METHOD_RE.exec(line);\r\n const pathMatch = ROUTE_PATH_RE.exec(line);\r\n if (methodMatch && pathMatch) {\r\n found.push({ method: methodMatch[1].toUpperCase(), path: pathMatch[0] });\r\n }\r\n const exportMatch = ROUTE_EXPORT_RE.exec(line);\r\n if (exportMatch) {\r\n found.push({ method: exportMatch[1].toUpperCase(), path: NO_PATH });\r\n }\r\n }\r\n return found;\r\n}\r\n\r\n/** `:id`, `{id}`, `[id]` all become `*` so a declared surface and a detected mention compare equal\r\n * regardless of the exact param name either side happens to use. */\r\nfunction normalizePath(path: string): string {\r\n return path.replace(/:[A-Za-z0-9_]+|\\{[^}]+\\}|\\[[^\\]]+\\]/g, \"*\");\r\n}\r\n\r\nfunction surfaceCovers(surface: string, mention: RouteMention): boolean {\r\n if (!new RegExp(`\\\\b${mention.method}\\\\b`, \"i\").test(surface)) return false;\r\n if (mention.path === NO_PATH) return true; // method presence is all a route-export mention has\r\n const declaredPath = normalizePath(surface);\r\n const mentionPath = normalizePath(mention.path);\r\n return declaredPath.includes(mentionPath) || mentionPath.includes(declaredPath);\r\n}\r\n\r\n/** Lines present in `after` but not in `before` \u2014 a set difference, not a positional diff (code\r\n * can shift line numbers around an addition). Good enough to separate \"genuinely new this run\"\r\n * from \"was already there\" without a real diff algorithm, same spirit as this package's other\r\n * scanners. */\r\nfunction addedLines(before: string, after: string): string {\r\n const beforeLines = new Set(before.split(\"\\n\"));\r\n return after\r\n .split(\"\\n\")\r\n .filter((line) => !beforeLines.has(line))\r\n .join(\"\\n\");\r\n}\r\n\r\n/** A test names and calls routes constantly (`describe(\"POST /api/x\", \u2026)`) but cannot define one,\r\n * so scanning it can only produce false positives. Common conventions only, in the same spirit as\r\n * the rest of this file \u2014 not an exhaustive per-framework list. */\r\nconst TEST_FILE_RES = [\r\n /(^|\\/)(__tests__|__mocks__|tests?|specs?)\\//i,\r\n /\\.(test|spec)\\.[^/.]+$/i,\r\n /(^|\\/)test_[^/]+\\.py$/i,\r\n /_test\\.(py|go)$/i,\r\n /Tests?\\.(java|kt|cs)$/,\r\n];\r\n\r\nfunction isTestFile(path: string): boolean {\r\n return TEST_FILE_RES.some((re) => re.test(path));\r\n}\r\n\r\nexport function checkApiScope(\r\n results: CodegenFileResult[],\r\n targets: PilotTarget[],\r\n apiChanges: { surface: string; change: string; reason: string }[],\r\n): ScopeCheck {\r\n const targetsByPath = new Map(targets.map((t) => [t.path, t]));\r\n const violations: ScopeViolation[] = [];\r\n\r\n for (const { targetPath, newContent } of results) {\r\n if (isTestFile(targetPath)) continue;\r\n const target = targetsByPath.get(targetPath);\r\n const isNewFile = target?.kind === \"NEW_FILE\";\r\n\r\n let scanned: string;\r\n if (isNewFile) {\r\n scanned = newContent;\r\n } else {\r\n let currentContent: string;\r\n try {\r\n currentContent = readFileSync(targetPath, \"utf8\");\r\n } catch {\r\n currentContent = \"\";\r\n }\r\n scanned = addedLines(currentContent, newContent);\r\n }\r\n\r\n for (const mention of detectMentions(scanned)) {\r\n if (!apiChanges.some((c) => surfaceCovers(c.surface, mention))) {\r\n violations.push({ file: targetPath, method: mention.method, path: mention.path });\r\n }\r\n }\r\n }\r\n\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\nexport function describeScopeViolations(check: ScopeCheck): string {\r\n return check.violations\r\n .map((v) => `${v.file} adds ${v.method} ${v.path}, not declared in the design's API changes`)\r\n .join(\"; \");\r\n}\r\n", "import { resolve, relative, isAbsolute } from \"node:path\";\r\nimport { findDeniedContextPath, matchesDeniedPath } from \"./deniedPaths\";\r\nimport { listFiles } from \"./git\";\r\nimport { checkHardFailure, unwrapExecute } from \"./envelope\";\r\nimport { RuntimeReplyError } from \"./runtimeReplyError\";\r\nimport type { PilotPacket } from \"./packet\";\r\nimport { fetchWithRetry } from \"./retryFetch\";\r\n\r\n/**\r\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\r\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\r\n * Runtime against a real 624-file QuikChat listing before this was wired in.\r\n *\r\n * QUIKTR-1083 (\u00A715) \u2014 the versioned test-target contract. `contractVersion: \"test-targets-1\"` is\r\n * sent unconditionally: per \u00A715.6 the unversioned path is only \"exactly today's behaviour\" for a\r\n * caller that never asks for the new shape, and this runner always wants it once it ships.\r\n */\r\nconst CONTRACT_VERSION = \"test-targets-1\";\r\n\r\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\r\n\r\nexport interface PilotTarget {\r\n path: string;\r\n kind: TargetKind;\r\n planStepsImplemented: string[];\r\n // Context contract change \u2014 pilot.targeting now names, per target, which other files\r\n // pilot.codegen should read before writing this one (\"to write this file, read these\").\r\n // codegen.ts validates and reads these; absent/empty means no context, no fallback.\r\n contextPaths?: string[];\r\n /** \u00A715.3 \u2014 present only on a test target: the automation IDs (not database ids \u2014 see\r\n * \u00A715.3's own naming rationale) this target's generated file must cover. codegen.ts forwards\r\n * only the matching `requiredTests` subset for a target carrying this. */\r\n automationIds?: string[];\r\n}\r\n\r\n/** \u00A715.3 amendment 1 \u2014 a case with no behaviour (given/when/then all null) is named here instead\r\n * of silently dropped; the model has no discretion over which cases land here vs. in a target's\r\n * `automationIds` (completeness is enforced on the runtime side). Informational on this side \u2014\r\n * folded into `run.ts`'s `warnings`, never blocking. */\r\nexport interface SkippedCase {\r\n automationId: string;\r\n reason: \"NO_BEHAVIOUR\";\r\n}\r\n\r\nexport type TargetingResult =\r\n | {\r\n outcome: \"TARGETED\";\r\n targets: PilotTarget[];\r\n skippedCases: SkippedCase[];\r\n /** Paths targeting called NEW_FILE although they are already in the checkout; they come back as EXISTING. */\r\n correctedKinds?: string[];\r\n }\r\n | { outcome: \"NO_TARGET\"; reason: string | null };\r\n\r\ninterface TargetingResponse {\r\n outcome?: \"TARGETED\" | \"NO_TARGET\";\r\n targets?: {\r\n path: string;\r\n kind: string;\r\n planStepsImplemented: string[];\r\n contextPaths?: string[];\r\n automationIds?: string[];\r\n }[];\r\n skippedCases?: SkippedCase[];\r\n noTargetReason?: string;\r\n}\r\n\r\n/**\r\n * Tracked files under the packet's workspace root, or the whole checkout when it's null\r\n * (QUIKTR-1033) \u2014 never normalised to \".\" at the packet layer itself, only here where a concrete\r\n * pathspec is actually needed. An unscoped listing on a large monorepo is ~210k tokens, which fits\r\n * one provider and breaks the fallback chain \u2014 see workspaceRoot's own doc comment on PilotPacket.\r\n */\r\nexport function listWorkspaceFiles(workspaceRoot: string | null): string[] {\r\n return listFiles(workspaceRoot ?? \".\");\r\n}\r\n\r\n/**\r\n * VALIDATION IS OURS \u2014 the AI Runtime's schema doesn't guarantee a path is actually safe to write.\r\n * An EXISTING target must already be in the checkout; a NEW_FILE target must resolve inside the\r\n * workspace root. Either failure throws \u2014 a dropped target is a plan half-executed, and run.ts's\r\n * existing top-level try/catch already turns this into the same hard failure any other pre-setup\r\n * step gets.\r\n */\r\nfunction validateTarget(\r\n target: { path: string; kind: string; contextPaths?: string[] },\r\n workspaceRoot: string | null,\r\n workspaceListing: Set<string>,\r\n deniedPaths: string[],\r\n): void {\r\n // QUIKTR-1083 (\u00A715.3) \u2014 layer 2 of three: checked here, before any codegen spend, regardless of\r\n // kind. Layer 1 (the runtime's own targeting validator) should already exclude a denied path;\r\n // this does not trust that and re-checks independently.\r\n const denied = matchesDeniedPath(target.path, deniedPaths);\r\n if (denied) {\r\n throw new Error(\r\n `pilot.targeting proposed a target matching a denied path (${denied}): ${target.path}`,\r\n );\r\n }\r\n // QUIKTR-1420 \u2014 the same list applies to what the target cites as CONTEXT, which the runner reads and\r\n // sends to the model provider. Checked before anything else, and before any codegen spend.\r\n const deniedContext = findDeniedContextPath(target.contextPaths ?? [], deniedPaths);\r\n if (deniedContext) {\r\n throw new Error(\r\n `pilot.targeting cited a denied path as context (${deniedContext.pattern}): ${deniedContext.path} (target ${target.path})`,\r\n );\r\n }\r\n if (target.kind !== \"EXISTING\" && target.kind !== \"NEW_FILE\") {\r\n throw new Error(`pilot.targeting returned an unknown kind \"${target.kind}\" for ${target.path}`);\r\n }\r\n if (target.kind === \"EXISTING\") {\r\n if (!workspaceListing.has(target.path)) {\r\n throw new Error(\r\n `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`,\r\n );\r\n }\r\n return;\r\n }\r\n const root = resolve(workspaceRoot ?? \".\");\r\n const rel = relative(root, resolve(target.path));\r\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\r\n throw new Error(\r\n `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`,\r\n );\r\n }\r\n}\r\n\r\nexport async function runTargeting(\r\n gateway: PilotPacket[\"gateway\"],\r\n design: PilotPacket[\"design\"],\r\n workspaceRoot: string | null,\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n testDiscovery: PilotPacket[\"testDiscovery\"],\r\n /** QUIKTR-1401 (\u00A720) \u2014 what the reviewer approved the change must NOT touch. Optional and last: every\r\n * existing caller is unchanged. */\r\n outOfScope: string[] = [],\r\n): Promise<TargetingResult> {\r\n // QUIKTR-1069 \u2014 retries a transport-level failure only (502/503/504, a dropped connection); a\r\n // real refusal always arrives as a 200 with the refusal inside the envelope, below.\r\n const contextData: Record<string, unknown> = {\r\n // NESTED, NOT FLATTENED \u2014 a second vocabulary for the design shape is exactly what\r\n // QUIKTR-1034 cost.\r\n workspaceListing,\r\n design,\r\n // QUIKTR-1065/1083 \u2014 requiredTests carried through so targeting can propose a test-file\r\n // target naming which cases it covers (\u00A715.1's Case shape, unchanged).\r\n requiredTests,\r\n // QUIKTR-1083 (\u00A715.6) \u2014 required on the versioned path.\r\n contractVersion: CONTRACT_VERSION,\r\n };\r\n // QUIKTR-1083 (\u00A715.3) \u2014 optional on the wire; omitted rather than sent empty, matching\r\n // codegen.ts's identical treatment.\r\n if (deniedPaths.length > 0) {\r\n contextData.deniedPaths = deniedPaths;\r\n }\r\n // QUIKTR-1401, \u00A720 of the AI Runtime contract (deployed and confirmed 2026-10-01) \u2014 an optional declared key\r\n // under the versioned contract, sent only when non-empty: an empty list would make the prompt mention\r\n // constraints that are not there. Free text, so unlike deniedPaths it can only be TOLD to the model, never\r\n // checked. Never sent to pilot.design.\r\n if (outOfScope.length > 0) {\r\n contextData.outOfScope = outOfScope;\r\n }\r\n // QUIKTR-1315, \u00A719 of the AI Runtime contract \u2014 AGREED (2026-09-28), confirmed deployed and\r\n // live (2026-09-29). ALWAYS sent, never omitted \u2014 \u00A719's whole point is the tagged\r\n // `{ report: \"PRESENT\" | \"ABSENT\" }` shape replacing an absent-vs-empty key distinction, so this\r\n // must not fall back to \"omit when nothing to say\" the way `deniedPaths` does above. The packet\r\n // already resolves this to a real value in every case (never undefined) \u2014 see packet.ts.\r\n contextData.testDiscovery = testDiscovery;\r\n\r\n const res = await fetchWithRetry(`${gateway.baseUrl}/ai/execute`, {\r\n method: \"POST\",\r\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\r\n body: JSON.stringify({\r\n appId: \"quiktrack\",\r\n useCase: \"pilot.targeting\",\r\n expectedOutputType: \"json\",\r\n userPrompt: \"\",\r\n contextData,\r\n }),\r\n });\r\n\r\n if (!res.ok) {\r\n throw new Error(`Targeting call failed: ${res.status} ${res.statusText}`);\r\n }\r\n\r\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\r\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\r\n // QUIKTR-1083 \u2014 SEMANTIC_MISMATCH/CONTRACT_REJECTED are checked on the raw envelope, before\r\n // unwrapping, same reason codegen.ts's pre-existing CODEGEN_* checks do: unwrapping first would\r\n // throw unwrapExecute's generic success:false error and lose the distinction.\r\n const envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.targeting\");\r\n const body = unwrapExecute<TargetingResponse>(envelope, \"pilot.targeting\");\r\n\r\n if (body.outcome === \"NO_TARGET\") {\r\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\r\n }\r\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\r\n throw new RuntimeReplyError(\r\n `pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`,\r\n \"pilot.targeting returned an unexpected shape\",\r\n );\r\n }\r\n\r\n const listing = new Set(workspaceListing);\r\n for (const target of body.targets) {\r\n validateTarget(target, workspaceRoot, listing, deniedPaths);\r\n }\r\n\r\n // A NEW_FILE target is sent to codegen with no current content, so a file that already exists would be\r\n // overwritten blind (QUIKTR-1448). The checkout listing says which it is, so the label is corrected here\r\n // rather than failing a run over a mistake with an obvious answer.\r\n const correctedKinds: string[] = [];\r\n const targets = (body.targets as PilotTarget[]).map((target) => {\r\n if (target.kind === \"NEW_FILE\" && listing.has(target.path)) {\r\n correctedKinds.push(target.path);\r\n return { ...target, kind: \"EXISTING\" as const };\r\n }\r\n return target;\r\n });\r\n\r\n return {\r\n outcome: \"TARGETED\",\r\n targets,\r\n skippedCases: body.skippedCases ?? [],\r\n ...(correctedKinds.length > 0 ? { correctedKinds } : {}),\r\n };\r\n}\r\n", "import type { TargetKind, TargetingResult } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1421 \u2014 a record of what pilot.targeting decided, reported to QuikTrack in the run's final callback so\r\n * \"which contextPaths did targeting list for the test?\" can be answered after the fact. Twice it could not\r\n * (QUIKSPL-16, then run 25): the AI Runtime's logs carry counts only, deliberately, and QuikTrack's run trail\r\n * stores a payload hash, so neither side kept what was actually DECIDED.\r\n *\r\n * PATHS AND CASE IDS ONLY (Suyash). Never case text, never `planStepsImplemented` (model-written prose about\r\n * the customer's code), never file content. The one free-text field is the NO_TARGET reason, cut to 300\r\n * characters with a flag saying so.\r\n *\r\n * Every cap below matches QuikTrack's `targetingRecordSchema`. That is not tidiness: a record QuikTrack finds\r\n * invalid is dropped, so a record over the caps is a record lost. Anything cut sets `truncated`.\r\n */\r\nconst MAX_TARGETS = 25;\r\nconst MAX_IDS_PER_TARGET = 50;\r\nconst MAX_CONTEXT_PATHS = 20;\r\nconst MAX_ADDED_PATHS = 20;\r\nconst MAX_SKIPPED_CONTEXT = 20;\r\nconst MAX_SKIPPED_CASES = 200;\r\nconst MAX_CONTEXT_RECORDS = 25;\r\nconst MAX_PATH_CHARS = 300;\r\nconst MAX_ID_CHARS = 100;\r\nconst MAX_REASON_CHARS = 300;\r\n\r\n/** One `runCodegen` call: what targeting named as context, what the runner ADDED (QUIKTR-1419), and what it\r\n * skipped. `runCodegen` fills a caller-owned array of these, so the entries survive a later throw. */\r\nexport interface CodegenContextRecord {\r\n targetPath: string;\r\n contextPaths: string[];\r\n addedPaths: string[];\r\n skipped: { path: string; reason: string }[];\r\n /** QUIKTR-1454 \u2014 the part of `addedPaths` that came from the target's own imports. Log line only: QuikTrack's\r\n * record keeps `addedPaths` (which includes them) and strips fields it does not know. Omitted when empty. */\r\n importedPaths?: string[];\r\n /** QUIKTR-1454 \u2014 path-alias imports (`@/x`) seen and not followed. Counted, not listed. Omitted when zero. */\r\n aliasImports?: number;\r\n /** The runtime refused the context as too large and the call was retried WITHOUT the added files, so\r\n * `addedPaths` is empty even though files were offered first. */\r\n retriedWithoutAdded?: true;\r\n}\r\n\r\nexport interface TargetingRecord {\r\n outcome: \"TARGETED\" | \"NO_TARGET\";\r\n noTargetReason?: string;\r\n noTargetReasonTruncated?: true;\r\n targets: { path: string; kind: TargetKind; contextPaths: string[]; automationIds: string[] }[];\r\n skippedCaseIds: string[];\r\n codegenContext: CodegenContextRecord[];\r\n truncated?: true;\r\n}\r\n\r\n/** Keeps at most `max` non-empty entries no longer than `maxChars`, telling the caller if anything was cut. A\r\n * too-long value is DROPPED, not shortened: a cut-off path is a wrong path. */\r\nfunction clampList(values: string[] | undefined, max: number, maxChars: number): { kept: string[]; cut: boolean } {\r\n let cut = false;\r\n const kept: string[] = [];\r\n for (const raw of values ?? []) {\r\n const v = typeof raw === \"string\" ? raw.trim() : \"\";\r\n if (v.length === 0) continue;\r\n if (v.length > maxChars || kept.length >= max) {\r\n cut = true;\r\n continue;\r\n }\r\n kept.push(v);\r\n }\r\n return { kept, cut };\r\n}\r\n\r\nexport function buildTargetingRecord(targeting: TargetingResult, contextLog: CodegenContextRecord[]): TargetingRecord {\r\n let truncated = false;\r\n const note = (cut: boolean) => {\r\n if (cut) truncated = true;\r\n };\r\n\r\n if (targeting.outcome === \"NO_TARGET\") {\r\n const record: TargetingRecord = { outcome: \"NO_TARGET\", targets: [], skippedCaseIds: [], codegenContext: [] };\r\n const reason = (targeting.reason ?? \"\").trim();\r\n if (reason.length > 0) {\r\n record.noTargetReason = reason.slice(0, MAX_REASON_CHARS);\r\n if (reason.length > MAX_REASON_CHARS) record.noTargetReasonTruncated = true;\r\n }\r\n return record;\r\n }\r\n\r\n const targets: TargetingRecord[\"targets\"] = [];\r\n for (const t of targeting.targets) {\r\n if (targets.length >= MAX_TARGETS) {\r\n truncated = true;\r\n break;\r\n }\r\n const path = typeof t.path === \"string\" ? t.path.trim() : \"\";\r\n if (path.length === 0 || path.length > MAX_PATH_CHARS) {\r\n truncated = true;\r\n continue;\r\n }\r\n const contextPaths = clampList(t.contextPaths, MAX_CONTEXT_PATHS, MAX_PATH_CHARS);\r\n const automationIds = clampList(t.automationIds, MAX_IDS_PER_TARGET, MAX_ID_CHARS);\r\n note(contextPaths.cut);\r\n note(automationIds.cut);\r\n targets.push({ path, kind: t.kind, contextPaths: contextPaths.kept, automationIds: automationIds.kept });\r\n }\r\n\r\n const skipped = clampList(\r\n (targeting.skippedCases ?? []).map((c) => c.automationId),\r\n MAX_SKIPPED_CASES,\r\n MAX_ID_CHARS,\r\n );\r\n note(skipped.cut);\r\n\r\n const codegenContext: CodegenContextRecord[] = [];\r\n for (const entry of contextLog) {\r\n if (codegenContext.length >= MAX_CONTEXT_RECORDS) {\r\n truncated = true;\r\n break;\r\n }\r\n const targetPath = typeof entry.targetPath === \"string\" ? entry.targetPath.trim() : \"\";\r\n if (targetPath.length === 0 || targetPath.length > MAX_PATH_CHARS) {\r\n truncated = true;\r\n continue;\r\n }\r\n const contextPaths = clampList(entry.contextPaths, MAX_CONTEXT_PATHS, MAX_PATH_CHARS);\r\n const addedPaths = clampList(entry.addedPaths, MAX_ADDED_PATHS, MAX_PATH_CHARS);\r\n const skippedPaths = clampList(\r\n (entry.skipped ?? []).map((s) => s.path),\r\n MAX_SKIPPED_CONTEXT,\r\n MAX_PATH_CHARS,\r\n );\r\n note(contextPaths.cut);\r\n note(addedPaths.cut);\r\n note(skippedPaths.cut);\r\n const reasonByPath = new Map((entry.skipped ?? []).map((s) => [s.path.trim(), s.reason]));\r\n codegenContext.push({\r\n targetPath,\r\n contextPaths: contextPaths.kept,\r\n addedPaths: addedPaths.kept,\r\n skipped: skippedPaths.kept.map((path) => ({ path, reason: String(reasonByPath.get(path) ?? \"skipped\").slice(0, 40) })),\r\n ...(entry.retriedWithoutAdded ? { retriedWithoutAdded: true as const } : {}),\r\n });\r\n }\r\n\r\n const record: TargetingRecord = {\r\n outcome: \"TARGETED\",\r\n targets,\r\n skippedCaseIds: skipped.kept,\r\n codegenContext,\r\n };\r\n if (truncated) record.truncated = true;\r\n return record;\r\n}\r\n", "import type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1315 \u2014 targeting can claim a test case's `automationId` against a SOURCE-file target while\r\n * proposing a separate, empty test-file target alongside it (no plan steps, no automationIds).\r\n * Verified against a real captured AI Runtime sample (`targeting-versioned.json`): the model wrote\r\n * `tests/auth/login.test.ts` with `automationIds: []` and claimed all three cases on\r\n * `src/auth/middleware.ts`/`src/auth/login.ts` instead. When that happens, the generated test lands\r\n * inside a source file the repository's test runner never discovers \u2014 the case has zero real\r\n * coverage even though its id is present in the generated text, and \u00A715's own completeness rule\r\n * (every case appears exactly once) is satisfied regardless.\r\n *\r\n * Two detectors, both using the repository's OWN JUnit report as ground truth for \"which files the\r\n * test runner actually looks at\" \u2014 no naming convention, derived by running the repo's own tooling,\r\n * language-neutral by construction:\r\n *\r\n * `checkTestPlacement` \u2014 BEFORE the write, against the BASELINE report (pre-codegen).\r\n * Scoped to EXISTING targets only: a NEW_FILE test target is never\r\n * in the baseline set because it does not exist yet, so this check\r\n * must never run on one \u2014 a legitimate first test file would be\r\n * indistinguishable from the suspicious case.\r\n * `checkAutomationIdCoverage` \u2014 AFTER the change, against the AFTER report (post-codegen). The\r\n * stronger of the two: catches inverted placement regardless of\r\n * why it happened, including whatever the first check's loose\r\n * file-matching missed.\r\n *\r\n * Both are TRIPWIRES, not proofs \u2014 same posture as this package's other `*Check.ts` scanners\r\n * (`dependencyCheck.ts`, `scopeCheck.ts`): a minimal heuristic against an arbitrary target repo,\r\n * deliberately erring toward under-flagging (fewer false positives blocking a real run) rather than\r\n * over-flagging, since both are hard-failing checks.\r\n */\r\nexport interface TestPlacementViolation {\r\n file: string;\r\n automationIds: string[];\r\n}\r\n\r\nexport interface TestPlacementCheck {\r\n blocked: boolean;\r\n violations: TestPlacementViolation[];\r\n}\r\n\r\n/** A target's path counts as \"discovered\" if it exactly equals, is a suffix of, or has as a suffix,\r\n * any candidate string the JUnit report produced. Loose on purpose: `classname` is a real file path\r\n * for Vitest and derivable for pytest, but not guaranteed for Jest or Go \u2014 see this file's module\r\n * docblock. A tighter, exact-only match would false-positive on every repo where the report's path\r\n * is relative to a different root than the target's own path. */\r\nfunction isDiscovered(targetPath: string, discoveredFiles: Set<string>): boolean {\r\n const normalized = targetPath.replace(/\\\\/g, \"/\");\r\n for (const candidate of discoveredFiles) {\r\n if (candidate === normalized) return true;\r\n if (candidate.endsWith(normalized) || normalized.endsWith(candidate)) return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * `discoveredFiles` is the BASELINE run's `TestSnapshot.discoveredFiles` \u2014 `undefined`/`null`/empty\r\n * all mean \"can't tell,\" and the check no-ops rather than blocking on a question it can't answer\r\n * (no baseline report at all, or one with no file-shaped attribution). A repository producing no\r\n * JUnit report gets no detector \u2014 not a gap here, `readiness-panel`'s existing dry-run warning\r\n * (QUIKTR-1084) is what tells the user to fix that.\r\n */\r\nexport function checkTestPlacement(\r\n targets: PilotTarget[],\r\n discoveredFiles: Set<string> | null | undefined,\r\n): TestPlacementCheck {\r\n if (!discoveredFiles || discoveredFiles.size === 0) return { blocked: false, violations: [] };\r\n\r\n const violations: TestPlacementViolation[] = [];\r\n for (const target of targets) {\r\n if (target.kind !== \"EXISTING\") continue;\r\n if (!target.automationIds || target.automationIds.length === 0) continue;\r\n if (!isDiscovered(target.path, discoveredFiles)) {\r\n violations.push({ file: target.path, automationIds: target.automationIds });\r\n }\r\n }\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\nexport function describeTestPlacementViolations(check: TestPlacementCheck): string {\r\n return check.violations\r\n .map(\r\n (v) =>\r\n `${v.file} claims test case(s) ${v.automationIds.join(\", \")} but the repository's own test runner never discovered this file`,\r\n )\r\n .join(\"; \");\r\n}\r\n\r\nexport interface AutomationCoverageCheck {\r\n blocked: boolean;\r\n missing: string[];\r\n}\r\n\r\n/**\r\n * `discoveredAutomationIds` is the AFTER run's `TestSnapshot.discoveredAutomationIds` \u2014\r\n * `undefined`/`null` means \"can't tell\" (no post-codegen report at all), same no-op posture as\r\n * `checkTestPlacement`. An EMPTY (present) set is different and deliberate: it means a report\r\n * existed but nothing in it carried a bracketed id at all, which \u2014 if this run claimed any\r\n * `automationIds` \u2014 is exactly the failure this check exists to catch, so it blocks.\r\n */\r\nexport function checkAutomationIdCoverage(\r\n targets: PilotTarget[],\r\n discoveredAutomationIds: Set<string> | null | undefined,\r\n): AutomationCoverageCheck {\r\n if (discoveredAutomationIds === null || discoveredAutomationIds === undefined) {\r\n return { blocked: false, missing: [] };\r\n }\r\n\r\n const claimed = new Set<string>();\r\n for (const target of targets) {\r\n for (const id of target.automationIds ?? []) claimed.add(id);\r\n }\r\n const missing = [...claimed].filter((id) => !discoveredAutomationIds.has(id));\r\n return { blocked: missing.length > 0, missing };\r\n}\r\n\r\nexport function describeAutomationCoverageViolations(check: AutomationCoverageCheck): string {\r\n return `test case(s) ${check.missing.join(\", \")} have no matching test discovered in the test run \u2014 generated, but never executed`;\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\ninterface TokenExchangeResponse {\r\n success: boolean;\r\n data: { runToken: string; expiresAt: string };\r\n}\r\n\r\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\r\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\r\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\r\n const res = await fetch(tokenUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${oidcToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Exchange run token failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as TokenExchangeResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\r\n }\r\n return body.data.runToken;\r\n}\r\n", "import type { TestSnapshot } from \"./regressionCheck\";\r\n\r\n/**\r\n * QUIKTR-1448 \u2014 a test that ran before the change and is missing from the final report. The regression gate\r\n * only looks at tests present AFTER, so a rewritten test file that drops tests passes it (QuikSplit PR #4\r\n * lost 9 tests this way). Warn-only: the fix may mean to remove or rename a test, and a user has no way yet\r\n * to approve that, so nothing here blocks a run.\r\n */\r\nexport interface VanishedTests {\r\n /** Test ids (`classname::name`), at most MAX_VANISHED_NAMES. */\r\n names: string[];\r\n /** How many went missing, including any names cut by the cap. */\r\n total: number;\r\n}\r\n\r\n/** Bounds the callback body and the pull request description. */\r\nexport const MAX_VANISHED_NAMES = 50;\r\n\r\n/** Null when nothing is missing, or when either run produced no report (cannot tell \u2014 same posture as\r\n * `checkForRegressions`, which also stays quiet then). A test that still exists and now fails is a\r\n * regression, not a missing test, so it is not named here. */\r\nexport function findVanishedTests(baseline: TestSnapshot, after: TestSnapshot): VanishedTests | null {\r\n if (!baseline.results || !after.results) return null;\r\n const missing = [...baseline.results.keys()].filter((id) => !after.results!.has(id));\r\n if (missing.length === 0) return null;\r\n return { names: missing.slice(0, MAX_VANISHED_NAMES), total: missing.length };\r\n}\r\n\r\n/** The run-event warning. A COUNT only: test titles are the customer's text and the event reason is stored by\r\n * QuikTrack; the titles go to the pull request description instead. */\r\nexport function describeVanishedTests(vanished: VanishedTests): string {\r\n const noun = vanished.total === 1 ? \"1 test\" : `${vanished.total} tests`;\r\n return `${noun} that ran before this change ${vanished.total === 1 ? \"is\" : \"are\"} missing from the final test report; the pull request lists ${vanished.total === 1 ? \"it\" : \"them\"}.`;\r\n}\r\n", "import { reportBack } from \"./callback\";\r\nimport { runCommand, runTestCommand } from \"./commands\";\r\nimport { commitAndPush } from \"./commit\";\r\nimport { buildJudgedByPool, flushCodegenResults, runCodegen, type CodegenFileResult } from \"./codegen\";\r\nimport {\r\n checkImportDependencies,\r\n describeDependencyViolations,\r\n readDeclaredDependencies,\r\n resolveAliasPrefixes,\r\n} from \"./dependencyCheck\";\r\nimport type { PilotRunEnv } from \"./env\";\r\nimport { checkGuardrail } from \"./guardrail\";\r\nimport { checkoutTargetBranch } from \"./git\";\r\nimport { exchangeForInstallationToken } from \"./installationToken\";\r\nimport { fetchGithubOidcToken } from \"./oidc\";\r\nimport { describeOverlapWarnings, findOverlappingSteps } from \"./overlapCheck\";\r\nimport { fetchPacket, type PilotPacket } from \"./packet\";\r\nimport { writePhase0Marker } from \"./phase0\";\r\nimport { describeUnmatchedAutomationIds, readTestReportBytes, reportToQuikTest } from \"./quiktest\";\r\nimport { runBaselineCheck, type BaselineFindings } from \"./baselineCheck\";\r\nimport { writeFailureArtifact } from \"./failureArtifact\";\r\nimport { describeFailureReason, failureSummary } from \"./failureReason\";\r\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\r\nimport { checkApiScope, describeScopeViolations } from \"./scopeCheck\";\r\nimport { listWorkspaceFiles, runTargeting, type TargetingResult } from \"./targeting\";\r\nimport { buildTargetingRecord, type CodegenContextRecord } from \"./targetingRecord\";\r\nimport {\r\n checkAutomationIdCoverage,\r\n checkTestPlacement,\r\n describeAutomationCoverageViolations,\r\n describeTestPlacementViolations,\r\n} from \"./testPlacementCheck\";\r\nimport { exchangeForRunToken } from \"./tokenExchange\";\r\nimport { describeVanishedTests, findVanishedTests, type VanishedTests } from \"./vanishedTests\";\r\n\r\n/**\r\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\r\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\r\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\r\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\r\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\r\n *\r\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\r\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\r\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\r\n *\r\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\r\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\r\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\r\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\r\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\r\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\r\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\r\n *\r\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\r\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\r\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\r\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\r\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\r\n * reportToQuikTest/reportBack fire normally either way.\r\n */\r\n/** Caller narrows `RunnerEnv` to `PilotRunEnv` first \u2014 `index.ts` branches on `mode` before either\r\n * this or `readinessCheck.ts`'s `runReadinessCheck` is invoked. No default parameter: the old\r\n * `readRunnerEnv()` default returned this shape unconditionally, which is no longer true now\r\n * that `RunnerEnv` is a union (QUIKTR-1084). */\r\nexport async function run(env: PilotRunEnv): Promise<{ hardFailure: boolean }> {\r\n let hardFailure = false;\r\n let packet: PilotPacket | undefined;\r\n let branch: string | undefined;\r\n let runToken: string | undefined;\r\n const warnings: string[] = [];\r\n // Why the run failed, for the final callback. The message used to be printed to the job log and lost to\r\n // QuikTrack, which then knew only \"failed\". Scrubbed of credentials and cut before it is kept.\r\n const failureReasons: string[] = [];\r\n const recordFailure = (err: unknown) => {\r\n const message = err instanceof Error ? err.message : String(err);\r\n console.error(message);\r\n // The job log gets the full message; what is reported is the summary when the error quotes the AI Runtime's reply.\r\n const reason = describeFailureReason(failureSummary(err), runToken ? [runToken] : []);\r\n if (reason) failureReasons.push(reason);\r\n };\r\n // QUIKTR-1067 \u2014 hoisted out of the try block's TARGETED branch: commitAndPush\r\n // needs it later, outside that scope, to build a real commit message instead\r\n // of the \"Phase 0 skeleton\" placeholder. Defaults false \u2014 correct for\r\n // NO_TARGET and for any early hard failure, both of which skip commitAndPush\r\n // or must fall back to the marker message anyway.\r\n let targeted = false;\r\n // QUIKTR-1333 \u2014 same hoisting reason as `targeted` above: reportToQuikTest is\r\n // called later, outside the TARGETED branch's scope where `results` lives.\r\n // Empty for NO_TARGET and any early failure \u2014 correct, since nothing was\r\n // written either way.\r\n let generatedFilePaths: string[] = [];\r\n // QUIKTR-1447 \u2014 hoisted for the same reason, so a run that fails AFTER code generation can keep what was generated.\r\n // Held in memory because the dependency, scope and placement checks fail before the files are flushed. The final\r\n // test report is read right after the post-generation test run and nowhere else: a report on disk before that is\r\n // the baseline's, and reportToQuikTest deletes it once sent.\r\n let generatedResults: CodegenFileResult[] = [];\r\n let finalTestReport: Buffer | null = null;\r\n // QUIKTR-1421 \u2014 hoisted for the same reason: the record is built at the end, outside the try, so a run that\r\n // dies in codegen still reports what targeting decided and which context codegen had already assembled.\r\n let targetingResult: TargetingResult | undefined;\r\n // QUIKTR-1402 \u2014 hoisted for the same reason: reported at the end, outside the try. Undefined when the check\r\n // did not run or flagged nothing.\r\n let baselineFindings: BaselineFindings | undefined;\r\n // QUIKTR-1448 \u2014 hoisted for the same reason: reported at the end, and it must survive a run that then fails on a\r\n // regression. Undefined when no test went missing or a report was not available.\r\n let vanishedTests: VanishedTests | undefined;\r\n const contextLog: CodegenContextRecord[] = [];\r\n\r\n try {\r\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\r\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\r\n checkoutTargetBranch(packet.targetBranch);\r\n\r\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\r\n // QUIKTR-1401 (\u00A720) \u2014 the reviewer's approved \"must not change\" list, with blank entries dropped. A QuikTrack\r\n // that predates the field sends none, which is the same as an empty list.\r\n const outOfScope = (packet.outOfScope ?? []).map((entry) => entry.trim()).filter((entry) => entry.length > 0);\r\n const targeting = await runTargeting(\r\n packet.gateway,\r\n packet.design,\r\n packet.workspaceRoot,\r\n workspaceListing,\r\n packet.requiredTests,\r\n packet.guardrails.deniedPaths,\r\n packet.testDiscovery,\r\n outOfScope,\r\n );\r\n targetingResult = targeting;\r\n // QUIKTR-1448 \u2014 targeting called an existing file a new one; runTargeting already treated it as existing, so the\r\n // model saw its content. Said out loud because it is a mistake in the plan, not something to hide.\r\n if (targeting.outcome === \"TARGETED\") {\r\n for (const path of targeting.correctedKinds ?? []) {\r\n const w = `QuikPilot named ${path} as a new file, but it already exists in the repository. It was treated as an existing file so its current content was kept in view.`;\r\n warnings.push(w);\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n console.log(JSON.stringify({ event: \"targeting.kind_corrected\", path }));\r\n }\r\n }\r\n if (targeting.outcome === \"NO_TARGET\") {\r\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\r\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\r\n writePhase0Marker(env.runId);\r\n runCommand(packet.commands.setup, \"Setup\");\r\n runCommand(packet.commands.lint, \"Lint\");\r\n runTestCommand(packet.commands.test);\r\n } else {\r\n targeted = true;\r\n // QUIKTR-1083 (\u00A715.3) \u2014 informational, never blocking: a case with no given/when/then has\r\n // nothing to test, and the runtime already enforces every requiredTests case lands in\r\n // exactly one of a target's automationIds or here, never both, never neither. Folded into\r\n // the same warnings array the overlap-check below already populates and reportBack sends.\r\n if (targeting.skippedCases?.length) {\r\n for (const skipped of targeting.skippedCases) {\r\n const w = `Test case ${skipped.automationId} has no given/when/then \u2014 skipped, no test was written for it.`;\r\n warnings.push(w);\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n }\r\n }\r\n // QUIKTR-1064 \u2014 cheap: two targets whose planStepsImplemented describe the same rule (the\r\n // real fix is pilot.targeting's prompt, an AI Runtime change, not this package's \u2014 see\r\n // overlapCheck.ts). QUIKTR-1081 \u2014 a literal identical instruction now blocks outright: two\r\n // legitimate halves of one change never share the exact same instruction, and PR #23 merged\r\n // 28 seconds after opening on exactly this signal. A near-identical, reworded pair stays a\r\n // non-blocking warning, logged and reported back, same as before.\r\n const overlaps = findOverlappingSteps(targeting.targets);\r\n const blockingOverlaps = overlaps.filter((o) => o.severity === \"identical\");\r\n const softOverlaps = overlaps.filter((o) => o.severity === \"similar\");\r\n if (softOverlaps.length > 0) {\r\n const overlapWarnings = describeOverlapWarnings(softOverlaps);\r\n warnings.push(...overlapWarnings);\r\n for (const w of overlapWarnings) {\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n }\r\n }\r\n if (blockingOverlaps.length > 0) {\r\n throw new Error(\r\n `QuikPilot's generated plan gives two files identical instructions \u2014 ${describeOverlapWarnings(blockingOverlaps).join(\"; \")}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\r\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\r\n // dependencies doesn't depend on which application source files exist, so this is safe, and\r\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\r\n runCommand(packet.commands.setup, \"Setup\");\r\n\r\n // \u00A718 \u2014 built once, from every case claimed by any target in the run, minus the\r\n // NO_BEHAVIOUR skips above. Sent only to code targets (codegen.ts's own else-branch);\r\n // targeting.skippedCases is the same list already folded into warnings just above.\r\n const judgedByPool = buildJudgedByPool(\r\n packet.requiredTests,\r\n targeting.targets,\r\n targeting.skippedCases ?? [],\r\n );\r\n\r\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\r\n // until flushCodegenResults, so there's nothing for the baseline to race against.\r\n const [baseline, results] = await Promise.all([\r\n captureBaselineSnapshot(packet.commands.test),\r\n runCodegen(\r\n packet.gateway,\r\n targeting.targets,\r\n workspaceListing,\r\n packet.requiredTests,\r\n packet.guardrails.deniedPaths,\r\n judgedByPool,\r\n warnings,\r\n contextLog,\r\n outOfScope,\r\n ),\r\n ]);\r\n\r\n generatedResults = results;\r\n\r\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\r\n // written: an invented import is never written to disk at all, matching\r\n // the same all-or-nothing treatment every other codegen failure already\r\n // gets here. Hard failure \u2014 a generation that imports a package this\r\n // repository doesn't have can't be trusted.\r\n const depCheck = checkImportDependencies(\r\n results,\r\n readDeclaredDependencies(results, packet.workspaceRoot),\r\n resolveAliasPrefixes(results, packet.workspaceRoot),\r\n );\r\n if (depCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1081 \u2014 QUIKSPL-5's PR #22: codegen added an undeclared PUT endpoint alongside the\r\n // fix nobody asked for. Checked here for the same reason as the dependency check above \u2014\r\n // in-memory, before anything is written \u2014 against the design's own declared apiChanges.\r\n const scopeCheck = checkApiScope(results, targeting.targets, packet.design?.apiChanges ?? []);\r\n if (scopeCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code exceeds the approved design \u2014 ${describeScopeViolations(scopeCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1315 \u2014 same \"in-memory results, before anything is written\" point as the two checks\r\n // above: a test case claimed against a source-file target instead of the real test file has\r\n // zero coverage even though its id is present, and nothing else here catches that. Uses the\r\n // BASELINE run's JUnit report (already captured above) as the ground truth for which files\r\n // the test runner actually discovers \u2014 never the workspace listing, which includes files the\r\n // runner never looks at.\r\n const placementCheck = checkTestPlacement(targeting.targets, baseline.discoveredFiles);\r\n if (placementCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated tests are not where the test runner will find them \u2014 ${describeTestPlacementViolations(placementCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1402 \u2014 run the generated tests alone on the still-untouched tree and flag a non-Regression\r\n // case that already passes there. After the in-memory checks above (no point spending the time on a\r\n // run that is about to fail) and before the flush (the code files are still the originals). Flag-only:\r\n // it never throws out of here, and a surprise from it must not cost the run.\r\n try {\r\n const baselineCheck = await runBaselineCheck({\r\n targets: targeting.targets,\r\n results,\r\n testFileCmd: packet.commands.testFile,\r\n requiredTestTypes: packet.requiredTestTypes,\r\n });\r\n warnings.push(...baselineCheck.warnings);\r\n baselineFindings = baselineCheck.findings ?? undefined;\r\n } catch (err) {\r\n const message = `Baseline check could not run: ${err instanceof Error ? err.message : String(err)}`;\r\n console.error(message);\r\n warnings.push(message);\r\n }\r\n\r\n // QUIKTR-1333 \u2014 the files QuikPilot actually generated or edited this run, exactly what\r\n // reportToQuikTest's generatedFiles param needs to scope the unmatched-id warning. runCodegen\r\n // is all-or-nothing, so by this point `results` is the complete, successful set \u2014 nothing\r\n // extra needed from targeting.targets.\r\n generatedFilePaths = results.map((r) => r.targetPath);\r\n\r\n flushCodegenResults(results);\r\n try {\r\n runCommand(packet.commands.format, \"Format\");\r\n } catch (err) {\r\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\r\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n runCommand(packet.commands.lint, \"Lint\");\r\n\r\n const after = captureTestSnapshot(packet.commands.test);\r\n finalTestReport = readTestReportBytes();\r\n // QUIKTR-1448 \u2014 before the regression throw below, so a run that then fails still reports it. Warn-only.\r\n vanishedTests = findVanishedTests(baseline, after) ?? undefined;\r\n if (vanishedTests) {\r\n const w = describeVanishedTests(vanishedTests);\r\n warnings.push(w);\r\n console.warn(`QuikPilot test warning (not blocking): ${w}`);\r\n }\r\n const check = checkForRegressions(baseline, after);\r\n if (check.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1315 \u2014 the stronger of the two placement checks: run against the REAL, post-codegen\r\n // JUnit report, so it catches inverted placement regardless of why it happened, including\r\n // whatever checkTestPlacement's baseline-only, loose file-matching missed above.\r\n const coverageCheck = checkAutomationIdCoverage(targeting.targets, after.discoveredAutomationIds);\r\n if (coverageCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated tests were not executed \u2014 ${describeAutomationCoverageViolations(coverageCheck)}`,\r\n );\r\n }\r\n }\r\n } catch (err) {\r\n hardFailure = true;\r\n recordFailure(err);\r\n }\r\n\r\n if (!runToken) {\r\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\r\n return { hardFailure: true };\r\n }\r\n\r\n const quikTestReport = await reportToQuikTest({\r\n resultsUrl: packet?.quikTest?.resultsUrl,\r\n runToken,\r\n githubServerUrl: env.githubServerUrl,\r\n githubRepository: env.githubRepository,\r\n githubRunId: env.githubRunId,\r\n generatedFiles: generatedFilePaths,\r\n });\r\n // QUIKTR-1374 \u2014 the ingest response already knows which generated automationIds matched no\r\n // test case; read it and surface it here instead of letting it disappear once reportToQuikTest\r\n // returns. Reuses the same warnings -> reportBack path QUIKTR-1064's overlap detection already\r\n // uses, which QuikTrack folds into the run's own event timeline \u2014 no new plumbing.\r\n const unmatchedWarning = quikTestReport ? describeUnmatchedAutomationIds(quikTestReport.unmatched) : null;\r\n if (unmatchedWarning) {\r\n warnings.push(unmatchedWarning);\r\n console.warn(`QuikPilot ingest warning (not blocking): ${unmatchedWarning}`);\r\n }\r\n\r\n if (!hardFailure && packet) {\r\n try {\r\n checkGuardrail(packet.guardrails.deniedPaths);\r\n const installationToken = await exchangeForInstallationToken(\r\n env.installationTokenUrl,\r\n runToken,\r\n );\r\n const result = commitAndPush(\r\n packet.branch,\r\n env.runId,\r\n installationToken,\r\n targeted,\r\n packet.issueKey,\r\n packet.issueTitle,\r\n );\r\n branch = result.branch;\r\n } catch (err) {\r\n hardFailure = true;\r\n recordFailure(err);\r\n }\r\n }\r\n\r\n // QUIKTR-1447 \u2014 before the callback, so it exists whether or not the callback succeeds. Only for a run that got as far\r\n // as generating files, and never allowed to change how the run ends.\r\n if (hardFailure && generatedResults.length > 0) {\r\n try {\r\n writeFailureArtifact({\r\n cwd: process.cwd(),\r\n runId: env.runId,\r\n issueKey: packet?.issueKey ?? null,\r\n targets: targetingResult?.outcome === \"TARGETED\" ? targetingResult.targets : [],\r\n results: generatedResults,\r\n testReport: finalTestReport,\r\n failureReasons,\r\n secrets: runToken ? [runToken] : [],\r\n });\r\n } catch (err: unknown) {\r\n console.warn(`::warning::Could not keep the failed run's files: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n\r\n await reportBack({\r\n callbackUrl: env.callbackUrl,\r\n runToken,\r\n status: hardFailure ? \"failed\" : \"completed\",\r\n branch,\r\n warnings,\r\n // Omitted when targeting itself never produced a result (nothing exists to record).\r\n targeting: targetingResult ? buildTargetingRecord(targetingResult, contextLog) : undefined,\r\n baselineFindings,\r\n vanishedTests,\r\n unresolved: failureReasons.length > 0 ? failureReasons : undefined,\r\n });\r\n\r\n return { hardFailure };\r\n}\r\n", "import type { ReadinessCheckEnv } from \"./env\";\r\nimport { runCommand, runTestCommand } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\nimport { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\n/**\r\n * QUIKTR-1084 \u2014 readiness's \"later session\": actually run the customer's `setupCmd`/`testCmd` and\r\n * report whether the run produced a JUnit report the pilot-run path (`quiktest.ts`) will ever\r\n * find. Checked out onto the default branch already by the workflow's own `actions/checkout` step\r\n * \u2014 no packet, no design, no codegen, no commit, no push.\r\n *\r\n * Both command failures are soft here, deliberately unlike `run.ts`'s hard-fails-on-Setup: a\r\n * repo's setup or test suite failing is not what this check is FOR \u2014 it exists purely to answer\r\n * \"if a real run happened, would QuikTest hear about it,\" which only needs the report to exist,\r\n * not the tests to pass.\r\n */\r\nexport interface ReadinessCheckResult {\r\n setupOk: boolean;\r\n testOk: boolean;\r\n junitFound: boolean;\r\n junitPath: string | null;\r\n}\r\n\r\nexport async function runReadinessCheck(env: ReadinessCheckEnv): Promise<void> {\r\n let setupOk = true;\r\n try {\r\n runCommand(env.setupCmd || null, \"Setup\");\r\n } catch (err) {\r\n setupOk = false;\r\n console.error(err instanceof Error ? err.message : String(err));\r\n }\r\n\r\n const testOutcome = runTestCommand(env.testCmd);\r\n const testOk = testOutcome === \"success\";\r\n\r\n const junitPath = findJUnitReport();\r\n const result: ReadinessCheckResult = {\r\n setupOk,\r\n testOk,\r\n junitFound: junitPath !== null,\r\n junitPath,\r\n };\r\n\r\n try {\r\n const res = await fetch(env.readinessCallbackUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${env.readinessToken}`, \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(result),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Readiness callback POST failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n } catch (err) {\r\n // Same \"never throws\" posture as reportToQuikTest/reportBack \u2014 the job's own log is the\r\n // fallback record if even this fails. The expiry sweep readiness.ts will need (mirroring\r\n // dispatch.ts's DISPATCHING-expiry sweep) is what notices a dry run stuck in RUNNING.\r\n console.warn(\r\n `::warning::QuikPilot readiness check failed to report its result: ${err instanceof Error ? err.message : String(err)}`,\r\n );\r\n }\r\n}\r\n", "import { readRunnerEnv } from \"./env\";\r\nimport { run } from \"./run\";\r\nimport { runReadinessCheck } from \"./readinessCheck\";\r\n\r\nconst env = readRunnerEnv();\r\n\r\n// QUIKTR-1084 \u2014 narrows the RunnerEnv union before either branch runs; run()/runReadinessCheck()\r\n// each take only their own variant, not the union, so this `if` is what makes that safe.\r\nconst task =\r\n env.mode === \"readiness_check\"\r\n ? runReadinessCheck(env).then(() => ({ hardFailure: false }))\r\n : run(env);\r\n\r\ntask\r\n .then(({ hardFailure }) => {\r\n process.exitCode = hardFailure ? 1 : 0;\r\n })\r\n .catch((err) => {\r\n // reportBack/the readiness callback itself throwing is the one failure mode neither branch can\r\n // recover from internally \u2014 still exit non-zero so the raw Actions UI shows the run as failed.\r\n console.error(err instanceof Error ? err.message : String(err));\r\n process.exitCode = 1;\r\n });\r\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["env", "resolve", "import_node_child_process", "import_node_path", "relative", "path", "path", "import_node_fs", "import_node_path", "env", "import_node_fs", "import_node_fs", "import_node_path", "readFileSync", "import_node_child_process", "import_node_fs", "import_node_path", "import_node_fs", "isTestTarget", "import_node_fs", "import_node_path", "import_node_fs", "import_node_path", "CONTRACT_VERSION", "record", "env", "env"]
|
|
3
|
+
"sources": ["../src/env.ts", "../src/quiktrackError.ts", "../src/callback.ts", "../src/commands.ts", "../src/git.ts", "../src/commit.ts", "../src/codegen.ts", "../src/deniedPaths.ts", "../src/editsApply.ts", "../src/runtimeReplyError.ts", "../src/envelope.ts", "../src/importContext.ts", "../src/retryFetch.ts", "../src/dependencyCheck.ts", "../src/guardrail.ts", "../src/installationToken.ts", "../src/oidc.ts", "../src/overlapCheck.ts", "../src/packet.ts", "../src/phase0.ts", "../src/quiktest.ts", "../src/baselineCheck.ts", "../src/regressionCheck.ts", "../src/failureArtifact.ts", "../src/failureReason.ts", "../src/scopeCheck.ts", "../src/targeting.ts", "../src/targetingErrors.ts", "../src/targetingMode.ts", "../src/targetingPaths.ts", "../src/targetingTools.ts", "../src/tokenEstimate.ts", "../src/targetingLoop.ts", "../src/targetingRecord.ts", "../src/testPlacementCheck.ts", "../src/tokenExchange.ts", "../src/vanishedTests.ts", "../src/run.ts", "../src/readinessCheck.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/** The `workflow_dispatch` inputs QuikTrack's `dispatch.ts` sends, unchanged by QUIKTR-572 \u2014 the\r\n * generated workflow file still passes them through as job-level env vars under these exact\r\n * names. QUIKTR-805: `runToken`/`RUN_TOKEN` (a bearer, visible in the Actions UI as a dispatch\r\n * input) was replaced with `tokenUrl`/`TOKEN_URL` \u2014 the runner now exchanges a GitHub OIDC ID\r\n * token there for a run token at runtime; see `oidc.ts` and `tokenExchange.ts`. QUIKTR-804 adds\r\n * `installationTokenUrl`/`INSTALLATION_TOKEN_URL` \u2014 the run token is exchanged there for a\r\n * repo-scoped GitHub push credential; see `installationToken.ts`. */\r\nexport interface PilotRunEnv {\r\n mode: \"run\";\r\n runId: string;\r\n callbackUrl: string;\r\n packetUrl: string;\r\n tokenUrl: string;\r\n installationTokenUrl: string;\r\n /** GitHub Actions built-ins, read directly from `process.env` rather than threaded through here\r\n * individually. */\r\n githubRunId: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n}\r\n\r\n/**\r\n * QUIKTR-1084 \u2014 the readiness dry-run branch. Deliberately carries none of `PilotRunEnv`'s\r\n * fields: no packet fetch, no OIDC/run-token exchange, no design/codegen/commit/push. It only\r\n * needs the two commands to run and where to report the result.\r\n *\r\n * `readinessToken`/`READINESS_TOKEN` travels as a plain dispatch input, unlike the pilot-run\r\n * token \u2014 deliberately. QUIKTR-805 stopped doing that for the run token because a leaked one\r\n * could spend money through the LLM gateway; this token can only POST a\r\n * `{ junitFound, junitPath }` result for the one `QtPilotConfig` it was minted for (see\r\n * `readiness-dispatch.ts`), which is the same blast radius the pre-805 run token had. Splitting\r\n * out a second OIDC-exchange endpoint to protect a credential this narrow isn't worth the new\r\n * surface.\r\n */\r\nexport interface ReadinessCheckEnv {\r\n mode: \"readiness_check\";\r\n readinessToken: string;\r\n readinessCallbackUrl: string;\r\n setupCmd: string;\r\n testCmd: string;\r\n githubRunId: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n}\r\n\r\nexport type RunnerEnv = PilotRunEnv | ReadinessCheckEnv;\r\n\r\nexport function required(name: string, value: string | undefined): string {\r\n if (!value) {\r\n throw new Error(`Missing required environment variable: ${name}`);\r\n }\r\n return value;\r\n}\r\n\r\nexport function readRunnerEnv(env: NodeJS.ProcessEnv = process.env): RunnerEnv {\r\n const githubRunId = required(\"GITHUB_RUN_ID\", env.GITHUB_RUN_ID);\r\n const githubServerUrl = env.GITHUB_SERVER_URL ?? \"https://github.com\";\r\n const githubRepository = required(\"GITHUB_REPOSITORY\", env.GITHUB_REPOSITORY);\r\n\r\n if (env.MODE === \"readiness_check\") {\r\n return {\r\n mode: \"readiness_check\",\r\n readinessToken: required(\"READINESS_TOKEN\", env.READINESS_TOKEN),\r\n readinessCallbackUrl: required(\"READINESS_CALLBACK_URL\", env.READINESS_CALLBACK_URL),\r\n setupCmd: env.SETUP_CMD ?? \"\",\r\n testCmd: required(\"TEST_CMD\", env.TEST_CMD),\r\n githubRunId,\r\n githubServerUrl,\r\n githubRepository,\r\n };\r\n }\r\n\r\n return {\r\n mode: \"run\",\r\n runId: required(\"RUN_ID\", env.RUN_ID),\r\n callbackUrl: required(\"CALLBACK_URL\", env.CALLBACK_URL),\r\n packetUrl: required(\"PACKET_URL\", env.PACKET_URL),\r\n tokenUrl: required(\"TOKEN_URL\", env.TOKEN_URL),\r\n installationTokenUrl: required(\"INSTALLATION_TOKEN_URL\", env.INSTALLATION_TOKEN_URL),\r\n githubRunId,\r\n githubServerUrl,\r\n githubRepository,\r\n };\r\n}\r\n", "/**\r\n * QUIKTR-1080 \u2014 QuikTrack's internal pilot routes return a stable `reason_code` in the body on\r\n * every `pilotError()`-shaped failure (401/403/409/429); the generic 500 catch-all has none, and a\r\n * non-2xx response isn't guaranteed to be JSON at all (a proxy/gateway error can produce a\r\n * non-JSON body). Best effort: falls back to bare status/statusText when `reason_code` is absent\r\n * or the body doesn't parse \u2014 never throws itself.\r\n *\r\n * Unrelated to envelope.ts's `errorCode` \u2014 that's the AI Runtime's own, separate `/ai/execute`\r\n * contract. Two different services, two different field names; not to be conflated.\r\n */\r\nexport async function describeQuikTrackFailure(res: Response): Promise<string> {\r\n try {\r\n const body = await res.json();\r\n if (body && typeof body === \"object\" && typeof (body as Record<string, unknown>).reason_code === \"string\") {\r\n return `${res.status} ${res.statusText} (${(body as Record<string, unknown>).reason_code})`;\r\n }\r\n } catch {\r\n // not JSON, no json() method at all, or already consumed \u2014 fall back below\r\n }\r\n return `${res.status} ${res.statusText}`;\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\nimport type { BaselineFindings } from \"./baselineCheck\";\r\nimport type { TargetingRecord } from \"./targetingRecord\";\r\nimport type { VanishedTests } from \"./vanishedTests\";\r\n\r\nexport type RunStatus = \"completed\" | \"failed\";\r\n\r\n/** Always fires, regardless of what failed upstream \u2014 a run that fails silently is worse than one\r\n * that fails loudly. `branch` is omitted entirely (not sent as null/empty) when no push happened,\r\n * matching the original `jq ... | with_entries(select(.value != null and .value != \"\"))`. Same\r\n * treatment for `warnings` (QUIKTR-1064) \u2014 non-fatal findings like a targeting overlap, omitted\r\n * when there are none rather than sent as an empty array. */\r\nexport async function reportBack(params: {\r\n callbackUrl: string;\r\n runToken: string;\r\n status: RunStatus;\r\n branch?: string;\r\n warnings?: string[];\r\n /** QUIKTR-1421 \u2014 what pilot.targeting decided (paths and case ids only). Omitted when targeting never\r\n * produced a result; an older QuikTrack strips the unknown key silently. */\r\n targeting?: TargetingRecord;\r\n /** QUIKTR-1402 \u2014 test cases that passed against the unmodified code (ids only). Omitted when the check\r\n * flagged nothing or did not run; QuikTrack validates it separately and drops a bad one. */\r\n baselineFindings?: BaselineFindings;\r\n /** QUIKTR-1448 \u2014 tests that ran before the change and are missing from the final report. Test titles are the\r\n * customer's own text, so QuikTrack puts them in the pull request description only and stores none. Omitted when\r\n * nothing is missing; an older QuikTrack ignores the unknown key. */\r\n vanishedTests?: VanishedTests;\r\n /** Why a failed run stopped (already written on one line, cut and scrubbed of credentials). Omitted when there is\r\n * nothing to say; an older QuikTrack accepts it and ignores it for a failed run. */\r\n unresolved?: string[];\r\n}): Promise<void> {\r\n const { callbackUrl, runToken, status, branch, warnings, targeting, baselineFindings, vanishedTests, unresolved } = params;\r\n const body: Record<string, unknown> = { status };\r\n if (branch) body.branch = branch;\r\n if (warnings && warnings.length > 0) body.warnings = warnings;\r\n if (unresolved && unresolved.length > 0) body.unresolved = unresolved;\r\n if (targeting) body.targeting = targeting;\r\n if (baselineFindings) body.baselineFindings = baselineFindings;\r\n if (vanishedTests) body.vanishedTests = vanishedTests;\r\n const res = await fetch(callbackUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(body),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Report back to QuikTrack failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n}\r\n", "import { execSync, spawn } from \"node:child_process\";\r\n\r\n/** Runs a packet-supplied command through bash \u2014 same interpreter GitHub's own `run:` steps used,\r\n * so a command written against that shell (e.g. `set -o pipefail`-reliant) behaves the same way.\r\n * A null/empty command is a no-op, matching the original `[ -n \"$CMD\" ]` guard. */\r\nexport function runCommand(command: string | null, label: string): void {\r\n if (!command) return;\r\n try {\r\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n } catch (err) {\r\n throw new Error(`${label} failed: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n}\r\n\r\nexport type TestOutcome = \"success\" | \"failure\";\r\n\r\n/** The Test step alone is soft \u2014 a failing suite must not hide the rest of the run (guardrail,\r\n * commit, push) from happening, and must not flip the final callback to `failed`. QuikTest owns\r\n * per-test outcomes; this is only ever logged, never reported. QUIKTR-1036: this is still correct\r\n * for a NO_TARGET run (nothing was generated, so there's nothing to regress against) \u2014 a\r\n * codegen'd run's Test step is decided by regressionCheck.ts instead, using the async twin below. */\r\nexport function runTestCommand(command: string | null): TestOutcome {\r\n if (!command) return \"success\";\r\n try {\r\n execSync(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n return \"success\";\r\n } catch {\r\n return \"failure\";\r\n }\r\n}\r\n\r\n/** Same contract as `runTestCommand`, but non-blocking: `execSync` blocks the event loop, which\r\n * would serialize the baseline test run behind (or in front of) codegen's network-bound calls\r\n * instead of letting them overlap. QUIKTR-1036 \u2014 the baseline run is the only caller today. */\r\nexport function runTestCommandAsync(command: string | null): Promise<TestOutcome> {\r\n if (!command) return Promise.resolve(\"success\");\r\n return new Promise((resolve) => {\r\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\" });\r\n child.on(\"exit\", (code) => resolve(code === 0 ? \"success\" : \"failure\"));\r\n child.on(\"error\", () => resolve(\"failure\"));\r\n });\r\n}\r\n\r\nexport type TimedRunOutcome = \"exited\" | \"timeout\" | \"error\";\r\n\r\n/**\r\n * QUIKTR-1402 \u2014 runs a command through bash with a hard time limit, for the baseline check's single-file\r\n * run. A command that HANGS produces no error, so \"any failure means no flag\" cannot cover it: without a\r\n * limit it would hold the run until the job's own limit and look like QuikPilot being slow. The exit code\r\n * is deliberately not reported \u2014 a failing test is the normal outcome of running a generated test against\r\n * code that does not have the change yet; only \"finished\", \"timed out\" and \"could not start\" matter.\r\n *\r\n * The command runs in its own process group (`detached`) so a timeout can kill the test runner AND\r\n * whatever it started; killing only the shell would leave the runner holding the job open.\r\n */\r\nexport function runCommandWithTimeout(command: string, timeoutMs: number): Promise<TimedRunOutcome> {\r\n return new Promise((resolve) => {\r\n let settled = false;\r\n const finish = (outcome: TimedRunOutcome) => {\r\n if (settled) return;\r\n settled = true;\r\n clearTimeout(timer);\r\n resolve(outcome);\r\n };\r\n const child = spawn(command, { shell: \"/bin/bash\", stdio: \"inherit\", detached: true });\r\n const timer = setTimeout(() => {\r\n try {\r\n if (child.pid !== undefined) process.kill(-child.pid, \"SIGKILL\");\r\n else child.kill(\"SIGKILL\");\r\n } catch {\r\n try {\r\n child.kill(\"SIGKILL\");\r\n } catch {\r\n // already gone\r\n }\r\n }\r\n finish(\"timeout\");\r\n }, timeoutMs);\r\n child.on(\"exit\", () => finish(\"exited\"));\r\n child.on(\"error\", () => finish(\"error\"));\r\n });\r\n}\r\n", "import { execFileSync } from \"node:child_process\";\r\n\r\n/** Thin wrapper around `execFileSync` \u2014 args passed as an array, never through a shell, so a\r\n * branch name or guardrail pattern can never be interpreted as shell syntax. `extraEnv` layers\r\n * on top of the inherited environment; every existing call site is unaffected since it defaults\r\n * to empty. */\r\nfunction git(args: string[], extraEnv: NodeJS.ProcessEnv = {}): string {\r\n return execFileSync(\"git\", args, {\r\n encoding: \"utf8\",\r\n env: { ...process.env, ...extraEnv },\r\n }).trim();\r\n}\r\n\r\nexport function currentBranch(): string {\r\n return git([\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\r\n}\r\n\r\n/** Only fetches + checks out when the packet names a target branch different from the one the\r\n * workflow_dispatch already put us on \u2014 dispatch always runs against the default branch (the\r\n * only place `workflow_dispatch` can find the file), but the PR base may differ. */\r\nexport function checkoutTargetBranch(targetBranch: string | null): void {\r\n if (!targetBranch || targetBranch === currentBranch()) return;\r\n git([\"fetch\", \"origin\", targetBranch]);\r\n git([\"checkout\", targetBranch]);\r\n}\r\n\r\nexport function addAll(): void {\r\n git([\"add\", \"-A\"]);\r\n}\r\n\r\n/** `:(glob)` pathspec \u2014 same semantics `**` needs that a hand-rolled glob-to-regex would risk\r\n * getting wrong. */\r\nexport function diffCachedNamesMatching(pattern: string): string[] {\r\n const out = git([\"diff\", \"--cached\", \"--name-only\", \"--\", `:(glob)${pattern}`]);\r\n return out ? out.split(\"\\n\").filter(Boolean) : [];\r\n}\r\n\r\n/** Tracked files under `pathspec`, relative to cwd \u2014 same cwd every other export here already\r\n * assumes is the checkout root, so a caller can feed these straight to readFileSync/writeFileSync\r\n * with no translation. QUIKTR-1035 \u2014 `pathspec` is always concrete; \"null means repo root\" is\r\n * targeting.ts's workspaceRoot concept, not a generic git one. */\r\nexport function listFiles(pathspec: string): string[] {\r\n const out = git([\"ls-files\", \"--\", pathspec]);\r\n return out ? out.split(\"\\n\").filter(Boolean) : [];\r\n}\r\n\r\nexport function hasStagedChanges(): boolean {\r\n try {\r\n execFileSync(\"git\", [\"diff\", \"--cached\", \"--quiet\"]);\r\n return false;\r\n } catch {\r\n return true;\r\n }\r\n}\r\n\r\nexport function configureCommitIdentity(): void {\r\n git([\"config\", \"user.name\", \"quikpilot[bot]\"]);\r\n git([\"config\", \"user.email\", \"quikpilot@users.noreply.github.com\"]);\r\n}\r\n\r\nexport function checkoutNewBranch(branch: string): void {\r\n git([\"checkout\", \"-b\", branch]);\r\n}\r\n\r\nexport function commit(message: string): void {\r\n git([\"commit\", \"-m\", message]);\r\n}\r\n\r\n/**\r\n * Push, authenticated with a repo-scoped GitHub installation token (QUIKTR-804, D16) rather than\r\n * whatever ambient credential checkout configured. `x-access-token:<token>` Basic-auth, GitHub's\r\n * documented scheme for installation tokens over HTTPS git.\r\n *\r\n * Carried via `GIT_CONFIG_COUNT`/`GIT_CONFIG_KEY_0`/`GIT_CONFIG_VALUE_0` env vars rather than a\r\n * `-c http.extraheader=...` argv flag or a `.git/config` write: env vars are not visible to `ps`,\r\n * argv is \u2014 the same class of exposure `packet.ts`'s own header comment already avoids for this\r\n * runner's other credential. Scoped to this one invocation only; never persisted.\r\n *\r\n * QUIKTR-943 rehearsal, 7.0.1 \u2014 the key MUST be `http.https://github.com/.extraheader`\r\n * (URL-scoped), not the unscoped `http.extraheader`. `actions/checkout` persists its own\r\n * credential under the URL-scoped key, pointing at the job's ambient token (contents: read since\r\n * QUIKTR-804 dropped it). Git prefers the more specific URL-scoped key, so an unscoped header here\r\n * silently loses to checkout's read-only one \u2014 the push then fails with \"denied to\r\n * github-actions[bot]\" even though this token itself has write access and the exchange succeeded.\r\n *\r\n * QUIKTR-943 rehearsal, 7.0.2 \u2014 url-scoping alone re-broke the push a second way:\r\n * `http.<url>.extraheader` is multi-valued (git appends, it doesn't replace), so checkout's\r\n * `.git/config` entry and this call's env-var entry are BOTH sent, and GitHub 400s with\r\n * `Duplicate header: \"Authorization\"`. `--unset-all` clears checkout's entry from `.git/config`\r\n * first, so our env-var header (scoped to this one invocation, never written to disk) is the only\r\n * one on the wire. Tolerates the key already being absent (exit 5) \u2014 nothing to clear is not a\r\n * failure, and a workflow that ever runs with `persist-credentials: false` shouldn't crash here.\r\n */\r\nfunction clearCheckoutExtraHeader(): void {\r\n try {\r\n git([\"config\", \"--unset-all\", \"http.https://github.com/.extraheader\"]);\r\n } catch (err: unknown) {\r\n const status = (err as { status?: number }).status;\r\n if (status !== 5) throw err;\r\n }\r\n}\r\n\r\nexport function push(branch: string, installationToken: string): void {\r\n clearCheckoutExtraHeader();\r\n const basicAuth = Buffer.from(`x-access-token:${installationToken}`).toString(\"base64\");\r\n git([\"push\", \"--set-upstream\", \"origin\", branch], {\r\n GIT_CONFIG_COUNT: \"1\",\r\n GIT_CONFIG_KEY_0: \"http.https://github.com/.extraheader\",\r\n GIT_CONFIG_VALUE_0: `AUTHORIZATION: basic ${basicAuth}`,\r\n });\r\n}\r\n", "import {\r\n checkoutNewBranch,\r\n commit,\r\n configureCommitIdentity,\r\n hasStagedChanges,\r\n push,\r\n} from \"./git\";\r\n\r\nexport interface CommitResult {\r\n changed: boolean;\r\n branch?: string;\r\n}\r\n\r\n/**\r\n * QUIKTR-1067 \u2014 \"QuikPilot Phase 0 skeleton\" used to be hardcoded for every commit, including one\r\n * carrying a real generated fix (PR #19) \u2014 indistinguishable from the genuinely-empty NO_TARGET\r\n * marker commit without opening the diff, and git history is permanent. `targeted: false` is the\r\n * one case that message is still accurate for. `issueKey`/`issueTitle` null with `targeted: true`\r\n * is defensive only \u2014 dispatch never reaches commit before Gate 1, which always attaches an issue.\r\n */\r\nexport function buildCommitMessage(\r\n runId: string,\r\n targeted: boolean,\r\n issueKey: string | null,\r\n issueTitle: string | null,\r\n): string {\r\n if (!targeted) return `QuikPilot Phase 0 skeleton (run ${runId})`;\r\n if (issueKey && issueTitle) return `${issueKey}: ${issueTitle}\\n\\nQuikPilot run ${runId}`;\r\n return `QuikPilot generated changes (run ${runId})`;\r\n}\r\n\r\n/** Runs regardless of the Test step's outcome \u2014 a failing suite must not hide the generated diff\r\n * from a reviewer (the whole reason Test alone is a soft failure). Only reached when Setup, Lint,\r\n * and the guardrail check all passed. The branch name comes from the packet, not `runId`: QuikTrack\r\n * already computed and stored it, and two sources for one value will eventually disagree.\r\n * `installationToken` (QUIKTR-804) is the repo-scoped GitHub credential the push authenticates\r\n * with \u2014 see git.ts's `push` for why. */\r\nexport function commitAndPush(\r\n branch: string | null,\r\n runId: string,\r\n installationToken: string,\r\n targeted: boolean,\r\n issueKey: string | null,\r\n issueTitle: string | null,\r\n): CommitResult {\r\n if (!hasStagedChanges()) return { changed: false };\r\n if (!branch) {\r\n throw new Error(\"packet carried no branch name\");\r\n }\r\n configureCommitIdentity();\r\n checkoutNewBranch(branch);\r\n commit(buildCommitMessage(runId, targeted, issueKey, issueTitle));\r\n push(branch, installationToken);\r\n return { changed: true, branch };\r\n}\r\n", "import { readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\r\nimport { dirname } from \"node:path\";\r\nimport { findDeniedContextPath, matchesDeniedPath } from \"./deniedPaths\";\r\nimport { applyEdits, detectLineEnding, fromLf, toLf, type AnchorRefusal, type LineEnding } from \"./editsApply\";\r\nimport { checkHardFailure, unwrapExecute } from \"./envelope\";\r\nimport { ACTIONABLE_IMPORT_SKIPS, collectImportContext } from \"./importContext\";\r\nimport { RuntimeReplyError } from \"./runtimeReplyError\";\r\nimport type { PilotPacket } from \"./packet\";\r\nimport { fetchWithRetry } from \"./retryFetch\";\r\nimport type { CodegenContextRecord } from \"./targetingRecord\";\r\nimport type { PilotTarget, SkippedCase } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-823 \u2014 one `/ai/execute` call per file, proven working against a real request this\r\n * morning (Suyash): `x-run-token` header carrying the packet's `gateway.token`, full file content\r\n * in and out. Never a patch \u2014 a failed apply would cost a whole extra call against a tight budget,\r\n * and a patch that can't apply is exactly the kind of failure this loop can't safely paper over.\r\n *\r\n * QUIKTR-1035 \u2014 `targets` (with per-target `planStepsImplemented`) replaces the old\r\n * `targetPaths: string[]` plus a single `design`-derived `planSteps` shared across every file.\r\n * Merging targeting's per-target steps back into one shared list would destroy the reason they're\r\n * per-target: the route file and the service file need different instructions.\r\n *\r\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\r\n *\r\n * The first failed or REFUSED file throws, and `run.ts`'s existing hard-failure handling takes it\r\n * from there: no branch, no pull request. A pull request is a claim the work is done; a\r\n * partially-applied change compiles sometimes, passes tests sometimes, and looks complete either\r\n * way. Already decided twice elsewhere for the same reason \u2014 Gate 1's spec commit is one\r\n * transaction, and `create_issue` with `testCases` is explicitly all-or-nothing. Retrying the\r\n * failed file instead of discarding the rest is the better long-run answer and belongs with\r\n * self-heal (Phase 3, unscoped) \u2014 not silently attempted here.\r\n *\r\n * `CODEGEN_FILE_TOO_LARGE` and `CODEGEN_CONTEXT_TOO_LARGE` are the AI Runtime's own distinct error\r\n * codes, checked on their side before dispatch \u2014 retrying hits the identical wall every time, so\r\n * both are deliberately not retried, same as every other failure here.\r\n *\r\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\r\n *\r\n * pilot.targeting now names, per target, which other files pilot.codegen should read\r\n * (`target.contextPaths`) \u2014 replacing the old `siblingContent` guess (nearest file by directory),\r\n * which only ever ran for NEW_FILE targets and was never more than a stated assumption about this\r\n * repo's own layout. `contextContents: [{ path, content }]` is now sent for EXISTING targets too,\r\n * not just NEW_FILE. Empty/absent contextPaths means empty contextContents \u2014 no fallback.\r\n * `workspaceListing` still goes out for NEW_FILE only, unchanged.\r\n *\r\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\r\n *\r\n * `runCodegen` no longer writes anything \u2014 it collects `{targetPath, newContent}` in memory and\r\n * `flushCodegenResults` writes them all, only once every call has succeeded. Two independent\r\n * reasons: it makes all-or-nothing literally true for the working tree, not just the pull request\r\n * (today a failure on file 3 leaves files 1-2 already written even though the throw stops the\r\n * commit); and it lets the test baseline run against an untouched tree while codegen's network-\r\n * bound calls are still in flight (QUIKTR-1036 is what actually wires that concurrency up \u2014 this\r\n * only makes it possible).\r\n */\r\nconst FILE_TOO_LARGE_CODE = \"CODEGEN_FILE_TOO_LARGE\";\r\nconst CONTEXT_TOO_LARGE_CODE = \"CODEGEN_CONTEXT_TOO_LARGE\";\r\n/** \u00A716.7 \u2014 the AI Runtime's OWN output-cap guard telling us directly, distinct from\r\n * `looksLikeTruncatedRewrite` below (this file's interim heuristic guess at the same problem). */\r\nconst OUTPUT_TOO_LARGE_CODE = \"CODEGEN_OUTPUT_TOO_LARGE\";\r\nconst NOT_RETRIED_CODES = new Set([FILE_TOO_LARGE_CODE, CONTEXT_TOO_LARGE_CODE, OUTPUT_TOO_LARGE_CODE]);\r\n/** \u00A718.8.1 \u2014 the ONE retried refusal in this file, deliberately not in `NOT_RETRIED_CODES` above:\r\n * unlike the three sibling TOO_LARGE codes (which hit the identical wall on any retry), this one\r\n * is retried exactly once, with `judgedBy` narrowed to only the cases a test target's own\r\n * `contextPaths` ties to this code target \u2014 see `narrowJudgedByForTarget` below. */\r\nconst JUDGED_BY_TOO_LARGE_CODE = \"CODEGEN_JUDGED_BY_TOO_LARGE\";\r\n\r\n/**\r\n * QUIKTR-1419 \u2014 a test target is written against whatever files pilot.targeting listed for it (model\r\n * output), so it can be handed nothing of the code the run is changing. The runner therefore also gives it\r\n * the run's OTHER existing code targets. Bounded on purpose (Suyash): files changed in this run only, never\r\n * the files THEY import.\r\n *\r\n * QUIKTR-1454 \u2014 separately, EVERY existing target is also shown the files IT imports, one hop (importContext.ts).\r\n * That is a different rule from the one above, not an exception to it: an import is a fact the file states,\r\n * so it is parsed rather than left to targeting's judgement (the first real 9.0.0 run failed twice on a file\r\n * targeting never listed). Suyash, 5 Oct: one hop, what was added and skipped is logged with the reason, and\r\n * targeting's own list is never replaced. The run files above still never bring THEIR imports with them.\r\n *\r\n * The contract states no numeric limit for CODEGEN_CONTEXT_TOO_LARGE (only 200,000 chars for\r\n * `currentContent`), and that budget is shared with `currentContent` and `workspaceListing`. These are our\r\n * own conservative numbers, in characters like every other runner number (real targets seen: ~38.5k and\r\n * ~39.5k). Going over skips a file; it never fails the run.\r\n */\r\nconst MAX_ADDED_FILE_CHARS = 40_000;\r\nconst MAX_ADDED_CONTEXT_CHARS = 60_000;\r\n\r\nexport interface AddedContext {\r\n entries: { path: string; content: string }[];\r\n skipped: { path: string; reason: \"too large\" | \"over budget\" | \"unreadable\" }[];\r\n}\r\n\r\n/**\r\n * The extra `contextContents` entries for one target. Empty unless it is a TEST target (one with\r\n * `automationIds`); a code target's context stays exactly what targeting asked for. Candidates are the run's\r\n * other EXISTING targets that are not tests: a NEW_FILE has nothing on disk yet, and another test file adds\r\n * size for no help. `alreadyNamed` are the paths targeting already listed, so nothing is sent twice.\r\n *\r\n * Content is what is on disk NOW, i.e. before this run's edit \u2014 writes are buffered until every call has\r\n * succeeded. A route the change is adding is therefore visible to the test only through the plan steps.\r\n */\r\nexport function collectRunContext(\r\n target: PilotTarget,\r\n targets: PilotTarget[],\r\n alreadyNamed: Set<string>,\r\n deniedPaths: string[],\r\n readFile: (path: string) => string = (p) => readFileSync(p, \"utf8\"),\r\n): AddedContext {\r\n const added: AddedContext = { entries: [], skipped: [] };\r\n if (!target.automationIds?.length) return added;\r\n\r\n const seen = new Set(alreadyNamed);\r\n seen.add(target.path);\r\n let total = 0;\r\n for (const candidate of targets) {\r\n if (candidate.kind !== \"EXISTING\" || candidate.automationIds?.length) continue;\r\n if (seen.has(candidate.path)) continue;\r\n seen.add(candidate.path);\r\n // validateTarget already rejects a denied target, so this is defence in depth: a path in context is\r\n // read and sent to the LLM provider.\r\n if (matchesDeniedPath(candidate.path, deniedPaths)) continue;\r\n\r\n let content: string;\r\n try {\r\n content = readFile(candidate.path);\r\n } catch {\r\n added.skipped.push({ path: candidate.path, reason: \"unreadable\" });\r\n continue;\r\n }\r\n if (content.length > MAX_ADDED_FILE_CHARS) {\r\n added.skipped.push({ path: candidate.path, reason: \"too large\" });\r\n } else if (total + content.length > MAX_ADDED_CONTEXT_CHARS) {\r\n added.skipped.push({ path: candidate.path, reason: \"over budget\" });\r\n } else {\r\n total += content.length;\r\n added.entries.push({ path: candidate.path, content });\r\n }\r\n }\r\n return added;\r\n}\r\n\r\n/**\r\n * \u00A716.7 \u2014 interim runner-side guard, live under \u00A715 today (not gated on self-heal or on the AI\r\n * Runtime's own `CODEGEN_OUTPUT_TOO_LARGE` check, which isn't deployed yet). Codegen's output is\r\n * capped around 8,192 tokens; `CODEGEN_FILE_TOO_LARGE` only checks the ~200k-char *input*, so a\r\n * rewrite of a file well under that can still get truncated on the way out. The dangerous case is\r\n * a retry that comes back as valid, `success: true` JSON with the file quietly abbreviated \u2014\r\n * codegen's contract is that anything missing from `newContent` is deleted, so that reads as a\r\n * clean success while silently destroying code. \u00A716.7 names this exact heuristic as QuikTrack's\r\n * own stopgap until the real guard (a pre-dispatch prediction plus a finish-reason check) ships on\r\n * the runtime side.\r\n */\r\nconst SUSPECT_PLACEHOLDER_RE =\r\n /rest(?: of the)? (?:file|code) unchanged|remainder unchanged|\\/\\/\\s*\\.\\.\\.\\s*(?:rest|remaining)/i;\r\n/** Below 60% of its original length, an EXISTING rewrite is suspect rather than a real edit \u2014 a\r\n * targeted fix (planStepsImplemented) trims, it doesn't gut a file to a stub. Raised from 0.5 to\r\n * 0.6 after the AI Runtime's 2026-09-24 incident: a real pilot-chat.ts rewrite came back 38,500 ->\r\n * 22,585 chars (58.67% remaining) with success: true and no placeholder text \u2014 the old 0.5 ratio\r\n * only fires below 50% remaining, so that exact silent deletion sailed through undetected. */\r\nconst SUSPECT_LENGTH_DROP_RATIO = 0.6;\r\n/** A drop in character count can hide behind reformatting (fewer, longer lines) \u2014 this catches\r\n * the opposite failure: a rewrite that removes a large share of *lines* without a matching drop\r\n * in characters. 30% is a deliberately conservative starting point, not a calibrated number \u2014 no\r\n * incident has been observed on this signal alone yet. Tighten once real call metrics exist. */\r\nconst SUSPECT_REMOVED_LINE_RATIO = 0.3;\r\n/** Below this many lines, the multiset diff's \"changed line looks like removed+added\" blind spot\r\n * makes the ratio check unreliable \u2014 skip it rather than false-positive on small/single-line files. */\r\nconst MIN_LINES_FOR_REMOVED_LINE_CHECK = 10;\r\n/** Exported symbols removed silently are exactly the \"code vanishes, response still looks valid\"\r\n * failure mode \u2014 TS/JS only, since this parses no grammar beyond an `export` declaration. */\r\nconst JS_TS_EXTENSION_RE = /\\.(?:ts|tsx|js|jsx|mjs|cjs)$/;\r\nconst EXPORTED_SYMBOL_RE =\r\n /^export\\s+(?:default\\s+)?(?:async\\s+)?(?:function\\*?|class|const|let|var|interface|type|enum)\\s+([A-Za-z_$][\\w$]*)/gm;\r\n\r\n/** Language-neutral, line-based multiset diff \u2014 not an LCS/AST diff. Counts lines present in\r\n * `currentContent` with no matching occurrence left in `newContent`; good enough to flag \"lines\r\n * vanished\" without claiming to be a minimal diff. */\r\nfunction countRemovedLines(currentContent: string, newContent: string): number {\r\n const remaining = new Map<string, number>();\r\n for (const line of newContent.split(\"\\n\")) {\r\n remaining.set(line, (remaining.get(line) ?? 0) + 1);\r\n }\r\n let removed = 0;\r\n for (const line of currentContent.split(\"\\n\")) {\r\n const count = remaining.get(line) ?? 0;\r\n if (count > 0) {\r\n remaining.set(line, count - 1);\r\n } else {\r\n removed++;\r\n }\r\n }\r\n return removed;\r\n}\r\n\r\nfunction extractExportedSymbols(content: string): Set<string> {\r\n const symbols = new Set<string>();\r\n for (const match of content.matchAll(EXPORTED_SYMBOL_RE)) {\r\n symbols.add(match[1]);\r\n }\r\n return symbols;\r\n}\r\n\r\n/** Symbols removed by the rewrite that the plan text never names \u2014 a naive substring check, not a\r\n * reference-tracking one: it undercounts (a symbol renamed to match a plan word would slip past)\r\n * rather than overcounts, which is the right side to err on for a hard-failing guard. */\r\nfunction removedUnexplainedSymbols(targetPath: string, planText: string, currentContent: string, newContent: string): string[] {\r\n if (!JS_TS_EXTENSION_RE.test(targetPath)) return [];\r\n const before = extractExportedSymbols(currentContent);\r\n const after = extractExportedSymbols(newContent);\r\n const lowerPlan = planText.toLowerCase();\r\n return [...before].filter((symbol) => !after.has(symbol) && !lowerPlan.includes(symbol.toLowerCase()));\r\n}\r\n\r\nfunction looksLikeTruncatedRewrite(target: PilotTarget, currentContent: string, newContent: string): string | null {\r\n if (SUSPECT_PLACEHOLDER_RE.test(newContent)) {\r\n return \"contains placeholder text suggesting an abbreviated rewrite\";\r\n }\r\n if (currentContent.length > 0 && newContent.length < currentContent.length * SUSPECT_LENGTH_DROP_RATIO) {\r\n return `sharp length drop (${currentContent.length} -> ${newContent.length} chars)`;\r\n }\r\n\r\n // A multiset line diff can't tell \"line changed\" from \"line removed\" \u2014 on a short/single-line\r\n // file, one edited line reads as 100% removed. Require a real line count before trusting it.\r\n const currentLineCount = currentContent.length > 0 ? currentContent.split(\"\\n\").length : 0;\r\n if (currentLineCount >= MIN_LINES_FOR_REMOVED_LINE_CHECK) {\r\n const removedLines = countRemovedLines(currentContent, newContent);\r\n if (removedLines > currentLineCount * SUSPECT_REMOVED_LINE_RATIO) {\r\n const pct = ((removedLines / currentLineCount) * 100).toFixed(0);\r\n return `removed ${removedLines} of ${currentLineCount} lines (${pct}%) without a matching drop in character count`;\r\n }\r\n }\r\n\r\n const planText = target.planStepsImplemented.join(\" \");\r\n const unexplainedSymbols = removedUnexplainedSymbols(target.path, planText, currentContent, newContent);\r\n if (unexplainedSymbols.length > 0) {\r\n return `removed exported symbol(s) the plan steps don't mention: ${unexplainedSymbols.join(\", \")}`;\r\n }\r\n\r\n return null;\r\n}\r\n\r\n/** QUIKTR-1083 (\u00A715.6) \u2014 sent on every codegen call, same reasoning as targeting.ts's own constant. */\r\nconst CONTRACT_VERSION = \"test-targets-1\";\r\n/** 9.0.0, Doc 62 \u00A72 \u2014 cumulative over test-targets-1. For an EXISTING target the reply is anchored `edits` the runner\r\n * applies, not a whole file. A NEW_FILE target has nothing to anchor against and never asks for it. */\r\nconst CONTRACT_VERSION_EDITS = \"edits-1\";\r\n/** The runtime's code for anchors the ONE regeneration still could not place (Doc 62 \u00A72.1). Our remedy is our own:\r\n * re-request the whole file without edits-1. The fallback is the runner's, so it shows in the run trail. */\r\nconst ANCHOR_REFUSED_CODE = \"CODEGEN_ANCHOR_REFUSED\";\r\n\r\n/** The shape at `envelope.structuredJson` for `pilot.codegen` \u2014 NOT the envelope itself. A\r\n * refusal's reason is `refusalReason`; the envelope has no `code`/`message` fields (those were\r\n * never real \u2014 see envelope.ts). Under edits-1 an EXISTING target's GENERATED reply carries `edits`, not `newContent`. */\r\ninterface CodegenResult {\r\n outcome?: \"GENERATED\" | \"REFUSED\";\r\n newContent?: string;\r\n edits?: unknown;\r\n summary?: string;\r\n refusalReason?: string;\r\n}\r\n\r\n/** Which way a call went, for the one log line per call. `edits`: anchored edits applied. `fallback`: edits were\r\n * refused or did not place, so the whole file was requested. `whole_file`: no edits were asked for, or the reply was\r\n * a whole file anyway. */\r\ntype EditsPath = \"edits\" | \"fallback\" | \"whole_file\";\r\n\r\n/** What a refusal may say about itself: counts and kinds, never the text of an anchor. These strings end up in the\r\n * run's warnings, which reach QuikTrack. */\r\ninterface RefusalSummary {\r\n text: string;\r\n matchCounts: number[];\r\n}\r\n\r\nfunction summariseLocalRefusals(refusals: AnchorRefusal[]): RefusalSummary {\r\n const parts: string[] = [];\r\n const matchCounts: number[] = [];\r\n for (const r of refusals) {\r\n if (r.kind === \"ambiguous\") {\r\n parts.push(`an anchor matched ${r.matchCount} times`);\r\n if (r.matchCount !== null) matchCounts.push(r.matchCount);\r\n } else if (r.kind === \"no_match\") {\r\n parts.push(\"an anchor matched nothing\");\r\n } else if (r.kind === \"overlap\") {\r\n parts.push(`edits ${r.edits.join(\" and \")} overlap`);\r\n } else if (r.kind === \"no_edits\") {\r\n parts.push(\"the reply had no edits\");\r\n } else {\r\n parts.push(\"an edit was missing its anchor or replacement\");\r\n }\r\n }\r\n return { text: [...new Set(parts)].join(\"; \"), matchCounts };\r\n}\r\n\r\n/** The runtime's own refusal text quotes the anchor (\"The anchor was: \u2026\"), so it is read for its counts and never passed on. */\r\nfunction summariseRuntimeRefusal(error: unknown): RefusalSummary {\r\n const text = typeof error === \"string\" ? error : \"\";\r\n const matchCounts = [...text.matchAll(/anchor matched (\\d+) times/g)].map((m) => Number(m[1]));\r\n const parts: string[] = matchCounts.map((n) => `an anchor matched ${n} times`);\r\n if (/no match/i.test(text)) parts.push(\"an anchor matched nothing\");\r\n if (/overlap/i.test(text)) parts.push(\"edits overlapped\");\r\n if (/empty anchor|missing a string/i.test(text)) parts.push(\"an edit was missing its anchor or replacement\");\r\n return { text: parts.length > 0 ? [...new Set(parts)].join(\"; \") : \"the runtime could not place the edits\", matchCounts };\r\n}\r\n\r\n/** The two hard stops a reply can carry after any retry: a code that is never retried, and a judgedBy overflow that is\r\n * still too large after narrowing. One place so the whole-file fallback holds the same line as the first call. */\r\nfunction throwOnTerminalRefusal(envelope: any, targetPath: string): void {\r\n if (typeof envelope?.errorCode === \"string\" && NOT_RETRIED_CODES.has(envelope.errorCode)) {\r\n const detail = envelope.error ? `: ${envelope.error}` : \"\";\r\n throw new RuntimeReplyError(\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (not retried)${detail}`,\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (not retried)`,\r\n );\r\n }\r\n if (envelope?.errorCode === JUDGED_BY_TOO_LARGE_CODE) {\r\n // Still too large after narrowing (or the retry hit some other JUDGED_BY_TOO_LARGE cause) \u2014\r\n // no further retry, same all-or-nothing posture as every other codegen failure here.\r\n const detail = envelope.error ? `: ${envelope.error}` : \"\";\r\n throw new RuntimeReplyError(\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (after narrowing)${detail}`,\r\n `Codegen refused ${targetPath}: ${envelope.errorCode} (after narrowing)`,\r\n );\r\n }\r\n}\r\n\r\nfunction codegenRefusedError(targetPath: string, body: CodegenResult): RuntimeReplyError {\r\n return new RuntimeReplyError(\r\n `Codegen refused ${targetPath}${body.refusalReason ? `: ${body.refusalReason}` : \"\"}`,\r\n `Codegen refused ${targetPath}`,\r\n );\r\n}\r\n\r\nexport interface CodegenFileResult {\r\n targetPath: string;\r\n newContent: string;\r\n}\r\n\r\n/** \u00A718 `judgedBy` \u2014 the internal (runner-only) shape, keeping `automationId` for the\r\n * overflow-narrowing filter below; stripped down to `{title, given, when, then}` only when\r\n * actually serialized onto the wire (\u00A718.9 refuses any other key on an entry). */\r\nexport interface JudgedByCase {\r\n automationId: string;\r\n title: string;\r\n given: string;\r\n when: string;\r\n then: string;\r\n}\r\n\r\n/**\r\n * \u00A718 \u2014 every case claimed by SOME target in this run (not scoped to `contextPaths` matches \u2014\r\n * that's `narrowJudgedByForTarget`'s overflow-fallback job only, not the primary rule), minus\r\n * targeting's own `skippedCases` (\u00A715.3's `NO_BEHAVIOUR` skip), minus any entry still missing\r\n * given/when/then \u2014 defensive: a non-skipped case should already have all three by construction,\r\n * but \u00A718.9 refuses `CONTRACT_REJECTED` on any entry outside the declared shape, so this never\r\n * trusts that invariant blindly. Built once per run, in `run.ts`, and passed into `runCodegen`.\r\n */\r\nexport function buildJudgedByPool(\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n targets: PilotTarget[],\r\n skippedCases: SkippedCase[],\r\n): JudgedByCase[] {\r\n const claimedIds = new Set<string>();\r\n for (const t of targets) {\r\n for (const id of t.automationIds ?? []) claimedIds.add(id);\r\n }\r\n const skippedIds = new Set(skippedCases.map((s) => s.automationId));\r\n\r\n const pool: JudgedByCase[] = [];\r\n for (const tc of requiredTests) {\r\n if (!claimedIds.has(tc.automationId) || skippedIds.has(tc.automationId)) continue;\r\n if (!tc.given || !tc.when || !tc.then) continue;\r\n pool.push({ automationId: tc.automationId, title: tc.title, given: tc.given, when: tc.when, then: tc.then });\r\n }\r\n return pool;\r\n}\r\n\r\n/** \u00A718.8.1's overflow fallback \u2014 narrow the full pool down to only cases claimed by a test target\r\n * whose own `contextPaths` names this code target's path. Not the primary rule (a claiming test\r\n * target's `contextPaths` is model output and can be missing/wrong), only the retry narrowing. */\r\nfunction narrowJudgedByForTarget(pool: JudgedByCase[], targets: PilotTarget[], codeTargetPath: string): JudgedByCase[] {\r\n const narrowedIds = new Set<string>();\r\n for (const t of targets) {\r\n if (!t.automationIds?.length || !t.contextPaths?.includes(codeTargetPath)) continue;\r\n for (const id of t.automationIds) narrowedIds.add(id);\r\n }\r\n return pool.filter((c) => narrowedIds.has(c.automationId));\r\n}\r\n\r\n/** Strips `automationId` for the wire \u2014 \u00A718.9 refuses any key outside `{title, given, when, then}`. */\r\nfunction toWireJudgedBy(pool: JudgedByCase[]): { title: string; given: string; when: string; then: string }[] {\r\n return pool.map(({ automationId: _automationId, ...rest }) => rest);\r\n}\r\n\r\n/**\r\n * Run codegen for exactly the targets named, in order, stopping at the first failure. Throws\r\n * rather than returning a partial result \u2014 see the ALL-OR-NOTHING note above; a caller that wants\r\n * to know how far it got before failing should catch and inspect the message, not branch on a\r\n * return value that implies partial success is a valid state. Writes nothing \u2014 call\r\n * `flushCodegenResults` with the return value once this resolves.\r\n *\r\n * `warnings` is a shared, mutable array \u2014 same convention `run.ts` already uses for\r\n * QUIKTR-1064/1374's non-blocking findings \u2014 pushed into directly rather than returned, so this\r\n * function's return type stays `CodegenFileResult[]`.\r\n */\r\nexport async function runCodegen(\r\n gateway: PilotPacket[\"gateway\"],\r\n targets: PilotTarget[],\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n judgedByPool: JudgedByCase[],\r\n warnings: string[],\r\n /** QUIKTR-1421 \u2014 a caller-owned array this fills with one entry per call (what targeting named, what the\r\n * runner added, what it skipped), so run.ts can report it to QuikTrack. Optional and last: every existing\r\n * caller is unchanged. Entries are pushed BEFORE the call, so they survive a later throw. */\r\n contextLog?: CodegenContextRecord[],\r\n /** QUIKTR-1401 (\u00A720) \u2014 what the reviewer approved the change must NOT touch, sent on every call (code and test\r\n * targets alike) when non-empty. Optional and last: every existing caller is unchanged. */\r\n outOfScope: string[] = [],\r\n): Promise<CodegenFileResult[]> {\r\n const results: CodegenFileResult[] = [];\r\n const listing = new Set(workspaceListing);\r\n\r\n for (const target of targets) {\r\n const isNewFile = target.kind === \"NEW_FILE\";\r\n const currentContent = isNewFile ? \"\" : readFileSync(target.path, \"utf8\");\r\n // 9.0.0, Doc 62 \u00A72 \u2014 an EXISTING file asks for anchored edits against its LF form, and gets its own convention back\r\n // when written. A file with BOTH conventions cannot be restored faithfully, so it keeps the whole-file path.\r\n const lineEnding: LineEnding = isNewFile ? \"LF\" : detectLineEnding(currentContent);\r\n const wantsEdits = !isNewFile && lineEnding !== \"mixed\";\r\n\r\n // targeting names its own context needs per target \u2014 an invented contextPath is the same\r\n // class of bug as an invented EXISTING target (targeting.ts's validateTarget): fail loudly\r\n // rather than silently sending less context than the model asked for.\r\n const contextPaths = target.contextPaths ?? [];\r\n // QUIKTR-1420 \u2014 the egress point: this is where a context file is READ and put in the request.\r\n // runTargeting re-checks too; this holds even for a target that did not come through it, and it runs\r\n // before the not-found check so a denied path is never reported as merely missing.\r\n const deniedContext = findDeniedContextPath(contextPaths, deniedPaths);\r\n if (deniedContext) {\r\n throw new Error(\r\n `pilot.codegen contextPaths cited a denied path (${deniedContext.pattern}): ${deniedContext.path} (target ${target.path})`,\r\n );\r\n }\r\n for (const contextPath of contextPaths) {\r\n if (!listing.has(contextPath)) {\r\n throw new Error(\r\n `pilot.codegen contextPaths named a file not found in the checkout: ${contextPath} (target ${target.path})`,\r\n );\r\n }\r\n }\r\n const namedContents = contextPaths.map((path) => ({ path, content: readFileSync(path, \"utf8\") }));\r\n\r\n // QUIKTR-1419 \u2014 for a test target, also the run's other existing code files (see collectRunContext).\r\n const runFiles = collectRunContext(target, targets, new Set(contextPaths), deniedPaths);\r\n for (const s of runFiles.skipped) {\r\n warnings.push(`not shown to the test for ${target.path}: ${s.path} (${s.reason})`);\r\n }\r\n // QUIKTR-1454 \u2014 and the files this target itself imports, one hop. Added AFTER what targeting named and what the\r\n // run's files brought, never instead of them. A NEW_FILE has no content to read imports from.\r\n const imports = isNewFile\r\n ? { entries: [], skipped: [], importedPaths: [], aliasImports: 0 }\r\n : collectImportContext({\r\n targetPath: target.path,\r\n source: currentContent,\r\n alreadyNamed: new Set([...contextPaths, ...runFiles.entries.map((e) => e.path)]),\r\n deniedPaths,\r\n listing,\r\n readFile: (p) => readFileSync(p, \"utf8\"),\r\n maxFileChars: MAX_ADDED_FILE_CHARS,\r\n maxTotalChars: MAX_ADDED_CONTEXT_CHARS,\r\n spentChars: runFiles.entries.reduce((n, e) => n + e.content.length, 0),\r\n });\r\n for (const s of imports.skipped) {\r\n if (ACTIONABLE_IMPORT_SKIPS.has(s.reason)) {\r\n warnings.push(`not shown with ${target.path}: ${s.path} (imported by it; ${s.reason.replace(/^import: /, \"\")})`);\r\n }\r\n }\r\n const added: Pick<AddedContext, \"entries\"> & { skipped: { path: string; reason: string }[] } = {\r\n entries: [...runFiles.entries, ...imports.entries],\r\n skipped: [...runFiles.skipped, ...imports.skipped],\r\n };\r\n const contextContents = [...namedContents, ...added.entries];\r\n // One line per call: which files targeting named and which the runner added. Without it, \"was the\r\n // file even in front of the model?\" cannot be answered from this runner's own log (run 25). QUIKTR-1454: and\r\n // which of those came from imports, what was skipped and why, and how many path aliases were not followed.\r\n const contextRecord: CodegenContextRecord = {\r\n targetPath: target.path,\r\n contextPaths,\r\n addedPaths: added.entries.map((e) => e.path),\r\n skipped: added.skipped,\r\n ...(imports.importedPaths.length > 0 ? { importedPaths: imports.importedPaths } : {}),\r\n ...(imports.aliasImports > 0 ? { aliasImports: imports.aliasImports } : {}),\r\n };\r\n console.log(JSON.stringify({ event: \"codegen.context\", ...contextRecord }));\r\n // QUIKTR-1421 \u2014 the same facts, handed back so they reach QuikTrack's run trail, not just this job's log.\r\n contextLog?.push(contextRecord);\r\n\r\n const contextData: Record<string, unknown> = {\r\n targetPath: target.path,\r\n // Every anchor and replacement is LF, always (Doc 62 \u00A72), so the file is sent as LF.\r\n currentContent: wantsEdits ? toLf(currentContent) : currentContent,\r\n planSteps: target.planStepsImplemented,\r\n kind: target.kind,\r\n contextContents,\r\n // QUIKTR-1083 (\u00A715.6) \u2014 required on every call on the versioned path.\r\n contractVersion: wantsEdits ? CONTRACT_VERSION_EDITS : CONTRACT_VERSION,\r\n };\r\n if (isNewFile) {\r\n // Bounds WHAT EXISTS \u2014 stops an invented import like hooks/useGroups \u2014 only meaningful for\r\n // a file that doesn't exist yet to compare against.\r\n contextData.workspaceListing = workspaceListing;\r\n }\r\n if (deniedPaths.length > 0) {\r\n contextData.deniedPaths = deniedPaths;\r\n }\r\n // QUIKTR-1401, \u00A720 \u2014 omitted rather than sent empty, same as deniedPaths. Free text: told, never checked.\r\n if (outOfScope.length > 0) {\r\n contextData.outOfScope = outOfScope;\r\n }\r\n // QUIKTR-1083 (\u00A715.4) \u2014 only for a test target (one targeting named automationIds for), and\r\n // only that target's own subset \u2014 never the full list, and never for a code target at all.\r\n if (target.automationIds && target.automationIds.length > 0) {\r\n const wanted = new Set(target.automationIds);\r\n contextData.requiredTests = requiredTests.filter((tc) => wanted.has(tc.automationId));\r\n } else if (judgedByPool.length > 0) {\r\n // \u00A718 \u2014 a code target (no automationIds of its own) gets the run's claimed cases as\r\n // judging context instead. Mutually exclusive with requiredTests per call, by construction:\r\n // this is the else branch of the exact same condition. Omitted entirely when the pool is\r\n // empty, never sent as `[]`.\r\n contextData.judgedBy = toWireJudgedBy(judgedByPool);\r\n }\r\n\r\n // QUIKTR-1069 \u2014 retries a transport-level failure only (502/503/504, a dropped connection);\r\n // a real refusal always arrives as a 200 with the refusal inside the envelope, below.\r\n const callCodegen = () =>\r\n fetchWithRetry(`${gateway.baseUrl}/ai/execute`, {\r\n method: \"POST\",\r\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\r\n body: JSON.stringify({\r\n appId: \"quiktrack\",\r\n useCase: \"pilot.codegen\",\r\n expectedOutputType: \"json\",\r\n userPrompt: \"\",\r\n contextData,\r\n }),\r\n });\r\n\r\n let res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n\r\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\r\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\r\n // CODEGEN_FILE_TOO_LARGE / CODEGEN_CONTEXT_TOO_LARGE are checked on the RAW envelope, before\r\n // unwrapping: they arrive as a failure (success:false), so unwrapping first would throw the\r\n // generic envelope error and lose the not-retried distinction this check exists to preserve.\r\n let envelope: any = await res.json();\r\n // QUIKTR-1083 \u2014 SEMANTIC_MISMATCH/CONTRACT_REJECTED, same \"raw envelope, before unwrap\" point\r\n // as the CODEGEN_* check right below.\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n\r\n // \u00A718.8.1 \u2014 the one retried refusal here: narrow judgedBy to only the cases a test target's\r\n // own contextPaths ties to this file, then retry ONCE. Recorded on the run's trail either way\r\n // (even if the retry still fails) so the trail shows what was attempted.\r\n if (envelope?.errorCode === JUDGED_BY_TOO_LARGE_CODE && contextData.judgedBy) {\r\n const before = (contextData.judgedBy as unknown[]).length;\r\n const narrowed = narrowJudgedByForTarget(judgedByPool, targets, target.path);\r\n if (narrowed.length > 0) {\r\n contextData.judgedBy = toWireJudgedBy(narrowed);\r\n } else {\r\n delete contextData.judgedBy;\r\n }\r\n warnings.push(`judgedBy narrowed for ${target.path}: ${before} \u2192 ${narrowed.length} cases`);\r\n\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n }\r\n\r\n // QUIKTR-1419 \u2014 the runner's own additions must never turn a run that would have passed into a\r\n // failure. If the runtime refuses the context as too large AND we added files, retry ONCE with only\r\n // what targeting named; if it still refuses, that overflow is real and falls through to the throw below.\r\n if (envelope?.errorCode === CONTEXT_TOO_LARGE_CODE && added.entries.length > 0) {\r\n contextData.contextContents = namedContents;\r\n warnings.push(`context for ${target.path} was too large with the run's other files; retried without them`);\r\n // QUIKTR-1421 \u2014 the record must not claim files were shown that the retry dropped. The same object is\r\n // already in `contextLog`, so mutating it updates what gets reported.\r\n contextRecord.addedPaths = [];\r\n delete contextRecord.importedPaths;\r\n contextRecord.retriedWithoutAdded = true;\r\n\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n }\r\n\r\n throwOnTerminalRefusal(envelope, target.path);\r\n\r\n // 9.0.0, Doc 62 \u00A72/\u00A72.1 \u2014 what became of the edits. `newContent` is the file to write; `failedEdits` is set when the\r\n // edits could not be used, and there is exactly ONE answer to that: ask again for the whole file, without edits-1.\r\n let newContent: string | null = null;\r\n let failedEdits: { reason: \"anchor_refused\" | \"local_refusal\"; summary: RefusalSummary } | null = null;\r\n let editCount: number | undefined;\r\n let path: EditsPath = \"whole_file\";\r\n let reason: string | undefined = isNewFile ? \"new_file\" : wantsEdits ? undefined : \"mixed_line_endings\";\r\n\r\n if (wantsEdits && envelope?.errorCode === ANCHOR_REFUSED_CODE) {\r\n // Arrives only after the runtime's own ONE regeneration, so \"this was already retried\" is unambiguous.\r\n failedEdits = { reason: \"anchor_refused\", summary: summariseRuntimeRefusal(envelope.error) };\r\n } else {\r\n const body = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\r\n if (wantsEdits) {\r\n // A genuine refusal is the runtime's answer, not a malformed one: it ends the run exactly as it always has.\r\n if (body.outcome === \"REFUSED\") throw codegenRefusedError(target.path, body);\r\n // We asked for edits-1, so check we GOT edits-1 before using anything (Suyash, 5 Oct). `newContent` is valid under\r\n // test-targets-1, which is exactly why it must not be applied here: the call would succeed having asked for edits\r\n // and silently got something else. The runtime turns a malformed reply into SCHEMA_MISMATCH, so this should never\r\n // arrive; if it does it is a failure, not a candidate for the fallback, which is for anchors only (Suyash).\r\n if (body.outcome !== \"GENERATED\" || typeof body.newContent === \"string\") {\r\n throw new RuntimeReplyError(\r\n `Codegen reply for ${target.path} was not in the edits-1 shape and was not applied`,\r\n `Codegen reply for ${target.path} was not in the edits-1 shape`,\r\n );\r\n }\r\n // Every anchor is resolved against the content we sent, by the same rules the runtime held: exactly once, no\r\n // overlap. The runner writes the file, so it does not take the runtime's word for it.\r\n const applied = applyEdits(toLf(currentContent), body.edits);\r\n if (applied.ok) {\r\n newContent = fromLf(applied.content, lineEnding);\r\n path = \"edits\";\r\n editCount = applied.editCount;\r\n } else if (applied.refusals.some((r) => r.kind === \"no_edits\")) {\r\n // GENERATED with nothing to apply: a model that changed nothing while saying it did. The runtime's own answer to\r\n // that is SEMANTIC_MISMATCH, which is never retried; asking again here would only spend a bigger call on it.\r\n throw new RuntimeReplyError(\r\n `Codegen reply for ${target.path} carried no edits (not retried)`,\r\n `Codegen reply for ${target.path} carried no edits`,\r\n );\r\n } else {\r\n // Anchors that could not be placed: the one thing the whole-file fallback is for.\r\n failedEdits = { reason: \"local_refusal\", summary: summariseLocalRefusals(applied.refusals) };\r\n }\r\n } else {\r\n if (body.outcome !== \"GENERATED\" || typeof body.newContent !== \"string\") {\r\n throw codegenRefusedError(target.path, body);\r\n }\r\n newContent = body.newContent;\r\n }\r\n }\r\n\r\n if (failedEdits) {\r\n // The saving is lost on this call; the run survives, so edits-1 is never a new way to fail. It is also VISIBLE: this\r\n // warning reaches QuikTrack's run trail, which a runtime-side fallback could not do. Counts only, never an anchor.\r\n warnings.push(\r\n `edits for ${target.path} could not be placed (${failedEdits.summary.text}); asked again for the whole file`,\r\n );\r\n contextData.currentContent = currentContent;\r\n contextData.contractVersion = CONTRACT_VERSION;\r\n try {\r\n res = await callCodegen();\r\n if (!res.ok) {\r\n throw new Error(`Codegen call failed for ${target.path}: ${res.status} ${res.statusText}`);\r\n }\r\n envelope = await res.json();\r\n checkHardFailure(envelope, \"pilot.codegen\", target.path);\r\n throwOnTerminalRefusal(envelope, target.path);\r\n const whole = unwrapExecute<CodegenResult>(envelope, \"pilot.codegen\");\r\n if (whole.outcome !== \"GENERATED\" || typeof whole.newContent !== \"string\") {\r\n throw codegenRefusedError(target.path, whole);\r\n }\r\n newContent = whole.newContent;\r\n } catch (error: unknown) {\r\n // Honest, not a retry: the whole file is a BIGGER request, so where the provider cannot serve a large one\r\n // (AI_UNAVAILABLE) this can only fail the same way, and that is not transient. Say what happened and in which\r\n // order, so the failure is not read as a plain provider hiccup. Names and codes only in the reported summary.\r\n if (error instanceof RuntimeReplyError) {\r\n throw new RuntimeReplyError(\r\n `${error.message} (this was the whole-file request made after the edits for ${target.path} were refused: ${failedEdits.summary.text})`,\r\n `${error.summary} (the whole-file request, made after the edits were refused)`,\r\n );\r\n }\r\n throw error;\r\n }\r\n path = \"fallback\";\r\n reason = failedEdits.reason;\r\n }\r\n\r\n if (newContent === null) throw new Error(`Codegen produced no content for ${target.path}`);\r\n\r\n if (!isNewFile) {\r\n // Which path each call took (Doc 62 \u00A72.1): without it nobody can tell whether the retry earns its place, and the\r\n // measurement is free if collected from the start. Counts and outcomes only: no anchor, no replacement.\r\n console.log(\r\n JSON.stringify({\r\n event: \"codegen.edits_path\",\r\n targetPath: target.path,\r\n path,\r\n ...(reason ? { reason } : {}),\r\n ...(editCount !== undefined ? { editCount } : {}),\r\n ...(failedEdits && failedEdits.summary.matchCounts.length > 0 ? { matchCounts: failedEdits.summary.matchCounts } : {}),\r\n lineEnding,\r\n }),\r\n );\r\n }\r\n\r\n if (!isNewFile) {\r\n const suspectReason = looksLikeTruncatedRewrite(target, currentContent, newContent);\r\n if (suspectReason) {\r\n throw new Error(\r\n `Codegen output for ${target.path} looks like a truncated/abbreviated rewrite (${suspectReason}) ` +\r\n `\u2014 refusing to apply it. Interim guard per \u00A716.7; the AI Runtime's own output-cap check is not live yet.`,\r\n );\r\n }\r\n }\r\n\r\n // AI Runtime, 2026-09-24 \u2014 one structured line per call, to build the input/output/removed-line\r\n // distribution SUSPECT_LENGTH_DROP_RATIO and SUSPECT_REMOVED_LINE_RATIO were guessed without.\r\n // Not itself a safety check \u2014 plain data collection for calibrating the two guards above.\r\n console.log(\r\n JSON.stringify({\r\n event: \"codegen.metrics\",\r\n targetPath: target.path,\r\n kind: target.kind,\r\n inputLength: currentContent.length,\r\n outputLength: newContent.length,\r\n removedLines: isNewFile ? null : countRemovedLines(currentContent, newContent),\r\n }),\r\n );\r\n\r\n results.push({ targetPath: target.path, newContent });\r\n }\r\n\r\n return results;\r\n}\r\n\r\n/** Writes every result to disk. Only ever call this after every `runCodegen` call succeeded \u2014\r\n * see the buffered-writes note above. Creates the parent directory first: a NEW_FILE target can\r\n * legitimately name a directory that doesn't exist yet (e.g. a repo's first hooks/ file). */\r\nexport function flushCodegenResults(results: CodegenFileResult[]): void {\r\n for (const { targetPath, newContent } of results) {\r\n mkdirSync(dirname(targetPath), { recursive: true });\r\n writeFileSync(targetPath, newContent);\r\n }\r\n}\r\n", "/**\r\n * QUIKTR-1083 (\u00A715.3) \u2014 layer 2 of the three denied-path layers the contract describes: after\r\n * `pilot.targeting` responds, every proposed target's path is checked against `deniedPaths` here,\r\n * before any codegen spend. (Layer 1 is the AI Runtime's own targeting validator; layer 3 is\r\n * `guardrail.ts`'s post-commit check on the actually-staged diff.)\r\n *\r\n * Hand-rolled rather than a `minimatch`/`picomatch` dependency: this package is published\r\n * publicly and carries no secrets or heavy deps on purpose (see workflow-template.ts's own\r\n * docblock), and the denied-path patterns in real use (a dotfile glob under a double-star prefix,\r\n * a workflows directory suffixed with a double star, a bare lockfile name under a double-star\r\n * prefix) never need brace expansion, character classes, or `?` \u2014 only a double star (any depth,\r\n * including none) and a single star (anything but a path separator). A dependency for two glob\r\n * tokens is not worth the weight.\r\n */\r\nfunction globToRegExp(pattern: string): RegExp {\r\n const escaped = pattern\r\n .split(\"\")\r\n .map((c) => (/[.+^${}()|[\\]\\\\]/.test(c) ? `\\\\${c}` : c))\r\n .join(\"\");\r\n // Order matters: the more specific `**/` token first, so the generic `**`/`*` passes below\r\n // don't consume it first and lose the \"zero directories is also a match\" behaviour every\r\n // default pattern (`**/*.env*`, `**/package-lock.json`, ...) actually depends on \u2014 a repo-root\r\n // `.env` must match `**/*.env*` exactly as a nested one does, the same way `.gitignore`'s own\r\n // `**/` prefix works.\r\n const withGlobs = escaped\r\n .replace(/\\*\\*\\//g, \" SLASH \")\r\n .replace(/\\*\\*/g, \" STAR \")\r\n .replace(/\\*/g, \"[^/]*\")\r\n .replace(/ SLASH /g, \"(?:.*/)?\")\r\n .replace(/ STAR /g, \".*\");\r\n return new RegExp(`^${withGlobs}$`);\r\n}\r\n\r\n/** The first pattern `path` matches, or `null`. `path` is repo-relative, matching how every\r\n * `deniedPaths` entry and every target's `path` are already written elsewhere in this package. */\r\nexport function matchesDeniedPath(path: string, patterns: string[]): string | null {\r\n for (const pattern of patterns) {\r\n if (globToRegExp(pattern).test(path)) return pattern;\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * QUIKTR-1420 \u2014 the first path in a list that matches a denied pattern, with the pattern it matched, or\r\n * `null`. For `contextPaths`: the runner reads each one and puts its content in the request to the model\r\n * provider, so a protected file cited as context is the same egress as one named as a target. The AI Runtime\r\n * refuses these itself (pilot_targeting.py:374, per Suyash), but for targets this package deliberately\r\n * re-checks rather than trusting that, and context was the one gap.\r\n */\r\nexport function findDeniedContextPath(\r\n contextPaths: string[],\r\n patterns: string[],\r\n): { path: string; pattern: string } | null {\r\n for (const path of contextPaths) {\r\n const pattern = matchesDeniedPath(path, patterns);\r\n if (pattern) return { path, pattern };\r\n }\r\n return null;\r\n}\r\n", "/**\r\n * Doc 62 \u00A72 / \u00A72.1 (\"edits-1\") \u2014 applying the AI Runtime's anchored edits to a file the runner is about to write.\r\n *\r\n * The runtime validates anchors against the content it was sent and splices only to measure the result; the RUNNER\r\n * writes the real file, so it applies the edits itself and holds the same rules rather than trusting the reply:\r\n * - every `find` matches the ORIGINAL content exactly once. Zero or several is a refusal, never a guess;\r\n * - every range is resolved before anything is applied, so a whole response is validated or refused;\r\n * - overlapping ranges refuse the WHOLE response; adjacent ranges do not overlap;\r\n * - application is order-independent, because ranges are spliced by position, not applied in sequence.\r\n *\r\n * Line endings: the content handed to `applyEdits` is LF. `toLf` / `detectLineEnding` / `fromLf` normalise a file before it\r\n * is sent and restore its own convention when it is written. Nothing else is normalised: in Python and YAML whitespace is\r\n * semantics, not formatting.\r\n *\r\n * Refusal messages carry counts and edit numbers only, never the text of an anchor or a replacement: they end up in the\r\n * run's warnings, which reach QuikTrack, and customer code does not.\r\n */\r\n\r\nexport type LineEnding = \"LF\" | \"CRLF\" | \"mixed\";\r\n\r\n/** The convention of `text` as read from disk. A lone CR is not a line ending, so it is counted neither way. */\r\nexport function detectLineEnding(text: string): LineEnding {\r\n const crlf = text.split(\"\\r\\n\").length - 1;\r\n const bareLf = text.split(\"\\n\").length - 1 - crlf;\r\n if (crlf > 0 && bareLf > 0) return \"mixed\";\r\n return crlf > 0 ? \"CRLF\" : \"LF\";\r\n}\r\n\r\nexport function toLf(text: string): string {\r\n return text.replace(/\\r\\n/g, \"\\n\");\r\n}\r\n\r\n/** Restores a convention on LF text. `mixed` cannot be restored faithfully, so callers never ask for it. */\r\nexport function fromLf(text: string, ending: LineEnding): string {\r\n return ending === \"CRLF\" ? text.replace(/\\n/g, \"\\r\\n\") : text;\r\n}\r\n\r\nexport type AnchorRefusalKind = \"ambiguous\" | \"no_match\" | \"empty\" | \"overlap\" | \"no_edits\";\r\n\r\nexport interface AnchorRefusal {\r\n kind: AnchorRefusalKind;\r\n /** 1-based numbers of the edits involved: one, or two for an overlap; empty for `no_edits`. */\r\n edits: number[];\r\n /** How many times the anchor matched; null when that does not apply. */\r\n matchCount: number | null;\r\n message: string;\r\n}\r\n\r\nexport type EditsOutcome =\r\n | { ok: true; content: string; editCount: number }\r\n | { ok: false; refusals: AnchorRefusal[]; editCount: number };\r\n\r\n/** Every start index of `needle` in `haystack`, overlapping occurrences included: \"aa\" occurs twice in \"aaa\", and an\r\n * anchor that can be placed two ways identifies no place. */\r\nfunction occurrences(haystack: string, needle: string): number[] {\r\n const found: number[] = [];\r\n let index = haystack.indexOf(needle);\r\n while (index !== -1) {\r\n found.push(index);\r\n index = haystack.indexOf(needle, index + 1);\r\n }\r\n return found;\r\n}\r\n\r\ninterface PlacedRange {\r\n start: number;\r\n end: number;\r\n number: number;\r\n replace: string;\r\n}\r\n\r\n/** Resolve every edit against `originalLf`, then either refuse the whole response or splice. Pure. */\r\nexport function applyEdits(originalLf: string, edits: unknown): EditsOutcome {\r\n if (!Array.isArray(edits) || edits.length === 0) {\r\n return {\r\n ok: false,\r\n editCount: 0,\r\n refusals: [{ kind: \"no_edits\", edits: [], matchCount: null, message: \"the response carried no edits\" }],\r\n };\r\n }\r\n\r\n const refusals: AnchorRefusal[] = [];\r\n const ranges: PlacedRange[] = [];\r\n\r\n edits.forEach((edit: unknown, index: number) => {\r\n const number = index + 1;\r\n const record = edit !== null && typeof edit === \"object\" ? (edit as Record<string, unknown>) : null;\r\n const find = record?.find;\r\n const replace = record?.replace;\r\n if (typeof find !== \"string\" || typeof replace !== \"string\") {\r\n refusals.push({\r\n kind: \"empty\",\r\n edits: [number],\r\n matchCount: null,\r\n message: `edit ${number} is missing a string find or replace`,\r\n });\r\n return;\r\n }\r\n if (find === \"\") {\r\n refusals.push({ kind: \"empty\", edits: [number], matchCount: null, message: `edit ${number} has an empty anchor` });\r\n return;\r\n }\r\n const starts = occurrences(originalLf, find);\r\n if (starts.length === 0) {\r\n refusals.push({ kind: \"no_match\", edits: [number], matchCount: 0, message: `edit ${number}: the anchor matched nothing` });\r\n } else if (starts.length > 1) {\r\n refusals.push({\r\n kind: \"ambiguous\",\r\n edits: [number],\r\n matchCount: starts.length,\r\n message: `edit ${number}: the anchor matched ${starts.length} times`,\r\n });\r\n } else {\r\n ranges.push({ start: starts[0]!, end: starts[0]! + find.length, number, replace });\r\n }\r\n });\r\n\r\n // Every overlapping pair, among the anchors that did place. Adjacent ranges (one ends where the next starts) are fine.\r\n for (let i = 0; i < ranges.length; i++) {\r\n for (let j = i + 1; j < ranges.length; j++) {\r\n const a = ranges[i]!;\r\n const b = ranges[j]!;\r\n if (a.start < b.end && b.start < a.end) {\r\n const [first, second] = a.number < b.number ? [a.number, b.number] : [b.number, a.number];\r\n refusals.push({\r\n kind: \"overlap\",\r\n edits: [first, second],\r\n matchCount: null,\r\n message: `edits ${first} and ${second} overlap`,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (refusals.length > 0) return { ok: false, refusals, editCount: edits.length };\r\n\r\n const pieces: string[] = [];\r\n let cursor = 0;\r\n for (const range of [...ranges].sort((x, y) => x.start - y.start)) {\r\n pieces.push(originalLf.slice(cursor, range.start), range.replace);\r\n cursor = range.end;\r\n }\r\n pieces.push(originalLf.slice(cursor));\r\n return { ok: true, content: pieces.join(\"\"), editCount: edits.length };\r\n}\r\n", "/** An error whose message quotes something the AI Runtime sent back: its explanation, a refusal reason, or the reply\r\n * itself. That text can carry case text or generated code, so the full `message` stays in the job log (where it has\r\n * always gone) and only `summary` \u2014 the error's name and code \u2014 may leave the job in the failed callback. Truncating\r\n * the message would bound its size, not its kind. */\r\nexport class RuntimeReplyError extends Error {\r\n readonly summary: string;\r\n\r\n constructor(message: string, summary: string) {\r\n super(message);\r\n this.name = \"RuntimeReplyError\";\r\n this.summary = summary;\r\n }\r\n}\r\n", "import { RuntimeReplyError } from \"./runtimeReplyError\";\r\n\r\n/**\r\n * QUIKTR-1046 \u2014 `/ai/execute` wraps every use-case result in an envelope; the use-case's own result\r\n * lives at `envelope.structuredJson`, not at the top level. Both `targeting.ts` and `codegen.ts`\r\n * read the raw response directly and have never worked against a real reply \u2014 this is the one\r\n * place that unwraps it, so there is exactly one place to get it right.\r\n *\r\n * A failed call can arrive as `success: false` in an HTTP 200 body \u2014 `res.ok` alone is not enough.\r\n * Observed live 2026-09-18/19/21, including a real RUN_CREDENTIAL_SCOPE refusal shaped exactly\r\n * like this.\r\n */\r\n/**\r\n * QUIKTR-1083 (\u00A715 of the spec-phase contract) \u2014 two hard-failure codes the AI Runtime raises on\r\n * the versioned `pilot.targeting`/`pilot.codegen` path, neither ever retried: `SEMANTIC_MISMATCH`\r\n * (the JSON shape was valid, a rule failed \u2014 e.g. a generated test file missing its\r\n * `[<automationId>]` marker) and `CONTRACT_REJECTED` (the request itself was refused \u2014 an unknown\r\n * or removed `contextData` key, or an unrecognised `contractVersion`). Both carry the explanation\r\n * in `envelope.error`.\r\n *\r\n * Checked on the RAW envelope, before `unwrapExecute` \u2014 same reason codegen.ts's existing\r\n * `CODEGEN_FILE_TOO_LARGE`/`CODEGEN_CONTEXT_TOO_LARGE` check already runs there: unwrapping first\r\n * would throw `unwrapExecute`'s generic `success:false` error and lose the distinction. No custom\r\n * error class \u2014 `run.ts`'s top-level catch already prints any thrown error's message, and\r\n * `fetchWithRetry` never retries a 200 response regardless of body, so \"print the violation list\"\r\n * and \"never retried\" both already hold once this throws a message that names the code and detail.\r\n */\r\nconst HARD_FAILURE_CODES = new Set([\"SEMANTIC_MISMATCH\", \"CONTRACT_REJECTED\"]);\r\n\r\n/** `target`, when the call is scoped to one file (codegen), is named in the message: the AI\r\n * Runtime's explanation says what broke but not in which file. */\r\nexport function checkHardFailure(envelope: any, useCase: string, target?: string): void {\r\n const code = envelope?.errorCode;\r\n if (typeof code === \"string\" && HARD_FAILURE_CODES.has(code)) {\r\n const detail = envelope.error ?? envelope.normalizedText ?? \"no detail\";\r\n const where = target ? ` for ${target}` : \"\";\r\n throw new RuntimeReplyError(\r\n `${useCase} failed${where} (${code}, not retried): ${detail}`,\r\n `${useCase} failed${where} (${code}, not retried)`,\r\n );\r\n }\r\n}\r\n\r\n/** Every error below quotes the AI Runtime's reply in its message (the job log keeps it); `RuntimeReplyError.summary`\r\n * is the name and code only, which is all that may be reported to QuikTrack. */\r\nexport function unwrapExecute<T>(envelope: any, useCase: string): T {\r\n if (envelope?.success === false) {\r\n const code = envelope.errorCode ?? \"UNKNOWN\";\r\n throw new RuntimeReplyError(\r\n `${useCase} failed: ${code} \u2014 ${envelope.error ?? envelope.normalizedText ?? \"no message\"}`,\r\n `${useCase} failed: ${code}`,\r\n );\r\n }\r\n if (!envelope?.structuredJson || typeof envelope.structuredJson !== \"object\") {\r\n throw new RuntimeReplyError(\r\n `${useCase} returned no structuredJson: ${JSON.stringify(envelope)}`,\r\n `${useCase} returned no structuredJson`,\r\n );\r\n }\r\n return envelope.structuredJson as T;\r\n}\r\n", "import { posix } from \"node:path\";\r\nimport { matchesDeniedPath } from \"./deniedPaths\";\r\n\r\n/**\r\n * QUIKTR-1454 \u2014 the files a changed file imports, shown to the code-writing step alongside the ones targeting\r\n * named. First real 9.0.0 run (QUIKSPL-35): `validation.js` imports from `exchange.js`, targeting did not list\r\n * it, and the model invented a name that file does not export. An import is a fact the file states, so it is\r\n * parsed here rather than asked of a model (Suyash, 5 Oct). Three rules from him: ONE hop (never what an\r\n * imported file imports), what was added and skipped is logged with the reason, and targeting's own list is\r\n * never replaced \u2014 this only adds to it.\r\n *\r\n * Pure: the caller hands over the repo listing and a reader. JavaScript/TypeScript only for now; any other kind\r\n * of file simply yields nothing.\r\n */\r\n\r\n// \u2500\u2500 reading imports out of source \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\ntype Token = { k: \"id\" | \"str\" | \"num\" | \"p\" | \"tpl\"; v: string };\r\n\r\nconst REGEX_PRECEDING_KEYWORDS = new Set([\r\n \"return\", \"typeof\", \"instanceof\", \"in\", \"of\", \"new\", \"delete\", \"void\", \"throw\", \"case\", \"do\", \"else\", \"yield\", \"await\",\r\n]);\r\n\r\n/** ASCII space characters plus the Unicode ones editors leave in files: byte-order mark, no-break space, line and\r\n * paragraph separators. A leading BOM read as part of the word \"import\" hid the first import of 72 repository files. */\r\nconst SPACE_CODES = new Set([0x20, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0xa0, 0x1680, 0x2028, 0x2029, 0x202f, 0x205f, 0x3000, 0xfeff]);\r\nconst isSpace = (c: string) => {\r\n const code = c.charCodeAt(0);\r\n return SPACE_CODES.has(code) || (code >= 0x2000 && code <= 0x200a);\r\n};\r\nconst isIdStart = (c: string) => !isSpace(c) && (/[A-Za-z_$]/.test(c) || c.charCodeAt(0) > 0x7f);\r\nconst isIdPart = (c: string) => !isSpace(c) && (/[A-Za-z0-9_$]/.test(c) || c.charCodeAt(0) > 0x7f);\r\n\r\n/**\r\n * Splits source into the tokens that matter and drops what must not be mistaken for code: comments, string\r\n * contents, template text and regular-expression literals. A quote that never closes on its line ends at the\r\n * line break, as a real scanner reports it \u2014 a JSX apostrophe (\"Don't\") must not swallow the rest of the file.\r\n * `${ \u2026 }` inside a template is code and is scanned (an `import()` can sit there).\r\n */\r\nfunction tokenize(src: string): Token[] {\r\n const out: Token[] = [];\r\n const n = src.length;\r\n\r\n function regexAllowed(): boolean {\r\n const prev = out[out.length - 1];\r\n if (!prev) return true;\r\n if (prev.k === \"p\") return prev.v !== \")\" && prev.v !== \"]\" && prev.v !== \"}\";\r\n if (prev.k === \"id\") return REGEX_PRECEDING_KEYWORDS.has(prev.v);\r\n return false;\r\n }\r\n\r\n /** Scans code from `i`; when `inSubstitution`, stops after the `}` that closes the `${`. Returns the next index. */\r\n function scan(start: number, inSubstitution: boolean): number {\r\n let i = start;\r\n let depth = 0;\r\n while (i < n) {\r\n const c = src[i]!;\r\n if (isSpace(c)) {\r\n i++;\r\n continue;\r\n }\r\n if (c === \"/\" && src[i + 1] === \"/\") {\r\n while (i < n && src[i] !== \"\\n\") i++;\r\n continue;\r\n }\r\n if (c === \"/\" && src[i + 1] === \"*\") {\r\n const end = src.indexOf(\"*/\", i + 2);\r\n i = end === -1 ? n : end + 2;\r\n continue;\r\n }\r\n if (c === \"'\" || c === '\"') {\r\n let j = i + 1;\r\n let closed = false;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === c) {\r\n closed = true;\r\n break;\r\n }\r\n if (d === \"\\n\" || d === \"\\r\") break;\r\n j++;\r\n }\r\n if (closed) out.push({ k: \"str\", v: src.slice(i + 1, j) });\r\n i = closed ? j + 1 : j;\r\n continue;\r\n }\r\n if (c === \"`\") {\r\n let j = i + 1;\r\n let hasSubstitution = false;\r\n let closed = false;\r\n const textStart = j;\r\n let textEnd = j;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === \"`\") {\r\n closed = true;\r\n textEnd = hasSubstitution ? textEnd : j;\r\n break;\r\n }\r\n if (d === \"$\" && src[j + 1] === \"{\") {\r\n hasSubstitution = true;\r\n j = scan(j + 2, true);\r\n continue;\r\n }\r\n j++;\r\n }\r\n if (closed) out.push(hasSubstitution ? { k: \"tpl\", v: \"\" } : { k: \"str\", v: src.slice(textStart, textEnd) });\r\n i = closed ? j + 1 : n;\r\n continue;\r\n }\r\n if (c === \"/\" && regexAllowed()) {\r\n let j = i + 1;\r\n let inClass = false;\r\n let closed = false;\r\n while (j < n) {\r\n const d = src[j]!;\r\n if (d === \"\\\\\") {\r\n j += 2;\r\n continue;\r\n }\r\n if (d === \"\\n\" || d === \"\\r\") break;\r\n if (d === \"[\") inClass = true;\r\n else if (d === \"]\") inClass = false;\r\n else if (d === \"/\" && !inClass) {\r\n closed = true;\r\n break;\r\n }\r\n j++;\r\n }\r\n if (closed) {\r\n j++;\r\n while (j < n && /[a-z]/i.test(src[j]!)) j++;\r\n out.push({ k: \"num\", v: \"/re/\" });\r\n i = j;\r\n continue;\r\n }\r\n out.push({ k: \"p\", v: \"/\" });\r\n i++;\r\n continue;\r\n }\r\n if (/[0-9]/.test(c)) {\r\n let j = i + 1;\r\n while (j < n && /[0-9A-Za-z_.]/.test(src[j]!)) j++;\r\n out.push({ k: \"num\", v: src.slice(i, j) });\r\n i = j;\r\n continue;\r\n }\r\n if (isIdStart(c)) {\r\n let j = i + 1;\r\n while (j < n && isIdPart(src[j]!)) j++;\r\n out.push({ k: \"id\", v: src.slice(i, j) });\r\n i = j;\r\n continue;\r\n }\r\n if (inSubstitution) {\r\n if (c === \"{\") depth++;\r\n else if (c === \"}\") {\r\n if (depth === 0) return i + 1;\r\n depth--;\r\n }\r\n }\r\n out.push({ k: \"p\", v: c });\r\n i++;\r\n }\r\n return n;\r\n }\r\n\r\n scan(0, false);\r\n return out;\r\n}\r\n\r\n/**\r\n * The module specifiers a JavaScript/TypeScript file names, in order of first appearance, each once: static\r\n * `import \u2026 from`, side-effect `import \"x\"`, `export \u2026 from`, `import(\"x\")`, `require(\"x\")` and\r\n * `import x = require(\"x\")`. Only string literals (or a template with no substitution) count; an expression is\r\n * ignored, as are comments, text inside strings and a method that merely happens to be called `require`.\r\n */\r\nexport function extractImportSpecifiers(source: string): string[] {\r\n const t = tokenize(source);\r\n const found: string[] = [];\r\n const seen = new Set<string>();\r\n const add = (s: string) => {\r\n if (!seen.has(s)) {\r\n seen.add(s);\r\n found.push(s);\r\n }\r\n };\r\n const isP = (tok: Token | undefined, v: string) => tok?.k === \"p\" && tok.v === v;\r\n\r\n for (let i = 0; i < t.length; i++) {\r\n const tok = t[i]!;\r\n if (tok.k !== \"id\") continue;\r\n if (isP(t[i - 1], \".\")) continue; // obj.import / obj.require \u2014 a property, not the keyword\r\n\r\n if (tok.v === \"require\") {\r\n if (isP(t[i + 1], \"(\") && t[i + 2]?.k === \"str\" && isP(t[i + 3], \")\")) add(t[i + 2]!.v);\r\n continue;\r\n }\r\n if (tok.v !== \"import\" && tok.v !== \"export\") continue;\r\n\r\n const next = t[i + 1];\r\n if (tok.v === \"import\") {\r\n if (next?.k === \"str\") {\r\n add(next.v);\r\n continue;\r\n }\r\n if (isP(next, \"(\")) {\r\n if (t[i + 2]?.k === \"str\" && (isP(t[i + 3], \")\") || isP(t[i + 3], \",\"))) add(t[i + 2]!.v);\r\n continue;\r\n }\r\n }\r\n // import <clause> from \"x\" / export <clause> from \"x\". The scan ends at the next import or export, so a long\r\n // chain of back-to-back statements (`export{a}export{b}\u2026`, no semicolons) is read once, not once per statement.\r\n for (let j = i + 1; j < t.length; j++) {\r\n const c = t[j]!;\r\n if (c.k === \"id\") {\r\n if (c.v === \"import\" || c.v === \"export\") break;\r\n if (c.v === \"from\" && t[j + 1]?.k === \"str\") {\r\n add(t[j + 1]!.v);\r\n break;\r\n }\r\n continue;\r\n }\r\n if (c.k === \"p\" && (c.v === \"{\" || c.v === \"}\" || c.v === \",\" || c.v === \"*\")) continue;\r\n break;\r\n }\r\n }\r\n return found;\r\n}\r\n\r\n/** Files the scanner understands. */\r\nexport function supportsImportScan(path: string): boolean {\r\n return /\\.(?:[cm]?[jt]sx?)$/i.test(path);\r\n}\r\n\r\n// \u2500\u2500 turning a specifier into a file in the repository \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport type ResolvedImport =\r\n | { kind: \"repo\"; path: string }\r\n | { kind: \"external\" }\r\n | { kind: \"unresolved\"; reason: \"alias\" | \"not found\" | \"asset\"; attempted?: string };\r\n\r\nconst CODE_EXTS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\", \".json\"];\r\nconst ASSET_EXTS = new Set([\r\n \".css\", \".scss\", \".sass\", \".less\", \".svg\", \".png\", \".jpg\", \".jpeg\", \".gif\", \".webp\", \".avif\", \".ico\", \".bmp\",\r\n \".woff\", \".woff2\", \".ttf\", \".otf\", \".eot\", \".mp3\", \".mp4\", \".webm\", \".wav\", \".pdf\", \".zip\", \".wasm\",\r\n]);\r\n/** TypeScript's ESM habit: `./x.js` written in source, `x.ts` on disk. */\r\nconst TS_SIBLINGS: Record<string, string[]> = { \".js\": [\".ts\", \".tsx\"], \".jsx\": [\".tsx\"], \".mjs\": [\".mts\"], \".cjs\": [\".cts\"] };\r\n\r\n/**\r\n * Where a specifier points. `listing` is the repository's file list (the same notion of \"what exists\" targeting's\r\n * context paths are checked against), so nothing is probed on disk and nothing outside it is ever followed.\r\n */\r\nexport function resolveImport(fromPath: string, specifier: string, listing: ReadonlySet<string>): ResolvedImport {\r\n if (/^(?:@\\/|~\\/|#|\\$|\\/)/.test(specifier)) return { kind: \"unresolved\", reason: \"alias\" };\r\n const clean = specifier.replace(/[?#].*$/, \"\");\r\n const relative = clean === \".\" || clean === \"..\" || clean.startsWith(\"./\") || clean.startsWith(\"../\");\r\n if (!relative) return { kind: \"external\" };\r\n\r\n const base = posix.normalize(posix.join(posix.dirname(fromPath), clean));\r\n if (base === \"..\" || base.startsWith(\"../\") || posix.isAbsolute(base)) return { kind: \"unresolved\", reason: \"not found\" };\r\n\r\n const ext = posix.extname(base);\r\n if (ASSET_EXTS.has(ext.toLowerCase())) return { kind: \"unresolved\", reason: \"asset\" };\r\n\r\n const candidates: string[] = [];\r\n if (CODE_EXTS.includes(ext)) {\r\n candidates.push(base);\r\n for (const sibling of TS_SIBLINGS[ext] ?? []) candidates.push(base.slice(0, -ext.length) + sibling);\r\n }\r\n for (const e of CODE_EXTS) candidates.push(base + e);\r\n candidates.push(base + \".d.ts\");\r\n for (const e of CODE_EXTS) candidates.push(`${base}/index${e}`);\r\n\r\n for (const candidate of candidates) {\r\n if (listing.has(candidate)) return { kind: \"repo\", path: candidate };\r\n }\r\n return { kind: \"unresolved\", reason: \"not found\", attempted: base };\r\n}\r\n\r\n// \u2500\u2500 what gets added \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nexport interface ImportContextParams {\r\n targetPath: string;\r\n /** The target's content on disk now. */\r\n source: string;\r\n /** Paths already in front of the model for this call (targeting's list and the run's other files). */\r\n alreadyNamed: ReadonlySet<string>;\r\n deniedPaths: string[];\r\n listing: ReadonlySet<string>;\r\n readFile: (path: string) => string;\r\n maxFileChars: number;\r\n maxTotalChars: number;\r\n /** Characters the run's other added files already spent against `maxTotalChars`. */\r\n spentChars: number;\r\n}\r\n\r\nexport interface ImportContext {\r\n entries: { path: string; content: string }[];\r\n skipped: { path: string; reason: string }[];\r\n /** The paths of `entries`, for the context log. */\r\n importedPaths: string[];\r\n /** Path-alias imports (`@/x`) seen and not followed. Counted, not listed: they can be many. */\r\n aliasImports: number;\r\n}\r\n\r\n/** Skips worth a line in the run's notes: the file mattered and could not be shown. The rest stay in the log. */\r\nexport const ACTIONABLE_IMPORT_SKIPS = new Set([\"import: too large\", \"import: over budget\", \"import: unreadable\"]);\r\n\r\n/**\r\n * The direct imports of one target, read and sized like the run's other added files (same per-file and total\r\n * limits, shared). Order is first appearance in the file. A path already named, already added, or the target\r\n * itself is never repeated; a denied path is never read.\r\n */\r\nexport function collectImportContext(p: ImportContextParams): ImportContext {\r\n const out: ImportContext = { entries: [], skipped: [], importedPaths: [], aliasImports: 0 };\r\n if (!supportsImportScan(p.targetPath)) return out;\r\n\r\n const seen = new Set<string>(p.alreadyNamed);\r\n seen.add(p.targetPath);\r\n let total = p.spentChars;\r\n\r\n for (const specifier of extractImportSpecifiers(p.source)) {\r\n const resolved = resolveImport(p.targetPath, specifier, p.listing);\r\n if (resolved.kind === \"external\") continue;\r\n if (resolved.kind === \"unresolved\") {\r\n if (resolved.reason === \"alias\") out.aliasImports++;\r\n else if (resolved.reason === \"not found\") {\r\n const path = resolved.attempted ?? specifier;\r\n if (!seen.has(path)) {\r\n seen.add(path);\r\n out.skipped.push({ path, reason: \"import: not in workspace\" });\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n const path = resolved.path;\r\n if (seen.has(path)) continue;\r\n seen.add(path);\r\n // Defence in depth, like the run-file collector: a path in context is read and sent to the model provider.\r\n if (matchesDeniedPath(path, p.deniedPaths)) {\r\n out.skipped.push({ path, reason: \"import: denied\" });\r\n continue;\r\n }\r\n let content: string;\r\n try {\r\n content = p.readFile(path);\r\n } catch {\r\n out.skipped.push({ path, reason: \"import: unreadable\" });\r\n continue;\r\n }\r\n if (content.length > p.maxFileChars) {\r\n out.skipped.push({ path, reason: \"import: too large\" });\r\n } else if (total + content.length > p.maxTotalChars) {\r\n out.skipped.push({ path, reason: \"import: over budget\" });\r\n } else {\r\n total += content.length;\r\n out.entries.push({ path, content });\r\n out.importedPaths.push(path);\r\n }\r\n }\r\n return out;\r\n}\r\n", "/**\r\n * QUIKTR-1069 \u2014 a gateway timeout in front of the AI Runtime is not a refusal: the demo rehearsal\r\n * hit a 504 from a devtunnel/load balancer, not the runtime, and the same call succeeded on retry.\r\n * Retries ONLY transport-level signals \u2014 HTTP 502/503/504, or a thrown network error\r\n * (ECONNRESET/ETIMEDOUT) \u2014 twice, with a short fixed backoff. Every other failure (a real refusal,\r\n * CODEGEN_FILE_TOO_LARGE, success:false+errorCode, any 4xx) arrives as a normal HTTP 200 with the\r\n * refusal inside the envelope body, or a genuine non-transient 4xx \u2014 neither ever matches this\r\n * function's retry condition, so nothing here needs to special-case them.\r\n *\r\n * Spend: a retried call the runtime actually completed has been paid for twice. maxRunUsd already\r\n * caps the run (enforced at the gateway, per packet.ts's own comment), so this fails safe \u2014 the\r\n * worst case is hitting the budget wall slightly sooner, never an uncapped spend.\r\n */\r\nconst RETRYABLE_STATUS_CODES = new Set([502, 503, 504]);\r\nconst RETRYABLE_NETWORK_ERROR_CODES = new Set([\"ECONNRESET\", \"ETIMEDOUT\"]);\r\n\r\nfunction isRetryableNetworkError(err: unknown): boolean {\r\n const code =\r\n (err as { cause?: { code?: string } } | undefined)?.cause?.code ??\r\n (err as { code?: string } | undefined)?.code;\r\n return typeof code === \"string\" && RETRYABLE_NETWORK_ERROR_CODES.has(code);\r\n}\r\n\r\nexport async function fetchWithRetry(\r\n url: string,\r\n init: RequestInit,\r\n { retries = 2, backoffMs = 250 }: { retries?: number; backoffMs?: number } = {},\r\n): Promise<Response> {\r\n for (let attempt = 0; ; attempt++) {\r\n try {\r\n const res = await fetch(url, init);\r\n if (RETRYABLE_STATUS_CODES.has(res.status) && attempt < retries) {\r\n await new Promise((r) => setTimeout(r, backoffMs));\r\n continue;\r\n }\r\n return res;\r\n } catch (err) {\r\n if (isRetryableNetworkError(err) && attempt < retries) {\r\n await new Promise((r) => setTimeout(r, backoffMs));\r\n continue;\r\n }\r\n throw err;\r\n }\r\n }\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport { resolve, join } from \"node:path\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\n\r\n/**\r\n * QUIKTR-1045 \u2014 codegen importing a package the repository doesn't have currently fails safely\r\n * (setup already ran, so the package genuinely isn't installed, and the regression check catches\r\n * the resulting test failure) but with the WRONG diagnosis: it reads as \"the generated logic is\r\n * broken\" when the real problem is a fabricated import. This names that failure correctly instead.\r\n *\r\n * Only a minimal regex import-scanner \u2014 not a real JS/TS parser. Same reasoning\r\n * `regressionCheck.ts` already states for its own hand-rolled JUnit scanner: this package is\r\n * dependency-free on purpose (published outside the monorepo, bundled into a single CLI file with\r\n * no externals \u2014 see build.mjs), so a real parser is off the table, not merely unused.\r\n *\r\n * Explicitly scoped to JS/TS: it only acts when a `package.json` is found. A repo in another\r\n * language has none, `readDeclaredDependencies` returns null, and the check no-ops \u2014 this is what\r\n * keeps it from looking like a general \"detect the repo's language\" mechanism, which it isn't.\r\n */\r\nexport interface DependencyViolation {\r\n file: string;\r\n packages: string[];\r\n}\r\n\r\nexport interface DependencyCheck {\r\n blocked: boolean;\r\n violations: DependencyViolation[];\r\n}\r\n\r\nconst SCANNABLE_EXTENSIONS = [\".ts\", \".tsx\", \".js\", \".jsx\", \".mjs\", \".cjs\", \".mts\", \".cts\"];\r\n\r\n// import ... from \"x\" / import \"x\" / export ... from \"x\" / require(\"x\") / import(\"x\")\r\nconst IMPORT_RE = /(?:\\bimport\\b[^'\"]*?\\bfrom\\s*|\\bimport\\s*\\(\\s*|\\bexport\\b[^'\"]*?\\bfrom\\s*|\\brequire\\s*\\(\\s*|\\bimport\\s+)(['\"])([^'\"]+)\\1/g;\r\n\r\n// Not exhaustive \u2014 same \"minimal, not exhaustive\" treatment regressionCheck.ts's own scanner uses.\r\nconst NODE_BUILTINS = new Set([\r\n \"assert\", \"buffer\", \"child_process\", \"cluster\", \"crypto\", \"dgram\", \"dns\", \"domain\", \"events\",\r\n \"fs\", \"http\", \"http2\", \"https\", \"net\", \"os\", \"path\", \"perf_hooks\", \"process\", \"punycode\",\r\n \"querystring\", \"readline\", \"repl\", \"stream\", \"string_decoder\", \"sys\", \"timers\", \"tls\", \"tty\",\r\n \"url\", \"util\", \"v8\", \"vm\", \"worker_threads\", \"zlib\", \"inspector\", \"async_hooks\",\r\n]);\r\n\r\n// QUIKTR-1063 \u2014 the two path-alias conventions common enough to assume even\r\n// when a repo's tsconfig can't be read or parsed: \"@/...\" (QuikTrack,\r\n// QuikChat, and most of this monorepo's own apps) and \"~/...\". Without this,\r\n// \"@/lib/x\" was parsed as the scoped package \"@/lib\" \u2014 a real package.json\r\n// entry it could never actually match \u2014 and every aliased import in a repo\r\n// using either convention was reported as an invented dependency.\r\n//\r\n// QUIKTR-1068 \u2014 this is now a FLOOR, not the whole answer: `resolveAliasPrefixes`\r\n// below adds whatever a real tsconfig.json/jsconfig.json actually declares in\r\n// `compilerOptions.paths`, for repos using some other convention entirely.\r\n// Always unioned in regardless of what a config says, so a repo with no\r\n// config (or an unparseable one) keeps exactly today's behavior.\r\nconst DEFAULT_ALIAS_PREFIXES = [\"@/\", \"~/\"];\r\n\r\nfunction packageNameFromSpecifier(specifier: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string | null {\r\n if (specifier.startsWith(\".\") || specifier.startsWith(\"/\")) return null; // relative/absolute\r\n if (specifier.startsWith(\"node:\")) return null; // explicit builtin\r\n if (aliasPrefixes.some((prefix) => specifier.startsWith(prefix))) return null; // path alias\r\n const segments = specifier.split(\"/\");\r\n const name = specifier.startsWith(\"@\") ? segments.slice(0, 2).join(\"/\") : segments[0];\r\n if (NODE_BUILTINS.has(name)) return null;\r\n return name;\r\n}\r\n\r\nfunction scanImports(source: string, aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES): string[] {\r\n const found = new Set<string>();\r\n let match: RegExpExecArray | null;\r\n IMPORT_RE.lastIndex = 0;\r\n while ((match = IMPORT_RE.exec(source))) {\r\n const name = packageNameFromSpecifier(match[2], aliasPrefixes);\r\n if (name) found.add(name);\r\n }\r\n return [...found];\r\n}\r\n\r\n/** Pure \u2014 no fs, trivially unit-testable. `declaredDependencies === null` means \"couldn't tell\r\n * what this repo declares\" (no package.json, or unparseable) \u2014 the check no-ops rather than\r\n * blocking on a question it can't actually answer. `aliasPrefixes` defaults to the floor above;\r\n * callers with a real tsconfig read (see `resolveAliasPrefixes`) pass the fuller list. */\r\nexport function checkImportDependencies(\r\n results: CodegenFileResult[],\r\n declaredDependencies: Set<string> | null,\r\n aliasPrefixes: string[] = DEFAULT_ALIAS_PREFIXES,\r\n): DependencyCheck {\r\n if (!declaredDependencies) return { blocked: false, violations: [] };\r\n\r\n const violations: DependencyViolation[] = [];\r\n for (const { targetPath, newContent } of results) {\r\n if (!SCANNABLE_EXTENSIONS.some((ext) => targetPath.endsWith(ext))) continue;\r\n const invented = scanImports(newContent, aliasPrefixes).filter((pkg) => !declaredDependencies.has(pkg));\r\n if (invented.length > 0) violations.push({ file: targetPath, packages: invented });\r\n }\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\ninterface PackageJson {\r\n dependencies?: Record<string, string>;\r\n devDependencies?: Record<string, string>;\r\n peerDependencies?: Record<string, string>;\r\n}\r\n\r\nfunction dependencyNames(pkg: PackageJson): Set<string> {\r\n // devDependencies included deliberately \u2014 a generated test file may legitimately import one.\r\n return new Set([\r\n ...Object.keys(pkg.dependencies ?? {}),\r\n ...Object.keys(pkg.devDependencies ?? {}),\r\n ...Object.keys(pkg.peerDependencies ?? {}),\r\n ]);\r\n}\r\n\r\n/**\r\n * Reads the target repo's declared dependencies. Checks `results` FIRST for a generated\r\n * `package.json` \u2014 codegen may have legitimately added the very dependency it's about to import,\r\n * and reading the pre-generation file on disk would false-flag that. Falls back to the on-disk\r\n * file, and to `null` (\u2192 the check no-ops) when neither exists or parses.\r\n */\r\nexport function readDeclaredDependencies(\r\n results: CodegenFileResult[],\r\n workspaceRoot: string | null,\r\n): Set<string> | null {\r\n const packageJsonPath = join(resolve(workspaceRoot ?? \".\"), \"package.json\");\r\n const generated = results.find((r) => resolve(r.targetPath) === packageJsonPath);\r\n\r\n let raw: string | null;\r\n if (generated) {\r\n raw = generated.newContent;\r\n } else {\r\n try {\r\n raw = readFileSync(packageJsonPath, \"utf8\");\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n if (raw === null) return null;\r\n\r\n try {\r\n return dependencyNames(JSON.parse(raw) as PackageJson);\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * QUIKTR-1068 \u2014 strips line and block comments plus trailing commas from a JSON(C) string, best\r\n * effort. Not a real JSONC parser: a character scanner rather than a regex replace (a regex would\r\n * corrupt a string VALUE containing `//`, e.g. a URL), but anything it can't cleanly handle just\r\n * fails `JSON.parse` afterward \u2014 `resolveAliasPrefixes` below treats that the same as no config at\r\n * all and falls back to the floor. Never throws itself.\r\n */\r\nfunction stripJsonComments(text: string): string {\r\n let out = \"\";\r\n let inString = false;\r\n let inLineComment = false;\r\n let inBlockComment = false;\r\n for (let i = 0; i < text.length; i++) {\r\n const c = text[i];\r\n const next = text[i + 1];\r\n if (inLineComment) {\r\n if (c === \"\\n\") {\r\n inLineComment = false;\r\n out += c;\r\n }\r\n continue;\r\n }\r\n if (inBlockComment) {\r\n if (c === \"*\" && next === \"/\") {\r\n inBlockComment = false;\r\n i++;\r\n }\r\n continue;\r\n }\r\n if (inString) {\r\n out += c;\r\n if (c === \"\\\\\") {\r\n out += next;\r\n i++;\r\n continue;\r\n }\r\n if (c === '\"') inString = false;\r\n continue;\r\n }\r\n if (c === '\"') {\r\n inString = true;\r\n out += c;\r\n continue;\r\n }\r\n if (c === \"/\" && next === \"/\") {\r\n inLineComment = true;\r\n i++;\r\n continue;\r\n }\r\n if (c === \"/\" && next === \"*\") {\r\n inBlockComment = true;\r\n i++;\r\n continue;\r\n }\r\n out += c;\r\n }\r\n return out.replace(/,(\\s*[}\\]])/g, \"$1\");\r\n}\r\n\r\ninterface TsOrJsConfig {\r\n compilerOptions?: { paths?: Record<string, unknown> };\r\n}\r\n\r\n/**\r\n * QUIKTR-1068 \u2014 `DEFAULT_ALIAS_PREFIXES` is a floor, not the whole answer: a repo may declare its\r\n * own alias conventions in `compilerOptions.paths`. Tries `tsconfig.json` then `jsconfig.json` at\r\n * the workspace root (same results-first-then-disk precedence as `readDeclaredDependencies` \u2014 a\r\n * generated config this run legitimately wrote should win over a stale on-disk one), unions any\r\n * `paths` keys (wildcard stripped: `\"@/*\"` \u2192 `\"@/\"`) with the floor, and dedupes. Never throws and\r\n * never returns fewer than the floor \u2014 an unreadable or malformed config is exactly the same as no\r\n * config, not a reason to block a run that could otherwise pass.\r\n *\r\n * Does NOT follow `extends` \u2014 only the root config's own `paths`, same \"minimal, not exhaustive\"\r\n * boundary this file already draws elsewhere (see the module docblock).\r\n */\r\nexport function resolveAliasPrefixes(\r\n results: CodegenFileResult[],\r\n workspaceRoot: string | null,\r\n): string[] {\r\n const root = resolve(workspaceRoot ?? \".\");\r\n\r\n for (const filename of [\"tsconfig.json\", \"jsconfig.json\"]) {\r\n const configPath = join(root, filename);\r\n const generated = results.find((r) => resolve(r.targetPath) === configPath);\r\n\r\n let raw: string | null;\r\n if (generated) {\r\n raw = generated.newContent;\r\n } else {\r\n try {\r\n raw = readFileSync(configPath, \"utf8\");\r\n } catch {\r\n raw = null;\r\n }\r\n }\r\n if (raw === null) continue;\r\n\r\n try {\r\n const parsed = JSON.parse(stripJsonComments(raw)) as TsOrJsConfig;\r\n const paths = parsed.compilerOptions?.paths;\r\n const fromConfig =\r\n paths && typeof paths === \"object\"\r\n ? Object.keys(paths).map((k) => (k.endsWith(\"*\") ? k.slice(0, -1) : k))\r\n : [];\r\n return [...new Set([...DEFAULT_ALIAS_PREFIXES, ...fromConfig])];\r\n } catch {\r\n continue; // malformed \u2014 try the next config file, or fall through to the floor\r\n }\r\n }\r\n\r\n return DEFAULT_ALIAS_PREFIXES;\r\n}\r\n\r\n/** Regressions and new failures named separately elsewhere in this package for the same reason\r\n * this exists at all: conflating diagnoses wastes someone's morning. */\r\nexport function describeDependencyViolations(check: DependencyCheck): string {\r\n return check.violations\r\n .map((v) => `${v.file} imports ${v.packages.join(\", \")}, not a dependency of this repository`)\r\n .join(\"; \");\r\n}\r\n", "import { addAll, diffCachedNamesMatching } from \"./git\";\r\n\r\n/** Stages everything, then refuses to proceed if any staged file matches a denied-path glob.\r\n * Public and inspectable on purpose (Suyash, 2026-09-10): moving this into a published package\r\n * doesn't hide the enforcement \u2014 it's the same check, just no longer duplicated per customer repo. */\r\nexport function checkGuardrail(deniedPaths: string[]): void {\r\n addAll();\r\n const violations = deniedPaths.flatMap((pattern) => diffCachedNamesMatching(pattern));\r\n if (violations.length > 0) {\r\n throw new Error(`QuikPilot touched denied paths:\\n${violations.join(\"\\n\")}`);\r\n }\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\ninterface InstallationTokenResponse {\r\n success: boolean;\r\n data: { token: string; expiresAt: string };\r\n}\r\n\r\n/** Exchange the QuikPilot run token for a repo-scoped GitHub installation token (QUIKTR-804) \u2014\r\n * mirrors `tokenExchange.ts`'s `exchangeForRunToken` shape: bearer auth, `{success,data}`\r\n * envelope, same error-message style. */\r\nexport async function exchangeForInstallationToken(\r\n installationTokenUrl: string,\r\n runToken: string,\r\n): Promise<string> {\r\n const res = await fetch(installationTokenUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Exchange installation token failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as InstallationTokenResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Exchange installation token failed: response did not carry success:true\");\r\n }\r\n return body.data.token;\r\n}\r\n", "import { required } from \"./env\";\r\n\r\n/** Must equal `apps/quiktrack/lib/services/github/oidc.ts`'s own copy of this literal \u2014 that app\r\n * verifies the token this package requests. Duplicated because this package is published outside\r\n * the monorepo and cannot import from the app; same reasoning `packet.ts`'s header gives for\r\n * duplicating `PilotPacket`'s shape. */\r\nconst QUIKPILOT_OIDC_AUDIENCE = \"quiktrack-quikpilot\";\r\n\r\ninterface OidcTokenResponse {\r\n value: string;\r\n}\r\n\r\n/** Request a GitHub Actions OIDC ID token \u2014 the runner's proof of identity, exchanged at\r\n * `TOKEN_URL` for a QuikPilot run token (QUIKTR-805). `ACTIONS_ID_TOKEN_REQUEST_URL` and\r\n * `ACTIONS_ID_TOKEN_REQUEST_TOKEN` are ambient GitHub Actions env vars, present only because the\r\n * generated workflow declares `permissions: id-token: write` \u2014 no dispatch input carries them. */\r\nexport async function fetchGithubOidcToken(\r\n env: NodeJS.ProcessEnv = process.env,\r\n): Promise<string> {\r\n const requestUrl = required(\r\n \"ACTIONS_ID_TOKEN_REQUEST_URL\",\r\n env.ACTIONS_ID_TOKEN_REQUEST_URL,\r\n );\r\n const requestToken = required(\r\n \"ACTIONS_ID_TOKEN_REQUEST_TOKEN\",\r\n env.ACTIONS_ID_TOKEN_REQUEST_TOKEN,\r\n );\r\n const separator = requestUrl.includes(\"?\") ? \"&\" : \"?\";\r\n const url = `${requestUrl}${separator}audience=${encodeURIComponent(QUIKPILOT_OIDC_AUDIENCE)}`;\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${requestToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Fetch GitHub OIDC token failed: ${res.status} ${res.statusText}`);\r\n }\r\n const body = (await res.json()) as OidcTokenResponse;\r\n if (!body.value) {\r\n throw new Error(\"GitHub OIDC token response carried no value\");\r\n }\r\n return body.value;\r\n}\r\n", "import type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1064 \u2014 QUIKSP-3's first live run implemented \"reject negative amounts\" twice: once in\r\n * src/server.js against raw input, once in src/validation.js against parsed minor units. Targeting\r\n * split the work across two files and gave each its own planStepsImplemented describing the same\r\n * rule; codegen faithfully built both. Per-target steps are meant to be DISJOINT (QUIKTR-1035) \u2014\r\n * nothing checked that they are.\r\n *\r\n * The real fix is `pilot.targeting`'s prompt \u2014 an AI Runtime change, not this package's. This is\r\n * the cheap half the ticket assigns here: a non-blocking warning, not semantic analysis. A\r\n * significant-word overlap between two steps in DIFFERENT targets is treated as the same rule\r\n * described twice. Same-target steps are never compared \u2014 one file legitimately implementing\r\n * several related steps is normal and not what this looks for.\r\n */\r\nexport interface OverlapWarning {\r\n targetA: string;\r\n stepA: string;\r\n targetB: string;\r\n stepB: string;\r\n /** QUIKTR-1081 \u2014 \"identical\" (the exact same instruction, modulo case/whitespace) is blocking;\r\n * \"similar\" (the existing Jaccard-threshold match, reworded but not the same text) stays a\r\n * warning. Two legitimate halves of one change never share the literal same instruction. */\r\n severity: \"identical\" | \"similar\";\r\n}\r\n\r\n// QUIKTR-1081 \u2014 a path-convention heuristic, not a real \"is this a test\" signal: nothing in this\r\n// package (or apps/quiktrack/lib/services/pilot) tags a PilotTarget as covering a test today. A\r\n// behaviour appearing in both a file and its test is correct, so a pair is exempt from this check\r\n// entirely \u2014 not merely from blocking \u2014 whenever either side looks like a test file.\r\nconst TEST_PATH_RE = /(\\.(test|spec)\\.[jt]sx?$)|(^|\\/)(__tests__|tests?)\\//i;\r\n\r\nexport function isTestTarget(path: string): boolean {\r\n return TEST_PATH_RE.test(path);\r\n}\r\n\r\nconst STOPWORDS = new Set([\r\n \"a\", \"an\", \"the\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\r\n \"of\", \"to\", \"in\", \"on\", \"for\", \"with\", \"at\", \"by\", \"from\", \"as\",\r\n \"and\", \"or\", \"not\", \"no\", \"nor\",\r\n \"this\", \"that\", \"these\", \"those\", \"it\", \"its\",\r\n \"cannot\", \"can't\", \"should\", \"must\", \"may\", \"will\", \"shall\",\r\n \"when\", \"if\", \"than\", \"then\", \"so\", \"do\", \"does\", \"did\",\r\n]);\r\n\r\n// Ignore words this short too \u2014 they add noise to the overlap without carrying meaning (\"id\",\r\n// \"an\", two-letter fragments from punctuation stripping).\r\nconst MIN_WORD_LENGTH = 3;\r\n\r\nfunction significantWords(step: string): Set<string> {\r\n return new Set(\r\n step\r\n .toLowerCase()\r\n .replace(/[^a-z0-9\\s]/g, \" \")\r\n .split(/\\s+/)\r\n .filter((w) => w.length >= MIN_WORD_LENGTH && !STOPWORDS.has(w)),\r\n );\r\n}\r\n\r\nfunction jaccard(a: Set<string>, b: Set<string>): number {\r\n if (a.size === 0 || b.size === 0) return 0;\r\n let intersection = 0;\r\n for (const w of a) if (b.has(w)) intersection++;\r\n const union = a.size + b.size - intersection;\r\n return intersection / union;\r\n}\r\n\r\n// QUIKTR-1081 \u2014 stricter than significantWords' normalization (which drops stopwords/short words\r\n// entirely): this only ignores case and incidental whitespace, so \"identical\" means the actual\r\n// same instruction, not merely \"shares enough meaningful words.\"\r\nfunction normalizedStep(step: string): string {\r\n return step.trim().toLowerCase().replace(/\\s+/g, \" \");\r\n}\r\n\r\n// Cheap and deliberately generous \u2014 a false positive here costs a reviewer one glance at a warning\r\n// line; a false negative is exactly the bug this exists to catch.\r\nconst OVERLAP_THRESHOLD = 0.5;\r\n\r\n/** Every cross-target pair of plan steps whose significant words overlap enough to plausibly be the\r\n * same rule described twice. Steps within the same target are never compared. */\r\nexport function findOverlappingSteps(targets: PilotTarget[]): OverlapWarning[] {\r\n const items = targets.flatMap((target) =>\r\n target.planStepsImplemented.map((step) => ({\r\n target: target.path,\r\n step,\r\n words: significantWords(step),\r\n })),\r\n );\r\n\r\n const warnings: OverlapWarning[] = [];\r\n for (let i = 0; i < items.length; i++) {\r\n for (let j = i + 1; j < items.length; j++) {\r\n if (items[i].target === items[j].target) continue;\r\n if (isTestTarget(items[i].target) || isTestTarget(items[j].target)) continue;\r\n if (jaccard(items[i].words, items[j].words) >= OVERLAP_THRESHOLD) {\r\n warnings.push({\r\n targetA: items[i].target,\r\n stepA: items[i].step,\r\n targetB: items[j].target,\r\n stepB: items[j].step,\r\n severity: normalizedStep(items[i].step) === normalizedStep(items[j].step) ? \"identical\" : \"similar\",\r\n });\r\n }\r\n }\r\n }\r\n return warnings;\r\n}\r\n\r\nexport function describeOverlapWarnings(warnings: OverlapWarning[]): string[] {\r\n return warnings.map(\r\n (w) =>\r\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.`,\r\n );\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\n/** Mirrors `apps/quiktrack/lib/services/pilot/packet.ts`'s `PilotPacket` shape. Duplicated rather\r\n * than imported \u2014 this package is published outside the monorepo and cannot depend on the app. */\r\nexport interface PilotPacket {\r\n runId: string;\r\n issueKey: string | null;\r\n /** QUIKTR-1067 \u2014 same nullability as issueKey, for the same reason: the commit message needs\r\n * both to say what actually changed instead of the hardcoded \"Phase 0 skeleton\" placeholder. */\r\n issueTitle: string | null;\r\n branch: string | null;\r\n targetBranch: string | null;\r\n /** QUIKTR-1033 \u2014 the subtree targeting (QUIKTR-1035) lists files under. Null means the\r\n * repository root, as null \u2014 never normalised to \".\". */\r\n workspaceRoot: string | null;\r\n commands: {\r\n setup: string | null;\r\n test: string | null;\r\n e2e: string | null;\r\n lint: string | null;\r\n /** QUIKTR-1045 \u2014 run after codegen flushes, before lint. Soft failure. */\r\n format: string | null;\r\n /** QUIKTR-1402 \u2014 runs ONE test file (path appended, or substituted for `{file}`) against the untouched\r\n * code, for the baseline check. Optional: an older QuikTrack omits it. Null/absent turns the check off. */\r\n testFile?: string | null;\r\n };\r\n guardrails: {\r\n deniedPaths: string[];\r\n maxHealIterations: number;\r\n maxWallClockMinutes: number;\r\n // No maxRunUsd \u2014 it travels as a claim on gateway.token instead (QUIKTR-823).\r\n };\r\n /** Where to call for AI codegen, and the credential that authorizes it. */\r\n gateway: {\r\n baseUrl: string;\r\n token: string;\r\n };\r\n /** The pilot.design technical design, as context for codegen. No file paths \u2014 see the app's\r\n * spec-contract.ts. Null only in theory (dispatch requires a design to already exist). */\r\n design: {\r\n rootCause: string;\r\n approach: string;\r\n /** Mirrors `apps/quiktrack/lib/services/pilot/spec-contract.ts`'s `PilotApiChange`. */\r\n apiChanges: { surface: string; change: string; reason: string }[];\r\n riskLevel: \"LOW\" | \"MEDIUM\" | \"HIGH\";\r\n riskRationale: string;\r\n } | null;\r\n quikTest: { testRunId: string; resultsUrl: string } | null;\r\n /** QUIKTR-1065 \u2014 the approved test cases codegen still owes real test code for. Sent to\r\n * pilot.targeting so it can propose a test-file target naming which cases it covers; today\r\n * nothing reads this field yet (the AI Runtime side isn't built), so it always arrives as `[]`\r\n * or is silently unused once wired up here. */\r\n requiredTests: {\r\n automationId: string;\r\n title: string;\r\n covers: string[];\r\n given: string | null;\r\n when: string | null;\r\n then: string | null;\r\n }[];\r\n /** QUIKTR-1402 \u2014 automationId -> the case's current type (FUNCTIONAL, NEGATIVE, REGRESSION, \u2026), only for\r\n * cases whose AI-assigned label QuikTrack recorded. Optional: an older QuikTrack omits it. A case that is\r\n * absent here is UNKNOWN and is never checked; REGRESSION is exempt. DELIBERATELY not a field of\r\n * `requiredTests`: those objects are forwarded to the AI Runtime as-is, and an unknown key on the\r\n * versioned path is refused CONTRACT_REJECTED. Nothing in this map may ever be sent to the runtime. */\r\n requiredTestTypes?: Record<string, string>;\r\n /** QUIKTR-1401 \u2014 the reviewer's approved \"things QuikPilot must not change\" list. Optional: a\r\n * QuikTrack that predates the field omits it. Forwarded to pilot.targeting and pilot.codegen (\u00A720,\r\n * deployed by the AI Runtime 2026-10-01) when non-empty, never to pilot.design. Free text, so unlike\r\n * `deniedPaths` it can only be told to the model, not checked. */\r\n outOfScope?: string[];\r\n /** QUIKTR-1315, \u00A719 of the AI Runtime contract (AGREED, final tagged shape) \u2014 the repo-relative\r\n * files the last DONE run's own ingested JUnit report named, sourced from stored QuikTest data,\r\n * not a live baseline capture here. Always present (never undefined) \u2014 \u00A719.12: a project with no\r\n * prior DONE run's report is `{ report: \"ABSENT\" }`, not an omitted field. `{ report: \"PRESENT\" }`\r\n * with an empty `discoveredTestFiles` is a different, real fact: a report was ingested but\r\n * nothing in it was path-shaped. See targeting.ts for how this is forwarded. */\r\n testDiscovery:\r\n | { report: \"PRESENT\"; discoveredTestFiles: string[]; unmappedEntries: number }\r\n | { report: \"ABSENT\" };\r\n}\r\n\r\ninterface PacketResponse {\r\n success: boolean;\r\n data: PilotPacket;\r\n}\r\n\r\n/** GET the run's work packet. Bearer auth via the run token, matching the header curl sent on\r\n * stdin (`--config -`) so it never showed up in `ps` \u2014 an HTTP client's header option is already\r\n * invisible to `ps`, so no equivalent trick is needed here. */\r\nexport async function fetchPacket(\r\n packetUrl: string,\r\n runToken: string,\r\n githubRunId: string,\r\n): Promise<PilotPacket> {\r\n const url = `${packetUrl}?githubRunId=${encodeURIComponent(githubRunId)}`;\r\n const res = await fetch(url, {\r\n headers: { Authorization: `Bearer ${runToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Fetch work packet failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as PacketResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Fetch work packet failed: response did not carry success:true\");\r\n }\r\n return body.data;\r\n}\r\n", "import { appendFileSync, mkdirSync } from \"node:fs\";\r\n\r\n/** Phase 0 has no agent. This proves the loop end to end without touching real source, which would\r\n * risk breaking the build for a reason nobody would connect back to QuikPilot. Verbatim carry-over\r\n * from the inlined workflow \u2014 real codegen is separate, not-yet-built work. */\r\nexport function writePhase0Marker(runId: string): void {\r\n mkdirSync(\".quikpilot\", { recursive: true });\r\n appendFileSync(\".quikpilot/phase0-marker.txt\", `QuikPilot Phase 0 skeleton marker for run ${runId}\\n`);\r\n}\r\n", "import { readFileSync, readdirSync, rmSync, statSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\"]);\r\n\r\nfunction walkForJUnitByName(dir: string): string | null {\r\n let entries: string[];\r\n try {\r\n entries = readdirSync(dir);\r\n } catch {\r\n return null;\r\n }\r\n for (const entry of entries) {\r\n if (SKIP_DIRS.has(entry)) continue;\r\n const full = join(dir, entry);\r\n let stat;\r\n try {\r\n stat = statSync(full);\r\n } catch {\r\n continue;\r\n }\r\n if (stat.isDirectory()) {\r\n const found = walkForJUnitByName(full);\r\n if (found) return found;\r\n } else if (/^junit.*\\.xml$/.test(entry)) {\r\n return full;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\nfunction firstXmlIn(dir: string, namePattern: RegExp): string | null {\r\n let entries: string[];\r\n try {\r\n entries = readdirSync(dir);\r\n } catch {\r\n return null;\r\n }\r\n const match = entries.find((e) => namePattern.test(e));\r\n return match ? join(dir, match) : null;\r\n}\r\n\r\n/** The test report as bytes, or null when there is none or it cannot be read. QUIKTR-1447 takes a copy for a failed\r\n * run BEFORE `reportToQuikTest` sends and deletes it. */\r\nexport function readTestReportBytes(cwd = process.cwd()): Buffer | null {\r\n try {\r\n const report = findJUnitReport(cwd);\r\n return report ? readFileSync(report) : null;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** QtPilotConfig has no column for the report path, so this is a convention over a short list of\r\n * common locations rather than a configurable setting. A project that writes its report elsewhere\r\n * reports nothing and finds out from the log \u2014 a missing artefact must not fail the run. Checked\r\n * in the same priority the original `find` clause listed them, though exact traversal order was\r\n * never guaranteed there either. */\r\nexport function findJUnitReport(cwd = process.cwd()): string | null {\r\n return (\r\n walkForJUnitByName(cwd) ??\r\n firstXmlIn(join(cwd, \"test-results\"), /\\.xml$/) ??\r\n firstXmlIn(join(cwd, \"reports\"), /^junit.*\\.xml$/) ??\r\n firstXmlIn(join(cwd, \"target\", \"surefire-reports\"), /\\.xml$/)\r\n );\r\n}\r\n\r\nfunction buildCiUrl(serverUrl: string, repository: string, githubRunId: string): string {\r\n return `${serverUrl}/${repository}/actions/runs/${githubRunId}`;\r\n}\r\n\r\n/** The ingest route's summary of automationIds present in the JUnit report that matched no\r\n * `QtTestCase` \u2014 computed and returned by QuikTrack's own ingest today (`IngestSummary.unmatched`\r\n * in `apps/quiktrack/lib/services/testIngest.ts`), but silently discarded here until QUIKTR-1374:\r\n * a bracket/format mismatch (or any other ingest failure) produced zero matches on every run with\r\n * nothing on screen to say why. */\r\nexport interface ReportToQuikTestResult {\r\n unmatched: Array<{ automationId: string; count: number }>;\r\n}\r\n\r\n/** One warning naming every unmatched id and its count \u2014 `null` when there's nothing to report,\r\n * so the caller can push straight into `warnings` without an extra length check. */\r\nexport function describeUnmatchedAutomationIds(unmatched: ReportToQuikTestResult[\"unmatched\"]): string | null {\r\n if (unmatched.length === 0) return null;\r\n const named = unmatched.map((u) => `${u.automationId} (\u00D7${u.count})`).join(\", \");\r\n return `${unmatched.length} generated test result(s) did not match any test case: ${named} \u2014 check the automationId format.`;\r\n}\r\n\r\n/** Best-effort \u2014 every branch here is designed to never throw, matching the bash step's own\r\n * `if: always()` + internally tolerant logic (null resultsUrl and \"no report found\" are both the\r\n * common path in Phase 0, not edge cases \u2014 D19). Deletes the report after a successful POST so the\r\n * guardrail's `git add -A` never commits a CI artefact into the customer's pull request. Returns\r\n * `null` whenever nothing was actually reported (no results URL, no report found, or the POST\r\n * itself failed) \u2014 the caller folds a non-null `unmatched` array into the run's warnings. */\r\nexport async function reportToQuikTest(params: {\r\n resultsUrl: string | null | undefined;\r\n runToken: string;\r\n githubServerUrl: string;\r\n githubRepository: string;\r\n githubRunId: string;\r\n /** QUIKTR-1333 \u2014 the files QuikPilot actually generated or edited this run. Scopes QuikTrack's\r\n * unmatched-automationId warning to just these, so a repository's own pre-existing tests (which\r\n * can never carry a QuikPilot id) stop being reported as unmatched on every single run.\r\n * `undefined` = no scoping information (the server keeps its unfiltered behavior). An EMPTY\r\n * array is a real answer \u2014 codegen produced nothing (it failed, or there was no target) \u2014 and is\r\n * sent as an empty parameter so the server scopes to nothing instead of falling back. */\r\n generatedFiles?: string[];\r\n cwd?: string;\r\n}): Promise<ReportToQuikTestResult | null> {\r\n const { resultsUrl, runToken, githubServerUrl, githubRepository, githubRunId, generatedFiles, cwd } = params;\r\n if (!resultsUrl) {\r\n console.log(\"packet.quikTest is null \u2014 this run has no QuikTest run to report into.\");\r\n return null;\r\n }\r\n const report = findJUnitReport(cwd);\r\n if (!report) {\r\n console.warn(\"::warning::QuikPilot found no JUnit report \u2014 no results reported to QuikTest.\");\r\n return null;\r\n }\r\n try {\r\n console.log(`reporting ${report}`);\r\n const ciUrl = buildCiUrl(githubServerUrl, githubRepository, githubRunId);\r\n const { readFileSync } = await import(\"node:fs\");\r\n const body = readFileSync(report);\r\n // QUIKTR-1082 \u2014 this runner is the only caller QuikPilot controls; requesting \"bracket\"\r\n // explicitly here changes nothing for any other QuikTest customer's own ingestion.\r\n let url = `${resultsUrl}?ciUrl=${encodeURIComponent(ciUrl)}&automationIdFormat=bracket`;\r\n // QUIKTR-1333 \u2014 optional: an old runner or a human's manual upload (the sibling route) never\r\n // sends this, and the server falls back to today's unfiltered behavior either way. Sent even\r\n // when empty: \"generated nothing\" must not be mistaken for \"no information\".\r\n if (generatedFiles) {\r\n url += `&generatedFiles=${encodeURIComponent(generatedFiles.join(\",\"))}`;\r\n }\r\n const res = await fetch(url, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${runToken}`, \"Content-Type\": \"text/xml\" },\r\n body,\r\n });\r\n if (!res.ok) {\r\n throw new Error(`QuikTest report POST failed: ${res.status} ${res.statusText}`);\r\n }\r\n rmSync(report, { force: true });\r\n // QUIKTR-1374 \u2014 read the ingest summary instead of discarding it. Best-effort: the POST\r\n // itself already succeeded (res.ok), so a body that isn't the expected JSON shape must never\r\n // turn a working report into a failure \u2014 it just means no warning can be derived from it.\r\n let unmatched: ReportToQuikTestResult[\"unmatched\"] = [];\r\n try {\r\n const json = (await res.json()) as { data?: { unmatched?: ReportToQuikTestResult[\"unmatched\"] } };\r\n unmatched = json.data?.unmatched ?? [];\r\n } catch {\r\n // Not JSON, or not the expected shape \u2014 leave unmatched empty.\r\n }\r\n return { unmatched };\r\n } catch (err) {\r\n console.warn(`::warning::QuikPilot failed to report results to QuikTest: ${err instanceof Error ? err.message : String(err)}`);\r\n return null;\r\n }\r\n}\r\n", "import { execFileSync } from \"node:child_process\";\r\nimport { existsSync, mkdirSync, readFileSync, rmSync, rmdirSync, statSync, writeFileSync } from \"node:fs\";\r\nimport { dirname, isAbsolute, relative, resolve } from \"node:path\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\nimport { runCommandWithTimeout, type TimedRunOutcome } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\nimport { readAutomationIdResults } from \"./regressionCheck\";\r\nimport type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1402 \u2014 the baseline check.\r\n *\r\n * A spec can contain a case that asserts something ALREADY TRUE before any change (\"the server route\r\n * remains unchanged\"); no test can satisfy it, and a phrase list cannot catch the next phrasing. What every\r\n * such case shares is not wording but behaviour: its generated test PASSES on the unmodified code. So,\r\n * after codegen and before anything is written for real, this writes ONLY the generated test files, runs\r\n * each one alone against the untouched code, flags a non-Regression case whose test passed, and puts\r\n * everything back. A Regression case is meant to pass there, so it is exempt.\r\n *\r\n * It FLAGS and never blocks: a no-op change is legitimate, and an unsatisfiable case is a spec problem a\r\n * person should see rather than a run that dies. Every uncertain outcome therefore means \"no flag\", and\r\n * every one of them is said out loud (a silent timeout would look exactly like a check that found nothing).\r\n *\r\n * Unknown is never flagged: only a case whose label QuikTrack recorded (`requiredTestTypes`) is checked,\r\n * so anything approved before the label was kept, and any label we did not recognise, is left alone.\r\n */\r\n\r\n/**\r\n * How long one single-file run may take before it is stopped. A constant, not a setting (Suyash): one more\r\n * knob is one more thing to get wrong, and nobody has the information to tune it. Measured on QuikTrack and\r\n * QuikChat, one file takes 2 to 5 seconds warm and up to ~14 seconds on a cold start; two minutes is far\r\n * outside that and only ever reached by a command that hangs, which produces no error and would otherwise\r\n * hold the run until the job's own limit while looking like QuikPilot being slow.\r\n */\r\nexport const BASELINE_CHECK_TIMEOUT_MS = 120_000;\r\n\r\nexport interface BaselineFindings {\r\n /** ALREADY_TRUE: the change altered the code but the case still passed before it. NO_OP: every file the\r\n * change edited came out unchanged. The check cannot tell the two apart for certain; the wording hedges. */\r\n cause: \"ALREADY_TRUE\" | \"NO_OP\";\r\n /** Case ids only \u2014 QuikTrack looks the titles up itself, so case text never travels. */\r\n automationIds: string[];\r\n}\r\n\r\nexport interface BaselineCheckResult {\r\n findings: BaselineFindings | null;\r\n /** Run-record sentences: a finding, or a reason the check could not give an answer. */\r\n warnings: string[];\r\n}\r\n\r\nexport interface BaselineCheckParams {\r\n targets: PilotTarget[];\r\n results: CodegenFileResult[];\r\n testFileCmd: string | null | undefined;\r\n /** automationId -> the case's current type, only for cases whose label is known. */\r\n requiredTestTypes: Record<string, string> | undefined;\r\n cwd?: string;\r\n /** Test seam: the real one spawns bash with a hard time limit. */\r\n runFile?: (command: string, timeoutMs: number) => Promise<TimedRunOutcome>;\r\n}\r\n\r\n/** POSIX single-quoting: the path is chosen by the model, so it must never be able to inject a command. */\r\nexport function shellQuote(value: string): string {\r\n return `'${value.split(\"'\").join(\"'\\\\''\")}'`;\r\n}\r\n\r\n/** `{file}` is replaced wherever it appears; with no placeholder the path is appended as the last argument. */\r\nexport function buildSingleFileCommand(command: string, path: string): string {\r\n const quoted = shellQuote(path);\r\n return command.includes(\"{file}\") ? command.split(\"{file}\").join(quoted) : `${command} ${quoted}`;\r\n}\r\n\r\nconst isTestTarget = (t: PilotTarget): boolean => (t.automationIds?.length ?? 0) > 0;\r\n\r\n/** A case is checked only if its label is KNOWN and is not Regression (which is supposed to pass). */\r\nfunction checkableIds(ids: string[], types: Record<string, string> | undefined): string[] {\r\n if (!types) return [];\r\n return ids.filter((id) => {\r\n if (!Object.prototype.hasOwnProperty.call(types, id)) return false;\r\n const type = types[id];\r\n return typeof type === \"string\" && type.trim() !== \"\" && type.trim().toUpperCase() !== \"REGRESSION\";\r\n });\r\n}\r\n\r\n/** Absolute path inside the checkout, or null when the target would land outside it. */\r\nfunction insideCheckout(cwd: string, path: string): string | null {\r\n const abs = resolve(cwd, path);\r\n const rel = relative(cwd, abs);\r\n return rel === \"\" || rel.startsWith(\"..\") || isAbsolute(rel) ? null : abs;\r\n}\r\n\r\ninterface WrittenFile {\r\n abs: string;\r\n /** null when the file did not exist before. */\r\n original: Buffer | null;\r\n /** Directories this check had to create, outermost first. */\r\n createdDirs: string[];\r\n}\r\n\r\nfunction writeForCheck(abs: string, content: string): WrittenFile {\r\n const original = existsSync(abs) ? readFileSync(abs) : null;\r\n const createdDirs: string[] = [];\r\n if (original === null) {\r\n const missing: string[] = [];\r\n for (let d = dirname(abs); !existsSync(d); d = dirname(d)) missing.push(d);\r\n for (const d of missing.reverse()) {\r\n mkdirSync(d);\r\n createdDirs.push(d);\r\n }\r\n }\r\n writeFileSync(abs, content);\r\n return { abs, original, createdDirs };\r\n}\r\n\r\nfunction restore(written: WrittenFile[]): void {\r\n for (const file of [...written].reverse()) {\r\n try {\r\n if (file.original !== null) writeFileSync(file.abs, file.original);\r\n else rmSync(file.abs, { force: true });\r\n for (const d of [...file.createdDirs].reverse()) {\r\n try {\r\n rmdirSync(d);\r\n } catch {\r\n // not empty or already gone \u2014 leave it\r\n }\r\n }\r\n } catch (err) {\r\n console.error(`Baseline check could not restore ${file.abs}: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n}\r\n\r\n/** Untracked, non-ignored files \u2014 exactly what the guardrail's `git add -A` would commit. `null` when git\r\n * cannot say, in which case nothing is cleaned up rather than guessing. */\r\nfunction untrackedFiles(cwd: string): Set<string> | null {\r\n try {\r\n const out = execFileSync(\"git\", [\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"], {\r\n cwd,\r\n encoding: \"utf8\",\r\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\r\n maxBuffer: 64 * 1024 * 1024,\r\n });\r\n return new Set(out.split(\"\\0\").filter(Boolean));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nconst mtimeOf = (path: string): number | null => {\r\n try {\r\n return statSync(path).mtimeMs;\r\n } catch {\r\n return null;\r\n }\r\n};\r\n\r\n/** NO_OP only when there is code to compare and every file the change edits came out exactly as it was. */\r\nfunction decideCause(targets: PilotTarget[], results: Map<string, string>, cwd: string): BaselineFindings[\"cause\"] {\r\n const codeTargets = targets.filter((t) => !isTestTarget(t));\r\n if (codeTargets.length === 0) return \"ALREADY_TRUE\";\r\n for (const t of codeTargets) {\r\n if (t.kind === \"NEW_FILE\") return \"ALREADY_TRUE\";\r\n const next = results.get(t.path);\r\n const abs = insideCheckout(cwd, t.path);\r\n if (next === undefined || abs === null) return \"ALREADY_TRUE\";\r\n try {\r\n if (readFileSync(abs, \"utf8\") !== next) return \"ALREADY_TRUE\";\r\n } catch {\r\n return \"ALREADY_TRUE\";\r\n }\r\n }\r\n return \"NO_OP\";\r\n}\r\n\r\nexport async function runBaselineCheck(params: BaselineCheckParams): Promise<BaselineCheckResult> {\r\n const { targets, results, testFileCmd, requiredTestTypes } = params;\r\n const cwd = params.cwd ?? process.cwd();\r\n const runFile = params.runFile ?? runCommandWithTimeout;\r\n const nothing: BaselineCheckResult = { findings: null, warnings: [] };\r\n\r\n if (!testFileCmd || testFileCmd.trim() === \"\") return nothing;\r\n const testTargets = targets.filter(isTestTarget);\r\n const toCheck = testTargets\r\n .map((target) => ({ target, ids: checkableIds(target.automationIds ?? [], requiredTestTypes) }))\r\n .filter((entry) => entry.ids.length > 0);\r\n if (toCheck.length === 0) {\r\n console.log(\"Baseline check: no case with a known, non-Regression label \u2014 nothing to check.\");\r\n return nothing;\r\n }\r\n\r\n const warnings: string[] = [];\r\n const flagged: string[] = [];\r\n const written: WrittenFile[] = [];\r\n const unsafe = new Set<string>();\r\n const skip = (path: string, why: string) => {\r\n const message = `Baseline check skipped for ${path}: ${why}`;\r\n console.warn(`::warning::${message}`);\r\n warnings.push(message);\r\n };\r\n\r\n try {\r\n const contentByPath = new Map(results.map((r) => [r.targetPath, r.newContent]));\r\n const cause = decideCause(targets, contentByPath, cwd);\r\n\r\n // Only the generated TEST files are written; the code under test stays exactly as it is.\r\n for (const target of testTargets) {\r\n const content = contentByPath.get(target.path);\r\n if (content === undefined) continue;\r\n const abs = insideCheckout(cwd, target.path);\r\n if (abs === null) {\r\n unsafe.add(target.path);\r\n continue;\r\n }\r\n written.push(writeForCheck(abs, content));\r\n }\r\n\r\n for (const { target, ids } of toCheck) {\r\n if (unsafe.has(target.path)) {\r\n skip(target.path, \"the path is outside the checkout, so the file was not written or run.\");\r\n continue;\r\n }\r\n if (!contentByPath.has(target.path)) continue;\r\n\r\n const reportBefore = findJUnitReport(cwd);\r\n const mtimeBefore = reportBefore ? mtimeOf(reportBefore) : null;\r\n const untrackedBefore = untrackedFiles(cwd);\r\n\r\n const outcome = await runFile(buildSingleFileCommand(testFileCmd, target.path), BASELINE_CHECK_TIMEOUT_MS);\r\n\r\n if (outcome === \"timeout\") {\r\n skip(\r\n target.path,\r\n `the single-file command did not finish within ${BASELINE_CHECK_TIMEOUT_MS / 1000} seconds and was stopped. ` +\r\n \"No test case from this file was flagged.\",\r\n );\r\n } else if (outcome === \"error\") {\r\n skip(target.path, \"the single-file command could not be started. No test case from this file was flagged.\");\r\n } else {\r\n const reportAfter = findJUnitReport(cwd);\r\n const fresh = reportAfter !== null && (reportAfter !== reportBefore || mtimeOf(reportAfter) !== mtimeBefore);\r\n if (!fresh) {\r\n skip(\r\n target.path,\r\n \"the single-file command wrote no new JUnit report (it must write the same JUnit report as the test \" +\r\n \"command), so nothing could be checked.\",\r\n );\r\n } else {\r\n const byId = readAutomationIdResults(cwd);\r\n for (const id of ids) if (byId?.get(id) === \"pass\") flagged.push(id);\r\n }\r\n }\r\n\r\n // The report has been read; now remove whatever this run left behind that the guardrail would commit\r\n // (a snapshot file written against the OLD behaviour would make the real run fail). Never anything\r\n // that existed before this run.\r\n const untrackedAfter = untrackedFiles(cwd);\r\n if (untrackedBefore && untrackedAfter) {\r\n for (const file of untrackedAfter) {\r\n if (untrackedBefore.has(file)) continue;\r\n const abs = insideCheckout(cwd, file);\r\n if (abs) rmSync(abs, { force: true });\r\n }\r\n }\r\n }\r\n\r\n if (flagged.length === 0) return { findings: null, warnings };\r\n\r\n const automationIds = [...new Set(flagged)].slice(0, 200);\r\n const list = automationIds.join(\", \");\r\n warnings.push(\r\n cause === \"NO_OP\"\r\n ? `Baseline check: ${automationIds.length} test case(s) passed against the unmodified code, and every file the ` +\r\n `generated change edited came out unchanged, so the change itself may have been a no-op: ${list}.`\r\n : `Baseline check: ${automationIds.length} test case(s) passed against the unmodified code, so they may assert ` +\r\n `something already true: ${list}. This check cannot tell that from a change that did nothing.`,\r\n );\r\n return { findings: { cause, automationIds }, warnings };\r\n } catch (err) {\r\n const message = `Baseline check could not run: ${err instanceof Error ? err.message : String(err)}`;\r\n console.warn(`::warning::${message}`);\r\n return { findings: null, warnings: [...warnings, message] };\r\n } finally {\r\n restore(written);\r\n }\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport { runTestCommand, runTestCommandAsync, type TestOutcome } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\n\r\n/**\r\n * QUIKTR-1036 \u2014 once codegen writes real code, a failing test after it probably means the\r\n * generated code (or a generated test) is wrong. Blocking unconditionally would break any repo\r\n * with pre-existing failures, so a run captures a \"before\" snapshot (the baseline, run against the\r\n * untouched tree) and an \"after\" snapshot (post-codegen), and diffs them per test:\r\n * passed before, fails now -> regression, block\r\n * absent before, fails now -> new failure, block (codegen writing test files makes this the\r\n * common case, not an edge case \u2014 a different diagnosis from a\r\n * regression, so it's reported separately)\r\n * failed before, fails now -> not ours, stays soft (the case the soft-fail existed for)\r\n *\r\n * Only a minimal <testcase> scanner \u2014 not a full XML parser like\r\n * apps/quiktrack/lib/test/resultParser.ts, which extracts failure messages/stack traces across\r\n * multiple formats for QuikTest's ingest API and can't be imported here anyway (this package is\r\n * published outside the monorepo \u2014 same reason packet.ts duplicates its types instead of sharing\r\n * them). classname::name (or bare name with no classname) is an internal-only identity, used only\r\n * to match a test between two local runs \u2014 it never needs to match QuikTest's own configurable\r\n * automationIdFormat.\r\n */\r\nexport interface TestSnapshot {\r\n outcome: TestOutcome;\r\n /** testId -> passed. null when no JUnit report was found or it couldn't be parsed \u2014 the\r\n * fallback used when either snapshot lacks this is to stay soft, same as today, since blocking\r\n * with no way to name what broke would contradict the whole point of the classification. */\r\n results: Map<string, boolean> | null;\r\n /**\r\n * QUIKTR-1029 self-heal prerequisite 1 (Suyash, 2026-09-22 \u2014 \"buildable now and useful on its\r\n * own: today a regression blocks the push without saying why the test failed\"). testId -> a\r\n * bounded failure message, only for tests that failed IN THIS SNAPSHOT. Deliberately a second,\r\n * optional map rather than widening `results`'s value type: `checkForRegressions`'s diffing\r\n * logic (and every existing test constructing a `TestSnapshot` fixture directly) stays untouched\r\n * \u2014 this is additive context, not a new signal the diff itself reasons about.\r\n */\r\n failureText?: Map<string, string>;\r\n /**\r\n * QUIKTR-1315 \u2014 the file paths the test runner itself discovered, read from each `<testsuite>`'s\r\n * `file` attribute and each `<testcase>`'s `file`/`classname` attributes, verbatim (backslashes\r\n * normalised to forward slashes only). `null` when no report was found \u2014 same \"can't tell, don't\r\n * block\" posture as `results`. An empty (non-null) set means a report existed but carried no\r\n * file-shaped attribution at all \u2014 also treated as \"can't tell\" by `testPlacementCheck.ts`, not as\r\n * \"nothing was discovered.\" Best-effort only: `classname` is a real file path for Vitest and\r\n * derivable for pytest, but not guaranteed for Jest (depends on `jest-junit` config) or Go\r\n * (typically package-, not file-, scoped) \u2014 see `testPlacementCheck.ts`'s own docblock for how\r\n * this is matched loosely rather than exactly for that reason.\r\n */\r\n discoveredFiles?: Set<string> | null;\r\n /**\r\n * QUIKTR-1315 \u2014 every `[<automationId>]` leading-bracket token found in a `<testcase>` name,\r\n * duplicating `apps/quiktrack/lib/test/resultParser.ts`'s `LEADING_BRACKET_RE` convention (this\r\n * package can't import that file \u2014 published outside the monorepo). `null` when no report was\r\n * found, same as `discoveredFiles`.\r\n */\r\n discoveredAutomationIds?: Set<string> | null;\r\n}\r\n\r\nconst TESTCASE_RE = /<testcase\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/testcase>)/g;\r\nconst NAME_ATTR_RE = /\\bname=\"([^\"]*)\"/;\r\nconst CLASSNAME_ATTR_RE = /\\bclassname=\"([^\"]*)\"/;\r\nconst FAILURE_CHILD_RE = /<failure\\b|<error\\b/;\r\nconst SKIPPED_CHILD_RE = /<skipped\\b/;\r\n\r\n// QUIKTR-1315 \u2014 `<testsuite>` open tags only (not self-closed the way an empty `<testcase/>` can\r\n// be): a suite always wraps at least its own attributes even with zero testcases inside.\r\nconst TESTSUITE_OPEN_RE = /<testsuite\\b([^>]*?)>/g;\r\nconst FILE_ATTR_RE = /\\bfile=\"([^\"]*)\"/;\r\n// QUIKTR-1082/1374's convention, duplicated \u2014 see this file's module docblock and\r\n// `TestSnapshot`'s `discoveredAutomationIds` field for why this can't just import\r\n// resultParser.ts instead. Matches QuikPilot's own token shape (QP-<PROJECT-KEY>-<issue>-<n>)\r\n// anywhere in the name rather than requiring it at the start \u2014 a bare \"[Smoke]\"-style tag can\r\n// never satisfy this shape, so QUIKTR-1082's \"don't match an unrelated bracketed tag\" safety\r\n// property holds without depending on position, which Vitest's JUnit reporter doesn't preserve.\r\nconst QP_TOKEN_BRACKET_RE = /\\[(QP-[A-Z][A-Z0-9]*-\\d+-\\d+)\\]/;\r\n\r\nfunction normalizeSlashes(path: string): string {\r\n return path.replace(/\\\\/g, \"/\");\r\n}\r\n\r\n/** The `<failure>`/`<error>` child itself, within one `<testcase>`'s already-isolated body. */\r\nconst FAILURE_TAG_RE = /<(?:failure|error)\\b([^>]*?)(?:\\/>|>([\\s\\S]*?)<\\/(?:failure|error)>)/;\r\nconst FAILURE_MESSAGE_ATTR_RE = /\\bmessage=\"([^\"]*)\"/;\r\n\r\n/** Console/PR-message budget, not a data-integrity bound \u2014 this is display text, never re-parsed. */\r\nconst MAX_FAILURE_TEXT = 500;\r\n\r\n/** The five entities the JUnit writers in real use (Vitest, Jest, pytest, go-junit-report) all\r\n * produce \u2014 not a general XML-unescape, same \"minimal scanner, not a parser\" posture as the rest\r\n * of this file. Literal `"`/`&` reaching a console log or a PR body reads as broken. */\r\nfunction unescapeXmlEntities(s: string): string {\r\n return s.replace(/</g, \"<\").replace(/>/g, \">\").replace(/"/g, '\"').replace(/'/g, \"'\").replace(/&/g, \"&\");\r\n}\r\n\r\n/** A file Vite cannot parse is reported with one generic message whatever the file or the syntax error;\r\n * only a `File: <path>:<line>[:<col>]` line in the body says which file and where (Vitest 4.1.11). */\r\nconst FAILURE_FILE_LINE_RE = /^[ \\t]*File:[ \\t]*(\\S[^\\r\\n]*?:\\d+(?::\\d+)?)[ \\t]*$/m;\r\nconst MAX_FAILURE_LOCATION = 300;\r\n\r\nfunction parseFailureLocation(body: string): string | null {\r\n const found = FAILURE_FILE_LINE_RE.exec(unescapeXmlEntities(body));\r\n if (!found) return null;\r\n const path = normalizeSlashes(found[1]);\r\n const root = `${normalizeSlashes(process.cwd()).replace(/\\/+$/, \"\")}/`;\r\n const shown = path.startsWith(root) ? path.slice(root.length) : path;\r\n return shown.length > MAX_FAILURE_LOCATION ? `${shown.slice(0, MAX_FAILURE_LOCATION)}\u2026` : shown;\r\n}\r\n\r\n/** `message=\"...\"` when present (short, what every framework puts the assertion diff in);\r\n * otherwise the tag's own body text (stack trace), truncated \u2014 never both, never neither if\r\n * either exists. `null` when the testcase body has no `<failure>`/`<error>` at all, or the tag\r\n * carries no text either way (both attrs and body empty \u2014 seen from at least one Go harness).\r\n *\r\n * Exception: when the message attribute is used and the body names a file and position (a file that\r\n * failed to parse), that location is appended, because the message alone cannot say which file. */\r\nfunction extractFailureText(testcaseBody: string): string | null {\r\n const tag = FAILURE_TAG_RE.exec(testcaseBody);\r\n if (!tag) return null;\r\n const [, attrs = \"\", inner = \"\"] = tag;\r\n const messageAttr = FAILURE_MESSAGE_ATTR_RE.exec(attrs)?.[1];\r\n const raw = (messageAttr ?? inner).trim();\r\n if (!raw) return null;\r\n const text = unescapeXmlEntities(raw);\r\n const shortened = text.length > MAX_FAILURE_TEXT ? `${text.slice(0, MAX_FAILURE_TEXT)}\u2026` : text;\r\n const location = messageAttr === undefined ? null : parseFailureLocation(inner);\r\n return location ? `${shortened} [at ${location}]` : shortened;\r\n}\r\n\r\n/** QUIKTR-1402 \u2014 one QuikPilot case's result in a report. `skipped` is its own answer, NOT a pass: a test\r\n * that did not run shows nothing about the case, and the baseline check must never read it as \"passed\". */\r\nexport type AutomationIdResult = \"pass\" | \"fail\" | \"skipped\";\r\n\r\n/** When several tests carry one case's id, the worst answer wins: fail > skipped > pass. */\r\nconst RESULT_RANK: Record<AutomationIdResult, number> = { pass: 0, skipped: 1, fail: 2 };\r\n\r\ninterface JUnitParseResult {\r\n outcomes: Map<string, boolean>;\r\n automationIdResults: Map<string, AutomationIdResult>;\r\n failureText: Map<string, string>;\r\n discoveredFiles: Set<string>;\r\n discoveredAutomationIds: Set<string>;\r\n}\r\n\r\nfunction parseJUnitOutcomes(xml: string): JUnitParseResult {\r\n const outcomes = new Map<string, boolean>();\r\n const automationIdResults = new Map<string, AutomationIdResult>();\r\n const failureText = new Map<string, string>();\r\n const discoveredFiles = new Set<string>();\r\n const discoveredAutomationIds = new Set<string>();\r\n\r\n TESTSUITE_OPEN_RE.lastIndex = 0;\r\n let suiteMatch: RegExpExecArray | null;\r\n while ((suiteMatch = TESTSUITE_OPEN_RE.exec(xml))) {\r\n const file = FILE_ATTR_RE.exec(suiteMatch[1])?.[1];\r\n if (file) discoveredFiles.add(normalizeSlashes(file));\r\n }\r\n\r\n let match: RegExpExecArray | null;\r\n TESTCASE_RE.lastIndex = 0;\r\n while ((match = TESTCASE_RE.exec(xml))) {\r\n const [, attrs, body = \"\"] = match;\r\n // A test's identity is its title as a person reads it. JUnit writers escape it (\"describe > test\" arrives as\r\n // \"describe > test\"), and the identity is what a failed run's reason names, so it is unescaped here once.\r\n const rawName = NAME_ATTR_RE.exec(attrs)?.[1];\r\n if (!rawName) continue;\r\n const name = unescapeXmlEntities(rawName);\r\n const rawClassname = CLASSNAME_ATTR_RE.exec(attrs)?.[1];\r\n const classname = rawClassname === undefined ? undefined : unescapeXmlEntities(rawClassname);\r\n const id = classname ? `${classname}::${name}` : name;\r\n const failed = FAILURE_CHILD_RE.test(body);\r\n outcomes.set(id, !failed);\r\n if (failed) {\r\n const text = extractFailureText(body);\r\n if (text) failureText.set(id, text);\r\n }\r\n const file = FILE_ATTR_RE.exec(attrs)?.[1];\r\n if (file) discoveredFiles.add(normalizeSlashes(file));\r\n if (classname) discoveredFiles.add(normalizeSlashes(classname));\r\n const bracket = QP_TOKEN_BRACKET_RE.exec(name)?.[1];\r\n if (bracket) {\r\n discoveredAutomationIds.add(bracket);\r\n const result: AutomationIdResult = failed ? \"fail\" : SKIPPED_CHILD_RE.test(body) ? \"skipped\" : \"pass\";\r\n const seen = automationIdResults.get(bracket);\r\n if (!seen || RESULT_RANK[result] > RESULT_RANK[seen]) automationIdResults.set(bracket, result);\r\n }\r\n }\r\n return { outcomes, automationIdResults, failureText, discoveredFiles, discoveredAutomationIds };\r\n}\r\n\r\nfunction readJUnitOutcomes(cwd: string): JUnitParseResult | null {\r\n const report = findJUnitReport(cwd);\r\n if (!report) return null;\r\n try {\r\n return parseJUnitOutcomes(readFileSync(report, \"utf8\"));\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/** QUIKTR-1402 \u2014 per-case results from whatever JUnit report is on disk now; `null` when none is found or\r\n * it cannot be parsed (\"could not tell\", which the baseline check must treat differently from \"nothing\r\n * passed\"). Deliberately not part of TestSnapshot: only the baseline check reads it. */\r\nexport function readAutomationIdResults(cwd = process.cwd()): Map<string, AutomationIdResult> | null {\r\n return readJUnitOutcomes(cwd)?.automationIdResults ?? null;\r\n}\r\n\r\nexport function captureTestSnapshot(command: string | null, cwd = process.cwd()): TestSnapshot {\r\n const outcome = runTestCommand(command);\r\n const parsed = readJUnitOutcomes(cwd);\r\n return {\r\n outcome,\r\n results: parsed?.outcomes ?? null,\r\n failureText: parsed?.failureText,\r\n discoveredFiles: parsed?.discoveredFiles ?? null,\r\n discoveredAutomationIds: parsed?.discoveredAutomationIds ?? null,\r\n };\r\n}\r\n\r\nexport async function captureBaselineSnapshot(\r\n command: string | null,\r\n cwd = process.cwd(),\r\n): Promise<TestSnapshot> {\r\n const outcome = await runTestCommandAsync(command);\r\n const parsed = readJUnitOutcomes(cwd);\r\n return {\r\n outcome,\r\n results: parsed?.outcomes ?? null,\r\n failureText: parsed?.failureText,\r\n discoveredFiles: parsed?.discoveredFiles ?? null,\r\n discoveredAutomationIds: parsed?.discoveredAutomationIds ?? null,\r\n };\r\n}\r\n\r\nexport interface RegressionCheck {\r\n blocked: boolean;\r\n regressions: string[];\r\n newFailures: string[];\r\n preExisting: string[];\r\n /** testId -> bounded failure text, for whichever `regressions`/`newFailures` entries had one in\r\n * the AFTER snapshot (the failure that actually blocks the push \u2014 the baseline's own failure\r\n * text, if any, is irrelevant here). Always present, possibly empty \u2014 never omitted, so a\r\n * caller never has to guard its absence the way `results` itself still requires. */\r\n failureText: Map<string, string>;\r\n}\r\n\r\nexport function checkForRegressions(baseline: TestSnapshot, after: TestSnapshot): RegressionCheck {\r\n if (!baseline.results || !after.results) {\r\n return { blocked: false, regressions: [], newFailures: [], preExisting: [], failureText: new Map() };\r\n }\r\n\r\n const regressions: string[] = [];\r\n const newFailures: string[] = [];\r\n const preExisting: string[] = [];\r\n const failureText = new Map<string, string>();\r\n const afterFailureText = after.failureText;\r\n\r\n for (const [testId, passed] of after.results) {\r\n if (passed) continue;\r\n const before = baseline.results.get(testId);\r\n if (before === true) {\r\n regressions.push(testId);\r\n const text = afterFailureText?.get(testId);\r\n if (text) failureText.set(testId, text);\r\n } else if (before === false) {\r\n preExisting.push(testId);\r\n } else {\r\n newFailures.push(testId);\r\n const text = afterFailureText?.get(testId);\r\n if (text) failureText.set(testId, text);\r\n }\r\n }\r\n\r\n return { blocked: regressions.length > 0 || newFailures.length > 0, regressions, newFailures, preExisting, failureText };\r\n}\r\n\r\n/** Regressions and new failures named separately \u2014 conflating them is the thing that wastes\r\n * someone's morning (they're different diagnoses: one means the generated code broke something\r\n * that worked, the other means a generated test doesn't pass yet). Pre-existing failures are\r\n * noted, not hidden, so the message doesn't read as if they were silently dropped.\r\n *\r\n * QUIKTR-1029 self-heal prerequisite 1 \u2014 each named test now carries its failure text inline\r\n * when one was captured, so a run that blocks says WHY, not only WHAT. */\r\nexport function describeRegressions(check: RegressionCheck): string {\r\n const withText = (id: string) => {\r\n const text = check.failureText.get(id);\r\n return text ? `${id} (${text})` : id;\r\n };\r\n const parts: string[] = [];\r\n if (check.regressions.length > 0) {\r\n parts.push(\r\n `${check.regressions.length} regression(s) (passed before, now fail): ${check.regressions.map(withText).join(\", \")}`,\r\n );\r\n }\r\n if (check.newFailures.length > 0) {\r\n parts.push(\r\n `${check.newFailures.length} new failure(s) (did not exist before): ${check.newFailures.map(withText).join(\", \")}`,\r\n );\r\n }\r\n if (check.preExisting.length > 0) {\r\n parts.push(`${check.preExisting.length} pre-existing failure(s), unrelated to this change, not blocking`);\r\n }\r\n return parts.join(\"; \");\r\n}\r\n", "import { existsSync, mkdirSync, rmSync, writeFileSync } from \"node:fs\";\r\nimport { dirname, isAbsolute, join, relative, resolve } from \"node:path\";\r\nimport { scrubSecrets } from \"./failureReason\";\r\n\r\n/**\r\n * QUIKTR-1447 \u2014 what a failed run leaves behind for a person: the files QuikPilot wrote, the last test report and a short\r\n * manifest, in a folder the workflow uploads as an Actions artifact (kept 7 days, readable by whoever can see the repo's\r\n * Actions). Nothing goes to a branch or a pull request, and QuikTrack stores none of it.\r\n *\r\n * Written only after code generation finished, and never able to change how the run ends: the caller wraps it, and it\r\n * reports `written: false` instead of throwing.\r\n */\r\n\r\n/** Relative to the checkout root, which is where the workflow's upload step looks. */\r\nexport const FAILURE_ARTIFACT_DIR = \"quikpilot-failure\";\r\n\r\n/** Not named `junit*.xml`: the runner's own report finder walks the checkout for that pattern and would pick the copy up. */\r\nconst REPORT_COPY = \"final-test-report.xml\";\r\nconst MAX_REPORT_BYTES = 5 * 1024 * 1024;\r\nconst MAX_FILES = 200;\r\n\r\n// Replaced at build time (build.mjs); absent under vitest.\r\ndeclare const __RUNNER_VERSION__: string | undefined;\r\nconst RUNNER_VERSION = typeof __RUNNER_VERSION__ === \"string\" ? __RUNNER_VERSION__ : \"dev\";\r\n\r\nexport interface FailureArtifactInput {\r\n cwd: string;\r\n runId: string;\r\n issueKey: string | null;\r\n targets: ReadonlyArray<{ path: string; kind: string; automationIds?: string[] }>;\r\n results: ReadonlyArray<{ targetPath: string; newContent: string }>;\r\n /** The test report from the run after code generation, or null if no such run happened. A report from before\r\n * generation (the baseline) must never be passed. */\r\n testReport: Buffer | null;\r\n /** Already scrubbed and cut by the caller; scrubbed again here as the manifest is written. */\r\n failureReasons: readonly string[];\r\n /** Values that must not appear anywhere in the manifest, such as the run token. */\r\n secrets: readonly string[];\r\n}\r\n\r\n/** A path from the model must resolve inside the folder: absolute and parent-directory paths are refused. */\r\nfunction safeDestination(base: string, repoPath: string): string | null {\r\n if (!repoPath || isAbsolute(repoPath)) return null;\r\n const destination = resolve(base, repoPath);\r\n const rel = relative(base, destination);\r\n if (!rel || rel.startsWith(\"..\") || isAbsolute(rel)) return null;\r\n return destination;\r\n}\r\n\r\nexport function writeFailureArtifact(input: FailureArtifactInput): { written: boolean } {\r\n if (input.results.length === 0) return { written: false };\r\n try {\r\n const base = resolve(input.cwd, FAILURE_ARTIFACT_DIR);\r\n // A folder from an earlier call must not mix with this one.\r\n rmSync(base, { recursive: true, force: true });\r\n mkdirSync(base, { recursive: true });\r\n\r\n const files: Array<{ path: string; bytes: number }> = [];\r\n const skipped: string[] = [];\r\n for (const result of input.results) {\r\n const destination = files.length < MAX_FILES ? safeDestination(base, result.targetPath) : null;\r\n if (!destination) {\r\n skipped.push(result.targetPath);\r\n continue;\r\n }\r\n mkdirSync(dirname(destination), { recursive: true });\r\n writeFileSync(destination, result.newContent);\r\n files.push({ path: result.targetPath, bytes: Buffer.byteLength(result.newContent) });\r\n }\r\n\r\n let testReport: \"included\" | \"none\" | \"too-large\" = \"none\";\r\n if (input.testReport) {\r\n if (input.testReport.byteLength > MAX_REPORT_BYTES) {\r\n testReport = \"too-large\";\r\n } else {\r\n writeFileSync(join(base, REPORT_COPY), input.testReport);\r\n testReport = \"included\";\r\n }\r\n }\r\n\r\n const manifest = {\r\n runId: input.runId,\r\n issueKey: input.issueKey,\r\n runnerVersion: RUNNER_VERSION,\r\n generatedAt: new Date().toISOString(),\r\n targets: input.targets.map((t) => ({\r\n path: t.path,\r\n kind: t.kind,\r\n ...(t.automationIds && t.automationIds.length > 0 ? { automationIds: t.automationIds } : {}),\r\n })),\r\n files,\r\n skipped,\r\n testReport,\r\n failureReasons: input.failureReasons,\r\n };\r\n // Every string is scrubbed as the manifest is written, so a token that reached any field is taken out.\r\n const text = JSON.stringify(manifest, (_key, value) => (typeof value === \"string\" ? scrubSecrets(value, input.secrets) : value), 2);\r\n writeFileSync(join(base, \"manifest.json\"), text);\r\n return { written: existsSync(join(base, \"manifest.json\")) };\r\n } catch (err: unknown) {\r\n console.warn(`::warning::Could not keep the failed run's files: ${err instanceof Error ? err.message : String(err)}`);\r\n return { written: false };\r\n }\r\n}\r\n", "import { RuntimeReplyError } from \"./runtimeReplyError\";\r\n\r\n/** What a failed run tells QuikTrack about why. The message a hard failure threw used to go to the CI job log and\r\n * nowhere else; it is now sent, so it is written on one line, cut to a safe length, and has anything that looks like\r\n * a credential taken out first (an error from a failed push or request can carry one). */\r\nexport const MAX_FAILURE_REASON = 1000;\r\n\r\n/** Anything shorter than this is not treated as a secret to search for: replacing a three-letter \"token\" would wreck\r\n * every word that contains it. */\r\nconst MIN_SECRET_LENGTH = 8;\r\n\r\nconst CREDENTIAL_PATTERNS: RegExp[] = [\r\n /\\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9]{20,}/g,\r\n /\\bgithub_pat_[A-Za-z0-9_]{20,}/g,\r\n /x-access-token:[^@\\s'\"]+/gi,\r\n // Only the header form (\"Authorization: basic <token>\"), or a bearer value that contains a digit: a bare\r\n // \"basic authentication\" or \"bearer of the news\" is prose, not a credential.\r\n /\\bauthorization:\\s*(?:basic|bearer|token)\\s+[^\\s'\"]{8,}/gi,\r\n /\\bbearer\\s+(?=[A-Za-z0-9._~+/=-]*\\d)[A-Za-z0-9._~+/=-]{12,}/gi,\r\n // A signed JWT is three dot-separated segments; QuikPilot's own run token is an encrypted JWT (alg dir) of five, the\r\n // second one empty. The run token is also matched by exact value, but one that has expired or rotated is not the\r\n // current value, so its shape has to catch it.\r\n /\\beyJ[A-Za-z0-9_-]{8,}(?:\\.[A-Za-z0-9_-]*){2,4}/g,\r\n];\r\n\r\n/** What may leave the job for a thrown error: the summary when the error quotes the AI Runtime's reply, otherwise its\r\n * message. The full message is still printed to the job log by the caller. */\r\nexport function failureSummary(err: unknown): string {\r\n if (err instanceof RuntimeReplyError) return err.summary;\r\n return err instanceof Error ? err.message : String(err);\r\n}\r\n\r\n/** Takes known secrets (by value) and anything shaped like a credential out of a piece of text. Does not change the\r\n * text otherwise: no line folding, no cutting. */\r\nexport function scrubSecrets(message: string, secrets: readonly string[] = []): string {\r\n let text = message;\r\n for (const secret of secrets) {\r\n if (secret.length >= MIN_SECRET_LENGTH) text = text.split(secret).join(\"***\");\r\n }\r\n for (const pattern of CREDENTIAL_PATTERNS) text = text.replace(pattern, \"***\");\r\n return text;\r\n}\r\n\r\nexport function describeFailureReason(message: string, secrets: readonly string[] = []): string {\r\n let text = scrubSecrets(message, secrets);\r\n text = text.replace(/\\s*\\n\\s*/g, \" | \").trim();\r\n return text.length > MAX_FAILURE_REASON ? `${text.slice(0, MAX_FAILURE_REASON)}\u2026` : text;\r\n}\r\n", "import { readFileSync } from \"node:fs\";\r\nimport type { CodegenFileResult } from \"./codegen\";\r\nimport type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1081 \u2014 QUIKSPL-5's PR #22 fixed the reported bug in src/validation.js and also silently\r\n * added an undeclared PUT endpoint to src/server.js that returned success while updating nothing.\r\n * Tests passed, the dependency check passed, and nothing compared what codegen actually added\r\n * against the design's own declared `apiChanges` \u2014 because nothing did.\r\n *\r\n * Same \"minimal, not exhaustive\" standard as dependencyCheck.ts's import scanner and\r\n * regressionCheck.ts's JUnit scanner, for the same reason: this package is dependency-free,\r\n * bundled into a single CLI file with no externals, published outside the monorepo, and the\r\n * target repository is arbitrary \u2014 no real per-framework route parser is on the table. This is a\r\n * same-line METHOD+PATH text heuristic, a tripwire against the ticket's own incident (method and\r\n * path both named on the documenting comment's line), not a route parser for every framework a\r\n * customer repo might use. It will not catch a Next.js-style `export function PUT(...)` whose path\r\n * comes from file location rather than an in-file string \u2014 ROUTE_EXPORT_RE below covers that one\r\n * export shape specifically, matched by method presence alone since it has no in-file path to\r\n * compare.\r\n *\r\n * \"Exported symbols\" (the ticket's own words) is deliberately narrowed to route-handler-shaped\r\n * exports here, not any new exported symbol: an arbitrary new exported helper is routine,\r\n * legitimate refactoring, and checking every export against free-text `apiChanges` would produce\r\n * exactly the kind of false-positive noise this package's checks otherwise avoid.\r\n */\r\nexport interface ScopeViolation {\r\n file: string;\r\n method: string;\r\n path: string;\r\n}\r\n\r\nexport interface ScopeCheck {\r\n blocked: boolean;\r\n violations: ScopeViolation[];\r\n}\r\n\r\ninterface RouteMention {\r\n method: string;\r\n path: string;\r\n}\r\n\r\nconst ROUTE_METHOD_RE = /\\b(GET|POST|PUT|PATCH|DELETE)\\b/i;\r\nconst ROUTE_PATH_RE = /\\/[A-Za-z0-9_\\-{}[\\]]+(?:\\/[A-Za-z0-9_\\-:{}[\\]]+)+/;\r\nconst ROUTE_EXPORT_RE = /\\bexport\\s+(?:async\\s+)?function\\s+(GET|POST|PUT|PATCH|DELETE)\\s*\\(/;\r\n\r\n/** No in-file path \u2014 a Next.js-style route handler's path comes from where the file lives, not a\r\n * string in it. Matched against `apiChanges` by method presence alone (see `surfaceCovers`). */\r\nconst NO_PATH = \"(this file's route)\";\r\n\r\nfunction detectMentions(text: string): RouteMention[] {\r\n const found: RouteMention[] = [];\r\n for (const line of text.split(\"\\n\")) {\r\n const methodMatch = ROUTE_METHOD_RE.exec(line);\r\n const pathMatch = ROUTE_PATH_RE.exec(line);\r\n if (methodMatch && pathMatch) {\r\n found.push({ method: methodMatch[1].toUpperCase(), path: pathMatch[0] });\r\n }\r\n const exportMatch = ROUTE_EXPORT_RE.exec(line);\r\n if (exportMatch) {\r\n found.push({ method: exportMatch[1].toUpperCase(), path: NO_PATH });\r\n }\r\n }\r\n return found;\r\n}\r\n\r\n/** `:id`, `{id}`, `[id]` all become `*` so a declared surface and a detected mention compare equal\r\n * regardless of the exact param name either side happens to use. */\r\nfunction normalizePath(path: string): string {\r\n return path.replace(/:[A-Za-z0-9_]+|\\{[^}]+\\}|\\[[^\\]]+\\]/g, \"*\");\r\n}\r\n\r\nfunction surfaceCovers(surface: string, mention: RouteMention): boolean {\r\n if (!new RegExp(`\\\\b${mention.method}\\\\b`, \"i\").test(surface)) return false;\r\n if (mention.path === NO_PATH) return true; // method presence is all a route-export mention has\r\n const declaredPath = normalizePath(surface);\r\n const mentionPath = normalizePath(mention.path);\r\n return declaredPath.includes(mentionPath) || mentionPath.includes(declaredPath);\r\n}\r\n\r\n/** Lines present in `after` but not in `before` \u2014 a set difference, not a positional diff (code\r\n * can shift line numbers around an addition). Good enough to separate \"genuinely new this run\"\r\n * from \"was already there\" without a real diff algorithm, same spirit as this package's other\r\n * scanners. */\r\nfunction addedLines(before: string, after: string): string {\r\n const beforeLines = new Set(before.split(\"\\n\"));\r\n return after\r\n .split(\"\\n\")\r\n .filter((line) => !beforeLines.has(line))\r\n .join(\"\\n\");\r\n}\r\n\r\n/** A test names and calls routes constantly (`describe(\"POST /api/x\", \u2026)`) but cannot define one,\r\n * so scanning it can only produce false positives. Common conventions only, in the same spirit as\r\n * the rest of this file \u2014 not an exhaustive per-framework list. */\r\nconst TEST_FILE_RES = [\r\n /(^|\\/)(__tests__|__mocks__|tests?|specs?)\\//i,\r\n /\\.(test|spec)\\.[^/.]+$/i,\r\n /(^|\\/)test_[^/]+\\.py$/i,\r\n /_test\\.(py|go)$/i,\r\n /Tests?\\.(java|kt|cs)$/,\r\n];\r\n\r\nfunction isTestFile(path: string): boolean {\r\n return TEST_FILE_RES.some((re) => re.test(path));\r\n}\r\n\r\nexport function checkApiScope(\r\n results: CodegenFileResult[],\r\n targets: PilotTarget[],\r\n apiChanges: { surface: string; change: string; reason: string }[],\r\n): ScopeCheck {\r\n const targetsByPath = new Map(targets.map((t) => [t.path, t]));\r\n const violations: ScopeViolation[] = [];\r\n\r\n for (const { targetPath, newContent } of results) {\r\n if (isTestFile(targetPath)) continue;\r\n const target = targetsByPath.get(targetPath);\r\n const isNewFile = target?.kind === \"NEW_FILE\";\r\n\r\n let scanned: string;\r\n if (isNewFile) {\r\n scanned = newContent;\r\n } else {\r\n let currentContent: string;\r\n try {\r\n currentContent = readFileSync(targetPath, \"utf8\");\r\n } catch {\r\n currentContent = \"\";\r\n }\r\n scanned = addedLines(currentContent, newContent);\r\n }\r\n\r\n for (const mention of detectMentions(scanned)) {\r\n if (!apiChanges.some((c) => surfaceCovers(c.surface, mention))) {\r\n violations.push({ file: targetPath, method: mention.method, path: mention.path });\r\n }\r\n }\r\n }\r\n\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\nexport function describeScopeViolations(check: ScopeCheck): string {\r\n return check.violations\r\n .map((v) => `${v.file} adds ${v.method} ${v.path}, not declared in the design's API changes`)\r\n .join(\"; \");\r\n}\r\n", "import { resolve, relative, isAbsolute } from \"node:path\";\r\nimport { findDeniedContextPath, matchesDeniedPath } from \"./deniedPaths\";\r\nimport { listFiles } from \"./git\";\r\nimport { checkHardFailure, unwrapExecute } from \"./envelope\";\r\nimport { RuntimeReplyError } from \"./runtimeReplyError\";\r\nimport type { PilotPacket } from \"./packet\";\r\nimport { fetchWithRetry } from \"./retryFetch\";\r\nimport { DeniedPathError, TargetingHttpError } from \"./targetingErrors\";\r\nimport { resolveTargetingMode, type TargetingMode } from \"./targetingMode\";\r\nimport {\r\n LoopFailure,\r\n SafetyRefusalError,\r\n runTargetingLoop,\r\n type FallbackReason,\r\n type LoopDeps,\r\n type LoopSummary,\r\n} from \"./targetingLoop\";\r\n\r\nexport { DeniedPathError, TargetingHttpError };\r\n\r\n/**\r\n * QUIKTR-1035 \u2014 `pilot.targeting`: turns the design plus a file listing into real per-file\r\n * instructions, replacing codegen.ts's old planStepsFromDesign entirely. Proven live by the AI\r\n * Runtime against a real 624-file QuikChat listing before this was wired in.\r\n *\r\n * QUIKTR-1083 (\u00A715) \u2014 the versioned test-target contract. `contractVersion: \"test-targets-1\"` is\r\n * sent unconditionally: per \u00A715.6 the unversioned path is only \"exactly today's behaviour\" for a\r\n * caller that never asks for the new shape, and this runner always wants it once it ships.\r\n */\r\nconst CONTRACT_VERSION = \"test-targets-1\";\r\n\r\nexport type TargetKind = \"EXISTING\" | \"NEW_FILE\";\r\n\r\nexport interface PilotTarget {\r\n path: string;\r\n kind: TargetKind;\r\n planStepsImplemented: string[];\r\n // Context contract change \u2014 pilot.targeting now names, per target, which other files\r\n // pilot.codegen should read before writing this one (\"to write this file, read these\").\r\n // codegen.ts validates and reads these; absent/empty means no context, no fallback.\r\n contextPaths?: string[];\r\n /** \u00A715.3 \u2014 present only on a test target: the automation IDs (not database ids \u2014 see\r\n * \u00A715.3's own naming rationale) this target's generated file must cover. codegen.ts forwards\r\n * only the matching `requiredTests` subset for a target carrying this. */\r\n automationIds?: string[];\r\n}\r\n\r\n/** \u00A715.3 amendment 1 \u2014 a case with no behaviour (given/when/then all null) is named here instead\r\n * of silently dropped; the model has no discretion over which cases land here vs. in a target's\r\n * `automationIds` (completeness is enforced on the runtime side). Informational on this side \u2014\r\n * folded into `run.ts`'s `warnings`, never blocking. */\r\nexport interface SkippedCase {\r\n automationId: string;\r\n reason: \"NO_BEHAVIOUR\";\r\n}\r\n\r\nexport type TargetingResult = (\r\n | {\r\n outcome: \"TARGETED\";\r\n targets: PilotTarget[];\r\n skippedCases: SkippedCase[];\r\n /** Paths targeting called NEW_FILE although they are already in the checkout; they come back as EXISTING. */\r\n correctedKinds?: string[];\r\n }\r\n | { outcome: \"NO_TARGET\"; reason: string | null }\r\n) & {\r\n /** QUIKTR-1458 \u2014 present only when the read-only loop ran (or was tried): what it did. */\r\n loop?: LoopSummary;\r\n /** Non-blocking notes for the run's warnings list (today: only \"the loop fell back\"). */\r\n warnings?: string[];\r\n};\r\n\r\nexport interface TargetingResponse {\r\n outcome?: \"TARGETED\" | \"NO_TARGET\";\r\n targets?: {\r\n path: string;\r\n kind: string;\r\n planStepsImplemented: string[];\r\n contextPaths?: string[];\r\n automationIds?: string[];\r\n }[];\r\n skippedCases?: SkippedCase[];\r\n noTargetReason?: string;\r\n}\r\n\r\n/**\r\n * Tracked files under the packet's workspace root, or the whole checkout when it's null\r\n * (QUIKTR-1033) \u2014 never normalised to \".\" at the packet layer itself, only here where a concrete\r\n * pathspec is actually needed. An unscoped listing on a large monorepo is ~210k tokens, which fits\r\n * one provider and breaks the fallback chain \u2014 see workspaceRoot's own doc comment on PilotPacket.\r\n */\r\nexport function listWorkspaceFiles(workspaceRoot: string | null): string[] {\r\n return listFiles(workspaceRoot ?? \".\");\r\n}\r\n\r\n/**\r\n * VALIDATION IS OURS \u2014 the AI Runtime's schema doesn't guarantee a path is actually safe to write.\r\n * An EXISTING target must already be in the checkout; a NEW_FILE target must resolve inside the\r\n * workspace root. Either failure throws \u2014 a dropped target is a plan half-executed, and run.ts's\r\n * existing top-level try/catch already turns this into the same hard failure any other pre-setup\r\n * step gets.\r\n */\r\nfunction validateTarget(\r\n target: { path: string; kind: string; contextPaths?: string[] },\r\n workspaceRoot: string | null,\r\n workspaceListing: Set<string>,\r\n deniedPaths: string[],\r\n): void {\r\n // QUIKTR-1083 (\u00A715.3) \u2014 layer 2 of three: checked here, before any codegen spend, regardless of\r\n // kind. Layer 1 (the runtime's own targeting validator) should already exclude a denied path;\r\n // this does not trust that and re-checks independently.\r\n const denied = matchesDeniedPath(target.path, deniedPaths);\r\n if (denied) {\r\n throw new DeniedPathError(\r\n `pilot.targeting proposed a target matching a denied path (${denied}): ${target.path}`,\r\n );\r\n }\r\n // QUIKTR-1420 \u2014 the same list applies to what the target cites as CONTEXT, which the runner reads and\r\n // sends to the model provider. Checked before anything else, and before any codegen spend.\r\n const deniedContext = findDeniedContextPath(target.contextPaths ?? [], deniedPaths);\r\n if (deniedContext) {\r\n throw new DeniedPathError(\r\n `pilot.targeting cited a denied path as context (${deniedContext.pattern}): ${deniedContext.path} (target ${target.path})`,\r\n );\r\n }\r\n if (target.kind !== \"EXISTING\" && target.kind !== \"NEW_FILE\") {\r\n throw new Error(`pilot.targeting returned an unknown kind \"${target.kind}\" for ${target.path}`);\r\n }\r\n if (target.kind === \"EXISTING\") {\r\n if (!workspaceListing.has(target.path)) {\r\n throw new Error(\r\n `pilot.targeting named an EXISTING file not found in the checkout: ${target.path}`,\r\n );\r\n }\r\n return;\r\n }\r\n const root = resolve(workspaceRoot ?? \".\");\r\n const rel = relative(root, resolve(target.path));\r\n if (rel.startsWith(\"..\") || isAbsolute(rel)) {\r\n throw new Error(\r\n `pilot.targeting named a NEW_FILE path that escapes the workspace root: ${target.path}`,\r\n );\r\n }\r\n}\r\n\r\n/**\r\n * The request body for the single-call `pilot.targeting`. Key ORDER is part of the contract with the\r\n * AI Runtime's versioned path and is pinned by targeting.characterisation.test.ts.\r\n */\r\nexport function buildContextData(\r\n design: PilotPacket[\"design\"],\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n testDiscovery: PilotPacket[\"testDiscovery\"],\r\n outOfScope: string[],\r\n): Record<string, unknown> {\r\n const contextData: Record<string, unknown> = {\r\n // NESTED, NOT FLATTENED \u2014 a second vocabulary for the design shape is exactly what\r\n // QUIKTR-1034 cost.\r\n workspaceListing,\r\n design,\r\n // QUIKTR-1065/1083 \u2014 requiredTests carried through so targeting can propose a test-file\r\n // target naming which cases it covers (\u00A715.1's Case shape, unchanged).\r\n requiredTests,\r\n // QUIKTR-1083 (\u00A715.6) \u2014 required on the versioned path.\r\n contractVersion: CONTRACT_VERSION,\r\n };\r\n // QUIKTR-1083 (\u00A715.3) \u2014 optional on the wire; omitted rather than sent empty, matching\r\n // codegen.ts's identical treatment.\r\n if (deniedPaths.length > 0) {\r\n contextData.deniedPaths = deniedPaths;\r\n }\r\n // QUIKTR-1401, \u00A720 of the AI Runtime contract (deployed and confirmed 2026-10-01) \u2014 an optional declared key\r\n // under the versioned contract, sent only when non-empty: an empty list would make the prompt mention\r\n // constraints that are not there. Free text, so unlike deniedPaths it can only be TOLD to the model, never\r\n // checked. Never sent to pilot.design.\r\n if (outOfScope.length > 0) {\r\n contextData.outOfScope = outOfScope;\r\n }\r\n // QUIKTR-1315, \u00A719 of the AI Runtime contract \u2014 AGREED (2026-09-28), confirmed deployed and\r\n // live (2026-09-29). ALWAYS sent, never omitted \u2014 \u00A719's whole point is the tagged\r\n // `{ report: \"PRESENT\" | \"ABSENT\" }` shape replacing an absent-vs-empty key distinction, so this\r\n // must not fall back to \"omit when nothing to say\" the way `deniedPaths` does above. The packet\r\n // already resolves this to a real value in every case (never undefined) \u2014 see packet.ts.\r\n contextData.testDiscovery = testDiscovery;\r\n return contextData;\r\n}\r\n\r\n/**\r\n * One POST of `pilot.targeting`, returning the RAW `/ai/execute` envelope. Shared by the single call\r\n * and by every turn of the read-only loop. QUIKTR-1069 \u2014 retryFetch retries a transport-level failure\r\n * only (502/503/504, a dropped connection); a real refusal always arrives as a 200 with the refusal\r\n * inside the envelope. `signal` is for loop turns only; the single call never had a timeout and\r\n * keeps behaving exactly as before.\r\n */\r\nexport async function postTargeting(\r\n gateway: PilotPacket[\"gateway\"],\r\n contextData: Record<string, unknown>,\r\n signal?: AbortSignal,\r\n): Promise<unknown> {\r\n const res = await fetchWithRetry(`${gateway.baseUrl}/ai/execute`, {\r\n method: \"POST\",\r\n headers: { \"content-type\": \"application/json\", \"x-run-token\": gateway.token },\r\n body: JSON.stringify({\r\n appId: \"quiktrack\",\r\n useCase: \"pilot.targeting\",\r\n expectedOutputType: \"json\",\r\n userPrompt: \"\",\r\n contextData,\r\n }),\r\n ...(signal ? { signal } : {}),\r\n });\r\n\r\n if (!res.ok) {\r\n throw new TargetingHttpError(res.status, res.statusText);\r\n }\r\n return res.json();\r\n}\r\n\r\n/**\r\n * Everything that happens to a targeting ANSWER, whichever way it was obtained: the shape check, our\r\n * own validation of every target, and the NEW_FILE correction. The single call and the read-only loop\r\n * both end here, so a target is judged by exactly the same rules either way.\r\n */\r\nexport function finalizeTargeting(\r\n body: TargetingResponse,\r\n workspaceRoot: string | null,\r\n workspaceListing: string[],\r\n deniedPaths: string[],\r\n): TargetingResult {\r\n if (body.outcome === \"NO_TARGET\") {\r\n return { outcome: \"NO_TARGET\", reason: body.noTargetReason ?? null };\r\n }\r\n if (body.outcome !== \"TARGETED\" || !Array.isArray(body.targets)) {\r\n throw new RuntimeReplyError(\r\n `pilot.targeting returned an unexpected shape: ${JSON.stringify(body)}`,\r\n \"pilot.targeting returned an unexpected shape\",\r\n );\r\n }\r\n\r\n const listing = new Set(workspaceListing);\r\n for (const target of body.targets) {\r\n validateTarget(target, workspaceRoot, listing, deniedPaths);\r\n }\r\n\r\n // A NEW_FILE target is sent to codegen with no current content, so a file that already exists would be\r\n // overwritten blind (QUIKTR-1448). The checkout listing says which it is, so the label is corrected here\r\n // rather than failing a run over a mistake with an obvious answer.\r\n const correctedKinds: string[] = [];\r\n const targets = (body.targets as PilotTarget[]).map((target) => {\r\n if (target.kind === \"NEW_FILE\" && listing.has(target.path)) {\r\n correctedKinds.push(target.path);\r\n return { ...target, kind: \"EXISTING\" as const };\r\n }\r\n return target;\r\n });\r\n\r\n return {\r\n outcome: \"TARGETED\",\r\n targets,\r\n skippedCases: body.skippedCases ?? [],\r\n ...(correctedKinds.length > 0 ? { correctedKinds } : {}),\r\n };\r\n}\r\n\r\n/** Today's behaviour: one call, answered from the file listing alone. */\r\nexport async function runSingleShot(\r\n gateway: PilotPacket[\"gateway\"],\r\n design: PilotPacket[\"design\"],\r\n workspaceRoot: string | null,\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n testDiscovery: PilotPacket[\"testDiscovery\"],\r\n outOfScope: string[] = [],\r\n): Promise<TargetingResult> {\r\n const contextData = buildContextData(design, workspaceListing, requiredTests, deniedPaths, testDiscovery, outOfScope);\r\n // /ai/execute wraps every result in an envelope \u2014 the use-case result lives at\r\n // structuredJson, and a failure can arrive as success:false in an HTTP 200 (see envelope.ts).\r\n // QUIKTR-1083 \u2014 SEMANTIC_MISMATCH/CONTRACT_REJECTED are checked on the raw envelope, before\r\n // unwrapping, same reason codegen.ts's pre-existing CODEGEN_* checks do: unwrapping first would\r\n // throw unwrapExecute's generic success:false error and lose the distinction.\r\n const envelope = await postTargeting(gateway, contextData);\r\n checkHardFailure(envelope, \"pilot.targeting\");\r\n const body = unwrapExecute<TargetingResponse>(envelope, \"pilot.targeting\");\r\n return finalizeTargeting(body, workspaceRoot, workspaceListing, deniedPaths);\r\n}\r\n\r\nexport interface RunTargetingOptions {\r\n /** Overrides the environment switch. Tests, and (one day) a QuikTrack setting, pass this. */\r\n mode?: TargetingMode;\r\n /** Test seam: a fake filesystem, tighter limits, a fake clock or log for the loop. */\r\n loopDeps?: Partial<Omit<LoopDeps, \"post\">>;\r\n}\r\n\r\nconst CODE_LIKE = /^[A-Z0-9_]{1,40}$/;\r\n\r\n/**\r\n * `pilot.targeting`: which files to change. By default one call answered from the file listing alone.\r\n * With the read-only loop switched on (QUIKTR-1458: `QUIKPILOT_TARGETING_MODE=loop`) the AI may look\r\n * at the code first; if the loop cannot finish for an ordinary reason, the run falls back to the\r\n * single call and says so. A refusal never falls back (see targetingLoop.ts).\r\n */\r\nexport async function runTargeting(\r\n gateway: PilotPacket[\"gateway\"],\r\n design: PilotPacket[\"design\"],\r\n workspaceRoot: string | null,\r\n workspaceListing: string[],\r\n requiredTests: PilotPacket[\"requiredTests\"],\r\n deniedPaths: string[],\r\n testDiscovery: PilotPacket[\"testDiscovery\"],\r\n /** QUIKTR-1401 (\u00A720) \u2014 what the reviewer approved the change must NOT touch. Optional and last: every\r\n * existing caller is unchanged. */\r\n outOfScope: string[] = [],\r\n options: RunTargetingOptions = {},\r\n): Promise<TargetingResult> {\r\n const mode = options.mode ?? resolveTargetingMode();\r\n if (mode !== \"loop\") {\r\n return runSingleShot(gateway, design, workspaceRoot, workspaceListing, requiredTests, deniedPaths, testDiscovery, outOfScope);\r\n }\r\n\r\n const baseContext = buildContextData(design, workspaceListing, requiredTests, deniedPaths, testDiscovery, outOfScope);\r\n let summary: LoopSummary | undefined;\r\n let runtimeCode: string | undefined;\r\n let reason: FallbackReason;\r\n try {\r\n const looped = await runTargetingLoop(\r\n { baseContext, listing: workspaceListing, deniedPaths },\r\n { ...options.loopDeps, post: (contextData, signal) => postTargeting(gateway, contextData, signal) },\r\n );\r\n summary = looped.summary;\r\n const result = finalizeTargeting(looped.body as TargetingResponse, workspaceRoot, workspaceListing, deniedPaths);\r\n return { ...result, loop: summary };\r\n } catch (err) {\r\n // A refusal is never answered by trying again another way.\r\n if (err instanceof DeniedPathError || err instanceof SafetyRefusalError) throw err;\r\n if (err instanceof LoopFailure) {\r\n reason = err.reason;\r\n runtimeCode = err.runtimeCode;\r\n summary = err.summary ?? summary;\r\n } else {\r\n // Only finalizeTargeting can end up here: the loop got an answer, but it is not usable.\r\n reason = \"final_invalid\";\r\n }\r\n }\r\n\r\n const fellBack: LoopSummary = {\r\n turns: summary?.turns ?? 0,\r\n toolCalls: summary?.toolCalls ?? 0,\r\n readChars: summary?.readChars ?? 0,\r\n refused: summary?.refused ?? 0,\r\n reads: summary?.reads ?? [],\r\n stopReason: \"fallback\",\r\n fellBack: true,\r\n fallbackReason: reason,\r\n };\r\n const log = options.loopDeps?.log ?? ((e: Record<string, unknown>) => console.log(JSON.stringify(e)));\r\n log({\r\n event: \"targeting.loop_fallback\",\r\n reason,\r\n turn: fellBack.turns,\r\n toolCalls: fellBack.toolCalls,\r\n ...(runtimeCode && CODE_LIKE.test(runtimeCode) ? { runtimeCode } : {}),\r\n });\r\n\r\n // If this fails too, it fails the run exactly as it would have without the loop.\r\n const single = await runSingleShot(gateway, design, workspaceRoot, workspaceListing, requiredTests, deniedPaths, testDiscovery, outOfScope);\r\n return {\r\n ...single,\r\n loop: fellBack,\r\n warnings: [`QuikPilot's read-only targeting could not complete (${reason}); standard targeting was used instead.`],\r\n };\r\n}\r\n", "/**\r\n * Error types shared by `targeting.ts` and the read-only targeting loop (QUIKTR-1458). They live in\r\n * a module of their own so the loop can recognise them without importing `targeting.ts`, which\r\n * imports the loop.\r\n */\r\n\r\n/**\r\n * A proposed target, or a cited context file, that matches a denied path. A class of its own so the\r\n * read-only loop can tell \"the AI asked for something we never allow\" - which must never be retried\r\n * by falling back - from \"the AI's answer was merely invalid\". The message text is exactly what it\r\n * was before, so nothing that read it changes.\r\n */\r\nexport class DeniedPathError extends Error {\r\n constructor(message: string) {\r\n super(message);\r\n this.name = \"DeniedPathError\";\r\n }\r\n}\r\n\r\n/** The call itself came back non-2xx (after retryFetch's own retries). Same message as ever. */\r\nexport class TargetingHttpError extends Error {\r\n readonly status: number;\r\n constructor(status: number, statusText: string) {\r\n super(`Targeting call failed: ${status} ${statusText}`);\r\n this.name = \"TargetingHttpError\";\r\n this.status = status;\r\n }\r\n}\r\n", "/**\r\n * QUIKTR-1458 \u2014 which way `pilot.targeting` runs.\r\n *\r\n * `single` is today's behaviour: one call, the model answers from the file listing alone. `loop` lets\r\n * the model look at the code first, through read-only tools (targetingLoop.ts). It is OFF unless\r\n * asked for, and only the exact word `loop` asks.\r\n *\r\n * Today the switch is an environment variable in the workflow file, set by hand. The long-term home\r\n * is a per-project QuikTrack setting carried in the run packet; `packetSetting` is that seam, so the\r\n * day it exists it is one argument at one call site and this precedence (setting, then environment,\r\n * then off) is already settled and tested. Nothing passes it yet.\r\n */\r\nexport type TargetingMode = \"single\" | \"loop\";\r\n\r\nexport const TARGETING_MODE_ENV = \"QUIKPILOT_TARGETING_MODE\";\r\n\r\nfunction parse(value: string | null | undefined): TargetingMode | null {\r\n if (typeof value !== \"string\") return null;\r\n const v = value.trim().toLowerCase();\r\n if (v === \"loop\") return \"loop\";\r\n if (v === \"single\") return \"single\";\r\n return null;\r\n}\r\n\r\nexport function resolveTargetingMode(\r\n env: NodeJS.ProcessEnv = process.env,\r\n packetSetting?: string | null,\r\n): TargetingMode {\r\n const fromSetting = parse(packetSetting);\r\n if (fromSetting) return fromSetting;\r\n return parse(env[TARGETING_MODE_ENV]) ?? \"single\";\r\n}\r\n", "import { posix } from \"node:path\";\r\nimport { matchesDeniedPath } from \"./deniedPaths\";\r\n\r\n/**\r\n * QUIKTR-1458 \u2014 the first gate for every path the AI names in the read-only targeting loop.\r\n *\r\n * This decides only whether a string could be a repo-relative path at all. Whether it is a tracked,\r\n * allowed file is the next gate's job: membership in the checkout listing, then the denied list.\r\n * (`deniedPaths.ts` does no normalising of its own and matches case-sensitively against a\r\n * forward-slash, repo-relative path exactly as `git ls-files` prints it, so everything has to be\r\n * brought to that shape first, or refused.)\r\n *\r\n * Order matters and is pinned by tests: a `..` segment is refused BEFORE the path is normalised,\r\n * because normalising `a/../b.js` quietly turns it into `b.js`, which would look perfectly fine.\r\n */\r\n\r\nexport type PathRefusal = \"path_invalid\" | \"outside_workspace\";\r\n\r\nexport type NormalisedPath = { ok: true; path: string } | { ok: false; reason: PathRefusal };\r\n\r\nconst MAX_PATH_CHARS = 300;\r\n\r\n// Any ASCII control character (NUL, newline, BEL, ESC, DEL, ...).\r\nfunction hasControlChar(s: string): boolean {\r\n for (let i = 0; i < s.length; i++) {\r\n const c = s.charCodeAt(i);\r\n if (c < 0x20 || c === 0x7f) return true;\r\n }\r\n return false;\r\n}\r\n\r\nexport function normaliseToolPath(raw: unknown, options: { allowRoot?: boolean } = {}): NormalisedPath {\r\n const allowRoot = options.allowRoot === true;\r\n\r\n if ((raw === undefined || raw === null || raw === \"\") && allowRoot) return { ok: true, path: \"\" };\r\n if (typeof raw !== \"string\" || raw.length === 0 || raw.length > MAX_PATH_CHARS) {\r\n return { ok: false, reason: \"path_invalid\" };\r\n }\r\n if (hasControlChar(raw)) return { ok: false, reason: \"path_invalid\" };\r\n // Never convert backslashes: a path the AI wrote with them is not a git path, and quietly\r\n // \"fixing\" it would hide that it is guessing.\r\n if (raw.includes(\"\\\\\")) return { ok: false, reason: \"path_invalid\" };\r\n if (raw.startsWith(\"/\") || /^[A-Za-z]:/.test(raw)) return { ok: false, reason: \"path_invalid\" };\r\n\r\n // Before normalising, on purpose (see the header).\r\n if (raw.split(\"/\").includes(\"..\")) return { ok: false, reason: \"outside_workspace\" };\r\n\r\n const normalised = posix.normalize(raw).replace(/\\/+$/, \"\");\r\n if (normalised === \"\" || normalised === \".\") {\r\n return allowRoot ? { ok: true, path: \"\" } : { ok: false, reason: \"path_invalid\" };\r\n }\r\n return { ok: true, path: normalised };\r\n}\r\n\r\n/** True when `path` is `prefix` or lives under it, on a whole path segment (`src` is not `srcx`). */\r\nexport function matchesPrefix(path: string, prefix: string): boolean {\r\n if (prefix === \"\") return true;\r\n return path === prefix || path.startsWith(`${prefix}/`);\r\n}\r\n\r\n/**\r\n * The listing with every denied path removed, sorted. Anything the AI is told about files comes\r\n * from this, so a protected file is never named, counted or hinted at. Sorting makes every answer\r\n * deterministic. The input is not changed.\r\n */\r\nexport function buildVisibleListing(listing: readonly string[], deniedPaths: string[]): string[] {\r\n return listing.filter((p) => !matchesDeniedPath(p, deniedPaths)).sort();\r\n}\r\n", "import { lstatSync, readFileSync, realpathSync } from \"node:fs\";\r\nimport { isAbsolute, join, relative } from \"node:path\";\r\nimport { matchesDeniedPath } from \"./deniedPaths\";\r\nimport { matchesPrefix, normaliseToolPath } from \"./targetingPaths\";\r\n\r\n/**\r\n * QUIKTR-1458 \u2014 the three READ-ONLY tools the AI may use while it chooses which files to change:\r\n * `list_files`, `read_file`, `grep`. Nothing here can write, run or fetch anything.\r\n *\r\n * The AI's arguments are untrusted input and the files are a customer's, so every rule below is\r\n * about safety first:\r\n * - a protected (denied) path is never read, listed, searched, counted or hinted at;\r\n * - nothing outside the checkout is reachable (no `..`, no absolute paths, no symlinks);\r\n * - only files git tracks can be named, so a made-up path simply is not found;\r\n * - every limit turns into a plain RESULT the AI can act on (`refused`, `budget_exhausted`, ...),\r\n * never an exception, and never echoes what the AI sent or what a file contained into an error;\r\n * - `grep` is a FIXED-STRING search. The pattern is model-supplied and runs over customer files in\r\n * CI; a regular expression there is a way to hang the job, and a name like `validateExpense` is\r\n * all the AI needs.\r\n *\r\n * File access goes through `ToolFs` so tests can simulate symlinks, escapes and binary files\r\n * without touching a real checkout; `createNodeToolFs` is the real one.\r\n */\r\n\r\nexport type ToolName = \"list_files\" | \"read_file\" | \"grep\";\r\n\r\nexport interface ToolCall {\r\n id: string;\r\n name: string;\r\n args: unknown;\r\n}\r\n\r\nexport type ToolStatus =\r\n | \"ok\"\r\n | \"refused\"\r\n | \"not_found\"\r\n | \"unreadable\"\r\n | \"bad_args\"\r\n | \"unknown_tool\"\r\n | \"duplicate\"\r\n | \"budget_exhausted\";\r\n\r\nexport interface ToolResult {\r\n id: string;\r\n name: string;\r\n status: ToolStatus;\r\n /** A fixed vocabulary word (or, for `duplicate`, the id of the earlier call). Never model or file text. */\r\n reason?: string;\r\n /** Runner-authored fixed text. Never echoes the AI's input or a file's content. */\r\n message?: string;\r\n output?: unknown;\r\n}\r\n\r\nexport interface ToolLimits {\r\n maxTurns: number;\r\n maxToolCalls: number;\r\n maxCallsPerTurn: number;\r\n readCharsPerRead: number;\r\n readCharsTotal: number;\r\n resultCharsTotal: number;\r\n /** The per-turn ceiling on one request, in estimated TOKENS (`tokenEstimate.ts`). */\r\n maxRequestTokens: number;\r\n grepMaxMatches: number;\r\n grepLineChars: number;\r\n grepFileBytes: number;\r\n grepMaxFiles: number;\r\n grepMaxBytes: number;\r\n fileBytesMax: number;\r\n listMaxEntries: number;\r\n maxReasoningChars: number;\r\n maxPatternChars: number;\r\n}\r\n\r\n/** Starting values; to be tuned by measurement (QUIKTR-1458). */\r\nexport const DEFAULT_LIMITS: ToolLimits = {\r\n maxTurns: 12,\r\n maxToolCalls: 25,\r\n maxCallsPerTurn: 8,\r\n readCharsPerRead: 20_000,\r\n // The per-run read cap stops the COST; the per-turn ceiling below stops the FAILURE. Different jobs.\r\n readCharsTotal: 60_000,\r\n resultCharsTotal: 80_000,\r\n // 131,072 (the smallest 128k-class window) - 8,192 reserved output - a 3,741-token real request leaves\r\n // ~116,000; 90,000 keeps ~26,000 for a repository whose listing is thousands of paths, and stays well\r\n // clear of the per-minute quota, which binds before the window does. Set by the AI Runtime owner.\r\n maxRequestTokens: 90_000,\r\n grepMaxMatches: 40,\r\n grepLineChars: 200,\r\n grepFileBytes: 262_144,\r\n grepMaxFiles: 3_000,\r\n grepMaxBytes: 20_000_000,\r\n fileBytesMax: 1_000_000,\r\n listMaxEntries: 500,\r\n maxReasoningChars: 500,\r\n maxPatternChars: 200,\r\n};\r\n\r\nexport interface ToolFs {\r\n /** The real path of the checkout root. */\r\n rootReal: string;\r\n /** Throws if the file is gone. Never follows a symlink. */\r\n lstat(rel: string): { isSymlink: boolean; isFile: boolean; size: number };\r\n /** True when the file's real location (after following any links) is inside the checkout. */\r\n realpathInside(rel: string): boolean;\r\n readBytes(rel: string): Uint8Array;\r\n}\r\n\r\nexport function createNodeToolFs(rootDir: string = process.cwd()): ToolFs {\r\n const rootReal = realpathSync(rootDir);\r\n return {\r\n rootReal,\r\n lstat(rel) {\r\n const s = lstatSync(join(rootDir, rel));\r\n return { isSymlink: s.isSymbolicLink(), isFile: s.isFile(), size: s.size };\r\n },\r\n realpathInside(rel) {\r\n const real = realpathSync(join(rootDir, rel));\r\n const r = relative(rootReal, real);\r\n return r !== \"\" && !r.startsWith(\"..\") && !isAbsolute(r);\r\n },\r\n readBytes(rel) {\r\n return readFileSync(join(rootDir, rel));\r\n },\r\n };\r\n}\r\n\r\nexport interface ToolEnv {\r\n /** Every tracked file, exactly as `git ls-files` printed it (membership gate). */\r\n listing: ReadonlySet<string>;\r\n /** The listing with denied paths removed, sorted: the only thing the AI is ever told about. */\r\n visible: readonly string[];\r\n deniedPaths: string[];\r\n fs: ToolFs;\r\n limits: ToolLimits;\r\n}\r\n\r\nexport interface ToolLedger {\r\n toolCalls: number;\r\n readChars: number;\r\n resultChars: number;\r\n refused: number;\r\n /** canonical call -> id of the first call that made it */\r\n seen: Map<string, string>;\r\n}\r\n\r\nexport function newLedger(): ToolLedger {\r\n return { toolCalls: 0, readChars: 0, resultChars: 0, refused: 0, seen: new Map() };\r\n}\r\n\r\n/** What was read, for the run's audit record. Paths only, never content. */\r\nexport interface ReadRecord {\r\n path: string;\r\n startLine?: number;\r\n endLine?: number;\r\n chars: number;\r\n refused?: true;\r\n}\r\n\r\ntype Partial_ = Omit<ToolResult, \"id\" | \"name\">;\r\ntype Executed = { result: Partial_; read?: ReadRecord };\r\ntype Prepared =\r\n | { fail: Partial_; read?: ReadRecord }\r\n | { key: string; exec: () => Executed };\r\n\r\nconst INVALID_PATH = \"(invalid path)\";\r\nconst CUT = \"\u2026[line cut]\";\r\n\r\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\r\n return typeof x === \"object\" && x !== null && !Array.isArray(x);\r\n}\r\n\r\nfunction bad(message: string): { fail: Partial_ } {\r\n return { fail: { status: \"bad_args\", message } };\r\n}\r\n\r\nfunction optionalInt(v: unknown): number | undefined | \"bad\" {\r\n if (v === undefined || v === null) return undefined;\r\n return typeof v === \"number\" && Number.isInteger(v) ? v : \"bad\";\r\n}\r\n\r\nfunction hasNul(bytes: Uint8Array): boolean {\r\n const n = Math.min(bytes.length, 8000);\r\n for (let i = 0; i < n; i++) if (bytes[i] === 0) return true;\r\n return false;\r\n}\r\n\r\n/** Path gates shared by read_file: shape, then denied, then membership. No file is touched. */\r\nfunction gatePath(raw: unknown, env: ToolEnv): { ok: true; path: string } | { ok: false; fail: Partial_; path: string } {\r\n const n = normaliseToolPath(raw);\r\n if (!n.ok) {\r\n return { ok: false, path: INVALID_PATH, fail: { status: \"refused\", reason: n.reason, message: \"That path is not allowed.\" } };\r\n }\r\n // Denied BEFORE membership: a protected file and a made-up file inside a protected folder give the\r\n // same answer, so the answer cannot be used to find out what exists there.\r\n if (matchesDeniedPath(n.path, env.deniedPaths)) {\r\n return { ok: false, path: n.path, fail: { status: \"refused\", reason: \"denied\", message: \"That path is protected and cannot be read.\" } };\r\n }\r\n if (!env.listing.has(n.path)) {\r\n return { ok: false, path: n.path, fail: { status: \"not_found\", message: \"Not a tracked file. Use list_files to see the available paths.\" } };\r\n }\r\n return { ok: true, path: n.path };\r\n}\r\n\r\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 read_file \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nfunction prepareReadFile(args: Record<string, unknown>, env: ToolEnv, ledger: ToolLedger): Prepared {\r\n const start = optionalInt(args.startLine);\r\n const end = optionalInt(args.endLine);\r\n if (start === \"bad\" || end === \"bad\") return bad(\"startLine and endLine must be whole numbers.\");\r\n if (start !== undefined && end !== undefined && end < start) return bad(\"endLine must not be before startLine.\");\r\n\r\n if (typeof args.path !== \"string\") return bad(\"path must be a string.\");\r\n const gate = gatePath(args.path, env);\r\n if (!gate.ok) {\r\n const read: ReadRecord | undefined = gate.fail.status === \"refused\" ? { path: gate.path, chars: 0, refused: true } : undefined;\r\n return { fail: gate.fail, ...(read ? { read } : {}) };\r\n }\r\n const path = gate.path;\r\n const key = JSON.stringify({ path, startLine: start ?? null, endLine: end ?? null });\r\n\r\n return {\r\n key,\r\n exec: () => {\r\n let size: number;\r\n try {\r\n const st = env.fs.lstat(path);\r\n if (st.isSymlink) {\r\n return { result: { status: \"refused\", reason: \"symlink\", message: \"Links are not followed.\" }, read: { path, chars: 0, refused: true } };\r\n }\r\n if (!st.isFile) return { result: { status: \"unreadable\", reason: \"not_a_file\", message: \"That entry is not a regular file.\" } };\r\n size = st.size;\r\n if (size > env.limits.fileBytesMax) {\r\n return { result: { status: \"unreadable\", reason: \"too_large\", message: \"That file is too large to read.\" } };\r\n }\r\n if (!env.fs.realpathInside(path)) {\r\n return { result: { status: \"refused\", reason: \"outside_workspace\", message: \"That path is not allowed.\" }, read: { path, chars: 0, refused: true } };\r\n }\r\n } catch {\r\n return { result: { status: \"unreadable\", reason: \"io\", message: \"That file could not be read.\" } };\r\n }\r\n\r\n let bytes: Uint8Array;\r\n try {\r\n bytes = env.fs.readBytes(path);\r\n } catch {\r\n return { result: { status: \"unreadable\", reason: \"io\", message: \"That file could not be read.\" } };\r\n }\r\n if (hasNul(bytes)) return { result: { status: \"unreadable\", reason: \"binary\", message: \"That file is binary.\" } };\r\n let text: string;\r\n try {\r\n text = new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes);\r\n } catch {\r\n return { result: { status: \"unreadable\", reason: \"not_utf8\", message: \"That file is not valid UTF-8 text.\" } };\r\n }\r\n if (text.charCodeAt(0) === 0xfeff) text = text.slice(1);\r\n text = text.replace(/\\r\\n/g, \"\\n\");\r\n\r\n const lines = text === \"\" ? [] : text.split(\"\\n\");\r\n if (lines.length > 0 && lines[lines.length - 1] === \"\") lines.pop();\r\n const totalLines = lines.length;\r\n\r\n const startLine = Math.max(1, start ?? 1);\r\n const endWanted = Math.min(totalLines, end ?? totalLines);\r\n if (startLine > totalLines) {\r\n return {\r\n result: { status: \"ok\", output: { path, startLine, endLine: totalLines, totalLines, truncated: false, content: \"\" } },\r\n read: { path, startLine, endLine: totalLines, chars: 0 },\r\n };\r\n }\r\n\r\n const budget = Math.max(0, Math.min(env.limits.readCharsPerRead, env.limits.readCharsTotal - ledger.readChars));\r\n const out: string[] = [];\r\n let used = 0;\r\n let endLine = startLine - 1;\r\n let truncated = false;\r\n for (let n = startLine; n <= endWanted; n++) {\r\n const line = `${n}\\t${lines[n - 1]}`;\r\n const cost = line.length + (out.length > 0 ? 1 : 0);\r\n if (used + cost <= budget) {\r\n out.push(line);\r\n used += cost;\r\n endLine = n;\r\n continue;\r\n }\r\n truncated = true;\r\n if (out.length === 0) {\r\n // One line on its own is bigger than the whole allowance: cut inside it.\r\n const keep = Math.max(0, budget - CUT.length);\r\n out.push(line.slice(0, keep) + CUT);\r\n used = out[0].length;\r\n endLine = n;\r\n }\r\n break;\r\n }\r\n\r\n let content = out.join(\"\\n\");\r\n ledger.readChars += used;\r\n const output: Record<string, unknown> = { path, startLine, endLine, totalLines, truncated };\r\n if (truncated) {\r\n if (endLine < totalLines) {\r\n output.nextStartLine = endLine + 1;\r\n content += `\\n[truncated: showing lines ${startLine}-${endLine} of ${totalLines}; call read_file with startLine=${endLine + 1}]`;\r\n } else {\r\n content += `\\n[truncated: line ${endLine} was cut]`;\r\n }\r\n }\r\n output.content = content;\r\n return { result: { status: \"ok\", output }, read: { path, startLine, endLine, chars: used } };\r\n },\r\n };\r\n}\r\n\r\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 list_files \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nfunction prepareListFiles(args: Record<string, unknown>, env: ToolEnv): Prepared {\r\n const max = optionalInt(args.maxEntries);\r\n if (max === \"bad\" || (max !== undefined && max < 1)) return bad(\"maxEntries must be a whole number of at least 1.\");\r\n if (args.prefix !== undefined && args.prefix !== null && typeof args.prefix !== \"string\") return bad(\"prefix must be a string.\");\r\n const n = normaliseToolPath(args.prefix, { allowRoot: true });\r\n if (!n.ok) return { fail: { status: \"refused\", reason: n.reason, message: \"That path is not allowed.\" } };\r\n const prefix = n.path;\r\n const cap = Math.min(max ?? env.limits.listMaxEntries, env.limits.listMaxEntries);\r\n\r\n return {\r\n key: JSON.stringify({ prefix, maxEntries: cap }),\r\n exec: () => {\r\n const matching = env.visible.filter((p) => matchesPrefix(p, prefix));\r\n const entries = matching.slice(0, cap);\r\n const truncated = matching.length > cap;\r\n const output: Record<string, unknown> = { entries, total: matching.length, truncated };\r\n if (truncated) {\r\n const counts = new Map<string, number>();\r\n for (const p of matching) {\r\n const rest = prefix === \"\" ? p : p.slice(prefix.length + 1);\r\n const slash = rest.indexOf(\"/\");\r\n if (slash > 0) counts.set(rest.slice(0, slash), (counts.get(rest.slice(0, slash)) ?? 0) + 1);\r\n }\r\n output.subdirs = [...counts.entries()]\r\n .map(([name, count]) => ({ name, count }))\r\n .sort((a, b) => b.count - a.count || (a.name < b.name ? -1 : 1))\r\n .slice(0, 50);\r\n }\r\n return { result: { status: \"ok\", output } };\r\n },\r\n };\r\n}\r\n\r\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 grep \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nconst WORD_CHAR = /[A-Za-z0-9_$]/;\r\n\r\nfunction lineMatches(line: string, needle: string, ignoreCase: boolean, wholeWord: boolean): number {\r\n const hay = ignoreCase ? line.toLowerCase() : line;\r\n let from = 0;\r\n for (;;) {\r\n const i = hay.indexOf(needle, from);\r\n if (i === -1) return -1;\r\n if (!wholeWord) return i;\r\n const before = i > 0 ? hay[i - 1] : \"\";\r\n const after = i + needle.length < hay.length ? hay[i + needle.length] : \"\";\r\n if (!(before && WORD_CHAR.test(before)) && !(after && WORD_CHAR.test(after))) return i;\r\n from = i + 1;\r\n }\r\n}\r\n\r\n/** Trim a matching line and, when it is long, show the stretch around the match. */\r\nfunction excerpt(line: string, at: number, max: number): string {\r\n const t = line.trim();\r\n if (t.length <= max) return t;\r\n const lead = line.length - line.trimStart().length;\r\n const pos = Math.max(0, at - lead);\r\n const from = Math.max(0, Math.min(pos - 40, t.length - max));\r\n const piece = t.slice(from, from + max);\r\n return `${from > 0 ? \"\u2026\" : \"\"}${piece}${from + max < t.length ? \"\u2026\" : \"\"}`;\r\n}\r\n\r\nfunction prepareGrep(args: Record<string, unknown>, env: ToolEnv): Prepared {\r\n const pattern = args.pattern;\r\n if (typeof pattern !== \"string\" || pattern.length === 0 || pattern.length > env.limits.maxPatternChars) {\r\n return bad(\"pattern must be a non-empty string within the length limit.\");\r\n }\r\n if (/[\\u0000\\r\\n]/.test(pattern)) return bad(\"pattern must be a single line of plain text.\");\r\n for (const flag of [\"ignoreCase\", \"wholeWord\"] as const) {\r\n if (args[flag] !== undefined && typeof args[flag] !== \"boolean\") return bad(`${flag} must be true or false.`);\r\n }\r\n const maxIn = optionalInt(args.maxResults);\r\n if (maxIn === \"bad\" || (maxIn !== undefined && maxIn < 1)) return bad(\"maxResults must be a whole number of at least 1.\");\r\n if (args.pathPrefix !== undefined && args.pathPrefix !== null && typeof args.pathPrefix !== \"string\") return bad(\"pathPrefix must be a string.\");\r\n const n = normaliseToolPath(args.pathPrefix, { allowRoot: true });\r\n if (!n.ok) return { fail: { status: \"refused\", reason: n.reason, message: \"That path is not allowed.\" } };\r\n\r\n const prefix = n.path;\r\n const ignoreCase = args.ignoreCase === true;\r\n const wholeWord = args.wholeWord === true;\r\n const maxMatches = Math.min(maxIn ?? env.limits.grepMaxMatches, env.limits.grepMaxMatches);\r\n const needle = ignoreCase ? pattern.toLowerCase() : pattern;\r\n\r\n return {\r\n key: JSON.stringify({ pattern, pathPrefix: prefix, maxResults: maxMatches, ignoreCase, wholeWord }),\r\n exec: () => {\r\n const matches: { path: string; line: number; text: string }[] = [];\r\n const skipped = { large: 0, binary: 0 };\r\n let filesScanned = 0;\r\n let bytesScanned = 0;\r\n let scanCapped = false;\r\n let truncated = false;\r\n\r\n scan: for (const path of env.visible) {\r\n if (!matchesPrefix(path, prefix)) continue;\r\n if (filesScanned >= env.limits.grepMaxFiles || bytesScanned >= env.limits.grepMaxBytes) {\r\n scanCapped = true;\r\n break;\r\n }\r\n filesScanned += 1;\r\n let bytes: Uint8Array;\r\n try {\r\n const st = env.fs.lstat(path);\r\n if (st.isSymlink || !st.isFile) continue;\r\n if (st.size > env.limits.grepFileBytes) {\r\n skipped.large += 1;\r\n continue;\r\n }\r\n if (!env.fs.realpathInside(path)) continue;\r\n bytes = env.fs.readBytes(path);\r\n } catch {\r\n continue;\r\n }\r\n bytesScanned += bytes.length;\r\n if (hasNul(bytes)) {\r\n skipped.binary += 1;\r\n continue;\r\n }\r\n const lines = new TextDecoder(\"utf-8\").decode(bytes).replace(/\\r\\n/g, \"\\n\").split(\"\\n\");\r\n for (let i = 0; i < lines.length; i++) {\r\n const at = lineMatches(lines[i], needle, ignoreCase, wholeWord);\r\n if (at === -1) continue;\r\n if (matches.length >= maxMatches) {\r\n truncated = true;\r\n break scan;\r\n }\r\n matches.push({ path, line: i + 1, text: excerpt(lines[i], at, env.limits.grepLineChars) });\r\n }\r\n }\r\n\r\n const output: Record<string, unknown> = { matches, truncated, filesScanned, skipped };\r\n if (scanCapped) output.scanCapped = true;\r\n return { result: { status: \"ok\", output } };\r\n },\r\n };\r\n}\r\n\r\n// \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 the entry point \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\r\n\r\nfunction budgetResult(reason: string): Partial_ {\r\n return { status: \"budget_exhausted\", reason, message: \"That limit has been reached; give your answer from what you have.\" };\r\n}\r\n\r\n/**\r\n * Run one tool call. Never throws for a tool-level problem: every outcome is a result the AI is told\r\n * about. Every call counts toward the total (refused, invalid and repeated ones too, so probing is\r\n * bounded), except one turned away because the budget is already gone.\r\n */\r\nexport function executeToolCall(call: ToolCall, env: ToolEnv, ledger: ToolLedger): { result: ToolResult; read?: ReadRecord } {\r\n const wrap = (r: Partial_): ToolResult => ({ id: call.id, name: call.name, ...r });\r\n const finish = (r: Partial_, read?: ReadRecord) => {\r\n const result = wrap(r);\r\n ledger.resultChars += JSON.stringify(result).length;\r\n if (result.status === \"refused\") ledger.refused += 1;\r\n return read ? { result, read } : { result };\r\n };\r\n\r\n if (ledger.toolCalls >= env.limits.maxToolCalls) return finish(budgetResult(\"tool_calls\"));\r\n if (ledger.resultChars >= env.limits.resultCharsTotal) return finish(budgetResult(\"result_chars\"));\r\n if (call.name === \"read_file\" && ledger.readChars >= env.limits.readCharsTotal) return finish(budgetResult(\"read_chars\"));\r\n\r\n ledger.toolCalls += 1;\r\n\r\n let prepared: Prepared;\r\n try {\r\n if (call.name !== \"read_file\" && call.name !== \"list_files\" && call.name !== \"grep\") {\r\n return finish({ status: \"unknown_tool\", message: \"Unknown tool. Use list_files, read_file or grep.\" });\r\n }\r\n if (!isPlainObject(call.args)) return finish({ status: \"bad_args\", message: \"Arguments must be an object.\" });\r\n prepared =\r\n call.name === \"read_file\"\r\n ? prepareReadFile(call.args, env, ledger)\r\n : call.name === \"list_files\"\r\n ? prepareListFiles(call.args, env)\r\n : prepareGrep(call.args, env);\r\n } catch {\r\n return finish({ status: \"bad_args\", message: \"Those arguments could not be used.\" });\r\n }\r\n\r\n if (\"fail\" in prepared) return finish(prepared.fail, prepared.read);\r\n\r\n const dupKey = `${call.name}:${prepared.key}`;\r\n const earlier = ledger.seen.get(dupKey);\r\n if (earlier !== undefined) {\r\n return finish({ status: \"duplicate\", reason: earlier, message: \"Identical call already made; see its result.\" });\r\n }\r\n ledger.seen.set(dupKey, call.id);\r\n\r\n let executed: Executed;\r\n try {\r\n executed = prepared.exec();\r\n } catch {\r\n executed = { result: { status: \"unreadable\", reason: \"io\", message: \"That could not be read.\" } };\r\n }\r\n return finish(executed.result, executed.read);\r\n}\r\n", "/**\r\n * QUIKTR-1458 \u2014 an estimate of what a request costs in TOKENS (contract section 23.5).\r\n *\r\n * The per-turn ceiling is in tokens and has to be counted the way the provider counts them. A character\r\n * budget is wrong, and so is chars / 4: measured against Gemini's own `count_tokens`, chars / 4\r\n * undercounts a path listing at 0.5x-0.9x and non-ASCII text at 0.5x-0.8x, so a repository with a long\r\n * listing or non-ASCII paths and comments would blow the cap while appearing inside it.\r\n *\r\n * So: a per-character-CLASS estimate. The weights were fitted against `count_tokens` on 14 real samples\r\n * (gemini-2.5-flash, 6 Oct 2026: real repository path listings of 40 to 3,000 paths, TypeScript plain and\r\n * wrapped in the JSON a tool result travels in, non-ASCII comments and paths), then rounded UP. Every\r\n * sample came out 1.14x to 1.50x ABOVE the real count; none under. Over-counting is the safe direction \u2014\r\n * the loop stops sooner and a run falls back to today's single call \u2014 so do not tidy these toward the\r\n * fitted values (0.26 / 0.16 / 0 / 0.92 / 0.66) without re-measuring.\r\n *\r\n * The AI Runtime carries the SAME estimator (`pilot_targeting_loop.estimate_tokens`) and both are pinned\r\n * to the same reference values. Class counts are integers and the weights are applied in one fixed order,\r\n * so the two agree to the token. A change to either is a change to both.\r\n */\r\n\r\nexport const TOKENS_PER_ALPHA_CHAR = 0.3;\r\nexport const TOKENS_PER_DIGIT_CHAR = 0.18;\r\nexport const TOKENS_PER_SPACE_CHAR = 0.05;\r\nexport const TOKENS_PER_PUNCTUATION_CHAR = 1.05;\r\nexport const TOKENS_PER_NON_ASCII_CHAR = 1.0;\r\n\r\n/**\r\n * What a request costs beyond the JSON `contextData` it carries: the system prompt, the loop\r\n * instruction, the response schema and the user turn. Measured at roughly 3,300 to 3,600 tokens, then\r\n * rounded up.\r\n */\r\nexport const PROMPT_OVERHEAD_TOKENS = 5_000;\r\n\r\n/** A deliberately high estimate of what `text` costs in tokens. Counts code points, not UTF-16 units. */\r\nexport function estimateTokens(text: string): number {\r\n let alpha = 0;\r\n let digit = 0;\r\n let space = 0;\r\n let punct = 0;\r\n let nonAscii = 0;\r\n for (const ch of text) {\r\n const code = ch.codePointAt(0)!;\r\n if (code >= 128) nonAscii++;\r\n else if ((code >= 65 && code <= 90) || (code >= 97 && code <= 122)) alpha++;\r\n else if (code >= 48 && code <= 57) digit++;\r\n else if (code === 32 || code === 9 || code === 13 || code === 10) space++;\r\n else punct++;\r\n }\r\n return Math.ceil(\r\n alpha * TOKENS_PER_ALPHA_CHAR +\r\n digit * TOKENS_PER_DIGIT_CHAR +\r\n space * TOKENS_PER_SPACE_CHAR +\r\n punct * TOKENS_PER_PUNCTUATION_CHAR +\r\n nonAscii * TOKENS_PER_NON_ASCII_CHAR,\r\n );\r\n}\r\n\r\n/**\r\n * The estimated size of the model request one loop turn becomes: the prompt overhead plus the context as\r\n * the runtime renders it (indent 2, non-ASCII kept \u2014 never escaped, which would turn every non-ASCII\r\n * character into six ASCII ones and flatter the count).\r\n */\r\nexport function estimateRequestTokens(contextData: unknown): number {\r\n return PROMPT_OVERHEAD_TOKENS + estimateTokens(JSON.stringify(contextData ?? {}, null, 2));\r\n}\r\n", "import { checkHardFailure, unwrapExecute } from \"./envelope\";\r\nimport { RuntimeReplyError } from \"./runtimeReplyError\";\r\nimport { TargetingHttpError } from \"./targetingErrors\";\r\nimport { buildVisibleListing } from \"./targetingPaths\";\r\nimport {\r\n DEFAULT_LIMITS,\r\n createNodeToolFs,\r\n executeToolCall,\r\n newLedger,\r\n type ReadRecord,\r\n type ToolEnv,\r\n type ToolFs,\r\n type ToolLimits,\r\n type ToolResult,\r\n} from \"./targetingTools\";\r\nimport { estimateRequestTokens } from \"./tokenEstimate\";\r\n\r\n/**\r\n * QUIKTR-1458 \u2014 the read-only targeting loop.\r\n *\r\n * Instead of one call answered from the file listing alone, the runner and the AI Runtime talk in\r\n * turns. Each turn the runner POSTs to the same `/ai/execute`, carrying everything said so far (the\r\n * runtime keeps no state); the runtime answers either \"run these read-only tools\" or the final\r\n * targeting answer, in exactly the shape the single call returns. The runner runs the tools locally,\r\n * on the checkout, and sends the results with the next turn.\r\n *\r\n * The loop is built so it cannot run away and cannot go quiet:\r\n * - it ends with a final answer or a `LoopFailure`; the last turn is always one where the AI is told\r\n * to answer now, and a runtime that still asks for tools then is a failure, not a hang;\r\n * - every limit and every refusal is reported to the AI as a tool RESULT, not an exception;\r\n * - nothing it logs contains file content, a search text or the AI's reasoning.\r\n *\r\n * A `LoopFailure` is an EXPECTED way for this to not work (an older runtime, a timeout, a malformed\r\n * reply), and the caller falls back to the single call. A `SafetyRefusalError` is not: it means the\r\n * runtime refused the run itself (spend cap, credential), and a second call would only be refused or\r\n * paid for again.\r\n *\r\n * The wire shape here is a proposal until the AI Runtime side is built to match it; it is isolated in\r\n * this file so it can change in one place.\r\n */\r\n\r\nexport const LOOP_CONTRACT_VERSION = \"targeting-loop-1\";\r\n\r\nexport type LoopFinalReason = \"max_turns\" | \"tool_budget\" | \"read_budget\" | \"no_progress\";\r\n\r\nexport type LoopStopReason =\r\n | \"model_final\"\r\n | \"forced_max_turns\"\r\n | \"forced_tool_budget\"\r\n | \"forced_read_budget\"\r\n | \"forced_no_progress\"\r\n | \"fallback\";\r\n\r\nexport type FallbackReason =\r\n | \"contract_rejected\"\r\n | \"semantic_mismatch\"\r\n | \"http_error\"\r\n | \"transport\"\r\n | \"turn_timeout\"\r\n | \"loop_deadline\"\r\n | \"runtime_failed\"\r\n | \"bad_reply\"\r\n | \"duplicate_call_ids\"\r\n | \"final_not_produced\"\r\n | \"final_invalid\"\r\n | \"token_ceiling\"\r\n | \"executor_error\"\r\n | \"internal_error\";\r\n\r\nexport interface LoopSummary {\r\n turns: number;\r\n toolCalls: number;\r\n readChars: number;\r\n refused: number;\r\n stopReason: LoopStopReason;\r\n fellBack?: true;\r\n fallbackReason?: FallbackReason;\r\n reads: ReadRecord[];\r\n}\r\n\r\nexport class LoopFailure extends Error {\r\n readonly reason: FallbackReason;\r\n readonly runtimeCode?: string;\r\n /** What the loop had done when it failed, so reads made before the failure are not lost. */\r\n summary?: LoopSummary;\r\n constructor(reason: FallbackReason, runtimeCode?: string, cause?: unknown) {\r\n super(`pilot.targeting loop failed: ${reason}${runtimeCode ? ` (${runtimeCode})` : \"\"}`);\r\n this.name = \"LoopFailure\";\r\n this.reason = reason;\r\n this.runtimeCode = runtimeCode;\r\n if (cause !== undefined) (this as { cause?: unknown }).cause = cause;\r\n }\r\n}\r\n\r\n/** The runtime refused the RUN (not just this turn). Never answered by falling back. */\r\nexport class SafetyRefusalError extends RuntimeReplyError {\r\n constructor(message: string, summary: string) {\r\n super(message, summary);\r\n this.name = \"SafetyRefusalError\";\r\n }\r\n}\r\n\r\n/**\r\n * Runtime error codes that mean the run itself was refused: out of money, or the run credential does\r\n * not cover this. The single call would be refused too, or paid for twice.\r\n */\r\nexport const NO_FALLBACK_CODES: ReadonlySet<string> = new Set([\"RUN_BUDGET_EXCEEDED\", \"RUN_CREDENTIAL_SCOPE\"]);\r\n\r\nexport interface LoopDeps {\r\n /** One POST of `pilot.targeting`; resolves to the RAW `/ai/execute` envelope. */\r\n post(contextData: Record<string, unknown>, signal: AbortSignal): Promise<unknown>;\r\n fs?: ToolFs;\r\n limits?: Partial<ToolLimits>;\r\n now?: () => number;\r\n log?: (event: Record<string, unknown>) => void;\r\n turnTimeoutMs?: number;\r\n deadlineMs?: number;\r\n}\r\n\r\nexport interface LoopArgs {\r\n /** Exactly today's contextData for the single call. */\r\n baseContext: Record<string, unknown>;\r\n listing: string[];\r\n deniedPaths: string[];\r\n}\r\n\r\nconst TOOL_NAMES = new Set([\"list_files\", \"read_file\", \"grep\"]);\r\nconst MAX_ID_CHARS = 64;\r\nconst MAX_CALLS_IN_A_REPLY = 50;\r\nconst MAX_ARGS_JSON_CHARS = 1_000;\r\n\r\nfunction isPlainObject(x: unknown): x is Record<string, unknown> {\r\n return typeof x === \"object\" && x !== null && !Array.isArray(x);\r\n}\r\n\r\nfunction safeArgs(args: unknown): unknown {\r\n try {\r\n return JSON.stringify(args).length <= MAX_ARGS_JSON_CHARS ? args : { _omitted: \"too large\" };\r\n } catch {\r\n return { _omitted: \"unreadable\" };\r\n }\r\n}\r\n\r\nfunction classifyTransport(err: unknown): LoopFailure {\r\n if (err instanceof TargetingHttpError) return new LoopFailure(\"http_error\", undefined, err);\r\n const name = (err as { name?: unknown })?.name;\r\n if (name === \"TimeoutError\" || name === \"AbortError\") return new LoopFailure(\"turn_timeout\", undefined, err);\r\n return new LoopFailure(\"transport\", undefined, err);\r\n}\r\n\r\nexport async function runTargetingLoop(args: LoopArgs, deps: LoopDeps): Promise<{ body: unknown; summary: LoopSummary }> {\r\n const limits: ToolLimits = { ...DEFAULT_LIMITS, ...deps.limits };\r\n const now = deps.now ?? Date.now;\r\n const log = deps.log ?? ((e: Record<string, unknown>) => console.log(JSON.stringify(e)));\r\n const turnTimeoutMs = deps.turnTimeoutMs ?? 180_000;\r\n const deadlineMs = deps.deadlineMs ?? 600_000;\r\n\r\n const env: ToolEnv = {\r\n listing: new Set(args.listing),\r\n visible: buildVisibleListing(args.listing, args.deniedPaths),\r\n deniedPaths: args.deniedPaths,\r\n fs: deps.fs ?? createNodeToolFs(),\r\n limits,\r\n };\r\n const ledger = newLedger();\r\n const reads: ReadRecord[] = [];\r\n const transcript: Record<string, unknown>[] = [];\r\n const toolResults: ToolResult[] = [];\r\n const usedIds = new Set<string>();\r\n\r\n let turns = 0;\r\n let noProgressStreak = 0;\r\n let forced: LoopFinalReason | null = null;\r\n const started = now();\r\n\r\n // Spread then override: `contractVersion` keeps the position it has in today's request.\r\n const buildContext = (turn: number, isFinal: boolean, finalReason: LoopFinalReason): Record<string, unknown> => ({\r\n ...args.baseContext,\r\n contractVersion: LOOP_CONTRACT_VERSION,\r\n loop: {\r\n turn,\r\n maxTurns: limits.maxTurns,\r\n final: isFinal,\r\n ...(isFinal ? { finalReason } : {}),\r\n remaining: {\r\n toolCalls: Math.max(0, limits.maxToolCalls - ledger.toolCalls),\r\n readChars: Math.max(0, limits.readCharsTotal - ledger.readChars),\r\n },\r\n transcript,\r\n toolResults,\r\n },\r\n });\r\n\r\n const snapshot = (stopReason: LoopStopReason): LoopSummary => ({\r\n turns,\r\n toolCalls: ledger.toolCalls,\r\n readChars: ledger.readChars,\r\n refused: ledger.refused,\r\n stopReason,\r\n reads: [...reads],\r\n });\r\n\r\n log({ event: \"targeting.loop_start\", mode: \"loop\", maxTurns: limits.maxTurns, maxToolCalls: limits.maxToolCalls, listingFiles: args.listing.length });\r\n\r\n try {\r\n for (let turn = 1; turn <= limits.maxTurns; turn++) {\r\n turns = turn;\r\n if (now() - started > deadlineMs) throw new LoopFailure(\"loop_deadline\");\r\n\r\n const isFinal = forced !== null || turn === limits.maxTurns;\r\n const finalReason: LoopFinalReason = forced ?? \"max_turns\";\r\n const contextData = buildContext(turn, isFinal, finalReason);\r\n const requestChars = JSON.stringify(contextData).length;\r\n // The ceiling is enforced HERE because nothing else does: the runtime has no pre-dispatch size check\r\n // for targeting, and an oversized turn does not refuse cleanly \u2014 it fails at the provider.\r\n const requestTokens = estimateRequestTokens(contextData);\r\n if (requestTokens > limits.maxRequestTokens) {\r\n log({ event: \"targeting.loop_ceiling\", turn, action: \"not_sent\", projectedTokens: requestTokens, ceiling: limits.maxRequestTokens });\r\n throw new LoopFailure(\"token_ceiling\");\r\n }\r\n\r\n const turnStarted = now();\r\n let envelope: unknown;\r\n try {\r\n envelope = await deps.post(contextData, AbortSignal.timeout(turnTimeoutMs));\r\n } catch (err) {\r\n throw classifyTransport(err);\r\n }\r\n\r\n const code = (envelope as { errorCode?: unknown } | null)?.errorCode;\r\n try {\r\n checkHardFailure(envelope, \"pilot.targeting\");\r\n } catch (err) {\r\n throw new LoopFailure(code === \"CONTRACT_REJECTED\" ? \"contract_rejected\" : \"semantic_mismatch\", String(code), err);\r\n }\r\n if ((envelope as { success?: unknown } | null)?.success === false) {\r\n const runtimeCode = typeof code === \"string\" ? code : undefined;\r\n if (runtimeCode && NO_FALLBACK_CODES.has(runtimeCode)) {\r\n let inner: RuntimeReplyError | undefined;\r\n try {\r\n unwrapExecute(envelope, \"pilot.targeting\");\r\n } catch (e) {\r\n inner = e instanceof RuntimeReplyError ? e : undefined;\r\n }\r\n const fallbackText = `pilot.targeting failed: ${runtimeCode}`;\r\n throw new SafetyRefusalError(inner?.message ?? fallbackText, inner?.summary ?? fallbackText);\r\n }\r\n throw new LoopFailure(\"runtime_failed\", runtimeCode);\r\n }\r\n\r\n let body: Record<string, unknown>;\r\n try {\r\n body = unwrapExecute<Record<string, unknown>>(envelope, \"pilot.targeting\");\r\n } catch (err) {\r\n throw new LoopFailure(\"bad_reply\", undefined, err);\r\n }\r\n\r\n if (body.outcome === \"TARGETED\" || body.outcome === \"NO_TARGET\") {\r\n log({ event: \"targeting.loop_turn\", turn, outcome: \"final\", requestChars, requestTokens, elapsedMs: now() - turnStarted, calls: [] });\r\n const stopReason: LoopStopReason = isFinal ? (`forced_${finalReason}` as LoopStopReason) : \"model_final\";\r\n log({ event: \"targeting.loop_done\", turns, toolCalls: ledger.toolCalls, readChars: ledger.readChars, refused: ledger.refused, stopReason });\r\n return { body, summary: snapshot(stopReason) };\r\n }\r\n if (body.outcome !== \"TOOL_CALLS\") throw new LoopFailure(\"bad_reply\");\r\n if (isFinal) throw new LoopFailure(\"final_not_produced\");\r\n\r\n const rawCalls = body.toolCalls;\r\n if (!Array.isArray(rawCalls) || rawCalls.length === 0 || rawCalls.length > MAX_CALLS_IN_A_REPLY) {\r\n throw new LoopFailure(\"bad_reply\");\r\n }\r\n const calls: { id: string; name: string; args: unknown }[] = [];\r\n for (const c of rawCalls) {\r\n if (!isPlainObject(c) || typeof c.id !== \"string\" || c.id.length === 0 || c.id.length > MAX_ID_CHARS || typeof c.name !== \"string\") {\r\n throw new LoopFailure(\"bad_reply\");\r\n }\r\n if (usedIds.has(c.id) || calls.some((x) => x.id === c.id)) throw new LoopFailure(\"duplicate_call_ids\");\r\n calls.push({ id: c.id, name: c.name, args: c.args });\r\n }\r\n for (const c of calls) usedIds.add(c.id);\r\n\r\n const results: ToolResult[] = [];\r\n const logged: Record<string, unknown>[] = [];\r\n const turnReads: (ReadRecord | undefined)[] = [];\r\n calls.forEach((call, index) => {\r\n let result: ToolResult;\r\n let read: ReadRecord | undefined;\r\n if (index >= limits.maxCallsPerTurn) {\r\n result = {\r\n id: call.id,\r\n name: call.name,\r\n status: \"budget_exhausted\",\r\n reason: \"too_many_calls\",\r\n message: \"Too many calls in one turn; this one was not run.\",\r\n };\r\n } else {\r\n try {\r\n ({ result, read } = executeToolCall(call, env, ledger));\r\n } catch (err) {\r\n throw new LoopFailure(\"executor_error\", undefined, err);\r\n }\r\n }\r\n results.push(result);\r\n turnReads[index] = read;\r\n if (read) reads.push(read);\r\n const tool = TOOL_NAMES.has(call.name) ? call.name : \"unknown\";\r\n const path = read && read.path !== \"(invalid path)\" ? { path: read.path } : {};\r\n logged.push({ tool, status: result.status, ...(result.reason && result.status !== \"duplicate\" ? { reason: result.reason } : {}), ...path });\r\n if (result.status === \"refused\") {\r\n log({ event: \"targeting.loop_refused\", turn, tool, reason: result.reason, ...path });\r\n }\r\n });\r\n\r\n const reasoning = typeof body.reasoning === \"string\" ? body.reasoning.slice(0, limits.maxReasoningChars) : undefined;\r\n transcript.push({\r\n turn,\r\n ...(reasoning ? { reasoning } : {}),\r\n toolCalls: calls.map((c) => ({ id: c.id, name: c.name, args: safeArgs(c.args) })),\r\n });\r\n toolResults.push(...results);\r\n\r\n noProgressStreak = results.every((r) => r.status === \"duplicate\") ? noProgressStreak + 1 : 0;\r\n if (noProgressStreak >= 2) forced = \"no_progress\";\r\n else if (ledger.toolCalls >= limits.maxToolCalls) forced = \"tool_budget\";\r\n else if (ledger.readChars >= limits.readCharsTotal || ledger.resultChars >= limits.resultCharsTotal) forced = \"read_budget\";\r\n\r\n // Would the NEXT request still fit? A loop accumulates, so it is this, not a total, that can break.\r\n // If not: do not deliver what this turn found, tell the AI so (a result it already understands:\r\n // `budget_exhausted`), and make the next turn its last. If even that cannot fit, give up to the\r\n // single call rather than send something the provider will fail on.\r\n const nextTurn = turn + 1;\r\n if (nextTurn <= limits.maxTurns) {\r\n const nextFinal = forced !== null || nextTurn === limits.maxTurns;\r\n const projected = estimateRequestTokens(buildContext(nextTurn, nextFinal, forced ?? \"max_turns\"));\r\n if (projected > limits.maxRequestTokens) {\r\n results.forEach((r, idx) => {\r\n if (r.status !== \"ok\") return;\r\n toolResults[toolResults.indexOf(r)] = {\r\n id: r.id,\r\n name: r.name,\r\n status: \"budget_exhausted\",\r\n reason: \"token_ceiling\",\r\n message: \"Too large to include; answer from what you have.\",\r\n };\r\n const dropped = turnReads[idx];\r\n if (dropped) {\r\n const at = reads.indexOf(dropped);\r\n if (at >= 0) reads.splice(at, 1);\r\n }\r\n logged[idx].status = \"budget_exhausted\";\r\n logged[idx].reason = \"token_ceiling\";\r\n });\r\n forced = \"read_budget\";\r\n const trimmed = estimateRequestTokens(buildContext(nextTurn, true, \"read_budget\"));\r\n const fits = trimmed <= limits.maxRequestTokens;\r\n log({\r\n event: \"targeting.loop_ceiling\",\r\n turn,\r\n action: fits ? \"dropped_results\" : \"fallback\",\r\n projectedTokens: projected,\r\n ceiling: limits.maxRequestTokens,\r\n });\r\n if (!fits) throw new LoopFailure(\"token_ceiling\");\r\n }\r\n }\r\n log({ event: \"targeting.loop_turn\", turn, outcome: \"tool_calls\", requestChars, requestTokens, elapsedMs: now() - turnStarted, calls: logged });\r\n }\r\n throw new LoopFailure(\"final_not_produced\");\r\n } catch (err) {\r\n if (err instanceof SafetyRefusalError) throw err;\r\n const failure = err instanceof LoopFailure ? err : new LoopFailure(\"internal_error\", undefined, err);\r\n failure.summary ??= snapshot(\"fallback\");\r\n throw failure;\r\n }\r\n}\r\n", "import type { TargetKind, TargetingResult } from \"./targeting\";\r\nimport type { LoopStopReason, LoopSummary } from \"./targetingLoop\";\r\n\r\n/**\r\n * QUIKTR-1421 \u2014 a record of what pilot.targeting decided, reported to QuikTrack in the run's final callback so\r\n * \"which contextPaths did targeting list for the test?\" can be answered after the fact. Twice it could not\r\n * (QUIKSPL-16, then run 25): the AI Runtime's logs carry counts only, deliberately, and QuikTrack's run trail\r\n * stores a payload hash, so neither side kept what was actually DECIDED.\r\n *\r\n * PATHS AND CASE IDS ONLY (Suyash). Never case text, never `planStepsImplemented` (model-written prose about\r\n * the customer's code), never file content. The one free-text field is the NO_TARGET reason, cut to 300\r\n * characters with a flag saying so.\r\n *\r\n * Every cap below matches QuikTrack's `targetingRecordSchema`. That is not tidiness: a record QuikTrack finds\r\n * invalid is dropped, so a record over the caps is a record lost. Anything cut sets `truncated`.\r\n */\r\nconst MAX_TARGETS = 25;\r\nconst MAX_IDS_PER_TARGET = 50;\r\nconst MAX_CONTEXT_PATHS = 20;\r\nconst MAX_ADDED_PATHS = 20;\r\nconst MAX_SKIPPED_CONTEXT = 20;\r\nconst MAX_SKIPPED_CASES = 200;\r\nconst MAX_CONTEXT_RECORDS = 25;\r\nconst MAX_PATH_CHARS = 300;\r\nconst MAX_ID_CHARS = 100;\r\nconst MAX_REASON_CHARS = 300;\r\n// QUIKTR-1458 \u2014 the read-only loop's part of the record. These must match QuikTrack's schema when it adds the field.\r\nconst MAX_LOOP_READS = 50;\r\nconst MAX_FALLBACK_REASON_CHARS = 40;\r\n\r\n/** One `runCodegen` call: what targeting named as context, what the runner ADDED (QUIKTR-1419), and what it\r\n * skipped. `runCodegen` fills a caller-owned array of these, so the entries survive a later throw. */\r\nexport interface CodegenContextRecord {\r\n targetPath: string;\r\n contextPaths: string[];\r\n addedPaths: string[];\r\n skipped: { path: string; reason: string }[];\r\n /** QUIKTR-1454 \u2014 the part of `addedPaths` that came from the target's own imports. Log line only: QuikTrack's\r\n * record keeps `addedPaths` (which includes them) and strips fields it does not know. Omitted when empty. */\r\n importedPaths?: string[];\r\n /** QUIKTR-1454 \u2014 path-alias imports (`@/x`) seen and not followed. Counted, not listed. Omitted when zero. */\r\n aliasImports?: number;\r\n /** The runtime refused the context as too large and the call was retried WITHOUT the added files, so\r\n * `addedPaths` is empty even though files were offered first. */\r\n retriedWithoutAdded?: true;\r\n}\r\n\r\n/**\r\n * QUIKTR-1458 \u2014 what the read-only targeting loop looked at. PATHS AND COUNTS ONLY: never file content, a\r\n * search text or the AI's reasoning. Present only when the loop ran (or was tried and fell back); an older\r\n * QuikTrack strips the key it does not know. It is how a reviewer can see what the AI read, which is why\r\n * refused reads are listed too.\r\n */\r\nexport interface LoopRecord {\r\n turns: number;\r\n toolCalls: number;\r\n refused: number;\r\n stopReason: LoopStopReason;\r\n fellBack?: true;\r\n fallbackReason?: string;\r\n reads: { path: string; startLine?: number; endLine?: number; chars: number; refused?: true }[];\r\n truncated?: true;\r\n}\r\n\r\nexport interface TargetingRecord {\r\n outcome: \"TARGETED\" | \"NO_TARGET\";\r\n noTargetReason?: string;\r\n noTargetReasonTruncated?: true;\r\n targets: { path: string; kind: TargetKind; contextPaths: string[]; automationIds: string[] }[];\r\n skippedCaseIds: string[];\r\n codegenContext: CodegenContextRecord[];\r\n truncated?: true;\r\n /** QUIKTR-1458 \u2014 see LoopRecord. */\r\n loop?: LoopRecord;\r\n}\r\n\r\n/** Keeps at most `max` non-empty entries no longer than `maxChars`, telling the caller if anything was cut. A\r\n * too-long value is DROPPED, not shortened: a cut-off path is a wrong path. */\r\nfunction clampList(values: string[] | undefined, max: number, maxChars: number): { kept: string[]; cut: boolean } {\r\n let cut = false;\r\n const kept: string[] = [];\r\n for (const raw of values ?? []) {\r\n const v = typeof raw === \"string\" ? raw.trim() : \"\";\r\n if (v.length === 0) continue;\r\n if (v.length > maxChars || kept.length >= max) {\r\n cut = true;\r\n continue;\r\n }\r\n kept.push(v);\r\n }\r\n return { kept, cut };\r\n}\r\n\r\nfunction wholeNumber(n: unknown): number {\r\n return typeof n === \"number\" && Number.isInteger(n) && n >= 0 ? n : 0;\r\n}\r\n\r\n/** A too-long path is DROPPED, not shortened (a cut-off path is a wrong path), and the cut is flagged. */\r\nfunction clampLoop(loop: LoopSummary): LoopRecord {\r\n let cut = false;\r\n const reads: LoopRecord[\"reads\"] = [];\r\n for (const r of loop.reads ?? []) {\r\n if (reads.length >= MAX_LOOP_READS) {\r\n cut = true;\r\n break;\r\n }\r\n const path = typeof r.path === \"string\" ? r.path.trim() : \"\";\r\n if (path.length === 0 || path.length > MAX_PATH_CHARS) {\r\n cut = true;\r\n continue;\r\n }\r\n reads.push({\r\n path,\r\n ...(Number.isInteger(r.startLine) ? { startLine: r.startLine } : {}),\r\n ...(Number.isInteger(r.endLine) ? { endLine: r.endLine } : {}),\r\n chars: wholeNumber(r.chars),\r\n ...(r.refused ? { refused: true as const } : {}),\r\n });\r\n }\r\n return {\r\n turns: wholeNumber(loop.turns),\r\n toolCalls: wholeNumber(loop.toolCalls),\r\n refused: wholeNumber(loop.refused),\r\n stopReason: loop.stopReason,\r\n ...(loop.fellBack ? { fellBack: true as const } : {}),\r\n ...(loop.fallbackReason ? { fallbackReason: String(loop.fallbackReason).slice(0, MAX_FALLBACK_REASON_CHARS) } : {}),\r\n reads,\r\n ...(cut ? { truncated: true as const } : {}),\r\n };\r\n}\r\n\r\nexport function buildTargetingRecord(targeting: TargetingResult, contextLog: CodegenContextRecord[]): TargetingRecord {\r\n let truncated = false;\r\n const note = (cut: boolean) => {\r\n if (cut) truncated = true;\r\n };\r\n\r\n if (targeting.outcome === \"NO_TARGET\") {\r\n const record: TargetingRecord = { outcome: \"NO_TARGET\", targets: [], skippedCaseIds: [], codegenContext: [] };\r\n const reason = (targeting.reason ?? \"\").trim();\r\n if (reason.length > 0) {\r\n record.noTargetReason = reason.slice(0, MAX_REASON_CHARS);\r\n if (reason.length > MAX_REASON_CHARS) record.noTargetReasonTruncated = true;\r\n }\r\n if (targeting.loop) record.loop = clampLoop(targeting.loop);\r\n return record;\r\n }\r\n\r\n const targets: TargetingRecord[\"targets\"] = [];\r\n for (const t of targeting.targets) {\r\n if (targets.length >= MAX_TARGETS) {\r\n truncated = true;\r\n break;\r\n }\r\n const path = typeof t.path === \"string\" ? t.path.trim() : \"\";\r\n if (path.length === 0 || path.length > MAX_PATH_CHARS) {\r\n truncated = true;\r\n continue;\r\n }\r\n const contextPaths = clampList(t.contextPaths, MAX_CONTEXT_PATHS, MAX_PATH_CHARS);\r\n const automationIds = clampList(t.automationIds, MAX_IDS_PER_TARGET, MAX_ID_CHARS);\r\n note(contextPaths.cut);\r\n note(automationIds.cut);\r\n targets.push({ path, kind: t.kind, contextPaths: contextPaths.kept, automationIds: automationIds.kept });\r\n }\r\n\r\n const skipped = clampList(\r\n (targeting.skippedCases ?? []).map((c) => c.automationId),\r\n MAX_SKIPPED_CASES,\r\n MAX_ID_CHARS,\r\n );\r\n note(skipped.cut);\r\n\r\n const codegenContext: CodegenContextRecord[] = [];\r\n for (const entry of contextLog) {\r\n if (codegenContext.length >= MAX_CONTEXT_RECORDS) {\r\n truncated = true;\r\n break;\r\n }\r\n const targetPath = typeof entry.targetPath === \"string\" ? entry.targetPath.trim() : \"\";\r\n if (targetPath.length === 0 || targetPath.length > MAX_PATH_CHARS) {\r\n truncated = true;\r\n continue;\r\n }\r\n const contextPaths = clampList(entry.contextPaths, MAX_CONTEXT_PATHS, MAX_PATH_CHARS);\r\n const addedPaths = clampList(entry.addedPaths, MAX_ADDED_PATHS, MAX_PATH_CHARS);\r\n const skippedPaths = clampList(\r\n (entry.skipped ?? []).map((s) => s.path),\r\n MAX_SKIPPED_CONTEXT,\r\n MAX_PATH_CHARS,\r\n );\r\n note(contextPaths.cut);\r\n note(addedPaths.cut);\r\n note(skippedPaths.cut);\r\n const reasonByPath = new Map((entry.skipped ?? []).map((s) => [s.path.trim(), s.reason]));\r\n codegenContext.push({\r\n targetPath,\r\n contextPaths: contextPaths.kept,\r\n addedPaths: addedPaths.kept,\r\n skipped: skippedPaths.kept.map((path) => ({ path, reason: String(reasonByPath.get(path) ?? \"skipped\").slice(0, 40) })),\r\n ...(entry.retriedWithoutAdded ? { retriedWithoutAdded: true as const } : {}),\r\n });\r\n }\r\n\r\n const record: TargetingRecord = {\r\n outcome: \"TARGETED\",\r\n targets,\r\n skippedCaseIds: skipped.kept,\r\n codegenContext,\r\n };\r\n if (truncated) record.truncated = true;\r\n if (targeting.loop) record.loop = clampLoop(targeting.loop);\r\n return record;\r\n}\r\n", "import type { PilotTarget } from \"./targeting\";\r\n\r\n/**\r\n * QUIKTR-1315 \u2014 targeting can claim a test case's `automationId` against a SOURCE-file target while\r\n * proposing a separate, empty test-file target alongside it (no plan steps, no automationIds).\r\n * Verified against a real captured AI Runtime sample (`targeting-versioned.json`): the model wrote\r\n * `tests/auth/login.test.ts` with `automationIds: []` and claimed all three cases on\r\n * `src/auth/middleware.ts`/`src/auth/login.ts` instead. When that happens, the generated test lands\r\n * inside a source file the repository's test runner never discovers \u2014 the case has zero real\r\n * coverage even though its id is present in the generated text, and \u00A715's own completeness rule\r\n * (every case appears exactly once) is satisfied regardless.\r\n *\r\n * Two detectors, both using the repository's OWN JUnit report as ground truth for \"which files the\r\n * test runner actually looks at\" \u2014 no naming convention, derived by running the repo's own tooling,\r\n * language-neutral by construction:\r\n *\r\n * `checkTestPlacement` \u2014 BEFORE the write, against the BASELINE report (pre-codegen).\r\n * Scoped to EXISTING targets only: a NEW_FILE test target is never\r\n * in the baseline set because it does not exist yet, so this check\r\n * must never run on one \u2014 a legitimate first test file would be\r\n * indistinguishable from the suspicious case.\r\n * `checkAutomationIdCoverage` \u2014 AFTER the change, against the AFTER report (post-codegen). The\r\n * stronger of the two: catches inverted placement regardless of\r\n * why it happened, including whatever the first check's loose\r\n * file-matching missed.\r\n *\r\n * Both are TRIPWIRES, not proofs \u2014 same posture as this package's other `*Check.ts` scanners\r\n * (`dependencyCheck.ts`, `scopeCheck.ts`): a minimal heuristic against an arbitrary target repo,\r\n * deliberately erring toward under-flagging (fewer false positives blocking a real run) rather than\r\n * over-flagging, since both are hard-failing checks.\r\n */\r\nexport interface TestPlacementViolation {\r\n file: string;\r\n automationIds: string[];\r\n}\r\n\r\nexport interface TestPlacementCheck {\r\n blocked: boolean;\r\n violations: TestPlacementViolation[];\r\n}\r\n\r\n/** A target's path counts as \"discovered\" if it exactly equals, is a suffix of, or has as a suffix,\r\n * any candidate string the JUnit report produced. Loose on purpose: `classname` is a real file path\r\n * for Vitest and derivable for pytest, but not guaranteed for Jest or Go \u2014 see this file's module\r\n * docblock. A tighter, exact-only match would false-positive on every repo where the report's path\r\n * is relative to a different root than the target's own path. */\r\nfunction isDiscovered(targetPath: string, discoveredFiles: Set<string>): boolean {\r\n const normalized = targetPath.replace(/\\\\/g, \"/\");\r\n for (const candidate of discoveredFiles) {\r\n if (candidate === normalized) return true;\r\n if (candidate.endsWith(normalized) || normalized.endsWith(candidate)) return true;\r\n }\r\n return false;\r\n}\r\n\r\n/**\r\n * `discoveredFiles` is the BASELINE run's `TestSnapshot.discoveredFiles` \u2014 `undefined`/`null`/empty\r\n * all mean \"can't tell,\" and the check no-ops rather than blocking on a question it can't answer\r\n * (no baseline report at all, or one with no file-shaped attribution). A repository producing no\r\n * JUnit report gets no detector \u2014 not a gap here, `readiness-panel`'s existing dry-run warning\r\n * (QUIKTR-1084) is what tells the user to fix that.\r\n */\r\nexport function checkTestPlacement(\r\n targets: PilotTarget[],\r\n discoveredFiles: Set<string> | null | undefined,\r\n): TestPlacementCheck {\r\n if (!discoveredFiles || discoveredFiles.size === 0) return { blocked: false, violations: [] };\r\n\r\n const violations: TestPlacementViolation[] = [];\r\n for (const target of targets) {\r\n if (target.kind !== \"EXISTING\") continue;\r\n if (!target.automationIds || target.automationIds.length === 0) continue;\r\n if (!isDiscovered(target.path, discoveredFiles)) {\r\n violations.push({ file: target.path, automationIds: target.automationIds });\r\n }\r\n }\r\n return { blocked: violations.length > 0, violations };\r\n}\r\n\r\nexport function describeTestPlacementViolations(check: TestPlacementCheck): string {\r\n return check.violations\r\n .map(\r\n (v) =>\r\n `${v.file} claims test case(s) ${v.automationIds.join(\", \")} but the repository's own test runner never discovered this file`,\r\n )\r\n .join(\"; \");\r\n}\r\n\r\nexport interface AutomationCoverageCheck {\r\n blocked: boolean;\r\n missing: string[];\r\n}\r\n\r\n/**\r\n * `discoveredAutomationIds` is the AFTER run's `TestSnapshot.discoveredAutomationIds` \u2014\r\n * `undefined`/`null` means \"can't tell\" (no post-codegen report at all), same no-op posture as\r\n * `checkTestPlacement`. An EMPTY (present) set is different and deliberate: it means a report\r\n * existed but nothing in it carried a bracketed id at all, which \u2014 if this run claimed any\r\n * `automationIds` \u2014 is exactly the failure this check exists to catch, so it blocks.\r\n */\r\nexport function checkAutomationIdCoverage(\r\n targets: PilotTarget[],\r\n discoveredAutomationIds: Set<string> | null | undefined,\r\n): AutomationCoverageCheck {\r\n if (discoveredAutomationIds === null || discoveredAutomationIds === undefined) {\r\n return { blocked: false, missing: [] };\r\n }\r\n\r\n const claimed = new Set<string>();\r\n for (const target of targets) {\r\n for (const id of target.automationIds ?? []) claimed.add(id);\r\n }\r\n const missing = [...claimed].filter((id) => !discoveredAutomationIds.has(id));\r\n return { blocked: missing.length > 0, missing };\r\n}\r\n\r\nexport function describeAutomationCoverageViolations(check: AutomationCoverageCheck): string {\r\n return `test case(s) ${check.missing.join(\", \")} have no matching test discovered in the test run \u2014 generated, but never executed`;\r\n}\r\n", "import { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\ninterface TokenExchangeResponse {\r\n success: boolean;\r\n data: { runToken: string; expiresAt: string };\r\n}\r\n\r\n/** Exchange a GitHub OIDC ID token for a QuikPilot run token (QUIKTR-805) \u2014 mirrors `packet.ts`'s\r\n * `fetchPacket` shape: bearer auth, `{success,data}` envelope, same error-message style. */\r\nexport async function exchangeForRunToken(tokenUrl: string, oidcToken: string): Promise<string> {\r\n const res = await fetch(tokenUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${oidcToken}` },\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Exchange run token failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n const body = (await res.json()) as TokenExchangeResponse;\r\n if (body.success !== true) {\r\n throw new Error(\"Exchange run token failed: response did not carry success:true\");\r\n }\r\n return body.data.runToken;\r\n}\r\n", "import type { TestSnapshot } from \"./regressionCheck\";\r\n\r\n/**\r\n * QUIKTR-1448 \u2014 a test that ran before the change and is missing from the final report. The regression gate\r\n * only looks at tests present AFTER, so a rewritten test file that drops tests passes it (QuikSplit PR #4\r\n * lost 9 tests this way). Warn-only: the fix may mean to remove or rename a test, and a user has no way yet\r\n * to approve that, so nothing here blocks a run.\r\n */\r\nexport interface VanishedTests {\r\n /** Test ids (`classname::name`), at most MAX_VANISHED_NAMES. */\r\n names: string[];\r\n /** How many went missing, including any names cut by the cap. */\r\n total: number;\r\n}\r\n\r\n/** Bounds the callback body and the pull request description. */\r\nexport const MAX_VANISHED_NAMES = 50;\r\n\r\n/** Null when nothing is missing, or when either run produced no report (cannot tell \u2014 same posture as\r\n * `checkForRegressions`, which also stays quiet then). A test that still exists and now fails is a\r\n * regression, not a missing test, so it is not named here. */\r\nexport function findVanishedTests(baseline: TestSnapshot, after: TestSnapshot): VanishedTests | null {\r\n if (!baseline.results || !after.results) return null;\r\n const missing = [...baseline.results.keys()].filter((id) => !after.results!.has(id));\r\n if (missing.length === 0) return null;\r\n return { names: missing.slice(0, MAX_VANISHED_NAMES), total: missing.length };\r\n}\r\n\r\n/** The run-event warning. A COUNT only: test titles are the customer's text and the event reason is stored by\r\n * QuikTrack; the titles go to the pull request description instead. */\r\nexport function describeVanishedTests(vanished: VanishedTests): string {\r\n const noun = vanished.total === 1 ? \"1 test\" : `${vanished.total} tests`;\r\n return `${noun} that ran before this change ${vanished.total === 1 ? \"is\" : \"are\"} missing from the final test report; the pull request lists ${vanished.total === 1 ? \"it\" : \"them\"}.`;\r\n}\r\n", "import { reportBack } from \"./callback\";\r\nimport { runCommand, runTestCommand } from \"./commands\";\r\nimport { commitAndPush } from \"./commit\";\r\nimport { buildJudgedByPool, flushCodegenResults, runCodegen, type CodegenFileResult } from \"./codegen\";\r\nimport {\r\n checkImportDependencies,\r\n describeDependencyViolations,\r\n readDeclaredDependencies,\r\n resolveAliasPrefixes,\r\n} from \"./dependencyCheck\";\r\nimport type { PilotRunEnv } from \"./env\";\r\nimport { checkGuardrail } from \"./guardrail\";\r\nimport { checkoutTargetBranch } from \"./git\";\r\nimport { exchangeForInstallationToken } from \"./installationToken\";\r\nimport { fetchGithubOidcToken } from \"./oidc\";\r\nimport { describeOverlapWarnings, findOverlappingSteps } from \"./overlapCheck\";\r\nimport { fetchPacket, type PilotPacket } from \"./packet\";\r\nimport { writePhase0Marker } from \"./phase0\";\r\nimport { describeUnmatchedAutomationIds, readTestReportBytes, reportToQuikTest } from \"./quiktest\";\r\nimport { runBaselineCheck, type BaselineFindings } from \"./baselineCheck\";\r\nimport { writeFailureArtifact } from \"./failureArtifact\";\r\nimport { describeFailureReason, failureSummary } from \"./failureReason\";\r\nimport { captureBaselineSnapshot, captureTestSnapshot, checkForRegressions, describeRegressions } from \"./regressionCheck\";\r\nimport { checkApiScope, describeScopeViolations } from \"./scopeCheck\";\r\nimport { listWorkspaceFiles, runTargeting, type TargetingResult } from \"./targeting\";\r\nimport { buildTargetingRecord, type CodegenContextRecord } from \"./targetingRecord\";\r\nimport {\r\n checkAutomationIdCoverage,\r\n checkTestPlacement,\r\n describeAutomationCoverageViolations,\r\n describeTestPlacementViolations,\r\n} from \"./testPlacementCheck\";\r\nimport { exchangeForRunToken } from \"./tokenExchange\";\r\nimport { describeVanishedTests, findVanishedTests, type VanishedTests } from \"./vanishedTests\";\r\n\r\n/**\r\n * QUIKTR-572 \u2014 the run sequence, preserving the original inlined workflow's error semantics exactly:\r\n * Fetch packet / Checkout branch / Setup / Lint / Guardrail are hard failures that skip everything\r\n * remaining except the QuikTest report and the final callback (both ran under `if: always()`\r\n * before). Test alone is soft \u2014 its failure never blocks Guardrail/Commit/Push and never flips the\r\n * final callback to `failed` (QuikTest owns per-test outcomes; captured here only for the log).\r\n *\r\n * QUIKTR-1045 \u2014 Format is soft, same reasoning as Test: a formatting hiccup must not block a\r\n * correct fix. Caught locally at its own call site (not a new commands.ts function) and logged;\r\n * never sets hardFailure, never blocks the Lint/regression-check/Guardrail/Commit/Push that follow.\r\n *\r\n * QUIKTR-805 \u2014 the very first thing the run does is exchange a GitHub OIDC ID token for a run\r\n * token (no QuikPilot credential exists before this). It is folded into the same top-level try as\r\n * every other hard failure, with one deliberate exception: if THIS step fails, there is no run\r\n * token to report failure with either, so reportToQuikTest/reportBack are skipped rather than\r\n * called with nothing to authenticate \u2014 the job's own log is the only record, and the run's\r\n * existing DISPATCHING-expiry sweep is what notices it (same accepted fallback dispatch.ts's own\r\n * docblock documents for its \"RESIDUAL WINDOW\" crash case).\r\n *\r\n * QUIKTR-804 \u2014 immediately before pushing, the run token (already in hand by this point) is\r\n * exchanged for a repo-scoped GitHub installation token, which authenticates the push itself\r\n * instead of the ambient `github.token`. Folded into the EXISTING Guardrail/Commit/Push try block\r\n * below rather than given its own \u2014 a failure here is just another commit/push hard failure, with\r\n * no new edge case: unlike the OIDC exchange above, the run token already exists, so\r\n * reportToQuikTest/reportBack fire normally either way.\r\n */\r\n/** Caller narrows `RunnerEnv` to `PilotRunEnv` first \u2014 `index.ts` branches on `mode` before either\r\n * this or `readinessCheck.ts`'s `runReadinessCheck` is invoked. No default parameter: the old\r\n * `readRunnerEnv()` default returned this shape unconditionally, which is no longer true now\r\n * that `RunnerEnv` is a union (QUIKTR-1084). */\r\nexport async function run(env: PilotRunEnv): Promise<{ hardFailure: boolean }> {\r\n let hardFailure = false;\r\n let packet: PilotPacket | undefined;\r\n let branch: string | undefined;\r\n let runToken: string | undefined;\r\n const warnings: string[] = [];\r\n // Why the run failed, for the final callback. The message used to be printed to the job log and lost to\r\n // QuikTrack, which then knew only \"failed\". Scrubbed of credentials and cut before it is kept.\r\n const failureReasons: string[] = [];\r\n const recordFailure = (err: unknown) => {\r\n const message = err instanceof Error ? err.message : String(err);\r\n console.error(message);\r\n // The job log gets the full message; what is reported is the summary when the error quotes the AI Runtime's reply.\r\n const reason = describeFailureReason(failureSummary(err), runToken ? [runToken] : []);\r\n if (reason) failureReasons.push(reason);\r\n };\r\n // QUIKTR-1067 \u2014 hoisted out of the try block's TARGETED branch: commitAndPush\r\n // needs it later, outside that scope, to build a real commit message instead\r\n // of the \"Phase 0 skeleton\" placeholder. Defaults false \u2014 correct for\r\n // NO_TARGET and for any early hard failure, both of which skip commitAndPush\r\n // or must fall back to the marker message anyway.\r\n let targeted = false;\r\n // QUIKTR-1333 \u2014 same hoisting reason as `targeted` above: reportToQuikTest is\r\n // called later, outside the TARGETED branch's scope where `results` lives.\r\n // Empty for NO_TARGET and any early failure \u2014 correct, since nothing was\r\n // written either way.\r\n let generatedFilePaths: string[] = [];\r\n // QUIKTR-1447 \u2014 hoisted for the same reason, so a run that fails AFTER code generation can keep what was generated.\r\n // Held in memory because the dependency, scope and placement checks fail before the files are flushed. The final\r\n // test report is read right after the post-generation test run and nowhere else: a report on disk before that is\r\n // the baseline's, and reportToQuikTest deletes it once sent.\r\n let generatedResults: CodegenFileResult[] = [];\r\n let finalTestReport: Buffer | null = null;\r\n // QUIKTR-1421 \u2014 hoisted for the same reason: the record is built at the end, outside the try, so a run that\r\n // dies in codegen still reports what targeting decided and which context codegen had already assembled.\r\n let targetingResult: TargetingResult | undefined;\r\n // QUIKTR-1402 \u2014 hoisted for the same reason: reported at the end, outside the try. Undefined when the check\r\n // did not run or flagged nothing.\r\n let baselineFindings: BaselineFindings | undefined;\r\n // QUIKTR-1448 \u2014 hoisted for the same reason: reported at the end, and it must survive a run that then fails on a\r\n // regression. Undefined when no test went missing or a report was not available.\r\n let vanishedTests: VanishedTests | undefined;\r\n const contextLog: CodegenContextRecord[] = [];\r\n\r\n try {\r\n runToken = await exchangeForRunToken(env.tokenUrl, await fetchGithubOidcToken());\r\n packet = await fetchPacket(env.packetUrl, runToken, env.githubRunId);\r\n checkoutTargetBranch(packet.targetBranch);\r\n\r\n const workspaceListing = listWorkspaceFiles(packet.workspaceRoot);\r\n // QUIKTR-1401 (\u00A720) \u2014 the reviewer's approved \"must not change\" list, with blank entries dropped. A QuikTrack\r\n // that predates the field sends none, which is the same as an empty list.\r\n const outOfScope = (packet.outOfScope ?? []).map((entry) => entry.trim()).filter((entry) => entry.length > 0);\r\n const targeting = await runTargeting(\r\n packet.gateway,\r\n packet.design,\r\n packet.workspaceRoot,\r\n workspaceListing,\r\n packet.requiredTests,\r\n packet.guardrails.deniedPaths,\r\n packet.testDiscovery,\r\n outOfScope,\r\n );\r\n targetingResult = targeting;\r\n // QUIKTR-1458 \u2014 the read-only loop could not finish and the single call was used instead. Not blocking, but\r\n // said out loud: it changes what the AI was shown, and a run that quietly stopped using the loop would make\r\n // every comparison between the two modes meaningless.\r\n for (const w of targeting.warnings ?? []) {\r\n warnings.push(w);\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n }\r\n // QUIKTR-1448 \u2014 targeting called an existing file a new one; runTargeting already treated it as existing, so the\r\n // model saw its content. Said out loud because it is a mistake in the plan, not something to hide.\r\n if (targeting.outcome === \"TARGETED\") {\r\n for (const path of targeting.correctedKinds ?? []) {\r\n const w = `QuikPilot named ${path} as a new file, but it already exists in the repository. It was treated as an existing file so its current content was kept in view.`;\r\n warnings.push(w);\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n console.log(JSON.stringify({ event: \"targeting.kind_corrected\", path }));\r\n }\r\n }\r\n if (targeting.outcome === \"NO_TARGET\") {\r\n // Nothing to write \u2014 a marker commit is more honest than an empty one. Nothing was\r\n // generated, so there's nothing to regress against \u2014 Test stays soft, unchanged.\r\n writePhase0Marker(env.runId);\r\n runCommand(packet.commands.setup, \"Setup\");\r\n runCommand(packet.commands.lint, \"Lint\");\r\n runTestCommand(packet.commands.test);\r\n } else {\r\n targeted = true;\r\n // QUIKTR-1083 (\u00A715.3) \u2014 informational, never blocking: a case with no given/when/then has\r\n // nothing to test, and the runtime already enforces every requiredTests case lands in\r\n // exactly one of a target's automationIds or here, never both, never neither. Folded into\r\n // the same warnings array the overlap-check below already populates and reportBack sends.\r\n if (targeting.skippedCases?.length) {\r\n for (const skipped of targeting.skippedCases) {\r\n const w = `Test case ${skipped.automationId} has no given/when/then \u2014 skipped, no test was written for it.`;\r\n warnings.push(w);\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n }\r\n }\r\n // QUIKTR-1064 \u2014 cheap: two targets whose planStepsImplemented describe the same rule (the\r\n // real fix is pilot.targeting's prompt, an AI Runtime change, not this package's \u2014 see\r\n // overlapCheck.ts). QUIKTR-1081 \u2014 a literal identical instruction now blocks outright: two\r\n // legitimate halves of one change never share the exact same instruction, and PR #23 merged\r\n // 28 seconds after opening on exactly this signal. A near-identical, reworded pair stays a\r\n // non-blocking warning, logged and reported back, same as before.\r\n const overlaps = findOverlappingSteps(targeting.targets);\r\n const blockingOverlaps = overlaps.filter((o) => o.severity === \"identical\");\r\n const softOverlaps = overlaps.filter((o) => o.severity === \"similar\");\r\n if (softOverlaps.length > 0) {\r\n const overlapWarnings = describeOverlapWarnings(softOverlaps);\r\n warnings.push(...overlapWarnings);\r\n for (const w of overlapWarnings) {\r\n console.warn(`QuikPilot targeting warning (not blocking): ${w}`);\r\n }\r\n }\r\n if (blockingOverlaps.length > 0) {\r\n throw new Error(\r\n `QuikPilot's generated plan gives two files identical instructions \u2014 ${describeOverlapWarnings(blockingOverlaps).join(\"; \")}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1036 \u2014 Setup moves here (was after codegen/flush): the baseline test needs\r\n // dependencies installed, but has to run against the PRE-codegen tree. Installing\r\n // dependencies doesn't depend on which application source files exist, so this is safe, and\r\n // running Setup a second time later would undercut \"the baseline costs almost no wall-clock.\"\r\n runCommand(packet.commands.setup, \"Setup\");\r\n\r\n // \u00A718 \u2014 built once, from every case claimed by any target in the run, minus the\r\n // NO_BEHAVIOUR skips above. Sent only to code targets (codegen.ts's own else-branch);\r\n // targeting.skippedCases is the same list already folded into warnings just above.\r\n const judgedByPool = buildJudgedByPool(\r\n packet.requiredTests,\r\n targeting.targets,\r\n targeting.skippedCases ?? [],\r\n );\r\n\r\n // Baseline runs concurrently with codegen's network-bound calls \u2014 codegen writes nothing\r\n // until flushCodegenResults, so there's nothing for the baseline to race against.\r\n const [baseline, results] = await Promise.all([\r\n captureBaselineSnapshot(packet.commands.test),\r\n runCodegen(\r\n packet.gateway,\r\n targeting.targets,\r\n workspaceListing,\r\n packet.requiredTests,\r\n packet.guardrails.deniedPaths,\r\n judgedByPool,\r\n warnings,\r\n contextLog,\r\n outOfScope,\r\n ),\r\n ]);\r\n\r\n generatedResults = results;\r\n\r\n // QUIKTR-1045 \u2014 checked on the in-memory results, BEFORE anything is\r\n // written: an invented import is never written to disk at all, matching\r\n // the same all-or-nothing treatment every other codegen failure already\r\n // gets here. Hard failure \u2014 a generation that imports a package this\r\n // repository doesn't have can't be trusted.\r\n const depCheck = checkImportDependencies(\r\n results,\r\n readDeclaredDependencies(results, packet.workspaceRoot),\r\n resolveAliasPrefixes(results, packet.workspaceRoot),\r\n );\r\n if (depCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code imports packages this repository doesn't have \u2014 ${describeDependencyViolations(depCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1081 \u2014 QUIKSPL-5's PR #22: codegen added an undeclared PUT endpoint alongside the\r\n // fix nobody asked for. Checked here for the same reason as the dependency check above \u2014\r\n // in-memory, before anything is written \u2014 against the design's own declared apiChanges.\r\n const scopeCheck = checkApiScope(results, targeting.targets, packet.design?.apiChanges ?? []);\r\n if (scopeCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code exceeds the approved design \u2014 ${describeScopeViolations(scopeCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1315 \u2014 same \"in-memory results, before anything is written\" point as the two checks\r\n // above: a test case claimed against a source-file target instead of the real test file has\r\n // zero coverage even though its id is present, and nothing else here catches that. Uses the\r\n // BASELINE run's JUnit report (already captured above) as the ground truth for which files\r\n // the test runner actually discovers \u2014 never the workspace listing, which includes files the\r\n // runner never looks at.\r\n const placementCheck = checkTestPlacement(targeting.targets, baseline.discoveredFiles);\r\n if (placementCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated tests are not where the test runner will find them \u2014 ${describeTestPlacementViolations(placementCheck)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1402 \u2014 run the generated tests alone on the still-untouched tree and flag a non-Regression\r\n // case that already passes there. After the in-memory checks above (no point spending the time on a\r\n // run that is about to fail) and before the flush (the code files are still the originals). Flag-only:\r\n // it never throws out of here, and a surprise from it must not cost the run.\r\n try {\r\n const baselineCheck = await runBaselineCheck({\r\n targets: targeting.targets,\r\n results,\r\n testFileCmd: packet.commands.testFile,\r\n requiredTestTypes: packet.requiredTestTypes,\r\n });\r\n warnings.push(...baselineCheck.warnings);\r\n baselineFindings = baselineCheck.findings ?? undefined;\r\n } catch (err) {\r\n const message = `Baseline check could not run: ${err instanceof Error ? err.message : String(err)}`;\r\n console.error(message);\r\n warnings.push(message);\r\n }\r\n\r\n // QUIKTR-1333 \u2014 the files QuikPilot actually generated or edited this run, exactly what\r\n // reportToQuikTest's generatedFiles param needs to scope the unmatched-id warning. runCodegen\r\n // is all-or-nothing, so by this point `results` is the complete, successful set \u2014 nothing\r\n // extra needed from targeting.targets.\r\n generatedFilePaths = results.map((r) => r.targetPath);\r\n\r\n flushCodegenResults(results);\r\n try {\r\n runCommand(packet.commands.format, \"Format\");\r\n } catch (err) {\r\n // QUIKTR-1045 \u2014 soft, like Test: see the file docblock.\r\n console.error(`Format failed (not blocking): ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n runCommand(packet.commands.lint, \"Lint\");\r\n\r\n const after = captureTestSnapshot(packet.commands.test);\r\n finalTestReport = readTestReportBytes();\r\n // QUIKTR-1448 \u2014 before the regression throw below, so a run that then fails still reports it. Warn-only.\r\n vanishedTests = findVanishedTests(baseline, after) ?? undefined;\r\n if (vanishedTests) {\r\n const w = describeVanishedTests(vanishedTests);\r\n warnings.push(w);\r\n console.warn(`QuikPilot test warning (not blocking): ${w}`);\r\n }\r\n const check = checkForRegressions(baseline, after);\r\n if (check.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated code introduced test failures \u2014 ${describeRegressions(check)}`,\r\n );\r\n }\r\n\r\n // QUIKTR-1315 \u2014 the stronger of the two placement checks: run against the REAL, post-codegen\r\n // JUnit report, so it catches inverted placement regardless of why it happened, including\r\n // whatever checkTestPlacement's baseline-only, loose file-matching missed above.\r\n const coverageCheck = checkAutomationIdCoverage(targeting.targets, after.discoveredAutomationIds);\r\n if (coverageCheck.blocked) {\r\n throw new Error(\r\n `QuikPilot's generated tests were not executed \u2014 ${describeAutomationCoverageViolations(coverageCheck)}`,\r\n );\r\n }\r\n }\r\n } catch (err) {\r\n hardFailure = true;\r\n recordFailure(err);\r\n }\r\n\r\n if (!runToken) {\r\n console.error(\"No run token \u2014 the OIDC exchange failed before QuikTrack could be reached.\");\r\n return { hardFailure: true };\r\n }\r\n\r\n const quikTestReport = await reportToQuikTest({\r\n resultsUrl: packet?.quikTest?.resultsUrl,\r\n runToken,\r\n githubServerUrl: env.githubServerUrl,\r\n githubRepository: env.githubRepository,\r\n githubRunId: env.githubRunId,\r\n generatedFiles: generatedFilePaths,\r\n });\r\n // QUIKTR-1374 \u2014 the ingest response already knows which generated automationIds matched no\r\n // test case; read it and surface it here instead of letting it disappear once reportToQuikTest\r\n // returns. Reuses the same warnings -> reportBack path QUIKTR-1064's overlap detection already\r\n // uses, which QuikTrack folds into the run's own event timeline \u2014 no new plumbing.\r\n const unmatchedWarning = quikTestReport ? describeUnmatchedAutomationIds(quikTestReport.unmatched) : null;\r\n if (unmatchedWarning) {\r\n warnings.push(unmatchedWarning);\r\n console.warn(`QuikPilot ingest warning (not blocking): ${unmatchedWarning}`);\r\n }\r\n\r\n if (!hardFailure && packet) {\r\n try {\r\n checkGuardrail(packet.guardrails.deniedPaths);\r\n const installationToken = await exchangeForInstallationToken(\r\n env.installationTokenUrl,\r\n runToken,\r\n );\r\n const result = commitAndPush(\r\n packet.branch,\r\n env.runId,\r\n installationToken,\r\n targeted,\r\n packet.issueKey,\r\n packet.issueTitle,\r\n );\r\n branch = result.branch;\r\n } catch (err) {\r\n hardFailure = true;\r\n recordFailure(err);\r\n }\r\n }\r\n\r\n // QUIKTR-1447 \u2014 before the callback, so it exists whether or not the callback succeeds. Only for a run that got as far\r\n // as generating files, and never allowed to change how the run ends.\r\n if (hardFailure && generatedResults.length > 0) {\r\n try {\r\n writeFailureArtifact({\r\n cwd: process.cwd(),\r\n runId: env.runId,\r\n issueKey: packet?.issueKey ?? null,\r\n targets: targetingResult?.outcome === \"TARGETED\" ? targetingResult.targets : [],\r\n results: generatedResults,\r\n testReport: finalTestReport,\r\n failureReasons,\r\n secrets: runToken ? [runToken] : [],\r\n });\r\n } catch (err: unknown) {\r\n console.warn(`::warning::Could not keep the failed run's files: ${err instanceof Error ? err.message : String(err)}`);\r\n }\r\n }\r\n\r\n await reportBack({\r\n callbackUrl: env.callbackUrl,\r\n runToken,\r\n status: hardFailure ? \"failed\" : \"completed\",\r\n branch,\r\n warnings,\r\n // Omitted when targeting itself never produced a result (nothing exists to record).\r\n targeting: targetingResult ? buildTargetingRecord(targetingResult, contextLog) : undefined,\r\n baselineFindings,\r\n vanishedTests,\r\n unresolved: failureReasons.length > 0 ? failureReasons : undefined,\r\n });\r\n\r\n return { hardFailure };\r\n}\r\n", "import type { ReadinessCheckEnv } from \"./env\";\r\nimport { runCommand, runTestCommand } from \"./commands\";\r\nimport { findJUnitReport } from \"./quiktest\";\r\nimport { describeQuikTrackFailure } from \"./quiktrackError\";\r\n\r\n/**\r\n * QUIKTR-1084 \u2014 readiness's \"later session\": actually run the customer's `setupCmd`/`testCmd` and\r\n * report whether the run produced a JUnit report the pilot-run path (`quiktest.ts`) will ever\r\n * find. Checked out onto the default branch already by the workflow's own `actions/checkout` step\r\n * \u2014 no packet, no design, no codegen, no commit, no push.\r\n *\r\n * Both command failures are soft here, deliberately unlike `run.ts`'s hard-fails-on-Setup: a\r\n * repo's setup or test suite failing is not what this check is FOR \u2014 it exists purely to answer\r\n * \"if a real run happened, would QuikTest hear about it,\" which only needs the report to exist,\r\n * not the tests to pass.\r\n */\r\nexport interface ReadinessCheckResult {\r\n setupOk: boolean;\r\n testOk: boolean;\r\n junitFound: boolean;\r\n junitPath: string | null;\r\n}\r\n\r\nexport async function runReadinessCheck(env: ReadinessCheckEnv): Promise<void> {\r\n let setupOk = true;\r\n try {\r\n runCommand(env.setupCmd || null, \"Setup\");\r\n } catch (err) {\r\n setupOk = false;\r\n console.error(err instanceof Error ? err.message : String(err));\r\n }\r\n\r\n const testOutcome = runTestCommand(env.testCmd);\r\n const testOk = testOutcome === \"success\";\r\n\r\n const junitPath = findJUnitReport();\r\n const result: ReadinessCheckResult = {\r\n setupOk,\r\n testOk,\r\n junitFound: junitPath !== null,\r\n junitPath,\r\n };\r\n\r\n try {\r\n const res = await fetch(env.readinessCallbackUrl, {\r\n method: \"POST\",\r\n headers: { Authorization: `Bearer ${env.readinessToken}`, \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify(result),\r\n });\r\n if (!res.ok) {\r\n throw new Error(`Readiness callback POST failed: ${await describeQuikTrackFailure(res)}`);\r\n }\r\n } catch (err) {\r\n // Same \"never throws\" posture as reportToQuikTest/reportBack \u2014 the job's own log is the\r\n // fallback record if even this fails. The expiry sweep readiness.ts will need (mirroring\r\n // dispatch.ts's DISPATCHING-expiry sweep) is what notices a dry run stuck in RUNNING.\r\n console.warn(\r\n `::warning::QuikPilot readiness check failed to report its result: ${err instanceof Error ? err.message : String(err)}`,\r\n );\r\n }\r\n}\r\n", "import { readRunnerEnv } from \"./env\";\r\nimport { run } from \"./run\";\r\nimport { runReadinessCheck } from \"./readinessCheck\";\r\n\r\nconst env = readRunnerEnv();\r\n\r\n// QUIKTR-1084 \u2014 narrows the RunnerEnv union before either branch runs; run()/runReadinessCheck()\r\n// each take only their own variant, not the union, so this `if` is what makes that safe.\r\nconst task =\r\n env.mode === \"readiness_check\"\r\n ? runReadinessCheck(env).then(() => ({ hardFailure: false }))\r\n : run(env);\r\n\r\ntask\r\n .then(({ hardFailure }) => {\r\n process.exitCode = hardFailure ? 1 : 0;\r\n })\r\n .catch((err) => {\r\n // reportBack/the readiness callback itself throwing is the one failure mode neither branch can\r\n // recover from internally \u2014 still exit non-zero so the raw Actions UI shows the run as failed.\r\n console.error(err instanceof Error ? err.message : String(err));\r\n process.exitCode = 1;\r\n });\r\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["env", "resolve", "import_node_child_process", "import_node_path", "relative", "path", "path", "import_node_fs", "import_node_path", "env", "import_node_fs", "import_node_fs", "import_node_path", "readFileSync", "import_node_child_process", "import_node_fs", "import_node_path", "import_node_fs", "isTestTarget", "import_node_fs", "import_node_path", "import_node_fs", "import_node_path", "env", "import_node_path", "import_node_fs", "import_node_path", "env", "isPlainObject", "env", "CONTRACT_VERSION", "MAX_PATH_CHARS", "MAX_ID_CHARS", "record", "env", "env"]
|
|
7
7
|
}
|