glimmervoid 0.36.0 → 0.37.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 (41) hide show
  1. package/README.md +86 -84
  2. package/dist/bin/glimmervoid.js +54 -115
  3. package/dist/chunks/{adapters-BdnLyJjf.js → adapters-BmfVPxlH.js} +22 -15
  4. package/dist/chunks/adapters-CqFFmM2R.js +1 -0
  5. package/dist/chunks/{agent-api-cli-DIqRLvu3.js → agent-api-cli-BTHEyJKS.js} +1 -1
  6. package/dist/chunks/{agent-api-cli-d-Bgsshx.js → agent-api-cli-CBgOKXoO.js} +41 -12
  7. package/dist/chunks/{agent-api-core-BUC9WND7.js → agent-api-core-DzKhakCv.js} +94 -3
  8. package/dist/chunks/{agent-setup-cli-CH7EHsAX.js → agent-setup-cli-C8DGxlA-.js} +1 -1
  9. package/dist/chunks/{config-CuZ16F9W.js → config-BYc2z1Oc.js} +15 -10
  10. package/dist/chunks/{config-store-LqQ7MuyV.js → config-store-B7MpiYxG.js} +7 -7
  11. package/dist/chunks/config-store-CsUoy88Q.js +1 -0
  12. package/dist/chunks/{contracts-BLZAOP57.js → contracts-C6ipN_zw.js} +48 -9
  13. package/dist/chunks/git-version-6QFnKbWa.js +139 -0
  14. package/dist/chunks/{grok-Ch4-35_r.js → grok-CZ6kP_vD.js} +5 -1
  15. package/dist/chunks/guardrails-deps-Cb-ki4EU.js +70 -0
  16. package/dist/chunks/{sandbox-proxy-core-hnQgKR0T.js → guardrails-proxy-core-BI3rdY-m.js} +4 -4
  17. package/dist/chunks/{knowledge-graph-cli-DD7QvcFd.js → knowledge-graph-cli-DApeMzA8.js} +1 -1
  18. package/dist/chunks/{loopback-post-DepQfdcM.js → loopback-post-DJ6iYWuL.js} +9 -9
  19. package/dist/chunks/{main-Rmo83Ow-.js → main-BUfjroXE.js} +12976 -11532
  20. package/dist/chunks/{pair-cli-DzFeAmq5.js → pair-cli-GZ9t1mIO.js} +2 -2
  21. package/dist/chunks/{remote-config-CPdSF2Xi.js → remote-config-D2Is89Kj.js} +1 -1
  22. package/dist/chunks/{session-B8RhqQJe.js → session-BZbariv5.js} +54 -8
  23. package/dist/chunks/{session-routes-DB5aDKsx.js → session-routes-C4t8O8yg.js} +9 -9
  24. package/dist/chunks/{settings-cli-C2TY6hl-.js → settings-cli-DQOjmjev.js} +3 -3
  25. package/dist/chunks/{ssh-sign-cli-C2nUwJC-.js → ssh-sign-cli-LIBP8ppO.js} +2 -2
  26. package/dist/client/assets/index-B_Qt7fbZ.css +1 -0
  27. package/dist/client/assets/index-D-upBor0.js +265 -0
  28. package/dist/client/index.html +2 -2
  29. package/dist/scripts/postinstall-path-check.js +4 -4
  30. package/dist/server/index.js +1 -1
  31. package/dist/session/command-hook-relay.js +1 -1
  32. package/dist/session/{sandbox-open-launcher.js → guardrails-open-launcher.js} +10 -10
  33. package/dist/session/hook-relay.js +1 -1
  34. package/dist/session/statusline-relay.js +1 -1
  35. package/package.json +4 -3
  36. package/dist/chunks/adapters-BVozg-Lg.js +0 -1
  37. package/dist/chunks/config-store-tVmt_nfm.js +0 -1
  38. package/dist/chunks/git-version-CUcDtF5k.js +0 -58
  39. package/dist/chunks/sandbox-deps-CWiH1d1w.js +0 -70
  40. package/dist/client/assets/index-BIaSyXwH.css +0 -1
  41. package/dist/client/assets/index-Ddu7M4Ad.js +0 -259
@@ -3,10 +3,10 @@ import { r as execFileSync } from "./child-process-safe-CbQnyh7D.js";
3
3
  import { n as resolveAgentCommand, t as buildAgentSpawnCommand } from "./spawn-command-Cc40FiZI.js";
4
4
  import { s as rawTextOr } from "./coerce-NSst8oRP.js";
5
5
  import { r as nextBackoffMs } from "./backoff-DjVpfHk7.js";
6
- import { l as supervisionLine } from "./session-routes-DB5aDKsx.js";
7
- import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-Ch4-35_r.js";
6
+ import { l as supervisionLine } from "./session-routes-C4t8O8yg.js";
7
+ import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-CZ6kP_vD.js";
8
8
  import { t as buildHookCommand } from "./hook-command-core-qTNK-xMF.js";
9
- import "./contracts-BLZAOP57.js";
9
+ import "./contracts-C6ipN_zw.js";
10
10
  import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-BkxllUHE.js";
11
11
  import fs from "node:fs";
12
12
  import path from "node:path";
