glimmervoid 0.42.3 → 0.43.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 (28) hide show
  1. package/dist/bin/glimmervoid.js +13 -13
  2. package/dist/chunks/{adapters-DeqV4wUv.js → adapters-EqOJN5vD.js} +1 -1
  3. package/dist/chunks/{adapters-Bga1N6Ie.js → adapters-jRUJYLhH.js} +5 -5
  4. package/dist/chunks/{agent-api-cli-YvQ8WxHA.js → agent-api-cli-B0fpc41n.js} +3 -3
  5. package/dist/chunks/{agent-api-cli-DWVeqlLu.js → agent-api-cli-DYwXyAmN.js} +1 -1
  6. package/dist/chunks/{agent-api-core-DFYLP1bF.js → agent-api-core-BeSecYrA.js} +3 -3
  7. package/dist/chunks/{agent-setup-cli-C9qDV2g5.js → agent-setup-cli-NfJQxNdp.js} +1 -1
  8. package/dist/chunks/{config-store-DOGtTJ1d.js → config-store-CBjnq-OI.js} +2 -2
  9. package/dist/chunks/config-store-DCrosJLg.js +1 -0
  10. package/dist/chunks/{contracts-Ds_eevZs.js → contracts-BJGgl8et.js} +2 -2
  11. package/dist/chunks/{control-messages-Dgap3JRR.js → control-messages-CD99vE0V.js} +9 -3
  12. package/dist/chunks/{git-version-DqagvnAZ.js → git-version-ByOV7a_h.js} +1 -1
  13. package/dist/chunks/{grok-DwrAcNHC.js → grok-DPmX1ozS.js} +1 -1
  14. package/dist/chunks/{main-DOZJniDn.js → main-_78bVmTr.js} +1898 -1426
  15. package/dist/chunks/{pair-cli-PCXITdEd.js → pair-cli-DAJNPgsi.js} +2 -2
  16. package/dist/chunks/{remote-config-DeWURqqr.js → remote-config-BdCTswa1.js} +1 -1
  17. package/dist/chunks/{session-3eSP3t1i.js → session-BUcx9uJa.js} +2 -0
  18. package/dist/chunks/{session-routes-B2oSzmQn.js → session-routes-DdeSkLqC.js} +1 -1
  19. package/dist/chunks/{settings-cli-xpR7vk9L.js → settings-cli-CMLEvC05.js} +5 -5
  20. package/dist/chunks/{settings-readout-core-C2mOk9Yz.js → settings-readout-core-CBqSjZiW.js} +2 -2
  21. package/dist/chunks/{ssh-sign-cli-rKiqiNem.js → ssh-sign-cli-CvqtQNQe.js} +6 -6
  22. package/dist/client/assets/{index-NhAGtpDY.css → index-CW2LelmE.css} +1 -1
  23. package/dist/client/assets/index-Cl0UmezJ.js +177 -0
  24. package/dist/client/index.html +2 -2
  25. package/dist/server/index.js +1 -1
  26. package/package.json +2 -2
  27. package/dist/chunks/config-store-CGrS8s6x.js +0 -1
  28. package/dist/client/assets/index-CuuOi3Bp.js +0 -177
