glimmervoid 0.31.0 → 0.32.1

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 (39) hide show
  1. package/dist/bin/glimmervoid.js +19 -14
  2. package/dist/chunks/{adapters-gn7ulNO4.js → adapters-BS_7o8fj.js} +28 -23
  3. package/dist/chunks/{adapters-ClA_GbtA.js → adapters-Bn-dQ02i.js} +1 -1
  4. package/dist/chunks/{agent-api-cli-DAA7Jx8N.js → agent-api-cli-BR0GVDn6.js} +21 -5
  5. package/dist/chunks/agent-api-core-DUiWHSHg.js +201 -0
  6. package/dist/chunks/{agent-setup-cli-CiJSDWSo.js → agent-setup-cli-BqYcwfOs.js} +1 -1
  7. package/dist/chunks/child-process-safe-B3zcPdFM.js +2 -0
  8. package/dist/chunks/{child-process-safe-Ch-Zgxqs.js → child-process-safe-DDELk9XC.js} +2 -1
  9. package/dist/chunks/{config-W1Sv-iPK.js → config-B6BkTOcE.js} +20 -6
  10. package/dist/chunks/config-store-C8Ry8ZFD.js +2 -0
  11. package/dist/chunks/{config-store-BCy4FHNG.js → config-store-aZpWeX92.js} +14 -5
  12. package/dist/chunks/{contracts-3LkrilQX.js → contracts-DzDg-Z9I.js} +100 -7
  13. package/dist/chunks/git-version-CrLW4a6r.js +58 -0
  14. package/dist/chunks/{grok-CXKeSt2z.js → grok-7Z5KcgcY.js} +1 -2
  15. package/dist/chunks/{knowledge-graph-cli-D2tt5hPn.js → knowledge-graph-cli-D5Gf87Y7.js} +2 -2
  16. package/dist/chunks/{main-DyTCWIu2.js → main-BG6iHwoY.js} +3724 -1928
  17. package/dist/chunks/{pair-cli-BbCBfd6l.js → pair-cli-DQkrt_-s.js} +2 -2
  18. package/dist/chunks/{remote-config-DKIH_VxM.js → remote-config-Da4C7tMG.js} +2 -2
  19. package/dist/chunks/rtk-resolver-CIVLE_xk.js +2 -0
  20. package/dist/chunks/{rtk-resolver-BGDzw5XK.js → rtk-resolver-jJxy_Mrt.js} +1 -1
  21. package/dist/chunks/{sandbox-deps-BPKE-ylr.js → sandbox-deps-DuaNFq7n.js} +1 -1
  22. package/dist/chunks/{session-fc4pFbon.js → session-Dtkp9o3r.js} +28 -2
  23. package/dist/chunks/{visions-cli-CT5rjiwf.js → visions-cli-BhFdym5n.js} +1 -1
  24. package/dist/chunks/{visions-setup-BmOkI-QE.js → visions-setup-CfgNHiG3.js} +1 -1
  25. package/dist/client/assets/index-BxU3Ww0L.css +1 -0
  26. package/dist/client/assets/index-Co4S7tnh.js +254 -0
  27. package/dist/client/index.html +2 -2
  28. package/dist/scripts/postinstall-path-check.js +1 -1
  29. package/dist/server/index.js +1 -1
  30. package/dist/session/hook-tool-relay.js +1 -1
  31. package/dist/session/sandbox-open-launcher.js +42 -3
  32. package/dist/session/statusline-relay.js +1 -1
  33. package/package.json +1 -1
  34. package/dist/chunks/agent-api-core-hVcT26JW.js +0 -112
  35. package/dist/chunks/child-process-safe-BKPZ-5qQ.js +0 -2
  36. package/dist/chunks/config-store-DbBp7LJZ.js +0 -2
  37. package/dist/chunks/rtk-resolver-D4Nke1Fr.js +0 -2
  38. package/dist/client/assets/index-C6KD8lgZ.css +0 -1
  39. package/dist/client/assets/index-CThQEAEy.js +0 -249
@@ -2,11 +2,12 @@
2
2
  import { o as nodePtyRebuildHint, r as firstLine, t as probeNodePty } from "../chunks/node-pty-preflight-C8QIlrtU.js";
3
3
  import { i as errorText } from "../chunks/text-DoirglWV.js";
4
4
  import { a as packageRoot } from "../chunks/runtime-paths-BPoxENmK.js";
5
- import { t as AGENT_API_VERBS } from "../chunks/session-fc4pFbon.js";
6
- import { i as execSync } from "../chunks/child-process-safe-Ch-Zgxqs.js";
5
+ import { t as AGENT_API_VERBS } from "../chunks/session-Dtkp9o3r.js";
6
+ import { i as execSync } from "../chunks/child-process-safe-DDELk9XC.js";
7
7
  import { t as renderTable } from "../chunks/ascii-figure-core-pDAwtlKO.js";
8
8
  import { n as glimmervoidHomeDir, t as decideConfigPath } from "../chunks/config-path-core-DFt-TemS.js";
