@whittlelabs/sifter 0.34.0 → 0.36.0

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.
Files changed (3) hide show
  1. package/bin.js +759 -610
  2. package/bin.js.map +4 -4
  3. package/package.json +1 -1
package/bin.js CHANGED
@@ -9961,6 +9961,8 @@ var require_progress = __commonJS({
9961
9961
  seq = 0;
9962
9962
  pending = [];
9963
9963
  textBuf = "";
9964
+ /** The last two characters of reasoning emitted since the last tool; null when none. */
9965
+ reasoningTail = null;
9964
9966
  timer = null;
9965
9967
  closed = false;
9966
9968
  flushMs;
@@ -9970,20 +9972,39 @@ var require_progress = __commonJS({
9970
9972
  this.flushMs = options.flushMs ?? 400;
9971
9973
  this.maxChars = options.maxChars ?? 1200;
9972
9974
  }
9975
+ /** A fragment of reasoning, continuing whatever came before it. */
9973
9976
  reasoning(text) {
9974
9977
  if (this.closed || !text)
9975
9978
  return;
9976
9979
  this.textBuf += text;
9980
+ this.reasoningTail = ((this.reasoningTail ?? "") + text).slice(-2);
9977
9981
  if (this.textBuf.length >= this.maxChars) {
9978
9982
  this.flush();
9979
9983
  } else {
9980
9984
  this.arm();
9981
9985
  }
9982
9986
  }
9987
+ /**
9988
+ * A whole block of reasoning (a thinking summary, a message between tool
9989
+ * calls), trimmed and set off from the reasoning before it by one blank
9990
+ * line. A consumer flows consecutive reasoning frames into one passage, so
9991
+ * two blocks reported as fragments run together mid-sentence, and a
9992
+ * block's own trailing blank lines (thinking summaries end in them) would
9993
+ * show as empty lines before the next act.
9994
+ */
9995
+ reasoningBlock(text) {
9996
+ const block = text.trim();
9997
+ if (this.closed || !block)
9998
+ return;
9999
+ const tail = this.reasoningTail;
10000
+ const gap = tail === null || tail.endsWith("\n\n") ? "" : tail.endsWith("\n") ? "\n" : "\n\n";
10001
+ this.reasoning(gap + block);
10002
+ }
9983
10003
  tool(name, target) {
9984
10004
  if (this.closed || !name)
9985
10005
  return;
9986
10006
  this.drainText();
10007
+ this.reasoningTail = null;
9987
10008
  this.push({ kind: "tool", tool: target ? { name, target } : { name } });
9988
10009
  this.flush();
9989
10010
  }
@@ -10611,6 +10632,87 @@ var require_workspace_telemetry = __commonJS({
10611
10632
  }
10612
10633
  });
10613
10634
 
10635
+ // ../../packages/shuttle/dist/executors/cli-version.js
10636
+ var require_cli_version = __commonJS({
10637
+ "../../packages/shuttle/dist/executors/cli-version.js"(exports2) {
10638
+ "use strict";
10639
+ Object.defineProperty(exports2, "__esModule", { value: true });
10640
+ exports2.cliVersion = cliVersion;
10641
+ var child_process_1 = require("child_process");
10642
+ var VERSION_TIMEOUT_MS = 5e3;
10643
+ function cliVersion(bin, env) {
10644
+ return new Promise((resolve) => {
10645
+ try {
10646
+ (0, child_process_1.execFile)(bin, ["--version"], { timeout: VERSION_TIMEOUT_MS, ...env ? { env } : {} }, (err, stdout) => {
10647
+ resolve(err ? null : String(stdout).match(/\d+\.\d+\.\d+/)?.[0] ?? null);
10648
+ });
10649
+ } catch {
10650
+ resolve(null);
10651
+ }
10652
+ });
10653
+ }
10654
+ }
10655
+ });
10656
+
10657
+ // ../../packages/shuttle/dist/version-check.js
10658
+ var require_version_check = __commonJS({
10659
+ "../../packages/shuttle/dist/version-check.js"(exports2) {
10660
+ "use strict";
10661
+ Object.defineProperty(exports2, "__esModule", { value: true });
10662
+ exports2.UpgradeRequiredError = exports2.LATEST_VERSION_HEADER = exports2.MIN_VERSION_HEADER = void 0;
10663
+ exports2.compareSemver = compareSemver;
10664
+ exports2.checkResponseMinVersion = checkResponseMinVersion;
10665
+ exports2.readResponseLatestVersion = readResponseLatestVersion;
10666
+ exports2.MIN_VERSION_HEADER = "x-sifter-min-version";
10667
+ exports2.LATEST_VERSION_HEADER = "x-sifter-latest-version";
10668
+ var UpgradeRequiredError2 = class extends Error {
10669
+ currentVersion;
10670
+ minVersion;
10671
+ packageName;
10672
+ constructor(opts) {
10673
+ super(`The backend requires ${opts.packageName} ${opts.minVersion} or newer. You're running ${opts.currentVersion}. Upgrade: npm install -g ${opts.packageName}@latest`);
10674
+ this.name = "UpgradeRequiredError";
10675
+ this.currentVersion = opts.currentVersion;
10676
+ this.minVersion = opts.minVersion;
10677
+ this.packageName = opts.packageName;
10678
+ }
10679
+ };
10680
+ exports2.UpgradeRequiredError = UpgradeRequiredError2;
10681
+ function compareSemver(a, b) {
10682
+ const parse = (v) => {
10683
+ const core = v.replace(/^v/, "").split(/[-+]/, 1)[0];
10684
+ const parts = core.split(".").map((p) => Number.parseInt(p, 10));
10685
+ return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
10686
+ };
10687
+ const [aMaj, aMin, aPat] = parse(a);
10688
+ const [bMaj, bMin, bPat] = parse(b);
10689
+ if (aMaj !== bMaj)
10690
+ return aMaj < bMaj ? -1 : 1;
10691
+ if (aMin !== bMin)
10692
+ return aMin < bMin ? -1 : 1;
10693
+ if (aPat !== bPat)
10694
+ return aPat < bPat ? -1 : 1;
10695
+ return 0;
10696
+ }
10697
+ function checkResponseMinVersion(opts) {
10698
+ const minVersion = opts.response.headers.get(exports2.MIN_VERSION_HEADER);
10699
+ if (!minVersion)
10700
+ return;
10701
+ if (compareSemver(opts.currentVersion, minVersion) >= 0)
10702
+ return;
10703
+ throw new UpgradeRequiredError2({
10704
+ currentVersion: opts.currentVersion,
10705
+ minVersion,
10706
+ packageName: opts.packageName
10707
+ });
10708
+ }
10709
+ function readResponseLatestVersion(response) {
10710
+ const latest = response.headers.get(exports2.LATEST_VERSION_HEADER);
10711
+ return latest && latest.trim().length > 0 ? latest.trim() : null;
10712
+ }
10713
+ }
10714
+ });
10715
+
10614
10716
  // ../../packages/shuttle/dist/executors/claude-code.js
10615
10717
  var require_claude_code = __commonJS({
10616
10718
  "../../packages/shuttle/dist/executors/claude-code.js"(exports2) {
@@ -10634,9 +10736,12 @@ var require_claude_code = __commonJS({
10634
10736
  var json_answer_1 = require_json_answer();
10635
10737
  var models_1 = require_models();
10636
10738
  var workspace_telemetry_1 = require_workspace_telemetry();
10739
+ var cli_version_1 = require_cli_version();
10637
10740
  var apply_1 = require_apply();
10741
+ var version_check_1 = require_version_check();
10638
10742
  var DEFAULT_TIMEOUT = 6e5;
10639
10743
  var REVIEW_TOOLS = ["Read", "Grep", "Glob"];
10744
+ var THINKING_DISPLAY_FLOOR = "2.1.94";
10640
10745
  function reviewRunArgs(settingSources) {
10641
10746
  return [
10642
10747
  "--setting-sources",
@@ -10891,13 +10996,17 @@ var require_claude_code = __commonJS({
10891
10996
  args.push("--model", model);
10892
10997
  if (effort)
10893
10998
  args.push("--effort", effort);
10999
+ const version = await (0, cli_version_1.cliVersion)("claude", childEnv);
11000
+ if (version !== null && (0, version_check_1.compareSemver)(version, THINKING_DISPLAY_FLOOR) >= 0) {
11001
+ args.push("--thinking-display", "summarized");
11002
+ }
10894
11003
  if (this.config.maxTurns !== void 0)
10895
11004
  args.push("--max-turns", String(this.config.maxTurns));
10896
11005
  if (allowedTools && allowedTools.length > 0) {
10897
11006
  args.push("--allowedTools", allowedTools.join(","));
10898
11007
  }
10899
11008
  const tap = reporter ? new progress_1.StreamJsonTap({
10900
- onReasoning: (t) => reporter.reasoning(t),
11009
+ onReasoning: (t) => reporter.reasoningBlock(t),
10901
11010
  onTool: (name, target) => reporter.tool(name, target),
10902
11011
  onResult: () => reporter.flush()
10903
11012
  }) : null;
@@ -11072,6 +11181,7 @@ var require_claude_code = __commonJS({
11072
11181
  let finalText = null;
11073
11182
  const readPaths = [];
11074
11183
  let usage = null;
11184
+ const toolCalls = {};
11075
11185
  let resultMeta = null;
11076
11186
  let structuredOutput = null;
11077
11187
  let sessionId = null;
@@ -11099,6 +11209,8 @@ var require_claude_code = __commonJS({
11099
11209
  const b = block;
11100
11210
  if (b?.type !== "tool_use")
11101
11211
  continue;
11212
+ if (typeof b.name === "string")
11213
+ toolCalls[b.name] = (toolCalls[b.name] ?? 0) + 1;
11102
11214
  const fp = b.input?.file_path;
11103
11215
  if (b.name === "Read" && typeof fp === "string") {
11104
11216
  readPaths.push(fp);
@@ -11125,13 +11237,19 @@ var require_claude_code = __commonJS({
11125
11237
  }
11126
11238
  const u = event.usage;
11127
11239
  const cost = event.total_cost_usd;
11240
+ const turns = event.num_turns;
11128
11241
  usage = {
11129
11242
  ...typeof u?.input_tokens === "number" ? { inputTokens: u.input_tokens } : {},
11130
11243
  ...typeof u?.output_tokens === "number" ? { outputTokens: u.output_tokens } : {},
11131
- ...typeof cost === "number" ? { costUsd: cost } : {}
11244
+ ...typeof u?.cache_read_input_tokens === "number" ? { cacheReadInputTokens: u.cache_read_input_tokens } : {},
11245
+ ...typeof u?.cache_creation_input_tokens === "number" ? { cacheCreationInputTokens: u.cache_creation_input_tokens } : {},
11246
+ ...typeof cost === "number" ? { costUsd: cost } : {},
11247
+ ...typeof turns === "number" ? { turns } : {}
11132
11248
  };
11133
11249
  }
11134
11250
  }
11251
+ if (usage && Object.keys(toolCalls).length > 0)
11252
+ usage.toolCalls = toolCalls;
11135
11253
  return { finalText, readPaths, usage, resultMeta, structuredOutput, sessionId, model, toolInputs };
11136
11254
  }
11137
11255
  }
@@ -11386,6 +11504,11 @@ var require_codex = __commonJS({
11386
11504
  'approval_policy="never"',
11387
11505
  "-c",
11388
11506
  'web_search="disabled"',
11507
+ // Reasoning summaries are the live view's narration. With the user config
11508
+ // ignored, codex 0.162.1 emits no reasoning items at all; `detailed`
11509
+ // brings them back without touching the answer.
11510
+ "-c",
11511
+ 'model_reasoning_summary="detailed"',
11389
11512
  ...DISABLED_FEATURES.flatMap((f) => ["--disable", f])
11390
11513
  ];
11391
11514
  }
@@ -11640,12 +11763,17 @@ var require_codex = __commonJS({
11640
11763
  if (event.type === "item.started" && kind === "command_execution" && typeof item?.command === "string") {
11641
11764
  reporter.tool("shell", item.command);
11642
11765
  } else if (event.type === "item.completed" && kind === "reasoning" && typeof item?.text === "string") {
11643
- reporter.reasoning(item.text);
11766
+ reporter.reasoningBlock(plainHeadings(item.text));
11767
+ } else if (event.type === "item.completed" && kind === "agent_message" && typeof item?.text === "string" && (0, json_answer_1.extractJsonObject)(item.text) === void 0) {
11768
+ reporter.reasoningBlock(item.text);
11644
11769
  } else if (event.type === "turn.completed") {
11645
11770
  reporter.flush();
11646
11771
  }
11647
11772
  });
11648
11773
  }
11774
+ function plainHeadings(text) {
11775
+ return text.replace(/^\*\*([^*\n]+)\*\*[ \t]*$/gm, "$1");
11776
+ }
11649
11777
  function itemKind(item) {
11650
11778
  const kind = typeof item.type === "string" ? item.type : typeof item.item_type === "string" ? item.item_type : null;
11651
11779
  return kind === "assistant_message" ? "agent_message" : kind;
@@ -12173,7 +12301,7 @@ ${JSON.stringify(spec.outputSchema)}
12173
12301
  const target = [args.path, args.pattern].find((v) => typeof v === "string");
12174
12302
  reporter.tool(data.toolName, target);
12175
12303
  } else if (event.type === "assistant.reasoning" && typeof data.content === "string") {
12176
- reporter.reasoning(data.content);
12304
+ reporter.reasoningBlock(data.content);
12177
12305
  } else if (event.type === "assistant.turn_end") {
12178
12306
  reporter.flush();
12179
12307
  }
@@ -13721,65 +13849,6 @@ var require_custom_script = __commonJS({
13721
13849
  }
13722
13850
  });
13723
13851
 
13724
- // ../../packages/shuttle/dist/version-check.js
13725
- var require_version_check = __commonJS({
13726
- "../../packages/shuttle/dist/version-check.js"(exports2) {
13727
- "use strict";
13728
- Object.defineProperty(exports2, "__esModule", { value: true });
13729
- exports2.UpgradeRequiredError = exports2.LATEST_VERSION_HEADER = exports2.MIN_VERSION_HEADER = void 0;
13730
- exports2.compareSemver = compareSemver;
13731
- exports2.checkResponseMinVersion = checkResponseMinVersion;
13732
- exports2.readResponseLatestVersion = readResponseLatestVersion;
13733
- exports2.MIN_VERSION_HEADER = "x-sifter-min-version";
13734
- exports2.LATEST_VERSION_HEADER = "x-sifter-latest-version";
13735
- var UpgradeRequiredError2 = class extends Error {
13736
- currentVersion;
13737
- minVersion;
13738
- packageName;
13739
- constructor(opts) {
13740
- super(`The backend requires ${opts.packageName} ${opts.minVersion} or newer. You're running ${opts.currentVersion}. Upgrade: npm install -g ${opts.packageName}@latest`);
13741
- this.name = "UpgradeRequiredError";
13742
- this.currentVersion = opts.currentVersion;
13743
- this.minVersion = opts.minVersion;
13744
- this.packageName = opts.packageName;
13745
- }
13746
- };
13747
- exports2.UpgradeRequiredError = UpgradeRequiredError2;
13748
- function compareSemver(a, b) {
13749
- const parse = (v) => {
13750
- const core = v.replace(/^v/, "").split(/[-+]/, 1)[0];
13751
- const parts = core.split(".").map((p) => Number.parseInt(p, 10));
13752
- return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
13753
- };
13754
- const [aMaj, aMin, aPat] = parse(a);
13755
- const [bMaj, bMin, bPat] = parse(b);
13756
- if (aMaj !== bMaj)
13757
- return aMaj < bMaj ? -1 : 1;
13758
- if (aMin !== bMin)
13759
- return aMin < bMin ? -1 : 1;
13760
- if (aPat !== bPat)
13761
- return aPat < bPat ? -1 : 1;
13762
- return 0;
13763
- }
13764
- function checkResponseMinVersion(opts) {
13765
- const minVersion = opts.response.headers.get(exports2.MIN_VERSION_HEADER);
13766
- if (!minVersion)
13767
- return;
13768
- if (compareSemver(opts.currentVersion, minVersion) >= 0)
13769
- return;
13770
- throw new UpgradeRequiredError2({
13771
- currentVersion: opts.currentVersion,
13772
- minVersion,
13773
- packageName: opts.packageName
13774
- });
13775
- }
13776
- function readResponseLatestVersion(response) {
13777
- const latest = response.headers.get(exports2.LATEST_VERSION_HEADER);
13778
- return latest && latest.trim().length > 0 ? latest.trim() : null;
13779
- }
13780
- }
13781
- });
13782
-
13783
13852
  // ../../packages/shuttle/dist/branding/environment.js
13784
13853
  var require_environment = __commonJS({
13785
13854
  "../../packages/shuttle/dist/branding/environment.js"(exports2) {
@@ -26124,75 +26193,326 @@ var require_chain = __commonJS({
26124
26193
  }
26125
26194
  });
26126
26195
 
26127
- // ../../packages/shuttle/dist/workspace/git.js
26128
- var require_git = __commonJS({
26129
- "../../packages/shuttle/dist/workspace/git.js"(exports2) {
26196
+ // ../../packages/shuttle/dist/executors/output-gates.js
26197
+ var require_output_gates = __commonJS({
26198
+ "../../packages/shuttle/dist/executors/output-gates.js"(exports2) {
26130
26199
  "use strict";
26131
- var __importDefault = exports2 && exports2.__importDefault || function(mod) {
26132
- return mod && mod.__esModule ? mod : { "default": mod };
26133
- };
26134
26200
  Object.defineProperty(exports2, "__esModule", { value: true });
26135
- exports2.gitMaterializer = void 0;
26136
- exports2.buildGitAuthEnv = buildGitAuthEnv;
26137
- var child_process_1 = require("child_process");
26138
- var fs_1 = require("fs");
26139
- var path_1 = __importDefault(require("path"));
26140
- var DEFAULT_GIT_TIMEOUT_MS = 12e4;
26141
- var DEFAULT_GIT_PROTOCOLS = "https:ssh:git";
26142
- var DEFAULT_MAX_CONTEXT_REPOS = 5;
26143
- exports2.gitMaterializer = {
26144
- namespace: "git",
26145
- materialize: materializeGit
26146
- };
26147
- async function materializeGit(request, runRoot, options) {
26148
- const resolvedPrimary = readGitWorkspace(request);
26149
- const primaryDir = path_1.default.join(runRoot, "primary");
26150
- await fs_1.promises.mkdir(primaryDir, { recursive: true });
26151
- if ("warning" in resolvedPrimary) {
26152
- return { materialized: false, warning: resolvedPrimary.warning, context: [] };
26153
- }
26154
- const primary = resolvedPrimary.git;
26155
- const timeoutMs = options.commandTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
26156
- const allowedProtocols = options.allowedProtocols ?? DEFAULT_GIT_PROTOCOLS;
26157
- const signal = options.signal;
26158
- const maxContext = options.maxContextRepos ?? DEFAULT_MAX_CONTEXT_REPOS;
26159
- const contextPlan = planContextRepos(primary.context, maxContext);
26160
- const ref = primary.fetchCredential;
26161
- let gitToken = null;
26162
- if (ref && typeof ref.name === "string" && typeof ref.principal === "string" && options.credentials) {
26163
- try {
26164
- gitToken = await options.credentials.reveal(ref);
26165
- } catch {
26166
- gitToken = null;
26167
- }
26168
- }
26169
- const authEnv = gitToken !== null ? buildGitAuthEnv([primary.remote, ...contextPlan.materialize.map((c) => c.git.remote)], gitToken) : void 0;
26170
- const git = (args, cwd) => runGit(args, cwd, { timeoutMs, signal, allowedProtocols, extraEnv: authEnv });
26171
- const primaryResult = await materializeCommit(primary, primaryDir, git);
26172
- if (!primaryResult.ok) {
26173
- await fs_1.promises.rm(primaryDir, { recursive: true, force: true }).catch(() => {
26174
- });
26175
- await fs_1.promises.mkdir(primaryDir).catch(() => {
26176
- });
26177
- return { materialized: false, warning: primaryResult.warning, context: [] };
26201
+ exports2.isSanctionedPaint = isSanctionedPaint;
26202
+ exports2.unsanctionedPaints = unsanctionedPaints;
26203
+ exports2.resolvePath = resolvePath;
26204
+ exports2.evaluateOutputGates = evaluateOutputGates;
26205
+ exports2.renderRepairPrompt = renderRepairPrompt;
26206
+ var INPUT_REF = "input:";
26207
+ var COLOR_BEARING = ["fill", "stroke", "color", "stop-color", "flood-color", "lighting-color"];
26208
+ var INERT = /* @__PURE__ */ new Set(["none", "inherit", "initial", "unset", "transparent", "currentcolor"]);
26209
+ function isSanctionedPaint(raw) {
26210
+ const value = raw.trim().toLowerCase();
26211
+ if (value === "")
26212
+ return true;
26213
+ if (INERT.has(value))
26214
+ return true;
26215
+ if (/^url\(\s*['"]?#[^)'"]+['"]?\s*\)$/.test(value))
26216
+ return true;
26217
+ const varMatch = /^var\(\s*(--[a-z0-9-]+)\s*(?:,([\s\S]*))?\)$/.exec(value);
26218
+ if (!varMatch)
26219
+ return false;
26220
+ const [, name, fallback] = varMatch;
26221
+ if (!name.startsWith("--color-"))
26222
+ return false;
26223
+ return fallback === void 0 || isSanctionedPaint(fallback);
26224
+ }
26225
+ function unsanctionedPaints(source) {
26226
+ const found = [];
26227
+ const attrs = COLOR_BEARING.join("|");
26228
+ const attribute = new RegExp(`\\b(?:${attrs})\\s*=\\s*(['"])([\\s\\S]*?)\\1`, "gi");
26229
+ const declaration = new RegExp(`\\b(?:${attrs})\\s*:\\s*([^;"'}\\n]+)`, "gi");
26230
+ for (const [, , value] of source.matchAll(attribute)) {
26231
+ if (!isSanctionedPaint(value))
26232
+ found.push(value.trim());
26178
26233
  }
26179
- const context = [];
26180
- for (const planned of contextPlan.skip) {
26181
- context.push({ ...planned, materialized: false });
26234
+ for (const [, value] of source.matchAll(declaration)) {
26235
+ if (!isSanctionedPaint(value))
26236
+ found.push(value.trim());
26182
26237
  }
26183
- if (contextPlan.materialize.length > 0) {
26184
- const contextRoot = path_1.default.join(runRoot, "context");
26185
- await fs_1.promises.mkdir(contextRoot, { recursive: true });
26186
- for (const entry of contextPlan.materialize) {
26187
- const dir = path_1.default.join(contextRoot, entry.name);
26188
- await fs_1.promises.mkdir(dir);
26189
- const result = await materializeCommit(entry.git, dir, git);
26190
- context.push({
26191
- name: entry.name,
26192
- requestedName: entry.requestedName,
26193
- materialized: result.ok,
26194
- ...result.ok ? {} : { warning: result.warning }
26195
- });
26238
+ return found;
26239
+ }
26240
+ function resolvePath(root, path) {
26241
+ let ctx = root;
26242
+ for (const seg of path.split(".")) {
26243
+ const project = seg.endsWith("[*]");
26244
+ const key = project ? seg.slice(0, -3) : seg;
26245
+ if (Array.isArray(ctx)) {
26246
+ ctx = ctx.map((el) => key ? el?.[key] : el);
26247
+ } else {
26248
+ ctx = key ? ctx?.[key] : ctx;
26249
+ }
26250
+ if (project && !Array.isArray(ctx)) {
26251
+ ctx = ctx == null ? [] : [ctx];
26252
+ }
26253
+ }
26254
+ return ctx;
26255
+ }
26256
+ function resolveRef(ref, output, inputs) {
26257
+ if (ref.startsWith(INPUT_REF)) {
26258
+ const label = ref.slice(INPUT_REF.length);
26259
+ const row = inputs.find((i) => i.label === label) ?? inputs.find((i) => i.label === "artifacts" && i.payload.label === label);
26260
+ if (!row)
26261
+ return void 0;
26262
+ return Object.prototype.hasOwnProperty.call(row.payload, "value") ? row.payload.value : row.payload;
26263
+ }
26264
+ return resolvePath(output, ref);
26265
+ }
26266
+ function asStrings(value) {
26267
+ if (Array.isArray(value))
26268
+ return value.map((v) => String(v));
26269
+ if (value == null)
26270
+ return [];
26271
+ return [String(value)];
26272
+ }
26273
+ var PRIMITIVES = {
26274
+ /**
26275
+ * `coverage` — the values at `got` must exactly cover the set at `want`:
26276
+ * every wanted value present, nothing invented, none repeated. Params:
26277
+ * `{ got: <output path>, want: <ref>, subject?: <noun> }`.
26278
+ */
26279
+ coverage(params, output, inputs) {
26280
+ const subject = typeof params.subject === "string" ? params.subject : "item";
26281
+ const got = asStrings(resolveRef(String(params.got), output, inputs));
26282
+ const want = asStrings(resolveRef(String(params.want), output, inputs));
26283
+ const gotSet = new Set(got);
26284
+ const wantSet = new Set(want);
26285
+ const missing = want.filter((v) => !gotSet.has(v));
26286
+ const unknown = [...new Set(got.filter((v) => !wantSet.has(v)))];
26287
+ const seen = /* @__PURE__ */ new Set();
26288
+ const duplicated = [];
26289
+ for (const v of got) {
26290
+ if (seen.has(v))
26291
+ duplicated.push(v);
26292
+ else
26293
+ seen.add(v);
26294
+ }
26295
+ if (missing.length === 0 && unknown.length === 0 && duplicated.length === 0)
26296
+ return [];
26297
+ const parts = [];
26298
+ if (missing.length)
26299
+ parts.push(`missing ${subject}(s): [${missing.join(", ")}]`);
26300
+ if (unknown.length)
26301
+ parts.push(`not a known ${subject}: [${unknown.join(", ")}]`);
26302
+ if (duplicated.length)
26303
+ parts.push(`assessed more than once: [${[...new Set(duplicated)].join(", ")}]`);
26304
+ return [
26305
+ `every ${subject} must be covered exactly once \u2014 ${parts.join("; ")}. Return one entry per ${subject}, using its exact id.`
26306
+ ];
26307
+ },
26308
+ /**
26309
+ * `non_empty_when` — the array at `path` must be non-empty, optionally only
26310
+ * when `when.path` equals `when.equals`. Params:
26311
+ * `{ path: <output path>, when?: { path: <output path>, equals: <value> } }`.
26312
+ */
26313
+ non_empty_when(params, output) {
26314
+ const when = params.when;
26315
+ if (when && typeof when.path === "string") {
26316
+ if (resolvePath(output, when.path) !== when.equals)
26317
+ return [];
26318
+ }
26319
+ const path = String(params.path);
26320
+ const value = resolvePath(output, path);
26321
+ if (Array.isArray(value) && value.length > 0)
26322
+ return [];
26323
+ const cond = when && typeof when.path === "string" ? ` when ${when.path} is ${JSON.stringify(when.equals)}` : "";
26324
+ return [
26325
+ `'${path}' must be a non-empty array${cond}; it was ${Array.isArray(value) ? "empty" : "absent"}.`
26326
+ ];
26327
+ },
26328
+ /**
26329
+ * `bounded_palette` — every colour in the sources at `path` must be named
26330
+ * by role rather than written as a value. Params:
26331
+ * `{ path: <output path>, roles?: <role names for the repair turn> }`.
26332
+ *
26333
+ * A drawing the model authors is markup the house did not write, and a
26334
+ * literal in it is a colour outside the consuming palette: unproved
26335
+ * against the colours beside it, unchecked for contrast on the ground it
26336
+ * lands on, and fixed to one theme. The consumer strips such a paint at
26337
+ * render, so an artifact that carries one silently loses it. Catching it
26338
+ * HERE is what makes that a repair the model can make while it still has
26339
+ * the drawing in hand, instead of a defect nobody sees until the picture
26340
+ * comes out plain.
26341
+ */
26342
+ bounded_palette(params, output) {
26343
+ const path = String(params.path);
26344
+ const value = resolvePath(output, path);
26345
+ const sources = (Array.isArray(value) ? value : [value]).filter((v) => typeof v === "string" && v.length > 0);
26346
+ const offenders = [...new Set(sources.flatMap(unsanctionedPaints))];
26347
+ if (offenders.length === 0)
26348
+ return [];
26349
+ const roles = Array.isArray(params.roles) ? params.roles.map(String) : [];
26350
+ const vocabulary = roles.length > 0 ? ` Use one of: ${roles.join(", ")}.` : "";
26351
+ return [
26352
+ `'${path}' states ${offenders.length} colour value${offenders.length === 1 ? "" : "s"} directly (${offenders.slice(0, 8).join(", ")}${offenders.length > 8 ? ", \u2026" : ""}). Every colour must be named by role \u2014 var(--color-\u2026), currentColor, or none \u2014 never as a hex, rgb(), hsl() or colour name, because a value cannot adapt to the reader's theme and was never checked against the colours beside it.${vocabulary} Redraw with roles and return the whole output again.`
26353
+ ];
26354
+ }
26355
+ };
26356
+ function evaluateOutputGates(gates, output, inputs) {
26357
+ const findings = [];
26358
+ for (const gate of gates) {
26359
+ const primitive = PRIMITIVES[gate.primitive];
26360
+ if (!primitive) {
26361
+ findings.push({ gate: gate.name, message: `unknown gate primitive '${gate.primitive}'` });
26362
+ continue;
26363
+ }
26364
+ for (const message of primitive(gate.params, output, inputs)) {
26365
+ findings.push({ gate: gate.name, message });
26366
+ }
26367
+ }
26368
+ return { ok: findings.length === 0, findings };
26369
+ }
26370
+ function renderRepairPrompt(findings) {
26371
+ return [
26372
+ "Your previous answer did not satisfy these output checks. Return the corrected, complete answer that resolves every item below. Produce the same output shape with the problems fixed, and nothing else \u2014 no commentary, no explanation of the changes.",
26373
+ "",
26374
+ ...findings.map((f) => `- [${f.gate}] ${f.message}`)
26375
+ ].join("\n");
26376
+ }
26377
+ }
26378
+ });
26379
+
26380
+ // ../../packages/shuttle/dist/logging/logger.js
26381
+ var require_logger = __commonJS({
26382
+ "../../packages/shuttle/dist/logging/logger.js"(exports2) {
26383
+ "use strict";
26384
+ Object.defineProperty(exports2, "__esModule", { value: true });
26385
+ exports2.createLogger = createLogger;
26386
+ exports2.setGlobalLogger = setGlobalLogger;
26387
+ exports2.getLogger = getLogger;
26388
+ var LEVEL_ORDER = {
26389
+ debug: 0,
26390
+ info: 1,
26391
+ warn: 2,
26392
+ error: 3
26393
+ };
26394
+ function formatContext(context) {
26395
+ return Object.entries(context).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
26396
+ }
26397
+ function formatPretty(level, message, context) {
26398
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
26399
+ const tag = level.toUpperCase().padEnd(5);
26400
+ const base = `[${timestamp}] ${tag} ${message}`;
26401
+ if (context && Object.keys(context).length > 0) {
26402
+ return `${base} ${formatContext(context)}`;
26403
+ }
26404
+ return base;
26405
+ }
26406
+ function formatJson(level, message, context) {
26407
+ const entry = {
26408
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26409
+ level,
26410
+ message,
26411
+ ...context
26412
+ };
26413
+ return JSON.stringify(entry);
26414
+ }
26415
+ function createLogger(options) {
26416
+ const threshold = LEVEL_ORDER[options.level];
26417
+ const format = options.format === "json" ? formatJson : formatPretty;
26418
+ function emit(level, message, context) {
26419
+ if (LEVEL_ORDER[level] < threshold)
26420
+ return;
26421
+ const line = format(level, message, context);
26422
+ if (level === "error") {
26423
+ console.error(line);
26424
+ } else if (level === "warn") {
26425
+ console.warn(line);
26426
+ } else {
26427
+ console.log(line);
26428
+ }
26429
+ }
26430
+ return {
26431
+ debug: (message, context) => emit("debug", message, context),
26432
+ info: (message, context) => emit("info", message, context),
26433
+ warn: (message, context) => emit("warn", message, context),
26434
+ error: (message, context) => emit("error", message, context)
26435
+ };
26436
+ }
26437
+ var globalLogger = createLogger({ level: "info", format: "pretty" });
26438
+ function setGlobalLogger(logger) {
26439
+ globalLogger = logger;
26440
+ }
26441
+ function getLogger() {
26442
+ return globalLogger;
26443
+ }
26444
+ }
26445
+ });
26446
+
26447
+ // ../../packages/shuttle/dist/workspace/git.js
26448
+ var require_git = __commonJS({
26449
+ "../../packages/shuttle/dist/workspace/git.js"(exports2) {
26450
+ "use strict";
26451
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
26452
+ return mod && mod.__esModule ? mod : { "default": mod };
26453
+ };
26454
+ Object.defineProperty(exports2, "__esModule", { value: true });
26455
+ exports2.gitMaterializer = void 0;
26456
+ exports2.buildGitAuthEnv = buildGitAuthEnv;
26457
+ var child_process_1 = require("child_process");
26458
+ var fs_1 = require("fs");
26459
+ var path_1 = __importDefault(require("path"));
26460
+ var DEFAULT_GIT_TIMEOUT_MS = 12e4;
26461
+ var DEFAULT_GIT_PROTOCOLS = "https:ssh:git";
26462
+ var DEFAULT_MAX_CONTEXT_REPOS = 5;
26463
+ exports2.gitMaterializer = {
26464
+ namespace: "git",
26465
+ materialize: materializeGit
26466
+ };
26467
+ async function materializeGit(request, runRoot, options) {
26468
+ const resolvedPrimary = readGitWorkspace(request);
26469
+ const primaryDir = path_1.default.join(runRoot, "primary");
26470
+ await fs_1.promises.mkdir(primaryDir, { recursive: true });
26471
+ if ("warning" in resolvedPrimary) {
26472
+ return { materialized: false, warning: resolvedPrimary.warning, context: [] };
26473
+ }
26474
+ const primary = resolvedPrimary.git;
26475
+ const timeoutMs = options.commandTimeoutMs ?? DEFAULT_GIT_TIMEOUT_MS;
26476
+ const allowedProtocols = options.allowedProtocols ?? DEFAULT_GIT_PROTOCOLS;
26477
+ const signal = options.signal;
26478
+ const maxContext = options.maxContextRepos ?? DEFAULT_MAX_CONTEXT_REPOS;
26479
+ const contextPlan = planContextRepos(primary.context, maxContext);
26480
+ const ref = primary.fetchCredential;
26481
+ let gitToken = null;
26482
+ if (ref && typeof ref.name === "string" && typeof ref.principal === "string" && options.credentials) {
26483
+ try {
26484
+ gitToken = await options.credentials.reveal(ref);
26485
+ } catch {
26486
+ gitToken = null;
26487
+ }
26488
+ }
26489
+ const authEnv = gitToken !== null ? buildGitAuthEnv([primary.remote, ...contextPlan.materialize.map((c) => c.git.remote)], gitToken) : void 0;
26490
+ const git = (args, cwd) => runGit(args, cwd, { timeoutMs, signal, allowedProtocols, extraEnv: authEnv });
26491
+ const primaryResult = await materializeCommit(primary, primaryDir, git);
26492
+ if (!primaryResult.ok) {
26493
+ await fs_1.promises.rm(primaryDir, { recursive: true, force: true }).catch(() => {
26494
+ });
26495
+ await fs_1.promises.mkdir(primaryDir).catch(() => {
26496
+ });
26497
+ return { materialized: false, warning: primaryResult.warning, context: [] };
26498
+ }
26499
+ const context = [];
26500
+ for (const planned of contextPlan.skip) {
26501
+ context.push({ ...planned, materialized: false });
26502
+ }
26503
+ if (contextPlan.materialize.length > 0) {
26504
+ const contextRoot = path_1.default.join(runRoot, "context");
26505
+ await fs_1.promises.mkdir(contextRoot, { recursive: true });
26506
+ for (const entry of contextPlan.materialize) {
26507
+ const dir = path_1.default.join(contextRoot, entry.name);
26508
+ await fs_1.promises.mkdir(dir);
26509
+ const result = await materializeCommit(entry.git, dir, git);
26510
+ context.push({
26511
+ name: entry.name,
26512
+ requestedName: entry.requestedName,
26513
+ materialized: result.ok,
26514
+ ...result.ok ? {} : { warning: result.warning }
26515
+ });
26196
26516
  }
26197
26517
  }
26198
26518
  context.sort((a, b) => contextOrder(contextPlan, a.requestedName) - contextOrder(contextPlan, b.requestedName));
@@ -26522,448 +26842,321 @@ var require_overlay = __commonJS({
26522
26842
  throw new Error("overlay file exceeds size cap");
26523
26843
  chunks.push(buf);
26524
26844
  }
26525
- return Buffer.concat(chunks);
26526
- } finally {
26527
- clearTimeout(timer);
26528
- opts.signal?.removeEventListener("abort", onParentAbort);
26529
- }
26530
- }
26531
- }
26532
- });
26533
-
26534
- // ../../packages/shuttle/dist/workspace/materialize.js
26535
- var require_materialize = __commonJS({
26536
- "../../packages/shuttle/dist/workspace/materialize.js"(exports2) {
26537
- "use strict";
26538
- var __importDefault = exports2 && exports2.__importDefault || function(mod) {
26539
- return mod && mod.__esModule ? mod : { "default": mod };
26540
- };
26541
- Object.defineProperty(exports2, "__esModule", { value: true });
26542
- exports2.registerMaterializer = registerMaterializer;
26543
- exports2.registerModifier = registerModifier;
26544
- exports2.materializeWorkspace = materializeWorkspace;
26545
- var fs_1 = require("fs");
26546
- var os_1 = __importDefault(require("os"));
26547
- var path_1 = __importDefault(require("path"));
26548
- var git_1 = require_git();
26549
- var overlay_1 = require_overlay();
26550
- var materializers = /* @__PURE__ */ new Map();
26551
- var modifiers = /* @__PURE__ */ new Map();
26552
- function registerMaterializer(provider) {
26553
- materializers.set(provider.namespace, provider);
26554
- }
26555
- function registerModifier(provider) {
26556
- modifiers.set(provider.namespace, provider);
26557
- }
26558
- registerMaterializer(git_1.gitMaterializer);
26559
- registerModifier(overlay_1.overlayModifier);
26560
- async function materializeWorkspace(bag, options = {}) {
26561
- const tmpBase = options.tmpDir ?? os_1.default.tmpdir();
26562
- const runRoot = await fs_1.promises.mkdtemp(path_1.default.join(tmpBase, "shuttle-ws-"));
26563
- const cleanup = async () => {
26564
- await fs_1.promises.rm(runRoot, { recursive: true, force: true }).catch(() => {
26565
- });
26566
- };
26567
- let materialized = false;
26568
- let primaryDir;
26569
- let warning;
26570
- let context = [];
26571
- let ranBase = false;
26572
- for (const [namespace, provider] of materializers) {
26573
- if (bag[namespace] !== void 0) {
26574
- const outcome = await provider.materialize(bag[namespace], runRoot, options);
26575
- materialized = outcome.materialized;
26576
- primaryDir = outcome.primaryDir;
26577
- warning = outcome.warning;
26578
- context = outcome.context;
26579
- ranBase = true;
26580
- break;
26581
- }
26582
- }
26583
- if (!ranBase) {
26584
- const offered = Object.keys(bag).join(", ") || "(none)";
26585
- await fs_1.promises.mkdir(path_1.default.join(runRoot, "primary"), { recursive: true }).catch(() => {
26586
- });
26587
- warning = `workspace carries no materializer this runner understands (offered: ${offered}; supported: ${[...materializers.keys()].join(", ")})`;
26588
- }
26589
- let overlay;
26590
- for (const [namespace, provider] of modifiers) {
26591
- if (bag[namespace] !== void 0) {
26592
- overlay = await provider.apply(bag[namespace], runRoot, options);
26593
- }
26594
- }
26595
- return { cwd: runRoot, materialized, primaryDir, warning, context, overlay, cleanup };
26596
- }
26597
- }
26598
- });
26599
-
26600
- // ../../packages/shuttle/dist/workspace/index.js
26601
- var require_workspace = __commonJS({
26602
- "../../packages/shuttle/dist/workspace/index.js"(exports2) {
26603
- "use strict";
26604
- Object.defineProperty(exports2, "__esModule", { value: true });
26605
- exports2.applyOverlay = exports2.overlayModifier = exports2.buildGitAuthEnv = exports2.gitMaterializer = exports2.registerModifier = exports2.registerMaterializer = exports2.materializeWorkspace = void 0;
26606
- var materialize_1 = require_materialize();
26607
- Object.defineProperty(exports2, "materializeWorkspace", { enumerable: true, get: function() {
26608
- return materialize_1.materializeWorkspace;
26609
- } });
26610
- Object.defineProperty(exports2, "registerMaterializer", { enumerable: true, get: function() {
26611
- return materialize_1.registerMaterializer;
26612
- } });
26613
- Object.defineProperty(exports2, "registerModifier", { enumerable: true, get: function() {
26614
- return materialize_1.registerModifier;
26615
- } });
26616
- var git_1 = require_git();
26617
- Object.defineProperty(exports2, "gitMaterializer", { enumerable: true, get: function() {
26618
- return git_1.gitMaterializer;
26619
- } });
26620
- Object.defineProperty(exports2, "buildGitAuthEnv", { enumerable: true, get: function() {
26621
- return git_1.buildGitAuthEnv;
26622
- } });
26623
- var overlay_1 = require_overlay();
26624
- Object.defineProperty(exports2, "overlayModifier", { enumerable: true, get: function() {
26625
- return overlay_1.overlayModifier;
26626
- } });
26627
- Object.defineProperty(exports2, "applyOverlay", { enumerable: true, get: function() {
26628
- return overlay_1.applyOverlay;
26629
- } });
26630
- }
26631
- });
26632
-
26633
- // ../../packages/shuttle/dist/credentials/registry.js
26634
- var require_registry2 = __commonJS({
26635
- "../../packages/shuttle/dist/credentials/registry.js"(exports2) {
26636
- "use strict";
26637
- Object.defineProperty(exports2, "__esModule", { value: true });
26638
- exports2.registerCredentialResolver = registerCredentialResolver;
26639
- exports2.getCredentialResolver = getCredentialResolver;
26640
- var resolvers = /* @__PURE__ */ new Map();
26641
- function registerCredentialResolver(name, resolver) {
26642
- resolvers.set(name, resolver);
26643
- }
26644
- function getCredentialResolver(name) {
26645
- return resolvers.get(name);
26646
- }
26647
- registerCredentialResolver("managed-model-key", async (keep, principal) => {
26648
- const reveal = await keep.revealManagedSifterKey(principal);
26649
- return reveal.apiKey;
26650
- });
26651
- registerCredentialResolver("github-user-token", async (keep, principal) => {
26652
- try {
26653
- const reveal = await keep.getUserGithubToken(principal);
26654
- return reveal.access_token;
26655
- } catch {
26656
- return null;
26657
- }
26658
- });
26659
- }
26660
- });
26661
-
26662
- // ../../packages/shuttle/dist/credentials/broker.js
26663
- var require_broker = __commonJS({
26664
- "../../packages/shuttle/dist/credentials/broker.js"(exports2) {
26665
- "use strict";
26666
- Object.defineProperty(exports2, "__esModule", { value: true });
26667
- exports2.createCredentialBroker = createCredentialBroker;
26668
- var keep_1 = require_dist2();
26669
- var env_ref_1 = require_env_ref();
26670
- var registry_1 = require_registry2();
26671
- function createCredentialBroker(config, deps = {}) {
26672
- if (typeof config !== "object" || config === null || config.apiKeyFrom !== "job-metadata") {
26673
- return null;
26674
- }
26675
- const cfg = config;
26676
- const keepApiUrl = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepApiUrl", "KEEP_API_URL");
26677
- const clientId = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientId", "KEEP_CLIENT_ID");
26678
- const clientSecret = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientSecret", "KEEP_CLIENT_SECRET");
26679
- const stmFactory = deps.buildServiceTokenManager ?? ((c) => new keep_1.ServiceTokenManager(c));
26680
- const stm = stmFactory({ keepApiUrl, clientId, clientSecret });
26681
- const keepFactory = deps.buildKeepClient ?? ((c) => new keep_1.KeepClient(c));
26682
- return {
26683
- async reveal({ name, principal }) {
26684
- const resolver = (0, registry_1.getCredentialResolver)(name);
26685
- if (!resolver)
26686
- return null;
26687
- const serviceToken = await stm.getToken();
26688
- if (!serviceToken) {
26689
- throw new Error("credential broker: Keep service-token exchange failed. Check KEEP_CLIENT_ID / KEEP_CLIENT_SECRET.");
26690
- }
26691
- const keep = keepFactory({ baseUrl: keepApiUrl, serviceToken });
26692
- return resolver(keep, principal);
26693
- }
26694
- };
26845
+ return Buffer.concat(chunks);
26846
+ } finally {
26847
+ clearTimeout(timer);
26848
+ opts.signal?.removeEventListener("abort", onParentAbort);
26849
+ }
26695
26850
  }
26696
26851
  }
26697
26852
  });
26698
26853
 
26699
- // ../../packages/shuttle/dist/credentials/index.js
26700
- var require_credentials = __commonJS({
26701
- "../../packages/shuttle/dist/credentials/index.js"(exports2) {
26702
- "use strict";
26703
- Object.defineProperty(exports2, "__esModule", { value: true });
26704
- exports2.getCredentialResolver = exports2.registerCredentialResolver = exports2.createCredentialBroker = void 0;
26705
- var broker_1 = require_broker();
26706
- Object.defineProperty(exports2, "createCredentialBroker", { enumerable: true, get: function() {
26707
- return broker_1.createCredentialBroker;
26708
- } });
26709
- var registry_1 = require_registry2();
26710
- Object.defineProperty(exports2, "registerCredentialResolver", { enumerable: true, get: function() {
26711
- return registry_1.registerCredentialResolver;
26712
- } });
26713
- Object.defineProperty(exports2, "getCredentialResolver", { enumerable: true, get: function() {
26714
- return registry_1.getCredentialResolver;
26715
- } });
26716
- }
26717
- });
26718
-
26719
- // ../../packages/shuttle/dist/executors/output-gates.js
26720
- var require_output_gates = __commonJS({
26721
- "../../packages/shuttle/dist/executors/output-gates.js"(exports2) {
26854
+ // ../../packages/shuttle/dist/workspace/materialize.js
26855
+ var require_materialize = __commonJS({
26856
+ "../../packages/shuttle/dist/workspace/materialize.js"(exports2) {
26722
26857
  "use strict";
26858
+ var __importDefault = exports2 && exports2.__importDefault || function(mod) {
26859
+ return mod && mod.__esModule ? mod : { "default": mod };
26860
+ };
26723
26861
  Object.defineProperty(exports2, "__esModule", { value: true });
26724
- exports2.isSanctionedPaint = isSanctionedPaint;
26725
- exports2.unsanctionedPaints = unsanctionedPaints;
26726
- exports2.resolvePath = resolvePath;
26727
- exports2.evaluateOutputGates = evaluateOutputGates;
26728
- exports2.renderRepairPrompt = renderRepairPrompt;
26729
- var INPUT_REF = "input:";
26730
- var COLOR_BEARING = ["fill", "stroke", "color", "stop-color", "flood-color", "lighting-color"];
26731
- var INERT = /* @__PURE__ */ new Set(["none", "inherit", "initial", "unset", "transparent", "currentcolor"]);
26732
- function isSanctionedPaint(raw) {
26733
- const value = raw.trim().toLowerCase();
26734
- if (value === "")
26735
- return true;
26736
- if (INERT.has(value))
26737
- return true;
26738
- if (/^url\(\s*['"]?#[^)'"]+['"]?\s*\)$/.test(value))
26739
- return true;
26740
- const varMatch = /^var\(\s*(--[a-z0-9-]+)\s*(?:,([\s\S]*))?\)$/.exec(value);
26741
- if (!varMatch)
26742
- return false;
26743
- const [, name, fallback] = varMatch;
26744
- if (!name.startsWith("--color-"))
26745
- return false;
26746
- return fallback === void 0 || isSanctionedPaint(fallback);
26862
+ exports2.registerMaterializer = registerMaterializer;
26863
+ exports2.registerModifier = registerModifier;
26864
+ exports2.materializeWorkspace = materializeWorkspace;
26865
+ var fs_1 = require("fs");
26866
+ var os_1 = __importDefault(require("os"));
26867
+ var path_1 = __importDefault(require("path"));
26868
+ var git_1 = require_git();
26869
+ var overlay_1 = require_overlay();
26870
+ var materializers = /* @__PURE__ */ new Map();
26871
+ var modifiers = /* @__PURE__ */ new Map();
26872
+ function registerMaterializer(provider) {
26873
+ materializers.set(provider.namespace, provider);
26747
26874
  }
26748
- function unsanctionedPaints(source) {
26749
- const found = [];
26750
- const attrs = COLOR_BEARING.join("|");
26751
- const attribute = new RegExp(`\\b(?:${attrs})\\s*=\\s*(['"])([\\s\\S]*?)\\1`, "gi");
26752
- const declaration = new RegExp(`\\b(?:${attrs})\\s*:\\s*([^;"'}\\n]+)`, "gi");
26753
- for (const [, , value] of source.matchAll(attribute)) {
26754
- if (!isSanctionedPaint(value))
26755
- found.push(value.trim());
26756
- }
26757
- for (const [, value] of source.matchAll(declaration)) {
26758
- if (!isSanctionedPaint(value))
26759
- found.push(value.trim());
26760
- }
26761
- return found;
26875
+ function registerModifier(provider) {
26876
+ modifiers.set(provider.namespace, provider);
26762
26877
  }
26763
- function resolvePath(root, path) {
26764
- let ctx = root;
26765
- for (const seg of path.split(".")) {
26766
- const project = seg.endsWith("[*]");
26767
- const key = project ? seg.slice(0, -3) : seg;
26768
- if (Array.isArray(ctx)) {
26769
- ctx = ctx.map((el) => key ? el?.[key] : el);
26770
- } else {
26771
- ctx = key ? ctx?.[key] : ctx;
26772
- }
26773
- if (project && !Array.isArray(ctx)) {
26774
- ctx = ctx == null ? [] : [ctx];
26878
+ registerMaterializer(git_1.gitMaterializer);
26879
+ registerModifier(overlay_1.overlayModifier);
26880
+ async function materializeWorkspace(bag, options = {}) {
26881
+ const tmpBase = options.tmpDir ?? os_1.default.tmpdir();
26882
+ const runRoot = await fs_1.promises.mkdtemp(path_1.default.join(tmpBase, "shuttle-ws-"));
26883
+ const cleanup = async () => {
26884
+ await fs_1.promises.rm(runRoot, { recursive: true, force: true }).catch(() => {
26885
+ });
26886
+ };
26887
+ let materialized = false;
26888
+ let primaryDir;
26889
+ let warning;
26890
+ let context = [];
26891
+ let ranBase = false;
26892
+ for (const [namespace, provider] of materializers) {
26893
+ if (bag[namespace] !== void 0) {
26894
+ const outcome = await provider.materialize(bag[namespace], runRoot, options);
26895
+ materialized = outcome.materialized;
26896
+ primaryDir = outcome.primaryDir;
26897
+ warning = outcome.warning;
26898
+ context = outcome.context;
26899
+ ranBase = true;
26900
+ break;
26775
26901
  }
26776
26902
  }
26777
- return ctx;
26778
- }
26779
- function resolveRef(ref, output, inputs) {
26780
- if (ref.startsWith(INPUT_REF)) {
26781
- const label = ref.slice(INPUT_REF.length);
26782
- const row = inputs.find((i) => i.label === label) ?? inputs.find((i) => i.label === "artifacts" && i.payload.label === label);
26783
- if (!row)
26784
- return void 0;
26785
- return Object.prototype.hasOwnProperty.call(row.payload, "value") ? row.payload.value : row.payload;
26903
+ if (!ranBase) {
26904
+ const offered = Object.keys(bag).join(", ") || "(none)";
26905
+ await fs_1.promises.mkdir(path_1.default.join(runRoot, "primary"), { recursive: true }).catch(() => {
26906
+ });
26907
+ warning = `workspace carries no materializer this runner understands (offered: ${offered}; supported: ${[...materializers.keys()].join(", ")})`;
26786
26908
  }
26787
- return resolvePath(output, ref);
26788
- }
26789
- function asStrings(value) {
26790
- if (Array.isArray(value))
26791
- return value.map((v) => String(v));
26792
- if (value == null)
26793
- return [];
26794
- return [String(value)];
26795
- }
26796
- var PRIMITIVES = {
26797
- /**
26798
- * `coverage` — the values at `got` must exactly cover the set at `want`:
26799
- * every wanted value present, nothing invented, none repeated. Params:
26800
- * `{ got: <output path>, want: <ref>, subject?: <noun> }`.
26801
- */
26802
- coverage(params, output, inputs) {
26803
- const subject = typeof params.subject === "string" ? params.subject : "item";
26804
- const got = asStrings(resolveRef(String(params.got), output, inputs));
26805
- const want = asStrings(resolveRef(String(params.want), output, inputs));
26806
- const gotSet = new Set(got);
26807
- const wantSet = new Set(want);
26808
- const missing = want.filter((v) => !gotSet.has(v));
26809
- const unknown = [...new Set(got.filter((v) => !wantSet.has(v)))];
26810
- const seen = /* @__PURE__ */ new Set();
26811
- const duplicated = [];
26812
- for (const v of got) {
26813
- if (seen.has(v))
26814
- duplicated.push(v);
26815
- else
26816
- seen.add(v);
26817
- }
26818
- if (missing.length === 0 && unknown.length === 0 && duplicated.length === 0)
26819
- return [];
26820
- const parts = [];
26821
- if (missing.length)
26822
- parts.push(`missing ${subject}(s): [${missing.join(", ")}]`);
26823
- if (unknown.length)
26824
- parts.push(`not a known ${subject}: [${unknown.join(", ")}]`);
26825
- if (duplicated.length)
26826
- parts.push(`assessed more than once: [${[...new Set(duplicated)].join(", ")}]`);
26827
- return [
26828
- `every ${subject} must be covered exactly once \u2014 ${parts.join("; ")}. Return one entry per ${subject}, using its exact id.`
26829
- ];
26830
- },
26831
- /**
26832
- * `non_empty_when` — the array at `path` must be non-empty, optionally only
26833
- * when `when.path` equals `when.equals`. Params:
26834
- * `{ path: <output path>, when?: { path: <output path>, equals: <value> } }`.
26835
- */
26836
- non_empty_when(params, output) {
26837
- const when = params.when;
26838
- if (when && typeof when.path === "string") {
26839
- if (resolvePath(output, when.path) !== when.equals)
26840
- return [];
26909
+ let overlay;
26910
+ for (const [namespace, provider] of modifiers) {
26911
+ if (bag[namespace] !== void 0) {
26912
+ overlay = await provider.apply(bag[namespace], runRoot, options);
26841
26913
  }
26842
- const path = String(params.path);
26843
- const value = resolvePath(output, path);
26844
- if (Array.isArray(value) && value.length > 0)
26845
- return [];
26846
- const cond = when && typeof when.path === "string" ? ` when ${when.path} is ${JSON.stringify(when.equals)}` : "";
26847
- return [
26848
- `'${path}' must be a non-empty array${cond}; it was ${Array.isArray(value) ? "empty" : "absent"}.`
26849
- ];
26850
- },
26851
- /**
26852
- * `bounded_palette` — every colour in the sources at `path` must be named
26853
- * by role rather than written as a value. Params:
26854
- * `{ path: <output path>, roles?: <role names for the repair turn> }`.
26855
- *
26856
- * A drawing the model authors is markup the house did not write, and a
26857
- * literal in it is a colour outside the consuming palette: unproved
26858
- * against the colours beside it, unchecked for contrast on the ground it
26859
- * lands on, and fixed to one theme. The consumer strips such a paint at
26860
- * render, so an artifact that carries one silently loses it. Catching it
26861
- * HERE is what makes that a repair the model can make while it still has
26862
- * the drawing in hand, instead of a defect nobody sees until the picture
26863
- * comes out plain.
26864
- */
26865
- bounded_palette(params, output) {
26866
- const path = String(params.path);
26867
- const value = resolvePath(output, path);
26868
- const sources = (Array.isArray(value) ? value : [value]).filter((v) => typeof v === "string" && v.length > 0);
26869
- const offenders = [...new Set(sources.flatMap(unsanctionedPaints))];
26870
- if (offenders.length === 0)
26871
- return [];
26872
- const roles = Array.isArray(params.roles) ? params.roles.map(String) : [];
26873
- const vocabulary = roles.length > 0 ? ` Use one of: ${roles.join(", ")}.` : "";
26874
- return [
26875
- `'${path}' states ${offenders.length} colour value${offenders.length === 1 ? "" : "s"} directly (${offenders.slice(0, 8).join(", ")}${offenders.length > 8 ? ", \u2026" : ""}). Every colour must be named by role \u2014 var(--color-\u2026), currentColor, or none \u2014 never as a hex, rgb(), hsl() or colour name, because a value cannot adapt to the reader's theme and was never checked against the colours beside it.${vocabulary} Redraw with roles and return the whole output again.`
26876
- ];
26877
26914
  }
26878
- };
26879
- function evaluateOutputGates(gates, output, inputs) {
26880
- const findings = [];
26881
- for (const gate of gates) {
26882
- const primitive = PRIMITIVES[gate.primitive];
26883
- if (!primitive) {
26884
- findings.push({ gate: gate.name, message: `unknown gate primitive '${gate.primitive}'` });
26885
- continue;
26915
+ return { cwd: runRoot, materialized, primaryDir, warning, context, overlay, cleanup };
26916
+ }
26917
+ }
26918
+ });
26919
+
26920
+ // ../../packages/shuttle/dist/workspace/index.js
26921
+ var require_workspace = __commonJS({
26922
+ "../../packages/shuttle/dist/workspace/index.js"(exports2) {
26923
+ "use strict";
26924
+ Object.defineProperty(exports2, "__esModule", { value: true });
26925
+ exports2.applyOverlay = exports2.overlayModifier = exports2.buildGitAuthEnv = exports2.gitMaterializer = exports2.registerModifier = exports2.registerMaterializer = exports2.materializeWorkspace = void 0;
26926
+ var materialize_1 = require_materialize();
26927
+ Object.defineProperty(exports2, "materializeWorkspace", { enumerable: true, get: function() {
26928
+ return materialize_1.materializeWorkspace;
26929
+ } });
26930
+ Object.defineProperty(exports2, "registerMaterializer", { enumerable: true, get: function() {
26931
+ return materialize_1.registerMaterializer;
26932
+ } });
26933
+ Object.defineProperty(exports2, "registerModifier", { enumerable: true, get: function() {
26934
+ return materialize_1.registerModifier;
26935
+ } });
26936
+ var git_1 = require_git();
26937
+ Object.defineProperty(exports2, "gitMaterializer", { enumerable: true, get: function() {
26938
+ return git_1.gitMaterializer;
26939
+ } });
26940
+ Object.defineProperty(exports2, "buildGitAuthEnv", { enumerable: true, get: function() {
26941
+ return git_1.buildGitAuthEnv;
26942
+ } });
26943
+ var overlay_1 = require_overlay();
26944
+ Object.defineProperty(exports2, "overlayModifier", { enumerable: true, get: function() {
26945
+ return overlay_1.overlayModifier;
26946
+ } });
26947
+ Object.defineProperty(exports2, "applyOverlay", { enumerable: true, get: function() {
26948
+ return overlay_1.applyOverlay;
26949
+ } });
26950
+ }
26951
+ });
26952
+
26953
+ // ../../packages/shuttle/dist/core/run-dispatch.js
26954
+ var require_run_dispatch = __commonJS({
26955
+ "../../packages/shuttle/dist/core/run-dispatch.js"(exports2) {
26956
+ "use strict";
26957
+ Object.defineProperty(exports2, "__esModule", { value: true });
26958
+ exports2.GATE_REPAIR_BUDGET = void 0;
26959
+ exports2.runDispatch = runDispatch;
26960
+ exports2.runOutputGates = runOutputGates;
26961
+ exports2.mergeRepairedResponse = mergeRepairedResponse;
26962
+ var loom_1 = require_dist();
26963
+ var output_gates_1 = require_output_gates();
26964
+ var logger_1 = require_logger();
26965
+ var workspace_1 = require_workspace();
26966
+ exports2.GATE_REPAIR_BUDGET = 2;
26967
+ async function runDispatch(dispatch, executor, options) {
26968
+ const { credentials, signal } = options;
26969
+ const environment = executor.prepareEnvironment ? await executor.prepareEnvironment(dispatch) : void 0;
26970
+ let workspace = null;
26971
+ if (environment?.workspaceRequest) {
26972
+ try {
26973
+ workspace = await (0, workspace_1.materializeWorkspace)(environment.workspaceRequest, {
26974
+ ...environment.materializeOptions ?? {},
26975
+ credentials,
26976
+ signal
26977
+ });
26978
+ } catch (err) {
26979
+ (0, logger_1.getLogger)().warn("workspace materialization failed; running prompt-only", {
26980
+ jobId: dispatch.job.id,
26981
+ error: err instanceof Error ? err.message : String(err)
26982
+ });
26983
+ workspace = null;
26886
26984
  }
26887
- for (const message of primitive(gate.params, output, inputs)) {
26888
- findings.push({ gate: gate.name, message });
26985
+ }
26986
+ const ctx = {
26987
+ ...options.reportProgress ? { reportProgress: options.reportProgress } : {},
26988
+ workspace,
26989
+ credentials
26990
+ };
26991
+ let response;
26992
+ try {
26993
+ response = await executor.execute(dispatch, signal, ctx);
26994
+ } catch (error) {
26995
+ return { kind: "executor-failed", error };
26996
+ } finally {
26997
+ if (workspace)
26998
+ await workspace.cleanup();
26999
+ }
27000
+ const gated = await runOutputGates(dispatch, response, executor, signal, ctx);
27001
+ if (!gated.ok)
27002
+ return { kind: "gate-failed", reason: gated.reason };
27003
+ return { kind: "completed", response: gated.response };
27004
+ }
27005
+ async function runOutputGates(dispatch, response, executor, signal, ctx) {
27006
+ let spec;
27007
+ try {
27008
+ spec = (0, loom_1.readPromptExecutionSpec)(dispatch.inputs);
27009
+ } catch {
27010
+ return { ok: true, response };
27011
+ }
27012
+ const gates = spec.gates;
27013
+ if (!gates || gates.length === 0)
27014
+ return { ok: true, response };
27015
+ let current = response;
27016
+ let result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
27017
+ let attempts = 0;
27018
+ while (!result.ok && attempts < exports2.GATE_REPAIR_BUDGET && current.continuation !== void 0 && typeof executor.continue === "function") {
27019
+ try {
27020
+ const repaired = await executor.continue(current.continuation, (0, output_gates_1.renderRepairPrompt)(result.findings), signal, ctx);
27021
+ current = mergeRepairedResponse(current, repaired);
27022
+ } catch {
27023
+ break;
26889
27024
  }
27025
+ result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
27026
+ attempts += 1;
26890
27027
  }
26891
- return { ok: findings.length === 0, findings };
27028
+ if (result.ok)
27029
+ return { ok: true, response: current };
27030
+ const detail = result.findings.map((f) => `[${f.gate}] ${f.message}`).join(" | ");
27031
+ return {
27032
+ ok: false,
27033
+ reason: `output gate(s) failed${attempts > 0 ? ` after ${attempts} repair attempt(s)` : ""}: ${detail}`
27034
+ };
26892
27035
  }
26893
- function renderRepairPrompt(findings) {
26894
- return [
26895
- "Your previous answer did not satisfy these output checks. Return the corrected, complete answer that resolves every item below. Produce the same output shape with the problems fixed, and nothing else \u2014 no commentary, no explanation of the changes.",
26896
- "",
26897
- ...findings.map((f) => `- [${f.gate}] ${f.message}`)
26898
- ].join("\n");
27036
+ function mergeRepairedResponse(original, repaired) {
27037
+ const replaced = new Set(repaired.outputs.map((o) => o.label));
27038
+ const outputs = [...original.outputs.filter((o) => !replaced.has(o.label)), ...repaired.outputs];
27039
+ const usage = sumUsage(original.usage, repaired.usage);
27040
+ return {
27041
+ ...original,
27042
+ ...repaired,
27043
+ outputs,
27044
+ ...usage ? { usage } : {}
27045
+ };
27046
+ }
27047
+ var ADDITIVE_USAGE = [
27048
+ "inputTokens",
27049
+ "outputTokens",
27050
+ "cacheReadInputTokens",
27051
+ "cacheCreationInputTokens",
27052
+ "costUsd",
27053
+ "turns"
27054
+ ];
27055
+ function sumUsage(a, b) {
27056
+ if (!a)
27057
+ return b;
27058
+ if (!b)
27059
+ return a;
27060
+ const sum = { ...a, ...b };
27061
+ for (const key of ADDITIVE_USAGE) {
27062
+ if (a[key] === void 0 && b[key] === void 0)
27063
+ continue;
27064
+ sum[key] = (a[key] ?? 0) + (b[key] ?? 0);
27065
+ }
27066
+ if (a.toolCalls || b.toolCalls) {
27067
+ const calls = { ...a.toolCalls ?? {} };
27068
+ for (const [name, n] of Object.entries(b.toolCalls ?? {}))
27069
+ calls[name] = (calls[name] ?? 0) + n;
27070
+ sum.toolCalls = calls;
27071
+ }
27072
+ return sum;
26899
27073
  }
26900
27074
  }
26901
27075
  });
26902
27076
 
26903
- // ../../packages/shuttle/dist/logging/logger.js
26904
- var require_logger = __commonJS({
26905
- "../../packages/shuttle/dist/logging/logger.js"(exports2) {
27077
+ // ../../packages/shuttle/dist/credentials/registry.js
27078
+ var require_registry2 = __commonJS({
27079
+ "../../packages/shuttle/dist/credentials/registry.js"(exports2) {
26906
27080
  "use strict";
26907
27081
  Object.defineProperty(exports2, "__esModule", { value: true });
26908
- exports2.createLogger = createLogger;
26909
- exports2.setGlobalLogger = setGlobalLogger;
26910
- exports2.getLogger = getLogger;
26911
- var LEVEL_ORDER = {
26912
- debug: 0,
26913
- info: 1,
26914
- warn: 2,
26915
- error: 3
26916
- };
26917
- function formatContext(context) {
26918
- return Object.entries(context).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
26919
- }
26920
- function formatPretty(level, message, context) {
26921
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
26922
- const tag = level.toUpperCase().padEnd(5);
26923
- const base = `[${timestamp}] ${tag} ${message}`;
26924
- if (context && Object.keys(context).length > 0) {
26925
- return `${base} ${formatContext(context)}`;
26926
- }
26927
- return base;
27082
+ exports2.registerCredentialResolver = registerCredentialResolver;
27083
+ exports2.getCredentialResolver = getCredentialResolver;
27084
+ var resolvers = /* @__PURE__ */ new Map();
27085
+ function registerCredentialResolver(name, resolver) {
27086
+ resolvers.set(name, resolver);
26928
27087
  }
26929
- function formatJson(level, message, context) {
26930
- const entry = {
26931
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
26932
- level,
26933
- message,
26934
- ...context
26935
- };
26936
- return JSON.stringify(entry);
27088
+ function getCredentialResolver(name) {
27089
+ return resolvers.get(name);
26937
27090
  }
26938
- function createLogger(options) {
26939
- const threshold = LEVEL_ORDER[options.level];
26940
- const format = options.format === "json" ? formatJson : formatPretty;
26941
- function emit(level, message, context) {
26942
- if (LEVEL_ORDER[level] < threshold)
26943
- return;
26944
- const line = format(level, message, context);
26945
- if (level === "error") {
26946
- console.error(line);
26947
- } else if (level === "warn") {
26948
- console.warn(line);
26949
- } else {
26950
- console.log(line);
26951
- }
27091
+ registerCredentialResolver("managed-model-key", async (keep, principal) => {
27092
+ const reveal = await keep.revealManagedSifterKey(principal);
27093
+ return reveal.apiKey;
27094
+ });
27095
+ registerCredentialResolver("github-user-token", async (keep, principal) => {
27096
+ try {
27097
+ const reveal = await keep.getUserGithubToken(principal);
27098
+ return reveal.access_token;
27099
+ } catch {
27100
+ return null;
27101
+ }
27102
+ });
27103
+ }
27104
+ });
27105
+
27106
+ // ../../packages/shuttle/dist/credentials/broker.js
27107
+ var require_broker = __commonJS({
27108
+ "../../packages/shuttle/dist/credentials/broker.js"(exports2) {
27109
+ "use strict";
27110
+ Object.defineProperty(exports2, "__esModule", { value: true });
27111
+ exports2.createCredentialBroker = createCredentialBroker;
27112
+ var keep_1 = require_dist2();
27113
+ var env_ref_1 = require_env_ref();
27114
+ var registry_1 = require_registry2();
27115
+ function createCredentialBroker(config, deps = {}) {
27116
+ if (typeof config !== "object" || config === null || config.apiKeyFrom !== "job-metadata") {
27117
+ return null;
26952
27118
  }
27119
+ const cfg = config;
27120
+ const keepApiUrl = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepApiUrl", "KEEP_API_URL");
27121
+ const clientId = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientId", "KEEP_CLIENT_ID");
27122
+ const clientSecret = (0, env_ref_1.resolveConfigStringOrEnv)(cfg, "keepClientSecret", "KEEP_CLIENT_SECRET");
27123
+ const stmFactory = deps.buildServiceTokenManager ?? ((c) => new keep_1.ServiceTokenManager(c));
27124
+ const stm = stmFactory({ keepApiUrl, clientId, clientSecret });
27125
+ const keepFactory = deps.buildKeepClient ?? ((c) => new keep_1.KeepClient(c));
26953
27126
  return {
26954
- debug: (message, context) => emit("debug", message, context),
26955
- info: (message, context) => emit("info", message, context),
26956
- warn: (message, context) => emit("warn", message, context),
26957
- error: (message, context) => emit("error", message, context)
27127
+ async reveal({ name, principal }) {
27128
+ const resolver = (0, registry_1.getCredentialResolver)(name);
27129
+ if (!resolver)
27130
+ return null;
27131
+ const serviceToken = await stm.getToken();
27132
+ if (!serviceToken) {
27133
+ throw new Error("credential broker: Keep service-token exchange failed. Check KEEP_CLIENT_ID / KEEP_CLIENT_SECRET.");
27134
+ }
27135
+ const keep = keepFactory({ baseUrl: keepApiUrl, serviceToken });
27136
+ return resolver(keep, principal);
27137
+ }
26958
27138
  };
26959
27139
  }
26960
- var globalLogger = createLogger({ level: "info", format: "pretty" });
26961
- function setGlobalLogger(logger) {
26962
- globalLogger = logger;
26963
- }
26964
- function getLogger() {
26965
- return globalLogger;
26966
- }
27140
+ }
27141
+ });
27142
+
27143
+ // ../../packages/shuttle/dist/credentials/index.js
27144
+ var require_credentials = __commonJS({
27145
+ "../../packages/shuttle/dist/credentials/index.js"(exports2) {
27146
+ "use strict";
27147
+ Object.defineProperty(exports2, "__esModule", { value: true });
27148
+ exports2.getCredentialResolver = exports2.registerCredentialResolver = exports2.createCredentialBroker = void 0;
27149
+ var broker_1 = require_broker();
27150
+ Object.defineProperty(exports2, "createCredentialBroker", { enumerable: true, get: function() {
27151
+ return broker_1.createCredentialBroker;
27152
+ } });
27153
+ var registry_1 = require_registry2();
27154
+ Object.defineProperty(exports2, "registerCredentialResolver", { enumerable: true, get: function() {
27155
+ return registry_1.registerCredentialResolver;
27156
+ } });
27157
+ Object.defineProperty(exports2, "getCredentialResolver", { enumerable: true, get: function() {
27158
+ return registry_1.getCredentialResolver;
27159
+ } });
26967
27160
  }
26968
27161
  });
26969
27162
 
@@ -27527,9 +27720,8 @@ var require_shuttle = __commonJS({
27527
27720
  var loom_1 = require_dist();
27528
27721
  var chain_1 = require_chain();
27529
27722
  var types_1 = require_types2();
27530
- var workspace_1 = require_workspace();
27723
+ var run_dispatch_1 = require_run_dispatch();
27531
27724
  var credentials_1 = require_credentials();
27532
- var output_gates_1 = require_output_gates();
27533
27725
  var keep_1 = require_dist2();
27534
27726
  var apply_1 = require_apply();
27535
27727
  var environment_1 = require_environment();
@@ -27549,7 +27741,6 @@ var require_shuttle = __commonJS({
27549
27741
  var audit_log_1 = require_audit_log();
27550
27742
  var spend_tracker_1 = require_spend_tracker();
27551
27743
  var store_1 = require_store();
27552
- var GATE_REPAIR_BUDGET = 2;
27553
27744
  var ENVIRONMENT_HOLD = "executor-environment";
27554
27745
  function requiredExecutor(dispatch, strategy) {
27555
27746
  if (strategy !== loom_1.PROMPT_EXECUTION_STRATEGY)
@@ -27616,36 +27807,6 @@ var require_shuttle = __commonJS({
27616
27807
  function formatInstant(epochMs) {
27617
27808
  return new Date(epochMs).toISOString().replace(/\.\d{3}Z$/, "Z");
27618
27809
  }
27619
- async function runOutputGates(dispatch, response, executor, signal, ctx) {
27620
- let spec;
27621
- try {
27622
- spec = (0, loom_1.readPromptExecutionSpec)(dispatch.inputs);
27623
- } catch {
27624
- return { ok: true, response };
27625
- }
27626
- const gates = spec.gates;
27627
- if (!gates || gates.length === 0)
27628
- return { ok: true, response };
27629
- let current = response;
27630
- let result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
27631
- let attempts = 0;
27632
- while (!result.ok && attempts < GATE_REPAIR_BUDGET && current.continuation !== void 0 && typeof executor.continue === "function") {
27633
- try {
27634
- current = await executor.continue(current.continuation, (0, output_gates_1.renderRepairPrompt)(result.findings), signal, ctx);
27635
- } catch {
27636
- break;
27637
- }
27638
- result = (0, output_gates_1.evaluateOutputGates)(gates, current.parsed ?? {}, dispatch.inputs);
27639
- attempts += 1;
27640
- }
27641
- if (result.ok)
27642
- return { ok: true, response: current };
27643
- const detail = result.findings.map((f) => `[${f.gate}] ${f.message}`).join(" | ");
27644
- return {
27645
- ok: false,
27646
- reason: `output gate(s) failed${attempts > 0 ? ` after ${attempts} repair attempt(s)` : ""}: ${detail}`
27647
- };
27648
- }
27649
27810
  var Shuttle = class {
27650
27811
  brand;
27651
27812
  config;
@@ -27837,35 +27998,16 @@ var require_shuttle = __commonJS({
27837
27998
  const runOn = async (executor) => {
27838
27999
  await observerChain.notify({ kind: "executor.dispatch.started", jobId, attendanceId, executor: executor.capability.id, strategy }, onObserverError);
27839
28000
  const dispatchStartedAt = Date.now();
27840
- const environment = executor.prepareEnvironment ? await executor.prepareEnvironment(dispatch) : void 0;
27841
- let preparedWorkspace = null;
27842
- if (environment?.workspaceRequest) {
27843
- try {
27844
- preparedWorkspace = await (0, workspace_1.materializeWorkspace)(environment.workspaceRequest, {
27845
- ...environment.materializeOptions ?? {},
27846
- credentials: this.broker,
27847
- signal
27848
- });
27849
- } catch (err) {
27850
- (0, logger_1.getLogger)().warn("workspace materialization failed; running prompt-only", {
27851
- jobId,
27852
- error: err instanceof Error ? err.message : String(err)
27853
- });
27854
- preparedWorkspace = null;
27855
- }
27856
- }
27857
- const executionCtx = {
28001
+ const outcome = await (0, run_dispatch_1.runDispatch)(dispatch, executor, {
28002
+ credentials: this.broker,
28003
+ signal,
27858
28004
  reportProgress: (channel, frames) => {
27859
28005
  void jobsClient.postProgress(jobId, { channel, frames }).then(() => activity.record()).catch(() => {
27860
28006
  });
27861
- },
27862
- workspace: preparedWorkspace,
27863
- credentials: this.broker
27864
- };
27865
- let response;
27866
- try {
27867
- response = await executor.execute(dispatch, signal, executionCtx);
27868
- } catch (err) {
28007
+ }
28008
+ });
28009
+ if (outcome.kind === "executor-failed") {
28010
+ const err = outcome.error;
27869
28011
  const reason = `executor failed: ${err instanceof Error ? err.message : String(err)}`;
27870
28012
  if (this.broker === null && (0, types_1.isExecutorEnvironmentError)(err)) {
27871
28013
  this.markUnwell(executor, err, subscribeLogger);
@@ -27875,14 +28017,11 @@ var require_shuttle = __commonJS({
27875
28017
  return { kind: "result", result: { status: "failed", reason, failureCode: types_1.MODEL_UNAVAILABLE } };
27876
28018
  }
27877
28019
  return { kind: "result", result: { status: "failed", reason } };
27878
- } finally {
27879
- if (preparedWorkspace)
27880
- await preparedWorkspace.cleanup();
27881
28020
  }
27882
- const gated = await runOutputGates(dispatch, response, executor, signal, executionCtx);
27883
- if (!gated.ok)
27884
- return { kind: "result", result: { status: "failed", reason: gated.reason } };
27885
- response = gated.response;
28021
+ if (outcome.kind === "gate-failed") {
28022
+ return { kind: "result", result: { status: "failed", reason: outcome.reason } };
28023
+ }
28024
+ const response = outcome.response;
27886
28025
  await observerChain.notify({
27887
28026
  kind: "executor.dispatch.completed",
27888
28027
  jobId,
@@ -28823,8 +28962,8 @@ var require_dist5 = __commonJS({
28823
28962
  "../../packages/shuttle/dist/index.js"(exports2) {
28824
28963
  "use strict";
28825
28964
  Object.defineProperty(exports2, "__esModule", { value: true });
28826
- exports2.verificationJson = exports2.resolveEnvironment = exports2.renderVerificationLine = exports2.renderEnvironmentReport = exports2.isWorthReporting = exports2.hostOf = exports2.executorDefaultsFor = exports2.environmentReportJson = exports2.environmentPolledBy = exports2.applyEnvironment = exports2.renderTemplate = exports2.expandHome = exports2.resolvePaths = exports2.SpendStore = exports2.AuditLogStore = exports2.createSpendTrackerObserver = exports2.createAuditLogObserver = exports2.createLoggerObserver = exports2.SpendCapExceeded = exports2.ObserverChain = exports2.createCustomScriptExecutor = exports2.createWebhookExecutor = exports2.createHttpApiExecutor = exports2.createCopilotExecutor = exports2.createCodexExecutor = exports2.createClaudeCodeExecutor = exports2.MODEL_UNAVAILABLE = exports2.ExecutorModelUnavailableError = exports2.ExecutorEnvironmentError = exports2.ExecutorRegistry = exports2.AgentCredentialRevokedError = exports2.runPreflight = exports2.renderLines = exports2.renderJson = exports2.printReport = exports2.hasFailure = exports2.createProbes = exports2.checksFor = exports2.PREFLIGHT_FLOORS = exports2.PREFLIGHT_EXIT_CODE = exports2.CHECKS = exports2.readResponseLatestVersion = exports2.checkResponseMinVersion = exports2.compareSemver = exports2.UpgradeRequiredError = exports2.LATEST_VERSION_HEADER = exports2.MIN_VERSION_HEADER = exports2.loadConfig = exports2.Shuttle = exports2.createCli = void 0;
28827
- exports2.revokePairing = exports2.listPairings = exports2.PairingConfigStore = exports2.pair = exports2.scaffoldedConfigPath = exports2.planScaffold = exports2.DEFAULT_REFUSAL_MESSAGE = exports2.DEFAULT_MONTHLY_PERIOD = exports2.DEFAULT_DAILY_PERIOD = exports2.SUBSTRATE_BRAND = void 0;
28965
+ exports2.renderEnvironmentReport = exports2.isWorthReporting = exports2.hostOf = exports2.executorDefaultsFor = exports2.environmentReportJson = exports2.environmentPolledBy = exports2.applyEnvironment = exports2.renderTemplate = exports2.expandHome = exports2.resolvePaths = exports2.SpendStore = exports2.AuditLogStore = exports2.createSpendTrackerObserver = exports2.createAuditLogObserver = exports2.createLoggerObserver = exports2.SpendCapExceeded = exports2.ObserverChain = exports2.createCustomScriptExecutor = exports2.createWebhookExecutor = exports2.createHttpApiExecutor = exports2.createCopilotExecutor = exports2.createCodexExecutor = exports2.createClaudeCodeExecutor = exports2.MODEL_UNAVAILABLE = exports2.ExecutorModelUnavailableError = exports2.ExecutorEnvironmentError = exports2.ExecutorRegistry = exports2.AgentCredentialRevokedError = exports2.runPreflight = exports2.renderLines = exports2.renderJson = exports2.printReport = exports2.hasFailure = exports2.createProbes = exports2.checksFor = exports2.PREFLIGHT_FLOORS = exports2.PREFLIGHT_EXIT_CODE = exports2.CHECKS = exports2.readResponseLatestVersion = exports2.checkResponseMinVersion = exports2.compareSemver = exports2.UpgradeRequiredError = exports2.LATEST_VERSION_HEADER = exports2.MIN_VERSION_HEADER = exports2.loadConfig = exports2.GATE_REPAIR_BUDGET = exports2.mergeRepairedResponse = exports2.runDispatch = exports2.Shuttle = exports2.createCli = void 0;
28966
+ exports2.revokePairing = exports2.listPairings = exports2.PairingConfigStore = exports2.pair = exports2.scaffoldedConfigPath = exports2.planScaffold = exports2.DEFAULT_REFUSAL_MESSAGE = exports2.DEFAULT_MONTHLY_PERIOD = exports2.DEFAULT_DAILY_PERIOD = exports2.SUBSTRATE_BRAND = exports2.verificationJson = exports2.resolveEnvironment = exports2.renderVerificationLine = void 0;
28828
28967
  var cli_1 = require_cli();
28829
28968
  Object.defineProperty(exports2, "createCli", { enumerable: true, get: function() {
28830
28969
  return cli_1.createCli;
@@ -28833,6 +28972,16 @@ var require_dist5 = __commonJS({
28833
28972
  Object.defineProperty(exports2, "Shuttle", { enumerable: true, get: function() {
28834
28973
  return shuttle_1.Shuttle;
28835
28974
  } });
28975
+ var run_dispatch_1 = require_run_dispatch();
28976
+ Object.defineProperty(exports2, "runDispatch", { enumerable: true, get: function() {
28977
+ return run_dispatch_1.runDispatch;
28978
+ } });
28979
+ Object.defineProperty(exports2, "mergeRepairedResponse", { enumerable: true, get: function() {
28980
+ return run_dispatch_1.mergeRepairedResponse;
28981
+ } });
28982
+ Object.defineProperty(exports2, "GATE_REPAIR_BUDGET", { enumerable: true, get: function() {
28983
+ return run_dispatch_1.GATE_REPAIR_BUDGET;
28984
+ } });
28836
28985
  var loader_1 = require_loader();
28837
28986
  Object.defineProperty(exports2, "loadConfig", { enumerable: true, get: function() {
28838
28987
  return loader_1.loadConfig;
@@ -29043,7 +29192,7 @@ var import_path = require("path");
29043
29192
  var import_promises = require("fs/promises");
29044
29193
  var import_yaml = __toESM(require_dist3());
29045
29194
  var import_shuttle = __toESM(require_dist5());
29046
- var buildVersion = true ? "0.34.0" : pkg.version;
29195
+ var buildVersion = true ? "0.36.0" : pkg.version;
29047
29196
  var AGENT_EXECUTORS = ["claude-code", "codex", "copilot"];
29048
29197
  var sifterBrand = {
29049
29198
  product: {