glimmervoid 0.33.0 → 0.34.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.
package/README.md CHANGED
@@ -57,7 +57,7 @@ Update a clone with `git pull --ff-only && npm ci && npm run build`, then restar
57
57
  - **Claude Code CLI** on PATH, or another supported agent below.
58
58
  - **git** on PATH, for per-session worktrees.
59
59
  - **Linux only:** `build-essential` and `python3` for node-pty.
60
- - **Linux only:** `bubblewrap` (`bwrap`), `socat` and `ripgrep` (`rg`) for the sandbox that sandboxed sessions and factory checks run in (`sudo apt install bubblewrap socat ripgrep`). `glimmervoid doctor` reports all three.
60
+ - **Linux only:** `bubblewrap` (`bwrap`), `socat` and `ripgrep` (`rg`) for the sandbox runtime behind session guardrails and factory checks (`sudo apt install bubblewrap socat ripgrep`). `glimmervoid doctor` reports all three.
61
61
 
62
62
  ## Supported agents
63
63
 
@@ -6,7 +6,7 @@ import { t as AGENT_API_VERBS } from "../chunks/session-C7rstCmA.js";
6
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-DuaNFq7n.js";
9
+ import { i as sandboxDoctorRows, r as probeSandboxDependencies } from "../chunks/sandbox-deps-C63o3mZs.js";
10
10
  import { r as gitDoctorRows, t as probeGitVersion } from "../chunks/git-version-CrLW4a6r.js";
11
11
  import { i as pnpmGlobalBinDir, n as npmGlobalBinDir, r as onPath, t as formatPathNotice } from "../chunks/path-doctor-C23VAqeu.js";
12
12
  import fs from "node:fs";
@@ -135,7 +135,7 @@ var SUBCOMMAND_RUNNERS = new Map([
135
135
  return 0;
136
136
  }],
137
137
  ["pair", async (subcommandArgs) => {
138
- const { runPairCli } = await import("../chunks/pair-cli-BuyzST-U.js");
138
+ const { runPairCli } = await import("../chunks/pair-cli-CI848omy.js");
139
139
  return runPairCli(subcommandArgs);
140
140
  }],
