glimmervoid 0.31.0 → 0.32.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 (39) hide show
  1. package/dist/bin/glimmervoid.js +18 -14
  2. package/dist/chunks/{adapters-ClA_GbtA.js → adapters-BU74M4QZ.js} +1 -1
  3. package/dist/chunks/{adapters-gn7ulNO4.js → adapters-CoC18rdt.js} +28 -23
  4. package/dist/chunks/{agent-api-cli-DAA7Jx8N.js → agent-api-cli-V_BkYhBI.js} +12 -5
  5. package/dist/chunks/agent-api-core-B3YI8SYs.js +192 -0
  6. package/dist/chunks/{agent-setup-cli-CiJSDWSo.js → agent-setup-cli-D4956BfN.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-CZ4H51D0.js} +20 -6
  10. package/dist/chunks/{config-store-BCy4FHNG.js → config-store-BVtdHkDK.js} +14 -5
  11. package/dist/chunks/config-store-Cp62jN1O.js +2 -0
  12. package/dist/chunks/{contracts-3LkrilQX.js → contracts-DXujp-Zn.js} +60 -7
  13. package/dist/chunks/git-version-CrLW4a6r.js +58 -0
  14. package/dist/chunks/{grok-CXKeSt2z.js → grok-C4lzPFEg.js} +1 -2
  15. package/dist/chunks/{knowledge-graph-cli-D2tt5hPn.js → knowledge-graph-cli-Bjy9_kv5.js} +2 -2
  16. package/dist/chunks/{main-DyTCWIu2.js → main-DSbpYn2Y.js} +3337 -1965
  17. package/dist/chunks/{pair-cli-BbCBfd6l.js → pair-cli-CKn-wUw9.js} +2 -2
  18. package/dist/chunks/{remote-config-DKIH_VxM.js → remote-config-DP44Ybt9.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-B8fJb_Or.js} +19 -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-C_XKsDFx.css +1 -0
  26. package/dist/client/assets/index-CoqWjYxP.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 +1 -1
  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-B8fJb_Or.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,7 @@ 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
109
111
  kg [command] Experimental typed knowledge and task graph (Settings > Lanes > Knowledge graph)
110
112
 
111
113
  Options:
@@ -131,23 +133,23 @@ var SUBCOMMAND_RUNNERS = new Map([
131
133
  return 0;
132
134
  }],
133
135
  ["pair", async (subcommandArgs) => {
134
- const { runPairCli } = await import("../chunks/pair-cli-BbCBfd6l.js");
136
+ const { runPairCli } = await import("../chunks/pair-cli-CKn-wUw9.js");
135
137
  return runPairCli(subcommandArgs);
136
138
  }],
137
139
  ["agent", async (subcommandArgs) => {
138
- const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-CiJSDWSo.js");
140
+ const { runAgentSetupCli } = await import("../chunks/agent-setup-cli-D4956BfN.js");
139
141
  return runAgentSetupCli(subcommandArgs);
140
142
  }],
141
143
  ["kg", async (subcommandArgs) => {
142
- const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-D2tt5hPn.js");
144
+ const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-Bjy9_kv5.js");
143
145
  return runKnowledgeGraphCommand(subcommandArgs);
144
146
  }],
145
147
  ["visions", async (subcommandArgs) => {
146
- const { runVisionsCli } = await import("../chunks/visions-cli-CT5rjiwf.js");
148
+ const { runVisionsCli } = await import("../chunks/visions-cli-BhFdym5n.js");
147
149
  return runVisionsCli(subcommandArgs);
148
150
  }],
149
151
  ...AGENT_API_VERBS.map((verb) => [verb, async (subcommandArgs, subcommandName) => {
150
- const { runAgentApiCli } = await import("../chunks/agent-api-cli-DAA7Jx8N.js");
152
+ const { runAgentApiCli } = await import("../chunks/agent-api-cli-V_BkYhBI.js");
151
153
  return runAgentApiCli([subcommandName, ...subcommandArgs]);
152
154
  }])
153
155
  ]);