9
- import { i as sandboxDoctorRows, r as probeSandboxDependencies } from "../chunks/sandbox-deps-BPKE-ylr.js";
9
+ import { i as sandboxDoctorRows, r as probeSandboxDependencies } from "../chunks/sandbox-deps-DuaNFq7n.js";
10
+ import { r as gitDoctorRows, t as probeGitVersion } from "../chunks/git-version-CrLW4a6r.js";
10
11
  import { i as pnpmGlobalBinDir, n as npmGlobalBinDir, r as onPath, t as formatPathNotice } from "../chunks/path-doctor-C23VAqeu.js";
11
12
  import fs from "node:fs";
12
13
  import path from "node:path";
@@ -106,6 +107,8 @@ Commands:
106
107
  spawn <prompt> From inside a Glimmervoid session, start a sibling session on that prompt
107
108
  attention <note> From inside a Glimmervoid session, flag it as needing the operator
108
109
  board From inside a Glimmervoid session, list the live sessions
110
+ push From inside a Glimmervoid session, land its commits on the integration branch and push it
111
+ edit <path> From inside a Glimmervoid session, surface a text file for the operator to edit in the dashboard
109
112
  kg [command] Experimental typed knowledge and task graph (Settings > Lanes > Knowledge graph)
110
113
 
111
114
  Options:
@@ -131,23 +134,23 @@ var SUBCOMMAND_RUNNERS = new Map([
131
134
  return 0;
132
135
  }],
133
136
  ["pair", async (subcommandArgs) => {
134
- const { runPairCli } = await import("../chunks/pair-cli-BbCBfd6l.js");
137
+ const { runPairCli } = await import("../chunks/pair-cli-DQkrt_-s.js");
135
138
  return runPairCli(subcommandArgs);
136
139
  }],
137
140
  ["agent", async (subcommandArgs) => {
138
- const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-CiJSDWSo.js");
141
+ const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-BqYcwfOs.js");
139
142
  return runAgentSetupCli(subcommandArgs);
140
143
  }],
141
144
  ["kg", async (subcommandArgs) => {
142
- const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-D2tt5hPn.js");
145
+ const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-D5Gf87Y7.js");
143
146
  return runKnowledgeGraphCommand(subcommandArgs);
144
147
  }],
145
148
  ["visions", async (subcommandArgs) => {
146
- const { runVisionsCli } = await import("../chunks/visions-cli-CT5rjiwf.js");
149
+ const { runVisionsCli } = await import("../chunks/visions-cli-BhFdym5n.js");
147
150
  return runVisionsCli(subcommandArgs);
148
151
  }],
149
152
  ...AGENT_API_VERBS.map((verb) => [verb, async (subcommandArgs, subcommandName) => {
150
- const { runAgentApiCli } = await import("../chunks/agent-api-cli-DAA7Jx8N.js");
153
+ const { runAgentApiCli } = await import("../chunks/agent-api-cli-BR0GVDn6.js");
151
154
  return runAgentApiCli([subcommandName, ...subcommandArgs]);
152
155
  }])
153
156
  ]);
@@ -201,7 +204,7 @@ async function readDeclaredCustomAgents() {
201
204
  declared: [],
202
205
  error: null
203
206
  };