141
141
  ["agent", async (subcommandArgs) => {
@@ -143,7 +143,7 @@ var SUBCOMMAND_RUNNERS = new Map([
143
143
  return runAgentSetupCli(subcommandArgs);
144
144
  }],
145
145
  ["kg", async (subcommandArgs) => {
146
- const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-C7G-x5sY.js");
146
+ const { runKnowledgeGraphCommand } = await import("../chunks/knowledge-graph-cli-BBE3R9DJ.js");
147
147
  return runKnowledgeGraphCommand(subcommandArgs);
148
148
  }],
149
149
  ["visions", async (subcommandArgs) => {
@@ -209,7 +209,7 @@ async function readDeclaredCustomAgents() {
209
209
  declared: [],
210
210
  error: null
211
211
  };
212
- const { loadConfigFile } = await import("../chunks/config-store-DaRS2c2d.js");
212
+ const { loadConfigFile } = await import("../chunks/config-store-DwTxLe8Y.js");
213
213
  try {
214
214
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
215
215
  if (!loaded.config) return {
@@ -285,7 +285,7 @@ async function runDoctor() {
285
285
  }
286
286
  switchSection("Agents");
287
287
  try {
288
- const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-C9gI2MHS.js");
288
+ const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-CgbcceU3.js");
289
289
  const declaredCustomAgents = await readDeclaredCustomAgents();
290
290
  if (declaredCustomAgents.error) line("config", declaredCustomAgents.error);
291
291
  setCustomAgents(declaredCustomAgents.declared);
@@ -1,2 +1,2 @@
1
- import { a as describeAgentResolvability, d as setCustomAgents, l as listAgentIds } from "./adapters-CUBEhjOR.js";
1
+ import { a as describeAgentResolvability, d as setCustomAgents, l as listAgentIds } from "./adapters-D-cRFZ_Q.js";
2
2
  export { describeAgentResolvability, listAgentIds, setCustomAgents };
@@ -5,7 +5,7 @@ import { n as resolveAgentCommand, t as buildAgentSpawnCommand } from "./spawn-c
5
5
  import { n as isRecord } from "./coerce-NSst8oRP.js";
6
6
  import { c as buildAgentEnv, i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, t as grok } from "./grok-BYKnBgdr.js";
7
7
  import { t as buildHookCommand } from "./hook-command-core-DclEoE9e.js";
8
- import "./contracts-DWv6q8ir.js";
8
+ import "./contracts-DZV9H8px.js";
9
9
  import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-UX2fmt81.js";
10
10
  import fs from "node:fs";
11
11
  //#region session/adapters/claude-code.ts
@@ -1448,12 +1448,16 @@ var AgentApiSettings = z.object(agentApiShape, { error: "agentApi must be an obj
1448
1448
  var AgentApiFileSettings = z.object(agentApiShape, { error: "agentApi must be an object" }).passthrough().optional();
1449
1449
  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();
1450
1450
  var sandboxShape = {
1451
- unconfinedRepos: optionalPathList("sandbox.unconfinedRepos"),
1452
- writablePaths: optionalPathList("sandbox.writablePaths"),
1453
- unreadablePaths: optionalPathList("sandbox.unreadablePaths")
1451
+ unguardedRepos: optionalPathList("guardrails.unguardedRepos"),
1452
+ blockedPaths: optionalPathList("guardrails.blockedPaths"),
1453
+ unreadablePaths: optionalPathList("guardrails.unreadablePaths")
1454
1454
  };
1455
- var SandboxSettings = z.object(sandboxShape, { error: "sandbox must be an object" }).strict().optional();
1456
- var SandboxFileSettings = z.object(sandboxShape, { error: "sandbox must be an object" }).passthrough().optional();
1455
+ var isHomeRelativePath = (entry) => entry === "~" || entry.startsWith("~/") || entry.startsWith("~\\");
1456
+ var createSandboxSettings = (isAbsolutePath) => z.object({
1457
+ ...sandboxShape,
1458
+ 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()
1459
+ }, { error: "guardrails must be an object" }).strict().optional();
1460
+ var SandboxFileSettings = z.object(sandboxShape, { error: "guardrails must be an object" }).passthrough().optional();
1457
1461
  var telemetryShape = { enabled: optionalBoolean("telemetry.enabled") };
1458
1462
  var TelemetrySettings = z.object(telemetryShape, { error: "telemetry must be an object" }).strict().optional();
1459
1463
  var TelemetryFileSettings = z.object(telemetryShape, { error: "telemetry must be an object" }).passthrough().optional();
@@ -1496,7 +1500,7 @@ var createBrowserConfigShape = (isAbsolutePath) => ({
1496
1500
  telegram: TelegramSettings,
1497
1501
  ingest: IngestSettings,
1498
1502
  agentApi: AgentApiSettings,
1499
- sandbox: SandboxSettings,
1503
+ guardrails: createSandboxSettings(isAbsolutePath),
1500
1504
  telemetry: TelemetrySettings,
1501
1505
  workflows: WorkflowsSettings.nullable().optional()
1502
1506
  });
@@ -1593,7 +1597,7 @@ var ProjectConfig = z.object({
1593
1597
  agent: z.string({ error: "projects[].agent must be a string" }).regex(AGENT_ID_RE, { error: `projects[].agent must be ${AGENT_ID_SHAPE_MESSAGE}` }).optional(),
1594
1598
  codexBypassHookTrust: z.boolean().optional(),
1595
1599
  dangerouslySkipPermissions: z.boolean({ error: "projects[].dangerouslySkipPermissions must be a boolean" }).optional(),
1596
- unconfined: z.boolean({ error: "projects[].unconfined must be a boolean" }).optional()
1600
+ unguarded: z.boolean({ error: "projects[].unguarded must be a boolean" }).optional()
1597
1601
  }).passthrough();
1598
1602
  var FILE_CONFIG_SHAPE = {
1599
1603
  ...BROWSER_CONFIG_SHAPE,
@@ -1612,7 +1616,7 @@ var FILE_CONFIG_SHAPE = {
1612
1616
  ingest: optionalLooseObject("ingest"),
1613
1617
  workflows: optionalLooseObject("workflows"),
1614
1618
  agentApi: AgentApiFileSettings,
1615
- sandbox: SandboxFileSettings,
1619
+ guardrails: SandboxFileSettings,
1616
1620
  telemetry: TelemetryFileSettings,
1617
1621
  trace: TraceSettings,
1618
1622
  planReview: PlanReviewSettings,
@@ -1669,7 +1673,7 @@ var CONFIG_BLOCK_KEYS = Object.freeze([
1669
1673
  "telegram",
1670
1674
  "ingest",
1671
1675
  "agentApi",
1672
- "sandbox",
1676
+ "guardrails",
1673
1677
  "telemetry",
1674
1678
  "workflows",
1675
1679
  "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-Cneb8Ujj.js";
7
- import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-DWv6q8ir.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-DTwMFUjx.js";
7
+ import { V as FeatureFlagsResponse, W as TELEMETRY_KILL_SWITCH_FLAG } from "./contracts-DZV9H8px.js";
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import os from "node:os";
@@ -1113,9 +1113,9 @@ var DEFAULT_CONFIG = {
1113
1113
  mirrorHarnessRuns: false
1114
1114
  },
1115
1115
  agentApi: { enabled: false },
1116
- sandbox: {
1117
- unconfinedRepos: [],
1118
- writablePaths: ["~/.npm", "~/.cache"],
1116
+ guardrails: {
1117
+ unguardedRepos: [],
1118
+ blockedPaths: [],
1119
1119
  unreadablePaths: []
1120
1120
  },
1121
1121
  telemetry: { enabled: true },
@@ -1388,6 +1388,12 @@ function pickRedactedBlock(stored, allowedKeys, secretKeys) {
1388
1388
  }
1389
1389
  return redacted;
1390
1390
  }
1391
+ function retiredGuardrailKeysWarning(config) {
1392
+ const projects = Array.isArray(config.projects) ? config.projects : [];
1393
+ const retiredKeys = [...Object.hasOwn(config, "sandbox") ? ["sandbox (move it to guardrails, renaming unconfinedRepos to unguardedRepos)"] : [], ...projects.some((project) => isRecord(project) && Object.hasOwn(project, "unconfined")) ? ["projects[].unconfined (rename it to unguarded)"] : []];
1394
+ if (retiredKeys.length === 0) return null;
1395
+ return `[guardrails] config.json still has ${retiredKeys.join(" and ")}. These keys are ignored, so their unreadable paths and opt-outs do not apply until you move them.`;
1396
+ }
1391
1397
  function createConfigStore({ settingsDefaults } = {}) {
1392
1398
  const configPath = resolveConfigPath();
1393
1399
  const effectiveDefaults = {
@@ -1401,6 +1407,8 @@ function createConfigStore({ settingsDefaults } = {}) {
1401
1407
  writeBackupContent(`${configPath}.boot.bak`, loadedConfig.loadedContent);
1402
1408
  config.repoRoots = config.repoRoots || [];
1403
1409
  config.branchGc = resolveBranchGcAndWarn(config.branchGc);
1410
+ const retiredGuardrailKeys = retiredGuardrailKeysWarning(config);
1411
+ if (retiredGuardrailKeys !== null) console.warn(retiredGuardrailKeys);
1404
1412
  if (Array.isArray(config.projects) && ensureProjectIds(config.projects)) try {
1405
1413
  writeJsonAtomicSync(configPath, withoutEnvSecrets(config, envSecrets), { mode: 384 });
1406
1414
  console.log("[config] Auto-assigned IDs to projects missing them");
@@ -1520,9 +1528,9 @@ function createConfigStore({ settingsDefaults } = {}) {
1520
1528
  recordSignals: config.recordSignals ?? effectiveDefaults.recordSignals,
1521
1529
  trace: { enabled: config.trace?.enabled ?? DEFAULT_CONFIG.trace.enabled },
1522
1530
  agentApi: { enabled: config.agentApi?.enabled ?? DEFAULT_CONFIG.agentApi.enabled },
1523
- sandbox: {
1524
- ...DEFAULT_CONFIG.sandbox,
1525
- ...config.sandbox
1531
+ guardrails: {
1532
+ ...DEFAULT_CONFIG.guardrails,
1533
+ ...config.guardrails
1526
1534
  },
1527
1535
  telemetry: { enabled: config.telemetry?.enabled ?? DEFAULT_CONFIG.telemetry.enabled },
1528
1536
  telemetryForcedOff: isTelemetryForcedOff(process.env),
@@ -1598,7 +1606,7 @@ function createConfigStore({ settingsDefaults } = {}) {
1598
1606
  if (newConfig.telegram != null) config.telegram = newConfig.telegram;
1599
1607
  if (newConfig.ingest != null) config.ingest = newConfig.ingest;
1600
1608
  if (newConfig.agentApi != null) config.agentApi = newConfig.agentApi;
1601
- if (newConfig.sandbox != null) config.sandbox = newConfig.sandbox;
1609
+ if (newConfig.guardrails != null) config.guardrails = newConfig.guardrails;
1602
1610
  if (newConfig.telemetry != null) config.telemetry = newConfig.telemetry;
1603
1611
  if (newConfig.workflows == null) delete config.workflows;
1604
1612
  if (newConfig.workflows != null) config.workflows = newConfig.workflows;
@@ -0,0 +1,2 @@
1
+ import { c as loadConfigFile } from "./config-store-D0lRWsAM.js";
2
+ export { loadConfigFile };
@@ -1,5 +1,5 @@
1
1
  import { T as TaskTitle, b as SessionSnapshot, d as PendingPromptDetail, g as SESSION_DOC_PATH_MAX_CHARS, p as PendingWakeup, x as SessionState, y as SessionDoc } from "./session-C7rstCmA.js";
2
- import { D as MyPrMergeWhenReadyRequest, Dt as CoherenceRisk, Et as CoherenceReadiness, F as CommitSha, O as MyPrMergeWhenReadyResult, P as MyPrsStatus, Q as TeamReviewActionResult, S as MyPrKeepMergeableResult, T as MyPrMergeResult, Tt as CoherenceOrient, Z as TeamReviewActionRequest, _t as ReviewsRefreshResult, gt as ReviewsRefreshRequest, jt as CoherenceWorkState, mt as REPO_SLUG_RE, n as BUILTIN_AGENT_IDS, nt as TeamReviewStatus, vt as reviewsPollingShape, w as MyPrMergeRequest, x as MyPrKeepMergeableRequest } from "./config-Cneb8Ujj.js";
2
+ import { D as MyPrMergeWhenReadyRequest, Dt as CoherenceRisk, Et as CoherenceReadiness, F as CommitSha, O as MyPrMergeWhenReadyResult, P as MyPrsStatus, Q as TeamReviewActionResult, S as MyPrKeepMergeableResult, T as MyPrMergeResult, Tt as CoherenceOrient, Z as TeamReviewActionRequest, _t as ReviewsRefreshResult, gt as ReviewsRefreshRequest, jt as CoherenceWorkState, mt as REPO_SLUG_RE, n as BUILTIN_AGENT_IDS, nt as TeamReviewStatus, vt as reviewsPollingShape, w as MyPrMergeRequest, x as MyPrKeepMergeableRequest } from "./config-DTwMFUjx.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({
@@ -1370,6 +1370,15 @@ var clientVariants = [
1370
1370
  id: sessionId,
1371
1371
  newName: z.string()
1372
1372
  }),
1373
+ loose("get-workspace-repos", {
1374
+ id: sessionId,
1375
+ requestId
1376
+ }),
1377
+ loose("set-workspace-repos", {
1378
+ id: sessionId,
1379
+ repos: z.array(z.string()),
1380
+ requestId
1381
+ }),
1373
1382
  loose("set-session-title", {
1374
1383
  id: sessionId,
1375
1384
  title: TaskTitle
@@ -1511,6 +1520,8 @@ Object.freeze([
1511
1520
  "hooks-report",
1512
1521
  "save-hook-result",
1513
1522
  "delete-hook-result",
1523
+ "workspace-repos",
1524
+ "set-workspace-repos-result",
1514
1525
  "hooks-updated",
1515
1526
  "state-change",
1516
1527
  "session-added",
@@ -1635,6 +1646,19 @@ var serverVariants = [
1635
1646
  error: optionalError,
1636
1647
  id: z.string().optional()
1637
1648
  }),
1649
+ loose("workspace-repos", {
1650
+ requestId,
1651
+ id: sessionId,
1652
+ ok: z.boolean(),
1653
+ repos: z.array(z.string()),
1654
+ error: optionalError
1655
+ }),
1656
+ loose("set-workspace-repos-result", {
1657
+ requestId,
1658
+ id: sessionId,
1659
+ ok: z.boolean(),
1660
+ error: optionalError
1661
+ }),
1638
1662
  loose("hooks-updated", { count: z.number().int().nonnegative() }),
1639
1663
  loose("state-change", {
1640
1664
  id: sessionId,
@@ -2,7 +2,7 @@ import { r as errorMessage } from "./text-DoirglWV.js";
2
2
  import { s as resolvePackageBin } from "./runtime-paths-BPoxENmK.js";
3
3
  import { r as execFileSync } from "./child-process-safe-DDELk9XC.js";
4
4
  import { n as glimmervoidHomeDir, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
5
- import { r as BrowserConfig } from "./config-Cneb8Ujj.js";
5
+ import { r as BrowserConfig } from "./config-DTwMFUjx.js";
6
6
  import fs, { closeSync, constants, existsSync, fstatSync, lstatSync, mkdirSync, openSync, readFileSync, readdirSync, realpathSync } from "node:fs";
7
7
  import path, { dirname, join, posix, resolve, win32 } from "node:path";
8
8
  import { parseArgs } from "node:util";