@@ -201,7 +203,7 @@ async function readDeclaredCustomAgents() {
201
203
  declared: [],
202
204
  error: null
203
205
  };
204
- const { loadConfigFile } = await import("../chunks/config-store-DbBp7LJZ.js");
206
+ const { loadConfigFile } = await import("../chunks/config-store-Cp62jN1O.js");
205
207
  try {
206
208
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
207
209
  if (!loaded.config) return {
@@ -277,7 +279,7 @@ async function runDoctor() {
277
279
  }
278
280
  switchSection("Agents");
279
281
  try {
280
- const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-ClA_GbtA.js");
282
+ const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-BU74M4QZ.js");
281
283
  const declaredCustomAgents = await readDeclaredCustomAgents();
282
284
  if (declaredCustomAgents.error) line("config", declaredCustomAgents.error);
283
285
  setCustomAgents(declaredCustomAgents.declared);
@@ -285,7 +287,7 @@ async function runDoctor() {
285
287
  const { label, path: resolvedPath } = describeAgentResolvability(id);
286
288
  line(`${id} (${label})`, resolvedPath ?? "not found on PATH");
287
289
  }
288
- const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-CiJSDWSo.js");
290
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-D4956BfN.js");
289
291
  const grokSetup = inspectGrokAgentSetup();
290
292
  line("grok hook setup", `${grokSetup.classification}: ${grokSetup.filePath}`);
291
293
  } catch (err) {
@@ -293,7 +295,7 @@ async function runDoctor() {
293
295
  }
294
296
  switchSection("rtk");
295
297
  try {
296
- const { getRtkPath } = await import("../chunks/rtk-resolver-D4Nke1Fr.js");
298
+ const { getRtkPath } = await import("../chunks/rtk-resolver-CIVLE_xk.js");
297
299
  line("rtk", getRtkPath() || "not installed (Glimmervoid installs it when the rtk setting is on)");
298
300
  } catch (err) {
299
301
  line("rtk", `probe failed: ${firstLine(errorText(err))}`);
@@ -301,8 +303,8 @@ async function runDoctor() {
301
303
  switchSection("Sane YOLO");
302
304
  try {
303
305
  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");
306
+ const { execFileSync } = await import("../chunks/child-process-safe-B3zcPdFM.js");
307
+ const { inspectGrokAgentSetup } = await import("../chunks/agent-setup-cli-D4956BfN.js");
306
308
  const binPath = resolvePackageBin("cc-safety-net", "cc-safety-net");
307
309
  line("Sane YOLO", binPath || "not installed");
308
310
  if (binPath) line("cc-safety-net version", execFileSync(process.execPath, [binPath, "--version"], {
@@ -327,6 +329,8 @@ async function runDoctor() {
327
329
  platform,
328
330
  exec: execSync
329
331
  }))) line(label, value);
332
+ switchSection("Git");
333
+ for (const [label, value] of gitDoctorRows(probeGitVersion())) line(label, value);
330
334
  switchSection("Config");
331
335
  line("resolved config", resolveConfigPathReadOnly());
332
336
  flush();
@@ -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-CoC18rdt.js";
2
2
  export { describeAgentResolvability, listAgentIds, setCustomAgents };
@@ -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 { b as toolDetailFieldValue, d as PendingPromptQuestion, l as PROMPT_DETAIL_HIDDEN_CHARACTERS, y as firstDetailLine } from "./session-B8fJb_Or.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-C4lzPFEg.js";
7
7
  import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
8
- import "./contracts-3LkrilQX.js";
8
+ import "./contracts-DXujp-Zn.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,11 +1,15 @@
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, n as AGENT_URL_ENV, s as AgentTicketRequest } from "./session-B8fJb_Or.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-B3YI8SYs.js";
6
6
  import http from "node:http";
7
7
  //#region server/agent-api-cli.ts
8
8
  var AGENT_PATH_PREFIX = "/agent/";
9
+ function ticketBody(rest) {
10
+ const parsed = AgentTicketRequest.safeParse({ workId: rest[0] });
11
+ return parsed.success ? parsed.data : null;
12
+ }
9
13
  var BODY_BUILDERS = {
10
14
  spawn: (rest) => {
11
15
  const prompt = rest.join(" ").trim();
@@ -16,10 +20,13 @@ var BODY_BUILDERS = {
16
20
  return note ? { note } : null;
17
21
  },
18
22
  board: () => ({}),
23
+ push: () => ({}),
19
24
  dispatch: (rest) => {
20
25
  const parsed = AgentDispatchRequest.safeParse(rest[0] === "--ready" ? { readyIntent: rest[1] } : { workId: rest[0] });
21
26
  return parsed.success ? parsed.data : null;
22
- }
27
+ },
28
+ reopen: (rest) => ticketBody(rest),
29
+ cancel: (rest) => ticketBody(rest)
23
30
  };
24
31
  function bodySaysOk(text) {
25
32
  try {
@@ -110,8 +117,8 @@ async function runAgentApiCli(args) {
110
117
  }
111
118
  const body = BODY_BUILDERS[verb](args.slice(1));
112
119
  if (!body) {
113
- if (verb === "dispatch") {
114
- console.error("glimmervoid dispatch: expected a work id matching wrk-[0-9a-f]{16}");
120
+ if (isOrchestratorAgentVerb(verb)) {
121
+ console.error(`glimmervoid ${verb}: expected a work id matching wrk-[0-9a-f]{16}`);
115
122
  return 1;
116
123
  }
117
124
  console.error(`glimmervoid ${verb}: this command needs text, for example "glimmervoid ${verb} check the failing test"`);
@@ -0,0 +1,192 @@
1
+ import { a as AgentDispatchRequest, c as ORCHESTRATOR_AGENT_VERBS, i as AgentAttentionRequest, o as AgentSpawnRequest, t as AGENT_API_VERBS } from "./session-B8fJb_Or.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
+ const parsed = AgentSpawnRequest.safeParse(payload);
142
+ if (!parsed.success) return refuseInvalidBody(parsed.error.issues);
143
+ return {
144
+ ok: true,
145
+ verb,
146
+ request: parsed.data
147
+ };
148
+ }
149
+ function describePushLanding(landing) {
150
+ if (!landing.merged) {
151
+ const reason = landing.reason || "unknown";
152
+ const explain = PUSH_REFUSAL_COPY[reason];
153
+ return {
154
+ status: PUSH_REFUSED_STATUS,
155
+ body: {
156
+ ok: false,
157
+ reason,
158
+ error: explain ? explain(landing) : `the merge stopped: ${reason}`
159
+ }
160
+ };
161
+ }
162
+ if (landing.pushed) return {
163
+ status: 200,
164
+ body: {
165
+ ok: true,
166
+ landedOn: landing.base ?? null,
167
+ pushed: true
168
+ }
169
+ };
170
+ return {
171
+ status: 200,
172
+ body: {
173
+ ok: true,
174
+ landedOn: landing.base ?? null,
175
+ pushed: false,
176
+ note: "landed locally and nothing was pushed, because the repository has no origin remote or origin did not take a fast-forward"
177
+ }
178
+ };
179
+ }
180
+ function deriveChildSessionName(parentName, existingNames) {
181
+ const base = `${String(parentName || "").trim() || "session"} agent`;
182
+ const taken = new Set(existingNames);
183
+ let candidate = base;
184
+ let suffix = 1;
185
+ while (taken.has(candidate)) {
186
+ suffix += 1;
187
+ candidate = `${base} ${suffix}`;
188
+ }
189
+ return candidate;
190
+ }
191
+ //#endregion
192
+ 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-C4lzPFEg.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 { _ as TaskTitle } from "./session-B8fJb_Or.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"
@@ -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-CZ4H51D0.js";
7
+ import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-DXujp-Zn.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;
@@ -0,0 +1,2 @@
1
+ import { c as loadConfigFile } from "./config-store-BVtdHkDK.js";
2
+ export { loadConfigFile };