204
- const { loadConfigFile } = await import("../chunks/config-store-DbBp7LJZ.js");
207
+ const { loadConfigFile } = await import("../chunks/config-store-C8Ry8ZFD.js");
205
208
  try {
206
209
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
207
210
  if (!loaded.config) return {
@@ -277,7 +280,7 @@ async function runDoctor() {
277
280
  }
278
281
  switchSection("Agents");
279
282
  try {
280
- const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-ClA_GbtA.js");
283
+ const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-Bn-dQ02i.js");
281
284
  const declaredCustomAgents = await readDeclaredCustomAgents();
282
285
  if (declaredCustomAgents.error) line("config", declaredCustomAgents.error);
283
286
  setCustomAgents(declaredCustomAgents.declared);
@@ -285,7 +288,7 @@ async function runDoctor() {
285
288
  const { label, path: resolvedPath } = describeAgentResolvability(id);
286
289
  line(`${id} (${label})`, resolvedPath ?? "not found on PATH");
287
290
  }
288
- const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-CiJSDWSo.js");
291
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-BqYcwfOs.js");
289
292
  const grokSetup = inspectGrokAgentSetup();
290
293
  line("grok hook setup", `${grokSetup.classification}: ${grokSetup.filePath}`);
291
294
  } catch (err) {
@@ -293,7 +296,7 @@ async function runDoctor() {
293
296
  }
294
297
  switchSection("rtk");
295
298
  try {
296
- const { getRtkPath } = await import("../chunks/rtk-resolver-D4Nke1Fr.js");
299
+ const { getRtkPath } = await import("../chunks/rtk-resolver-CIVLE_xk.js");
297
300
  line("rtk", getRtkPath() || "not installed (Glimmervoid installs it when the rtk setting is on)");
298
301
  } catch (err) {
299
302
  line("rtk", `probe failed: ${firstLine(errorText(err))}`);
@@ -301,8 +304,8 @@ async function runDoctor() {
301
304
  switchSection("Sane YOLO");
302
305
  try {
303
306
  const { resolvePackageBin } = await import("../chunks/runtime-paths-DU5jBEEO.js");
304
- const { execFileSync } = await import("../chunks/child-process-safe-BKPZ-5qQ.js");
305
- const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-CiJSDWSo.js");
307
+ const { execFileSync } = await import("../chunks/child-process-safe-B3zcPdFM.js");
308
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-BqYcwfOs.js");
306
309
  const binPath = resolvePackageBin("cc-safety-net", "cc-safety-net");
307
310
  line("Sane YOLO", binPath || "not installed");
308
311
  if (binPath) line("cc-safety-net version", execFileSync(process.execPath, [binPath, "--version"], {
@@ -327,6 +330,8 @@ async function runDoctor() {
327
330
  platform,
328
331
  exec: execSync
329
332
  }))) line(label, value);
333
+ switchSection("Git");
334
+ for (const [label, value] of gitDoctorRows(probeGitVersion())) line(label, value);
330
335
  switchSection("Config");
331
336
  line("resolved config", resolveConfigPathReadOnly());
332
337
  flush();
@@ -1,27 +1,13 @@
1
1
  import { o as relayPath } from "./runtime-paths-BPoxENmK.js";
2
- import { _ as firstDetailLine, l as PendingPromptQuestion, s as PROMPT_DETAIL_HIDDEN_CHARACTERS, v as toolDetailFieldValue } from "./session-fc4pFbon.js";
3
- import { r as execFileSync } from "./child-process-safe-Ch-Zgxqs.js";
2
+ import { C as firstDetailLine, f as PendingPromptQuestion, u as PROMPT_DETAIL_HIDDEN_CHARACTERS, w as toolDetailFieldValue } from "./session-Dtkp9o3r.js";
3
+ import { r as execFileSync } from "./child-process-safe-DDELk9XC.js";
4
4
  import { n as resolveAgentCommand, t as buildAgentSpawnCommand } from "./spawn-command-Cc40FiZI.js";
5
5
  import { n as isRecord } from "./coerce-NSst8oRP.js";
6
- import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-CXKeSt2z.js";
6
+ import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-7Z5KcgcY.js";
7
7
  import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
8
- import "./contracts-3LkrilQX.js";
8
+ import "./contracts-DzDg-Z9I.js";
9
9
  import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-UX2fmt81.js";
10
10
  import fs from "node:fs";
11
- //#region session/core/anti-slop-prompt.ts
12
- var ANTI_SLOP_NOTE = [
13
- "Code hygiene for this session:",
14
- "Write comments only to explain why, never narration that restates the code (no Now-we, This-function, or Step-1 openers).",
15
- "Do not leave debug statements (console.log, print, debugger) in committed code.",
16
- "Never swallow exceptions: no empty catch blocks and no catch that only logs and continues.",
17
- "No placeholder stubs or in-a-real-implementation hand-waving; implement the real thing or stop and ask.",
18
- "Do not silence type or lint errors with as-any, ts-ignore, or eslint-disable; fix the cause.",
19
- "Avoid speculative wrappers and single-use indirection. Prefer deleting code over adding it."
20
- ].join(" ");
21
- function buildAntiSlopArgs(enabled) {
22
- return enabled ? ["--append-system-prompt", ANTI_SLOP_NOTE] : [];
23
- }
24
- //#endregion
25
11
  //#region session/adapters/claude-code.ts
26
12
  var ID$1 = "claude-code";
27
13
  var COMMAND_NAME$1 = "claude";
@@ -175,7 +161,29 @@ function buildEnv$1(baseEnv, extraEnv, options) {
175
161
  return buildAgentEnv(baseEnv, extraEnv, envProfile$2, options);
176
162
  }
177
163
  var settingsArgs = (settingsPath) => ["--settings", settingsPath];
178
- function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], antiSlopPrompt = false, initialPrompt = null } = {}) {
164
+ var SESSION_ID_FLAG = "--session-id";
165
+ function requestedSessionId(extraArgs) {
166
+ const flagIndex = extraArgs.indexOf(SESSION_ID_FLAG);
167
+ if (flagIndex !== -1) return extraArgs[flagIndex + 1] ?? null;
168
+ const assignment = extraArgs.find((argument) => argument.startsWith(`${SESSION_ID_FLAG}=`));
169
+ return assignment ? assignment.slice(13) : null;
170
+ }
171
+ function launchSessionId({ resumeSessionId, extraArgs, generatedId }) {
172
+ const knownSessionId = resumeSessionId ?? requestedSessionId(extraArgs);
173
+ if (knownSessionId) return {
174
+ agentSessionId: knownSessionId,
175
+ extraArgs: [...extraArgs]
176
+ };
177
+ return {
178
+ agentSessionId: generatedId,
179
+ extraArgs: [
180
+ ...extraArgs,
181
+ SESSION_ID_FLAG,
182
+ generatedId
183
+ ]
184
+ };
185
+ }
186
+ function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = null, extraArgs = [], initialPrompt = null } = {}) {
179
187
  const args = dangerouslySkipPermissions ? ["--dangerously-skip-permissions"] : [];
180
188
  if (resumeSessionId) args.push("--resume", resumeSessionId);
181
189
  for (let index = 0; index < extraArgs.length; index += 1) {
@@ -187,7 +195,6 @@ function buildArgs$1({ dangerouslySkipPermissions = false, resumeSessionId = nul
187
195
  if (resumeSessionId && argument.startsWith("--session-id=")) continue;
188
196
  args.push(argument);
189
197
  }
190
- args.push(...buildAntiSlopArgs(antiSlopPrompt));
191
198
  if (initialPrompt != null) args.push(initialPrompt);
192
199
  return args;
193
200
  }
@@ -204,6 +211,7 @@ var claudeCode = {
204
211
  buildEnv: buildEnv$1,
205
212
  buildArgs: buildArgs$1,
206
213
  settingsArgs,
214
+ launchSessionId,
207
215
  capabilities: {
208
216
  hooks: true,
209
217
  awaitingInput: true,
@@ -212,7 +220,6 @@ var claudeCode = {
212
220
  statusLine: true,
213
221
  rtk: true,
214
222
  saneYolo: true,
215
- antiSlop: true,
216
223
  compactQuiet: true,
217
224
  skipPermissionsFlag: true,
218
225
  headless: true
@@ -407,7 +414,6 @@ var codex = {
407
414
  statusLine: false,
408
415
  rtk: true,
409
416
  saneYolo: true,
410
- antiSlop: false,
411
417
  compactQuiet: false,
412
418
  skipPermissionsFlag: true,
413
419
  headless: true
@@ -427,7 +433,6 @@ var TITLE_ONLY_CAPABILITIES = Object.freeze({
427
433
  statusLine: false,
428
434
  rtk: false,
429
435
  saneYolo: false,
430
- antiSlop: false,
431
436
  compactQuiet: false,
432
437
  skipPermissionsFlag: false,
433
438
  headless: false
@@ -1,2 +1,2 @@
1
- import { a as describeAgentResolvability, d as setCustomAgents, l as listAgentIds } from "./adapters-gn7ulNO4.js";
1
+ import { a as describeAgentResolvability, d as setCustomAgents, l as listAgentIds } from "./adapters-BS_7o8fj.js";
2
2
  export { describeAgentResolvability, listAgentIds, setCustomAgents };
@@ -1,11 +1,16 @@
1
1
  import { t as errorCode } from "./text-DoirglWV.js";
2
- import { a as AgentDispatchRequest, n as AGENT_URL_ENV } from "./session-fc4pFbon.js";
2
+ import { a as AgentDispatchRequest, c as AgentTicketRequest, n as AGENT_URL_ENV } from "./session-Dtkp9o3r.js";
3
3
  import { i as resolveHookTarget } from "./hook-relay-core-DA_bz2KA.js";
4
4
  import { n as decideSandboxProxy } from "./sandbox-proxy-core-hnQgKR0T.js";
5
- import { a as isAgentApiVerb } from "./agent-api-core-hVcT26JW.js";
5
+ import { c as isAgentApiVerb, l as isOrchestratorAgentVerb } from "./agent-api-core-DUiWHSHg.js";
6
+ import path from "node:path";
6
7
  import http from "node:http";
7
8
  //#region server/agent-api-cli.ts
8
9
  var AGENT_PATH_PREFIX = "/agent/";
10
+ function ticketBody(rest) {
11
+ const parsed = AgentTicketRequest.safeParse({ workId: rest[0] });
12
+ return parsed.success ? parsed.data : null;
13
+ }
9
14
  var BODY_BUILDERS = {
10
15
  spawn: (rest) => {
11
16
  const prompt = rest.join(" ").trim();
@@ -16,10 +21,17 @@ var BODY_BUILDERS = {
16
21
  return note ? { note } : null;
17
22
  },
18
23
  board: () => ({}),
24
+ push: () => ({}),
25
+ edit: (rest) => {
26
+ const docPath = rest.join(" ").trim();
27
+ return docPath ? { path: path.resolve(docPath) } : null;
28
+ },
19
29
  dispatch: (rest) => {
20
30
  const parsed = AgentDispatchRequest.safeParse(rest[0] === "--ready" ? { readyIntent: rest[1] } : { workId: rest[0] });
21
31
  return parsed.success ? parsed.data : null;
22
- }
32
+ },
33
+ reopen: (rest) => ticketBody(rest),
34
+ cancel: (rest) => ticketBody(rest)
23
35
  };
24
36
  function bodySaysOk(text) {
25
37
  try {
@@ -110,8 +122,12 @@ async function runAgentApiCli(args) {
110
122
  }
111
123
  const body = BODY_BUILDERS[verb](args.slice(1));
112
124
  if (!body) {
113
- if (verb === "dispatch") {
114
- console.error("glimmervoid dispatch: expected a work id matching wrk-[0-9a-f]{16}");
125
+ if (isOrchestratorAgentVerb(verb)) {
126
+ console.error(`glimmervoid ${verb}: expected a work id matching wrk-[0-9a-f]{16}`);
127
+ return 1;
128
+ }
129
+ if (verb === "edit") {
130
+ console.error("glimmervoid edit: this command needs a file path, for example \"glimmervoid edit drafts/post.md\"");
115
131
  return 1;
116
132
  }
117
133
  console.error(`glimmervoid ${verb}: this command needs text, for example "glimmervoid ${verb} check the failing test"`);
@@ -0,0 +1,201 @@
1
+ import { a as AgentDispatchRequest, i as AgentAttentionRequest, l as ORCHESTRATOR_AGENT_VERBS, o as AgentEditRequest, s as AgentSpawnRequest, t as AGENT_API_VERBS } from "./session-Dtkp9o3r.js";
2
+ import crypto from "node:crypto";
3
+ var MAX_SPAWNS_IN_FLIGHT = 1;
4
+ var SPAWNABLE_DEPTH = 0;
5
+ var REFUSAL_REASON = "unknown session";
6
+ var INVALID_BODY_STATUS = 400;
7
+ var PUSH_REFUSED_STATUS = 409;
8
+ var PUSH_UNAVAILABLE_REASON = "not-operator-session";
9
+ var PUSH_REFUSAL_COPY = Object.freeze({
10
+ [PUSH_UNAVAILABLE_REASON]: () => "only an operator session or a session it spawned can push",
11
+ "no-worktree": () => "this session has no worktree of its own, so there is nothing of its own to land",
12
+ "merge-in-progress": () => "a merge for this session is already running, so try again when it ends",
13
+ "not-continuable": () => "this session cannot be merged in its current state",
14
+ destroyed: () => "this session is ending",
15
+ "nothing-to-commit": () => "no commit on this branch is missing from the integration branch, so commit your work first",
16
+ "rebase-conflict": ({ base, conflicts = [] }) => `this branch conflicts with ${base} in ${conflicts.join(", ") || "one or more files"}, so rebase onto ${base}, resolve the conflicts, commit, then push again`,
17
+ "not-fast-forward": ({ base }) => `${base} could not be fast-forwarded to this branch, and a push is never forced`,
18
+ "base-diverged": ({ base }) => `the local ${base} and origin/${base} have diverged, which the operator has to reconcile`
19
+ });
20
+ function tokensMatch(presented, expected) {
21
+ if (presented.length !== expected.length) return false;
22
+ try {
23
+ return crypto.timingSafeEqual(Buffer.from(presented, "utf8"), Buffer.from(expected, "utf8"));
24
+ } catch {
25
+ return false;
26
+ }
27
+ }
28
+ function refused() {
29
+ return {
30
+ ok: false,
31
+ status: 404,
32
+ reason: REFUSAL_REASON
33
+ };
34
+ }
35
+ function decideAgentRequest({ sessionId, presentedToken, expectedToken, isLoopback }) {
36
+ if (!isLoopback) return refused();
37
+ if (!sessionId) return refused();
38
+ if (!expectedToken) return refused();
39
+ if (!presentedToken) return refused();
40
+ if (!tokensMatch(presentedToken, expectedToken)) return refused();
41
+ return { ok: true };
42
+ }
43
+ function decideSpawnAllowance({ liveChildren, lifetimeSpawns, inFlight, depth }) {
44
+ if (depth !== SPAWNABLE_DEPTH) return {
45
+ ok: false,
46
+ status: 403,
47
+ reason: "a spawned session may not spawn another"
48
+ };
49
+ if (inFlight >= MAX_SPAWNS_IN_FLIGHT) return {
50
+ ok: false,
51
+ status: 429,
52
+ reason: "a spawn is already in flight"
53
+ };
54
+ if (liveChildren >= 3) return {
55
+ ok: false,
56
+ status: 429,
57
+ reason: `at most 3 spawned sessions may be live at once`
58
+ };
59
+ if (lifetimeSpawns >= 10) return {
60
+ ok: false,
61
+ status: 429,
62
+ reason: `this session has used its 10 spawns`
63
+ };
64
+ return { ok: true };
65
+ }
66
+ function isAgentApiVerb(verb) {
67
+ return AGENT_API_VERBS.includes(verb);
68
+ }
69
+ function isOrchestratorAgentVerb(verb) {
70
+ return ORCHESTRATOR_AGENT_VERBS.includes(verb);
71
+ }
72
+ var TICKET_ACTION_STATES = Object.freeze({
73
+ reopen: Object.freeze(["blocked"]),
74
+ cancel: Object.freeze(["open", "blocked"])
75
+ });
76
+ function decideTicketAction({ verb, intentId, ticket }) {
77
+ if (!ticket) return {
78
+ ok: false,
79
+ reason: "no such ticket"
80
+ };
81
+ if (ticket.parent !== intentId) return {
82
+ ok: false,
83
+ reason: "the ticket is not a child of the active intent"
84
+ };
85
+ const allowed = TICKET_ACTION_STATES[verb];
86
+ if (!allowed.includes(ticket.state)) return {
87
+ ok: false,
88
+ reason: `only a ${allowed.join(" or ")} ticket can be ${verb === "reopen" ? "reopened" : "cancelled"}, and this one is ${ticket.state}`
89
+ };
90
+ if (verb === "reopen") return {
91
+ ok: true,
92
+ kind: "transition",
93
+ to: "open"
94
+ };
95
+ return {
96
+ ok: true,
97
+ kind: "close",
98
+ outcome: "cancelled"
99
+ };
100
+ }
101
+ function refuseInvalidBody(issues) {
102
+ return {
103
+ ok: false,
104
+ status: INVALID_BODY_STATUS,
105
+ error: issues[0]?.message || "invalid request"
106
+ };
107
+ }
108
+ function parseAgentVerb(verb, payload) {
109
+ if (!isAgentApiVerb(verb)) return {
110
+ ok: false,
111
+ status: 404,
112
+ error: REFUSAL_REASON
113
+ };
114
+ if (verb === "dispatch") {
115
+ const parsed = AgentDispatchRequest.safeParse(payload);
116
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
117
+ return {
118
+ ok: true,
119
+ verb,
120
+ request: parsed.data
121
+ };
122
+ }
123
+ if (verb === "reopen" || verb === "cancel") return {
124
+ ok: false,
125
+ status: 403,
126
+ error: `${verb} requires a live factory orchestrator`
127
+ };
128
+ if (verb === "board" || verb === "push") return {
129
+ ok: true,
130
+ verb
131
+ };
132
+ if (verb === "attention") {
133
+ const parsed = AgentAttentionRequest.safeParse(payload);
134
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
135
+ return {
136
+ ok: true,
137
+ verb,
138
+ request: parsed.data
139
+ };
140
+ }
141
+ if (verb === "edit") {
142
+ const parsed = AgentEditRequest.safeParse(payload);
143
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
144
+ return {
145
+ ok: true,
146
+ verb,
147
+ request: parsed.data
148
+ };
149
+ }
150
+ const parsed = AgentSpawnRequest.safeParse(payload);
151
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
152
+ return {
153
+ ok: true,
154
+ verb,
155
+ request: parsed.data
156
+ };
157
+ }
158
+ function describePushLanding(landing) {
159
+ if (!landing.merged) {
160
+ const reason = landing.reason || "unknown";
161
+ const explain = PUSH_REFUSAL_COPY[reason];
162
+ return {
163
+ status: PUSH_REFUSED_STATUS,
164
+ body: {
165
+ ok: false,
166
+ reason,
167
+ error: explain ? explain(landing) : `the merge stopped: ${reason}`
168
+ }
169
+ };
170
+ }
171
+ if (landing.pushed) return {
172
+ status: 200,
173
+ body: {
174
+ ok: true,
175
+ landedOn: landing.base ?? null,
176
+ pushed: true
177
+ }
178
+ };
179
+ return {
180
+ status: 200,
181
+ body: {
182
+ ok: true,
183
+ landedOn: landing.base ?? null,
184
+ pushed: false,
185
+ note: "landed locally and nothing was pushed, because the repository has no origin remote or origin did not take a fast-forward"
186
+ }
187
+ };
188
+ }
189
+ function deriveChildSessionName(parentName, existingNames) {
190
+ const base = `${String(parentName || "").trim() || "session"} agent`;
191
+ const taken = new Set(existingNames);
192
+ let candidate = base;
193
+ let suffix = 1;
194
+ while (taken.has(candidate)) {
195
+ suffix += 1;
196
+ candidate = `${base} ${suffix}`;
197
+ }
198
+ return candidate;
199
+ }
200
+ //#endregion
201
+ export { decideTicketAction as a, isAgentApiVerb as c, decideSpawnAllowance as i, isOrchestratorAgentVerb as l, REFUSAL_REASON as n, deriveChildSessionName as o, decideAgentRequest as r, describePushLanding as s, PUSH_UNAVAILABLE_REASON as t, parseAgentVerb 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-CXKeSt2z.js";
2
+ import { a as classifyGrokHooksFile, o as renderGrokHooksFile, t as grok } from "./grok-7Z5KcgcY.js";
3
3
  import { p as writeTextAtomicSync } from "./json-file-oEH9vt-0.js";
4
4
  import fs from "node:fs";
5
5
  import path from "node:path";
@@ -0,0 +1,2 @@
1
+ import { r as execFileSync } from "./child-process-safe-DDELk9XC.js";
2
+ export { execFileSync };
@@ -13,7 +13,8 @@ function split(rest) {
13
13
  let options;
14
14
  let callback;
15
15
  for (const v of rest) {
16
- if (Array.isArray(v) && v.every((entry) => typeof entry === "string")) args = v;
16
+ if (Array.isArray(v) && !v.every((entry) => typeof entry === "string")) throw new TypeError("command arguments must all be strings");
17
+ if (Array.isArray(v)) args = v;
17
18
  if (typeof v === "function") callback = v;
18
19
  if (v && typeof v === "object" && !Array.isArray(v)) options = v;
19
20
  }
@@ -1,4 +1,4 @@
1
- import { h as TaskTitle } from "./session-fc4pFbon.js";
1
+ import { x as TaskTitle } from "./session-Dtkp9o3r.js";
2
2
  import { n as isRecord } from "./coerce-NSst8oRP.js";
3
3
  import path from "node:path";
4
4
  import { z } from "zod";
@@ -84,8 +84,8 @@ var CoherenceOrient = z.looseObject({
84
84
  })),
85
85
  unsynthesized: z.array(z.unknown())
86
86
  }).nullable(),
87
- consequences: z.looseObject({ unverifiedCompletedWork: z.array(z.string()) }),
88
- verification: z.looseObject({ state: z.string() })
87
+ consequences: z.looseObject({ unverifiedCompletedWork: z.array(z.string()) }).nullable(),
88
+ verification: z.looseObject({ state: z.string() }).nullable()
89
89
  });
90
90
  var CoherenceWorkInspect = z.looseObject({
91
91
  work: z.array(z.looseObject({
@@ -568,6 +568,7 @@ z.object({
568
568
  });
569
569
  var PriorReview = z.object({
570
570
  head: CommitSha,
571
+ base: CommitSha.optional(),
571
572
  verdict: ReviewVerdict,
572
573
  summary: z.string(),
573
574
  body: z.string(),
@@ -670,6 +671,7 @@ var ReviewDraft = z.object({
670
671
  tier: z.enum(["stamp", "full"]),
671
672
  reasons: z.array(z.string()),
672
673
  reviewedHead: CommitSha,
674
+ reviewedBase: CommitSha.optional(),
673
675
  verdict: storedVerdict,
674
676
  summary: z.string(),
675
677
  assessment: ReviewAssessment.optional(),
@@ -1397,7 +1399,8 @@ var FactorySettings = z.object({
1397
1399
  posthogProjectId: z.number().int().positive()
1398
1400
  })).optional(),
1399
1401
  dailyBudgetUsd: z.number().finite().nonnegative().nullable().optional(),
1400
- verifierModel: z.string().trim().min(1).nullable().optional()
1402
+ verifierModel: z.string().trim().min(1).nullable().optional(),
1403
+ mirrorHarnessRuns: optionalBoolean("factory.mirrorHarnessRuns")
1401
1404
  }).nullable().optional();
1402
1405
  var KnowledgeGraphSettings = optionalObject("knowledgeGraph", { enabled: optionalBoolean("knowledgeGraph.enabled") });
1403
1406
  var posthogNumberRanges = {
@@ -1453,6 +1456,14 @@ var PlanReviewSettings = z.object({ enabled: optionalBoolean("planReview.enabled
1453
1456
  var agentApiShape = { enabled: optionalBoolean("agentApi.enabled") };
1454
1457
  var AgentApiSettings = z.object(agentApiShape, { error: "agentApi must be an object" }).strict().optional();
1455
1458
  var AgentApiFileSettings = z.object(agentApiShape, { error: "agentApi must be an object" }).passthrough().optional();
1459
+ 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();
1460
+ var sandboxShape = {
1461
+ unconfinedRepos: optionalPathList("sandbox.unconfinedRepos"),
1462
+ writablePaths: optionalPathList("sandbox.writablePaths"),
1463
+ unreadablePaths: optionalPathList("sandbox.unreadablePaths")
1464
+ };
1465
+ var SandboxSettings = z.object(sandboxShape, { error: "sandbox must be an object" }).strict().optional();
1466
+ var SandboxFileSettings = z.object(sandboxShape, { error: "sandbox must be an object" }).passthrough().optional();
1456
1467
  var telemetryShape = { enabled: optionalBoolean("telemetry.enabled") };
1457
1468
  var TelemetrySettings = z.object(telemetryShape, { error: "telemetry must be an object" }).strict().optional();
1458
1469
  var TelemetryFileSettings = z.object(telemetryShape, { error: "telemetry must be an object" }).passthrough().optional();
@@ -1469,7 +1480,6 @@ var createBrowserConfigShape = (isAbsolutePath) => ({
1469
1480
  calmLayout: optionalBoolean("calmLayout"),
1470
1481
  detectBackgroundAgents: optionalBoolean("detectBackgroundAgents"),
1471
1482
  recordSignals: optionalBoolean("recordSignals"),
1472
- antiSlopPrompt: optionalBoolean("antiSlopPrompt"),
1473
1483
  rtk: optionalBoolean("rtk"),
1474
1484
  saneYolo: optionalBoolean("saneYolo"),
1475
1485
  skipPermissionsByDefault: optionalBoolean("skipPermissionsByDefault"),
@@ -1496,6 +1506,7 @@ var createBrowserConfigShape = (isAbsolutePath) => ({
1496
1506
  telegram: TelegramSettings,
1497
1507
  ingest: IngestSettings,
1498
1508
  agentApi: AgentApiSettings,
1509
+ sandbox: SandboxSettings,
1499
1510
  telemetry: TelemetrySettings,
1500
1511
  workflows: WorkflowsSettings.nullable().optional()
1501
1512
  });
@@ -1591,7 +1602,8 @@ var ProjectConfig = z.object({
1591
1602
  repos: z.array(z.string()).min(2).optional(),
1592
1603
  agent: z.string({ error: "projects[].agent must be a string" }).regex(AGENT_ID_RE, { error: `projects[].agent must be ${AGENT_ID_SHAPE_MESSAGE}` }).optional(),
1593
1604
  codexBypassHookTrust: z.boolean().optional(),
1594
- dangerouslySkipPermissions: z.boolean({ error: "projects[].dangerouslySkipPermissions must be a boolean" }).optional()
1605
+ dangerouslySkipPermissions: z.boolean({ error: "projects[].dangerouslySkipPermissions must be a boolean" }).optional(),
1606
+ unconfined: z.boolean({ error: "projects[].unconfined must be a boolean" }).optional()
1595
1607
  }).passthrough();
1596
1608
  var FILE_CONFIG_SHAPE = {
1597
1609
  ...BROWSER_CONFIG_SHAPE,
@@ -1610,6 +1622,7 @@ var FILE_CONFIG_SHAPE = {
1610
1622
  ingest: optionalLooseObject("ingest"),
1611
1623
  workflows: optionalLooseObject("workflows"),
1612
1624
  agentApi: AgentApiFileSettings,
1625
+ sandbox: SandboxFileSettings,
1613
1626
  telemetry: TelemetryFileSettings,
1614
1627
  trace: TraceSettings,
1615
1628
  planReview: PlanReviewSettings,
@@ -1666,6 +1679,7 @@ var CONFIG_BLOCK_KEYS = Object.freeze([
1666
1679
  "telegram",
1667
1680
  "ingest",
1668
1681
  "agentApi",
1682
+ "sandbox",
1669
1683
  "telemetry",
1670
1684
  "workflows",
1671
1685
  "coder"
@@ -0,0 +1,2 @@
1
+ import { c as loadConfigFile } from "./config-store-aZpWeX92.js";
2
+ export { loadConfigFile };
@@ -3,8 +3,8 @@ import { i as equalsIgnoringCaseOnWindows, t as canonicalizePath } from "./paths
3
3
  import { n as glimmervoidHomeDir$1, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
4
4
  import { a as positiveIntOr, c as textOr, n as isRecord } from "./coerce-NSst8oRP.js";
5
5
  import { d as writeJsonAtomicSync, f as writeTextAtomic, p as writeTextAtomicSync } from "./json-file-oEH9vt-0.js";
6
- import { St as normalizeLegacyConfigNumbers, f as BranchGcFileSettings, i as Config, l as configIssueMessage, m as DEFAULT_FACTORY_PROTECTED_PATHS, n as BUILTIN_AGENT_IDS, p as DEFAULT_FACTORY_CHECKS, s as RUNTIME_CONFIG_SCALAR_KEYS, t as AGENT_ID_SHAPE_MESSAGE } from "./config-W1Sv-iPK.js";
7
- import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-3LkrilQX.js";
6
+ import { St as normalizeLegacyConfigNumbers, f as BranchGcFileSettings, i as Config, l as configIssueMessage, m as DEFAULT_FACTORY_PROTECTED_PATHS, n as BUILTIN_AGENT_IDS, p as DEFAULT_FACTORY_CHECKS, s as RUNTIME_CONFIG_SCALAR_KEYS, t as AGENT_ID_SHAPE_MESSAGE } from "./config-B6BkTOcE.js";
7
+ import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-DzDg-Z9I.js";
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import os from "node:os";
@@ -1111,15 +1111,20 @@ var DEFAULT_CONFIG = {
1111
1111
  watchWindowMinutes: 30,
1112
1112
  watchProjects: [],
1113
1113
  dailyBudgetUsd: null,
1114
- verifierModel: null
1114
+ verifierModel: null,
1115
+ mirrorHarnessRuns: false
1115
1116
  },
1116
1117
  agentApi: { enabled: false },
1118
+ sandbox: {
1119
+ unconfinedRepos: [],
1120
+ writablePaths: ["~/.npm", "~/.cache"],
1121
+ unreadablePaths: []
1122
+ },
1117
1123
  telemetry: { enabled: true },
1118
1124
  checkForUpdates: true,
1119
1125
  updateChannel: "release",
1120
1126
  autoResume: true,
1121
1127
  skipPermissionsByDefault: false,
1122
- antiSlopPrompt: false,
1123
1128
  rtk: false,
1124
1129
  saneYolo: true,
1125
1130
  telegramNotifications: false,
@@ -1517,9 +1522,12 @@ function createConfigStore({ settingsDefaults } = {}) {
1517
1522
  recordSignals: config.recordSignals ?? effectiveDefaults.recordSignals,
1518
1523
  trace: { enabled: config.trace?.enabled ?? DEFAULT_CONFIG.trace.enabled },
1519
1524
  agentApi: { enabled: config.agentApi?.enabled ?? DEFAULT_CONFIG.agentApi.enabled },
1525
+ sandbox: {
1526
+ ...DEFAULT_CONFIG.sandbox,
1527
+ ...config.sandbox
1528
+ },
1520
1529
  telemetry: { enabled: config.telemetry?.enabled ?? DEFAULT_CONFIG.telemetry.enabled },
1521
1530
  telemetryForcedOff: isTelemetryForcedOff(process.env),
1522
- antiSlopPrompt: config.antiSlopPrompt ?? effectiveDefaults.antiSlopPrompt,
1523
1531
  rtk: config.rtk ?? effectiveDefaults.rtk,
1524
1532
  rtkInstallSupported: assetForPlatform(process.platform, process.arch) !== null,
1525
1533
  saneYolo: config.saneYolo ?? effectiveDefaults.saneYolo,
@@ -1592,6 +1600,7 @@ function createConfigStore({ settingsDefaults } = {}) {
1592
1600
  if (newConfig.telegram != null) config.telegram = newConfig.telegram;
1593
1601
  if (newConfig.ingest != null) config.ingest = newConfig.ingest;
1594
1602
  if (newConfig.agentApi != null) config.agentApi = newConfig.agentApi;
1603
+ if (newConfig.sandbox != null) config.sandbox = newConfig.sandbox;
1595
1604
  if (newConfig.telemetry != null) config.telemetry = newConfig.telemetry;
1596
1605
  if (newConfig.workflows == null) delete config.workflows;
1597
1606
  if (newConfig.workflows != null) config.workflows = newConfig.workflows;