@@ -152,10 +152,10 @@ var APPENDED_SYSTEM_PROMPT_FLAGS = Object.freeze([APPEND_SYSTEM_PROMPT_FLAG, "--
152
152
  function isAppendedSystemPromptArgument(launchArgument) {
153
153
  return APPENDED_SYSTEM_PROMPT_FLAGS.some((flag) => launchArgument === flag || launchArgument.startsWith(`${flag}=`));
154
154
  }
155
- function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterSandbox = false, canRunHelpCommand = true } = {}) {
155
+ function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterGuardrails = false, canRunHelpCommand = true } = {}) {
156
156
  const args = dangerouslySkipPermissions ? ["--dangerously-skip-permissions"] : [];
157
157
  if (resumeSessionId) args.push("--resume", resumeSessionId);
158
- if (canRunHelpCommand && !extraArgs.some(isAppendedSystemPromptArgument)) args.push(APPEND_SYSTEM_PROMPT_FLAG, supervisionLine({ isSandboxed: hasOuterSandbox }));
158
+ if (canRunHelpCommand && !extraArgs.some(isAppendedSystemPromptArgument)) args.push(APPEND_SYSTEM_PROMPT_FLAG, supervisionLine({ isGuarded: hasOuterGuardrails }));
159
159
  for (let index = 0; index < extraArgs.length; index += 1) {
160
160
  const argument = extraArgs[index];
161
161
  if (resumeSessionId && argument === "--session-id") {
@@ -455,6 +455,9 @@ function mayContributeHooks(configText) {
455
455
  if (typeof configText !== "string") return false;
456
456
  return HOOKS_DECLARATION_RE.test(configText);
457
457
  }
458
+ function userConfigFolders(env) {
459
+ return codexHomes(env, null);
460
+ }
458
461
  function buildHookArgs({ relayPath = RELAY_PATH, events = HOOK_EVENTS, bypassHookTrust = false, hookTools = [], hookToolRelayPath = HOOK_TOOL_RELAY_PATH } = {}) {
459
462
  const args = bypassHookTrust ? [TRUST_BYPASS_FLAG] : [];
460
463
  const preToolUseGroups = [];
@@ -484,6 +487,7 @@ var hooks = {
484
487
  events: HOOK_EVENTS,
485
488
  buildHookArgs,
486
489
  projectConfigCandidates: PROJECT_CONFIG_CANDIDATES,
490
+ userConfigFolders,
487
491
  mayContributeHooks
488
492
  }
489
493
  };
@@ -513,15 +517,15 @@ var SKIP_PERMISSIONS_ARGS = [
513
517
  "-s",
514
518
  "workspace-write"
515
519
  ];
516
- var OUTER_SANDBOX_ARGS = ["-s", "danger-full-access"];
517
- var OUTER_SANDBOX_SKIP_PERMISSIONS_ARGS = [
520
+ var OUTER_GUARDRAILS_ARGS = ["-s", "danger-full-access"];
521
+ var OUTER_GUARDRAILS_SKIP_PERMISSIONS_ARGS = [
518
522
  "-a",
519
523
  "never",
520
- ...OUTER_SANDBOX_ARGS
524
+ ...OUTER_GUARDRAILS_ARGS
521
525
  ];
522
- function permissionArgs(dangerouslySkipPermissions, hasOuterSandbox) {
523
- if (hasOuterSandbox && dangerouslySkipPermissions) return OUTER_SANDBOX_SKIP_PERMISSIONS_ARGS;
524
- if (hasOuterSandbox) return OUTER_SANDBOX_ARGS;
526
+ function permissionArgs(dangerouslySkipPermissions, hasOuterGuardrails) {
527
+ if (hasOuterGuardrails && dangerouslySkipPermissions) return OUTER_GUARDRAILS_SKIP_PERMISSIONS_ARGS;
528
+ if (hasOuterGuardrails) return OUTER_GUARDRAILS_ARGS;
525
529
  if (dangerouslySkipPermissions) return SKIP_PERMISSIONS_ARGS;
526
530
  return [];
527
531
  }
@@ -539,11 +543,11 @@ function setsOperatorInstructions(operatorConfigText) {
539
543
  function isDeveloperInstructionsOverride(launchArgument) {
540
544
  return launchArgument.startsWith(`${DEVELOPER_INSTRUCTIONS_KEY}=`);
541
545
  }
542
- function buildArgs({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterSandbox = false, hasOperatorInstructions = false, canRunHelpCommand = true } = {}) {
546
+ function buildArgs({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null, hasOuterGuardrails = false, hasOperatorInstructions = false, canRunHelpCommand = true } = {}) {
543
547
  const args = [...UPDATE_CHECK_ARGS];
544
- if (canRunHelpCommand && !hasOperatorInstructions && !extraArgs.some(isDeveloperInstructionsOverride)) args.push("-c", `${DEVELOPER_INSTRUCTIONS_KEY}='''${supervisionLine({ isSandboxed: hasOuterSandbox })}'''`);
548
+ if (canRunHelpCommand && !hasOperatorInstructions && !extraArgs.some(isDeveloperInstructionsOverride)) args.push("-c", `${DEVELOPER_INSTRUCTIONS_KEY}='''${supervisionLine({ isGuarded: hasOuterGuardrails })}'''`);
545
549
  if (resumeSessionId) args.push("resume", resumeSessionId);
546
- args.push(...permissionArgs(dangerouslySkipPermissions, hasOuterSandbox));
550
+ args.push(...permissionArgs(dangerouslySkipPermissions, hasOuterGuardrails));
547
551
  if (extraArgs.length > 0) args.push(...extraArgs);
548
552
  if (initialPrompt != null) args.push(initialPrompt);
549
553
  return args;
@@ -767,5 +771,8 @@ function cachedAgentResolvability(agentId) {
767
771
  resolvable: !!cached.path
768
772
  };
769
773
  }
774
+ function resetCommandCache() {
775
+ resolvedCommands.clear();
776
+ }
770
777
  //#endregion
771
- export { claudeCode as A, laneSpendStatus as C, shouldEvaluateDespiteIoFailures as D, resolveProjectsDirs as E, shouldPersistWarehouse as O, isUsageFile as S, projectDirCandidates as T, decideFileRead as _, describeAgentResolvability as a, grokHomes as b, isKnownAgentId as c, setCustomAgents as d, codexFallbackRoots as f, continuationDelayMs as g, codexSessionIdFromPath as h, customAgentFingerprint as i, splitLines as k, listAgentIds as l, codexRootCandidates as m, cachedAgentResolvability as n, getAdapter as o, codexHomes as p, commandFor as r, hookProfileOf as s, DEFAULT_AGENT_ID as t, resolveAdapter as u, dedupeCodexFiles as v, passOutcome as w, grokRootCandidates as x, expandTilde as y };
778
+ export { splitLines as A, isUsageFile as C, resolveProjectsDirs as D, projectDirCandidates as E, shouldEvaluateDespiteIoFailures as O, grokRootCandidates as S, passOutcome as T, continuationDelayMs as _, describeAgentResolvability as a, expandTilde as b, isKnownAgentId as c, resolveAdapter as d, setCustomAgents as f, codexSessionIdFromPath as g, codexRootCandidates as h, customAgentFingerprint as i, claudeCode as j, shouldPersistWarehouse as k, listAgentIds as l, codexHomes as m, cachedAgentResolvability as n, getAdapter as o, codexFallbackRoots as p, commandFor as r, hookProfileOf as s, DEFAULT_AGENT_ID as t, resetCommandCache as u, decideFileRead as v, laneSpendStatus as w, grokHomes as x, dedupeCodexFiles as y };
@@ -0,0 +1 @@
1
+ export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-BmfVPxlH.js";
@@ -1 +1 @@
1
- export { n as runAgentApiCli, r as sessionLimitsHelpLines } from "./agent-api-cli-d-Bgsshx.js";
1
+ export { n as runAgentApiCli, r as sessionLimitsHelpLines } from "./agent-api-cli-CBgOKXoO.js";
@@ -1,10 +1,10 @@
1
1
  import { t as errorCode } from "./text-DoirglWV.js";
2
- import { a as AgentDispatchRequest, l as AgentTicketRequest, n as AGENT_URL_ENV, s as AgentLimitsReply } from "./session-B8RhqQJe.js";
2
+ import { a as AgentDispatchRequest, c as AgentFactoryStatusRequest, d as AgentTicketRequest, l as AgentLimitsReply, n as AGENT_URL_ENV, s as AgentFactoryRetryRequest } from "./session-BZbariv5.js";
3
3
  import { i as resolveHookTarget } from "./hook-relay-core-DA_bz2KA.js";
4
- import { n as decideSandboxProxy } from "./sandbox-proxy-core-hnQgKR0T.js";
4
+ import { n as decideGuardrailsProxy } from "./guardrails-proxy-core-BI3rdY-m.js";
5
5
  import { t as parseJsonOrNull } from "./json-core-dfa_7Fak.js";
6
- import { a as formatSessionLimits } from "./session-routes-DB5aDKsx.js";
7
- import { d as isOrchestratorAgentVerb, u as isAgentApiVerb } from "./agent-api-core-BUC9WND7.js";
6
+ import { a as formatSessionLimits } from "./session-routes-C4t8O8yg.js";
7
+ import { m as isOrchestratorAgentVerb, p as isAgentApiVerb } from "./agent-api-core-DzKhakCv.js";
8
8
  import path from "node:path";
9
9
  import http from "node:http";
10
10
  //#region server/agent-api-cli.ts
@@ -36,7 +36,18 @@ var BODY_BUILDERS = {
36
36
  return parsed.success ? parsed.data : null;
37
37
  },
38
38
  reopen: (rest) => ticketBody(rest),
39
- cancel: (rest) => ticketBody(rest)
39
+ cancel: (rest) => ticketBody(rest),
40
+ "factory-status": (rest) => {
41
+ if (rest.length === 0) return {};
42
+ if (rest.length !== 2 || rest[0] !== "--project") return null;
43
+ const parsed = AgentFactoryStatusRequest.safeParse({ projectId: rest[1] });
44
+ return parsed.success ? parsed.data : null;
45
+ },
46
+ "factory-retry": (rest) => {
47
+ if (rest.length !== 1) return null;
48
+ const parsed = AgentFactoryRetryRequest.safeParse({ intentId: rest[0] });
49
+ return parsed.success ? parsed.data : null;
50
+ }
40
51
  };
41
52
  function bodySaysOk(text) {
42
53
  try {
@@ -52,6 +63,13 @@ function limitsLines(replyText) {
52
63
  return formatSessionLimits(limits.data);
53
64
  }
54
65
  function printableReply(verb, replyText) {
66
+ if (verb === "factory-status" || verb === "factory-retry") {
67
+ const reply = parseJsonOrNull(replyText);
68
+ if (typeof reply !== "object" || reply === null) return replyText;
69
+ if ("text" in reply && typeof reply.text === "string") return reply.text;
70
+ if ("error" in reply && typeof reply.error === "string") return reply.error;
71
+ return replyText;
72
+ }
55
73
  if (verb !== "limits") return replyText;
56
74
  return limitsLines(replyText)?.join("\n") ?? replyText;
57
75
  }
@@ -79,12 +97,12 @@ async function postDirectly({ endpoint, headers, bodyText, deadline }) {
79
97
  text: await response.text()
80
98
  };
81
99
  }
82
- function postThroughSandboxProxy(sandboxProxy, { endpoint, headers, bodyText, deadline }) {
83
- const proxyHeaders = sandboxProxy.authorization ? { "proxy-authorization": sandboxProxy.authorization } : {};
100
+ function postThroughGuardrailsProxy(guardrailsProxy, { endpoint, headers, bodyText, deadline }) {
101
+ const proxyHeaders = guardrailsProxy.authorization ? { "proxy-authorization": guardrailsProxy.authorization } : {};
84
102
  return new Promise((resolve, reject) => {
85
103
  const request = http.request({
86
- host: sandboxProxy.hostname,
87
- port: sandboxProxy.port,
104
+ host: guardrailsProxy.hostname,
105
+ port: guardrailsProxy.port,
88
106
  method: "POST",
89
107
  path: endpoint.href,
90
108
  headers: {
@@ -129,9 +147,9 @@ async function postToAgentIngress({ endpoint, token, body, deadline = null }) {
129
147
  return await postDirectly(post);
130
148
  } catch (error) {
131
149
  if (!wasConnectionRefused(error)) throw error;
132
- const sandboxProxy = decideSandboxProxy(process.env);
133
- if (!sandboxProxy) throw error;
134
- return postThroughSandboxProxy(sandboxProxy, post);
150
+ const guardrailsProxy = decideGuardrailsProxy(process.env);
151
+ if (!guardrailsProxy) throw error;
152
+ return postThroughGuardrailsProxy(guardrailsProxy, post);
135
153
  }
136
154
  }
137
155
  async function sessionLimitsHelpLines({ timeoutMs = HELP_LIMITS_TIMEOUT_MS } = {}) {
@@ -151,6 +169,13 @@ async function sessionLimitsHelpLines({ timeoutMs = HELP_LIMITS_TIMEOUT_MS } = {
151
169
  }
152
170
  }
153
171
  async function runAgentApiCli(args) {
172
+ if (args[0] === "factory") {
173
+ if (args[1] !== "status" && args[1] !== "retry") {
174
+ console.error("glimmervoid factory: expected status [--project <projectId>] or retry <intentId>");
175
+ return 1;
176
+ }
177
+ return runAgentApiCli([`factory-${args[1]}`, ...args.slice(2)]);
178
+ }
154
179
  const verb = args[0];
155
180
  if (!verb || !isAgentApiVerb(verb)) {
156
181
  console.error(`glimmervoid: ${verb || "that"} is not an agent command`);
@@ -158,6 +183,10 @@ async function runAgentApiCli(args) {
158
183
  }
159
184
  const body = BODY_BUILDERS[verb](args.slice(1));
160
185
  if (!body) {
186
+ if (verb === "factory-status" || verb === "factory-retry") {
187
+ console.error(`glimmervoid factory: expected ${verb === "factory-status" ? "status [--project <projectId>]" : "retry <intentId>"}`);
188
+ return 1;
189
+ }
161
190
  if (isOrchestratorAgentVerb(verb)) {
162
191
  console.error(`glimmervoid ${verb}: expected a work id matching wrk-[0-9a-f]{16}`);
163
192
  return 1;
@@ -1,5 +1,5 @@
1
- import { a as AgentDispatchRequest, c as AgentSpawnRequest, f as ORCHESTRATOR_AGENT_VERBS, i as AgentAttentionRequest, o as AgentEditRequest, t as AGENT_API_VERBS } from "./session-B8RhqQJe.js";
2
- import { c as spawnRoute, i as editRoute, n as attentionRoute, s as pushRoute, t as NO_OWN_WORKTREE_REASON } from "./session-routes-DB5aDKsx.js";
1
+ import { a as AgentDispatchRequest, c as AgentFactoryStatusRequest, i as AgentAttentionRequest, o as AgentEditRequest, s as AgentFactoryRetryRequest, t as AGENT_API_VERBS, u as AgentSpawnRequest, y as ORCHESTRATOR_AGENT_VERBS } from "./session-BZbariv5.js";
2
+ import { c as spawnRoute, i as editRoute, n as attentionRoute, s as pushRoute, t as NO_OWN_WORKTREE_REASON } from "./session-routes-C4t8O8yg.js";
3
3
  import crypto from "node:crypto";
4
4
  var MAX_SPAWNS_IN_FLIGHT = 1;
5
5
  var SPAWNABLE_DEPTH = 0;
@@ -77,6 +77,16 @@ function decideAttentionAllowance(caller) {
77
77
  function decideEditAllowance(caller) {
78
78
  return refuseByRole(editRoute(caller));
79
79
  }
80
+ function factoryControlRoute({ factoryRole, isEphemeral, isSpawnedChild }) {
81
+ if (!(factoryRole !== null || isEphemeral && !isSpawnedChild)) return { answers: true };
82
+ return {
83
+ answers: false,
84
+ reason: "only an operator session or a session it spawned may read factory status or retry parked work, so factory and lane sessions stay on their own task"
85
+ };
86
+ }
87
+ function decideFactoryControlAllowance(caller) {
88
+ return refuseByRole(factoryControlRoute(caller));
89
+ }
80
90
  function describePushRouteRefusal(caller) {
81
91
  const route = pushRoute(caller);
82
92
  if (route.answers) return null;
@@ -137,6 +147,24 @@ function parseAgentVerb(verb, payload) {
137
147
  status: 404,
138
148
  error: REFUSAL_REASON
139
149
  };
150
+ if (verb === "factory-status") {
151
+ const parsed = AgentFactoryStatusRequest.safeParse(payload);
152
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
153
+ return {
154
+ ok: true,
155
+ verb,
156
+ request: parsed.data
157
+ };
158
+ }
159
+ if (verb === "factory-retry") {
160
+ const parsed = AgentFactoryRetryRequest.safeParse(payload);
161
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
162
+ return {
163
+ ok: true,
164
+ verb,
165
+ request: parsed.data
166
+ };
167
+ }
140
168
  if (verb === "dispatch") {
141
169
  const parsed = AgentDispatchRequest.safeParse(payload);
142
170
  if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
@@ -223,5 +251,68 @@ function deriveChildSessionName(parentName, existingNames) {
223
251
  }
224
252
  return candidate;
225
253
  }
254
+ function factoryTicketNextAction(ticket, intentId) {
255
+ if (ticket.state === "completed" || ticket.state === "cancelled") return "none";
256
+ if (ticket.parked) return `glimmervoid factory retry ${intentId}`;
257
+ if (ticket.state === "blocked") return "orchestrator reopens";
258
+ return "in progress";
259
+ }
260
+ function describeFactoryProjectUnavailability(project) {
261
+ if (project.error !== null) return project.error;
262
+ if (project.heading.action === "refuse") return `orientation refused: ${project.heading.reasons.join("; ") || "no reason given"}`;
263
+ return null;
264
+ }
265
+ function describeUnavailableFactoryState(projects) {
266
+ for (const project of projects) {
267
+ const unavailability = describeFactoryProjectUnavailability(project);
268
+ if (unavailability !== null) return `Factory state for ${project.projectId} is unavailable: ${unavailability}`;
269
+ }
270
+ return null;
271
+ }
272
+ function describeSpentToday(spentTodayUsd) {
273
+ if (spentTodayUsd === void 0) return "unknown";
274
+ return `$${spentTodayUsd.toFixed(2)}`;
275
+ }
276
+ function describeDailyBudget(dailyBudgetUsd) {
277
+ if (dailyBudgetUsd === null) return "unlimited";
278
+ if (dailyBudgetUsd === void 0) return "unknown";
279
+ return `$${dailyBudgetUsd.toFixed(2)}`;
280
+ }
281
+ function formatFactoryStatus(projects, buildDigest) {
282
+ const lines = [];
283
+ for (const project of projects) {
284
+ lines.push(`Project ${project.projectId}: ${project.projectName}`);
285
+ lines.push(`Project spend today: ${describeSpentToday(project.spentTodayUsd)} of ${describeDailyBudget(project.dailyBudgetUsd)} budget`);
286
+ const unavailability = describeFactoryProjectUnavailability(project);
287
+ if (unavailability !== null) lines.push(`Factory exception: ${unavailability}`);
288
+ const ticketsByIntentId = /* @__PURE__ */ new Map();
289
+ const partialIntentIds = new Set(project.partialIntentIds ?? []);
290
+ for (const order of project.orders) {
291
+ if (order.parent === null) continue;
292
+ const tickets = ticketsByIntentId.get(order.parent) ?? [];
293
+ tickets.push(order);
294
+ ticketsByIntentId.set(order.parent, tickets);
295
+ }
296
+ let intentCount = 0;
297
+ for (const intent of project.orders) {
298
+ if (intent.parent !== null || intent.state === "cancelled") continue;
299
+ intentCount += 1;
300
+ const tickets = ticketsByIntentId.get(intent.id) ?? [];
301
+ const digest = buildDigest({
302
+ ...project,
303
+ orders: [intent, ...tickets],
304
+ partialIntentIds: partialIntentIds.has(intent.id) ? [intent.id] : []
305
+ }, intent.id);
306
+ const outcome = intent.state === "completed" ? "completed" : digest.isPartial ? "partial" : "in progress";
307
+ lines.push(`Intent ${intent.id}: ${intent.objective}`, `Outcome: ${outcome}; merged: ${digest.merged.length}; parked: ${digest.parked.length}`);
308
+ for (const ticket of tickets) lines.push(` ${ticket.id} | state: ${ticket.parked ? "parked" : ticket.state} | blocks: ${ticket.blockCount ?? 0} | last reason: ${ticket.blockReason ?? "none"} | next action: ${factoryTicketNextAction(ticket, intent.id)}`);
309
+ lines.push("Confirmed flakes:");
310
+ for (const flake of digest.confirmedFlakes) lines.push(` ${flake}`);
311
+ if (digest.confirmedFlakes.length === 0) lines.push(" none");
312
+ }
313
+ if (intentCount === 0 && unavailability === null) lines.push("No intents.");
314
+ }
315
+ return lines.join("\n") || "No factory projects.";
316
+ }
226
317
  //#endregion
227
- export { decideSpawnAllowance as a, describePushLanding as c, isOrchestratorAgentVerb as d, parseAgentVerb as f, decideEditAllowance as i, describePushRouteRefusal as l, decideAgentRequest as n, decideTicketAction as o, decideAttentionAllowance as r, deriveChildSessionName as s, REFUSAL_REASON as t, isAgentApiVerb as u };
318
+ export { decideFactoryControlAllowance as a, deriveChildSessionName as c, describeUnavailableFactoryState as d, formatFactoryStatus as f, parseAgentVerb as h, decideEditAllowance as i, describePushLanding as l, isOrchestratorAgentVerb as m, decideAgentRequest as n, decideSpawnAllowance as o, isAgentApiVerb as p, decideAttentionAllowance as r, decideTicketAction as s, REFUSAL_REASON as t, describePushRouteRefusal as u };
@@ -1,5 +1,5 @@
1
1
  import { a as isMissingFileError, r as errorMessage } from "./text-DoirglWV.js";
2
- import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-Ch4-35_r.js";
2
+ import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-CZ6kP_vD.js";
3
3
  import { p as writeTextAtomicSync } from "./json-file-BaxGcB2R.js";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -1,4 +1,4 @@
1
- import { Ct as GH_SEGMENT, E as TaskTitle, Et as repoParts, G as CommitSha, L as MyPrSearchNode, U as SessionPrLinks, W as repositoryName } from "./session-B8RhqQJe.js";
1
+ import { $ as repositoryName, Ft as repoParts, K as MyPrSearchNode, Mt as GH_SEGMENT, N as TaskTitle, Q as SessionPrLinks, et as CommitSha } from "./session-BZbariv5.js";
2
2
  import { n as isRecord } from "./coerce-NSst8oRP.js";
3
3
  import path from "node:path";
4
4
  import { z } from "zod";
@@ -99,7 +99,8 @@ var CoherenceWorkInspect = z.looseObject({
99
99
  last: z.looseObject({
100
100
  event: z.string(),
101
101
  at: z.string(),
102
- session: z.string()
102
+ session: z.string(),
103
+ reason: z.string().optional()
103
104
  }).nullable(),
104
105
  opened: z.looseObject({
105
106
  at: z.iso.datetime(),
@@ -696,17 +697,17 @@ var IngestSettings = z.object({ enabled: optionalBoolean("ingest.enabled") }, {
696
697
  var TraceSettings = z.object({ enabled: optionalBoolean("trace.enabled") }, { error: "trace must be an object" }).optional();
697
698
  var PlanReviewSettings = z.object({ enabled: optionalBoolean("planReview.enabled") }, { error: "planReview must be an object" }).optional();
698
699
  var optionalPathList = (field) => z.array(z.string({ error: `${field} must be an array of paths` }).trim().min(1, { error: `${field} must be an array of paths` }), { error: `${field} must be an array of paths` }).optional();
699
- var sandboxShape = {
700
+ var guardrailsShape = {
700
701
  unguardedRepos: optionalPathList("guardrails.unguardedRepos"),
701
702
  blockedPaths: optionalPathList("guardrails.blockedPaths"),
702
703
  unreadablePaths: optionalPathList("guardrails.unreadablePaths")
703
704
  };
704
705
  var isHomeRelativePath = (entry) => entry === "~" || entry.startsWith("~/") || entry.startsWith("~\\");
705
- var createSandboxSettings = (isAbsolutePath) => z.object({
706
- ...sandboxShape,
706
+ var createGuardrailsSettings = (isAbsolutePath) => z.object({
707
+ ...guardrailsShape,
707
708
  blockedPaths: z.array(z.string({ error: "guardrails.blockedPaths must be an array of paths" }).trim().min(1, { error: "guardrails.blockedPaths must be an array of paths" }).refine((entry) => isHomeRelativePath(entry) || isAbsolutePath(entry), { message: "guardrails.blockedPaths entries must be absolute paths or start with ~/" }), { error: "guardrails.blockedPaths must be an array of paths" }).optional()
708
709
  }, { error: "guardrails must be an object" }).strict().optional();
709
- var SandboxFileSettings = z.object(sandboxShape, { error: "guardrails must be an object" }).passthrough().optional();
710
+ var GuardrailsFileSettings = z.object(guardrailsShape, { error: "guardrails must be an object" }).passthrough().optional();
710
711
  var telemetryShape = { enabled: optionalBoolean("telemetry.enabled") };
711
712
  var TelemetrySettings = z.object(telemetryShape, { error: "telemetry must be an object" }).strict().optional();
712
713
  var TelemetryFileSettings = z.object(telemetryShape, { error: "telemetry must be an object" }).passthrough().optional();
@@ -749,7 +750,7 @@ var createBrowserConfigShape = (isAbsolutePath) => ({
749
750
  usage: createUsageSettings(isAbsolutePath),
750
751
  telegram: TelegramSettings,
751
752
  ingest: IngestSettings,
752
- guardrails: createSandboxSettings(isAbsolutePath),
753
+ guardrails: createGuardrailsSettings(isAbsolutePath),
753
754
  telemetry: TelemetrySettings,
754
755
  workflows: WorkflowsSettings.nullable().optional()
755
756
  });
@@ -866,7 +867,11 @@ var ProjectConfig = z.object({
866
867
  codexBypassHookTrust: z.boolean().optional(),
867
868
  conversationView: z.boolean({ error: "projects[].conversationView must be a boolean" }).optional(),
868
869
  dangerouslySkipPermissions: z.boolean({ error: "projects[].dangerouslySkipPermissions must be a boolean" }).optional(),
869
- unguarded: z.boolean({ error: "projects[].unguarded must be a boolean" }).optional()
870
+ unguarded: z.boolean({ error: "projects[].unguarded must be a boolean" }).optional(),
871
+ factoryProfile: FactorySettings.unwrap().unwrap().extend({
872
+ focusedTestCommand: z.string().trim().min(1).optional(),
873
+ widenableScopes: z.array(z.string().trim().min(1)).optional()
874
+ }).optional()
870
875
  }).passthrough();
871
876
  var FILE_CONFIG_SHAPE = {
872
877
  ...BROWSER_CONFIG_SHAPE,
@@ -884,7 +889,7 @@ var FILE_CONFIG_SHAPE = {
884
889
  telegram: optionalLooseObject("telegram"),
885
890
  ingest: optionalLooseObject("ingest"),
886
891
  workflows: optionalLooseObject("workflows"),
887
- guardrails: SandboxFileSettings,
892
+ guardrails: GuardrailsFileSettings,
888
893
  telemetry: TelemetryFileSettings,
889
894
  trace: TraceSettings,
890
895
  planReview: PlanReviewSettings,
@@ -968,4 +973,4 @@ function configIssueMessage(error) {
968
973
  return error.issues[0]?.message || "settings are invalid";
969
974
  }
970
975
  //#endregion
971
- export { KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE as A, USAGE_BUDGET_RANGE as B, normalizeLegacyConfigNumbers as C, FLYING_ANIMALS_DURATION_RANGE as D, FLYING_ANIMALS_DEFAULTS as E, POSTHOG_TRAFFIC_BASELINE_RANGE as F, WORKFLOWS_MAX_CONCURRENT_SESSIONS_RANGE as G, USAGE_RETAIN_DAYS_RANGE as H, POSTHOG_TRAFFIC_MIN_USERS_RANGE as I, CoherenceRisk as J, CoherenceOrient as K, POSTHOG_TRAFFIC_MULTIPLIER_RANGE as L, PORT_RANGE as M, POSITIVE_NUMBER_RANGE as N, FLYING_ANIMALS_GAP_RANGE as O, POSTHOG_FIX_TIMEOUT_RANGE as P, CoherenceWorkState as Q, REPLAY_BUFFER_KB_RANGE as R, USAGE_VENDOR_KEYS as S, FACTORY_MAX_LIVE_WORKERS_RANGE as T, USAGE_SCAN_INTERVAL_RANGE as U, USAGE_INTEGER_RANGES as V, WORKFLOWS_MAX_ACTIONS_PER_POLL_RANGE as W, CoherenceWorkCreated as X, CoherenceTicketCreated as Y, CoherenceWorkInspect as Z, WorkflowLabelName as _, ConfigUpdate as a, WorkflowsState as b, TASK_TITLE_SOURCE_PRIORITY as c, CHANGE_MAP_NARRATOR_ENGINES as d, DEFAULT_FACTORY_CHECKS as f, WorkflowCommentBody as g, UPDATE_CHANNELS as h, Config as i, NON_NEGATIVE_NUMBER_RANGE as j, FLYING_ANIMALS_SCALE_RANGE as k, configIssueMessage as l, POST_TURN_CHECK_MODES as m, BUILTIN_AGENT_IDS as n, PersistedTaskTitle as o, DEFAULT_FACTORY_PROTECTED_PATHS as p, CoherenceReadiness as q, BrowserConfig as r, RUNTIME_CONFIG_SCALAR_KEYS as s, AGENT_ID_SHAPE_MESSAGE as t, BranchGcFileSettings as u, WorkflowSearchNode as v, CHANGE_MAP_NARRATOR_TIMEOUT_RANGE as w, USAGE_COST_MODES as x, WorkflowsSettings as y, TASK_TITLE_TIMEOUT_RANGE as z };
976
+ export { CoherenceWorkInspect as $, FLYING_ANIMALS_GAP_RANGE as A, REPLAY_BUFFER_KB_RANGE as B, USAGE_COST_MODES as C, FACTORY_MAX_LIVE_WORKERS_RANGE as D, CHANGE_MAP_NARRATOR_TIMEOUT_RANGE as E, POSITIVE_NUMBER_RANGE as F, USAGE_SCAN_INTERVAL_RANGE as G, USAGE_BUDGET_RANGE as H, POSTHOG_FIX_TIMEOUT_RANGE as I, CoherenceOrient as J, WORKFLOWS_MAX_ACTIONS_PER_POLL_RANGE as K, POSTHOG_TRAFFIC_BASELINE_RANGE as L, KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE as M, NON_NEGATIVE_NUMBER_RANGE as N, FLYING_ANIMALS_DEFAULTS as O, PORT_RANGE as P, CoherenceWorkCreated as Q, POSTHOG_TRAFFIC_MIN_USERS_RANGE as R, WorkflowsState as S, normalizeLegacyConfigNumbers as T, USAGE_INTEGER_RANGES as U, TASK_TITLE_TIMEOUT_RANGE as V, USAGE_RETAIN_DAYS_RANGE as W, CoherenceRisk as X, CoherenceReadiness as Y, CoherenceTicketCreated as Z, UPDATE_CHANNELS as _, ConfigUpdate as a, WorkflowSearchNode as b, RUNTIME_CONFIG_SCALAR_KEYS as c, BranchGcFileSettings as d, CoherenceWorkState as et, CHANGE_MAP_NARRATOR_ENGINES as f, POST_TURN_CHECK_MODES as g, FactorySettings as h, Config as i, FLYING_ANIMALS_SCALE_RANGE as j, FLYING_ANIMALS_DURATION_RANGE as k, TASK_TITLE_SOURCE_PRIORITY as l, DEFAULT_FACTORY_PROTECTED_PATHS as m, BUILTIN_AGENT_IDS as n, PersistedTaskTitle as o, DEFAULT_FACTORY_CHECKS as p, WORKFLOWS_MAX_CONCURRENT_SESSIONS_RANGE as q, BrowserConfig as r, ProjectConfig as s, AGENT_ID_SHAPE_MESSAGE as t, configIssueMessage as u, WorkflowCommentBody as v, USAGE_VENDOR_KEYS as w, WorkflowsSettings as x, WorkflowLabelName as y, POSTHOG_TRAFFIC_MULTIPLIER_RANGE as z };
@@ -3,8 +3,8 @@ import { n as equalsIgnoringCaseOnWindows } from "./paths-Bu4eH1Yd.js";
3
3
  import { n as glimmervoidHomeDir$1, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
4
4
  import { n as isRecord } from "./coerce-NSst8oRP.js";
5
5
  import { d as writeJsonAtomicSync, f as writeTextAtomic, p as writeTextAtomicSync } from "./json-file-BaxGcB2R.js";
6
- import { A as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, B as USAGE_BUDGET_RANGE, C as normalizeLegacyConfigNumbers, D as FLYING_ANIMALS_DURATION_RANGE, E as FLYING_ANIMALS_DEFAULTS, F as POSTHOG_TRAFFIC_BASELINE_RANGE, G as WORKFLOWS_MAX_CONCURRENT_SESSIONS_RANGE, H as USAGE_RETAIN_DAYS_RANGE, I as POSTHOG_TRAFFIC_MIN_USERS_RANGE, L as POSTHOG_TRAFFIC_MULTIPLIER_RANGE, M as PORT_RANGE, N as POSITIVE_NUMBER_RANGE, O as FLYING_ANIMALS_GAP_RANGE, P as POSTHOG_FIX_TIMEOUT_RANGE, R as REPLAY_BUFFER_KB_RANGE, T as FACTORY_MAX_LIVE_WORKERS_RANGE, U as USAGE_SCAN_INTERVAL_RANGE, V as USAGE_INTEGER_RANGES, W as WORKFLOWS_MAX_ACTIONS_PER_POLL_RANGE, d as CHANGE_MAP_NARRATOR_ENGINES, f as DEFAULT_FACTORY_CHECKS, h as UPDATE_CHANNELS, i as Config, j as NON_NEGATIVE_NUMBER_RANGE, k as FLYING_ANIMALS_SCALE_RANGE, l as configIssueMessage, m as POST_TURN_CHECK_MODES, n as BUILTIN_AGENT_IDS, p as DEFAULT_FACTORY_PROTECTED_PATHS, s as RUNTIME_CONFIG_SCALAR_KEYS, t as AGENT_ID_SHAPE_MESSAGE, u as BranchGcFileSettings, w as CHANGE_MAP_NARRATOR_TIMEOUT_RANGE, x as USAGE_COST_MODES, z as TASK_TITLE_TIMEOUT_RANGE } from "./config-CuZ16F9W.js";
7
- import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-BLZAOP57.js";
6
+ import { A as FLYING_ANIMALS_GAP_RANGE, B as REPLAY_BUFFER_KB_RANGE, C as USAGE_COST_MODES, D as FACTORY_MAX_LIVE_WORKERS_RANGE, E as CHANGE_MAP_NARRATOR_TIMEOUT_RANGE, F as POSITIVE_NUMBER_RANGE, G as USAGE_SCAN_INTERVAL_RANGE, H as USAGE_BUDGET_RANGE, I as POSTHOG_FIX_TIMEOUT_RANGE, K as WORKFLOWS_MAX_ACTIONS_PER_POLL_RANGE, L as POSTHOG_TRAFFIC_BASELINE_RANGE, M as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, N as NON_NEGATIVE_NUMBER_RANGE, O as FLYING_ANIMALS_DEFAULTS, P as PORT_RANGE, R as POSTHOG_TRAFFIC_MIN_USERS_RANGE, T as normalizeLegacyConfigNumbers, U as USAGE_INTEGER_RANGES, V as TASK_TITLE_TIMEOUT_RANGE, W as USAGE_RETAIN_DAYS_RANGE, _ as UPDATE_CHANNELS, c as RUNTIME_CONFIG_SCALAR_KEYS, d as BranchGcFileSettings, f as CHANGE_MAP_NARRATOR_ENGINES, g as POST_TURN_CHECK_MODES, i as Config, j as FLYING_ANIMALS_SCALE_RANGE, k as FLYING_ANIMALS_DURATION_RANGE, m as DEFAULT_FACTORY_PROTECTED_PATHS, n as BUILTIN_AGENT_IDS, p as DEFAULT_FACTORY_CHECKS, q as WORKFLOWS_MAX_CONCURRENT_SESSIONS_RANGE, t as AGENT_ID_SHAPE_MESSAGE, u as configIssueMessage, z as POSTHOG_TRAFFIC_MULTIPLIER_RANGE } from "./config-BYc2z1Oc.js";
7
+ import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-C6ipN_zw.js";
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import os from "node:os";
@@ -264,7 +264,7 @@ var POSTHOG_INGEST_HOST = "https://us.i.posthog.com";
264
264
  var TELEMETRY_BATCH_URL = `${POSTHOG_INGEST_HOST}/batch/`;
265
265
  var TELEMETRY_FLAGS_URL = `${POSTHOG_INGEST_HOST}/flags?v=2`;
266
266
  var MAX_STACK_LENGTH = 16384;
267
- var FIRST_RUN_NOTICE = ["Glimmervoid sends anonymous usage and error data to help improve it: app starts, daily activity, session starts and ends with the agent kind, exit kind and duration, errors as their type, error code and scrubbed stack frames, per session token counts, models and estimated cost, and factory outcomes as the kind of decision, how it came out, its duration and attempt number. No error messages, paths, repository names, prompts, objectives, model output or terminal output.", "Turn it off in Settings > Privacy, or set GLIMMERVOID_TELEMETRY=0 or DO_NOT_TRACK=1."].join("\n");
267
+ var FIRST_RUN_NOTICE = ["Anonymous usage data is on. Never paths, prompts or output. Details: https://github.com/johncwaters/glimmervoid/blob/main/docs/configuration.md#telemetry", "Turn it off in Settings > Privacy, or GLIMMERVOID_TELEMETRY=0."].join("\n");
268
268
  var TRUTHY_FLAGS = /* @__PURE__ */ new Set([
269
269
  "1",
270
270
  "true",
@@ -1003,7 +1003,7 @@ var SECTIONS = Object.freeze([
1003
1003
  id: "auto-resume",
1004
1004
  path: "autoResume",
1005
1005
  title: "Auto-resume sessions on startup",
1006
- description: "Resume conversations that were live when Glimmervoid last shut down or crashed.",
1006
+ description: "Resume conversations that were live when Glimmervoid last shut down or crashed, and tell sessions that were mid-turn to continue.",
1007
1007
  control: "toggle",
1008
1008
  keywords: ["startup", "conversation"],
1009
1009
  defaultValue: true,
@@ -1013,7 +1013,7 @@ var SECTIONS = Object.freeze([
1013
1013
  id: "conversation-view",
1014
1014
  path: "conversationView",
1015
1015
  title: "Conversation view (experimental)",
1016
- description: "Let each Claude Code and Codex session turn on a Conversation face from its card menu, which renders the transcript as messages, approvals and a composer. Sessions stay on the terminal until you turn it on for them. A Codex session connects on its next start, through a local app-server so approvals can be answered from the dashboard; sandboxed Codex sessions and those that bypass Codex hook trust keep the terminal only.",
1016
+ description: "Let each Claude Code and Codex session turn on a Conversation face from its card menu, which renders the transcript as messages, approvals and a composer. Sessions stay on the terminal until you turn it on for them. A Claude Code session started while this is on can answer its permission prompts and questions there. A Codex session connects on its next start, through a local app-server so approvals can be answered from the dashboard; guarded Codex sessions and those that bypass Codex hook trust keep the terminal only.",
1017
1017
  control: "toggle",
1018
1018
  keywords: [
1019
1019
  "experimental",
@@ -1628,7 +1628,7 @@ var SECTIONS = Object.freeze([
1628
1628
  id: "team-review-keep-mergeable-enabled",
1629
1629
  path: "teamReview.keepMergeableEnabled",
1630
1630
  title: "Keep mergeable",
1631
- description: "Offer Keep mergeable on your pull requests: a sandboxed agent repairs conflicts and failing checks and pushes the repair. Off hides the control and starts no repair; the pull requests you chose stay chosen for when you turn it back on.",
1631
+ description: "Offer Keep mergeable on your pull requests: a guarded agent repairs conflicts and failing checks and pushes the repair. Off hides the control and starts no repair; the pull requests you chose stay chosen for when you turn it back on.",
1632
1632
  control: "toggle",
1633
1633
  keywords: [
1634
1634
  "repair",
@@ -1704,7 +1704,7 @@ var SECTIONS = Object.freeze([
1704
1704
  id: "workflows-rules",
1705
1705
  path: "status:workflow-rules",
1706
1706
  title: "Workflow rules",
1707
- description: "Each rule watches repositories for one pull request event (opened, checks-failed, review-requested, approved, commented or merged), narrows it by author, labels, base branch, your own pull requests or a review request to your team, and then notifies you, labels or comments on the pull request, or starts a sandboxed agent session that pushes nothing. Rules start disabled. Turn each rule on or off here; everything else about a rule is set in config.json under workflows.rules.",
1707
+ description: "Each rule watches repositories for one pull request event (opened, checks-failed, review-requested, approved, commented or merged), narrows it by author, labels, base branch, your own pull requests or a review request to your team, and then notifies you, labels or comments on the pull request, or starts a guarded agent session that pushes nothing. Rules start disabled. Turn each rule on or off here; everything else about a rule is set in config.json under workflows.rules.",
1708
1708
  control: "readonly",
1709
1709
  keywords: [
1710
1710
  "pull requests",
@@ -0,0 +1 @@
1
+ export { s as loadConfigFile } from "./config-store-B7MpiYxG.js";
@@ -1,5 +1,5 @@
1
- import { A as MyPrKeepMergeableResult, D as LinkedPr, Dt as GithubPollingRefreshRequest, E as TaskTitle, F as MyPrMergeWhenReadyRequest, G as CommitSha, H as MyPrsStatus, I as MyPrMergeWhenReadyResult, M as MyPrMergeRequest, N as MyPrMergeResult, Ot as GithubPollingRefreshResult, S as SessionState, Tt as REPO_SLUG_RE, U as SessionPrLinks, _ as SESSION_DOC_PATH_MAX_CHARS, b as SessionDoc, ct as TeamReviewActionResult, d as ConversationApprovalDecision, ft as TeamReviewStatus, k as MyPrKeepMergeableRequest, kt as githubPollingShape, p as PendingWakeup, st as TeamReviewActionRequest, u as ConversationApproval, vt as hasRequiredActionHead, x as SessionSnapshot } from "./session-B8RhqQJe.js";
2
- import { J as CoherenceRisk, K as CoherenceOrient, Q as CoherenceWorkState, n as BUILTIN_AGENT_IDS, q as CoherenceReadiness } from "./config-CuZ16F9W.js";
1
+ import { D as SessionDoc, Dt as hasRequiredActionHead, G as MyPrMergeWhenReadyResult, H as MyPrMergeResult, It as GithubPollingRefreshRequest, Lt as GithubPollingRefreshResult, N as TaskTitle, O as SessionSnapshot, P as LinkedPr, Pt as REPO_SLUG_RE, Q as SessionPrLinks, R as MyPrKeepMergeableRequest, Rt as githubPollingShape, V as MyPrMergeRequest, W as MyPrMergeWhenReadyRequest, Z as MyPrsStatus, _ as ConversationApprovalDecision, _t as TeamReviewActionResult, b as PendingWakeup, et as CommitSha, g as ConversationApproval, gt as TeamReviewActionRequest, h as ConversationAnswers, k as SessionState, w as SESSION_DOC_PATH_MAX_CHARS, xt as TeamReviewStatus, z as MyPrKeepMergeableResult } from "./session-BZbariv5.js";
2
+ import { J as CoherenceOrient, X as CoherenceRisk, Y as CoherenceReadiness, et as CoherenceWorkState, h as FactorySettings, n as BUILTIN_AGENT_IDS } from "./config-BYc2z1Oc.js";
3
3
  import { z } from "zod";
4
4
  //#region shared/contracts/factory.ts
5
5
  var FactoryConsequences = z.looseObject({ records: z.array(z.looseObject({
@@ -15,6 +15,7 @@ var FactoryConsequences = z.looseObject({ records: z.array(z.looseObject({
15
15
  session: z.string().optional(),
16
16
  evidence: z.string().optional()
17
17
  })) });
18
+ var confirmedFlakes = z.array(z.string().min(1)).max(256);
18
19
  var FactoryProjectState = z.object({
19
20
  projectId: z.string(),
20
21
  projectName: z.string(),
@@ -34,6 +35,12 @@ var FactoryProjectState = z.object({
34
35
  spentTodayUsd: z.number().finite().nonnegative().optional(),
35
36
  dailyBudgetUsd: z.number().finite().nonnegative().nullable().optional(),
36
37
  verifierIntentIds: z.array(z.string()).optional(),
38
+ confirmedFlakesByIntent: z.record(z.string().min(1), confirmedFlakes).optional(),
39
+ partialIntentIds: z.array(z.string()).optional(),
40
+ factoryProfile: FactorySettings.unwrap().unwrap().pick({ checks: true }).extend({
41
+ focusedTestCommand: z.string().trim().min(1).optional(),
42
+ widenableScopes: z.array(z.string().trim().min(1)).optional()
43
+ }).optional(),
37
44
  error: z.string().nullable(),
38
45
  heading: z.object({
39
46
  action: CoherenceOrient.shape.action,
@@ -52,6 +59,9 @@ var FactoryProjectState = z.object({
52
59
  dependsOn: z.array(z.string()),
53
60
  writeScopes: z.array(z.string()),
54
61
  owner: z.string().nullable(),
62
+ blockReason: z.string().nullable().optional(),
63
+ parked: z.boolean().optional(),
64
+ blockCount: z.number().int().nonnegative().optional(),
55
65
  lastEvent: z.object({
56
66
  event: z.string(),
57
67
  at: z.string(),
@@ -79,7 +89,11 @@ var FactoryHarnessStateLine = z.object({
79
89
  state: FactoryState
80
90
  });
81
91
  var FactoryHarnessVerdict = z.looseObject({
82
- outcome: z.enum(["pass", "fail"]),
92
+ outcome: z.enum([
93
+ "pass",
94
+ "partial",
95
+ "fail"
96
+ ]),
83
97
  failureClass: z.string().nullable().optional()
84
98
  });
85
99
  var FACTORY_ERROR_MAX_CHARS = 16384;
@@ -141,12 +155,22 @@ var FactoryQueueIntentResult = z.object({
141
155
  });
142
156
  var FactoryControlRequest = z.object({
143
157
  projectId,
144
- action: z.enum(["pause", "resume"])
158
+ action: z.enum([
159
+ "pause",
160
+ "resume",
161
+ "retry-parked",
162
+ "rerun-setup"
163
+ ]),
164
+ intentId: z.string().trim().min(1).max(128).optional()
165
+ }).refine((request) => request.action !== "retry-parked" || request.intentId !== void 0, {
166
+ message: "Retry parked requires an intentId",
167
+ path: ["intentId"]
145
168
  });
146
169
  var FactoryControlResult = z.object({
147
170
  projectId: z.string().max(128),
148
171
  action: FactoryControlRequest.shape.action,
149
172
  ok: z.boolean(),
173
+ reopenedWorkIds: z.array(z.string().min(1)).optional(),
150
174
  error: z.string().max(FACTORY_ERROR_MAX_CHARS).optional()
151
175
  });
152
176
  var FactoryReviewVerdict = z.object({
@@ -181,6 +205,8 @@ var FactoryLaneState = z.object({
181
205
  trustedIntentIds: z.array(z.string().min(1)).optional(),
182
206
  intentWriteScopes: z.record(z.string().min(1), z.array(z.string().min(1))).optional(),
183
207
  intentFloorAllowances: z.record(z.string().min(1), floorAllowances).optional(),
208
+ intentConfirmedFlakes: z.record(z.string().min(1), confirmedFlakes).optional(),
209
+ intentScopeNeeds: z.record(z.string().min(1), z.array(z.string().min(1)).max(256)).optional(),
184
210
  ticketedIntentIds: z.array(z.string().min(1)).optional(),
185
211
  pendingIntentTickets: z.record(z.string().min(1), z.object({
186
212
  risk: CoherenceRisk,
@@ -191,7 +217,7 @@ var FactoryLaneState = z.object({
191
217
  factoryLandedShas: z.array(z.string().regex(/^[a-f0-9]{40,64}$/)).optional(),
192
218
  unlandedFactoryRecords: z.array(FactoryUnlandedRecord).optional(),
193
219
  ticketBlockCounts: z.record(z.string().min(1), z.number().int().nonnegative()).optional(),
194
- intentCapCancelCounts: z.record(z.string().min(1), z.number().int().nonnegative()).optional()
220
+ notifiedIntentOutcomes: z.array(z.string().min(1)).optional()
195
221
  });
196
222
  var FactoryWorkerEvent = z.object({
197
223
  workId: z.string().min(1),
@@ -269,7 +295,7 @@ var decisionFields = {
269
295
  attempt: z.number().int().positive().nullable(),
270
296
  durationMs: z.number().int().nonnegative().nullable(),
271
297
  failureClass: FactoryDecisionFailureClass.nullable(),
272
- reason: z.string().max(1e3).nullable()
298
+ reason: z.string().max(3999).nullable()
273
299
  };
274
300
  var FactoryDecisionLogLine = z.discriminatedUnion("kind", [
275
301
  z.strictObject({
@@ -1276,6 +1302,7 @@ var SessionCardFields = z.object({
1276
1302
  saneYolo: z.boolean(),
1277
1303
  worktree: z.boolean(),
1278
1304
  workspace: z.boolean().optional(),
1305
+ guarded: z.boolean().optional(),
1279
1306
  resumeSessionId: nullableString,
1280
1307
  ephemeral: z.boolean().optional(),
1281
1308
  linkedPrs: z.array(LinkedPr).optional()
@@ -1400,8 +1427,14 @@ var clientVariants = [
1400
1427
  settings: z.record(z.string(), z.unknown()),
1401
1428
  requestId
1402
1429
  }),
1403
- loose("scan-repo-roots", { requestId }),
1404
- loose("list-agents", { requestId }),
1430
+ loose("scan-repo-roots", {
1431
+ requestId,
1432
+ includeSuggestions: z.boolean().optional()
1433
+ }),
1434
+ loose("list-agents", {
1435
+ requestId,
1436
+ rescan: z.boolean().optional()
1437
+ }),
1405
1438
  loose("get-radar-report", {
1406
1439
  issueId: z.union([z.string(), z.number()]),
1407
1440
  requestId
@@ -1519,7 +1552,8 @@ var clientVariants = [
1519
1552
  loose("conversation-approval", {
1520
1553
  id: sessionId,
1521
1554
  requestId: ConversationApproval.shape.requestId,
1522
- decision: ConversationApprovalDecision
1555
+ decision: ConversationApprovalDecision,
1556
+ answers: ConversationAnswers.optional()
1523
1557
  }),
1524
1558
  loose("session-doc-read", {
1525
1559
  id: sessionId,
@@ -1918,6 +1952,11 @@ var serverVariants = [
1918
1952
  path: z.string()
1919
1953
  }))
1920
1954
  })),
1955
+ suggestions: z.array(openObject({
1956
+ path: z.string(),
1957
+ label: z.string(),
1958
+ gitRepoCount: z.number().int().nonnegative()
1959
+ })).optional(),
1921
1960
  error: z.string().optional()
1922
1961
  }),
1923
1962
  loose("conversations", {