@@ -2,13 +2,13 @@ import { i as sanitizeOneLine, n as requireExecutableSpawnHelper, r as firstLine
2
2
  import { a as isMissingFileError, i as errorText$1, r as errorMessage, t as errorCode } from "./text-DoirglWV.js";
3
3
  import { a as sanitizeWorktreeName, i as safePathSegment, n as equalsIgnoringCaseOnWindows, r as isPathInside, t as caseFoldedPathKey } from "./paths-Bu4eH1Yd.js";
4
4
  import { a as packageRoot, n as cliPath, o as relayPath, r as clientDir, s as resolvePackageBin, t as bundled } from "./runtime-paths-BkeftE60.js";
5
- import { $t as STATES, A as SIGN_URL_ENV, At as TeamReviewStatus, B as LinkedPr, Bt as shortSha, Ct as ReviewThreadId, Dt as TeamReviewCompareFiles, E as SESSION_DOC_BODY_CAP_BYTES, Ft as decisionAsIfApprovalRequired, G as MyPrKeepMergeableRequest, H as MyPrAutoRebase, Ht as NODE_ID_RE, I as SshSignRequest, J as MyPrMergeMethod, L as TASK_TITLE_CONTROL_CHARACTERS, Lt as hasStandingViewerApproval, Mt as TeamReviewThreadResult, Nt as TeamReviewThreadsRepository, O as SESSION_NAME_PATTERN, Ot as TeamReviewResolveResponse, Pt as canApproveAfterComment, Q as MyPrMergeWhenReadyRequest, Qt as RESTARTABLE_STATES, R as TaskTitle, S as ConversationQuestion, St as ReviewResult, Tt as TeamReviewActionRequest, U as MyPrCheckContext, Ut as REPO_SLUG_RE, V as MyPr, Vt as GH_SEGMENT, W as MyPrCheckContextsResponse, Wt as repoParts, Xt as KILLABLE_STATES, Y as MyPrMergeRequest, Yt as BADGE_LABELS, Z as MyPrMergeStateResponse, Zt as MERGEABLE_LIVE_STATES, _ as CONVERSATION_TOOL_RESULT_HOOK_EVENT, _t as QueuedReview, bt as ReviewDraft, dt as EarlierReview, ft as FindingSeverity, g as CONVERSATION_PERMISSION_HOOK_EVENT, gt as PrDetail, h as CONVERSATION_APPROVAL_SUMMARY_MAX_CHARS, ht as PostingPlan, it as MyPrsState, j as SSH_SIGN_BODY_CAP_BYTES, jt as TeamReviewThreadCommentsResponse, k as SESSION_NAME_RULE_TEXT, kt as TeamReviewStateEntry, lt as CommitSha, m as COHERENCE_HOOKS_INACTIVE, mt as GithubReviewState, n as AGENT_URL_ENV, nt as MyPrThreadsResponse, q as MyPrLaneEntry, r as ASK_USER_QUESTION_TOOL_NAME, rt as MyPrsSnapshot, tt as MyPrThreadNode, ut as DECIDING_REVIEW_STATES, w as RefinedTaskTitle, wt as ReviewVerdict, xt as ReviewFinding, yt as ReviewComment, zt as HEX_SHA_RE } from "./session-3eSP3t1i.js";
5
+ import { $t as STATES, A as SIGN_URL_ENV, At as TeamReviewStatus, B as LinkedPr, Bt as shortSha, Ct as ReviewThreadId, Dt as TeamReviewCompareFiles, E as SESSION_DOC_BODY_CAP_BYTES, Ft as decisionAsIfApprovalRequired, G as MyPrKeepMergeableRequest, H as MyPrAutoRebase, Ht as NODE_ID_RE, I as SshSignRequest, J as MyPrMergeMethod, L as TASK_TITLE_CONTROL_CHARACTERS, Lt as hasStandingViewerApproval, Mt as TeamReviewThreadResult, Nt as TeamReviewThreadsRepository, O as SESSION_NAME_PATTERN, Ot as TeamReviewResolveResponse, Pt as canApproveAfterComment, Q as MyPrMergeWhenReadyRequest, Qt as RESTARTABLE_STATES, R as TaskTitle, S as ConversationQuestion, St as ReviewResult, Tt as TeamReviewActionRequest, U as MyPrCheckContext, Ut as REPO_SLUG_RE, V as MyPr, Vt as GH_SEGMENT, W as MyPrCheckContextsResponse, Wt as repoParts, Xt as KILLABLE_STATES, Y as MyPrMergeRequest, Yt as BADGE_LABELS, Z as MyPrMergeStateResponse, Zt as MERGEABLE_LIVE_STATES, _ as CONVERSATION_TOOL_RESULT_HOOK_EVENT, _t as QueuedReview, bt as ReviewDraft, dt as EarlierReview, ft as FindingSeverity, g as CONVERSATION_PERMISSION_HOOK_EVENT, gt as PrDetail, h as CONVERSATION_APPROVAL_SUMMARY_MAX_CHARS, ht as PostingPlan, it as MyPrsState, j as SSH_SIGN_BODY_CAP_BYTES, jt as TeamReviewThreadCommentsResponse, k as SESSION_NAME_RULE_TEXT, kt as TeamReviewStateEntry, lt as CommitSha, m as COHERENCE_HOOKS_INACTIVE, mt as GithubReviewState, n as AGENT_URL_ENV, nt as MyPrThreadsResponse, q as MyPrLaneEntry, r as ASK_USER_QUESTION_TOOL_NAME, rt as MyPrsSnapshot, tt as MyPrThreadNode, ut as DECIDING_REVIEW_STATES, w as RefinedTaskTitle, wt as ReviewVerdict, xt as ReviewFinding, yt as ReviewComment, zt as HEX_SHA_RE } from "./session-BUcx9uJa.js";
6
6
  import { n as execFileAsync, o as spawn, r as execFileSync, t as execFile } from "./child-process-safe-D4hyVIXj.js";
7
- import { At as GithubIssueResponse, C as comparablePrKey, Ct as PLAN_RESULT_HOOK_EVENT, Dt as parseExitPlanModeHookPayload, E as WorkflowsSettings, Et as PlanRevision, F as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, Ft as IssuesStatus, It as issuePullRequestStateFromGithub, Mt as IssueUpdate, Nt as IssuesSearchResponse, O as WorkflowsState, Ot as planTitle, Pt as IssuesState, S as GithubPrsFrame, St as PLAN_HOOK_OUTPUT_MAX_CHARS, T as WorkflowLabelName, Tt as PlanDecision, _ as MinedPrReviewData, _t as CoherenceJournalOutput, b as GithubPrKey, bt as PLAN_BODY_CAP_BYTES, c as BenchmarkActionRequest, d as BenchmarkJudgement, f as BenchmarkRun, ft as UpdateJournal, g as MergedPrListing, gt as TraceRecord, h as CommitComparison, ht as TraceCheckpoint, jt as IssueKey, kt as GithubIssuePullRequestsRepository, l as BenchmarkCase, m as BenchmarkSuite, mt as MAX_RAW_LINE_CHARS, n as ClientMessage, p as BenchmarkStatus, pt as SessionSetup, s as pullRequestKeyFromReference, t as CONTROL_FRAME_MAX_BYTES, tt as USAGE_INTEGER_RANGES, u as BenchmarkId, v as PrCheckoutCaseInput, vt as ChangeMap, w as WorkflowCommentBody, wt as PLAN_TOOL_NAME, x as GithubPrLightSearchNode, xt as PLAN_HOOK_EVENT, y as GithubPrDetailNode, yt as changeMapFactId } from "./control-messages-Dgap3JRR.js";
8
- import { a as permitsHelpCommand, r as describeSessionLimits } from "./session-routes-B2oSzmQn.js";
9
- import { a as decideSpawnAllowance, c as describeKeptChildAttention, d as describeUnpushedCloseRefusal, h as projectReviews, i as decideAgentRequest, l as describePushLanding, m as projectMyPrs, n as REFUSAL_REASON, o as deriveChildSessionName, p as parseAgentVerb, s as describeChildEndNote, u as describeRoleRefusal } from "./agent-api-core-DFYLP1bF.js";
7
+ import { At as GithubIssueResponse, C as comparablePrKey, Ct as PLAN_RESULT_HOOK_EVENT, Dt as parseExitPlanModeHookPayload, E as WorkflowsSettings, Et as PlanRevision, F as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANGE, Ft as IssuesStatus, It as issuePullRequestStateFromGithub, Mt as IssueUpdate, Nt as IssuesSearchResponse, O as WorkflowsState, Ot as planTitle, Pt as IssuesState, S as GithubPrsFrame, St as PLAN_HOOK_OUTPUT_MAX_CHARS, T as WorkflowLabelName, Tt as PlanDecision, _ as MinedPrReviewData, _t as CoherenceJournalOutput, b as GithubPrKey, bt as PLAN_BODY_CAP_BYTES, c as BenchmarkActionRequest, d as BenchmarkJudgement, f as BenchmarkRun, ft as UpdateJournal, g as MergedPrListing, gt as TraceRecord, h as CommitComparison, ht as TraceCheckpoint, jt as IssueKey, kt as GithubIssuePullRequestsRepository, l as BenchmarkCase, m as BenchmarkSuite, mt as MAX_RAW_LINE_CHARS, n as ClientMessage, p as BenchmarkStatus, pt as SessionSetup, s as pullRequestKeyFromReference, t as CONTROL_FRAME_MAX_BYTES, tt as USAGE_INTEGER_RANGES, u as BenchmarkId, v as PrCheckoutCaseInput, vt as ChangeMap, w as WorkflowCommentBody, wt as PLAN_TOOL_NAME, x as GithubPrLightSearchNode, xt as PLAN_HOOK_EVENT, y as GithubPrDetailNode, yt as changeMapFactId } from "./control-messages-CD99vE0V.js";
8
+ import { a as permitsHelpCommand, r as describeSessionLimits } from "./session-routes-DdeSkLqC.js";
9
+ import { a as decideSpawnAllowance, c as describeKeptChildAttention, d as describeUnpushedCloseRefusal, h as projectReviews, i as decideAgentRequest, l as describePushLanding, m as projectMyPrs, n as REFUSAL_REASON, o as deriveChildSessionName, p as parseAgentVerb, s as describeChildEndNote, u as describeRoleRefusal } from "./agent-api-core-BeSecYrA.js";
10
10
  import { n as glimmervoidHomeDir, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
11
- import { i as parseCommandLine, n as warnWhenGitIsTooOld } from "./git-version-DqagvnAZ.js";
11
+ import { i as parseCommandLine, n as warnWhenGitIsTooOld } from "./git-version-ByOV7a_h.js";
12
12
  import { n as checkGuardrailsDependencies, t as allowGuardedSpawn } from "./guardrails-deps-BjPzk1rE.js";
13
13
  import { t as HOOK_URL_ENV } from "./hook-relay-core-DA_bz2KA.js";
14
14
  import { t as HOOK_VIA_GUARDRAILS_PROXY_ENV } from "./guardrails-proxy-core-BI3rdY-m.js";
@@ -21,13 +21,13 @@ import { n as DEFAULT_MAX_MS, r as nextBackoffMs, t as DEFAULT_BASE_MS } from ".
21
21
  import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.js";
22
22
  import { n as shellQuote } from "./hook-command-core-qTNK-xMF.js";
23
23
  import { C as parseCgroupBytes, S as memoryReserveBytes, T as parseMemAvailableBytes, _ as createSpawnGate, a as jsonStateLoadError, b as cgroupLimitBytes, c as loadedJsonValue, d as writeJsonAtomicSync, f as writeTextAtomic, g as createSerialQueue, h as createMemoryAdmission, i as createJsonStateWriter, m as createKeyedSerialQueue, n as appendJsonLines, o as loadJsonStateFile, p as writeTextAtomicSync, r as createJsonStateStore, s as loadJsonStateFileSync, t as appendJsonLine, u as writeJsonAtomic, v as isQueueAdmissionTimeout, w as parseCgroupV2Path, x as headroomFromReadings, y as cgroupAncestorPaths } from "./json-file-DFCTvPjj.js";
24
- import { $ as DEFAULT_BRANCH_GC_PREFIXES, B as buildExceptionProperties, F as TELEMETRY_BATCH_URL, G as exceptionFingerprint, H as decideIsDevInstall, I as TELEMETRY_FLAGS_URL, J as resolveProjectToken, K as nodeMajorVersion, L as adapterBucket, P as FIRST_RUN_NOTICE, R as buildAiGenerationEvents, U as decideRemoteTelemetryState, V as classifySessionExit, W as decideTelemetryConsent, Z as stableConfigKey, a as generateProjectId, at as worktreeIntegrationTips, b as validateSettingsBlock, ct as isSameDirectoryPath, d as assetForPlatform, et as matchedPrefix, f as decideRtkInstall, g as verifyDigest, h as isRtkBinaryName, i as ensureProjectIds, it as usablePrefixes, m as installTargetPath, n as DEFAULT_CONFIG, nt as planWorktreeGc, o as glimmervoidHomeDir$1, ot as canonicalizePath, p as findEscapingArchiveMember, q as parsePosthogReleaseId, r as createConfigStore, rt as sessionIdFromBranch, st as comparableDirectoryPath, t as ABORT_CONFIG_SAVE, tt as planBranchGc, v as mergeSettingsBlock, y as settingsBlockSpecFor, z as buildBrowserExceptionProperties } from "./config-store-DOGtTJ1d.js";
25
- import { T as USAGE_VENDOR_KEYS, _ as PersistedTaskTitle, a as parseDataClientMessage, b as configIssueMessage, c as PendingCrashReport, d as TelemetryState, g as ConfigUpdate, i as parseDataAttachHistory, l as TELEMETRY_EVENT_SCHEMAS, m as BrowserConfig, n as HookEnvelope, o as DashboardTelemetryReport, r as DEEP_HISTORY_SCROLLBACK_LINES, t as HTTP_URL_RE, v as RUNTIME_CONFIG_SCALAR_KEYS, w as USAGE_COST_MODES, y as TASK_TITLE_SOURCE_PRIORITY } from "./contracts-Ds_eevZs.js";
26
- import { A as dedupeCodexFiles, B as shouldPersistWarehouse, C as shortSha$1, D as codexSessionIdFromPath, E as codexRootCandidates, F as passOutcome, H as claudeCode, I as projectDirCandidates, L as resolveProjectsDirs, M as grokHomes, N as grokRootCandidates, O as continuationDelayMs, P as isUsageFile, R as scopedClaudeRoots, S as parseResolvedSha, T as codexHomes, V as splitLines$1, _ as isCheckFresh, a as describeAgentResolvability, b as parseRegistryDeprecation, c as isKnownAgentId, d as resolveAdapter, f as setCustomAgents, g as decideUpdateStatus, h as decideInstallFlavor, i as customAgentFingerprint, j as expandTilde, k as decideFileRead, l as listAgentIds, m as readHostCodexVersion, n as cachedAgentResolvability, o as getAdapter, p as codex, r as commandFor, s as hookProfileOf, t as DEFAULT_AGENT_ID, u as resetCommandCache, v as normalizeSha, w as codexFallbackRoots, x as parseRegistryLatest, y as normalizeUpdateChannel, z as shouldEvaluateDespiteIoFailures } from "./adapters-Bga1N6Ie.js";
24
+ import { $ as DEFAULT_BRANCH_GC_PREFIXES, B as buildExceptionProperties, F as TELEMETRY_BATCH_URL, G as exceptionFingerprint, H as decideIsDevInstall, I as TELEMETRY_FLAGS_URL, J as resolveProjectToken, K as nodeMajorVersion, L as adapterBucket, P as FIRST_RUN_NOTICE, R as buildAiGenerationEvents, U as decideRemoteTelemetryState, V as classifySessionExit, W as decideTelemetryConsent, Z as stableConfigKey, a as generateProjectId, at as worktreeIntegrationTips, b as validateSettingsBlock, ct as isSameDirectoryPath, d as assetForPlatform, et as matchedPrefix, f as decideRtkInstall, g as verifyDigest, h as isRtkBinaryName, i as ensureProjectIds, it as usablePrefixes, m as installTargetPath, n as DEFAULT_CONFIG, nt as planWorktreeGc, o as glimmervoidHomeDir$1, ot as canonicalizePath, p as findEscapingArchiveMember, q as parsePosthogReleaseId, r as createConfigStore, rt as sessionIdFromBranch, st as comparableDirectoryPath, t as ABORT_CONFIG_SAVE, tt as planBranchGc, v as mergeSettingsBlock, y as settingsBlockSpecFor, z as buildBrowserExceptionProperties } from "./config-store-CBjnq-OI.js";
25
+ import { T as USAGE_VENDOR_KEYS, _ as PersistedTaskTitle, a as parseDataClientMessage, b as configIssueMessage, c as PendingCrashReport, d as TelemetryState, g as ConfigUpdate, i as parseDataAttachHistory, l as TELEMETRY_EVENT_SCHEMAS, m as BrowserConfig, n as HookEnvelope, o as DashboardTelemetryReport, r as DEEP_HISTORY_SCROLLBACK_LINES, t as HTTP_URL_RE, v as RUNTIME_CONFIG_SCALAR_KEYS, w as USAGE_COST_MODES, y as TASK_TITLE_SOURCE_PRIORITY } from "./contracts-BJGgl8et.js";
26
+ import { A as dedupeCodexFiles, B as shouldPersistWarehouse, C as shortSha$1, D as codexSessionIdFromPath, E as codexRootCandidates, F as passOutcome, H as claudeCode, I as projectDirCandidates, L as resolveProjectsDirs, M as grokHomes, N as grokRootCandidates, O as continuationDelayMs, P as isUsageFile, R as scopedClaudeRoots, S as parseResolvedSha, T as codexHomes, V as splitLines$1, _ as isCheckFresh, a as describeAgentResolvability, b as parseRegistryDeprecation, c as isKnownAgentId, d as resolveAdapter, f as setCustomAgents, g as decideUpdateStatus, h as decideInstallFlavor, i as customAgentFingerprint, j as expandTilde, k as decideFileRead, l as listAgentIds, m as readHostCodexVersion, n as cachedAgentResolvability, o as getAdapter, p as codex, r as commandFor, s as hookProfileOf, t as DEFAULT_AGENT_ID, u as resetCommandCache, v as normalizeSha, w as codexFallbackRoots, x as parseRegistryLatest, y as normalizeUpdateChannel, z as shouldEvaluateDespiteIoFailures } from "./adapters-jRUJYLhH.js";
27
27
  import { t as HOOK_TOOLS } from "./hook-tools-Dl7-r2Eb.js";
28
28
  import { a as formatSshPublicKey, c as orderAgentSockets, i as commitSigningShimText, l as parseSshPublicKey, n as NO_AGENT_HOLDS_KEY, o as isForwardedAgentDirName, r as agentListsKey, s as isSignableGitObject, t as COMMIT_SIGNING_SHIM_NAME } from "./ssh-signing-core-CRhVVWNW.js";
29
- import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-DeWURqqr.js";
30
- import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-C2mOk9Yz.js";
29
+ import { a as configSiblingPath, c as defaultPairingsPath, d as decideDeviceAuth, f as deviceNameFromUserAgent, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, p as hashSecret, r as validateRemoteConfig, s as createSeenStore, t as decideBindHost, u as DEFAULT_DEVICE_MAX_AGE_MS } from "./remote-config-BdCTswa1.js";
30
+ import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-CBqSjZiW.js";
31
31
  import { _ as escapeMarkup, g as createLaneLog, n as createVisionsSetup } from "./visions-setup-DB2P8JUL.js";
32
32
  import { t as getRtkPath } from "./rtk-resolver-BDHi6RMv.js";
33
33
  import { createRequire } from "node:module";
@@ -39,7 +39,7 @@ import crypto, { createHash, randomBytes, randomInt, randomUUID } from "node:cry
39
39
  import WebSocket$1, { WebSocket, WebSocketServer } from "ws";
40
40
  import http from "node:http";
41
41
  import net, { isIPv6 } from "node:net";
42
- import fsp, { access, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
42
+ import fs$1, { access, chmod, copyFile, lstat, mkdir, mkdtemp, open, readFile, readdir, readlink, realpath, rename, rm, stat, symlink, writeFile } from "node:fs/promises";
43
43
  import { pipeline } from "node:stream";
44
44
  import express from "express";
45
45
  import { EventEmitter } from "node:events";
@@ -49,6 +49,168 @@ import { AsyncLocalStorage } from "node:async_hooks";
49
49
  import https from "node:https";
50
50
  import { StringDecoder } from "node:string_decoder";
51
51
  import { monitorEventLoopDelay } from "node:perf_hooks";
52
+ //#region shared/contracts/owned-paths.ts
53
+ var OwnedPathOwner = z.string().regex(/^(session|lane):[A-Za-z0-9._:#-]+$/);
54
+ var OwnedPathEntry = z.object({
55
+ path: z.string().min(1),
56
+ owner: OwnedPathOwner,
57
+ kind: z.enum(["git-worktree", "folder"]),
58
+ projectPath: z.string().min(1).nullable(),
59
+ branch: z.string().min(1).nullable()
60
+ }).strict();
61
+ var OwnedPathsLedger = z.object({
62
+ version: z.literal(1),
63
+ entries: z.array(OwnedPathEntry)
64
+ }).strict();
65
+ //#endregion
66
+ //#region server/core/owned-paths-core.ts
67
+ var SESSION_OWNER_PREFIX = "session:";
68
+ var RESTART_SURVIVING_LANE_OWNERS = /* @__PURE__ */ new Set(["lane:update-apply", "lane:team-review"]);
69
+ function isOwnerGone(owner, configuredSessionIds) {
70
+ if (!owner.startsWith(SESSION_OWNER_PREFIX)) return !RESTART_SURVIVING_LANE_OWNERS.has(owner);
71
+ return !configuredSessionIds.has(owner.slice(8));
72
+ }
73
+ function orphanedOwnedPaths(entries, configuredSessionIds) {
74
+ const orphans = entries.filter((entry) => isOwnerGone(entry.owner, configuredSessionIds));
75
+ return [...orphans.filter((entry) => entry.kind === "git-worktree"), ...orphans.filter((entry) => entry.kind === "folder")];
76
+ }
77
+ function holdsKeptPath(folderPath, keptPaths) {
78
+ return keptPaths.some((keptPath) => {
79
+ const relativePath = path.relative(folderPath, keptPath);
80
+ return relativePath === "" || !relativePath.startsWith("..") && !path.isAbsolute(relativePath);
81
+ });
82
+ }
83
+ //#endregion
84
+ //#region server/owned-paths-ledger.ts
85
+ function ownedPathsLedgerPath(glimmervoidHome = glimmervoidHomeDir$1()) {
86
+ return path.join(glimmervoidHome, "owned-paths.json");
87
+ }
88
+ function ledgerKey(ownedPath) {
89
+ return caseFoldedPathKey(path.resolve(ownedPath));
90
+ }
91
+ async function canonicalOwnedPath(ownedPath) {
92
+ const resolvedPath = path.resolve(ownedPath);
93
+ const missingSegments = [];
94
+ let existingAncestor = resolvedPath;
95
+ while (true) {
96
+ const realAncestor = await fs$1.realpath(existingAncestor).catch(() => null);
97
+ if (realAncestor !== null) return path.join(realAncestor, ...missingSegments);
98
+ const parent = path.dirname(existingAncestor);
99
+ if (parent === existingAncestor) return resolvedPath;
100
+ missingSegments.unshift(path.basename(existingAncestor));
101
+ existingAncestor = parent;
102
+ }
103
+ }
104
+ function createOwnedPathsLedger({ filePath, log = console }) {
105
+ const entriesByPath = /* @__PURE__ */ new Map();
106
+ const keysRecordedThisRun = /* @__PURE__ */ new Set();
107
+ let isLoaded = false;
108
+ const store = createJsonStateStore({
109
+ name: "owned paths ledger",
110
+ filePath,
111
+ parse: (raw) => OwnedPathsLedger.safeParse(raw).data ?? null,
112
+ adopt: (ledger) => {
113
+ entriesByPath.clear();
114
+ for (const entry of ledger?.entries ?? []) entriesByPath.set(ledgerKey(entry.path), entry);
115
+ isLoaded = true;
116
+ },
117
+ warn: (message, fields) => log.warn(`[owned-paths] ${message} ${JSON.stringify(fields)}`)
118
+ });
119
+ async function persist() {
120
+ const ledger = {
121
+ version: 1,
122
+ entries: [...entriesByPath.values()]
123
+ };
124
+ await store.write(ledger, () => `${JSON.stringify(ledger, null, 2)}\n`);
125
+ }
126
+ async function record(entry) {
127
+ await store.load();
128
+ if (!isLoaded) return;
129
+ const canonicalEntry = {
130
+ ...entry,
131
+ path: await canonicalOwnedPath(entry.path)
132
+ };
133
+ const canonicalKey = ledgerKey(canonicalEntry.path);
134
+ keysRecordedThisRun.add(canonicalKey);
135
+ entriesByPath.set(canonicalKey, canonicalEntry);
136
+ await persist();
137
+ }
138
+ async function forget(ownedPath) {
139
+ await store.load();
140
+ if (!isLoaded || !entriesByPath.delete(ledgerKey(await canonicalOwnedPath(ownedPath)))) return;
141
+ await persist();
142
+ }
143
+ async function loadEarlierRunEntries() {
144
+ await store.load();
145
+ if (!isLoaded) return { ok: false };
146
+ return {
147
+ ok: true,
148
+ entries: [...entriesByPath.entries()].filter(([key]) => !keysRecordedThisRun.has(key)).map(([, entry]) => entry)
149
+ };
150
+ }
151
+ return {
152
+ loadEarlierRunEntries,
153
+ record,
154
+ forget,
155
+ idle: () => store.idle()
156
+ };
157
+ }
158
+ async function pathExists$1(ownedPath) {
159
+ return fs$1.lstat(ownedPath).then(() => true, () => false);
160
+ }
161
+ async function holdsCheckout(folderPath) {
162
+ const children = await fs$1.readdir(folderPath).catch(() => []);
163
+ return (await Promise.all(children.map((child) => pathExists$1(path.join(folderPath, child, ".git"))))).includes(true);
164
+ }
165
+ async function removeOrphanedWorktree(entry, git, shareList) {
166
+ if (!entry.projectPath || !entry.branch) return "it names no repository and branch to check its work against";
167
+ const work = await git.describeWorkspaceMemberWork({
168
+ projectPath: entry.projectPath,
169
+ cwd: entry.path,
170
+ branch: entry.branch
171
+ });
172
+ if (work) return work;
173
+ const removed = await git.removeWorkspaceMember({
174
+ projectPath: entry.projectPath,
175
+ cwd: entry.path,
176
+ shareList
177
+ });
178
+ if (!removed.ok || await pathExists$1(entry.path)) return `git could not remove it: ${removed.err || "the folder is still there"}`;
179
+ return null;
180
+ }
181
+ async function removeOrphanedFolder(entry, ledger, keptPaths) {
182
+ if (holdsKeptPath(entry.path, keptPaths)) return "it holds a checkout that was kept";
183
+ if (await holdsCheckout(entry.path)) return "it still holds a checkout";
184
+ const removal = await fs$1.rm(entry.path, {
185
+ recursive: true,
186
+ force: true
187
+ }).then(() => null, (error) => `it could not be deleted: ${errorMessage(error)}`);
188
+ if (removal) return removal;
189
+ await ledger.forget(entry.path);
190
+ return null;
191
+ }
192
+ async function reconcileOwnedPaths({ ledger, configuredSessionIds, git, shareList, log = console }) {
193
+ const loaded = await ledger.loadEarlierRunEntries();
194
+ if (!loaded.ok) {
195
+ log.warn("[owned-paths] deleted nothing at startup because the owned paths ledger could not be read");
196
+ return;
197
+ }
198
+ const keptPaths = [];
199
+ for (const entry of orphanedOwnedPaths(loaded.entries, configuredSessionIds)) {
200
+ if (!await pathExists$1(entry.path)) {
201
+ await ledger.forget(entry.path);
202
+ continue;
203
+ }
204
+ const keepReason = entry.kind === "folder" ? await removeOrphanedFolder(entry, ledger, keptPaths) : await removeOrphanedWorktree(entry, git, shareList);
205
+ if (!keepReason) {
206
+ log.log(`[owned-paths] deleted ${entry.path}, left by ${entry.owner}`);
207
+ continue;
208
+ }
209
+ keptPaths.push(entry.path);
210
+ log.warn(`[owned-paths] kept ${entry.path}, left by ${entry.owner}, because ${keepReason}`);
211
+ }
212
+ }
213
+ //#endregion
52
214
  //#region server/core/restart-strategy.ts
53
215
  function decideRestartStrategy(env) {
54
216
  const invocationId = env ? env.INVOCATION_ID : void 0;
@@ -1363,7 +1525,7 @@ function decideByteRange(rangeHeader, sizeBytes) {
1363
1525
  var CUSTOM_SOUNDS_ROUTE = "/custom-sounds";
1364
1526
  async function listCustomSounds(soundsDir) {
1365
1527
  try {
1366
- return selectCustomSoundNames((await fsp.readdir(soundsDir, { withFileTypes: true })).map((entry) => ({
1528
+ return selectCustomSoundNames((await fs$1.readdir(soundsDir, { withFileTypes: true })).map((entry) => ({
1367
1529
  name: entry.name,
1368
1530
  isFile: entry.isFile()
1369
1531
  })));
@@ -1373,10 +1535,10 @@ async function listCustomSounds(soundsDir) {
1373
1535
  }
1374
1536
  async function resolveServableSound(soundsDir, name) {
1375
1537
  try {
1376
- const realDirectory = await fsp.realpath(soundsDir);
1377
- const realFile = await fsp.realpath(path.join(soundsDir, name));
1538
+ const realDirectory = await fs$1.realpath(soundsDir);
1539
+ const realFile = await fs$1.realpath(path.join(soundsDir, name));
1378
1540
  if (!isDirectChildOf$1(realDirectory, realFile)) return null;
1379
- const linkStats = await fsp.lstat(path.join(soundsDir, name));
1541
+ const linkStats = await fs$1.lstat(path.join(soundsDir, name));
1380
1542
  if (!linkStats.isFile()) return null;
1381
1543
  return {
1382
1544
  realFile,
@@ -1584,12 +1746,12 @@ function isStatuslineEvent(event) {
1584
1746
  async function sweepSessionUploads(dir, justWritten) {
1585
1747
  let entries = null;
1586
1748
  try {
1587
- entries = await fsp.readdir(dir);
1749
+ entries = await fs$1.readdir(dir);
1588
1750
  } catch {
1589
1751
  return;
1590
1752
  }
1591
1753
  for (const name of planUploadRetention(entries, { justWritten })) try {
1592
- await fsp.unlink(path.join(dir, name));
1754
+ await fs$1.unlink(path.join(dir, name));
1593
1755
  } catch {}
1594
1756
  }
1595
1757
  function receiveUpload({ req, res, sess, dir, filename, savedPath }) {
@@ -1604,7 +1766,7 @@ function receiveUpload({ req, res, sess, dir, filename, savedPath }) {
1604
1766
  let discardWanted = false;
1605
1767
  let streamClosed = false;
1606
1768
  const unlinkPartial = () => {
1607
- fsp.unlink(savedPath).catch(() => {});
1769
+ fs$1.unlink(savedPath).catch(() => {});
1608
1770
  };
1609
1771
  const discardPartial = () => {
1610
1772
  discardWanted = true;
@@ -1929,7 +2091,7 @@ function createBackendHttpApp(dependencies) {
1929
2091
  abortedBeforeReceive = true;
1930
2092
  };
1931
2093
  req.on("error", markAbortedBeforeReceive);
1932
- fsp.mkdir(dir, {
2094
+ fs$1.mkdir(dir, {
1933
2095
  recursive: true,
1934
2096
  mode: 448
1935
2097
  }).then(() => {
@@ -1955,7 +2117,7 @@ function createBackendHttpApp(dependencies) {
1955
2117
  return;
1956
2118
  }
1957
2119
  const savedPath = path.join(uploadsRoot, sessionId, filename);
1958
- fsp.lstat(savedPath).then((savedStat) => {
2120
+ fs$1.lstat(savedPath).then((savedStat) => {
1959
2121
  if (!savedStat.isFile()) {
1960
2122
  res.status(404).end();
1961
2123
  return;
@@ -5819,6 +5981,1006 @@ function decideMarkerBase({ marker, fallbackBase, configuredIntegrationBranch, d
5819
5981
  };
5820
5982
  }
5821
5983
  //#endregion
5984
+ //#region shared/contracts/guardrails-launch.ts
5985
+ var GuardrailsLaunchLogin = z.object({
5986
+ linkPath: z.string().min(1),
5987
+ targetPath: z.string().min(1)
5988
+ }).strict();
5989
+ var GuardrailsLaunchOwner = z.object({
5990
+ ownerPid: z.number().int().positive(),
5991
+ ownerHost: z.string(),
5992
+ ownerPidNamespace: z.string().nullable(),
5993
+ ownsTempDir: z.boolean(),
5994
+ keptTempFolderName: z.string().min(1).optional(),
5995
+ logins: z.array(GuardrailsLaunchLogin),
5996
+ placeholderPaths: z.array(z.string().min(1))
5997
+ }).strict();
5998
+ //#endregion
5999
+ //#region server/core/claude-trust-core.ts
6000
+ var CLAUDE_GLOBAL_CONFIG_FILE_NAME = ".claude.json";
6001
+ var CLAUDE_LEGACY_CONFIG_FILE_NAME = ".config.json";
6002
+ var CLAUDE_CONFIG_LOCK_SUFFIX = ".lock";
6003
+ var CLAUDE_CONFIG_LOCK_STALE_MS = 1e4;
6004
+ var CLAUDE_CONFIG_LOCK_RETRY_DELAYS_MS = Object.freeze([
6005
+ 200,
6006
+ 400,
6007
+ 800,
6008
+ 1600
6009
+ ]);
6010
+ var GRANTED_KEYS = Object.freeze([
6011
+ "hasTrustDialogAccepted",
6012
+ "hasClaudeMdExternalIncludesApproved",
6013
+ "hasClaudeMdExternalIncludesWarningShown"
6014
+ ]);
6015
+ var TRUST_ONLY_KEYS = Object.freeze(["hasTrustDialogAccepted"]);
6016
+ function isPlainRecord(value) {
6017
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6018
+ }
6019
+ function newProjectEntry() {
6020
+ return {
6021
+ allowedTools: [],
6022
+ mcpContextUris: [],
6023
+ mcpServers: {},
6024
+ enabledMcpjsonServers: [],
6025
+ disabledMcpjsonServers: []
6026
+ };
6027
+ }
6028
+ function listClaudeGlobalConfigPathCandidates(env, homeDir) {
6029
+ const configuredDir = env.CLAUDE_CONFIG_DIR?.trim();
6030
+ const legacyConfigHome = (configuredDir || path.join(homeDir, ".claude")).normalize("NFC");
6031
+ return [path.join(legacyConfigHome, CLAUDE_LEGACY_CONFIG_FILE_NAME), path.join(configuredDir || homeDir, CLAUDE_GLOBAL_CONFIG_FILE_NAME)];
6032
+ }
6033
+ function claudeProjectKeyOf(folderPath, platform) {
6034
+ if (platform !== "win32") return path.posix.normalize(folderPath);
6035
+ return path.win32.normalize(folderPath).replaceAll("\\", "/");
6036
+ }
6037
+ function repositoryRootOfCommonGitDir(commonGitDir) {
6038
+ if (!path.isAbsolute(commonGitDir) || path.basename(commonGitDir) !== ".git") return null;
6039
+ return path.dirname(commonGitDir);
6040
+ }
6041
+ function isConfigLockStale(lockModifiedMs, nowMs) {
6042
+ return nowMs - lockModifiedMs > CLAUDE_CONFIG_LOCK_STALE_MS;
6043
+ }
6044
+ function hasRecordedExternalImportsDecline(existingEntry) {
6045
+ return existingEntry?.hasClaudeMdExternalIncludesWarningShown === true && existingEntry.hasClaudeMdExternalIncludesApproved !== true;
6046
+ }
6047
+ function decideFolderTrust(configText, repositoryRoot, platform) {
6048
+ const projectKey = claudeProjectKeyOf(repositoryRoot, platform);
6049
+ let config;
6050
+ try {
6051
+ config = JSON.parse(configText);
6052
+ } catch {
6053
+ return {
6054
+ kind: "unreadable",
6055
+ reason: "it is not valid JSON"
6056
+ };
6057
+ }
6058
+ if (!isPlainRecord(config)) return {
6059
+ kind: "unreadable",
6060
+ reason: "it is not a JSON object"
6061
+ };
6062
+ const projects = config.projects ?? {};
6063
+ if (!isPlainRecord(projects)) return {
6064
+ kind: "unreadable",
6065
+ reason: "its projects key is not an object"
6066
+ };
6067
+ const existingEntry = projects[projectKey];
6068
+ if (existingEntry !== void 0 && !isPlainRecord(existingEntry)) return {
6069
+ kind: "unreadable",
6070
+ reason: "its entry for this folder is not an object"
6071
+ };
6072
+ const keysToGrant = hasRecordedExternalImportsDecline(existingEntry) ? TRUST_ONLY_KEYS : GRANTED_KEYS;
6073
+ if (keysToGrant.every((key) => existingEntry?.[key] === true)) return { kind: "trusted" };
6074
+ const trustedEntry = {
6075
+ ...existingEntry ?? newProjectEntry(),
6076
+ ...Object.fromEntries(keysToGrant.map((key) => [key, true]))
6077
+ };
6078
+ const nextConfigText = JSON.stringify({
6079
+ ...config,
6080
+ projects: {
6081
+ ...projects,
6082
+ [projectKey]: trustedEntry
6083
+ }
6084
+ }, null, 2);
6085
+ return {
6086
+ kind: "grant",
6087
+ nextConfigText: configText.endsWith("\n") ? `${nextConfigText}\n` : nextConfigText
6088
+ };
6089
+ }
6090
+ //#endregion
6091
+ //#region server/guardrails/core/guardrails-bridge-socket-core.ts
6092
+ var LONGEST_BRIDGE_SOCKET_NAME = "claude-socks-0123456789abcdef.sock";
6093
+ var UNIX_SOCKET_PATH_BYTE_LIMIT = 107;
6094
+ var SHORT_BRIDGE_SOCKET_FOLDER = "/tmp";
6095
+ function bridgeSocketPathBytes(tempDirectory) {
6096
+ return Buffer.byteLength(path.join(tempDirectory, LONGEST_BRIDGE_SOCKET_NAME));
6097
+ }
6098
+ function hasRoomForBridgeSocket(tempDirectory, platform) {
6099
+ return platform !== "linux" || bridgeSocketPathBytes(tempDirectory) <= UNIX_SOCKET_PATH_BYTE_LIMIT;
6100
+ }
6101
+ function bridgeSocketLauncherEnv(inheritedTempDirectory, platform) {
6102
+ if (hasRoomForBridgeSocket(inheritedTempDirectory, platform)) return { TMPDIR: inheritedTempDirectory };
6103
+ return { TMPDIR: SHORT_BRIDGE_SOCKET_FOLDER };
6104
+ }
6105
+ //#endregion
6106
+ //#region server/guardrails/core/guardrails-policy-core.ts
6107
+ var VENDOR_PROFILES = Object.freeze({
6108
+ claude: {
6109
+ homeEntries: [".claude", ".claude.json"],
6110
+ launchWritableFolders: ({ cwd, agentSessionId }) => [path.join("projects", encodeProjectDir(cwd)), ...agentSessionId === null ? [] : [path.join("session-env", agentSessionId)]],
6111
+ launchPrivateFolders: ["shell-snapshots"],
6112
+ launchHomeEnvName: null,
6113
+ loginFiles: [".credentials.json"],
6114
+ configEntries: [
6115
+ "settings.json",
6116
+ "settings.local.json",
6117
+ "hooks",
6118
+ "skills",
6119
+ "plugins",
6120
+ "commands",
6121
+ "agents",
6122
+ "CLAUDE.md",
6123
+ "AGENTS.md"
6124
+ ],
6125
+ apiDomains: ["api.anthropic.com", "platform.claude.com"],
6126
+ launchEnv: { DISABLE_AUTOUPDATER: "1" }
6127
+ },
6128
+ codex: {
6129
+ homeEntries: [".codex"],
6130
+ launchWritableFolders: () => [],
6131
+ launchPrivateFolders: [],
6132
+ launchHomeEnvName: "CODEX_HOME",
6133
+ loginFiles: ["auth.json"],
6134
+ configEntries: [
6135
+ "config.toml",
6136
+ "AGENTS.md",
6137
+ "skills",
6138
+ "rules",
6139
+ "prompts",
6140
+ "hooks.json"
6141
+ ],
6142
+ apiDomains: [
6143
+ "chatgpt.com",
6144
+ "*.chatgpt.com",
6145
+ "auth.openai.com",
6146
+ "api.openai.com",
6147
+ "*.openai.com"
6148
+ ],
6149
+ launchEnv: {}
6150
+ }
6151
+ });
6152
+ var GUARDRAILS_VENDORS = Object.freeze(["claude", "codex"]);
6153
+ var UNWRAPPED_VENDOR_HOME_ENTRIES = Object.freeze([".grok"]);
6154
+ var CREDENTIAL_HOME_ENTRIES = Object.freeze([
6155
+ ".ssh",
6156
+ ".config/gh",
6157
+ ".config/coderv2",
6158
+ "Library/Application Support/coderv2",
6159
+ "Library/Keychains",
6160
+ ".git-credentials"
6161
+ ]);
6162
+ var CLOUD_CREDENTIAL_HOME_ENTRIES = Object.freeze([
6163
+ ".aws",
6164
+ ".azure",
6165
+ ".config/gcloud",
6166
+ ".kube",
6167
+ ".docker",
6168
+ ".gnupg",
6169
+ ".netrc",
6170
+ ".npmrc"
6171
+ ]);
6172
+ var STANDARD_LEVEL_USABLE_CREDENTIAL_ENTRIES = Object.freeze(["Library/Keychains"]);
6173
+ var XDG_CONFIG_DEFAULT_HOME_PREFIX = ".config/";
6174
+ var SHARED_TEMP_DIRS = Object.freeze(["/tmp/claude", "/private/tmp/claude"]);
6175
+ var SHARED_HOME_WRITE_ENTRIES = Object.freeze([".npm/_logs"]);
6176
+ var GUARDRAILS_PLACEHOLDER_NAMES = Object.freeze([
6177
+ ".bash_profile",
6178
+ ".bashrc",
6179
+ ".claude",
6180
+ ".gitconfig",
6181
+ ".gitmodules",
6182
+ ".idea",
6183
+ ".mcp.json",
6184
+ ".profile",
6185
+ ".ripgreprc",
6186
+ ".vscode",
6187
+ ".zprofile",
6188
+ ".zshrc"
6189
+ ]);
6190
+ var WHOLE_FILESYSTEM = "/";
6191
+ var GUARDRAILS_TEMP_FOLDER = "guardrails-temp";
6192
+ var AGENT_LOGINS_SIBLING_ENTRY = "agent-logins";
6193
+ var GLIMMERVOID_CONFIG_SIBLING_ENTRIES = Object.freeze([
6194
+ AGENT_LOGINS_SIBLING_ENTRY,
6195
+ "bin",
6196
+ "pairings.json",
6197
+ "pairings-seen.json",
6198
+ "plans",
6199
+ "telegram-outbox.json",
6200
+ "traces",
6201
+ "uploads",
6202
+ "usage-budget-state.json",
6203
+ "usage-lanes.json",
6204
+ "usage-warehouse.json",
6205
+ "visions-intent.json"
6206
+ ]);
6207
+ var GLIMMERVOID_HOME_STATE_ENTRIES = Object.freeze([
6208
+ "benchmark-runs",
6209
+ "benchmarks",
6210
+ "config.json",
6211
+ "issues-cache.json",
6212
+ "litellm-pricing.json",
6213
+ "my-prs-state.json",
6214
+ "my-prs-work",
6215
+ "posthog-reports",
6216
+ "posthog-state.json",
6217
+ "posthog-work",
6218
+ "recordings",
6219
+ "guardrails-homes",
6220
+ "guardrails-policies",
6221
+ "sane-yolo",
6222
+ "scratch",
6223
+ "sounds",
6224
+ "team-review-repos",
6225
+ "team-review-state.json",
6226
+ "team-review-work",
6227
+ "team-review-worktrees",
6228
+ "telemetry-pending-crash.json",
6229
+ "telemetry.json",
6230
+ "tmp",
6231
+ "update-check.json",
6232
+ "update-journal.json",
6233
+ "workflows-state.json",
6234
+ "workflows-work"
6235
+ ]);
6236
+ var RUNTIME_MANDATORY_CLAUDE_DENY_FOLDERS = Object.freeze(["commands", "agents"]);
6237
+ var GUARDED_PROXY_BYPASS = "localhost,::1,169.254.0.0/16,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16";
6238
+ var HOOK_LOOPBACK_HOST = "127.0.0.1";
6239
+ var AGENT_SESSION_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
6240
+ var STANDARD_OPEN_NETWORK = Object.freeze({
6241
+ allowAllUnixSockets: true,
6242
+ allowMachLookup: ["*"]
6243
+ });
6244
+ var STRICT_OPEN_NETWORK = Object.freeze({ allowAllUnixSockets: false });
6245
+ function unique(entries) {
6246
+ return [...new Set(entries)];
6247
+ }
6248
+ function literalEntries(entryPaths) {
6249
+ return unique(entryPaths).map((entryPath) => ({
6250
+ path: entryPath,
6251
+ literal: true
6252
+ }));
6253
+ }
6254
+ function homePaths(host, homeEntries) {
6255
+ return homeEntries.map((entry) => path.join(host.homeDir, entry));
6256
+ }
6257
+ function isInsideAny(parents, child) {
6258
+ return parents.some((parent) => isPathInside(parent, child));
6259
+ }
6260
+ function vendorStatePaths(host, vendor, stateFolderEntries) {
6261
+ return stateFolderEntries.map((entry) => path.join(host.vendorLocations[vendor].stateFolder, entry));
6262
+ }
6263
+ function vendorHeldPaths(host, vendor) {
6264
+ const { stateFolder, configFiles, otherHomes } = host.vendorLocations[vendor];
6265
+ return [
6266
+ stateFolder,
6267
+ ...configFiles,
6268
+ ...otherHomes
6269
+ ];
6270
+ }
6271
+ function launchHomeOf(host, vendor) {
6272
+ return path.join(host.launchHomeDir, vendor);
6273
+ }
6274
+ function vendorsWithLaunchHome(role) {
6275
+ if (role.vendorHome.scope === "state") return [];
6276
+ return role.vendors.filter((vendor) => VENDOR_PROFILES[vendor].launchHomeEnvName !== null);
6277
+ }
6278
+ function vendorWritableFolders(role, host) {
6279
+ const { vendorHome } = role;
6280
+ if (vendorHome.scope === "state") return role.vendors.map((vendor) => host.vendorLocations[vendor].stateFolder);
6281
+ return role.vendors.flatMap((vendor) => {
6282
+ const profile = VENDOR_PROFILES[vendor];
6283
+ if (profile.launchHomeEnvName !== null) return [launchHomeOf(host, vendor)];
6284
+ return vendorStatePaths(host, vendor, profile.launchWritableFolders(vendorHome));
6285
+ });
6286
+ }
6287
+ function launchPrivateFolders(role, host) {
6288
+ if (role.vendorHome.scope === "state") return [];
6289
+ return role.vendors.flatMap((vendor) => vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].launchPrivateFolders));
6290
+ }
6291
+ function launchHomeLinkCandidates(role, host) {
6292
+ return vendorsWithLaunchHome(role).flatMap((vendor) => {
6293
+ const { configEntries, loginFiles } = VENDOR_PROFILES[vendor];
6294
+ const linkFor = (entry, isLogin) => ({
6295
+ linkPath: path.join(launchHomeOf(host, vendor), entry),
6296
+ targetPath: path.join(host.vendorLocations[vendor].stateFolder, entry),
6297
+ isLogin
6298
+ });
6299
+ return [...configEntries.map((entry) => linkFor(entry, false)), ...loginFiles.map((entry) => linkFor(entry, true))];
6300
+ });
6301
+ }
6302
+ function launchHomeEnv(role, host) {
6303
+ return Object.fromEntries(vendorsWithLaunchHome(role).flatMap((vendor) => {
6304
+ const envName = VENDOR_PROFILES[vendor].launchHomeEnvName;
6305
+ return envName === null ? [] : [[envName, launchHomeOf(host, vendor)]];
6306
+ }));
6307
+ }
6308
+ function vendorLoginFiles(role, host) {
6309
+ return role.vendors.flatMap((vendor) => vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].loginFiles));
6310
+ }
6311
+ function roleWritableRoots(role) {
6312
+ return [
6313
+ ...role.writableRoots,
6314
+ ...role.lockedCheckouts,
6315
+ ...role.commitCheckouts.flatMap(({ checkout, gitDir }) => [checkout, gitDir])
6316
+ ];
6317
+ }
6318
+ function alwaysWritablePaths(role, host) {
6319
+ return [
6320
+ host.tempDir,
6321
+ ...roleWritableRoots(role),
6322
+ ...vendorWritableFolders(role, host)
6323
+ ];
6324
+ }
6325
+ function commitCheckoutWriteDenies({ checkout, gitDir }) {
6326
+ const gitPointer = path.join(checkout, ".git");
6327
+ const gitDirDenies = [path.join(gitDir, "hooks"), path.join(gitDir, "config")];
6328
+ if (path.resolve(gitPointer) === path.resolve(gitDir)) return gitDirDenies;
6329
+ return [gitPointer, ...gitDirDenies];
6330
+ }
6331
+ function writeDeniesWhenPresent(role, host) {
6332
+ const writablePaths = alwaysWritablePaths(role, host);
6333
+ const sharedHomeWrites = homePaths(host, SHARED_HOME_WRITE_ENTRIES).filter((sharedPath) => !isInsideAny(roleWritableRoots(role), sharedPath));
6334
+ const vendorConfig = role.vendors.flatMap((vendor) => [...vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].configEntries), ...host.vendorLocations[vendor].configFiles]).filter((configPath) => isInsideAny(writablePaths, configPath));
6335
+ return [
6336
+ ...SHARED_TEMP_DIRS,
6337
+ ...sharedHomeWrites,
6338
+ ...vendorConfig,
6339
+ ...role.commitCheckouts.flatMap(commitCheckoutWriteDenies)
6340
+ ];
6341
+ }
6342
+ function lockedCheckoutWriteDenies(role) {
6343
+ return role.lockedCheckouts.flatMap((checkout) => [path.join(checkout, ".git"), path.join(checkout, ".claude")]);
6344
+ }
6345
+ function lockedClaudeMountPoints(role) {
6346
+ return role.lockedCheckouts.flatMap((checkout) => RUNTIME_MANDATORY_CLAUDE_DENY_FOLDERS.map((folder) => path.join(checkout, ".claude", folder)));
6347
+ }
6348
+ function guardrailsPlaceholderPaths(role) {
6349
+ return unique([...(role.vendorHome.scope === "launch" ? [role.vendorHome.cwd] : []).flatMap((workingFolder) => GUARDRAILS_PLACEHOLDER_NAMES.map((placeholderName) => path.join(workingFolder, placeholderName))), ...lockedCheckoutWriteDenies(role)]);
6350
+ }
6351
+ function homeEntriesNamedLike(host, homeEntries) {
6352
+ return host.homeEntryNames.filter((entryName) => homeEntries.some((homeEntry) => entryName.startsWith(homeEntry)));
6353
+ }
6354
+ function relocatedXdgConfigPaths(host, homeEntries) {
6355
+ const xdgConfigHome = host.relocatedXdgConfigHome;
6356
+ if (xdgConfigHome === null) return [];
6357
+ return homeEntries.filter((entry) => entry.startsWith(XDG_CONFIG_DEFAULT_HOME_PREFIX)).map((entry) => path.join(xdgConfigHome, entry.slice(8)));
6358
+ }
6359
+ function isStandardLevel(role) {
6360
+ return role.guardrailLevel === "standard";
6361
+ }
6362
+ function blockedCredentialHomeEntries(role) {
6363
+ const credentialHomeEntries = [...CREDENTIAL_HOME_ENTRIES, ...CLOUD_CREDENTIAL_HOME_ENTRIES];
6364
+ if (!isStandardLevel(role)) return credentialHomeEntries;
6365
+ return credentialHomeEntries.filter((entry) => !STANDARD_LEVEL_USABLE_CREDENTIAL_ENTRIES.includes(entry));
6366
+ }
6367
+ function credentialWriteBlocks(role, host) {
6368
+ const credentialHomeEntries = blockedCredentialHomeEntries(role);
6369
+ return [...homePaths(host, credentialHomeEntries), ...relocatedXdgConfigPaths(host, credentialHomeEntries)];
6370
+ }
6371
+ function glimmervoidStateWriteBlocks(role, host) {
6372
+ const keptWritable = alwaysWritablePaths(role, host);
6373
+ const configFolder = path.dirname(host.glimmervoidConfigFile);
6374
+ const homeEntries = [
6375
+ ...GLIMMERVOID_HOME_STATE_ENTRIES,
6376
+ ...GLIMMERVOID_CONFIG_SIBLING_ENTRIES,
6377
+ ...host.glimmervoidHomeEntryNames
6378
+ ].map((entryName) => path.join(host.glimmervoidHome, entryName));
6379
+ const configSiblings = GLIMMERVOID_CONFIG_SIBLING_ENTRIES.map((entryName) => path.join(configFolder, entryName));
6380
+ return unique([
6381
+ host.glimmervoidConfigFile,
6382
+ ...homeEntries,
6383
+ ...configSiblings
6384
+ ]).filter((entryPath) => !keptWritable.some((writable) => isPathInside(entryPath, writable)));
6385
+ }
6386
+ function standardWriteBlockCandidates(role, host) {
6387
+ if (!isStandardLevel(role)) return [];
6388
+ return unique([
6389
+ ...credentialWriteBlocks(role, host),
6390
+ ...glimmervoidStateWriteBlocks(role, host),
6391
+ ...role.blockedPaths ?? []
6392
+ ]);
6393
+ }
6394
+ function readDeniedPaths(role, host) {
6395
+ const otherVendors = GUARDRAILS_VENDORS.filter((vendor) => !role.vendors.includes(vendor));
6396
+ const otherVendorHomeEntries = [...otherVendors.flatMap((vendor) => VENDOR_PROFILES[vendor].homeEntries), ...UNWRAPPED_VENDOR_HOME_ENTRIES];
6397
+ const credentialHomeEntries = blockedCredentialHomeEntries(role);
6398
+ return [
6399
+ ...homePaths(host, [
6400
+ ...credentialHomeEntries,
6401
+ ...otherVendorHomeEntries,
6402
+ ...homeEntriesNamedLike(host, otherVendorHomeEntries)
6403
+ ]),
6404
+ ...relocatedXdgConfigPaths(host, credentialHomeEntries),
6405
+ ...otherVendors.flatMap((vendor) => vendorHeldPaths(host, vendor)),
6406
+ ...host.unwrappedVendorHomes,
6407
+ host.glimmervoidHome,
6408
+ path.join(path.dirname(host.glimmervoidConfigFile), AGENT_LOGINS_SIBLING_ENTRY),
6409
+ ...launchPrivateFolders(role, host),
6410
+ ...role.readDenied
6411
+ ];
6412
+ }
6413
+ function guardrailsPolicyProbePaths(role, host) {
6414
+ return unique([
6415
+ ...writeDeniesWhenPresent(role, host),
6416
+ ...vendorLoginFiles(role, host),
6417
+ ...launchHomeLinkCandidates(role, host).map((link) => link.targetPath)
6418
+ ]);
6419
+ }
6420
+ function isValidPort(port) {
6421
+ return Number.isInteger(port) && port >= 1 && port <= 65535;
6422
+ }
6423
+ function hostNamedPaths(host) {
6424
+ const relocatedXdgConfigHomes = host.relocatedXdgConfigHome === null ? [] : [host.relocatedXdgConfigHome];
6425
+ return [
6426
+ host.homeDir,
6427
+ host.glimmervoidHome,
6428
+ host.glimmervoidConfigFile,
6429
+ host.tempDir,
6430
+ host.launchHomeDir,
6431
+ ...relocatedXdgConfigHomes,
6432
+ ...host.unwrappedVendorHomes,
6433
+ ...GUARDRAILS_VENDORS.flatMap((vendor) => vendorHeldPaths(host, vendor))
6434
+ ];
6435
+ }
6436
+ function guardrailsRoleRefusal(role, host) {
6437
+ const launchCwds = role.vendorHome.scope === "launch" ? [role.vendorHome.cwd] : [];
6438
+ const relativePath = [
6439
+ ...hostNamedPaths(host),
6440
+ ...roleWritableRoots(role),
6441
+ ...role.readDenied,
6442
+ ...role.readableWithinDenied,
6443
+ ...launchCwds
6444
+ ].find((namedPath) => !path.isAbsolute(namedPath));
6445
+ if (relativePath !== void 0) return `guardrails policy path is not absolute: ${relativePath}`;
6446
+ const rootOverProtectedHome = [...roleWritableRoots(role), ...vendorWritableFolders(role, host)].find((root) => isPathInside(root, host.homeDir) || isPathInside(root, host.glimmervoidHome));
6447
+ if (rootOverProtectedHome !== void 0) return `writable root ${rootOverProtectedHome} contains the home folder or the Glimmervoid home`;
6448
+ const writablePaths = alwaysWritablePaths(role, host);
6449
+ const reallowedAncestor = role.readableWithinDenied.find((readable) => writablePaths.some((writable) => isPathInside(readable, writable, { allowEqual: false })));
6450
+ if (reallowedAncestor !== void 0) return `readable path ${reallowedAncestor} is an ancestor of a writable root`;
6451
+ if (role.network.access === "allowlist" && role.network.hookPort !== null && !isValidPort(role.network.hookPort)) return "hook listener port is invalid";
6452
+ const agentSessionId = role.vendorHome.scope === "launch" ? role.vendorHome.agentSessionId : null;
6453
+ if (agentSessionId !== null && !AGENT_SESSION_ID_SHAPE.test(agentSessionId)) return "agent session id is invalid";
6454
+ return null;
6455
+ }
6456
+ function networkPolicy(role) {
6457
+ if (role.network.access === "open") return isStandardLevel(role) ? { ...STANDARD_OPEN_NETWORK } : { ...STRICT_OPEN_NETWORK };
6458
+ if (role.network.access === "none") return {
6459
+ allowedDomains: [],
6460
+ deniedDomains: [],
6461
+ allowLocalBinding: false,
6462
+ allowAllUnixSockets: false
6463
+ };
6464
+ const hookEndpoint = role.network.hookPort === null ? [] : [`${HOOK_LOOPBACK_HOST}:${role.network.hookPort}`];
6465
+ const vendorDomains = role.vendors.flatMap((vendor) => VENDOR_PROFILES[vendor].apiDomains);
6466
+ return {
6467
+ allowedDomains: unique([
6468
+ ...hookEndpoint,
6469
+ ...vendorDomains,
6470
+ ...role.network.domains
6471
+ ]),
6472
+ deniedDomains: [],
6473
+ strictAllowlist: true,
6474
+ allowLocalBinding: false,
6475
+ allowAllUnixSockets: false
6476
+ };
6477
+ }
6478
+ function guardedEnvFor(role, host) {
6479
+ if (role.network.access === "allowlist") return {
6480
+ NO_PROXY: GUARDED_PROXY_BYPASS,
6481
+ no_proxy: GUARDED_PROXY_BYPASS,
6482
+ [HOOK_VIA_GUARDRAILS_PROXY_ENV]: "1"
6483
+ };
6484
+ if (role.network.access === "open") return { TMPDIR: host.tempDir };
6485
+ return {};
6486
+ }
6487
+ function filesystemWrites(role, host, writablePaths) {
6488
+ if (isStandardLevel(role)) return {
6489
+ allowWrite: literalEntries([WHOLE_FILESYSTEM, ...writablePaths]),
6490
+ denyWrite: literalEntries(host.writeBlockedPaths)
6491
+ };
6492
+ const isPresent = (candidate) => host.existingPaths.has(candidate);
6493
+ return {
6494
+ allowWrite: literalEntries(writablePaths),
6495
+ denyWrite: literalEntries([...writeDeniesWhenPresent(role, host).filter(isPresent), ...lockedCheckoutWriteDenies(role)])
6496
+ };
6497
+ }
6498
+ function buildGuardrailsLaunchPlan(role, host) {
6499
+ const refusal = guardrailsRoleRefusal(role, host);
6500
+ if (refusal !== null) return {
6501
+ ok: false,
6502
+ reason: refusal
6503
+ };
6504
+ const isPresent = (candidate) => host.existingPaths.has(candidate);
6505
+ const writablePaths = [...alwaysWritablePaths(role, host), ...vendorLoginFiles(role, host).filter(isPresent)];
6506
+ const readDenied = readDeniedPaths(role, host);
6507
+ const writableWithinDenied = writablePaths.filter((writable) => isInsideAny(readDenied, writable));
6508
+ return {
6509
+ ok: true,
6510
+ plan: {
6511
+ launcher: role.network.access === "open" ? "open-network" : "runtime-cli",
6512
+ policy: {
6513
+ network: networkPolicy(role),
6514
+ filesystem: {
6515
+ denyRead: literalEntries(readDenied),
6516
+ allowRead: literalEntries([...writableWithinDenied, ...role.readableWithinDenied]),
6517
+ ...filesystemWrites(role, host, writablePaths)
6518
+ },
6519
+ terminalScope: isStandardLevel(role) ? "any" : "own",
6520
+ allowAppleEvents: isStandardLevel(role)
6521
+ },
6522
+ launchEnv: Object.assign({ CLAUDE_CODE_TMPDIR: host.tempDir }, ...role.vendors.map((vendor) => VENDOR_PROFILES[vendor].launchEnv), launchHomeEnv(role, host)),
6523
+ guardedEnv: guardedEnvFor(role, host),
6524
+ requiredDirectories: unique([
6525
+ host.tempDir,
6526
+ ...vendorWritableFolders(role, host),
6527
+ ...launchPrivateFolders(role, host)
6528
+ ]),
6529
+ launchHomeLinks: launchHomeLinkCandidates(role, host).filter((link) => isPresent(link.targetPath))
6530
+ }
6531
+ };
6532
+ }
6533
+ //#endregion
6534
+ //#region server/prune-files.ts
6535
+ var MS_PER_DAY = 864e5;
6536
+ function idForEntry(entry, suffixes) {
6537
+ for (const suffix of suffixes) {
6538
+ if (suffix.length === 0) return entry;
6539
+ if (entry.endsWith(suffix)) return entry.slice(0, -suffix.length);
6540
+ }
6541
+ return null;
6542
+ }
6543
+ async function pruneAgedFiles({ directory, suffixes, retainDays, now = Date.now(), isRetainedId = () => false, entryMode = "file", fsPromises = fs.promises }) {
6544
+ let entries;
6545
+ try {
6546
+ entries = await fsPromises.readdir(directory);
6547
+ } catch {
6548
+ return [];
6549
+ }
6550
+ const cutoff = now - retainDays * MS_PER_DAY;
6551
+ const removedIds = [];
6552
+ for (const entry of entries) {
6553
+ const id = idForEntry(entry, suffixes);
6554
+ if (!id || isRetainedId(id)) continue;
6555
+ const filePath = path.join(directory, entry);
6556
+ try {
6557
+ if ((await fsPromises.stat(filePath)).mtimeMs >= cutoff) continue;
6558
+ if (entryMode === "directory") await fsPromises.rm(filePath, {
6559
+ recursive: true,
6560
+ force: true
6561
+ });
6562
+ if (entryMode === "file") await fsPromises.unlink(filePath);
6563
+ removedIds.push(id);
6564
+ } catch {}
6565
+ }
6566
+ return removedIds;
6567
+ }
6568
+ //#endregion
6569
+ //#region server/guardrails/guardrails-launch.ts
6570
+ var LAUNCH_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
6571
+ var GUARDED_ENV_COMMAND = "/usr/bin/env";
6572
+ var POLICY_FOLDER = "guardrails-policies";
6573
+ var LAUNCH_HOME_FOLDER = "guardrails-homes";
6574
+ var START_FOLDER = "start";
6575
+ var OWNER_FILE_SUFFIX = ".owner.json";
6576
+ var ENTER_FOLDER_SCRIPT = "cd \"$1\" && shift && exec \"$@\"";
6577
+ var LOGIN_FILE_MODE = 384;
6578
+ var ABSENT_PATH_DENY_PLATFORM = "darwin";
6579
+ var OWN_PID_NAMESPACE_LINK = "/proc/self/ns/pid";
6580
+ var SESSION_TEMP_RETAIN_DAYS = 7;
6581
+ async function isPresent(candidate) {
6582
+ try {
6583
+ await access(candidate);
6584
+ return true;
6585
+ } catch (error) {
6586
+ if (!isMissingFileError(error)) throw error;
6587
+ return false;
6588
+ }
6589
+ }
6590
+ async function presentPaths$1(candidates) {
6591
+ const presence = await Promise.all(candidates.map(isPresent));
6592
+ return new Set(candidates.filter((_candidate, index) => presence[index]));
6593
+ }
6594
+ async function realPathWhenPresent(candidate) {
6595
+ if (!path.isAbsolute(candidate)) return candidate;
6596
+ try {
6597
+ return await realpath(candidate);
6598
+ } catch (error) {
6599
+ if (!isMissingFileError(error)) throw error;
6600
+ return candidate;
6601
+ }
6602
+ }
6603
+ function realPathsWhenPresent(candidates) {
6604
+ return Promise.all(candidates.map(realPathWhenPresent));
6605
+ }
6606
+ async function symlinkTargetsInside(folder) {
6607
+ const symlinkEntries = (await readdir(folder, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isSymbolicLink());
6608
+ return (await Promise.all(symlinkEntries.map((entry) => realpath(path.join(folder, entry.name)).catch(() => null)))).filter((target) => target !== null);
6609
+ }
6610
+ async function blockedPathsWithRealTargets(candidates, operatorBlockedPaths) {
6611
+ const resolved = await Promise.all(candidates.map(async (candidate) => {
6612
+ const isPresentEntry = await lstat(candidate).then(() => true, (error) => !isMissingFileError(error));
6613
+ const isKeptWhenAbsent = process.platform === ABSENT_PATH_DENY_PLATFORM || operatorBlockedPaths.includes(candidate);
6614
+ if (!isPresentEntry) return isKeptWhenAbsent ? [candidate] : [];
6615
+ const realCandidate = await realpath(candidate).catch(() => candidate);
6616
+ return [
6617
+ candidate,
6618
+ realCandidate,
6619
+ ...await symlinkTargetsInside(realCandidate)
6620
+ ];
6621
+ }));
6622
+ return [...new Set(resolved.flat())];
6623
+ }
6624
+ async function configuredConfigFile(glimmervoidHome) {
6625
+ const { envPath, homePath } = decideConfigPath({
6626
+ env: process.env,
6627
+ homeDir: glimmervoidHome
6628
+ }, () => false);
6629
+ const configFile = envPath ?? homePath;
6630
+ return path.join(await realPathWhenPresent(path.dirname(configFile)), path.basename(configFile));
6631
+ }
6632
+ function scannedClaudeHomes(env, homeDir) {
6633
+ return [env, {
6634
+ ...env,
6635
+ CLAUDE_CONFIG_DIR: void 0
6636
+ }].flatMap((scannedEnv) => projectDirCandidates(scannedEnv, [], homeDir)).map((projectsDir) => path.dirname(projectsDir));
6637
+ }
6638
+ async function resolveVendorLocations(env, homeDir) {
6639
+ const [legacyClaudeConfigPath, claudeConfigPath] = listClaudeGlobalConfigPathCandidates(env, homeDir);
6640
+ const [codexStateFolder, ...otherCodexHomes] = codexHomes(env, homeDir);
6641
+ if (codexStateFolder === void 0) return null;
6642
+ return {
6643
+ claude: {
6644
+ stateFolder: await realPathWhenPresent(path.dirname(legacyClaudeConfigPath)),
6645
+ configFiles: [await realPathWhenPresent(claudeConfigPath)],
6646
+ otherHomes: await realPathsWhenPresent(scannedClaudeHomes(env, homeDir))
6647
+ },
6648
+ codex: {
6649
+ stateFolder: await realPathWhenPresent(codexStateFolder),
6650
+ configFiles: [],
6651
+ otherHomes: await realPathsWhenPresent(otherCodexHomes)
6652
+ }
6653
+ };
6654
+ }
6655
+ async function withRealRoots(role) {
6656
+ const [writableRoots, lockedCheckouts, commitCheckouts] = await Promise.all([
6657
+ Promise.all(role.writableRoots.map((root) => realpath(root))),
6658
+ Promise.all(role.lockedCheckouts.map((checkout) => realpath(checkout))),
6659
+ Promise.all(role.commitCheckouts.map(async ({ checkout, gitDir }) => ({
6660
+ checkout: await realpath(checkout),
6661
+ gitDir: await realpath(gitDir)
6662
+ })))
6663
+ ]);
6664
+ const vendorHome = role.vendorHome.scope === "launch" ? {
6665
+ ...role.vendorHome,
6666
+ cwd: await realPathWhenPresent(role.vendorHome.cwd)
6667
+ } : role.vendorHome;
6668
+ return {
6669
+ ...role,
6670
+ vendorHome,
6671
+ writableRoots,
6672
+ lockedCheckouts,
6673
+ commitCheckouts,
6674
+ readableWithinDenied: await realPathsWhenPresent(role.readableWithinDenied)
6675
+ };
6676
+ }
6677
+ async function lstatWhenPresent(candidate) {
6678
+ try {
6679
+ return await lstat(candidate);
6680
+ } catch (error) {
6681
+ if (!isMissingFileError(error)) throw error;
6682
+ return null;
6683
+ }
6684
+ }
6685
+ async function isRegularFile(candidate) {
6686
+ return (await lstatWhenPresent(candidate))?.isFile() ?? false;
6687
+ }
6688
+ async function isRealDirectory$1(candidate) {
6689
+ return (await lstatWhenPresent(candidate))?.isDirectory() ?? false;
6690
+ }
6691
+ async function absentPaths(candidates) {
6692
+ const presentCandidates = await presentPaths$1(candidates);
6693
+ return candidates.filter((candidate) => !presentCandidates.has(candidate));
6694
+ }
6695
+ async function removeLeftoverPlaceholders(placeholderPaths) {
6696
+ for (const placeholderPath of placeholderPaths) {
6697
+ const placeholderStats = await lstat(placeholderPath).catch(() => null);
6698
+ if (placeholderStats?.isFile() && placeholderStats.size === 0) await rm(placeholderPath, { force: true });
6699
+ }
6700
+ }
6701
+ async function createMissingMountPoints(mountPoints) {
6702
+ for (const mountPoint of mountPoints) {
6703
+ if (!await isRealDirectory$1(path.dirname(mountPoint))) continue;
6704
+ await mkdir(mountPoint).catch((error) => {
6705
+ if (errorCode(error) !== "EEXIST") throw error;
6706
+ });
6707
+ }
6708
+ }
6709
+ async function isNewerThanTarget(linkPath, targetPath) {
6710
+ const targetStats = await stat(targetPath).catch(() => null);
6711
+ if (targetStats === null) return true;
6712
+ return (await lstat(linkPath)).mtimeMs > targetStats.mtimeMs;
6713
+ }
6714
+ async function keepRefreshedLogins(logins, launchId, { onlyWhenNewer }) {
6715
+ for (const { linkPath, targetPath } of logins) {
6716
+ if (!await isRegularFile(linkPath)) continue;
6717
+ if (onlyWhenNewer && !await isNewerThanTarget(linkPath, targetPath)) continue;
6718
+ const stagedPath = `${targetPath}.${launchId}`;
6719
+ await copyFile(linkPath, stagedPath);
6720
+ await chmod(stagedPath, LOGIN_FILE_MODE);
6721
+ await rename(stagedPath, targetPath);
6722
+ }
6723
+ }
6724
+ async function removeLaunch(folders, owner, launchId, { onlyNewerLogins }) {
6725
+ await rm(folders.policyPath, { force: true });
6726
+ await removeLeftoverPlaceholders(owner.placeholderPaths);
6727
+ await keepRefreshedLogins(owner.logins.filter((login) => isPathInside(folders.launchHomeDir, login.linkPath, { allowEqual: false })), launchId, { onlyWhenNewer: onlyNewerLogins });
6728
+ await rm(folders.launchHomeDir, {
6729
+ recursive: true,
6730
+ force: true
6731
+ });
6732
+ if (folders.ownedTempDir !== null) await rm(folders.ownedTempDir, {
6733
+ recursive: true,
6734
+ force: true
6735
+ });
6736
+ await rm(folders.ownerPath, { force: true });
6737
+ }
6738
+ function isProcessAlive$1(pid) {
6739
+ try {
6740
+ process.kill(pid, 0);
6741
+ return true;
6742
+ } catch (error) {
6743
+ return errorCode(error) === "EPERM";
6744
+ }
6745
+ }
6746
+ function readOwnPidNamespace() {
6747
+ return readlink(OWN_PID_NAMESPACE_LINK).catch(() => null);
6748
+ }
6749
+ async function readOwnerFile(ownerPath) {
6750
+ const outcome = await loadJsonStateFile({
6751
+ filePath: ownerPath,
6752
+ quarantine: false,
6753
+ parse: (raw) => GuardrailsLaunchOwner.safeParse(raw).data ?? null
6754
+ });
6755
+ return outcome.status === "loaded" ? outcome.value : null;
6756
+ }
6757
+ async function sweepOrphanedGuardrailsLaunches(log = console) {
6758
+ try {
6759
+ const policyDir = path.join(glimmervoidHomeDir$1(), POLICY_FOLDER);
6760
+ const entryNames = await readdir(policyDir).catch((error) => {
6761
+ if (isMissingFileError(error)) return [];
6762
+ throw error;
6763
+ });
6764
+ const glimmervoidHome = await realpath(glimmervoidHomeDir$1());
6765
+ const sweeperPidNamespace = await readOwnPidNamespace();
6766
+ let removedLaunchCount = 0;
6767
+ for (const entryName of entryNames) {
6768
+ if (!entryName.endsWith(OWNER_FILE_SUFFIX)) continue;
6769
+ const launchId = entryName.slice(0, -11);
6770
+ if (!LAUNCH_ID_SHAPE.test(launchId)) continue;
6771
+ const ownerPath = path.join(policyDir, entryName);
6772
+ const owner = await readOwnerFile(ownerPath);
6773
+ if (owner === null || owner.ownerHost !== os.hostname() || owner.ownerPidNamespace !== sweeperPidNamespace || isProcessAlive$1(owner.ownerPid)) continue;
6774
+ try {
6775
+ await removeLaunch({
6776
+ policyPath: path.join(policyDir, `${launchId}.json`),
6777
+ ownerPath,
6778
+ launchHomeDir: path.join(glimmervoidHome, LAUNCH_HOME_FOLDER, launchId),
6779
+ ownedTempDir: owner.ownsTempDir ? path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER, launchId) : null
6780
+ }, owner, launchId, { onlyNewerLogins: true });
6781
+ removedLaunchCount += 1;
6782
+ } catch (error) {
6783
+ log.warn(`[guardrails] could not remove the leftover launch ${launchId}: ${errorMessage(error)}`);
6784
+ }
6785
+ }
6786
+ if (removedLaunchCount > 0) log.log(`[guardrails] removed ${removedLaunchCount} launch folders left by sessions that ended without a clean shutdown`);
6787
+ } catch (error) {
6788
+ log.warn(`[guardrails] could not sweep leftover launch folders: ${errorMessage(error)}`);
6789
+ }
6790
+ }
6791
+ async function pruneLeftoverSessionTempFolders(glimmervoidHome, liveSessionIds, log = console) {
6792
+ const policyEntryNames = await readdir(path.join(glimmervoidHome, POLICY_FOLDER)).catch((error) => {
6793
+ if (isMissingFileError(error)) return [];
6794
+ log.warn(`[guardrails] kept every session temp folder because the launch list could not be read: ${errorMessage(error)}`);
6795
+ return null;
6796
+ });
6797
+ if (policyEntryNames === null) return;
6798
+ const ownerEntryNames = policyEntryNames.filter((entryName) => entryName.endsWith(OWNER_FILE_SUFFIX));
6799
+ const owners = await Promise.all(ownerEntryNames.map((entryName) => readOwnerFile(path.join(glimmervoidHome, POLICY_FOLDER, entryName))));
6800
+ const tempFolderNamesWithOwners = /* @__PURE__ */ new Set([...ownerEntryNames.map((entryName) => entryName.slice(0, -11)), ...owners.flatMap((owner) => owner?.keptTempFolderName === void 0 ? [] : [owner.keptTempFolderName])]);
6801
+ await pruneAgedFiles({
6802
+ directory: path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER),
6803
+ suffixes: [""],
6804
+ retainDays: SESSION_TEMP_RETAIN_DAYS,
6805
+ entryMode: "directory",
6806
+ isRetainedId: (id) => liveSessionIds.has(id) || tempFolderNamesWithOwners.has(id)
6807
+ });
6808
+ }
6809
+ function launcherCommand(plan, policyPath) {
6810
+ if (plan.launcher === "open-network") return {
6811
+ file: process.execPath,
6812
+ args: [relayPath("guardrails-open-launcher"), policyPath]
6813
+ };
6814
+ const runtimeCliPath = resolvePackageBin("@anthropic-ai/sandbox-runtime", "srt");
6815
+ if (!runtimeCliPath) return null;
6816
+ return {
6817
+ file: process.execPath,
6818
+ args: [
6819
+ runtimeCliPath,
6820
+ "--settings",
6821
+ policyPath,
6822
+ "--"
6823
+ ]
6824
+ };
6825
+ }
6826
+ function guardedEnvPrefix(plan) {
6827
+ const assignments = Object.entries(plan.guardedEnv).map(([name, value]) => `${name}=${value}`);
6828
+ return assignments.length === 0 ? [] : [GUARDED_ENV_COMMAND, ...assignments];
6829
+ }
6830
+ function enteringFolder(enterDir, file, args) {
6831
+ if (enterDir === void 0) return [file, ...args];
6832
+ return [
6833
+ "/bin/sh",
6834
+ "-c",
6835
+ ENTER_FOLDER_SCRIPT,
6836
+ "sh",
6837
+ enterDir,
6838
+ file,
6839
+ ...args
6840
+ ];
6841
+ }
6842
+ function sessionTempFolderFor(sessionId) {
6843
+ if (!LAUNCH_ID_SHAPE.test(sessionId)) return null;
6844
+ return path.join(glimmervoidHomeDir$1(), GUARDRAILS_TEMP_FOLDER, sessionId);
6845
+ }
6846
+ async function removeSessionTempFolder(sessionId, log = console) {
6847
+ const sessionTempFolder = sessionTempFolderFor(sessionId);
6848
+ if (!sessionTempFolder) return;
6849
+ await rm(sessionTempFolder, {
6850
+ recursive: true,
6851
+ force: true
6852
+ }).catch((error) => log.warn(`[guardrails] could not delete session temp folder ${sessionTempFolder}: ${errorMessage(error)}`));
6853
+ }
6854
+ function launchTempDirFor(glimmervoidHome, launchId, tempDir, keptTempFolderName) {
6855
+ if (tempDir !== void 0) return path.resolve(tempDir);
6856
+ return path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER, keptTempFolderName ?? launchId);
6857
+ }
6858
+ async function prepareGuardrailsLaunch({ role, launchId, tempDir, keptTempFolderName, enterDir }) {
6859
+ if (!LAUNCH_ID_SHAPE.test(launchId)) return {
6860
+ ok: false,
6861
+ reason: "guardrails launch id is invalid"
6862
+ };
6863
+ if (keptTempFolderName !== void 0 && !LAUNCH_ID_SHAPE.test(keptTempFolderName)) return {
6864
+ ok: false,
6865
+ reason: "guardrails temp folder name is invalid"
6866
+ };
6867
+ try {
6868
+ const policyDir = path.join(glimmervoidHomeDir$1(), POLICY_FOLDER);
6869
+ await mkdir(policyDir, {
6870
+ recursive: true,
6871
+ mode: 448
6872
+ });
6873
+ const [homeDir, glimmervoidHome, realRole, ownerPidNamespace] = await Promise.all([
6874
+ realpath(os.homedir()),
6875
+ realpath(glimmervoidHomeDir$1()),
6876
+ withRealRoots(role),
6877
+ readOwnPidNamespace()
6878
+ ]);
6879
+ const ownsTempDir = tempDir === void 0 && keptTempFolderName === void 0;
6880
+ const launchTempDir = launchTempDirFor(glimmervoidHome, launchId, tempDir, keptTempFolderName);
6881
+ const launchHomeDir = path.join(glimmervoidHome, LAUNCH_HOME_FOLDER, launchId);
6882
+ const vendorLocations = await resolveVendorLocations(process.env, homeDir);
6883
+ if (vendorLocations === null) return {
6884
+ ok: false,
6885
+ reason: "CODEX_HOME names no folder"
6886
+ };
6887
+ const xdgConfigHomeOverride = rawTextOr(process.env.XDG_CONFIG_HOME, null);
6888
+ const stableHostPaths = {
6889
+ homeDir,
6890
+ glimmervoidHome,
6891
+ glimmervoidConfigFile: await configuredConfigFile(glimmervoidHome),
6892
+ tempDir: launchTempDir,
6893
+ launchHomeDir,
6894
+ vendorLocations,
6895
+ unwrappedVendorHomes: await realPathsWhenPresent(grokHomes(process.env, homeDir)),
6896
+ relocatedXdgConfigHome: xdgConfigHomeOverride === null ? null : await realPathWhenPresent(xdgConfigHomeOverride)
6897
+ };
6898
+ const buildPlanFromCurrentDisk = async () => {
6899
+ const [homeEntryNames, glimmervoidHomeEntryNames] = await Promise.all([readdir(homeDir), readdir(glimmervoidHome)]);
6900
+ const hostPaths = {
6901
+ ...stableHostPaths,
6902
+ homeEntryNames,
6903
+ glimmervoidHomeEntryNames
6904
+ };
6905
+ const [existingPaths, writeBlockedPaths] = await Promise.all([presentPaths$1(guardrailsPolicyProbePaths(realRole, hostPaths)), blockedPathsWithRealTargets(standardWriteBlockCandidates(realRole, hostPaths), realRole.blockedPaths ?? [])]);
6906
+ return buildGuardrailsLaunchPlan(realRole, {
6907
+ ...hostPaths,
6908
+ existingPaths,
6909
+ writeBlockedPaths
6910
+ });
6911
+ };
6912
+ const built = await buildPlanFromCurrentDisk();
6913
+ if (!built.ok) return built;
6914
+ const { plan } = built;
6915
+ const policyPath = path.join(policyDir, `${launchId}.json`);
6916
+ const launcher = launcherCommand(plan, policyPath);
6917
+ if (!launcher) return {
6918
+ ok: false,
6919
+ reason: "the sandbox runtime CLI could not be resolved"
6920
+ };
6921
+ await Promise.all(plan.requiredDirectories.map((directory) => mkdir(directory, { recursive: true })));
6922
+ const startDir = enterDir === void 0 ? void 0 : path.join(launchTempDir, START_FOLDER);
6923
+ if (startDir !== void 0) await mkdir(startDir, { recursive: true });
6924
+ await Promise.all(plan.launchHomeLinks.map((link) => symlink(link.targetPath, link.linkPath)));
6925
+ await writeJsonAtomic(policyPath, plan.policy);
6926
+ const folders = {
6927
+ policyPath,
6928
+ ownerPath: path.join(policyDir, `${launchId}${OWNER_FILE_SUFFIX}`),
6929
+ launchHomeDir,
6930
+ ownedTempDir: ownsTempDir ? launchTempDir : null
6931
+ };
6932
+ const owner = {
6933
+ ownerPid: process.pid,
6934
+ ownerHost: os.hostname(),
6935
+ ownerPidNamespace,
6936
+ ownsTempDir,
6937
+ ...keptTempFolderName === void 0 ? {} : { keptTempFolderName },
6938
+ logins: plan.launchHomeLinks.filter((link) => link.isLogin).map(({ linkPath, targetPath }) => ({
6939
+ linkPath,
6940
+ targetPath
6941
+ })),
6942
+ placeholderPaths: []
6943
+ };
6944
+ await writeJsonAtomic(folders.ownerPath, owner);
6945
+ const envPrefix = guardedEnvPrefix(plan);
6946
+ return {
6947
+ ok: true,
6948
+ launch: {
6949
+ wrap: async (file, args, { hasTerminal }) => {
6950
+ const rebuilt = await buildPlanFromCurrentDisk();
6951
+ if (!rebuilt.ok) throw new Error(rebuilt.reason);
6952
+ await writeJsonAtomic(policyPath, {
6953
+ ...rebuilt.plan.policy,
6954
+ allowPty: hasTerminal && rebuilt.plan.launcher === "open-network"
6955
+ });
6956
+ owner.placeholderPaths = await absentPaths(guardrailsPlaceholderPaths(realRole));
6957
+ await writeJsonAtomic(folders.ownerPath, owner);
6958
+ await createMissingMountPoints(lockedClaudeMountPoints(realRole));
6959
+ return {
6960
+ file: launcher.file,
6961
+ args: [
6962
+ ...launcher.args,
6963
+ ...envPrefix,
6964
+ ...enteringFolder(enterDir, file, args)
6965
+ ]
6966
+ };
6967
+ },
6968
+ env: {
6969
+ ...plan.launchEnv,
6970
+ ...bridgeSocketLauncherEnv(os.tmpdir(), process.platform)
6971
+ },
6972
+ ...startDir === void 0 ? {} : { cwd: startDir },
6973
+ dispose: () => removeLaunch(folders, owner, launchId, { onlyNewerLogins: false })
6974
+ }
6975
+ };
6976
+ } catch (error) {
6977
+ return {
6978
+ ok: false,
6979
+ reason: errorMessage(error)
6980
+ };
6981
+ }
6982
+ }
6983
+ //#endregion
5822
6984
  //#region server/session/session-registry.ts
5823
6985
  function runAutoResume(sessions, config, spawnGate, logger = console) {
5824
6986
  const ids = pickAutoResume(config.projects, config, Date.now());
@@ -5968,7 +7130,7 @@ function createSessionRegistry(dependencies) {
5968
7130
  if (ingestLane) ingestLane.detachSessionTap(session);
5969
7131
  if (ingestLane) ingestLane.releaseSessionRoots(session);
5970
7132
  session.destroy();
5971
- Promise.resolve(session._killReap).catch(() => {}).then(() => session.discardWorktree?.()).catch(() => {});
7133
+ Promise.resolve(session._killReap).catch(() => {}).then(() => session.discardWorktree?.()).catch(() => {}).then(() => removeSessionTempFolder(id, dependencies.logger));
5972
7134
  sessions.delete(id);
5973
7135
  capturedAgentFingerprints.delete(id);
5974
7136
  dependencies.broadcastControl({
@@ -9233,8 +10395,10 @@ var QUICK_RETRY_DELAYS_MS = Object.freeze([
9233
10395
  3e4,
9234
10396
  9e4
9235
10397
  ]);
10398
+ var TRANSIENT_BACKOFF_MAX_MS = 3e5;
9236
10399
  function nextRetrySchedule({ failureStreak, quickRetryCount, quickRetries, retryAfterMs, baseMs, maxMs, random }) {
9237
- const quickRetryDelayMs = quickRetries && !(typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs > 0) ? QUICK_RETRY_DELAYS_MS[quickRetryCount] : void 0;
10400
+ const hasRateLimitWait = typeof retryAfterMs === "number" && Number.isFinite(retryAfterMs) && retryAfterMs > 0;
10401
+ const quickRetryDelayMs = quickRetries && !hasRateLimitWait ? QUICK_RETRY_DELAYS_MS[quickRetryCount] : void 0;
9238
10402
  if (quickRetryDelayMs !== void 0) return {
9239
10403
  waitMs: quickRetryDelayMs,
9240
10404
  retry: {
@@ -9242,11 +10406,12 @@ function nextRetrySchedule({ failureStreak, quickRetryCount, quickRetries, retry
9242
10406
  limit: QUICK_RETRY_DELAYS_MS.length
9243
10407
  }
9244
10408
  };
10409
+ const backoffCeilingMs = quickRetries && !hasRateLimitWait ? Math.min(maxMs, TRANSIENT_BACKOFF_MAX_MS) : maxMs;
9245
10410
  return {
9246
10411
  waitMs: nextBackoffMs({
9247
10412
  attempt: Math.max(1, failureStreak - quickRetryCount),
9248
10413
  baseMs,
9249
- maxMs,
10414
+ maxMs: backoffCeilingMs,
9250
10415
  retryAfterMs,
9251
10416
  random
9252
10417
  }),
@@ -9302,434 +10467,6 @@ function buildLanePermissions({ denyTools = [], allowTools = [] } = {}) {
9302
10467
  };
9303
10468
  }
9304
10469
  //#endregion
9305
- //#region server/guardrails/core/guardrails-policy-core.ts
9306
- var VENDOR_PROFILES = Object.freeze({
9307
- claude: {
9308
- homeEntries: [".claude", ".claude.json"],
9309
- launchWritableFolders: ({ cwd, agentSessionId }) => [path.join("projects", encodeProjectDir(cwd)), ...agentSessionId === null ? [] : [path.join("session-env", agentSessionId)]],
9310
- launchPrivateFolders: ["shell-snapshots"],
9311
- launchHomeEnvName: null,
9312
- loginFiles: [".credentials.json"],
9313
- configEntries: [
9314
- "settings.json",
9315
- "settings.local.json",
9316
- "hooks",
9317
- "skills",
9318
- "plugins",
9319
- "commands",
9320
- "agents",
9321
- "CLAUDE.md",
9322
- "AGENTS.md"
9323
- ],
9324
- apiDomains: ["api.anthropic.com", "platform.claude.com"],
9325
- launchEnv: { DISABLE_AUTOUPDATER: "1" }
9326
- },
9327
- codex: {
9328
- homeEntries: [".codex"],
9329
- launchWritableFolders: () => [],
9330
- launchPrivateFolders: [],
9331
- launchHomeEnvName: "CODEX_HOME",
9332
- loginFiles: ["auth.json"],
9333
- configEntries: [
9334
- "config.toml",
9335
- "AGENTS.md",
9336
- "skills",
9337
- "rules",
9338
- "prompts",
9339
- "hooks.json"
9340
- ],
9341
- apiDomains: [
9342
- "chatgpt.com",
9343
- "*.chatgpt.com",
9344
- "auth.openai.com",
9345
- "api.openai.com",
9346
- "*.openai.com"
9347
- ],
9348
- launchEnv: {}
9349
- }
9350
- });
9351
- var GUARDRAILS_VENDORS = Object.freeze(["claude", "codex"]);
9352
- var UNWRAPPED_VENDOR_HOME_ENTRIES = Object.freeze([".grok"]);
9353
- var CREDENTIAL_HOME_ENTRIES = Object.freeze([
9354
- ".ssh",
9355
- ".config/gh",
9356
- ".config/coderv2",
9357
- "Library/Application Support/coderv2",
9358
- "Library/Keychains",
9359
- ".git-credentials"
9360
- ]);
9361
- var CLOUD_CREDENTIAL_HOME_ENTRIES = Object.freeze([
9362
- ".aws",
9363
- ".azure",
9364
- ".config/gcloud",
9365
- ".kube",
9366
- ".docker",
9367
- ".gnupg",
9368
- ".netrc",
9369
- ".npmrc"
9370
- ]);
9371
- var STANDARD_LEVEL_USABLE_CREDENTIAL_ENTRIES = Object.freeze(["Library/Keychains"]);
9372
- var XDG_CONFIG_DEFAULT_HOME_PREFIX = ".config/";
9373
- var SHARED_TEMP_DIRS = Object.freeze(["/tmp/claude", "/private/tmp/claude"]);
9374
- var SHARED_HOME_WRITE_ENTRIES = Object.freeze([".npm/_logs"]);
9375
- var GUARDRAILS_PLACEHOLDER_NAMES = Object.freeze([
9376
- ".bash_profile",
9377
- ".bashrc",
9378
- ".claude",
9379
- ".gitconfig",
9380
- ".gitmodules",
9381
- ".idea",
9382
- ".mcp.json",
9383
- ".profile",
9384
- ".ripgreprc",
9385
- ".vscode",
9386
- ".zprofile",
9387
- ".zshrc"
9388
- ]);
9389
- var WHOLE_FILESYSTEM = "/";
9390
- var GUARDRAILS_TEMP_FOLDER = "guardrails-temp";
9391
- var AGENT_LOGINS_SIBLING_ENTRY = "agent-logins";
9392
- var GLIMMERVOID_CONFIG_SIBLING_ENTRIES = Object.freeze([
9393
- AGENT_LOGINS_SIBLING_ENTRY,
9394
- "bin",
9395
- "pairings.json",
9396
- "pairings-seen.json",
9397
- "plans",
9398
- "telegram-outbox.json",
9399
- "traces",
9400
- "uploads",
9401
- "usage-budget-state.json",
9402
- "usage-lanes.json",
9403
- "usage-warehouse.json",
9404
- "visions-intent.json"
9405
- ]);
9406
- var GLIMMERVOID_HOME_STATE_ENTRIES = Object.freeze([
9407
- "benchmark-runs",
9408
- "benchmarks",
9409
- "config.json",
9410
- "issues-cache.json",
9411
- "litellm-pricing.json",
9412
- "my-prs-state.json",
9413
- "my-prs-work",
9414
- "posthog-reports",
9415
- "posthog-state.json",
9416
- "posthog-work",
9417
- "recordings",
9418
- "guardrails-homes",
9419
- "guardrails-policies",
9420
- "sane-yolo",
9421
- "scratch",
9422
- "sounds",
9423
- "team-review-repos",
9424
- "team-review-state.json",
9425
- "team-review-work",
9426
- "team-review-worktrees",
9427
- "telemetry-pending-crash.json",
9428
- "telemetry.json",
9429
- "tmp",
9430
- "update-check.json",
9431
- "update-journal.json",
9432
- "workflows-state.json",
9433
- "workflows-work"
9434
- ]);
9435
- var RUNTIME_MANDATORY_CLAUDE_DENY_FOLDERS = Object.freeze(["commands", "agents"]);
9436
- var GUARDED_PROXY_BYPASS = "localhost,::1,169.254.0.0/16,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16";
9437
- var HOOK_LOOPBACK_HOST = "127.0.0.1";
9438
- var AGENT_SESSION_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9_-]{7,127}$/;
9439
- var STANDARD_OPEN_NETWORK = Object.freeze({
9440
- allowAllUnixSockets: true,
9441
- allowMachLookup: ["*"]
9442
- });
9443
- var STRICT_OPEN_NETWORK = Object.freeze({ allowAllUnixSockets: false });
9444
- function unique(entries) {
9445
- return [...new Set(entries)];
9446
- }
9447
- function literalEntries(entryPaths) {
9448
- return unique(entryPaths).map((entryPath) => ({
9449
- path: entryPath,
9450
- literal: true
9451
- }));
9452
- }
9453
- function homePaths(host, homeEntries) {
9454
- return homeEntries.map((entry) => path.join(host.homeDir, entry));
9455
- }
9456
- function isInsideAny(parents, child) {
9457
- return parents.some((parent) => isPathInside(parent, child));
9458
- }
9459
- function vendorStatePaths(host, vendor, stateFolderEntries) {
9460
- return stateFolderEntries.map((entry) => path.join(host.vendorLocations[vendor].stateFolder, entry));
9461
- }
9462
- function vendorHeldPaths(host, vendor) {
9463
- const { stateFolder, configFiles, otherHomes } = host.vendorLocations[vendor];
9464
- return [
9465
- stateFolder,
9466
- ...configFiles,
9467
- ...otherHomes
9468
- ];
9469
- }
9470
- function launchHomeOf(host, vendor) {
9471
- return path.join(host.launchHomeDir, vendor);
9472
- }
9473
- function vendorsWithLaunchHome(role) {
9474
- if (role.vendorHome.scope === "state") return [];
9475
- return role.vendors.filter((vendor) => VENDOR_PROFILES[vendor].launchHomeEnvName !== null);
9476
- }
9477
- function vendorWritableFolders(role, host) {
9478
- const { vendorHome } = role;
9479
- if (vendorHome.scope === "state") return role.vendors.map((vendor) => host.vendorLocations[vendor].stateFolder);
9480
- return role.vendors.flatMap((vendor) => {
9481
- const profile = VENDOR_PROFILES[vendor];
9482
- if (profile.launchHomeEnvName !== null) return [launchHomeOf(host, vendor)];
9483
- return vendorStatePaths(host, vendor, profile.launchWritableFolders(vendorHome));
9484
- });
9485
- }
9486
- function launchPrivateFolders(role, host) {
9487
- if (role.vendorHome.scope === "state") return [];
9488
- return role.vendors.flatMap((vendor) => vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].launchPrivateFolders));
9489
- }
9490
- function launchHomeLinkCandidates(role, host) {
9491
- return vendorsWithLaunchHome(role).flatMap((vendor) => {
9492
- const { configEntries, loginFiles } = VENDOR_PROFILES[vendor];
9493
- const linkFor = (entry, isLogin) => ({
9494
- linkPath: path.join(launchHomeOf(host, vendor), entry),
9495
- targetPath: path.join(host.vendorLocations[vendor].stateFolder, entry),
9496
- isLogin
9497
- });
9498
- return [...configEntries.map((entry) => linkFor(entry, false)), ...loginFiles.map((entry) => linkFor(entry, true))];
9499
- });
9500
- }
9501
- function launchHomeEnv(role, host) {
9502
- return Object.fromEntries(vendorsWithLaunchHome(role).flatMap((vendor) => {
9503
- const envName = VENDOR_PROFILES[vendor].launchHomeEnvName;
9504
- return envName === null ? [] : [[envName, launchHomeOf(host, vendor)]];
9505
- }));
9506
- }
9507
- function vendorLoginFiles(role, host) {
9508
- return role.vendors.flatMap((vendor) => vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].loginFiles));
9509
- }
9510
- function roleWritableRoots(role) {
9511
- return [
9512
- ...role.writableRoots,
9513
- ...role.lockedCheckouts,
9514
- ...role.commitCheckouts.flatMap(({ checkout, gitDir }) => [checkout, gitDir])
9515
- ];
9516
- }
9517
- function alwaysWritablePaths(role, host) {
9518
- return [
9519
- host.tempDir,
9520
- ...roleWritableRoots(role),
9521
- ...vendorWritableFolders(role, host)
9522
- ];
9523
- }
9524
- function commitCheckoutWriteDenies({ checkout, gitDir }) {
9525
- const gitPointer = path.join(checkout, ".git");
9526
- const gitDirDenies = [path.join(gitDir, "hooks"), path.join(gitDir, "config")];
9527
- if (path.resolve(gitPointer) === path.resolve(gitDir)) return gitDirDenies;
9528
- return [gitPointer, ...gitDirDenies];
9529
- }
9530
- function writeDeniesWhenPresent(role, host) {
9531
- const writablePaths = alwaysWritablePaths(role, host);
9532
- const sharedHomeWrites = homePaths(host, SHARED_HOME_WRITE_ENTRIES).filter((sharedPath) => !isInsideAny(roleWritableRoots(role), sharedPath));
9533
- const vendorConfig = role.vendors.flatMap((vendor) => [...vendorStatePaths(host, vendor, VENDOR_PROFILES[vendor].configEntries), ...host.vendorLocations[vendor].configFiles]).filter((configPath) => isInsideAny(writablePaths, configPath));
9534
- return [
9535
- ...SHARED_TEMP_DIRS,
9536
- ...sharedHomeWrites,
9537
- ...vendorConfig,
9538
- ...role.commitCheckouts.flatMap(commitCheckoutWriteDenies)
9539
- ];
9540
- }
9541
- function lockedCheckoutWriteDenies(role) {
9542
- return role.lockedCheckouts.flatMap((checkout) => [path.join(checkout, ".git"), path.join(checkout, ".claude")]);
9543
- }
9544
- function lockedClaudeMountPoints(role) {
9545
- return role.lockedCheckouts.flatMap((checkout) => RUNTIME_MANDATORY_CLAUDE_DENY_FOLDERS.map((folder) => path.join(checkout, ".claude", folder)));
9546
- }
9547
- function guardrailsPlaceholderPaths(role) {
9548
- return unique([...(role.vendorHome.scope === "launch" ? [role.vendorHome.cwd] : []).flatMap((workingFolder) => GUARDRAILS_PLACEHOLDER_NAMES.map((placeholderName) => path.join(workingFolder, placeholderName))), ...lockedCheckoutWriteDenies(role)]);
9549
- }
9550
- function homeEntriesNamedLike(host, homeEntries) {
9551
- return host.homeEntryNames.filter((entryName) => homeEntries.some((homeEntry) => entryName.startsWith(homeEntry)));
9552
- }
9553
- function relocatedXdgConfigPaths(host, homeEntries) {
9554
- const xdgConfigHome = host.relocatedXdgConfigHome;
9555
- if (xdgConfigHome === null) return [];
9556
- return homeEntries.filter((entry) => entry.startsWith(XDG_CONFIG_DEFAULT_HOME_PREFIX)).map((entry) => path.join(xdgConfigHome, entry.slice(8)));
9557
- }
9558
- function isStandardLevel(role) {
9559
- return role.guardrailLevel === "standard";
9560
- }
9561
- function blockedCredentialHomeEntries(role) {
9562
- const credentialHomeEntries = [...CREDENTIAL_HOME_ENTRIES, ...CLOUD_CREDENTIAL_HOME_ENTRIES];
9563
- if (!isStandardLevel(role)) return credentialHomeEntries;
9564
- return credentialHomeEntries.filter((entry) => !STANDARD_LEVEL_USABLE_CREDENTIAL_ENTRIES.includes(entry));
9565
- }
9566
- function credentialWriteBlocks(role, host) {
9567
- const credentialHomeEntries = blockedCredentialHomeEntries(role);
9568
- return [...homePaths(host, credentialHomeEntries), ...relocatedXdgConfigPaths(host, credentialHomeEntries)];
9569
- }
9570
- function glimmervoidStateWriteBlocks(role, host) {
9571
- const keptWritable = alwaysWritablePaths(role, host);
9572
- const configFolder = path.dirname(host.glimmervoidConfigFile);
9573
- const homeEntries = [
9574
- ...GLIMMERVOID_HOME_STATE_ENTRIES,
9575
- ...GLIMMERVOID_CONFIG_SIBLING_ENTRIES,
9576
- ...host.glimmervoidHomeEntryNames
9577
- ].map((entryName) => path.join(host.glimmervoidHome, entryName));
9578
- const configSiblings = GLIMMERVOID_CONFIG_SIBLING_ENTRIES.map((entryName) => path.join(configFolder, entryName));
9579
- return unique([
9580
- host.glimmervoidConfigFile,
9581
- ...homeEntries,
9582
- ...configSiblings
9583
- ]).filter((entryPath) => !keptWritable.some((writable) => isPathInside(entryPath, writable)));
9584
- }
9585
- function standardWriteBlockCandidates(role, host) {
9586
- if (!isStandardLevel(role)) return [];
9587
- return unique([
9588
- ...credentialWriteBlocks(role, host),
9589
- ...glimmervoidStateWriteBlocks(role, host),
9590
- ...role.blockedPaths ?? []
9591
- ]);
9592
- }
9593
- function readDeniedPaths(role, host) {
9594
- const otherVendors = GUARDRAILS_VENDORS.filter((vendor) => !role.vendors.includes(vendor));
9595
- const otherVendorHomeEntries = [...otherVendors.flatMap((vendor) => VENDOR_PROFILES[vendor].homeEntries), ...UNWRAPPED_VENDOR_HOME_ENTRIES];
9596
- const credentialHomeEntries = blockedCredentialHomeEntries(role);
9597
- return [
9598
- ...homePaths(host, [
9599
- ...credentialHomeEntries,
9600
- ...otherVendorHomeEntries,
9601
- ...homeEntriesNamedLike(host, otherVendorHomeEntries)
9602
- ]),
9603
- ...relocatedXdgConfigPaths(host, credentialHomeEntries),
9604
- ...otherVendors.flatMap((vendor) => vendorHeldPaths(host, vendor)),
9605
- ...host.unwrappedVendorHomes,
9606
- host.glimmervoidHome,
9607
- path.join(path.dirname(host.glimmervoidConfigFile), AGENT_LOGINS_SIBLING_ENTRY),
9608
- ...launchPrivateFolders(role, host),
9609
- ...role.readDenied
9610
- ];
9611
- }
9612
- function guardrailsPolicyProbePaths(role, host) {
9613
- return unique([
9614
- ...writeDeniesWhenPresent(role, host),
9615
- ...vendorLoginFiles(role, host),
9616
- ...launchHomeLinkCandidates(role, host).map((link) => link.targetPath)
9617
- ]);
9618
- }
9619
- function isValidPort(port) {
9620
- return Number.isInteger(port) && port >= 1 && port <= 65535;
9621
- }
9622
- function hostNamedPaths(host) {
9623
- const relocatedXdgConfigHomes = host.relocatedXdgConfigHome === null ? [] : [host.relocatedXdgConfigHome];
9624
- return [
9625
- host.homeDir,
9626
- host.glimmervoidHome,
9627
- host.glimmervoidConfigFile,
9628
- host.tempDir,
9629
- host.launchHomeDir,
9630
- ...relocatedXdgConfigHomes,
9631
- ...host.unwrappedVendorHomes,
9632
- ...GUARDRAILS_VENDORS.flatMap((vendor) => vendorHeldPaths(host, vendor))
9633
- ];
9634
- }
9635
- function guardrailsRoleRefusal(role, host) {
9636
- const launchCwds = role.vendorHome.scope === "launch" ? [role.vendorHome.cwd] : [];
9637
- const relativePath = [
9638
- ...hostNamedPaths(host),
9639
- ...roleWritableRoots(role),
9640
- ...role.readDenied,
9641
- ...role.readableWithinDenied,
9642
- ...launchCwds
9643
- ].find((namedPath) => !path.isAbsolute(namedPath));
9644
- if (relativePath !== void 0) return `guardrails policy path is not absolute: ${relativePath}`;
9645
- const rootOverProtectedHome = [...roleWritableRoots(role), ...vendorWritableFolders(role, host)].find((root) => isPathInside(root, host.homeDir) || isPathInside(root, host.glimmervoidHome));
9646
- if (rootOverProtectedHome !== void 0) return `writable root ${rootOverProtectedHome} contains the home folder or the Glimmervoid home`;
9647
- const writablePaths = alwaysWritablePaths(role, host);
9648
- const reallowedAncestor = role.readableWithinDenied.find((readable) => writablePaths.some((writable) => isPathInside(readable, writable, { allowEqual: false })));
9649
- if (reallowedAncestor !== void 0) return `readable path ${reallowedAncestor} is an ancestor of a writable root`;
9650
- if (role.network.access === "allowlist" && role.network.hookPort !== null && !isValidPort(role.network.hookPort)) return "hook listener port is invalid";
9651
- const agentSessionId = role.vendorHome.scope === "launch" ? role.vendorHome.agentSessionId : null;
9652
- if (agentSessionId !== null && !AGENT_SESSION_ID_SHAPE.test(agentSessionId)) return "agent session id is invalid";
9653
- return null;
9654
- }
9655
- function networkPolicy(role) {
9656
- if (role.network.access === "open") return isStandardLevel(role) ? { ...STANDARD_OPEN_NETWORK } : { ...STRICT_OPEN_NETWORK };
9657
- if (role.network.access === "none") return {
9658
- allowedDomains: [],
9659
- deniedDomains: [],
9660
- allowLocalBinding: false,
9661
- allowAllUnixSockets: false
9662
- };
9663
- const hookEndpoint = role.network.hookPort === null ? [] : [`${HOOK_LOOPBACK_HOST}:${role.network.hookPort}`];
9664
- const vendorDomains = role.vendors.flatMap((vendor) => VENDOR_PROFILES[vendor].apiDomains);
9665
- return {
9666
- allowedDomains: unique([
9667
- ...hookEndpoint,
9668
- ...vendorDomains,
9669
- ...role.network.domains
9670
- ]),
9671
- deniedDomains: [],
9672
- strictAllowlist: true,
9673
- allowLocalBinding: false,
9674
- allowAllUnixSockets: false
9675
- };
9676
- }
9677
- function guardedEnvFor(role, host) {
9678
- if (role.network.access === "allowlist") return {
9679
- NO_PROXY: GUARDED_PROXY_BYPASS,
9680
- no_proxy: GUARDED_PROXY_BYPASS,
9681
- [HOOK_VIA_GUARDRAILS_PROXY_ENV]: "1"
9682
- };
9683
- if (role.network.access === "open") return { TMPDIR: host.tempDir };
9684
- return {};
9685
- }
9686
- function filesystemWrites(role, host, writablePaths) {
9687
- if (isStandardLevel(role)) return {
9688
- allowWrite: literalEntries([WHOLE_FILESYSTEM, ...writablePaths]),
9689
- denyWrite: literalEntries(host.writeBlockedPaths)
9690
- };
9691
- const isPresent = (candidate) => host.existingPaths.has(candidate);
9692
- return {
9693
- allowWrite: literalEntries(writablePaths),
9694
- denyWrite: literalEntries([...writeDeniesWhenPresent(role, host).filter(isPresent), ...lockedCheckoutWriteDenies(role)])
9695
- };
9696
- }
9697
- function buildGuardrailsLaunchPlan(role, host) {
9698
- const refusal = guardrailsRoleRefusal(role, host);
9699
- if (refusal !== null) return {
9700
- ok: false,
9701
- reason: refusal
9702
- };
9703
- const isPresent = (candidate) => host.existingPaths.has(candidate);
9704
- const writablePaths = [...alwaysWritablePaths(role, host), ...vendorLoginFiles(role, host).filter(isPresent)];
9705
- const readDenied = readDeniedPaths(role, host);
9706
- const writableWithinDenied = writablePaths.filter((writable) => isInsideAny(readDenied, writable));
9707
- return {
9708
- ok: true,
9709
- plan: {
9710
- launcher: role.network.access === "open" ? "open-network" : "runtime-cli",
9711
- policy: {
9712
- network: networkPolicy(role),
9713
- filesystem: {
9714
- denyRead: literalEntries(readDenied),
9715
- allowRead: literalEntries([...writableWithinDenied, ...role.readableWithinDenied]),
9716
- ...filesystemWrites(role, host, writablePaths)
9717
- },
9718
- terminalScope: isStandardLevel(role) ? "any" : "own",
9719
- allowAppleEvents: isStandardLevel(role)
9720
- },
9721
- launchEnv: Object.assign({ CLAUDE_CODE_TMPDIR: host.tempDir }, ...role.vendors.map((vendor) => VENDOR_PROFILES[vendor].launchEnv), launchHomeEnv(role, host)),
9722
- guardedEnv: guardedEnvFor(role, host),
9723
- requiredDirectories: unique([
9724
- host.tempDir,
9725
- ...vendorWritableFolders(role, host),
9726
- ...launchPrivateFolders(role, host)
9727
- ]),
9728
- launchHomeLinks: launchHomeLinkCandidates(role, host).filter((link) => isPresent(link.targetPath))
9729
- }
9730
- };
9731
- }
9732
- //#endregion
9733
10470
  //#region shared/my-pr-merge.ts
9734
10471
  var FAILING_CHECK_STATES$1 = /* @__PURE__ */ new Set(["FAILURE", "ERROR"]);
9735
10472
  function myPrMergeBlocker(pr) {
@@ -10500,6 +11237,7 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
10500
11237
  let backoffUntil = 0;
10501
11238
  let rateLimitedUntil = 0;
10502
11239
  let failureStreak = 0;
11240
+ let quickRetryCount = 0;
10503
11241
  const unavailableKeys = /* @__PURE__ */ new Set();
10504
11242
  function getSnapshot() {
10505
11243
  const watchSnapshots = Object.fromEntries([...watches].map(([name, watch]) => [name, {
@@ -10568,19 +11306,21 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
10568
11306
  const retryAfterMs = secondaryRateLimitWaitMs(pollingError) ?? void 0;
10569
11307
  const schedule = nextRetrySchedule({
10570
11308
  failureStreak,
10571
- quickRetryCount: 0,
10572
- quickRetries: false,
11309
+ quickRetryCount,
11310
+ quickRetries: true,
10573
11311
  retryAfterMs,
10574
11312
  baseMs: 6e4,
10575
11313
  maxMs: GITHUB_RATE_LIMIT_WINDOW_MS,
10576
11314
  random: () => 1
10577
11315
  });
11316
+ if (schedule.retry) quickRetryCount += 1;
10578
11317
  backoffUntil = now() + schedule.waitMs;
10579
11318
  rateLimitedUntil = retryAfterMs === void 0 ? 0 : backoffUntil;
10580
11319
  log.warn(`[github-store] ${pollingError}`);
10581
11320
  return {
10582
11321
  failed: true,
10583
- retryAfterMs: schedule.waitMs
11322
+ retryAfterMs: schedule.waitMs,
11323
+ error: pollingError
10584
11324
  };
10585
11325
  }
10586
11326
  function recordReadFailure(error) {
@@ -10589,6 +11329,7 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
10589
11329
  function recordSuccess() {
10590
11330
  pollingError = null;
10591
11331
  failureStreak = 0;
11332
+ quickRetryCount = 0;
10592
11333
  backoffUntil = 0;
10593
11334
  rateLimitedUntil = 0;
10594
11335
  }
@@ -10787,11 +11528,15 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
10787
11528
  function tick(watchNames) {
10788
11529
  return exclusive(async () => {
10789
11530
  const tickStartedAt = now();
10790
- if (shouldSkipTick({
11531
+ if (watchNames !== void 0 && rateLimitedUntil > tickStartedAt) return {
11532
+ failed: true,
11533
+ retryAfterMs: rateLimitedUntil - tickStartedAt
11534
+ };
11535
+ if (watchNames === void 0 && shouldSkipTick({
10791
11536
  now: tickStartedAt,
10792
11537
  backoffUntil
10793
11538
  })) return {
10794
- failed: watchNames !== void 0,
11539
+ failed: false,
10795
11540
  retryAfterMs: backoffUntil - tickStartedAt
10796
11541
  };
10797
11542
  const previousError = pollingError;
@@ -10825,7 +11570,7 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
10825
11570
  } finally {
10826
11571
  publishChanges([...details, ...behindChangedPrs], removedKeys, previousError, hasWatchChanges);
10827
11572
  }
10828
- });
11573
+ }, { isPriority: watchNames !== void 0 });
10829
11574
  }
10830
11575
  async function refreshWatches(names) {
10831
11576
  if ((await tick(names)).failed) return {
@@ -11054,7 +11799,8 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
11054
11799
  function storeReadingLaneClock(clock) {
11055
11800
  return clock ? {
11056
11801
  schedule: clock.schedule,
11057
- exclusive: async (work) => work()
11802
+ exclusive: async (work) => work(),
11803
+ githubStatus: clock.githubStatus
11058
11804
  } : void 0;
11059
11805
  }
11060
11806
  function createGithubStoreWiring({ github, clock, now = Date.now, isDashboardConnected, broadcast, log }) {
@@ -11137,6 +11883,8 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11137
11883
  let rateLimitedUntil = 0;
11138
11884
  let isRefreshing = false;
11139
11885
  let refreshNotice = null;
11886
+ let lastRefreshedAt = null;
11887
+ let hasTransientFailure = false;
11140
11888
  const running = /* @__PURE__ */ new Set();
11141
11889
  function persist() {
11142
11890
  return persistQueue.run(() => writeState()).catch((e) => {
@@ -11165,14 +11913,17 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11165
11913
  retryTimer.unref?.();
11166
11914
  }
11167
11915
  function scheduleStatus() {
11916
+ const incident = hasTransientFailure ? clock?.githubStatus?.incident() ?? null : null;
11168
11917
  return {
11169
11918
  nextAttemptAt,
11170
11919
  retry,
11171
11920
  isRefreshing,
11172
- refreshNotice
11921
+ refreshNotice,
11922
+ lastRefreshedAt,
11923
+ incident
11173
11924
  };
11174
11925
  }
11175
- async function runTick(trigger) {
11926
+ async function runTick(trigger, beforeTick) {
11176
11927
  const isManual = trigger === "manual";
11177
11928
  if (stopped) return {
11178
11929
  ok: false,
@@ -11220,6 +11971,15 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11220
11971
  };
11221
11972
  }
11222
11973
  }
11974
+ if (isManual && beforeTick) {
11975
+ onScheduleChange();
11976
+ const refreshed = await beforeTick();
11977
+ if (stopped) return {
11978
+ ok: false,
11979
+ error: "Reviews polling is stopped."
11980
+ };
11981
+ if (!refreshed.ok) return refreshed;
11982
+ }
11223
11983
  clearRetryTimer();
11224
11984
  nextAttemptAt = null;
11225
11985
  retry = null;
@@ -11230,6 +11990,8 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11230
11990
  error: "Reviews polling is stopped."
11231
11991
  };
11232
11992
  if (outcome?.failed !== true) {
11993
+ lastRefreshedAt = now();
11994
+ hasTransientFailure = false;
11233
11995
  failureStreak = 0;
11234
11996
  quickRetryCount = 0;
11235
11997
  backoffUntil = 0;
@@ -11238,6 +12000,8 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11238
12000
  return { ok: true };
11239
12001
  }
11240
12002
  failureStreak += 1;
12003
+ hasTransientFailure = outcome.retryAfterMs === void 0;
12004
+ if (hasTransientFailure) clock?.githubStatus?.noteTransientFailure();
11241
12005
  const scheduled = nextRetrySchedule({
11242
12006
  failureStreak,
11243
12007
  quickRetryCount,
@@ -11250,7 +12014,7 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11250
12014
  if (scheduled.retry) quickRetryCount += 1;
11251
12015
  if (outcome.retryAfterMs && outcome.retryAfterMs > 0) rateLimitedUntil = now() + outcome.retryAfterMs;
11252
12016
  scheduleAttempt(scheduled.waitMs, scheduled.retry);
11253
- log.warn(`[${tag}] poll failed (${failureStreak} in a row) - backing off ${Math.round(scheduled.waitMs / 1e3)}s`);
12017
+ log.warn(`[${tag}] poll failed (${failureStreak} in a row)${outcome.error ? `: ${outcome.error}` : ""} - backing off ${Math.round(scheduled.waitMs / 1e3)}s`);
11254
12018
  return {
11255
12019
  ok: false,
11256
12020
  error: "Could not refresh from GitHub."
@@ -11270,8 +12034,8 @@ function createTickLoop({ tag, quickRetries = false, onScheduleChange = () => {}
11270
12034
  if (tickRunning) return;
11271
12035
  runTick("interval");
11272
12036
  }
11273
- function refresh() {
11274
- return runTick("manual");
12037
+ function refresh(beforeTick) {
12038
+ return runTick("manual", beforeTick);
11275
12039
  }
11276
12040
  async function start(prelude = null) {
11277
12041
  stopped = false;
@@ -11429,9 +12193,13 @@ function createIssuesPoller(dependencies) {
11429
12193
  }
11430
12194
  async function failedOutcome(error) {
11431
12195
  const waitMs = await rateLimitWaitMs() ?? secondaryRateLimitWaitMs(error);
11432
- return waitMs === null ? { failed: true } : {
12196
+ return waitMs === null ? {
11433
12197
  failed: true,
11434
- retryAfterMs: waitMs
12198
+ error
12199
+ } : {
12200
+ failed: true,
12201
+ retryAfterMs: waitMs,
12202
+ error
11435
12203
  };
11436
12204
  }
11437
12205
  async function runTick() {
@@ -11877,7 +12645,7 @@ async function runCommandSafely(command, args, { env, timeoutMs, signal }) {
11877
12645
  }
11878
12646
  }
11879
12647
  async function readTextFileOrNull$1(filePath) {
11880
- return fsp.readFile(filePath, "utf8").catch(() => null);
12648
+ return fs$1.readFile(filePath, "utf8").catch(() => null);
11881
12649
  }
11882
12650
  function sleepUnlessAborted(durationMs, signal) {
11883
12651
  return new Promise((resolve) => {
@@ -16609,11 +17377,6 @@ async function writeWhenAbsent(filePath, contents) {
16609
17377
  var WORKSPACE_MAP_FILE = "AGENTS.md";
16610
17378
  var WORKSPACE_POINTER_FILE = "CLAUDE.md";
16611
17379
  var WORKSPACE_MAP_HASH_FILE = ".glimmervoid-map-hash";
16612
- var GENERATED_WORKSPACE_FILES = /* @__PURE__ */ new Set([
16613
- WORKSPACE_MAP_FILE,
16614
- WORKSPACE_POINTER_FILE,
16615
- WORKSPACE_MAP_HASH_FILE
16616
- ]);
16617
17380
  function hashWorkspaceMap(contents) {
16618
17381
  return crypto.createHash("sha256").update(contents).digest("hex");
16619
17382
  }
@@ -16634,15 +17397,20 @@ async function writeWorkspaceMap(folder, contents) {
16634
17397
  await fs.promises.writeFile(mapPath, contents);
16635
17398
  await fs.promises.writeFile(hashPath, `${renderedHash}\n`);
16636
17399
  }
16637
- function createSessionWorkspaceMembers({ plan, sessionName, shareList, gitWorkspace }) {
17400
+ function createSessionWorkspaceMembers({ plan, owner, sessionName, shareList, gitWorkspace }) {
16638
17401
  let activeProvision = null;
16639
17402
  async function provisionBody() {
16640
17403
  try {
16641
17404
  await fs.promises.mkdir(plan.folder, { recursive: true });
17405
+ await gitWorkspace.recordOwnedFolder({
17406
+ folderPath: plan.folder,
17407
+ owner
17408
+ });
16642
17409
  const members = [];
16643
17410
  for (const member of plan.members) {
16644
17411
  const ensured = await gitWorkspace.ensureWorkspaceMember({
16645
17412
  projectPath: member.repoPath,
17413
+ owner,
16646
17414
  wtDir: member.dir,
16647
17415
  branch: plan.branch,
16648
17416
  shareList
@@ -16682,28 +17450,68 @@ function createSessionWorkspaceMembers({ plan, sessionName, shareList, gitWorksp
16682
17450
  });
16683
17451
  return attempt;
16684
17452
  }
16685
- async function release({ keepRepoPaths = [] } = {}) {
17453
+ const pathExists = (candidatePath) => fs.promises.stat(candidatePath).then(() => true, () => false);
17454
+ async function findMemberWork(member) {
17455
+ return gitWorkspace.describeWorkspaceMemberWork({
17456
+ projectPath: member.repoPath,
17457
+ cwd: member.dir,
17458
+ branch: plan.branch
17459
+ }).catch((error) => `its work could not be checked: ${errorMessage(error)}`);
17460
+ }
17461
+ async function findKeptWork() {
17462
+ if (activeProvision) await activeProvision;
17463
+ const kept = [];
17464
+ for (const member of plan.members) {
17465
+ if (!await pathExists(member.dir)) continue;
17466
+ const reason = await findMemberWork(member);
17467
+ if (reason) kept.push({
17468
+ path: member.dir,
17469
+ reason
17470
+ });
17471
+ }
17472
+ return kept;
17473
+ }
17474
+ async function releaseMember(member, discardWork) {
17475
+ if (!await pathExists(member.dir)) return null;
17476
+ const reason = discardWork ? null : await findMemberWork(member);
17477
+ if (reason) return {
17478
+ path: member.dir,
17479
+ reason
17480
+ };
17481
+ const removed = await gitWorkspace.removeWorkspaceMember({
17482
+ projectPath: member.repoPath,
17483
+ cwd: member.dir,
17484
+ shareList,
17485
+ discardWork
17486
+ });
17487
+ if (removed.ok) return null;
17488
+ return {
17489
+ path: member.dir,
17490
+ reason: removed.err?.split("\n")[0] || "git refused to remove it"
17491
+ };
17492
+ }
17493
+ async function release({ keepRepoPaths = [], discardWork = false } = {}) {
16686
17494
  if (activeProvision) await activeProvision;
16687
17495
  const keptRepoKeys = new Set(keepRepoPaths.map((repoPath) => caseFoldedPathKey(path.resolve(repoPath))));
16688
- const keptDirs = [];
17496
+ const kept = [];
16689
17497
  for (const member of plan.members) {
16690
17498
  if (keptRepoKeys.has(caseFoldedPathKey(member.repoPath))) continue;
16691
- if (!await fs.promises.stat(member.dir).then(() => true, () => false)) continue;
16692
- if (!(await gitWorkspace.removeWorkspaceMember({
16693
- projectPath: member.repoPath,
16694
- cwd: member.dir,
16695
- shareList
16696
- })).ok) keptDirs.push(member.dir);
17499
+ const keptMember = await releaseMember(member, discardWork);
17500
+ if (keptMember) kept.push(keptMember);
16697
17501
  }
16698
- const entries = await fs.promises.readdir(plan.folder).catch(() => []);
16699
- if (entries.some((entry) => !GENERATED_WORKSPACE_FILES.has(entry))) return { keptDirs };
16700
- for (const entry of entries) await fs.promises.rm(path.join(plan.folder, entry), { force: true });
16701
- await fs.promises.rmdir(plan.folder).catch(() => {});
16702
- return { keptDirs };
17502
+ if (keptRepoKeys.size > 0) return { kept };
17503
+ for (const member of plan.members) if (await pathExists(member.dir)) return { kept };
17504
+ await fs.promises.rm(plan.folder, {
17505
+ recursive: true,
17506
+ force: true
17507
+ });
17508
+ await gitWorkspace.forgetRemovedPath(plan.folder);
17509
+ return { kept };
16703
17510
  }
16704
17511
  return {
16705
17512
  provision,
16706
17513
  release,
17514
+ findKeptWork,
16707
17515
  branch: plan.branch
16708
17516
  };
16709
17517
  }
@@ -16711,6 +17519,18 @@ function createSessionWorkspaceMembers({ plan, sessionName, shareList, gitWorksp
16711
17519
  //#region session/session-worktree-lifecycle.ts
16712
17520
  var WORKTREE_CHECK_DEBOUNCE_MS = 400;
16713
17521
  var GIT_NOT_FOUND_EXIT_CODE = 1;
17522
+ function workspaceMemberGit(gitWorkspace) {
17523
+ if (!gitWorkspace) return null;
17524
+ const { ensureWorkspaceMember, removeWorkspaceMember, describeWorkspaceMemberWork, recordOwnedFolder, forgetRemovedPath } = gitWorkspace;
17525
+ if (!ensureWorkspaceMember || !removeWorkspaceMember || !describeWorkspaceMemberWork || !recordOwnedFolder || !forgetRemovedPath) return null;
17526
+ return {
17527
+ ensureWorkspaceMember,
17528
+ removeWorkspaceMember,
17529
+ describeWorkspaceMemberWork,
17530
+ recordOwnedFolder,
17531
+ forgetRemovedPath
17532
+ };
17533
+ }
16714
17534
  async function readGitStrict(args, options) {
16715
17535
  const command = await runGit(args, {
16716
17536
  ...options,
@@ -16750,9 +17570,8 @@ function setUpWorkspaceMembers({ folder, sessionId, sessionName, repoPaths, shar
16750
17570
  repoPaths
16751
17571
  });
16752
17572
  if (!planned.ok) return planned;
16753
- const ensureWorkspaceMember = gitWorkspace?.ensureWorkspaceMember;
16754
- const removeWorkspaceMember = gitWorkspace?.removeWorkspaceMember;
16755
- if (!ensureWorkspaceMember || !removeWorkspaceMember) return {
17573
+ const memberGit = workspaceMemberGit(gitWorkspace);
17574
+ if (!memberGit) return {
16756
17575
  ok: false,
16757
17576
  error: "Git workspace is unavailable"
16758
17577
  };
@@ -16760,12 +17579,10 @@ function setUpWorkspaceMembers({ folder, sessionId, sessionName, repoPaths, shar
16760
17579
  ok: true,
16761
17580
  members: createSessionWorkspaceMembers({
16762
17581
  plan: planned.plan,
17582
+ owner: `session:${sessionId}`,
16763
17583
  sessionName,
16764
17584
  shareList,
16765
- gitWorkspace: {
16766
- ensureWorkspaceMember,
16767
- removeWorkspaceMember
16768
- }
17585
+ gitWorkspace: memberGit
16769
17586
  })
16770
17587
  };
16771
17588
  }
@@ -17060,6 +17877,7 @@ function createSessionWorktreeLifecycle({ id, projectPath, integrationBranch = n
17060
17877
  try {
17061
17878
  workspace = await gitWorkspace.create({
17062
17879
  projectPath: currentProjectPath(),
17880
+ owner: `session:${id}`,
17063
17881
  teamId: "session",
17064
17882
  label: id,
17065
17883
  baseBranch,
@@ -17162,9 +17980,21 @@ function createSessionWorktreeLifecycle({ id, projectPath, integrationBranch = n
17162
17980
  lifecycleState.isWorktree = false;
17163
17981
  setMergeStatus(status);
17164
17982
  }
17983
+ let isWorkspaceWorkDiscardConfirmed = false;
17984
+ function confirmWorkspaceWorkDiscard() {
17985
+ isWorkspaceWorkDiscardConfirmed = true;
17986
+ }
17987
+ async function findWorkspaceKeptWork() {
17988
+ if (!workspaceMembers?.ok) return [];
17989
+ return workspaceMembers.members.findKeptWork();
17990
+ }
17165
17991
  async function releaseWorkspaceMembers(members, keepRepoPaths = []) {
17166
- const released = await members.release({ keepRepoPaths });
17167
- if (released.keptDirs.length > 0) console.warn(`[session ${id}] kept workspace members with uncommitted work: ${released.keptDirs.join(", ")}`);
17992
+ const released = await members.release({
17993
+ keepRepoPaths,
17994
+ discardWork: isWorkspaceWorkDiscardConfirmed
17995
+ });
17996
+ if (released.kept.length === 0) return;
17997
+ console.warn(`[session ${id}] kept workspace members: ${released.kept.map((kept) => `${kept.path} (${kept.reason})`).join(", ")}`);
17168
17998
  }
17169
17999
  async function releaseDroppedWorkspaceMembers(keepRepoPaths) {
17170
18000
  if (!workspaceMembers?.ok) return;
@@ -17947,6 +18777,8 @@ function createSessionWorktreeLifecycle({ id, projectPath, integrationBranch = n
17947
18777
  setMergeStatus,
17948
18778
  pasteMergePrompt,
17949
18779
  hasUnmergedWork,
18780
+ findWorkspaceKeptWork,
18781
+ confirmWorkspaceWorkDiscard,
17950
18782
  getDiff,
17951
18783
  getChangeScopes,
17952
18784
  resolveEffectiveBase,
@@ -19318,6 +20150,12 @@ var Session = class extends EventEmitter {
19318
20150
  discardWorktree() {
19319
20151
  return this.worktreeLifecycle.discardWorktree();
19320
20152
  }
20153
+ findWorkspaceKeptWork() {
20154
+ return this.worktreeLifecycle.findWorkspaceKeptWork();
20155
+ }
20156
+ confirmWorkspaceWorkDiscard() {
20157
+ this.worktreeLifecycle.confirmWorkspaceWorkDiscard();
20158
+ }
19321
20159
  getDetectionStats() {
19322
20160
  return {
19323
20161
  lastSignal: this._lastSignal,
@@ -20868,760 +21706,200 @@ function boundedToolCallInput(input) {
20868
21706
  return {
20869
21707
  input: bounded.text,
20870
21708
  truncated: true
20871
- };
20872
- }
20873
- if (!input || typeof input !== "object") return { input };
20874
- const bounded = Array.isArray(input) ? {
20875
- input,
20876
- hasCutProperty: false
20877
- } : boundedInputProperties(input);
20878
- const serialized = serializedInputText(bounded.input);
20879
- if (serialized.length > MAX_TRACE_CALL_INPUT_CHARS) return {
20880
- input: serialized.slice(0, MAX_TRACE_BODY_CHARS),
20881
- truncated: true
20882
- };
20883
- if (!bounded.hasCutProperty) return { input };
20884
- return {
20885
- input: bounded.input,
20886
- truncated: true
20887
- };
20888
- }
20889
- function everyTextBlockJoined(blocks) {
20890
- const blockTexts = blocks.flatMap((block) => firstTextBlock([block]) ?? []);
20891
- if (blockTexts.length === 0) return null;
20892
- return blockTexts.join("\n");
20893
- }
20894
- function isTaskNotificationLine(line) {
20895
- return line.origin?.kind === "task-notification" || line.turnOrigin?.kind === "task_notification";
20896
- }
20897
- function mapUserLine(rawLine, line, context) {
20898
- const base = baseRecord(line, context);
20899
- const content = line.message?.content;
20900
- const blocks = contentBlocks(line);
20901
- const toolResult = blocks.find((block) => block.type === "tool_result");
20902
- if (toolResult) {
20903
- const toolUseId = rawTextOr(toolResult.tool_use_id, null);
20904
- if (!toolUseId) return [rawRecord(rawLine, line, context)];
20905
- const bounded = boundedText(textContent(toolResult.content));
20906
- return [{
20907
- ...base,
20908
- kind: "tool_result",
20909
- toolUseId,
20910
- content: bounded.text,
20911
- isError: toolResult.is_error === true,
20912
- truncated: bounded.truncated
20913
- }];
20914
- }
20915
- if (line.isMeta === true) {
20916
- const expansionText = typeof content === "string" ? content : everyTextBlockJoined(blocks);
20917
- if (!expansionText) return [rawRecord(rawLine, line, context)];
20918
- const sourceToolUseId = rawTextOr(line.sourceToolUseID, null);
20919
- if (!sourceToolUseId) return [{
20920
- ...base,
20921
- kind: "expansion",
20922
- ...boundedTextFields(expansionText)
20923
- }];
20924
- return [{
20925
- ...base,
20926
- kind: "expansion",
20927
- toolUseId: sourceToolUseId,
20928
- ...boundedTextFields(expansionText)
20929
- }];
20930
- }
20931
- const text = typeof content === "string" ? content : firstTextBlock(blocks);
20932
- if (!text) return [rawRecord(rawLine, line, context)];
20933
- if (isTaskNotificationLine(line)) return [{
20934
- ...base,
20935
- kind: "expansion",
20936
- ...boundedTextFields(text)
20937
- }];
20938
- if (typeof content === "string" && /<command-name>[\s\S]*?<\/command-name>/.test(content)) return [{
20939
- ...base,
20940
- kind: "expansion",
20941
- ...boundedTextFields(content)
20942
- }];
20943
- return [{
20944
- ...base,
20945
- kind: "prompt",
20946
- ...boundedTextFields(text)
20947
- }];
20948
- }
20949
- function queuedCommandText(prompt) {
20950
- if (typeof prompt === "string") return prompt || null;
20951
- return firstTextBlock(objectBlocks(prompt));
20952
- }
20953
- function queuedCommandRecords(line, context) {
20954
- const attachment = line.attachment;
20955
- if (line.type !== "attachment" || attachment?.type !== "queued_command") return null;
20956
- const text = queuedCommandText(attachment.prompt);
20957
- if (!text) return null;
20958
- if (attachment.commandMode === "prompt" && attachment.origin?.kind === "human") return [{
20959
- ...baseRecord(line, context),
20960
- kind: "prompt",
20961
- ...boundedTextFields(text)
20962
- }];
20963
- if (attachment.commandMode === "task-notification") return [{
20964
- ...baseRecord(line, context),
20965
- kind: "expansion",
20966
- ...boundedTextFields(text)
20967
- }];
20968
- return null;
20969
- }
20970
- function mapAssistantLine(rawLine, line, context) {
20971
- const base = baseRecord(line, context);
20972
- const records = [];
20973
- let hasSkippedThinkingBlock = false;
20974
- for (const block of contentBlocks(line)) {
20975
- if (block.type === "thinking" && typeof block.thinking === "string") {
20976
- if (block.thinking.length === 0) {
20977
- hasSkippedThinkingBlock = true;
20978
- continue;
20979
- }
20980
- records.push({
20981
- ...base,
20982
- kind: "thinking",
20983
- ...boundedTextFields(block.thinking)
20984
- });
20985
- continue;
20986
- }
20987
- if (block.type === "text") {
20988
- const text = firstTextBlock([block]);
20989
- if (text) records.push({
20990
- ...base,
20991
- kind: "assistant",
20992
- ...boundedTextFields(text)
20993
- });
20994
- continue;
20995
- }
20996
- if (block.type !== "tool_use") continue;
20997
- const toolUseId = rawTextOr(block.id, null);
20998
- const name = rawTextOr(block.name, null);
20999
- if (!toolUseId || !name) return [rawRecord(rawLine, line, context)];
21000
- records.push({
21001
- ...base,
21002
- kind: "tool_call",
21003
- toolUseId,
21004
- name,
21005
- ...boundedToolCallInput(block.input)
21006
- });
21007
- }
21008
- if (records.length === 0 && hasSkippedThinkingBlock) return [];
21009
- if (records.length === 0) return [rawRecord(rawLine, line, context)];
21010
- return records;
21011
- }
21012
- function traceRecordsFromTranscriptLine(rawLine, context) {
21013
- const line = parseTranscriptLine(rawLine);
21014
- if (!line) return [rawRecord(rawLine, null, context)];
21015
- const queuedRecords = queuedCommandRecords(line, context);
21016
- if (queuedRecords) return queuedRecords;
21017
- if (isDroppedLine(line)) return [];
21018
- if (line.type === "user") return mapUserLine(rawLine, line, context);
21019
- if (line.type === "assistant") return mapAssistantLine(rawLine, line, context);
21020
- return [rawRecord(rawLine, line, context)];
21021
- }
21022
- //#endregion
21023
- //#region server/core/investigation-trail-core.ts
21024
- var TRAIL_MAX_STEPS = 80;
21025
- var TRAIL_TOOL_MAX_CHARS = 64;
21026
- var TRAIL_NOTE_MAX_CHARS = 600;
21027
- function describeToolStep(toolName, toolInput) {
21028
- const trimmed = typeof toolName === "string" ? toolName.trim() : "";
21029
- if (!trimmed) return null;
21030
- const tool = trimmed.slice(0, TRAIL_TOOL_MAX_CHARS);
21031
- return {
21032
- tool,
21033
- detail: toolDetailLine(tool, toolInput)
21034
- };
21035
- }
21036
- function trailStepFromHook(event, payload) {
21037
- if (String(event ?? "").toLowerCase() !== "pretooluse") return null;
21038
- return describeToolStep(payload.tool_name, payload.tool_input);
21039
- }
21040
- function trailNotesFromTranscriptLines(lines, now) {
21041
- return lines.flatMap((line) => traceRecordsFromTranscriptLine(line, {
21042
- vendorSessionId: "",
21043
- now
21044
- })).flatMap((record) => record.kind === "assistant" ? [record.text.trim().slice(0, TRAIL_NOTE_MAX_CHARS)] : []).filter((note) => note !== "");
21045
- }
21046
- function createInvestigationTrail(startedAt) {
21047
- return {
21048
- startedAt,
21049
- steps: []
21050
- };
21051
- }
21052
- function appendTrailStep(trail, step, maxSteps = TRAIL_MAX_STEPS) {
21053
- const isAppendingNote = isTrailNote(step);
21054
- const sameKindEntries = trail.steps.filter((entry) => isTrailNote(entry) === isAppendingNote);
21055
- const evictedCount = Math.max(0, sameKindEntries.length + 1 - maxSteps);
21056
- const evictedEntries = new Set(sameKindEntries.slice(0, evictedCount));
21057
- const keptEntries = trail.steps.filter((entry) => !evictedEntries.has(entry));
21058
- return {
21059
- startedAt: trail.startedAt,
21060
- steps: [...keptEntries, step]
21061
- };
21062
- }
21063
- function isTrailNote(entry) {
21064
- return "note" in entry;
21065
- }
21066
- //#endregion
21067
- //#region shared/contracts/guardrails-launch.ts
21068
- var GuardrailsLaunchLogin = z.object({
21069
- linkPath: z.string().min(1),
21070
- targetPath: z.string().min(1)
21071
- }).strict();
21072
- var GuardrailsLaunchOwner = z.object({
21073
- ownerPid: z.number().int().positive(),
21074
- ownerHost: z.string(),
21075
- ownerPidNamespace: z.string().nullable(),
21076
- ownsTempDir: z.boolean(),
21077
- keptTempFolderName: z.string().min(1).optional(),
21078
- logins: z.array(GuardrailsLaunchLogin),
21079
- placeholderPaths: z.array(z.string().min(1))
21080
- }).strict();
21081
- //#endregion
21082
- //#region server/core/claude-trust-core.ts
21083
- var CLAUDE_GLOBAL_CONFIG_FILE_NAME = ".claude.json";
21084
- var CLAUDE_LEGACY_CONFIG_FILE_NAME = ".config.json";
21085
- var CLAUDE_CONFIG_LOCK_SUFFIX = ".lock";
21086
- var CLAUDE_CONFIG_LOCK_STALE_MS = 1e4;
21087
- var CLAUDE_CONFIG_LOCK_RETRY_DELAYS_MS = Object.freeze([
21088
- 200,
21089
- 400,
21090
- 800,
21091
- 1600
21092
- ]);
21093
- var GRANTED_KEYS = Object.freeze([
21094
- "hasTrustDialogAccepted",
21095
- "hasClaudeMdExternalIncludesApproved",
21096
- "hasClaudeMdExternalIncludesWarningShown"
21097
- ]);
21098
- var TRUST_ONLY_KEYS = Object.freeze(["hasTrustDialogAccepted"]);
21099
- function isPlainRecord(value) {
21100
- return typeof value === "object" && value !== null && !Array.isArray(value);
21101
- }
21102
- function newProjectEntry() {
21103
- return {
21104
- allowedTools: [],
21105
- mcpContextUris: [],
21106
- mcpServers: {},
21107
- enabledMcpjsonServers: [],
21108
- disabledMcpjsonServers: []
21109
- };
21110
- }
21111
- function listClaudeGlobalConfigPathCandidates(env, homeDir) {
21112
- const configuredDir = env.CLAUDE_CONFIG_DIR?.trim();
21113
- const legacyConfigHome = (configuredDir || path.join(homeDir, ".claude")).normalize("NFC");
21114
- return [path.join(legacyConfigHome, CLAUDE_LEGACY_CONFIG_FILE_NAME), path.join(configuredDir || homeDir, CLAUDE_GLOBAL_CONFIG_FILE_NAME)];
21115
- }
21116
- function claudeProjectKeyOf(folderPath, platform) {
21117
- if (platform !== "win32") return path.posix.normalize(folderPath);
21118
- return path.win32.normalize(folderPath).replaceAll("\\", "/");
21119
- }
21120
- function repositoryRootOfCommonGitDir(commonGitDir) {
21121
- if (!path.isAbsolute(commonGitDir) || path.basename(commonGitDir) !== ".git") return null;
21122
- return path.dirname(commonGitDir);
21123
- }
21124
- function isConfigLockStale(lockModifiedMs, nowMs) {
21125
- return nowMs - lockModifiedMs > CLAUDE_CONFIG_LOCK_STALE_MS;
21126
- }
21127
- function hasRecordedExternalImportsDecline(existingEntry) {
21128
- return existingEntry?.hasClaudeMdExternalIncludesWarningShown === true && existingEntry.hasClaudeMdExternalIncludesApproved !== true;
21129
- }
21130
- function decideFolderTrust(configText, repositoryRoot, platform) {
21131
- const projectKey = claudeProjectKeyOf(repositoryRoot, platform);
21132
- let config;
21133
- try {
21134
- config = JSON.parse(configText);
21135
- } catch {
21136
- return {
21137
- kind: "unreadable",
21138
- reason: "it is not valid JSON"
21139
- };
21140
- }
21141
- if (!isPlainRecord(config)) return {
21142
- kind: "unreadable",
21143
- reason: "it is not a JSON object"
21144
- };
21145
- const projects = config.projects ?? {};
21146
- if (!isPlainRecord(projects)) return {
21147
- kind: "unreadable",
21148
- reason: "its projects key is not an object"
21149
- };
21150
- const existingEntry = projects[projectKey];
21151
- if (existingEntry !== void 0 && !isPlainRecord(existingEntry)) return {
21152
- kind: "unreadable",
21153
- reason: "its entry for this folder is not an object"
21154
- };
21155
- const keysToGrant = hasRecordedExternalImportsDecline(existingEntry) ? TRUST_ONLY_KEYS : GRANTED_KEYS;
21156
- if (keysToGrant.every((key) => existingEntry?.[key] === true)) return { kind: "trusted" };
21157
- const trustedEntry = {
21158
- ...existingEntry ?? newProjectEntry(),
21159
- ...Object.fromEntries(keysToGrant.map((key) => [key, true]))
21160
- };
21161
- const nextConfigText = JSON.stringify({
21162
- ...config,
21163
- projects: {
21164
- ...projects,
21165
- [projectKey]: trustedEntry
21166
- }
21167
- }, null, 2);
21168
- return {
21169
- kind: "grant",
21170
- nextConfigText: configText.endsWith("\n") ? `${nextConfigText}\n` : nextConfigText
21171
- };
21172
- }
21173
- //#endregion
21174
- //#region server/guardrails/core/guardrails-bridge-socket-core.ts
21175
- var LONGEST_BRIDGE_SOCKET_NAME = "claude-socks-0123456789abcdef.sock";
21176
- var UNIX_SOCKET_PATH_BYTE_LIMIT = 107;
21177
- var SHORT_BRIDGE_SOCKET_FOLDER = "/tmp";
21178
- function bridgeSocketPathBytes(tempDirectory) {
21179
- return Buffer.byteLength(path.join(tempDirectory, LONGEST_BRIDGE_SOCKET_NAME));
21180
- }
21181
- function hasRoomForBridgeSocket(tempDirectory, platform) {
21182
- return platform !== "linux" || bridgeSocketPathBytes(tempDirectory) <= UNIX_SOCKET_PATH_BYTE_LIMIT;
21183
- }
21184
- function bridgeSocketLauncherEnv(inheritedTempDirectory, platform) {
21185
- if (hasRoomForBridgeSocket(inheritedTempDirectory, platform)) return { TMPDIR: inheritedTempDirectory };
21186
- return { TMPDIR: SHORT_BRIDGE_SOCKET_FOLDER };
21187
- }
21188
- //#endregion
21189
- //#region server/prune-files.ts
21190
- var MS_PER_DAY = 864e5;
21191
- function idForEntry(entry, suffixes) {
21192
- for (const suffix of suffixes) {
21193
- if (suffix.length === 0) return entry;
21194
- if (entry.endsWith(suffix)) return entry.slice(0, -suffix.length);
21195
- }
21196
- return null;
21197
- }
21198
- async function pruneAgedFiles({ directory, suffixes, retainDays, now = Date.now(), isRetainedId = () => false, entryMode = "file", fsPromises = fs.promises }) {
21199
- let entries;
21200
- try {
21201
- entries = await fsPromises.readdir(directory);
21202
- } catch {
21203
- return [];
21204
- }
21205
- const cutoff = now - retainDays * MS_PER_DAY;
21206
- const removedIds = [];
21207
- for (const entry of entries) {
21208
- const id = idForEntry(entry, suffixes);
21209
- if (!id || isRetainedId(id)) continue;
21210
- const filePath = path.join(directory, entry);
21211
- try {
21212
- if ((await fsPromises.stat(filePath)).mtimeMs >= cutoff) continue;
21213
- if (entryMode === "directory") await fsPromises.rm(filePath, {
21214
- recursive: true,
21215
- force: true
21216
- });
21217
- if (entryMode === "file") await fsPromises.unlink(filePath);
21218
- removedIds.push(id);
21219
- } catch {}
21220
- }
21221
- return removedIds;
21222
- }
21223
- //#endregion
21224
- //#region server/guardrails/guardrails-launch.ts
21225
- var LAUNCH_ID_SHAPE = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
21226
- var GUARDED_ENV_COMMAND = "/usr/bin/env";
21227
- var POLICY_FOLDER = "guardrails-policies";
21228
- var LAUNCH_HOME_FOLDER = "guardrails-homes";
21229
- var START_FOLDER = "start";
21230
- var OWNER_FILE_SUFFIX = ".owner.json";
21231
- var ENTER_FOLDER_SCRIPT = "cd \"$1\" && shift && exec \"$@\"";
21232
- var LOGIN_FILE_MODE = 384;
21233
- var ABSENT_PATH_DENY_PLATFORM = "darwin";
21234
- var OWN_PID_NAMESPACE_LINK = "/proc/self/ns/pid";
21235
- var SESSION_TEMP_RETAIN_DAYS = 7;
21236
- async function isPresent(candidate) {
21237
- try {
21238
- await access(candidate);
21239
- return true;
21240
- } catch (error) {
21241
- if (!isMissingFileError(error)) throw error;
21242
- return false;
21243
- }
21244
- }
21245
- async function presentPaths$1(candidates) {
21246
- const presence = await Promise.all(candidates.map(isPresent));
21247
- return new Set(candidates.filter((_candidate, index) => presence[index]));
21248
- }
21249
- async function realPathWhenPresent(candidate) {
21250
- if (!path.isAbsolute(candidate)) return candidate;
21251
- try {
21252
- return await realpath(candidate);
21253
- } catch (error) {
21254
- if (!isMissingFileError(error)) throw error;
21255
- return candidate;
21256
- }
21257
- }
21258
- function realPathsWhenPresent(candidates) {
21259
- return Promise.all(candidates.map(realPathWhenPresent));
21260
- }
21261
- async function symlinkTargetsInside(folder) {
21262
- const symlinkEntries = (await readdir(folder, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isSymbolicLink());
21263
- return (await Promise.all(symlinkEntries.map((entry) => realpath(path.join(folder, entry.name)).catch(() => null)))).filter((target) => target !== null);
21264
- }
21265
- async function blockedPathsWithRealTargets(candidates, operatorBlockedPaths) {
21266
- const resolved = await Promise.all(candidates.map(async (candidate) => {
21267
- const isPresentEntry = await lstat(candidate).then(() => true, (error) => !isMissingFileError(error));
21268
- const isKeptWhenAbsent = process.platform === ABSENT_PATH_DENY_PLATFORM || operatorBlockedPaths.includes(candidate);
21269
- if (!isPresentEntry) return isKeptWhenAbsent ? [candidate] : [];
21270
- const realCandidate = await realpath(candidate).catch(() => candidate);
21271
- return [
21272
- candidate,
21273
- realCandidate,
21274
- ...await symlinkTargetsInside(realCandidate)
21275
- ];
21276
- }));
21277
- return [...new Set(resolved.flat())];
21278
- }
21279
- async function configuredConfigFile(glimmervoidHome) {
21280
- const { envPath, homePath } = decideConfigPath({
21281
- env: process.env,
21282
- homeDir: glimmervoidHome
21283
- }, () => false);
21284
- const configFile = envPath ?? homePath;
21285
- return path.join(await realPathWhenPresent(path.dirname(configFile)), path.basename(configFile));
21286
- }
21287
- function scannedClaudeHomes(env, homeDir) {
21288
- return [env, {
21289
- ...env,
21290
- CLAUDE_CONFIG_DIR: void 0
21291
- }].flatMap((scannedEnv) => projectDirCandidates(scannedEnv, [], homeDir)).map((projectsDir) => path.dirname(projectsDir));
21292
- }
21293
- async function resolveVendorLocations(env, homeDir) {
21294
- const [legacyClaudeConfigPath, claudeConfigPath] = listClaudeGlobalConfigPathCandidates(env, homeDir);
21295
- const [codexStateFolder, ...otherCodexHomes] = codexHomes(env, homeDir);
21296
- if (codexStateFolder === void 0) return null;
21297
- return {
21298
- claude: {
21299
- stateFolder: await realPathWhenPresent(path.dirname(legacyClaudeConfigPath)),
21300
- configFiles: [await realPathWhenPresent(claudeConfigPath)],
21301
- otherHomes: await realPathsWhenPresent(scannedClaudeHomes(env, homeDir))
21302
- },
21303
- codex: {
21304
- stateFolder: await realPathWhenPresent(codexStateFolder),
21305
- configFiles: [],
21306
- otherHomes: await realPathsWhenPresent(otherCodexHomes)
21307
- }
21308
- };
21309
- }
21310
- async function withRealRoots(role) {
21311
- const [writableRoots, lockedCheckouts, commitCheckouts] = await Promise.all([
21312
- Promise.all(role.writableRoots.map((root) => realpath(root))),
21313
- Promise.all(role.lockedCheckouts.map((checkout) => realpath(checkout))),
21314
- Promise.all(role.commitCheckouts.map(async ({ checkout, gitDir }) => ({
21315
- checkout: await realpath(checkout),
21316
- gitDir: await realpath(gitDir)
21317
- })))
21318
- ]);
21319
- const vendorHome = role.vendorHome.scope === "launch" ? {
21320
- ...role.vendorHome,
21321
- cwd: await realPathWhenPresent(role.vendorHome.cwd)
21322
- } : role.vendorHome;
21323
- return {
21324
- ...role,
21325
- vendorHome,
21326
- writableRoots,
21327
- lockedCheckouts,
21328
- commitCheckouts,
21329
- readableWithinDenied: await realPathsWhenPresent(role.readableWithinDenied)
21330
- };
21331
- }
21332
- async function lstatWhenPresent(candidate) {
21333
- try {
21334
- return await lstat(candidate);
21335
- } catch (error) {
21336
- if (!isMissingFileError(error)) throw error;
21337
- return null;
21338
- }
21339
- }
21340
- async function isRegularFile(candidate) {
21341
- return (await lstatWhenPresent(candidate))?.isFile() ?? false;
21342
- }
21343
- async function isRealDirectory$1(candidate) {
21344
- return (await lstatWhenPresent(candidate))?.isDirectory() ?? false;
21345
- }
21346
- async function absentPaths(candidates) {
21347
- const presentCandidates = await presentPaths$1(candidates);
21348
- return candidates.filter((candidate) => !presentCandidates.has(candidate));
21349
- }
21350
- async function removeLeftoverPlaceholders(placeholderPaths) {
21351
- for (const placeholderPath of placeholderPaths) {
21352
- const placeholderStats = await lstat(placeholderPath).catch(() => null);
21353
- if (placeholderStats?.isFile() && placeholderStats.size === 0) await rm(placeholderPath, { force: true });
21709
+ };
21354
21710
  }
21711
+ if (!input || typeof input !== "object") return { input };
21712
+ const bounded = Array.isArray(input) ? {
21713
+ input,
21714
+ hasCutProperty: false
21715
+ } : boundedInputProperties(input);
21716
+ const serialized = serializedInputText(bounded.input);
21717
+ if (serialized.length > MAX_TRACE_CALL_INPUT_CHARS) return {
21718
+ input: serialized.slice(0, MAX_TRACE_BODY_CHARS),
21719
+ truncated: true
21720
+ };
21721
+ if (!bounded.hasCutProperty) return { input };
21722
+ return {
21723
+ input: bounded.input,
21724
+ truncated: true
21725
+ };
21355
21726
  }
21356
- async function createMissingMountPoints(mountPoints) {
21357
- for (const mountPoint of mountPoints) {
21358
- if (!await isRealDirectory$1(path.dirname(mountPoint))) continue;
21359
- await mkdir(mountPoint).catch((error) => {
21360
- if (errorCode(error) !== "EEXIST") throw error;
21361
- });
21362
- }
21727
+ function everyTextBlockJoined(blocks) {
21728
+ const blockTexts = blocks.flatMap((block) => firstTextBlock([block]) ?? []);
21729
+ if (blockTexts.length === 0) return null;
21730
+ return blockTexts.join("\n");
21363
21731
  }
21364
- async function isNewerThanTarget(linkPath, targetPath) {
21365
- const targetStats = await stat(targetPath).catch(() => null);
21366
- if (targetStats === null) return true;
21367
- return (await lstat(linkPath)).mtimeMs > targetStats.mtimeMs;
21732
+ function isTaskNotificationLine(line) {
21733
+ return line.origin?.kind === "task-notification" || line.turnOrigin?.kind === "task_notification";
21368
21734
  }
21369
- async function keepRefreshedLogins(logins, launchId, { onlyWhenNewer }) {
21370
- for (const { linkPath, targetPath } of logins) {
21371
- if (!await isRegularFile(linkPath)) continue;
21372
- if (onlyWhenNewer && !await isNewerThanTarget(linkPath, targetPath)) continue;
21373
- const stagedPath = `${targetPath}.${launchId}`;
21374
- await copyFile(linkPath, stagedPath);
21375
- await chmod(stagedPath, LOGIN_FILE_MODE);
21376
- await rename(stagedPath, targetPath);
21735
+ function mapUserLine(rawLine, line, context) {
21736
+ const base = baseRecord(line, context);
21737
+ const content = line.message?.content;
21738
+ const blocks = contentBlocks(line);
21739
+ const toolResult = blocks.find((block) => block.type === "tool_result");
21740
+ if (toolResult) {
21741
+ const toolUseId = rawTextOr(toolResult.tool_use_id, null);
21742
+ if (!toolUseId) return [rawRecord(rawLine, line, context)];
21743
+ const bounded = boundedText(textContent(toolResult.content));
21744
+ return [{
21745
+ ...base,
21746
+ kind: "tool_result",
21747
+ toolUseId,
21748
+ content: bounded.text,
21749
+ isError: toolResult.is_error === true,
21750
+ truncated: bounded.truncated
21751
+ }];
21377
21752
  }
21378
- }
21379
- async function removeLaunch(folders, owner, launchId, { onlyNewerLogins }) {
21380
- await rm(folders.policyPath, { force: true });
21381
- await removeLeftoverPlaceholders(owner.placeholderPaths);
21382
- await keepRefreshedLogins(owner.logins.filter((login) => isPathInside(folders.launchHomeDir, login.linkPath, { allowEqual: false })), launchId, { onlyWhenNewer: onlyNewerLogins });
21383
- await rm(folders.launchHomeDir, {
21384
- recursive: true,
21385
- force: true
21386
- });
21387
- if (folders.ownedTempDir !== null) await rm(folders.ownedTempDir, {
21388
- recursive: true,
21389
- force: true
21390
- });
21391
- await rm(folders.ownerPath, { force: true });
21392
- }
21393
- function isProcessAlive$1(pid) {
21394
- try {
21395
- process.kill(pid, 0);
21396
- return true;
21397
- } catch (error) {
21398
- return errorCode(error) === "EPERM";
21753
+ if (line.isMeta === true) {
21754
+ const expansionText = typeof content === "string" ? content : everyTextBlockJoined(blocks);
21755
+ if (!expansionText) return [rawRecord(rawLine, line, context)];
21756
+ const sourceToolUseId = rawTextOr(line.sourceToolUseID, null);
21757
+ if (!sourceToolUseId) return [{
21758
+ ...base,
21759
+ kind: "expansion",
21760
+ ...boundedTextFields(expansionText)
21761
+ }];
21762
+ return [{
21763
+ ...base,
21764
+ kind: "expansion",
21765
+ toolUseId: sourceToolUseId,
21766
+ ...boundedTextFields(expansionText)
21767
+ }];
21399
21768
  }
21769
+ const text = typeof content === "string" ? content : firstTextBlock(blocks);
21770
+ if (!text) return [rawRecord(rawLine, line, context)];
21771
+ if (isTaskNotificationLine(line)) return [{
21772
+ ...base,
21773
+ kind: "expansion",
21774
+ ...boundedTextFields(text)
21775
+ }];
21776
+ if (typeof content === "string" && /<command-name>[\s\S]*?<\/command-name>/.test(content)) return [{
21777
+ ...base,
21778
+ kind: "expansion",
21779
+ ...boundedTextFields(content)
21780
+ }];
21781
+ return [{
21782
+ ...base,
21783
+ kind: "prompt",
21784
+ ...boundedTextFields(text)
21785
+ }];
21400
21786
  }
21401
- function readOwnPidNamespace() {
21402
- return readlink(OWN_PID_NAMESPACE_LINK).catch(() => null);
21787
+ function queuedCommandText(prompt) {
21788
+ if (typeof prompt === "string") return prompt || null;
21789
+ return firstTextBlock(objectBlocks(prompt));
21403
21790
  }
21404
- async function readOwnerFile(ownerPath) {
21405
- const outcome = await loadJsonStateFile({
21406
- filePath: ownerPath,
21407
- quarantine: false,
21408
- parse: (raw) => GuardrailsLaunchOwner.safeParse(raw).data ?? null
21409
- });
21410
- return outcome.status === "loaded" ? outcome.value : null;
21791
+ function queuedCommandRecords(line, context) {
21792
+ const attachment = line.attachment;
21793
+ if (line.type !== "attachment" || attachment?.type !== "queued_command") return null;
21794
+ const text = queuedCommandText(attachment.prompt);
21795
+ if (!text) return null;
21796
+ if (attachment.commandMode === "prompt" && attachment.origin?.kind === "human") return [{
21797
+ ...baseRecord(line, context),
21798
+ kind: "prompt",
21799
+ ...boundedTextFields(text)
21800
+ }];
21801
+ if (attachment.commandMode === "task-notification") return [{
21802
+ ...baseRecord(line, context),
21803
+ kind: "expansion",
21804
+ ...boundedTextFields(text)
21805
+ }];
21806
+ return null;
21411
21807
  }
21412
- async function sweepOrphanedGuardrailsLaunches(log = console) {
21413
- try {
21414
- const policyDir = path.join(glimmervoidHomeDir$1(), POLICY_FOLDER);
21415
- const entryNames = await readdir(policyDir).catch((error) => {
21416
- if (isMissingFileError(error)) return [];
21417
- throw error;
21418
- });
21419
- const glimmervoidHome = await realpath(glimmervoidHomeDir$1());
21420
- const sweeperPidNamespace = await readOwnPidNamespace();
21421
- let removedLaunchCount = 0;
21422
- for (const entryName of entryNames) {
21423
- if (!entryName.endsWith(OWNER_FILE_SUFFIX)) continue;
21424
- const launchId = entryName.slice(0, -11);
21425
- if (!LAUNCH_ID_SHAPE.test(launchId)) continue;
21426
- const ownerPath = path.join(policyDir, entryName);
21427
- const owner = await readOwnerFile(ownerPath);
21428
- if (owner === null || owner.ownerHost !== os.hostname() || owner.ownerPidNamespace !== sweeperPidNamespace || isProcessAlive$1(owner.ownerPid)) continue;
21429
- try {
21430
- await removeLaunch({
21431
- policyPath: path.join(policyDir, `${launchId}.json`),
21432
- ownerPath,
21433
- launchHomeDir: path.join(glimmervoidHome, LAUNCH_HOME_FOLDER, launchId),
21434
- ownedTempDir: owner.ownsTempDir ? path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER, launchId) : null
21435
- }, owner, launchId, { onlyNewerLogins: true });
21436
- removedLaunchCount += 1;
21437
- } catch (error) {
21438
- log.warn(`[guardrails] could not remove the leftover launch ${launchId}: ${errorMessage(error)}`);
21808
+ function mapAssistantLine(rawLine, line, context) {
21809
+ const base = baseRecord(line, context);
21810
+ const records = [];
21811
+ let hasSkippedThinkingBlock = false;
21812
+ for (const block of contentBlocks(line)) {
21813
+ if (block.type === "thinking" && typeof block.thinking === "string") {
21814
+ if (block.thinking.length === 0) {
21815
+ hasSkippedThinkingBlock = true;
21816
+ continue;
21439
21817
  }
21818
+ records.push({
21819
+ ...base,
21820
+ kind: "thinking",
21821
+ ...boundedTextFields(block.thinking)
21822
+ });
21823
+ continue;
21440
21824
  }
21441
- if (removedLaunchCount > 0) log.log(`[guardrails] removed ${removedLaunchCount} launch folders left by sessions that ended without a clean shutdown`);
21442
- } catch (error) {
21443
- log.warn(`[guardrails] could not sweep leftover launch folders: ${errorMessage(error)}`);
21825
+ if (block.type === "text") {
21826
+ const text = firstTextBlock([block]);
21827
+ if (text) records.push({
21828
+ ...base,
21829
+ kind: "assistant",
21830
+ ...boundedTextFields(text)
21831
+ });
21832
+ continue;
21833
+ }
21834
+ if (block.type !== "tool_use") continue;
21835
+ const toolUseId = rawTextOr(block.id, null);
21836
+ const name = rawTextOr(block.name, null);
21837
+ if (!toolUseId || !name) return [rawRecord(rawLine, line, context)];
21838
+ records.push({
21839
+ ...base,
21840
+ kind: "tool_call",
21841
+ toolUseId,
21842
+ name,
21843
+ ...boundedToolCallInput(block.input)
21844
+ });
21444
21845
  }
21846
+ if (records.length === 0 && hasSkippedThinkingBlock) return [];
21847
+ if (records.length === 0) return [rawRecord(rawLine, line, context)];
21848
+ return records;
21445
21849
  }
21446
- async function pruneLeftoverSessionTempFolders(glimmervoidHome, liveSessionIds, log = console) {
21447
- const policyEntryNames = await readdir(path.join(glimmervoidHome, POLICY_FOLDER)).catch((error) => {
21448
- if (isMissingFileError(error)) return [];
21449
- log.warn(`[guardrails] kept every session temp folder because the launch list could not be read: ${errorMessage(error)}`);
21450
- return null;
21451
- });
21452
- if (policyEntryNames === null) return;
21453
- const ownerEntryNames = policyEntryNames.filter((entryName) => entryName.endsWith(OWNER_FILE_SUFFIX));
21454
- const owners = await Promise.all(ownerEntryNames.map((entryName) => readOwnerFile(path.join(glimmervoidHome, POLICY_FOLDER, entryName))));
21455
- const tempFolderNamesWithOwners = /* @__PURE__ */ new Set([...ownerEntryNames.map((entryName) => entryName.slice(0, -11)), ...owners.flatMap((owner) => owner?.keptTempFolderName === void 0 ? [] : [owner.keptTempFolderName])]);
21456
- await pruneAgedFiles({
21457
- directory: path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER),
21458
- suffixes: [""],
21459
- retainDays: SESSION_TEMP_RETAIN_DAYS,
21460
- entryMode: "directory",
21461
- isRetainedId: (id) => liveSessionIds.has(id) || tempFolderNamesWithOwners.has(id)
21462
- });
21850
+ function traceRecordsFromTranscriptLine(rawLine, context) {
21851
+ const line = parseTranscriptLine(rawLine);
21852
+ if (!line) return [rawRecord(rawLine, null, context)];
21853
+ const queuedRecords = queuedCommandRecords(line, context);
21854
+ if (queuedRecords) return queuedRecords;
21855
+ if (isDroppedLine(line)) return [];
21856
+ if (line.type === "user") return mapUserLine(rawLine, line, context);
21857
+ if (line.type === "assistant") return mapAssistantLine(rawLine, line, context);
21858
+ return [rawRecord(rawLine, line, context)];
21463
21859
  }
21464
- function launcherCommand(plan, policyPath) {
21465
- if (plan.launcher === "open-network") return {
21466
- file: process.execPath,
21467
- args: [relayPath("guardrails-open-launcher"), policyPath]
21468
- };
21469
- const runtimeCliPath = resolvePackageBin("@anthropic-ai/sandbox-runtime", "srt");
21470
- if (!runtimeCliPath) return null;
21860
+ //#endregion
21861
+ //#region server/core/investigation-trail-core.ts
21862
+ var TRAIL_MAX_STEPS = 80;
21863
+ var TRAIL_TOOL_MAX_CHARS = 64;
21864
+ var TRAIL_NOTE_MAX_CHARS = 600;
21865
+ function describeToolStep(toolName, toolInput) {
21866
+ const trimmed = typeof toolName === "string" ? toolName.trim() : "";
21867
+ if (!trimmed) return null;
21868
+ const tool = trimmed.slice(0, TRAIL_TOOL_MAX_CHARS);
21471
21869
  return {
21472
- file: process.execPath,
21473
- args: [
21474
- runtimeCliPath,
21475
- "--settings",
21476
- policyPath,
21477
- "--"
21478
- ]
21870
+ tool,
21871
+ detail: toolDetailLine(tool, toolInput)
21479
21872
  };
21480
21873
  }
21481
- function guardedEnvPrefix(plan) {
21482
- const assignments = Object.entries(plan.guardedEnv).map(([name, value]) => `${name}=${value}`);
21483
- return assignments.length === 0 ? [] : [GUARDED_ENV_COMMAND, ...assignments];
21484
- }
21485
- function enteringFolder(enterDir, file, args) {
21486
- if (enterDir === void 0) return [file, ...args];
21487
- return [
21488
- "/bin/sh",
21489
- "-c",
21490
- ENTER_FOLDER_SCRIPT,
21491
- "sh",
21492
- enterDir,
21493
- file,
21494
- ...args
21495
- ];
21874
+ function trailStepFromHook(event, payload) {
21875
+ if (String(event ?? "").toLowerCase() !== "pretooluse") return null;
21876
+ return describeToolStep(payload.tool_name, payload.tool_input);
21496
21877
  }
21497
- function launchTempDirFor(glimmervoidHome, launchId, tempDir, keptTempFolderName) {
21498
- if (tempDir !== void 0) return path.resolve(tempDir);
21499
- return path.join(glimmervoidHome, GUARDRAILS_TEMP_FOLDER, keptTempFolderName ?? launchId);
21878
+ function trailNotesFromTranscriptLines(lines, now) {
21879
+ return lines.flatMap((line) => traceRecordsFromTranscriptLine(line, {
21880
+ vendorSessionId: "",
21881
+ now
21882
+ })).flatMap((record) => record.kind === "assistant" ? [record.text.trim().slice(0, TRAIL_NOTE_MAX_CHARS)] : []).filter((note) => note !== "");
21500
21883
  }
21501
- async function prepareGuardrailsLaunch({ role, launchId, tempDir, keptTempFolderName, enterDir }) {
21502
- if (!LAUNCH_ID_SHAPE.test(launchId)) return {
21503
- ok: false,
21504
- reason: "guardrails launch id is invalid"
21884
+ function createInvestigationTrail(startedAt) {
21885
+ return {
21886
+ startedAt,
21887
+ steps: []
21505
21888
  };
21506
- if (keptTempFolderName !== void 0 && !LAUNCH_ID_SHAPE.test(keptTempFolderName)) return {
21507
- ok: false,
21508
- reason: "guardrails temp folder name is invalid"
21889
+ }
21890
+ function appendTrailStep(trail, step, maxSteps = TRAIL_MAX_STEPS) {
21891
+ const isAppendingNote = isTrailNote(step);
21892
+ const sameKindEntries = trail.steps.filter((entry) => isTrailNote(entry) === isAppendingNote);
21893
+ const evictedCount = Math.max(0, sameKindEntries.length + 1 - maxSteps);
21894
+ const evictedEntries = new Set(sameKindEntries.slice(0, evictedCount));
21895
+ const keptEntries = trail.steps.filter((entry) => !evictedEntries.has(entry));
21896
+ return {
21897
+ startedAt: trail.startedAt,
21898
+ steps: [...keptEntries, step]
21509
21899
  };
21510
- try {
21511
- const policyDir = path.join(glimmervoidHomeDir$1(), POLICY_FOLDER);
21512
- await mkdir(policyDir, {
21513
- recursive: true,
21514
- mode: 448
21515
- });
21516
- const [homeDir, glimmervoidHome, realRole, ownerPidNamespace] = await Promise.all([
21517
- realpath(os.homedir()),
21518
- realpath(glimmervoidHomeDir$1()),
21519
- withRealRoots(role),
21520
- readOwnPidNamespace()
21521
- ]);
21522
- const ownsTempDir = tempDir === void 0 && keptTempFolderName === void 0;
21523
- const launchTempDir = launchTempDirFor(glimmervoidHome, launchId, tempDir, keptTempFolderName);
21524
- const launchHomeDir = path.join(glimmervoidHome, LAUNCH_HOME_FOLDER, launchId);
21525
- const vendorLocations = await resolveVendorLocations(process.env, homeDir);
21526
- if (vendorLocations === null) return {
21527
- ok: false,
21528
- reason: "CODEX_HOME names no folder"
21529
- };
21530
- const xdgConfigHomeOverride = rawTextOr(process.env.XDG_CONFIG_HOME, null);
21531
- const stableHostPaths = {
21532
- homeDir,
21533
- glimmervoidHome,
21534
- glimmervoidConfigFile: await configuredConfigFile(glimmervoidHome),
21535
- tempDir: launchTempDir,
21536
- launchHomeDir,
21537
- vendorLocations,
21538
- unwrappedVendorHomes: await realPathsWhenPresent(grokHomes(process.env, homeDir)),
21539
- relocatedXdgConfigHome: xdgConfigHomeOverride === null ? null : await realPathWhenPresent(xdgConfigHomeOverride)
21540
- };
21541
- const buildPlanFromCurrentDisk = async () => {
21542
- const [homeEntryNames, glimmervoidHomeEntryNames] = await Promise.all([readdir(homeDir), readdir(glimmervoidHome)]);
21543
- const hostPaths = {
21544
- ...stableHostPaths,
21545
- homeEntryNames,
21546
- glimmervoidHomeEntryNames
21547
- };
21548
- const [existingPaths, writeBlockedPaths] = await Promise.all([presentPaths$1(guardrailsPolicyProbePaths(realRole, hostPaths)), blockedPathsWithRealTargets(standardWriteBlockCandidates(realRole, hostPaths), realRole.blockedPaths ?? [])]);
21549
- return buildGuardrailsLaunchPlan(realRole, {
21550
- ...hostPaths,
21551
- existingPaths,
21552
- writeBlockedPaths
21553
- });
21554
- };
21555
- const built = await buildPlanFromCurrentDisk();
21556
- if (!built.ok) return built;
21557
- const { plan } = built;
21558
- const policyPath = path.join(policyDir, `${launchId}.json`);
21559
- const launcher = launcherCommand(plan, policyPath);
21560
- if (!launcher) return {
21561
- ok: false,
21562
- reason: "the sandbox runtime CLI could not be resolved"
21563
- };
21564
- await Promise.all(plan.requiredDirectories.map((directory) => mkdir(directory, { recursive: true })));
21565
- const startDir = enterDir === void 0 ? void 0 : path.join(launchTempDir, START_FOLDER);
21566
- if (startDir !== void 0) await mkdir(startDir, { recursive: true });
21567
- await Promise.all(plan.launchHomeLinks.map((link) => symlink(link.targetPath, link.linkPath)));
21568
- await writeJsonAtomic(policyPath, plan.policy);
21569
- const folders = {
21570
- policyPath,
21571
- ownerPath: path.join(policyDir, `${launchId}${OWNER_FILE_SUFFIX}`),
21572
- launchHomeDir,
21573
- ownedTempDir: ownsTempDir ? launchTempDir : null
21574
- };
21575
- const owner = {
21576
- ownerPid: process.pid,
21577
- ownerHost: os.hostname(),
21578
- ownerPidNamespace,
21579
- ownsTempDir,
21580
- ...keptTempFolderName === void 0 ? {} : { keptTempFolderName },
21581
- logins: plan.launchHomeLinks.filter((link) => link.isLogin).map(({ linkPath, targetPath }) => ({
21582
- linkPath,
21583
- targetPath
21584
- })),
21585
- placeholderPaths: []
21586
- };
21587
- await writeJsonAtomic(folders.ownerPath, owner);
21588
- const envPrefix = guardedEnvPrefix(plan);
21589
- return {
21590
- ok: true,
21591
- launch: {
21592
- wrap: async (file, args, { hasTerminal }) => {
21593
- const rebuilt = await buildPlanFromCurrentDisk();
21594
- if (!rebuilt.ok) throw new Error(rebuilt.reason);
21595
- await writeJsonAtomic(policyPath, {
21596
- ...rebuilt.plan.policy,
21597
- allowPty: hasTerminal && rebuilt.plan.launcher === "open-network"
21598
- });
21599
- owner.placeholderPaths = await absentPaths(guardrailsPlaceholderPaths(realRole));
21600
- await writeJsonAtomic(folders.ownerPath, owner);
21601
- await createMissingMountPoints(lockedClaudeMountPoints(realRole));
21602
- return {
21603
- file: launcher.file,
21604
- args: [
21605
- ...launcher.args,
21606
- ...envPrefix,
21607
- ...enteringFolder(enterDir, file, args)
21608
- ]
21609
- };
21610
- },
21611
- env: {
21612
- ...plan.launchEnv,
21613
- ...bridgeSocketLauncherEnv(os.tmpdir(), process.platform)
21614
- },
21615
- ...startDir === void 0 ? {} : { cwd: startDir },
21616
- dispose: () => removeLaunch(folders, owner, launchId, { onlyNewerLogins: false })
21617
- }
21618
- };
21619
- } catch (error) {
21620
- return {
21621
- ok: false,
21622
- reason: errorMessage(error)
21623
- };
21624
- }
21900
+ }
21901
+ function isTrailNote(entry) {
21902
+ return "note" in entry;
21625
21903
  }
21626
21904
  //#endregion
21627
21905
  //#region server/lanes/lane-spawn.ts
@@ -21642,7 +21920,7 @@ var LANE_SPAWN_DENY_TOOLS = Object.freeze([
21642
21920
  async function writeStandaloneDenySettings(permissions, userHooks) {
21643
21921
  const settingsDirectory = await makeHostScratchDirectory(SETTINGS_DIR_PREFIX);
21644
21922
  const settingsPath = path.join(settingsDirectory, "settings.json");
21645
- const removeSettingsDirectory = () => fsp.rm(settingsDirectory, {
21923
+ const removeSettingsDirectory = () => fs$1.rm(settingsDirectory, {
21646
21924
  recursive: true,
21647
21925
  force: true
21648
21926
  }).catch(() => {});
@@ -21742,7 +22020,7 @@ function createLaneSpawn({ sessions = /* @__PURE__ */ new Map(), closeSessionDat
21742
22020
  }
21743
22021
  async function readLaneResultFile(resultPath) {
21744
22022
  try {
21745
- return JSON.parse(await fsp.readFile(resultPath, "utf8"));
22023
+ return JSON.parse(await fs$1.readFile(resultPath, "utf8"));
21746
22024
  } catch {
21747
22025
  return null;
21748
22026
  }
@@ -21753,12 +22031,12 @@ var THREAD_JUDGE_TOOLS = Object.freeze(["Read", "Write"]);
21753
22031
  var THREAD_JUDGE_TIMEOUT_MS = 12e4;
21754
22032
  function createThreadJudge(spawn, shutdownSignal) {
21755
22033
  return async (prompt) => {
21756
- const workDir = await fsp.mkdtemp(path.join(os.tmpdir(), "glimmervoid-thread-judge-"));
22034
+ const workDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "glimmervoid-thread-judge-"));
21757
22035
  const controller = new AbortController();
21758
22036
  const timeout = setTimeout(() => controller.abort(), THREAD_JUDGE_TIMEOUT_MS);
21759
22037
  timeout.unref();
21760
22038
  try {
21761
- await fsp.writeFile(path.join(workDir, "thread-prompt.txt"), prompt, "utf8");
22039
+ await fs$1.writeFile(path.join(workDir, "thread-prompt.txt"), prompt, "utf8");
21762
22040
  const signal = shutdownSignal ? AbortSignal.any([controller.signal, shutdownSignal]) : controller.signal;
21763
22041
  if (signal.aborted) return null;
21764
22042
  await spawn({
@@ -21773,7 +22051,7 @@ function createThreadJudge(spawn, shutdownSignal) {
21773
22051
  return parseThreadJudgeResult(await readLaneResultFile(path.join(workDir, "thread-result.json")));
21774
22052
  } finally {
21775
22053
  clearTimeout(timeout);
21776
- await fsp.rm(workDir, {
22054
+ await fs$1.rm(workDir, {
21777
22055
  recursive: true,
21778
22056
  force: true
21779
22057
  });
@@ -21790,13 +22068,14 @@ var GH_MERGE_FLAGS = {
21790
22068
  var MY_PR_MERGE_STATE_QUERY = `query($owner: String!, $name: String!, $number: Int!) {
21791
22069
  repository(owner: $owner, name: $name) { pullRequest(number: $number) { state isInMergeQueue autoMergeRequest { enabledAt } } }
21792
22070
  }`;
21793
- var GH_TIMEOUT_MS = 3e4;
22071
+ var GH_READ_TIMEOUT_MS = 15e3;
22072
+ var GH_WRITE_TIMEOUT_MS = 3e4;
21794
22073
  var GH_MAX_BUFFER_BYTES = 2097153;
21795
- function run(cmd, args, cwd, input, preserveOutput = false) {
22074
+ function run(cmd, args, cwd, input, preserveOutput = false, timeoutMs = GH_READ_TIMEOUT_MS) {
21796
22075
  return runCommand(cmd, args, {
21797
22076
  cwd,
21798
22077
  input,
21799
- timeoutMs: GH_TIMEOUT_MS,
22078
+ timeoutMs,
21800
22079
  maxBuffer: GH_MAX_BUFFER_BYTES,
21801
22080
  trim: !preserveOutput,
21802
22081
  keepStdoutOnFailure: true,
@@ -22101,9 +22380,9 @@ function conditionalGetResult(response) {
22101
22380
  }
22102
22381
  }
22103
22382
  function createPrGh(cwd, commandRunner = run) {
22104
- async function runGh(args, input, preserveOutput = false) {
22383
+ async function runGh(args, input, preserveOutput = false, timeoutMs = GH_READ_TIMEOUT_MS) {
22105
22384
  try {
22106
- return await commandRunner("gh", args, cwd, input, preserveOutput);
22385
+ return await commandRunner("gh", args, cwd, input, preserveOutput, timeoutMs);
22107
22386
  } catch (error) {
22108
22387
  return {
22109
22388
  ok: false,
@@ -22433,7 +22712,7 @@ function createPrGh(cwd, commandRunner = run) {
22433
22712
  repo,
22434
22713
  "--add-label",
22435
22714
  label.data
22436
- ]);
22715
+ ], void 0, false, GH_WRITE_TIMEOUT_MS);
22437
22716
  return {
22438
22717
  ok: response.ok,
22439
22718
  err: response.ok ? "" : response.err.trim() || "gh pr edit failed"
@@ -22457,7 +22736,7 @@ function createPrGh(cwd, commandRunner = run) {
22457
22736
  repo,
22458
22737
  "--body-file",
22459
22738
  "-"
22460
- ], comment.data);
22739
+ ], comment.data, false, GH_WRITE_TIMEOUT_MS);
22461
22740
  return {
22462
22741
  ok: response.ok,
22463
22742
  err: response.ok ? "" : response.err.trim() || "gh pr comment failed"
@@ -22530,7 +22809,7 @@ function createPrGh(cwd, commandRunner = run) {
22530
22809
  `query=${RESOLVE_THREAD_MUTATION}`,
22531
22810
  "-f",
22532
22811
  `id=${threadId}`
22533
- ]);
22812
+ ], void 0, false, GH_WRITE_TIMEOUT_MS);
22534
22813
  const parsed = TeamReviewResolveResponse.safeParse(parseJsonOrNull(response.out));
22535
22814
  const isResolved = response.ok && parsed.success && !parsed.data.errors?.length && parsed.data.data?.resolveReviewThread.thread.id === threadId;
22536
22815
  return {
@@ -22691,7 +22970,7 @@ function createPrGh(cwd, commandRunner = run) {
22691
22970
  `id=${pullRequestId}`,
22692
22971
  "-f",
22693
22972
  `head=${expectedHeadSha}`
22694
- ]);
22973
+ ], void 0, false, GH_WRITE_TIMEOUT_MS);
22695
22974
  if (!response.ok) return {
22696
22975
  ok: false,
22697
22976
  err: response.err.trim() || "gh graphql rebase failed"
@@ -22730,7 +23009,7 @@ function createPrGh(cwd, commandRunner = run) {
22730
23009
  GH_MERGE_FLAGS[parsedMethod.data],
22731
23010
  "--match-head-commit",
22732
23011
  headSha
22733
- ]);
23012
+ ], void 0, false, GH_WRITE_TIMEOUT_MS);
22734
23013
  if (!response.ok) return {
22735
23014
  ok: false,
22736
23015
  err: response.err.trim() || "gh pr merge failed"
@@ -22966,7 +23245,7 @@ function createPrGh(cwd, commandRunner = run) {
22966
23245
  `repos/${parts[0]}/${parts[1]}/pulls/${number}/reviews`,
22967
23246
  "--input",
22968
23247
  "-"
22969
- ], input);
23248
+ ], input, false, GH_WRITE_TIMEOUT_MS);
22970
23249
  if (!response.ok) return {
22971
23250
  ok: false,
22972
23251
  err: response.err.trim() || "gh review post failed",
@@ -23004,7 +23283,7 @@ function createPrGh(cwd, commandRunner = run) {
23004
23283
  `repos/${parts[0]}/${parts[1]}/pulls/${number}/reviews/${reviewId}/dismissals`,
23005
23284
  "--input",
23006
23285
  "-"
23007
- ], input);
23286
+ ], input, false, GH_WRITE_TIMEOUT_MS);
23008
23287
  return {
23009
23288
  ok: response.ok,
23010
23289
  err: response.ok ? "" : response.err.trim() || "gh review dismissal failed"
@@ -23358,7 +23637,7 @@ var PROCESS_LIST_TIMEOUT_MS = 5e3;
23358
23637
  var TERMINATION_GRACE_MS = 2e3;
23359
23638
  var EXIT_POLL_MS = 100;
23360
23639
  async function resolvedPath(directory) {
23361
- return fsp.realpath(directory).catch(() => path.resolve(directory));
23640
+ return fs$1.realpath(directory).catch(() => path.resolve(directory));
23362
23641
  }
23363
23642
  async function listTeamReviewProcesses() {
23364
23643
  if (process.platform !== "darwin" && process.platform !== "linux") return [];
@@ -23375,7 +23654,7 @@ async function listTeamReviewProcesses() {
23375
23654
  const rows = parseProcessTable(stdout);
23376
23655
  if (process.platform === "linux") return Promise.all(rows.map(async (row) => ({
23377
23656
  ...row,
23378
- cwd: await fsp.readlink(`/proc/${row.pid}/cwd`).then((cwd) => path.resolve(cwd)).catch(() => null)
23657
+ cwd: await fs$1.readlink(`/proc/${row.pid}/cwd`).then((cwd) => path.resolve(cwd)).catch(() => null)
23379
23658
  })));
23380
23659
  const { stdout: cwdOutput } = await execFileAsync("lsof", [
23381
23660
  "-a",
@@ -23390,7 +23669,7 @@ async function listTeamReviewProcesses() {
23390
23669
  const cwdByPid = parseCwdTable(cwdOutput);
23391
23670
  return Promise.all(rows.map(async (row) => ({
23392
23671
  ...row,
23393
- cwd: await fsp.realpath(cwdByPid.get(row.pid) ?? "").catch(() => null)
23672
+ cwd: await fs$1.realpath(cwdByPid.get(row.pid) ?? "").catch(() => null)
23394
23673
  })));
23395
23674
  }
23396
23675
  function isMissingProcess(error) {
@@ -24137,9 +24416,13 @@ function createTeamReviewPoller(deps) {
24137
24416
  }
24138
24417
  async function rateLimitedOutcome() {
24139
24418
  const rateLimitWaitMs = await store.rateLimitWaitMs(now(), TEAM_REVIEW_RATE_LIMIT_RESOURCES) ?? secondaryRateLimitWaitMs(pollingError);
24140
- return rateLimitWaitMs === null ? { failed: true } : {
24419
+ return rateLimitWaitMs === null ? {
24141
24420
  failed: true,
24142
- retryAfterMs: rateLimitWaitMs
24421
+ error: pollingError ?? void 0
24422
+ } : {
24423
+ failed: true,
24424
+ retryAfterMs: rateLimitWaitMs,
24425
+ error: pollingError ?? void 0
24143
24426
  };
24144
24427
  }
24145
24428
  async function runTick() {
@@ -24154,7 +24437,8 @@ function createTeamReviewPoller(deps) {
24154
24437
  pollingError = "GitHub rate limit asks to wait.";
24155
24438
  return {
24156
24439
  failed: true,
24157
- retryAfterMs: tickRateLimitWaitMs
24440
+ retryAfterMs: tickRateLimitWaitMs,
24441
+ error: pollingError
24158
24442
  };
24159
24443
  }
24160
24444
  if (collected === null) {
@@ -24172,7 +24456,8 @@ function createTeamReviewPoller(deps) {
24172
24456
  pollingError = "GitHub rate limit asks to wait.";
24173
24457
  return {
24174
24458
  failed: true,
24175
- retryAfterMs: rateLimitWaitMs
24459
+ retryAfterMs: rateLimitWaitMs,
24460
+ error: pollingError
24176
24461
  };
24177
24462
  }
24178
24463
  const isPruned = await pruneDeparted(new Set(candidates.map((candidate) => candidate.key)), isComplete);
@@ -24185,7 +24470,8 @@ function createTeamReviewPoller(deps) {
24185
24470
  pollingError = "GitHub rate limit asks to wait.";
24186
24471
  return {
24187
24472
  failed: true,
24188
- retryAfterMs: tickRateLimitWaitMs
24473
+ retryAfterMs: tickRateLimitWaitMs,
24474
+ error: pollingError
24189
24475
  };
24190
24476
  }
24191
24477
  if (hasSlotFreedSinceSlotCount && waitingForSlot.length > 0 && !loop.isStopped()) setTimeoutFn(() => {
@@ -24438,10 +24724,11 @@ function createTeamReviewPoller(deps) {
24438
24724
  error: "Reviews polling is stopped."
24439
24725
  };
24440
24726
  if (watches.size === 0) await collectCandidates();
24441
- const refreshed = await store.refreshWatches([...watches.keys()]);
24442
- rebuild();
24443
- if (!refreshed.ok) return refreshed;
24444
- return loop.refresh();
24727
+ return loop.refresh(async () => {
24728
+ const refreshed = await store.refreshWatches([...watches.keys()]);
24729
+ rebuild();
24730
+ return refreshed;
24731
+ });
24445
24732
  }
24446
24733
  async function stop() {
24447
24734
  hasLoadedState = false;
@@ -24836,7 +25123,7 @@ function listHomeWorktreePathsMissingLock(porcelain, glimmervoidHomes) {
24836
25123
  }
24837
25124
  //#endregion
24838
25125
  //#region server/git/git-workspace.ts
24839
- var fsp$1 = fs.promises;
25126
+ var fsp = fs.promises;
24840
25127
  var MERGE_PROBE_TIMEOUT_MS = 3e4;
24841
25128
  var REMOTE_REF_PREFIX = "refs/remotes/origin/";
24842
25129
  var REMOTE_BRANCH_LISTING_MAX_BUFFER = 67108864;
@@ -24908,7 +25195,7 @@ function comparableGlimmervoidHomes(glimmervoidHome) {
24908
25195
  }
24909
25196
  async function directoryExists$1(candidatePath) {
24910
25197
  try {
24911
- await fsp$1.access(candidatePath);
25198
+ await fsp.access(candidatePath);
24912
25199
  return true;
24913
25200
  } catch {
24914
25201
  return false;
@@ -25068,13 +25355,19 @@ function createGitWorkspace(opts = {}) {
25068
25355
  }
25069
25356
  }
25070
25357
  const runInProject = (projectPath) => (args) => run(args, projectPath);
25071
- async function addWorktreeEntry(runGitInProject, worktreePath, addArgs) {
25358
+ async function addWorktreeEntry(runGitInProject, worktreePath, addArgs, ownership) {
25072
25359
  const added = await runGitInProject([
25073
25360
  "worktree",
25074
25361
  "add",
25075
25362
  ...addArgs
25076
25363
  ]);
25077
- if (!added.ok || !isWorktreeHiddenFromGuardedSessions(worktreePath, glimmervoidHomes)) return added;
25364
+ if (!added.ok) return added;
25365
+ await opts.ownedPaths?.record({
25366
+ path: worktreePath,
25367
+ kind: "git-worktree",
25368
+ ...ownership
25369
+ });
25370
+ if (!isWorktreeHiddenFromGuardedSessions(worktreePath, glimmervoidHomes)) return added;
25078
25371
  await lockWorktreeEntry(runGitInProject, worktreePath);
25079
25372
  return added;
25080
25373
  }
@@ -25100,12 +25393,27 @@ function createGitWorkspace(opts = {}) {
25100
25393
  "unlock",
25101
25394
  worktreePath
25102
25395
  ]);
25103
- return runGitInProject([
25396
+ const removed = await runGitInProject([
25104
25397
  "worktree",
25105
25398
  "remove",
25106
25399
  ...removeFlags,
25107
25400
  worktreePath
25108
25401
  ]);
25402
+ await forgetRemovedPath(worktreePath);
25403
+ return removed;
25404
+ }
25405
+ async function forgetRemovedPath(ownedPath) {
25406
+ if (await directoryExists$1(ownedPath)) return;
25407
+ await opts.ownedPaths?.forget(ownedPath);
25408
+ }
25409
+ async function recordOwnedFolder({ folderPath, owner }) {
25410
+ await opts.ownedPaths?.record({
25411
+ path: folderPath,
25412
+ owner,
25413
+ kind: "folder",
25414
+ projectPath: null,
25415
+ branch: null
25416
+ });
25109
25417
  }
25110
25418
  async function pruneWorktreeEntries(runGitInProject) {
25111
25419
  const listed = await runGitInProject([
@@ -25343,7 +25651,7 @@ function createGitWorkspace(opts = {}) {
25343
25651
  }
25344
25652
  return null;
25345
25653
  }
25346
- async function createBody({ projectPath, teamId, label, baseBranch = null, configuredIntegrationBranch = null, forkFromHead = false, worktreeBase, shareList }) {
25654
+ async function createBody({ projectPath, owner, teamId, label, baseBranch = null, configuredIntegrationBranch = null, forkFromHead = false, worktreeBase, shareList }) {
25347
25655
  const inside = await run(["rev-parse", "--is-inside-work-tree"], projectPath);
25348
25656
  if (!inside.ok || inside.out !== "true") return {
25349
25657
  cwd: projectPath,
@@ -25422,7 +25730,11 @@ function createGitWorkspace(opts = {}) {
25422
25730
  branch,
25423
25731
  wtDir,
25424
25732
  baseSha
25425
- ]);
25733
+ ], {
25734
+ owner,
25735
+ projectPath,
25736
+ branch
25737
+ });
25426
25738
  if (!add.ok) {
25427
25739
  try {
25428
25740
  fs.rmSync(wtDir, {
@@ -25470,7 +25782,7 @@ function createGitWorkspace(opts = {}) {
25470
25782
  if (keepTrackableLinks) return;
25471
25783
  await refuseTrackableLinks(wtDir, ignored);
25472
25784
  }
25473
- async function ensureWorkspaceMemberBody({ projectPath, wtDir, branch, shareList }) {
25785
+ async function ensureWorkspaceMemberBody({ projectPath, owner, wtDir, branch, shareList }) {
25474
25786
  if (!wtDir || !branch) return {
25475
25787
  cwd: projectPath,
25476
25788
  isGit: false,
@@ -25521,7 +25833,11 @@ function createGitWorkspace(opts = {}) {
25521
25833
  "--quiet",
25522
25834
  `refs/heads/${branch}`
25523
25835
  ], projectPath)).ok) {
25524
- const attached = await addWorktreeEntry(runInProject(projectPath), wtDir, [wtDir, branch]);
25836
+ const attached = await addWorktreeEntry(runInProject(projectPath), wtDir, [wtDir, branch], {
25837
+ owner,
25838
+ projectPath,
25839
+ branch
25840
+ });
25525
25841
  if (!attached.ok) return {
25526
25842
  cwd: projectPath,
25527
25843
  isGit: false,
@@ -25572,7 +25888,11 @@ function createGitWorkspace(opts = {}) {
25572
25888
  branch,
25573
25889
  wtDir,
25574
25890
  baseSha
25575
- ]);
25891
+ ], {
25892
+ owner,
25893
+ projectPath,
25894
+ branch
25895
+ });
25576
25896
  if (!added.ok) return {
25577
25897
  cwd: projectPath,
25578
25898
  isGit: false,
@@ -25601,11 +25921,11 @@ function createGitWorkspace(opts = {}) {
25601
25921
  rel
25602
25922
  ], wtDir)).ok) continue;
25603
25923
  const target = path.join(wtDir, rel);
25604
- const stat = await fsp$1.lstat(target).catch(() => null);
25924
+ const stat = await fsp.lstat(target).catch(() => null);
25605
25925
  if (!stat || !stat.isSymbolicLink()) continue;
25606
25926
  console.warn(`[git-workspace] not sharing ${rel}: git does not ignore it as a link, so a commit in the worktree would carry it (use a slash-free .gitignore entry)`);
25607
25927
  try {
25608
- await fsp$1.rm(target, { force: true });
25928
+ await fsp.rm(target, { force: true });
25609
25929
  } catch {}
25610
25930
  }
25611
25931
  }
@@ -25866,7 +26186,7 @@ function createGitWorkspace(opts = {}) {
25866
26186
  for (const [index, segment] of pathSegments.entries()) {
25867
26187
  if (!segment || segment === "." || segment === "..") return false;
25868
26188
  checkedPath = path.join(checkedPath, segment);
25869
- const entryStats = await fsp$1.lstat(checkedPath).catch(() => null);
26189
+ const entryStats = await fsp.lstat(checkedPath).catch(() => null);
25870
26190
  if (!entryStats) return false;
25871
26191
  if (index === pathSegments.length - 1) return entryStats.isFile();
25872
26192
  if (!entryStats.isDirectory()) return false;
@@ -26096,7 +26416,7 @@ function createGitWorkspace(opts = {}) {
26096
26416
  ], projectPath);
26097
26417
  await pruneWorktreeEntries(runInProject(projectPath));
26098
26418
  }
26099
- async function probeWorktreeWork({ projectPath, cwd, branch, integrationBranch, configuredIntegrationBranch }) {
26419
+ async function probeWorktreeWork({ projectPath, cwd, branch, measuredTip = branch, integrationBranch, configuredIntegrationBranch }) {
26100
26420
  const { base: resolvedIntegrationBranch, measureRef } = await migrateMarkerBase(projectPath, branch, integrationBranch, configuredIntegrationBranch);
26101
26421
  const dirty = await run(WORK_PRESENCE_STATUS_ARGS, cwd);
26102
26422
  return {
@@ -26104,11 +26424,32 @@ function createGitWorkspace(opts = {}) {
26104
26424
  ahead: !isDirtyResult(dirty) && resolvedIntegrationBranch ? await run([
26105
26425
  "rev-list",
26106
26426
  "--count",
26107
- `${measureRef || resolvedIntegrationBranch}..${branch}`
26427
+ `${measureRef || resolvedIntegrationBranch}..${measuredTip}`
26108
26428
  ], projectPath) : null,
26109
26429
  integrationBranch: resolvedIntegrationBranch ?? null
26110
26430
  };
26111
26431
  }
26432
+ async function describeWorkspaceMemberWorkBody({ projectPath, cwd, branch }) {
26433
+ const memberHead = await run([
26434
+ "rev-parse",
26435
+ "--verify",
26436
+ "HEAD"
26437
+ ], cwd);
26438
+ if (!memberHead.ok || !memberHead.out) return "its checked-out commit could not be read";
26439
+ const integrationBranch = await detectDefaultBranch({ projectPath });
26440
+ const { dirty, ahead, integrationBranch: comparedBranch } = await probeWorktreeWork({
26441
+ projectPath,
26442
+ cwd,
26443
+ branch,
26444
+ measuredTip: memberHead.out,
26445
+ integrationBranch
26446
+ });
26447
+ if (!dirty.ok) return "its git status could not be read";
26448
+ if (isDirtyResult(dirty)) return "uncommitted changes";
26449
+ if (!ahead?.ok) return "its commits could not be compared with the base branch";
26450
+ if (!ahead.out || ahead.out === "0") return null;
26451
+ return `${ahead.out} ${ahead.out === "1" ? "commit" : "commits"} not on ${comparedBranch}`;
26452
+ }
26112
26453
  async function hasUnmergedWorkBody({ projectPath, workspace, integrationBranch, configuredIntegrationBranch }) {
26113
26454
  if (!workspace || !workspace.isGit || !workspace.cwd || !workspace.branch) return true;
26114
26455
  const { dirty, ahead } = await probeWorktreeWork({
@@ -26314,7 +26655,7 @@ function createGitWorkspace(opts = {}) {
26314
26655
  for (const rel of shareList ?? []) {
26315
26656
  if (!rel || String(rel).includes("..")) continue;
26316
26657
  const linkPath = path.join(wtDir, rel);
26317
- const stat = await fsp$1.lstat(linkPath).catch(() => null);
26658
+ const stat = await fsp.lstat(linkPath).catch(() => null);
26318
26659
  if (!stat || !stat.isSymbolicLink()) continue;
26319
26660
  if (!(await run([
26320
26661
  "check-ignore",
@@ -26322,21 +26663,30 @@ function createGitWorkspace(opts = {}) {
26322
26663
  "--",
26323
26664
  rel
26324
26665
  ], wtDir)).ok) continue;
26325
- await fsp$1.rm(linkPath, {
26666
+ await fsp.rm(linkPath, {
26326
26667
  recursive: false,
26327
26668
  force: true
26328
- }).catch(() => fsp$1.rmdir(linkPath)).catch(() => {});
26669
+ }).catch(() => fsp.rmdir(linkPath)).catch(() => {});
26329
26670
  }
26330
26671
  }
26331
- async function removeWorkspaceMemberBody({ projectPath, cwd, shareList }) {
26672
+ async function removeWorkspaceMemberBody({ projectPath, cwd, shareList, discardWork = false }) {
26332
26673
  if (!cwd) return {
26333
26674
  ok: false,
26334
26675
  out: "",
26335
26676
  err: "a workspace member removal needs a path"
26336
26677
  };
26337
26678
  await removeSharedLinks(cwd, shareList);
26338
- const removed = await removeWorktreeEntry(runInProject(projectPath), cwd, []);
26679
+ const removed = await removeWorktreeEntry(runInProject(projectPath), cwd, discardWork ? ["--force", "--force"] : []);
26680
+ if (discardWork && await directoryExists$1(cwd)) await fsp.rm(cwd, {
26681
+ recursive: true,
26682
+ force: true
26683
+ });
26339
26684
  await pruneWorktreeEntries(runInProject(projectPath));
26685
+ await forgetRemovedPath(cwd);
26686
+ if (discardWork && !await directoryExists$1(cwd)) return {
26687
+ ok: true,
26688
+ out: removed.out
26689
+ };
26340
26690
  return removed;
26341
26691
  }
26342
26692
  async function listWorktreeBranches({ projectPath }) {
@@ -26457,7 +26807,7 @@ function createGitWorkspace(opts = {}) {
26457
26807
  if (!updated.ok) return updated;
26458
26808
  return okResult(originSha);
26459
26809
  }
26460
- async function stageDetachedWorktreeBody({ projectPath, worktreePath, sha, disableHooks, replaceEnv }) {
26810
+ async function stageDetachedWorktreeBody({ projectPath, worktreePath, sha, owner, disableHooks, replaceEnv }) {
26461
26811
  if (!worktreePath) return {
26462
26812
  ok: false,
26463
26813
  out: "",
@@ -26475,7 +26825,11 @@ function createGitWorkspace(opts = {}) {
26475
26825
  "--detach",
26476
26826
  worktreePath,
26477
26827
  sha
26478
- ]);
26828
+ ], {
26829
+ owner,
26830
+ projectPath,
26831
+ branch: null
26832
+ });
26479
26833
  }
26480
26834
  async function checkoutDetachedBody({ worktreePath, sha, ...isolation }) {
26481
26835
  if (!worktreePath) return {
@@ -26534,8 +26888,8 @@ function createGitWorkspace(opts = {}) {
26534
26888
  err: commonDir.err || "the source repository has no git dir"
26535
26889
  };
26536
26890
  const sourceObjectsDir = path.join(path.resolve(projectPath, commonDir.out), "objects");
26537
- await fsp$1.mkdir(path.dirname(checkoutPath), { recursive: true });
26538
- await fsp$1.mkdir(checkoutPath);
26891
+ await fsp.mkdir(path.dirname(checkoutPath), { recursive: true });
26892
+ await fsp.mkdir(checkoutPath);
26539
26893
  const initialized = await run([
26540
26894
  "init",
26541
26895
  "--quiet",
@@ -26543,8 +26897,8 @@ function createGitWorkspace(opts = {}) {
26543
26897
  ], checkoutPath);
26544
26898
  if (!initialized.ok) return initialized;
26545
26899
  const alternatesPath = path.join(checkoutPath, ".git", "objects", "info", "alternates");
26546
- await fsp$1.mkdir(path.dirname(alternatesPath), { recursive: true });
26547
- await fsp$1.writeFile(alternatesPath, `${sourceObjectsDir}\n`, "utf8");
26900
+ await fsp.mkdir(path.dirname(alternatesPath), { recursive: true });
26901
+ await fsp.writeFile(alternatesPath, `${sourceObjectsDir}\n`, "utf8");
26548
26902
  for (const [ref, refSha] of [[ISOLATED_CHECKOUT_REVIEW_REF, sha], [ISOLATED_CHECKOUT_BASE_REF, baseSha]]) {
26549
26903
  const updated = await run([
26550
26904
  "update-ref",
@@ -26730,7 +27084,7 @@ function createGitWorkspace(opts = {}) {
26730
27084
  };
26731
27085
  const addedPaths = added.out.split("\0").filter(Boolean);
26732
27086
  const collidingPaths = [];
26733
- for (const addedPath of addedPaths) if (await fsp$1.lstat(path.join(checkoutPath, addedPath)).then(() => true, (error) => !isMissingFileError(error, { includeNotDir: false }))) collidingPaths.push(addedPath);
27087
+ for (const addedPath of addedPaths) if (await fsp.lstat(path.join(checkoutPath, addedPath)).then(() => true, (error) => !isMissingFileError(error, { includeNotDir: false }))) collidingPaths.push(addedPath);
26734
27088
  return {
26735
27089
  ok: true,
26736
27090
  collidingPaths
@@ -27066,6 +27420,9 @@ function createGitWorkspace(opts = {}) {
27066
27420
  pruneWorktrees: serialized(pruneWorktreesBody),
27067
27421
  discardSessionBranch: serialized(discardSessionBranchBody),
27068
27422
  stageDetachedWorktree: serialized(stageDetachedWorktreeBody),
27423
+ forgetRemovedPath,
27424
+ recordOwnedFolder,
27425
+ describeWorkspaceMemberWork: serialized(describeWorkspaceMemberWorkBody),
27069
27426
  checkoutDetached: serialized(checkoutDetachedBody),
27070
27427
  stageIsolatedCheckout,
27071
27428
  mergeFastForwardTo,
@@ -27231,6 +27588,7 @@ function createGitWorkspaceSync(opts = {}) {
27231
27588
  "--force",
27232
27589
  cwd
27233
27590
  ], projectPath);
27591
+ if (!fs.existsSync(cwd)) opts.ownedPaths?.forget(cwd);
27234
27592
  }
27235
27593
  if (branch) run([
27236
27594
  "branch",
@@ -27289,10 +27647,10 @@ async function populateWorktree(projectPath, wtDir, shareList) {
27289
27647
  const src = path.join(projectPath, rel);
27290
27648
  const dst = path.join(wtDir, rel);
27291
27649
  try {
27292
- const srcStat = await fsp$1.stat(src).catch(() => null);
27650
+ const srcStat = await fsp.stat(src).catch(() => null);
27293
27651
  if (!srcStat) continue;
27294
- if (await fsp$1.access(dst).then(() => true, (error) => !isMissingFileError(error, { includeNotDir: false }))) continue;
27295
- await fsp$1.mkdir(path.dirname(dst), { recursive: true });
27652
+ if (await fsp.access(dst).then(() => true, (error) => !isMissingFileError(error, { includeNotDir: false }))) continue;
27653
+ await fsp.mkdir(path.dirname(dst), { recursive: true });
27296
27654
  if (srcStat.isDirectory()) {
27297
27655
  if (process.platform === "win32") {
27298
27656
  await execFileAsync("cmd", [
@@ -27304,10 +27662,10 @@ async function populateWorktree(projectPath, wtDir, shareList) {
27304
27662
  ]);
27305
27663
  continue;
27306
27664
  }
27307
- await fsp$1.symlink(src, dst, "dir");
27665
+ await fsp.symlink(src, dst, "dir");
27308
27666
  continue;
27309
27667
  }
27310
- await fsp$1.copyFile(src, dst);
27668
+ await fsp.copyFile(src, dst);
27311
27669
  } catch {}
27312
27670
  }
27313
27671
  }
@@ -27460,7 +27818,7 @@ async function describeTeamReviewRole({ checkoutPath, cachedClone, linkedCheckou
27460
27818
  }
27461
27819
  async function linkedCheckoutUnreadablePaths(linkedCheckout) {
27462
27820
  if (linkedCheckout === null) return [];
27463
- return (await fsp.readdir(linkedCheckout)).filter((entryName) => LINKED_CHECKOUT_UNREADABLE_ENTRY.test(entryName)).map((entryName) => path.join(linkedCheckout, entryName));
27821
+ return (await fs$1.readdir(linkedCheckout)).filter((entryName) => LINKED_CHECKOUT_UNREADABLE_ENTRY.test(entryName)).map((entryName) => path.join(linkedCheckout, entryName));
27464
27822
  }
27465
27823
  function teamReviewClaudeArgs(tier, readable) {
27466
27824
  const model = tier === "full" ? FULL_MODEL : STAMP_MODEL;
@@ -27511,11 +27869,11 @@ function hooksPathPinnedSpawnEnv(workDir) {
27511
27869
  }
27512
27870
  async function makeTeamReviewWorkDir(root, prefix) {
27513
27871
  const safePrefix = `glimmervoid-wt-${TEAM_REVIEW_LANE_ID}-${prefix}`.replace(/[^\w.-]+/g, "-");
27514
- await fsp.mkdir(root, { recursive: true });
27515
- const dir = await fsp.mkdtemp(path.join(root, `${safePrefix}-`));
27872
+ await fs$1.mkdir(root, { recursive: true });
27873
+ const dir = await fs$1.mkdtemp(path.join(root, `${safePrefix}-`));
27516
27874
  return {
27517
27875
  dir,
27518
- cleanup: () => fsp.rm(dir, {
27876
+ cleanup: () => fs$1.rm(dir, {
27519
27877
  recursive: true,
27520
27878
  force: true
27521
27879
  }).catch(() => {})
@@ -27524,11 +27882,11 @@ async function makeTeamReviewWorkDir(root, prefix) {
27524
27882
  async function readReviewReport(reportPath, expectedHead, isReReview) {
27525
27883
  let report;
27526
27884
  try {
27527
- if ((await fsp.stat(reportPath)).size > RESULT_MAX_BYTES$1) return {
27885
+ if ((await fs$1.stat(reportPath)).size > RESULT_MAX_BYTES$1) return {
27528
27886
  ok: false,
27529
27887
  reason: "the review report is too large"
27530
27888
  };
27531
- report = await fsp.readFile(reportPath, "utf8");
27889
+ report = await fs$1.readFile(reportPath, "utf8");
27532
27890
  } catch {
27533
27891
  return {
27534
27892
  ok: false,
@@ -27549,11 +27907,11 @@ async function readReviewReport(reportPath, expectedHead, isReReview) {
27549
27907
  async function readPostingPlan(postingPath, expectedHead, log) {
27550
27908
  let json;
27551
27909
  try {
27552
- if ((await fsp.stat(postingPath)).size > RESULT_MAX_BYTES$1) {
27910
+ if ((await fs$1.stat(postingPath)).size > RESULT_MAX_BYTES$1) {
27553
27911
  log.warn(`[${TEAM_REVIEW_LANE_ID}] the posting plan is too large, rendering from the findings instead`);
27554
27912
  return null;
27555
27913
  }
27556
- json = await fsp.readFile(postingPath, "utf8");
27914
+ json = await fs$1.readFile(postingPath, "utf8");
27557
27915
  } catch {
27558
27916
  return null;
27559
27917
  }
@@ -27566,7 +27924,7 @@ function worktreeDirName(repo, number, suffix) {
27566
27924
  return `glimmervoid-wt-${TEAM_REVIEW_LANE_ID}-${repo.replace(/[^\w.-]+/g, "-")}-${number}-${suffix}`;
27567
27925
  }
27568
27926
  async function pathExists(candidatePath) {
27569
- return fsp.lstat(candidatePath).then(() => true, () => false);
27927
+ return fs$1.lstat(candidatePath).then(() => true, () => false);
27570
27928
  }
27571
27929
  function isDirectChildOf(root, candidatePath) {
27572
27930
  return path.dirname(path.resolve(candidatePath)) === path.resolve(root);
@@ -27576,10 +27934,10 @@ function isOwnedResumable(record, roots) {
27576
27934
  }
27577
27935
  async function isRealChildDirectoryOrMissing(root, candidatePath) {
27578
27936
  if (!isDirectChildOf(root, candidatePath)) return false;
27579
- const candidateStat = await fsp.lstat(candidatePath).catch((error) => isMissingFileError(error, { includeNotDir: false }) ? "missing" : null);
27937
+ const candidateStat = await fs$1.lstat(candidatePath).catch((error) => isMissingFileError(error, { includeNotDir: false }) ? "missing" : null);
27580
27938
  if (candidateStat === "missing") return true;
27581
27939
  if (!candidateStat?.isDirectory()) return false;
27582
- const realPaths = await Promise.all([fsp.realpath(candidatePath), fsp.realpath(root)]).catch(() => null);
27940
+ const realPaths = await Promise.all([fs$1.realpath(candidatePath), fs$1.realpath(root)]).catch(() => null);
27583
27941
  if (!realPaths) return false;
27584
27942
  const [realCandidatePath, realRootPath] = realPaths;
27585
27943
  return path.dirname(realCandidatePath) === realRootPath;
@@ -27596,13 +27954,17 @@ async function pruneCachedClone(gitWorkspace, projectPath, log) {
27596
27954
  if (!pruned.ok) log.warn(`[${TEAM_REVIEW_LANE_ID}] worktree prune failed in ${projectPath}: ${firstLine$1(pruned.err ?? "")}`);
27597
27955
  }
27598
27956
  async function deleteDirectory(directory, log) {
27599
- await fsp.rm(directory, {
27957
+ await fs$1.rm(directory, {
27600
27958
  recursive: true,
27601
27959
  force: true
27602
27960
  }).catch((error) => log.warn(`[${TEAM_REVIEW_LANE_ID}] could not delete ${directory}: ${errorMessage(error)}`));
27603
27961
  }
27962
+ async function deleteCheckout(gitWorkspace, worktreePath, log) {
27963
+ await deleteDirectory(worktreePath, log);
27964
+ await gitWorkspace.forgetRemovedPath?.(worktreePath);
27965
+ }
27604
27966
  async function isDirectory(candidatePath) {
27605
- return (await fsp.stat(candidatePath).catch(() => null))?.isDirectory() === true;
27967
+ return (await fs$1.stat(candidatePath).catch(() => null))?.isDirectory() === true;
27606
27968
  }
27607
27969
  async function mainCheckoutOf(checkoutPath) {
27608
27970
  const gitDirs = await readGitDirsOfOwnCheckout(checkoutPath).catch(() => null);
@@ -27614,17 +27976,17 @@ async function mainCheckoutOf(checkoutPath) {
27614
27976
  async function configuredProjectPathsByRealPath(projects) {
27615
27977
  const configuredPathByRealPath = /* @__PURE__ */ new Map();
27616
27978
  for (const project of projects) {
27617
- const projectRealPath = await fsp.realpath(project.path).catch(() => null);
27979
+ const projectRealPath = await fs$1.realpath(project.path).catch(() => null);
27618
27980
  if (projectRealPath === null || configuredPathByRealPath.has(projectRealPath)) continue;
27619
27981
  configuredPathByRealPath.set(projectRealPath, project.path);
27620
27982
  }
27621
27983
  return configuredPathByRealPath;
27622
27984
  }
27623
27985
  async function findLocalCheckout({ repo, config, excludedRoots, gitWorkspace, log, requireInstalledModules = true, resolveCheckout }) {
27624
- const resolvedExcludedRoots = await Promise.all(excludedRoots.map(async (root) => fsp.realpath(root).catch(() => path.resolve(root))));
27986
+ const resolvedExcludedRoots = await Promise.all(excludedRoots.map(async (root) => fs$1.realpath(root).catch(() => path.resolve(root))));
27625
27987
  const candidatePaths = (config.projects ?? []).map((project) => project.path);
27626
27988
  for (const root of config.repoRoots ?? []) {
27627
- const childNames = (await fsp.readdir(root, { withFileTypes: true }).catch((error) => {
27989
+ const childNames = (await fs$1.readdir(root, { withFileTypes: true }).catch((error) => {
27628
27990
  log.warn(`[${TEAM_REVIEW_LANE_ID}] could not list local repositories in ${root}: ${errorMessage(error)}`);
27629
27991
  return [];
27630
27992
  })).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".") && entry.name !== "node_modules").map((entry) => entry.name).sort();
@@ -27632,7 +27994,7 @@ async function findLocalCheckout({ repo, config, excludedRoots, gitWorkspace, lo
27632
27994
  }
27633
27995
  const seenPaths = /* @__PURE__ */ new Set();
27634
27996
  for (const candidatePath of candidatePaths) {
27635
- const checkoutPath = await fsp.realpath(candidatePath).catch(() => null);
27997
+ const checkoutPath = await fs$1.realpath(candidatePath).catch(() => null);
27636
27998
  if (!checkoutPath || seenPaths.has(checkoutPath)) continue;
27637
27999
  seenPaths.add(checkoutPath);
27638
28000
  if (resolvedExcludedRoots.some((root) => isPathInside(root, checkoutPath))) continue;
@@ -27646,9 +28008,9 @@ async function findLocalCheckout({ repo, config, excludedRoots, gitWorkspace, lo
27646
28008
  }
27647
28009
  async function isLinkedToCheckout(worktreePath, localCheckout) {
27648
28010
  const modulesPath = path.join(worktreePath, "node_modules");
27649
- if (!(await fsp.lstat(modulesPath).catch(() => null))?.isSymbolicLink()) return false;
27650
- const linkedModules = await fsp.realpath(modulesPath).catch(() => null);
27651
- const checkoutModules = await fsp.realpath(path.join(localCheckout, "node_modules")).catch(() => null);
28011
+ if (!(await fs$1.lstat(modulesPath).catch(() => null))?.isSymbolicLink()) return false;
28012
+ const linkedModules = await fs$1.realpath(modulesPath).catch(() => null);
28013
+ const checkoutModules = await fs$1.realpath(path.join(localCheckout, "node_modules")).catch(() => null);
27652
28014
  return linkedModules !== null && linkedModules === checkoutModules;
27653
28015
  }
27654
28016
  async function sweepLeftoverCheckouts({ worktreeRoot, workRoot, keepPaths, repoCache, gitWorkspace, reapProcesses = reapTeamReviewProcesses, log }) {
@@ -27659,11 +28021,11 @@ async function sweepLeftoverCheckouts({ worktreeRoot, workRoot, keepPaths, repoC
27659
28021
  log
27660
28022
  }).catch((error) => log.warn(`[${TEAM_REVIEW_LANE_ID}] process reap failed: ${errorMessage(error)}`));
27661
28023
  for (const root of [worktreeRoot, workRoot]) {
27662
- const leftoverNames = await fsp.readdir(root).catch(() => []);
28024
+ const leftoverNames = await fs$1.readdir(root).catch(() => []);
27663
28025
  for (const leftoverName of leftoverNames) {
27664
28026
  const directory = path.join(root, leftoverName);
27665
28027
  if (keepPaths.has(directory)) continue;
27666
- await deleteDirectory(directory, log);
28028
+ await deleteCheckout(gitWorkspace, directory, log);
27667
28029
  }
27668
28030
  }
27669
28031
  const cachedClones = await repoCache.listRepos().catch((error) => {
@@ -27683,7 +28045,7 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27683
28045
  }));
27684
28046
  if (removal.ok && !await pathExists(worktreePath)) return;
27685
28047
  log.warn(`[${TEAM_REVIEW_LANE_ID}] worktree removal failed for ${worktreePath}, deleting it directly: ${firstLine$1(removal.err ?? "") || "the directory is still present"}`);
27686
- await deleteDirectory(worktreePath, log);
28048
+ await deleteCheckout(gitWorkspace, worktreePath, log);
27687
28049
  await pruneCachedClone(gitWorkspace, projectPath, log);
27688
28050
  }
27689
28051
  async function discoverLocalCheckout(repo) {
@@ -27730,7 +28092,7 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27730
28092
  return null;
27731
28093
  }
27732
28094
  const scratchObjectsDir = path.join(workDir, REMERGE_OBJECTS_DIRNAME);
27733
- await fsp.mkdir(scratchObjectsDir, { recursive: true });
28095
+ await fs$1.mkdir(scratchObjectsDir, { recursive: true });
27734
28096
  return {
27735
28097
  ...isolation.range,
27736
28098
  scratchObjectsDir
@@ -27840,7 +28202,7 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27840
28202
  }
27841
28203
  };
27842
28204
  if (hasWorkDir) await deleteDirectory(args.resume.workDir, log);
27843
- if (hasWorktree) await deleteDirectory(args.resume.worktreePath, log);
28205
+ if (hasWorktree) await deleteCheckout(gitWorkspace, args.resume.worktreePath, log);
27844
28206
  return {
27845
28207
  kind: "stopped",
27846
28208
  resumable: null
@@ -27931,7 +28293,7 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27931
28293
  projectPath,
27932
28294
  worktreePath: args.resume.worktreePath
27933
28295
  });
27934
- if (!projectPath) await deleteDirectory(args.resume.worktreePath, log);
28296
+ if (!projectPath) await deleteCheckout(gitWorkspace, args.resume.worktreePath, log);
27935
28297
  }
27936
28298
  if (hasWorkDir) await deleteDirectory(args.resume.workDir, log);
27937
28299
  sessionId = null;
@@ -27955,9 +28317,10 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27955
28317
  projectPath: staged.projectPath,
27956
28318
  worktreePath
27957
28319
  };
27958
- await fsp.mkdir(worktreeRoot, { recursive: true });
28320
+ await fs$1.mkdir(worktreeRoot, { recursive: true });
27959
28321
  const created = await gitWorkspace.stageDetachedWorktree({
27960
28322
  projectPath: staged.projectPath,
28323
+ owner: "lane:team-review",
27961
28324
  worktreePath,
27962
28325
  sha: detail.headRefOid
27963
28326
  });
@@ -27998,8 +28361,8 @@ function createTeamReviewDispatcher({ store, repoCache, gitWorkspace, spawnSessi
27998
28361
  priorReview,
27999
28362
  newWork
28000
28363
  });
28001
- await fsp.writeFile(path.join(workDir, REVIEW_PROMPT_FILENAME), prompt, "utf8");
28002
- await fsp.mkdir(emptyGhConfigDir(workDir), { recursive: true });
28364
+ await fs$1.writeFile(path.join(workDir, REVIEW_PROMPT_FILENAME), prompt, "utf8");
28365
+ await fs$1.mkdir(emptyGhConfigDir(workDir), { recursive: true });
28003
28366
  reportProgress({
28004
28367
  kind: "phase",
28005
28368
  phase: "reviewing",
@@ -28517,7 +28880,7 @@ function createTeamReviewWiring({ config, store, reviewSessions, closeSessionDat
28517
28880
  scope: "run",
28518
28881
  log
28519
28882
  }).catch((error) => log.warn(`[${TEAM_REVIEW_LANE_ID}] process reap failed: ${errorMessage(error)}`));
28520
- await deleteDirectory(record.worktreePath, log);
28883
+ await deleteCheckout(gitWorkspace, record.worktreePath, log);
28521
28884
  await deleteDirectory(record.workDir, log);
28522
28885
  const cachedClones = await repoCache.listRepos();
28523
28886
  for (const projectPath of cachedClones) await pruneCachedClone(gitWorkspace, projectPath, log);
@@ -28584,7 +28947,7 @@ function createTeamReviewWiring({ config, store, reviewSessions, closeSessionDat
28584
28947
  worktreeRoot,
28585
28948
  workRoot
28586
28949
  ];
28587
- const resolvedExcludedRoots = await Promise.all(excludedRoots.map((root) => fsp.realpath(root).catch(() => path.resolve(root))));
28950
+ const resolvedExcludedRoots = await Promise.all(excludedRoots.map((root) => fs$1.realpath(root).catch(() => path.resolve(root))));
28588
28951
  const configuredPathByRealPath = await configuredProjectPathsByRealPath(config.projects ?? []);
28589
28952
  return findLocalCheckout({
28590
28953
  repo,
@@ -28878,18 +29241,18 @@ function worktreeOwnerRepo(gitFileText) {
28878
29241
  async function readJsonFile$1(filePath) {
28879
29242
  return loadedJsonValue(await loadJsonStateFile({
28880
29243
  filePath,
28881
- fsPromises: fsp,
29244
+ fsPromises: fs$1,
28882
29245
  parse: (raw) => raw,
28883
29246
  quarantine: false
28884
29247
  }));
28885
29248
  }
28886
29249
  async function jsonFileNames(directory) {
28887
- return (await fsp.readdir(directory, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
29250
+ return (await fs$1.readdir(directory, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isFile() && entry.name.endsWith(".json")).map((entry) => entry.name).sort();
28888
29251
  }
28889
29252
  async function readBoundedText(filePath) {
28890
- const stat = await fsp.stat(filePath).catch(() => null);
29253
+ const stat = await fs$1.stat(filePath).catch(() => null);
28891
29254
  if (!stat?.isFile() || stat.size > RESULT_MAX_BYTES) return null;
28892
- return fsp.readFile(filePath, "utf8").catch(() => null);
29255
+ return fs$1.readFile(filePath, "utf8").catch(() => null);
28893
29256
  }
28894
29257
  function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast, store, repoCache, repoCacheRoot, gitWorkspace, spawnSubject, spawnJudge, credentials, claudeCommand, runArmCommand = runArmCommandSafely, guardrailsRefusal = allowGuardedSpawn, baseEnv = process.env, now = () => Date.now(), randomSuffix = () => randomBytes(4).toString("hex"), log = console }) {
28895
29258
  let activeRun = null;
@@ -28898,7 +29261,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
28898
29261
  let leftoverSweep = Promise.resolve();
28899
29262
  const suiteDir = (suiteId) => path.join(benchmarksRoot, suiteId);
28900
29263
  async function removeDirectoryOrWarn(directory) {
28901
- await fsp.rm(directory, {
29264
+ await fs$1.rm(directory, {
28902
29265
  recursive: true,
28903
29266
  force: true
28904
29267
  }).catch((error) => log.warn(`[${BENCHMARK_LANE_ID}] could not remove ${directory}: ${firstLine(errorMessage(error))}`));
@@ -28997,7 +29360,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
28997
29360
  return refreshed;
28998
29361
  }
28999
29362
  async function summarizeAndBroadcast() {
29000
- const suiteIds = (await fsp.readdir(benchmarksRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && BenchmarkId.safeParse(entry.name).success).map((entry) => entry.name).sort();
29363
+ const suiteIds = (await fs$1.readdir(benchmarksRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && BenchmarkId.safeParse(entry.name).success).map((entry) => entry.name).sort();
29001
29364
  const summaries = [];
29002
29365
  for (const suiteId of suiteIds) summaries.push(await summarizeSuite(suiteId).catch((error) => unreadableSuiteSummary(suiteId, errorMessage(error))));
29003
29366
  suites = summaries;
@@ -29054,7 +29417,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29054
29417
  error: mined.reason
29055
29418
  };
29056
29419
  const candidatesDir = path.join(suiteDir(suiteId), "candidates");
29057
- await fsp.mkdir(candidatesDir, { recursive: true });
29420
+ await fs$1.mkdir(candidatesDir, { recursive: true });
29058
29421
  for (const outcome of mined.outcomes) {
29059
29422
  if (!outcome.candidate) {
29060
29423
  log.warn(`[${BENCHMARK_LANE_ID}] ${caseSource.repo}#${outcome.number} not mined: ${outcome.refusal}`);
@@ -29150,7 +29513,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29150
29513
  reason: "the reviewed commit could not be fetched, or the base is not its ancestor"
29151
29514
  };
29152
29515
  const checkoutPath = path.join(staged.caseDir, "checkout");
29153
- const cleared = await fsp.rm(checkoutPath, {
29516
+ const cleared = await fs$1.rm(checkoutPath, {
29154
29517
  recursive: true,
29155
29518
  force: true
29156
29519
  }).then(() => null, (error) => errorMessage(error));
@@ -29171,7 +29534,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29171
29534
  reason: `could not stage a checkout: ${firstLine(created.err ?? "") || "the isolated checkout failed"}`
29172
29535
  };
29173
29536
  }
29174
- const sharedObjectsPath = firstLine(await fsp.readFile(path.join(checkoutPath, ".git", "objects", "info", "alternates"), "utf8").catch(() => ""));
29537
+ const sharedObjectsPath = firstLine(await fs$1.readFile(path.join(checkoutPath, ".git", "objects", "info", "alternates"), "utf8").catch(() => ""));
29175
29538
  if (!sharedObjectsPath) {
29176
29539
  await removeDirectoryOrWarn(checkoutPath);
29177
29540
  return {
@@ -29189,7 +29552,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29189
29552
  if (existing) return existing;
29190
29553
  const caseDir = path.join(runDir, benchmarkCase.id);
29191
29554
  const workDir = path.join(caseDir, "work");
29192
- await fsp.mkdir(workDir, { recursive: true });
29555
+ await fs$1.mkdir(workDir, { recursive: true });
29193
29556
  const staged = {
29194
29557
  checkoutPath: null,
29195
29558
  sharedObjectsPath: null,
@@ -29272,7 +29635,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29272
29635
  },
29273
29636
  judgeSeed: (cell) => cell.index + 1,
29274
29637
  async persist(run) {
29275
- await fsp.mkdir(runsDir, { recursive: true });
29638
+ await fs$1.mkdir(runsDir, { recursive: true });
29276
29639
  await writeJsonAtomic(path.join(runsDir, `${runId}.json`), redactedRun(run, usedTokens));
29277
29640
  },
29278
29641
  reportProgress
@@ -29299,10 +29662,10 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29299
29662
  };
29300
29663
  usedTokens.add(token.token);
29301
29664
  const resultPath = path.join(staged.workDir, SUBJECT_RESULT_FILENAME);
29302
- await fsp.rm(resultPath, { force: true });
29303
- await fsp.writeFile(path.join(staged.workDir, SUBJECT_PROMPT_FILENAME), prompt, "utf8");
29665
+ await fs$1.rm(resultPath, { force: true });
29666
+ await fs$1.writeFile(path.join(staged.workDir, SUBJECT_PROMPT_FILENAME), prompt, "utf8");
29304
29667
  const baseSpawnEnv = hooksPathPinnedSpawnEnv(staged.workDir);
29305
- await fsp.mkdir(baseSpawnEnv.GH_CONFIG_DIR, { recursive: true });
29668
+ await fs$1.mkdir(baseSpawnEnv.GH_CONFIG_DIR, { recursive: true });
29306
29669
  const subjectController = new AbortController();
29307
29670
  const stopSubject = () => subjectController.abort();
29308
29671
  let hasTimedOut = false;
@@ -29364,8 +29727,8 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29364
29727
  };
29365
29728
  }
29366
29729
  async function runJudgeSession({ cell, prompt, model, signal, runDir }) {
29367
- await fsp.mkdir(runDir, { recursive: true });
29368
- const judgeDir = await fsp.mkdtemp(path.join(runDir, `judge-${cell.index}-`));
29730
+ await fs$1.mkdir(runDir, { recursive: true });
29731
+ const judgeDir = await fs$1.mkdtemp(path.join(runDir, `judge-${cell.index}-`));
29369
29732
  const resultPath = path.join(judgeDir, JUDGE_RESULT_FILENAME);
29370
29733
  try {
29371
29734
  await spawnJudge({
@@ -29394,7 +29757,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29394
29757
  costUsd: null
29395
29758
  };
29396
29759
  } finally {
29397
- await fsp.rm(judgeDir, {
29760
+ await fs$1.rm(judgeDir, {
29398
29761
  recursive: true,
29399
29762
  force: true
29400
29763
  }).catch(() => {});
@@ -29480,7 +29843,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29480
29843
  return respond(outcome);
29481
29844
  }
29482
29845
  async function removeLeftoverWorktree(worktreePath) {
29483
- const projectPath = worktreeOwnerRepo(await fsp.readFile(path.join(worktreePath, ".git"), "utf8").catch(() => ""));
29846
+ const projectPath = worktreeOwnerRepo(await fs$1.readFile(path.join(worktreePath, ".git"), "utf8").catch(() => ""));
29484
29847
  if (projectPath) {
29485
29848
  const removal = await gitWorkspace.removeWorktreeByPath({
29486
29849
  projectPath,
@@ -29507,7 +29870,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29507
29870
  }
29508
29871
  async function sweepSuiteLeftovers(suiteId) {
29509
29872
  const worktreesDir = path.join(suiteDir(suiteId), "worktrees");
29510
- const worktreeEntries = await fsp.readdir(worktreesDir, { withFileTypes: true }).catch(() => []);
29873
+ const worktreeEntries = await fs$1.readdir(worktreesDir, { withFileTypes: true }).catch(() => []);
29511
29874
  for (const entry of worktreeEntries) if (entry.isDirectory()) await removeLeftoverWorktree(path.join(worktreesDir, entry.name));
29512
29875
  await removeDirectoryOrWarn(worktreesDir);
29513
29876
  await removeDirectoryOrWarn(path.join(suiteDir(suiteId), "work"));
@@ -29516,7 +29879,7 @@ function createBenchmarkWiring({ benchmarksRoot, runsRoot, isEnabled, broadcast,
29516
29879
  async function sweepAllLeftovers() {
29517
29880
  if (activeRun) return;
29518
29881
  await removeDirectoryOrWarn(runsRoot);
29519
- const suiteIds = (await fsp.readdir(benchmarksRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && BenchmarkId.safeParse(entry.name).success).map((entry) => entry.name);
29882
+ const suiteIds = (await fs$1.readdir(benchmarksRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && BenchmarkId.safeParse(entry.name).success).map((entry) => entry.name);
29520
29883
  for (const suiteId of suiteIds) await sweepSuiteLeftovers(suiteId).catch((error) => log.warn(`[${BENCHMARK_LANE_ID}] could not sweep ${suiteId}: ${errorMessage(error)}`));
29521
29884
  }
29522
29885
  function sweepLeftovers() {
@@ -30662,7 +31025,7 @@ function createCoderEnvWiring({ config, persistMapping, onReconciled = () => {},
30662
31025
  var DEFAULT_INTERVAL_MS$1 = 216e5;
30663
31026
  var BRANCH_GC_FETCH_TIMEOUT_MS = 6e4;
30664
31027
  function createBranchGcPoller(deps) {
30665
- const { gitWorkspace, getConfig, liveSessionIds, liveWorktreePaths, staleDays = 14, deleteUnmerged = false, prefixes = DEFAULT_BRANCH_GC_PREFIXES, pruneWorktrees = true, dryRun = false, intervalMs = DEFAULT_INTERVAL_MS$1, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, log = console, decisionTrace = () => {}, onTickComplete = () => {}, now = () => Date.now(), statProjectPath = (projectPath) => fsp.stat(projectPath) } = deps;
31028
+ const { gitWorkspace, getConfig, liveSessionIds, liveWorktreePaths, staleDays = 14, deleteUnmerged = false, prefixes = DEFAULT_BRANCH_GC_PREFIXES, pruneWorktrees = true, dryRun = false, intervalMs = DEFAULT_INTERVAL_MS$1, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, log = console, decisionTrace = () => {}, onTickComplete = () => {}, now = () => Date.now(), statProjectPath = (projectPath) => fs$1.stat(projectPath) } = deps;
30666
31029
  const skippedProjectPaths = /* @__PURE__ */ new Set();
30667
31030
  async function callGit(method, args) {
30668
31031
  try {
@@ -33403,7 +33766,7 @@ function classifyGitStatusFailure(error) {
33403
33766
  var DEFAULT_MAX_REPOS = 16;
33404
33767
  var DEFAULT_GIT_TIMEOUT_MS = 15e3;
33405
33768
  var MAX_GIT_BUFFER_BYTES = 8388608;
33406
- function createGitIngest({ publish, sourceConfig = {}, reposProvider = null, logger = console, execFileFn = execFileAsync, createWatch = createWatchDebounce, canonicalize = canonicalizePath, statRepoDir = (dir) => fsp.stat(dir), nowFn = Date.now, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, maxRepos = DEFAULT_MAX_REPOS, gitTimeoutMs = DEFAULT_GIT_TIMEOUT_MS, gitPath = "git" } = {}) {
33769
+ function createGitIngest({ publish, sourceConfig = {}, reposProvider = null, logger = console, execFileFn = execFileAsync, createWatch = createWatchDebounce, canonicalize = canonicalizePath, statRepoDir = (dir) => fs$1.stat(dir), nowFn = Date.now, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, maxRepos = DEFAULT_MAX_REPOS, gitTimeoutMs = DEFAULT_GIT_TIMEOUT_MS, gitPath = "git" } = {}) {
33407
33770
  if (typeof publish !== "function") throw new Error("createGitIngest requires publish");
33408
33771
  const publishEvent = publish;
33409
33772
  const settleMs = positiveIntOr(sourceConfig.debounceMs, DEFAULT_DEBOUNCE_MS);
@@ -34826,10 +35189,10 @@ function hasAutoSessionName(session) {
34826
35189
  return isAutoNameOf(session.name, path.basename(session.path));
34827
35190
  }
34828
35191
  async function refineTaskTitle(request, model, spawnLane, signal) {
34829
- const workDir = await fsp.mkdtemp(path.join(os.tmpdir(), "glimmervoid-task-title-"));
35192
+ const workDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "glimmervoid-task-title-"));
34830
35193
  const resultPath = path.join(workDir, RESULT_FILE$1);
34831
35194
  try {
34832
- await fsp.writeFile(path.join(workDir, PROMPT_FILE$1), buildTaskTitleRefinementPrompt({
35195
+ await fs$1.writeFile(path.join(workDir, PROMPT_FILE$1), buildTaskTitleRefinementPrompt({
34833
35196
  currentTitle: request.currentTitle,
34834
35197
  recentPrompts: request.recentPrompts,
34835
35198
  resultPath,
@@ -34852,7 +35215,7 @@ async function refineTaskTitle(request, model, spawnLane, signal) {
34852
35215
  proposedSessionName: request.wantsSessionName ? parseRefinedSessionName(laneResult) : null
34853
35216
  };
34854
35217
  } finally {
34855
- await fsp.rm(workDir, {
35218
+ await fs$1.rm(workDir, {
34856
35219
  recursive: true,
34857
35220
  force: true
34858
35221
  });
@@ -37939,6 +38302,7 @@ function createRadarWiring({ config, investigationSessions, closeSessionDataClie
37939
38302
  const issueId = safeIssueId(issue.issueId);
37940
38303
  const workspace = await Promise.resolve(gitWorkspace.create({
37941
38304
  projectPath: repoPath,
38305
+ owner: "lane:radar-fix",
37942
38306
  teamId: "radar-fix",
37943
38307
  label: `${safeIssueId(projectId)}-${issueId}-${newFixDiscriminator()}`,
37944
38308
  worktreeBase: worktreeBaseFor(repoPath),
@@ -38446,9 +38810,13 @@ function createMyPrsPoller(dependencies) {
38446
38810
  });
38447
38811
  async function failedOutcome(errorText) {
38448
38812
  const rateLimitWaitMs = await store.rateLimitWaitMs(now(), MY_PRS_RATE_LIMIT_RESOURCES) ?? secondaryRateLimitWaitMs(errorText);
38449
- return rateLimitWaitMs === null ? { failed: true } : {
38813
+ return rateLimitWaitMs === null ? {
38450
38814
  failed: true,
38451
- retryAfterMs: rateLimitWaitMs
38815
+ error: errorText
38816
+ } : {
38817
+ failed: true,
38818
+ retryAfterMs: rateLimitWaitMs,
38819
+ error: errorText
38452
38820
  };
38453
38821
  }
38454
38822
  async function runTick() {
@@ -38775,10 +39143,11 @@ function createMyPrsPoller(dependencies) {
38775
39143
  error: "Reviews polling is stopped."
38776
39144
  };
38777
39145
  registerWatches();
38778
- const refreshed = await store.refreshWatches(watchNames);
38779
- rebuild();
38780
- if (!refreshed.ok) return refreshed;
38781
- return loop.refresh();
39146
+ return loop.refresh(async () => {
39147
+ const refreshed = await store.refreshWatches(watchNames);
39148
+ rebuild();
39149
+ return refreshed;
39150
+ });
38782
39151
  }
38783
39152
  return {
38784
39153
  start,
@@ -38801,10 +39170,10 @@ function defaultAgentSearchRoots() {
38801
39170
  return roots.filter((root, index) => roots.indexOf(root) === index);
38802
39171
  }
38803
39172
  async function readEntryNames(directory) {
38804
- return fsp.readdir(directory).catch(() => []);
39173
+ return fs$1.readdir(directory).catch(() => []);
38805
39174
  }
38806
39175
  async function ownedSocketAt(socketPath, ownerUid) {
38807
- const stats = await fsp.lstat(socketPath).catch(() => null);
39176
+ const stats = await fs$1.lstat(socketPath).catch(() => null);
38808
39177
  if (!stats?.isSocket()) return null;
38809
39178
  if (ownerUid !== null && stats.uid !== ownerUid) return null;
38810
39179
  return {
@@ -38852,12 +39221,12 @@ function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSea
38852
39221
  ok: false,
38853
39222
  error: NO_AGENT_HOLDS_KEY
38854
39223
  };
38855
- const workDir = await fsp.mkdtemp(path.join(os.tmpdir(), "glimmervoid-sign-"));
39224
+ const workDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "glimmervoid-sign-"));
38856
39225
  try {
38857
39226
  const keyPath = path.join(workDir, "signing-key.pub");
38858
39227
  const payloadPath = path.join(workDir, "payload");
38859
- await fsp.writeFile(keyPath, `${formatSshPublicKey(publicKey)}\n`, { mode: 384 });
38860
- await fsp.writeFile(payloadPath, payload, { mode: 384 });
39228
+ await fs$1.writeFile(keyPath, `${formatSshPublicKey(publicKey)}\n`, { mode: 384 });
39229
+ await fs$1.writeFile(payloadPath, payload, { mode: 384 });
38861
39230
  await execFileAsync("ssh-keygen", [
38862
39231
  "-Y",
38863
39232
  "sign",
@@ -38877,7 +39246,7 @@ function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSea
38877
39246
  });
38878
39247
  return {
38879
39248
  ok: true,
38880
- signature: await fsp.readFile(`${payloadPath}.sig`, "utf8")
39249
+ signature: await fs$1.readFile(`${payloadPath}.sig`, "utf8")
38881
39250
  };
38882
39251
  } catch (error) {
38883
39252
  const stderr = error?.stderr;
@@ -38886,7 +39255,7 @@ function createSshSigner({ env = process.env, agentSearchRoots = defaultAgentSea
38886
39255
  error: `ssh-keygen could not sign: ${typeof stderr === "string" && stderr.trim() ? stderr.trim() : errorMessage(error)}`
38887
39256
  };
38888
39257
  } finally {
38889
- await fsp.rm(workDir, {
39258
+ await fs$1.rm(workDir, {
38890
39259
  recursive: true,
38891
39260
  force: true
38892
39261
  });
@@ -38901,7 +39270,7 @@ async function readSigningKeySetting(setting, cwd) {
38901
39270
  const literalKey = parseSshPublicKey(setting);
38902
39271
  if (literalKey) return literalKey;
38903
39272
  const keyPath = path.resolve(cwd, setting.replace(/^~(?=\/|$)/, os.homedir()));
38904
- return parseSshPublicKey(await fsp.readFile(keyPath, "utf8").catch(() => ""));
39273
+ return parseSshPublicKey(await fs$1.readFile(keyPath, "utf8").catch(() => ""));
38905
39274
  }
38906
39275
  function readTextOrNull(filePath) {
38907
39276
  try {
@@ -39089,8 +39458,8 @@ function createGuardedPrStaging({ spawnSession, repoCache, describeRole = guarde
39089
39458
  if (!staged.ok) return { error: `could not stage the checkout ${staged.err}` };
39090
39459
  }
39091
39460
  const excludePath = path.join(checkoutPath, ".git", "info", "exclude");
39092
- await fsp.mkdir(path.dirname(excludePath), { recursive: true });
39093
- await fsp.appendFile(excludePath, keepMergeableExcludeLines(), "utf8");
39461
+ await fs$1.mkdir(path.dirname(excludePath), { recursive: true });
39462
+ await fs$1.appendFile(excludePath, keepMergeableExcludeLines(), "utf8");
39094
39463
  return {
39095
39464
  projectPath,
39096
39465
  baseSha: baseSha.data
@@ -39283,7 +39652,7 @@ function createMyPrMergeabilityFix({ spawnSession, repoCache, workRoot, makeWork
39283
39652
  };
39284
39653
  }
39285
39654
  async function fetchSessionCommits(staged, checkoutPath, headSha, handoffRef, signal) {
39286
- const bundleDir = await fsp.mkdtemp(path.join(os.tmpdir(), "glimmervoid-keep-mergeable-"));
39655
+ const bundleDir = await fs$1.mkdtemp(path.join(os.tmpdir(), "glimmervoid-keep-mergeable-"));
39287
39656
  try {
39288
39657
  const bundlePath = path.join(bundleDir, "session.bundle");
39289
39658
  const bundled = await runGit([
@@ -39305,7 +39674,7 @@ function createMyPrMergeabilityFix({ spawnSession, repoCache, workRoot, makeWork
39305
39674
  `+${KEEP_MERGEABLE_WORK_BRANCH_REF}:${handoffRef}`
39306
39675
  ], staged.projectPath, signal);
39307
39676
  } finally {
39308
- await fsp.rm(bundleDir, {
39677
+ await fs$1.rm(bundleDir, {
39309
39678
  recursive: true,
39310
39679
  force: true
39311
39680
  });
@@ -39390,8 +39759,8 @@ function createMyPrMergeabilityFix({ spawnSession, repoCache, workRoot, makeWork
39390
39759
  if ("error" in staged) return reportRepairFailure(pr, `not started: ${staged.error}`);
39391
39760
  projectPath = staged.projectPath;
39392
39761
  if (signal.aborted) return stopped;
39393
- await fsp.writeFile(path.join(workDir.dir, MY_PRS_FIX_PROMPT_FILENAME), keepMergeablePrompt(pr), "utf8");
39394
- await fsp.mkdir(emptyGhConfigDir(workDir.dir), { recursive: true });
39762
+ await fs$1.writeFile(path.join(workDir.dir, MY_PRS_FIX_PROMPT_FILENAME), keepMergeablePrompt(pr), "utf8");
39763
+ await fs$1.mkdir(emptyGhConfigDir(workDir.dir), { recursive: true });
39395
39764
  const outcome = await runSession({
39396
39765
  idPrefix: MY_PRS_LANE_ID,
39397
39766
  name: `Keep mergeable ${pr.key}`,
@@ -40230,12 +40599,16 @@ function createWorkflowsPoller(dependencies) {
40230
40599
  return stateLoad;
40231
40600
  }
40232
40601
  function publishStatus() {
40602
+ const { nextAttemptAt, retry, isRefreshing, refreshNotice } = loop.scheduleStatus();
40233
40603
  onTickComplete({
40234
40604
  type: "workflows-status",
40235
40605
  ts: now(),
40236
40606
  configured: true,
40237
40607
  error: pollingError,
40238
- ...loop.scheduleStatus()
40608
+ nextAttemptAt,
40609
+ retry,
40610
+ isRefreshing,
40611
+ refreshNotice
40239
40612
  });
40240
40613
  }
40241
40614
  const loop = createTickLoop({
@@ -40415,8 +40788,8 @@ function createWorkflowSpawn({ staging, workRoot, makeWorkDir = makeTeamReviewWo
40415
40788
  const staged = await staging.stageCheckout(pr, workDir.dir, signal);
40416
40789
  if (signal.aborted) return;
40417
40790
  if ("error" in staged) return warn(`not started: ${staged.error}`);
40418
- await fsp.writeFile(path.join(workDir.dir, WORKFLOW_PROMPT_FILENAME), workflowSpawnPrompt(action.promptTemplate, event, MY_PRS_FIX_CHECKOUT_DIRNAME), "utf8");
40419
- await fsp.mkdir(emptyGhConfigDir(workDir.dir), { recursive: true });
40791
+ await fs$1.writeFile(path.join(workDir.dir, WORKFLOW_PROMPT_FILENAME), workflowSpawnPrompt(action.promptTemplate, event, MY_PRS_FIX_CHECKOUT_DIRNAME), "utf8");
40792
+ await fs$1.mkdir(emptyGhConfigDir(workDir.dir), { recursive: true });
40420
40793
  if (await staging.runSession({
40421
40794
  idPrefix: "workflows",
40422
40795
  name: workflowSessionName({
@@ -40507,15 +40880,28 @@ function createWorkflowsWiring({ config, notificationManager, spawnSession, log
40507
40880
  }
40508
40881
  //#endregion
40509
40882
  //#region server/github/github-clock.ts
40510
- function createGithubClock({ baseIntervalMs, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, log = console }) {
40883
+ function createGithubClock({ baseIntervalMs, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, log = console, githubStatus }) {
40511
40884
  const subscriptions = /* @__PURE__ */ new Set();
40512
40885
  let timer = null;
40513
40886
  let isSweeping = false;
40514
- let exclusiveChain = Promise.resolve();
40515
- function exclusive(work) {
40516
- const outcome = exclusiveChain.then(() => work());
40517
- exclusiveChain = outcome.catch(() => void 0);
40518
- return outcome;
40887
+ let isExclusiveRunning = false;
40888
+ const priorityJobs = [];
40889
+ const backgroundJobs = [];
40890
+ function runNextExclusiveJob() {
40891
+ if (isExclusiveRunning) return;
40892
+ const job = priorityJobs.shift() ?? backgroundJobs.shift();
40893
+ if (!job) return;
40894
+ isExclusiveRunning = true;
40895
+ job().finally(() => {
40896
+ isExclusiveRunning = false;
40897
+ runNextExclusiveJob();
40898
+ });
40899
+ }
40900
+ function exclusive(work, { isPriority = false } = {}) {
40901
+ return new Promise((resolve, reject) => {
40902
+ (isPriority ? priorityJobs : backgroundJobs).push(() => Promise.resolve().then(work).then(resolve, reject));
40903
+ runNextExclusiveJob();
40904
+ });
40519
40905
  }
40520
40906
  async function sweep() {
40521
40907
  if (isSweeping) return;
@@ -40557,7 +40943,56 @@ function createGithubClock({ baseIntervalMs, setIntervalFn = DEFAULT_TIMER_FNS.s
40557
40943
  return {
40558
40944
  schedule,
40559
40945
  exclusive,
40560
- sweep
40946
+ sweep,
40947
+ githubStatus
40948
+ };
40949
+ }
40950
+ //#endregion
40951
+ //#region server/github/core/github-status-core.ts
40952
+ var GITHUB_STATUS_CACHE_MS = 3e5;
40953
+ var GithubStatusSummary = z.object({ incidents: z.array(z.object({
40954
+ name: z.string(),
40955
+ status: z.string(),
40956
+ updated_at: z.iso.datetime({ offset: true })
40957
+ })) });
40958
+ function openIncidentName(body) {
40959
+ const summary = GithubStatusSummary.safeParse(body);
40960
+ if (!summary.success) return null;
40961
+ const openIncidents = summary.data.incidents.filter((incident) => incident.status !== "resolved" && incident.status !== "postmortem");
40962
+ openIncidents.sort((first, second) => Date.parse(second.updated_at) - Date.parse(first.updated_at));
40963
+ return openIncidents[0]?.name ?? null;
40964
+ }
40965
+ function isStatusReadDue(lastReadAtMs, nowMs) {
40966
+ return lastReadAtMs === null || nowMs - lastReadAtMs >= GITHUB_STATUS_CACHE_MS;
40967
+ }
40968
+ //#endregion
40969
+ //#region server/github/github-status.ts
40970
+ function createGithubStatus({ fetchFn = fetch, now = Date.now, log }) {
40971
+ let lastReadAtMs = null;
40972
+ let cachedIncident = null;
40973
+ let hasWarned = false;
40974
+ async function readStatus() {
40975
+ try {
40976
+ const response = await fetchFn("https://www.githubstatus.com/api/v2/summary.json", { signal: AbortSignal.timeout(5e3) });
40977
+ if (!response.ok) throw new Error(`HTTP ${response.status}`);
40978
+ cachedIncident = openIncidentName(GithubStatusSummary.parse(await response.json()));
40979
+ hasWarned = false;
40980
+ } catch (error) {
40981
+ cachedIncident = null;
40982
+ if (hasWarned) return;
40983
+ hasWarned = true;
40984
+ log.warn(`[github-status] read failed: ${errorMessage(error)}`);
40985
+ }
40986
+ }
40987
+ function noteTransientFailure() {
40988
+ const nowMs = now();
40989
+ if (!isStatusReadDue(lastReadAtMs, nowMs)) return;
40990
+ lastReadAtMs = nowMs;
40991
+ readStatus();
40992
+ }
40993
+ return {
40994
+ noteTransientFailure,
40995
+ incident: () => cachedIncident
40561
40996
  };
40562
40997
  }
40563
40998
  //#endregion
@@ -41611,7 +42046,7 @@ function isFresh(fetchedAt, nowMs) {
41611
42046
  if (!Number.isFinite(fetchedMs)) return false;
41612
42047
  return nowMs - fetchedMs < CACHE_TTL_MS;
41613
42048
  }
41614
- async function loadPricing({ fetchEnabled, fsPromises = fsp, fetchFn = globalThis.fetch, cachePath = path.join(glimmervoidHomeDir$1(), "litellm-pricing.json"), nowFn = Date.now, timeoutMs = 15e3, logger = null } = {}) {
42049
+ async function loadPricing({ fetchEnabled, fsPromises = fs$1, fetchFn = globalThis.fetch, cachePath = path.join(glimmervoidHomeDir$1(), "litellm-pricing.json"), nowFn = Date.now, timeoutMs = 15e3, logger = null } = {}) {
41615
42050
  if (!fetchEnabled) return {
41616
42051
  table: normalizePricingTable(claude_pricing_default),
41617
42052
  source: "snapshot",
@@ -42310,7 +42745,7 @@ async function walkSourceFiles(roots, fsPromises, laneLog) {
42310
42745
  };
42311
42746
  }
42312
42747
  function createUsageScanner(deps = {}) {
42313
- const { fsPromises = fsp, env = process.env, homeDir = os.homedir(), nowFn = Date.now, pricingTable, aliases = {}, costMode = "auto", blockHours = 5, retainDays = 90, extraProjectsDirs = [], vendors = {
42748
+ const { fsPromises = fs$1, env = process.env, homeDir = os.homedir(), nowFn = Date.now, pricingTable, aliases = {}, costMode = "auto", blockHours = 5, retainDays = 90, extraProjectsDirs = [], vendors = {
42314
42749
  codex: true,
42315
42750
  grok: true
42316
42751
  }, warehousePath = null, warehouseRetainDays = 365, budget: budgetDep = null, laneMap = null, logger = noopLogger, byteBudget = DEFAULT_BYTE_BUDGET, chunkSize = DEFAULT_CHUNK_SIZE, yieldNowFn = yieldNow } = deps;
@@ -43144,7 +43579,7 @@ function formatBudgetUsd(value) {
43144
43579
  function budgetAlertText({ scope, threshold, spentUsd, budgetUsd }) {
43145
43580
  return `Usage budget: ${scope === "monthly" ? "monthly" : "daily"} spend ${formatBudgetUsd(spentUsd)} reached ${threshold}% of ${formatBudgetUsd(budgetUsd)}`;
43146
43581
  }
43147
- function createUsageWiring({ config, sessions = /* @__PURE__ */ new Map(), broadcast = () => {}, controlClientCount = () => 0, warehousePath = null, budgetStatePath = null, laneMap = null, telemetry = null, sendTelegram = sendTelegramMessage, telegramTimeoutMs = TELEGRAM_TIMEOUT_MS, fsPromises = fsp, createScanner = createUsageScanner, loadPricingFn = loadPricing, execFileAsync: execFileAsync$1 = execFileAsync, rtkPathFn = defaultRtkPath, scannerDeps = {}, nowFn = Date.now, partialContinueMs = PARTIAL_CONTINUE_MS, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, logger = console, debug = false }) {
43582
+ function createUsageWiring({ config, sessions = /* @__PURE__ */ new Map(), broadcast = () => {}, controlClientCount = () => 0, warehousePath = null, budgetStatePath = null, laneMap = null, telemetry = null, sendTelegram = sendTelegramMessage, telegramTimeoutMs = TELEGRAM_TIMEOUT_MS, fsPromises = fs$1, createScanner = createUsageScanner, loadPricingFn = loadPricing, execFileAsync: execFileAsync$1 = execFileAsync, rtkPathFn = defaultRtkPath, scannerDeps = {}, nowFn = Date.now, partialContinueMs = PARTIAL_CONTINUE_MS, setIntervalFn = DEFAULT_TIMER_FNS.setIntervalFn, clearIntervalFn = DEFAULT_TIMER_FNS.clearIntervalFn, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, logger = console, debug = false }) {
43148
43583
  const laneLog = createLaneLog({
43149
43584
  prefix: "[usage]",
43150
43585
  logger,
@@ -43684,7 +44119,7 @@ function createUsageWiring({ config, sessions = /* @__PURE__ */ new Map(), broad
43684
44119
  }
43685
44120
  //#endregion
43686
44121
  //#region server/usage/usage-lane-ledger.ts
43687
- function createLaneLedger({ ledgerPath = null, fsPromises = fsp, nowFn = Date.now, retainDays = 365, logger = null } = {}) {
44122
+ function createLaneLedger({ ledgerPath = null, fsPromises = fs$1, nowFn = Date.now, retainDays = 365, logger = null } = {}) {
43688
44123
  const laneLog = createLaneLog({
43689
44124
  prefix: "[usage]",
43690
44125
  logger
@@ -44716,7 +45151,7 @@ function errorResult(reason, errorSource = ERROR_SOURCE_TRANSPORT) {
44716
45151
  async function readCommentsResult(resultPath, { lineCount = 0, onBytesRead = null } = {}) {
44717
45152
  let raw = "";
44718
45153
  try {
44719
- raw = await fsp.readFile(resultPath, "utf8");
45154
+ raw = await fs$1.readFile(resultPath, "utf8");
44720
45155
  } catch {
44721
45156
  return errorResult("no readable result file");
44722
45157
  }
@@ -44812,11 +45247,11 @@ function createVisionsSpawn({ sessions = /* @__PURE__ */ new Map(), closeSession
44812
45247
  };
44813
45248
  }
44814
45249
  function makeVisionsWorkDir() {
44815
- return fsp.mkdtemp(path.join(os.tmpdir(), "glimmervoid-visions-"));
45250
+ return fs$1.mkdtemp(path.join(os.tmpdir(), "glimmervoid-visions-"));
44816
45251
  }
44817
45252
  function createVisionsDispatcher({ spawnSession, timeoutSeconds = 180, model = null, logger = console, nowFn = Date.now, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, makeWorkDir = makeVisionsWorkDir, removeWorkDir = async (dir) => {
44818
45253
  try {
44819
- await fsp.rm(dir, {
45254
+ await fs$1.rm(dir, {
44820
45255
  recursive: true,
44821
45256
  force: true
44822
45257
  });
@@ -44886,7 +45321,7 @@ function createVisionsDispatcher({ spawnSession, timeoutSeconds = 180, model = n
44886
45321
  });
44887
45322
  const sizeDecision = decidePromptSize(generatedPrompt);
44888
45323
  if (!sizeDecision.dispatch) return errorResult(sizeDecision.gate);
44889
- await fsp.writeFile(path.join(workDir, PROMPT_FILE), generatedPrompt, "utf8");
45324
+ await fs$1.writeFile(path.join(workDir, PROMPT_FILE), generatedPrompt, "utf8");
44890
45325
  return await spawnWithTimeout({
44891
45326
  id: idFor(uri),
44892
45327
  name: `visions ${uri}`,
@@ -45293,7 +45728,7 @@ function changeFailureReason(uri, version, result) {
45293
45728
  if (result.reason === "stale-version") return `stale-version (uri=${uri} incoming=${result.version} current=${result.currentVersion})`;
45294
45729
  return `${result.reason} (uri=${uri} version=${version})`;
45295
45730
  }
45296
- function createVisionsWiring({ debounceMs = 300, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, nowFn = Date.now, sweep = sweepMarkdownWithFixes, maxPayload = MAX_FRAME_BYTES, autoFix = false, fixLogMax = 20, applyEditTimeoutMs = APPLY_EDIT_TIMEOUT_MS, logger = console, broadcast = null, dispatchConfig = null, dispatchHistory = [], dispatch = null, contextDigest = null, contextSeq = null, scopeProjects = [], pathsFoldCase = process.platform === "darwin", knownProjectIds = null, onEditorEvent = null, intentStatePath = null, intentThreadTtlMs = DEFAULT_THREAD_TTL_MS, fsFns = fs, fsPromises = fsp, digestBudgetChars = DIGEST_BUDGET_CHARS, hashFn = hashText$1, buildPrompt = buildVisionsPrompt, debug = false } = {}) {
45731
+ function createVisionsWiring({ debounceMs = 300, setTimeoutFn = DEFAULT_TIMER_FNS.setTimeoutFn, clearTimeoutFn = DEFAULT_TIMER_FNS.clearTimeoutFn, nowFn = Date.now, sweep = sweepMarkdownWithFixes, maxPayload = MAX_FRAME_BYTES, autoFix = false, fixLogMax = 20, applyEditTimeoutMs = APPLY_EDIT_TIMEOUT_MS, logger = console, broadcast = null, dispatchConfig = null, dispatchHistory = [], dispatch = null, contextDigest = null, contextSeq = null, scopeProjects = [], pathsFoldCase = process.platform === "darwin", knownProjectIds = null, onEditorEvent = null, intentStatePath = null, intentThreadTtlMs = DEFAULT_THREAD_TTL_MS, fsFns = fs, fsPromises = fs$1, digestBudgetChars = DIGEST_BUDGET_CHARS, hashFn = hashText$1, buildPrompt = buildVisionsPrompt, debug = false } = {}) {
45297
45732
  const wss = new WebSocketServer({
45298
45733
  noServer: true,
45299
45734
  maxPayload
@@ -46164,8 +46599,15 @@ function createBackendLanes(dependencies) {
46164
46599
  warn: (message) => logger.warn(message)
46165
46600
  });
46166
46601
  const spawnGate = createSpawnGate({ memoryAdmission });
46167
- const gitWorkspace = createGitWorkspace({ rerere: config.worktreeRerere !== false });
46168
- const gitWorkspaceSync = createGitWorkspaceSync();
46602
+ const ownedPaths = createOwnedPathsLedger({
46603
+ filePath: ownedPathsLedgerPath(),
46604
+ log: logger
46605
+ });
46606
+ const gitWorkspace = createGitWorkspace({
46607
+ rerere: config.worktreeRerere !== false,
46608
+ ownedPaths
46609
+ });
46610
+ const gitWorkspaceSync = createGitWorkspaceSync({ ownedPaths });
46169
46611
  const laneLedger = createLaneLedger({
46170
46612
  ledgerPath: configSiblingPath(configStore.configPath, "usage-lanes.json"),
46171
46613
  retainDays: resolveUsageConfig(config.usage).warehouseRetainDays,
@@ -46259,7 +46701,8 @@ function createBackendLanes(dependencies) {
46259
46701
  });
46260
46702
  const githubClock = createGithubClock({
46261
46703
  baseIntervalMs: 6e4,
46262
- log: logger
46704
+ log: logger,
46705
+ githubStatus: createGithubStatus({ log: logger })
46263
46706
  });
46264
46707
  const glimmervoidHome = glimmervoidHomeDir$1();
46265
46708
  const github = createPrGh(glimmervoidHome);
@@ -46653,6 +47096,7 @@ function createBackendLanes(dependencies) {
46653
47096
  currentVisions,
46654
47097
  gitWorkspace,
46655
47098
  gitWorkspaceSync,
47099
+ ownedPaths,
46656
47100
  githubStore,
46657
47101
  investigationSessions,
46658
47102
  planReview,
@@ -48851,7 +49295,7 @@ var SessionRecorder = class {
48851
49295
  if (this._retainDays <= 0 && this._retainFiles <= 0 && this._retainBytes <= 0) return;
48852
49296
  let entries;
48853
49297
  try {
48854
- entries = await fsp.readdir(this._baseDir);
49298
+ entries = await fs$1.readdir(this._baseDir);
48855
49299
  } catch {
48856
49300
  return;
48857
49301
  }
@@ -48869,7 +49313,7 @@ var SessionRecorder = class {
48869
49313
  for (const entry of recordings) {
48870
49314
  if (doomed.has(entry)) continue;
48871
49315
  try {
48872
- if ((await fsp.stat(path.join(this._baseDir, entry))).mtimeMs < cutoff) doomed.add(entry);
49316
+ if ((await fs$1.stat(path.join(this._baseDir, entry))).mtimeMs < cutoff) doomed.add(entry);
48873
49317
  } catch {}
48874
49318
  }
48875
49319
  }
@@ -48877,14 +49321,14 @@ var SessionRecorder = class {
48877
49321
  const filepath = path.join(this._baseDir, entry);
48878
49322
  if (filepath === this._filepath || openRecordingPaths.has(filepath)) continue;
48879
49323
  try {
48880
- await fsp.unlink(filepath);
49324
+ await fs$1.unlink(filepath);
48881
49325
  } catch {}
48882
49326
  }
48883
49327
  if (this._retainBytes <= 0) return;
48884
49328
  const current = this._filepath ? path.basename(this._filepath) : null;
48885
49329
  const measured = (await Promise.all(recordings.filter((entry) => !doomed.has(entry) && entry !== current).map(async (entry) => {
48886
49330
  try {
48887
- const stat = await fsp.stat(path.join(this._baseDir, entry));
49331
+ const stat = await fs$1.stat(path.join(this._baseDir, entry));
48888
49332
  return {
48889
49333
  entry,
48890
49334
  size: stat.size,
@@ -48899,7 +49343,7 @@ var SessionRecorder = class {
48899
49343
  for (const entry of evictable) {
48900
49344
  if (totalBytes <= this._retainBytes) return;
48901
49345
  try {
48902
- await fsp.unlink(path.join(this._baseDir, entry.entry));
49346
+ await fs$1.unlink(path.join(this._baseDir, entry.entry));
48903
49347
  totalBytes -= entry.size;
48904
49348
  } catch (err) {
48905
49349
  if (isMissingFileError(err, { includeNotDir: false })) totalBytes -= entry.size;
@@ -49027,6 +49471,8 @@ function createSessionFactory(dependencies) {
49027
49471
  isSettingOn: (dependencies.getConfig?.() ?? config).coherence?.enabled === true
49028
49472
  });
49029
49473
  const builtMapping = project.environment;
49474
+ const sessionTempFolder = builtMapping ? null : sessionTempFolderFor(project.id);
49475
+ if (sessionTempFolder) fs.mkdirSync(sessionTempFolder, { recursive: true });
49030
49476
  const session = new Session({
49031
49477
  id: project.id,
49032
49478
  name: project.name,
@@ -49064,6 +49510,10 @@ function createSessionFactory(dependencies) {
49064
49510
  commitSigningProgram: dependencies.commitSigningProgram ?? null,
49065
49511
  getRemoteLaunch: builtMapping ? () => remoteLaunchFor(project, builtMapping, dependencies.getConfig?.() ?? config) : null,
49066
49512
  ...overrides,
49513
+ spawnEnv: sessionTempFolder ? {
49514
+ CLAUDE_CODE_TMPDIR: sessionTempFolder,
49515
+ ...overrides.spawnEnv ?? {}
49516
+ } : overrides.spawnEnv,
49067
49517
  prepareGuardrails: "prepareGuardrails" in overrides ? overrides.prepareGuardrails : defaultGuardrailsFor(project, config, overrides)
49068
49518
  });
49069
49519
  const captureConfig = {
@@ -50923,22 +51373,37 @@ function registerControlHandlers(controlWss, deps) {
50923
51373
  console.log(`[control] Removed spawned session via UI: ${sess.name}`);
50924
51374
  return { ok: true };
50925
51375
  }
51376
+ const isDiscardingWorkspaceWork = sess.isWorkspace && msg.discardWork === true;
51377
+ if (isDiscardingWorkspaceWork) sess.killSession();
51378
+ const keptPaths = sess.isWorkspace ? await sess.findWorkspaceKeptWork() : [];
51379
+ const confirmedKeptPaths = new Set(isDiscardingWorkspaceWork ? msg.confirmedKeptPaths ?? [] : []);
51380
+ if (keptPaths.some((kept) => !confirmedKeptPaths.has(kept.path))) return {
51381
+ ok: false,
51382
+ error: "Workspace members hold work that is not saved",
51383
+ canDiscardWork: true,
51384
+ keptPaths
51385
+ };
50926
51386
  if (config.projects.some((project) => project.id === sess.id && project.environment) && coderEnv) {
50927
51387
  sess.killSession();
50928
51388
  const settlement = await coderEnv.settleRemoval({
50929
51389
  projectId: sess.id,
50930
- discardRemoteWork: msg.discardRemoteWork === true
51390
+ discardRemoteWork: msg.discardWork === true
50931
51391
  });
50932
51392
  if (!settlement.ok) return {
50933
51393
  ok: false,
50934
51394
  error: settlement.reason,
50935
- canDiscardRemoteWork: settlement.canDiscardRemoteWork
51395
+ canDiscardWork: settlement.canDiscardRemoteWork
50936
51396
  };
50937
51397
  }
50938
51398
  const freshConfig = configStore.save((cfg) => {
50939
51399
  cfg.projects = cfg.projects.filter((p) => p.id !== sess.id);
50940
51400
  });
50941
- if (freshConfig) applyConfigReload(freshConfig);
51401
+ if (!freshConfig) return {
51402
+ ok: false,
51403
+ error: `Could not save the removal of session "${sess.name}"`
51404
+ };
51405
+ if (isDiscardingWorkspaceWork) sess.confirmWorkspaceWorkDiscard();
51406
+ applyConfigReload(freshConfig);
50942
51407
  console.log(`[control] Removed session via UI: ${sess.name}`);
50943
51408
  return { ok: true };
50944
51409
  }
@@ -53799,7 +54264,7 @@ async function downloadCapped(url, { fetchImpl, timeoutMs = DOWNLOAD_TIMEOUT_MS
53799
54264
  }
53800
54265
  }
53801
54266
  async function findBinary(dir, platform) {
53802
- const entries = await fsp.readdir(dir, { withFileTypes: true });
54267
+ const entries = await fs$1.readdir(dir, { withFileTypes: true });
53803
54268
  const nested = [];
53804
54269
  for (const entry of entries) {
53805
54270
  const full = path.join(dir, entry.name);
@@ -53817,13 +54282,13 @@ async function findBinary(dir, platform) {
53817
54282
  }
53818
54283
  async function removeQuietly(target) {
53819
54284
  try {
53820
- await fsp.rm(target, {
54285
+ await fs$1.rm(target, {
53821
54286
  recursive: true,
53822
54287
  force: true
53823
54288
  });
53824
54289
  } catch {}
53825
54290
  }
53826
- async function moveIntoPlace(source, target, renameImpl = fsp.rename) {
54291
+ async function moveIntoPlace(source, target, renameImpl = fs$1.rename) {
53827
54292
  try {
53828
54293
  await renameImpl(source, target);
53829
54294
  return;
@@ -53832,15 +54297,15 @@ async function moveIntoPlace(source, target, renameImpl = fsp.rename) {
53832
54297
  }
53833
54298
  const partial = `${target}.partial`;
53834
54299
  try {
53835
- await fsp.copyFile(source, partial);
54300
+ await fs$1.copyFile(source, partial);
53836
54301
  await renameImpl(partial, target);
53837
54302
  } catch (err) {
53838
54303
  await removeQuietly(partial);
53839
54304
  throw err;
53840
54305
  }
53841
- await fsp.unlink(source);
54306
+ await fs$1.unlink(source);
53842
54307
  }
53843
- async function installRtk({ homeDir = os.homedir(), glimmervoidHome = glimmervoidHomeDir(homeDir, process.env), platform = process.platform, arch = process.arch, fetchImpl = globalThis.fetch, execFileImpl = execFileAsync, renameImpl = fsp.rename, timeoutMs = DOWNLOAD_TIMEOUT_MS, log = console, asset = assetForPlatform(platform, arch) } = {}) {
54308
+ async function installRtk({ homeDir = os.homedir(), glimmervoidHome = glimmervoidHomeDir(homeDir, process.env), platform = process.platform, arch = process.arch, fetchImpl = globalThis.fetch, execFileImpl = execFileAsync, renameImpl = fs$1.rename, timeoutMs = DOWNLOAD_TIMEOUT_MS, log = console, asset = assetForPlatform(platform, arch) } = {}) {
53844
54309
  if (!asset) return {
53845
54310
  ok: false,
53846
54311
  reason: `unsupported platform ${platform}-${arch}`
@@ -53851,7 +54316,7 @@ async function installRtk({ homeDir = os.homedir(), glimmervoidHome = glimmervoi
53851
54316
  };
53852
54317
  const stagingDir = path.join(glimmervoidHome, "tmp", `rtk-${crypto.randomBytes(6).toString("hex")}`);
53853
54318
  try {
53854
- await fsp.mkdir(stagingDir, { recursive: true });
54319
+ await fs$1.mkdir(stagingDir, { recursive: true });
53855
54320
  } catch (err) {
53856
54321
  return {
53857
54322
  ok: false,
@@ -53874,9 +54339,9 @@ async function installRtk({ homeDir = os.homedir(), glimmervoidHome = glimmervoi
53874
54339
  reason: `sha256 mismatch for ${asset.file}: expected ${asset.sha256}, got ${actualHex}`
53875
54340
  };
53876
54341
  const archivePath = path.join(stagingDir, asset.file);
53877
- await fsp.writeFile(archivePath, downloaded.bytes);
54342
+ await fs$1.writeFile(archivePath, downloaded.bytes);
53878
54343
  const extractDir = path.join(stagingDir, "extract");
53879
- await fsp.mkdir(extractDir, { recursive: true });
54344
+ await fs$1.mkdir(extractDir, { recursive: true });
53880
54345
  try {
53881
54346
  const listing = await execFileImpl("tar", ["-tf", archivePath]);
53882
54347
  const escaping = findEscapingArchiveMember(listing.stdout);
@@ -53901,13 +54366,13 @@ async function installRtk({ homeDir = os.homedir(), glimmervoidHome = glimmervoi
53901
54366
  ok: false,
53902
54367
  reason: `extract failed: no rtk binary inside ${asset.file}`
53903
54368
  };
53904
- if (!(await fsp.lstat(extracted)).isFile()) return {
54369
+ if (!(await fs$1.lstat(extracted)).isFile()) return {
53905
54370
  ok: false,
53906
54371
  reason: `extract failed: rtk inside ${asset.file} is not a regular file`
53907
54372
  };
53908
- if (platform !== "win32") await fsp.chmod(extracted, 493);
54373
+ if (platform !== "win32") await fs$1.chmod(extracted, 493);
53909
54374
  const target = installTargetPath(glimmervoidHome, platform);
53910
- await fsp.mkdir(path.dirname(target), { recursive: true });
54375
+ await fs$1.mkdir(path.dirname(target), { recursive: true });
53911
54376
  await removeQuietly(target);
53912
54377
  await moveIntoPlace(extracted, target, renameImpl);
53913
54378
  log?.log?.(`[rtk] installed rtk ${asset.version} at ${target}`);
@@ -53998,13 +54463,13 @@ function sleepFor(durationMs) {
53998
54463
  function createClaudeFolderTrust({ env = process.env, homeDir = os.homedir(), now = Date.now, platform = process.platform, sleep = sleepFor } = {}) {
53999
54464
  async function resolveConfiguredPath() {
54000
54465
  const [legacyConfigPath, currentConfigPath] = listClaudeGlobalConfigPathCandidates(env, homeDir);
54001
- return await fsp.access(legacyConfigPath).then(() => true, () => false) ? legacyConfigPath : currentConfigPath;
54466
+ return await fs$1.access(legacyConfigPath).then(() => true, () => false) ? legacyConfigPath : currentConfigPath;
54002
54467
  }
54003
54468
  function refusal(repositoryRoot, configPath, reason) {
54004
54469
  return /* @__PURE__ */ new Error(`Could not trust ${repositoryRoot} for Claude Code: ${configPath} was left unchanged because ${reason}`);
54005
54470
  }
54006
54471
  async function readTrustDecision(repositoryRoot, configPath) {
54007
- const decision = decideFolderTrust(await fsp.readFile(configPath, "utf8").catch((error) => {
54472
+ const decision = decideFolderTrust(await fs$1.readFile(configPath, "utf8").catch((error) => {
54008
54473
  throw refusal(repositoryRoot, configPath, `it could not be read (${errorCode(error) ?? "unknown error"})`);
54009
54474
  }), repositoryRoot, platform);
54010
54475
  if (decision.kind === "unreadable") throw refusal(repositoryRoot, configPath, decision.reason);
@@ -54012,13 +54477,13 @@ function createClaudeFolderTrust({ env = process.env, homeDir = os.homedir(), no
54012
54477
  }
54013
54478
  async function tryTakeConfigLock(lockPath) {
54014
54479
  try {
54015
- await fsp.mkdir(lockPath);
54480
+ await fs$1.mkdir(lockPath);
54016
54481
  return true;
54017
54482
  } catch (error) {
54018
54483
  if (errorCode(error) !== "EEXIST") throw error;
54019
54484
  }
54020
- const heldLock = await fsp.stat(lockPath).catch(() => null);
54021
- if (heldLock && isConfigLockStale(heldLock.mtimeMs, now())) await fsp.rmdir(lockPath).catch(() => {});
54485
+ const heldLock = await fs$1.stat(lockPath).catch(() => null);
54486
+ if (heldLock && isConfigLockStale(heldLock.mtimeMs, now())) await fs$1.rmdir(lockPath).catch(() => {});
54022
54487
  return false;
54023
54488
  }
54024
54489
  async function takeConfigLock(repositoryRoot, configuredPath) {
@@ -54031,17 +54496,17 @@ function createClaudeFolderTrust({ env = process.env, homeDir = os.homedir(), no
54031
54496
  }
54032
54497
  async function ensureTrusted(repositoryRoot) {
54033
54498
  const configuredPath = await resolveConfiguredPath();
54034
- const configPath = await fsp.realpath(configuredPath).catch(() => configuredPath);
54499
+ const configPath = await fs$1.realpath(configuredPath).catch(() => configuredPath);
54035
54500
  if ((await readTrustDecision(repositoryRoot, configPath)).kind === "trusted") return "already-trusted";
54036
54501
  const lockPath = await takeConfigLock(repositoryRoot, configuredPath);
54037
54502
  try {
54038
54503
  const decision = await readTrustDecision(repositoryRoot, configPath);
54039
54504
  if (decision.kind === "trusted") return "already-trusted";
54040
- const { mode } = await fsp.stat(configPath);
54505
+ const { mode } = await fs$1.stat(configPath);
54041
54506
  await writeTextAtomic(configPath, decision.nextConfigText, { mode: mode & 511 });
54042
54507
  return "granted";
54043
54508
  } finally {
54044
- await fsp.rmdir(lockPath).catch(() => {});
54509
+ await fs$1.rmdir(lockPath).catch(() => {});
54045
54510
  }
54046
54511
  }
54047
54512
  return { ensureTrusted };
@@ -54283,11 +54748,11 @@ function spawnConnectPty(file, args, options) {
54283
54748
  return pty.spawn(file, args, options);
54284
54749
  }
54285
54750
  async function makePrivateDir(directory) {
54286
- await fsp.mkdir(directory, {
54751
+ await fs$1.mkdir(directory, {
54287
54752
  recursive: true,
54288
54753
  mode: 448
54289
54754
  });
54290
- await fsp.chmod(directory, 448);
54755
+ await fs$1.chmod(directory, 448);
54291
54756
  }
54292
54757
  function createAgentConnect({ loginsRoot, loginSource, launchFor, onChange, ptySpawn = spawnConnectPty, makeHomeDir = makePrivateDir, setTimeoutFn = setTimeout, clearTimeoutFn = clearTimeout }) {
54293
54758
  const statusByAgent = new Map(CONNECTABLE_AGENTS.map((agent) => [agent, idleLoginStatus(agent, null)]));
@@ -54492,7 +54957,7 @@ function chatgptAuthTokensRefreshResult(login) {
54492
54957
  //#region server/codex-credentials.ts
54493
54958
  var HOST_REFRESH_TIMEOUT_MS = 6e4;
54494
54959
  async function readTextFileOrNull(filePath) {
54495
- return fsp.readFile(filePath, "utf8").catch(() => null);
54960
+ return fs$1.readFile(filePath, "utf8").catch(() => null);
54496
54961
  }
54497
54962
  function codexHomeDir(env, homeDir) {
54498
54963
  const override = env.CODEX_HOME?.trim();
@@ -55101,7 +55566,8 @@ function createUpdateApplyLane(dependencies) {
55101
55566
  await runWorkspaceStep("stage", () => dependencies.gitWorkspace.stageDetachedWorktree({
55102
55567
  projectPath: dependencies.packageRoot,
55103
55568
  worktreePath: stagingPath,
55104
- sha: status.latestSha || void 0
55569
+ sha: status.latestSha || void 0,
55570
+ owner: "lane:update-apply"
55105
55571
  }));
55106
55572
  const lockfileDiff = await gitCommand([
55107
55573
  "diff",
@@ -55472,19 +55938,19 @@ async function collectWorktreePaths(projects) {
55472
55938
  }
55473
55939
  async function readFileNames(folder) {
55474
55940
  try {
55475
- return (await fsp.readdir(folder, { withFileTypes: true })).filter((entry) => entry.isFile()).map((entry) => entry.name);
55941
+ return (await fs$1.readdir(folder, { withFileTypes: true })).filter((entry) => entry.isFile()).map((entry) => entry.name);
55476
55942
  } catch (error) {
55477
55943
  if (isMissingFileError(error)) return null;
55478
55944
  throw error;
55479
55945
  }
55480
55946
  }
55481
55947
  async function removeFolderIfEmpty(folder) {
55482
- if ((await fsp.readdir(folder)).length > 0) return;
55483
- await fsp.rmdir(folder);
55948
+ if ((await fs$1.readdir(folder)).length > 0) return;
55949
+ await fs$1.rmdir(folder);
55484
55950
  }
55485
55951
  async function isRealDirectory(folder) {
55486
55952
  try {
55487
- return (await fsp.lstat(folder)).isDirectory();
55953
+ return (await fs$1.lstat(folder)).isDirectory();
55488
55954
  } catch (error) {
55489
55955
  if (isMissingFileError(error)) return false;
55490
55956
  throw error;
@@ -55492,10 +55958,10 @@ async function isRealDirectory(folder) {
55492
55958
  }
55493
55959
  async function isReportFolderOwnedByWorktree(worktreePath, reportFolder) {
55494
55960
  if (!await isRealDirectory(path.dirname(reportFolder)) || !await isRealDirectory(reportFolder)) return false;
55495
- const realWorktreePath = await fsp.realpath(worktreePath);
55496
- if (!isPathInside(realWorktreePath, await fsp.realpath(reportFolder), { allowEqual: false })) return false;
55961
+ const realWorktreePath = await fs$1.realpath(worktreePath);
55962
+ if (!isPathInside(realWorktreePath, await fs$1.realpath(reportFolder), { allowEqual: false })) return false;
55497
55963
  const reportFolderTopLevel = (await gitOutput(["rev-parse", "--show-toplevel"], reportFolder)).trim();
55498
- return equalsIgnoringCaseOnWindows(await fsp.realpath(reportFolderTopLevel), realWorktreePath);
55964
+ return equalsIgnoringCaseOnWindows(await fs$1.realpath(reportFolderTopLevel), realWorktreePath);
55499
55965
  }
55500
55966
  async function listTrackedReportGitPaths(worktreePath) {
55501
55967
  return (await gitOutput([
@@ -55512,7 +55978,7 @@ async function cleanWorktree(worktreePath) {
55512
55978
  if (fileNames === null) return NOTHING_CLEANED;
55513
55979
  const trackedReportGitPaths = await listTrackedReportGitPaths(worktreePath);
55514
55980
  const deletableFileNames = untrackedReportFileNames(fileNames, trackedReportGitPaths);
55515
- for (const fileName of deletableFileNames) await fsp.rm(path.join(reportFolder, fileName), { force: true });
55981
+ for (const fileName of deletableFileNames) await fs$1.rm(path.join(reportFolder, fileName), { force: true });
55516
55982
  await removeFolderIfEmpty(reportFolder);
55517
55983
  await removeFolderIfEmpty(path.dirname(reportFolder));
55518
55984
  return {
@@ -56566,6 +57032,12 @@ function createBackend(httpServer, options = {}) {
56566
57032
  const reconcileProjectsOnReload = sessionRegistry.applyConfigReload;
56567
57033
  rtkInstall.maybeInstall();
56568
57034
  sweepOrphanedGuardrailsLaunches();
57035
+ reconcileOwnedPaths({
57036
+ ledger: laneAssembly.ownedPaths,
57037
+ configuredSessionIds: new Set(config.projects.map((project) => project.id)),
57038
+ git: laneAssembly.gitWorkspace,
57039
+ shareList: config.worktreeShare || DEFAULT_CONFIG.worktreeShare
57040
+ });
56569
57041
  laneAssembly.startRuntimeLanes();
56570
57042
  function applyCustomAgents(sourceConfig) {
56571
57043
  setCustomAgents(sourceConfig.customAgents ?? []);