glimmervoid 0.43.0 → 0.43.2

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.
@@ -65,7 +65,7 @@ var OWN_SUBCOMMAND_RUNNERS = [
65
65
  return 0;
66
66
  }],
67
67
  ["pair", async (subcommandArgs) => {
68
- const { runPairCli } = await import("../chunks/pair-cli-DAJNPgsi.js");
68
+ const { runPairCli } = await import("../chunks/pair-cli-CPv7mDTg.js");
69
69
  return runPairCli(subcommandArgs);
70
70
  }],
71
71
  ["agent", async (subcommandArgs) => {
@@ -73,7 +73,7 @@ var OWN_SUBCOMMAND_RUNNERS = [
73
73
  return runAgentSetupCli(subcommandArgs);
74
74
  }],
75
75
  ["settings", async (subcommandArgs) => {
76
- const { runSettingsCli } = await import("../chunks/settings-cli-CMLEvC05.js");
76
+ const { runSettingsCli } = await import("../chunks/settings-cli-4fX1olS3.js");
77
77
  return runSettingsCli(subcommandArgs);
78
78
  }],
79
79
  ["visions", async (subcommandArgs) => {
@@ -158,7 +158,7 @@ async function readDeclaredCustomAgents() {
158
158
  declared: [],
159
159
  error: null
160
160
  };
161
- const { loadConfigFile } = await import("../chunks/config-store-DCrosJLg.js");
161
+ const { loadConfigFile } = await import("../chunks/config-store-DW0ONWV5.js");
162
162
  try {
163
163
  const loaded = loadConfigFile(decided.path, { exitOnError: false });
164
164
  if (!loaded.config) return {
@@ -234,7 +234,7 @@ async function runDoctor() {
234
234
  }
235
235
  switchSection("Agents");
236
236
  try {
237
- const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-EqOJN5vD.js");
237
+ const { listAgentIds, describeAgentResolvability, setCustomAgents } = await import("../chunks/adapters-Ce0I__TH.js");
238
238
  const declaredCustomAgents = await readDeclaredCustomAgents();
239
239
  if (declaredCustomAgents.error) line("config", declaredCustomAgents.error);
240
240
  setCustomAgents(declaredCustomAgents.declared);
@@ -1 +1 @@
1
- export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-jRUJYLhH.js";
1
+ export { a as describeAgentResolvability, l as listAgentIds, f as setCustomAgents } from "./adapters-CjtgWEdg.js";
@@ -8,7 +8,7 @@ import { c as textOr, s as rawTextOr } from "./coerce-NSst8oRP.js";
8
8
  import { r as nextBackoffMs } from "./backoff-DjVpfHk7.js";
9
9
  import { i as isSpinnerChar, n as classifyAgentTitle, r as isBrailleChar, s as buildAgentEnv, t as grok } from "./grok-DPmX1ozS.js";
10
10
  import { t as buildHookCommand } from "./hook-command-core-qTNK-xMF.js";
11
- import "./contracts-BJGgl8et.js";
11
+ import "./contracts-CFm0dprb.js";
12
12
  import { n as mergeCodexPreToolUse, t as HOOK_TOOLS } from "./hook-tools-Dl7-r2Eb.js";
13
13
  import fs from "node:fs";
14
14
  import path from "node:path";
@@ -4,7 +4,7 @@ import { $ as TASK_TITLE_TIMEOUT_RANGE, F as KEEP_MERGEABLE_TIMEOUT_MINUTES_RANG
4
4
  import { n as glimmervoidHomeDir$1, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
5
5
  import { n as isRecord } from "./coerce-NSst8oRP.js";
6
6
  import { d as writeJsonAtomicSync, f as writeTextAtomic, p as writeTextAtomicSync } from "./json-file-DFCTvPjj.js";
7
- import { C as UPDATE_CHANNELS, E as normalizeLegacyConfigNumbers, S as POST_TURN_CHECK_MODES, b as configIssueMessage, f as AGENT_ID_SHAPE_MESSAGE, h as Config, p as BUILTIN_AGENT_IDS, s as FeatureFlagsResponse, u as TELEMETRY_KILL_SWITCH_FLAG, v as RUNTIME_CONFIG_SCALAR_KEYS, w as USAGE_COST_MODES, x as BranchGcFileSettings } from "./contracts-BJGgl8et.js";
7
+ import { C as UPDATE_CHANNELS, E as normalizeLegacyConfigNumbers, S as POST_TURN_CHECK_MODES, b as configIssueMessage, f as AGENT_ID_SHAPE_MESSAGE, h as Config, p as BUILTIN_AGENT_IDS, s as FeatureFlagsResponse, u as TELEMETRY_KILL_SWITCH_FLAG, v as RUNTIME_CONFIG_SCALAR_KEYS, w as USAGE_COST_MODES, x as BranchGcFileSettings } from "./contracts-CFm0dprb.js";
8
8
  import fs from "node:fs";
9
9
  import path from "node:path";
10
10
  import os from "node:os";
@@ -0,0 +1 @@
1
+ export { s as loadConfigFile } from "./config-store-2noiIsTg.js";
@@ -616,11 +616,15 @@ var OperatorActionProperties = z.object({
616
616
  }).strict().refine(isActionOfSurface, { message: "action does not belong to its surface" });
617
617
  var TeamReviewDraftedProperties = z.object({ inline_comment_count: nonNegativeInteger }).strict();
618
618
  var TeamReviewSettledProperties = z.object({
619
+ duration_ms: nonNegativeInteger,
619
620
  outcome: z.enum(TEAM_REVIEW_SETTLED_OUTCOMES),
620
621
  drafted_comment_count: nonNegativeInteger,
621
622
  posted_comment_count: nonNegativeInteger
622
623
  }).strict();
623
- var TeamReviewPostRefusedProperties = z.object({ reason: z.enum(TEAM_REVIEW_POST_REFUSAL_REASONS) }).strict();
624
+ var TeamReviewPostRefusedProperties = z.object({
625
+ duration_ms: nonNegativeInteger,
626
+ reason: z.enum(TEAM_REVIEW_POST_REFUSAL_REASONS)
627
+ }).strict();
624
628
  var RadarInvestigationFinishedProperties = z.object({
625
629
  verdict: z.enum(RADAR_VERDICTS),
626
630
  mode: z.enum(RADAR_JOB_MODES),
@@ -723,11 +727,11 @@ Object.freeze([
723
727
  },
724
728
  {
725
729
  name: "team_review_settled",
726
- description: "A team review draft was posted (approve, comment or approve-only) or discarded, with how many inline comments were drafted and how many were posted."
730
+ description: "A team review draft was posted (approve, comment or approve-only) or discarded, with how many inline comments were drafted and how many were posted, plus the total action duration in milliseconds."
727
731
  },
728
732
  {
729
733
  name: "team_review_post_refused",
730
- description: "Posting a team review was refused, with a reason from a fixed list. Never the error text."
734
+ description: "Posting a team review was refused, with a reason from a fixed list and the total action duration in milliseconds. Never the error text."
731
735
  },
732
736
  {
733
737
  name: "radar_investigation_finished",
@@ -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-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";
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-2noiIsTg.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-CFm0dprb.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-CjtgWEdg.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-BdCTswa1.js";
30
- import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-CBqSjZiW.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-DZWZ5fVJ.js";
30
+ import { n as configFileViewOf, u as readSettingsForAgent } from "./settings-readout-core-NoTHBGL6.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";
@@ -11584,25 +11584,38 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
11584
11584
  return Math.max(rateLimitedUntil - now(), rateLimitWaitMs ?? 0);
11585
11585
  }
11586
11586
  async function readWhenAllowed(read, canSkipWait = () => false, mode = "wait", resources = RATE_LIMIT_RESOURCES) {
11587
+ let queueWaitMs = 0;
11588
+ let readMs = 0;
11587
11589
  while (true) {
11590
+ const enqueuedAt = now();
11588
11591
  const attempt = await exclusive(async () => {
11592
+ queueWaitMs += now() - enqueuedAt;
11589
11593
  const waitMs = canSkipWait() ? 0 : await readWaitMs(resources);
11590
11594
  if (waitMs > 0) return {
11591
11595
  isReady: false,
11592
11596
  waitMs
11593
11597
  };
11594
- return {
11595
- isReady: true,
11596
- value: await read()
11597
- };
11598
- });
11598
+ const readStartedAt = now();
11599
+ try {
11600
+ return {
11601
+ isReady: true,
11602
+ value: await read()
11603
+ };
11604
+ } finally {
11605
+ readMs += now() - readStartedAt;
11606
+ }
11607
+ }, { isPriority: mode === "priority" });
11599
11608
  if (attempt.isReady) return {
11600
11609
  isRateLimited: false,
11601
- value: attempt.value
11610
+ value: attempt.value,
11611
+ queueWaitMs,
11612
+ readMs
11602
11613
  };
11603
- if (mode === "no-wait") return {
11614
+ if (mode !== "wait") return {
11604
11615
  isRateLimited: true,
11605
- waitMs: attempt.waitMs
11616
+ waitMs: attempt.waitMs,
11617
+ queueWaitMs,
11618
+ readMs
11606
11619
  };
11607
11620
  await new Promise((resolve) => setTimeoutFn(resolve, attempt.waitMs));
11608
11621
  }
@@ -11638,7 +11651,14 @@ function createGithubStorePoller({ github, now, isDashboardConnected, exclusive,
11638
11651
  }
11639
11652
  async function requestRead(read, fallback, hasCachedValue = () => false, mode = "wait", resources = RATE_LIMIT_RESOURCES) {
11640
11653
  try {
11641
- return await readWhenAllowed(read, hasCachedValue, mode, resources);
11654
+ return await readWhenAllowed(async () => {
11655
+ try {
11656
+ return await read();
11657
+ } catch (error) {
11658
+ recordReadFailure(error);
11659
+ return fallback;
11660
+ }
11661
+ }, hasCachedValue, mode, resources);
11642
11662
  } catch (error) {
11643
11663
  recordReadFailure(error);
11644
11664
  return {
@@ -28496,43 +28516,68 @@ var DRAFTED_REVIEW_STATUSES = /* @__PURE__ */ new Set([
28496
28516
  function isDraftedReview(draft) {
28497
28517
  return draft !== null && DRAFTED_REVIEW_STATUSES.has(draft.status) && !isThreadPlaceholderDraft(draft);
28498
28518
  }
28499
- function createTeamReviewActions({ drafts, github, store, log = console, telemetry = null, requestPrRefresh }) {
28519
+ function createTeamReviewActions({ drafts, github, store, log = console, telemetry = null, requestPrRefresh, now = Date.now }) {
28500
28520
  const actionsInFlight = /* @__PURE__ */ new Set();
28501
- function refusePost({ reason, error }) {
28502
- telemetry?.capture("team_review_post_refused", { reason });
28521
+ async function timeStep(timing, name, work) {
28522
+ const startedAt = now();
28523
+ try {
28524
+ return await work();
28525
+ } finally {
28526
+ timing.steps.push(`${name} wait 0 run ${Math.max(0, Math.round(now() - startedAt))}`);
28527
+ }
28528
+ }
28529
+ async function readStep(timing, name, work) {
28530
+ const startedAt = now();
28531
+ let read;
28532
+ try {
28533
+ read = await work();
28534
+ return read;
28535
+ } finally {
28536
+ const queueWaitMs = Math.max(0, Math.round(read?.queueWaitMs ?? 0));
28537
+ const runMs = Math.max(0, Math.round(read?.readMs ?? now() - startedAt - queueWaitMs));
28538
+ timing.steps.push(`${name} wait ${queueWaitMs} run ${runMs}`);
28539
+ }
28540
+ }
28541
+ function refusePost(timing, { reason, error }) {
28542
+ timing.refusalReason = reason;
28503
28543
  return {
28504
28544
  ok: false,
28505
28545
  error
28506
28546
  };
28507
28547
  }
28508
- function captureSettled(outcome, draft, postedCommentCount) {
28548
+ function captureSettled(outcome, draft, postedCommentCount, durationMs) {
28509
28549
  telemetry?.capture("team_review_settled", {
28510
28550
  outcome,
28551
+ duration_ms: durationMs,
28511
28552
  drafted_comment_count: draft?.comments.length ?? 0,
28512
28553
  posted_comment_count: postedCommentCount
28513
28554
  });
28514
28555
  }
28515
- async function markDraft(key, draft, patch) {
28516
- const updated = await drafts.updateDraft(key, {
28556
+ async function markDraft(timing, key, draft, patch) {
28557
+ const updated = await timeStep(timing, "mark", () => drafts.updateDraft(key, {
28517
28558
  reviewedHead: draft.reviewedHead,
28518
28559
  status: draft.status
28519
- }, patch);
28560
+ }, patch));
28520
28561
  if (!updated) log.warn(`[${TEAM_REVIEW_LANE_ID}] could not mark ${key} ${patch.status ?? "updated"}, the draft changed underneath the action`);
28521
28562
  return updated;
28522
28563
  }
28523
- async function markNotMine(request) {
28564
+ async function markNotMine(timing, request) {
28524
28565
  const draft = drafts.getDraft(request.key);
28525
28566
  if (request.head !== void 0 && draft?.reviewedHead !== request.head) return {
28526
28567
  ok: false,
28527
28568
  error: REPLACED_DRAFT_ERROR
28528
28569
  };
28529
28570
  const outcome = await drafts.markNotMine(request.key);
28530
- if (outcome.ok && isDraftedReview(draft)) captureSettled("discarded", draft, 0);
28571
+ if (outcome.ok && isDraftedReview(draft)) timing.settled = {
28572
+ outcome: "discarded",
28573
+ draft,
28574
+ postedCommentCount: 0
28575
+ };
28531
28576
  return outcome;
28532
28577
  }
28533
- async function misplacedCommentsRefusal(draft, comments) {
28578
+ async function misplacedCommentsRefusal(timing, draft, comments) {
28534
28579
  if (comments.length === 0) return null;
28535
- const diffRead = await store.requestPrDiff(draft.repo, draft.number, draft.reviewedHead, "no-wait");
28580
+ const diffRead = await readStep(timing, "diff", () => store.requestPrDiff(draft.repo, draft.number, draft.reviewedHead, "priority"));
28536
28581
  if (diffRead.isRateLimited) return {
28537
28582
  reason: "rate-limited",
28538
28583
  error: githubStoreRateLimitedError(diffRead.waitMs)
@@ -28548,19 +28593,19 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28548
28593
  error: describeInvalidComments(misplaced)
28549
28594
  } : null;
28550
28595
  }
28551
- async function retractApproval(key, draft, movedHead, reviewId) {
28552
- if (draft.status !== "posted") await markDraft(key, draft, { status: "stale" });
28596
+ async function retractApproval(timing, key, draft, movedHead, reviewId) {
28597
+ if (draft.status !== "posted") await markDraft(timing, key, draft, { status: "stale" });
28553
28598
  const moved = `The pull request moved to ${shortSha(movedHead)} while the approval was posting`;
28554
28599
  if (reviewId === null) return {
28555
28600
  ok: false,
28556
28601
  error: `${moved}, and GitHub did not return the review id, so the approval still stands. Dismiss it on GitHub`
28557
28602
  };
28558
- const dismissal = await github.dismissReview({
28603
+ const dismissal = await timeStep(timing, "dismiss", () => github.dismissReview({
28559
28604
  repo: draft.repo,
28560
28605
  number: draft.number,
28561
28606
  reviewId,
28562
28607
  message: STALE_APPROVAL_DISMISSAL
28563
- });
28608
+ }));
28564
28609
  if (!dismissal.ok) return {
28565
28610
  ok: false,
28566
28611
  error: `${moved}, and dismissing the approval failed (${firstLine$1(dismissal.err)}), so it still stands. Dismiss it on GitHub`
@@ -28571,73 +28616,77 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28571
28616
  error: `${moved}, so the approval was dismissed. ${draft.status === "posted" ? "Queue a review to look at the new commits" : "It will be reviewed again"}`
28572
28617
  };
28573
28618
  }
28574
- async function post(key, draft, request) {
28619
+ async function post(timing, key, draft, request) {
28575
28620
  const event = eventForAction(request.action);
28576
- if (!event) return refusePost({
28621
+ if (!event) return refusePost(timing, {
28577
28622
  reason: "unknown-action",
28578
28623
  error: "Unknown review action"
28579
28624
  });
28580
- if (!isPostableStatus(draft, event)) return refusePost({
28625
+ if (!isPostableStatus(draft, event)) return refusePost(timing, {
28581
28626
  reason: "not-postable",
28582
28627
  error: `The draft is ${draft.status}, so it cannot be posted`
28583
28628
  });
28584
28629
  const isFollowUpApproval = draft.status === "posted";
28585
28630
  const body = request.action === "approve-only" ? "" : request.body;
28586
28631
  const comments = request.action === "approve-only" ? [] : request.comments;
28587
- if (isFollowUpApproval && comments.length > 0) return refusePost({
28632
+ if (isFollowUpApproval && comments.length > 0) return refusePost(timing, {
28588
28633
  reason: "comments-already-posted",
28589
28634
  error: "The inline comments were already posted, so the approval cannot carry them again"
28590
28635
  });
28591
- if (event === "COMMENT" && !body.trim() && comments.length === 0) return refusePost({
28636
+ if (event === "COMMENT" && !body.trim() && comments.length === 0) return refusePost(timing, {
28592
28637
  reason: "empty-comment",
28593
28638
  error: "A comment review needs a body or an inline comment"
28594
28639
  });
28595
- const liveHeadRead = await store.requestPrHead(draft.repo, draft.number, "no-wait");
28596
- if (liveHeadRead.isRateLimited) return refusePost({
28640
+ const liveHeadRead = await readStep(timing, "head-before-post", () => store.requestPrHead(draft.repo, draft.number, "priority"));
28641
+ if (liveHeadRead.isRateLimited) return refusePost(timing, {
28597
28642
  reason: "rate-limited",
28598
28643
  error: githubStoreRateLimitedError(liveHeadRead.waitMs)
28599
28644
  });
28600
28645
  const liveHead = liveHeadRead.value;
28601
- if (!liveHead) return refusePost({
28646
+ if (!liveHead) return refusePost(timing, {
28602
28647
  reason: "head-unreadable",
28603
28648
  error: "Could not read the pull request head from GitHub"
28604
28649
  });
28605
28650
  if (!canPost(draft, draft.reviewedHead, liveHead, event)) {
28606
- if (isFollowUpApproval) return refusePost({
28651
+ if (isFollowUpApproval) return refusePost(timing, {
28607
28652
  reason: "head-moved",
28608
28653
  error: `The pull request moved to ${shortSha(liveHead)} after the comments were posted, so nothing was approved. Queue a review to look at the new commits`
28609
28654
  });
28610
- await markDraft(key, draft, { status: "stale" });
28611
- return refusePost({
28655
+ await markDraft(timing, key, draft, { status: "stale" });
28656
+ return refusePost(timing, {
28612
28657
  reason: "head-moved",
28613
28658
  error: `The pull request moved to ${shortSha(liveHead)} after this review, so nothing was posted. It will be reviewed again`
28614
28659
  });
28615
28660
  }
28616
- const commentsRefusal = await misplacedCommentsRefusal(draft, comments);
28617
- if (commentsRefusal) return refusePost(commentsRefusal);
28661
+ const commentsRefusal = await misplacedCommentsRefusal(timing, draft, comments);
28662
+ if (commentsRefusal) return refusePost(timing, commentsRefusal);
28618
28663
  const postedBody = postedReviewBody(event, body);
28619
- const posted = await github.postReview({
28664
+ const posted = await timeStep(timing, "post", () => github.postReview({
28620
28665
  repo: draft.repo,
28621
28666
  number: draft.number,
28622
28667
  commitId: draft.reviewedHead,
28623
28668
  event,
28624
28669
  body: postedBody,
28625
28670
  comments
28626
- });
28627
- if (!posted.ok) return refusePost({
28671
+ }));
28672
+ if (!posted.ok) return refusePost(timing, {
28628
28673
  reason: "github-refused",
28629
28674
  error: posted.err || "GitHub refused the review"
28630
28675
  });
28631
28676
  requestPrRefresh?.(comparablePrKey(draft));
28632
28677
  const settledOutcome = SETTLED_OUTCOME_BY_ACTION[request.action];
28633
- if (!isFollowUpApproval && settledOutcome) captureSettled(settledOutcome, draft, comments.length);
28634
- const headAfterPostRead = event === "APPROVE" ? await store.requestPrHead(draft.repo, draft.number, "no-wait") : {
28678
+ if (!isFollowUpApproval && settledOutcome) timing.settled = {
28679
+ outcome: settledOutcome,
28680
+ draft,
28681
+ postedCommentCount: comments.length
28682
+ };
28683
+ const headAfterPostRead = event === "APPROVE" ? await readStep(timing, "head-after-post", () => store.requestPrHead(draft.repo, draft.number, "priority")) : {
28635
28684
  isRateLimited: false,
28636
28685
  value: draft.reviewedHead
28637
28686
  };
28638
28687
  const headAfterPost = headAfterPostRead.isRateLimited ? null : headAfterPostRead.value;
28639
- if (headAfterPost !== null && headAfterPost !== draft.reviewedHead) return retractApproval(key, draft, headAfterPost, posted.reviewId);
28640
- const marked = await markDraft(key, draft, isFollowUpApproval ? {
28688
+ if (headAfterPost !== null && headAfterPost !== draft.reviewedHead) return retractApproval(timing, key, draft, headAfterPost, posted.reviewId);
28689
+ const marked = await markDraft(timing, key, draft, isFollowUpApproval ? {
28641
28690
  status: "posted",
28642
28691
  postedEvent: event
28643
28692
  } : {
@@ -28652,8 +28701,10 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28652
28701
  warning: warnings.join(". ")
28653
28702
  } : { ok: true };
28654
28703
  }
28655
- async function resolveThread(draft, request) {
28656
- if (!request.threadId || !github.resolveReviewThread || !drafts.updateThread) return {
28704
+ async function resolveThread(timing, draft, request) {
28705
+ const resolveReviewThread = github.resolveReviewThread?.bind(github);
28706
+ const updateThread = drafts.updateThread?.bind(drafts);
28707
+ if (!request.threadId || !resolveReviewThread || !updateThread) return {
28657
28708
  ok: false,
28658
28709
  error: "Thread resolution is unavailable"
28659
28710
  };
@@ -28670,10 +28721,10 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28670
28721
  ok: false,
28671
28722
  error: "That nit is resolved automatically"
28672
28723
  };
28673
- const fetchedRead = await store.requestTeamReviewThreads([{
28724
+ const fetchedRead = await readStep(timing, "threads", () => store.requestTeamReviewThreads([{
28674
28725
  repo: draft.repo,
28675
28726
  number: draft.number
28676
- }], "no-wait");
28727
+ }], "priority"));
28677
28728
  if (fetchedRead.isRateLimited) return {
28678
28729
  ok: false,
28679
28730
  error: githubStoreRateLimitedError(fetchedRead.waitMs)
@@ -28701,15 +28752,15 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28701
28752
  ok: false,
28702
28753
  error: "A new reply arrived. Read it before resolving"
28703
28754
  };
28704
- const resolved = await github.resolveReviewThread(thread.id);
28705
- await drafts.updateThread(request.key, thread.id, resolved.ok ? { isResolved: true } : { resolveError: resolved.err || "GitHub refused to resolve the thread" });
28755
+ const resolved = await timeStep(timing, "resolve", () => resolveReviewThread(thread.id));
28756
+ await timeStep(timing, "mark", () => updateThread(request.key, thread.id, resolved.ok ? { isResolved: true } : { resolveError: resolved.err || "GitHub refused to resolve the thread" }));
28706
28757
  return resolved.ok ? { ok: true } : {
28707
28758
  ok: false,
28708
28759
  error: resolved.err || "GitHub refused to resolve the thread"
28709
28760
  };
28710
28761
  }
28711
- async function runAction(request) {
28712
- if (request.action === "discard") return markNotMine(request);
28762
+ async function runAction(timing, request) {
28763
+ if (request.action === "discard") return markNotMine(timing, request);
28713
28764
  const draft = drafts.getDraft(request.key);
28714
28765
  if (!draft) return {
28715
28766
  ok: false,
@@ -28719,25 +28770,39 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28719
28770
  ok: false,
28720
28771
  error: REPLACED_DRAFT_ERROR
28721
28772
  };
28722
- if (request.action === "resolve-thread") return resolveThread(draft, request);
28773
+ if (request.action === "resolve-thread") return resolveThread(timing, draft, request);
28723
28774
  if (request.action === "requeue") return await drafts.requeue(request.key, draft.reviewedHead) ? { ok: true } : {
28724
28775
  ok: false,
28725
28776
  error: "only a failed, ready, stale, discarded or posted review can be queued again"
28726
28777
  };
28727
- return post(request.key, draft, request);
28778
+ return post(timing, request.key, draft, request);
28728
28779
  }
28729
28780
  async function submitAction(request) {
28730
- if (!TeamReviewActionRequest.safeParse(request).success) return {
28731
- ok: false,
28732
- error: "Invalid review action or thread id"
28733
- };
28734
- if (actionsInFlight.has(request.key)) return {
28735
- ok: false,
28736
- error: "An action for this pull request is already running"
28737
- };
28738
- actionsInFlight.add(request.key);
28781
+ const startedAt = now();
28782
+ const timing = { steps: [] };
28783
+ const shouldLogTiming = request.action === "resolve-thread" || SETTLED_OUTCOME_BY_ACTION[request.action] !== void 0;
28784
+ let hasActionLock = false;
28785
+ let loggedOutcome = "error";
28739
28786
  try {
28740
- return await runAction(request);
28787
+ if (!TeamReviewActionRequest.safeParse(request).success) {
28788
+ loggedOutcome = "refused:invalid-request";
28789
+ return {
28790
+ ok: false,
28791
+ error: "Invalid review action or thread id"
28792
+ };
28793
+ }
28794
+ if (actionsInFlight.has(request.key)) {
28795
+ loggedOutcome = "refused:action-in-flight";
28796
+ return {
28797
+ ok: false,
28798
+ error: "An action for this pull request is already running"
28799
+ };
28800
+ }
28801
+ actionsInFlight.add(request.key);
28802
+ hasActionLock = true;
28803
+ const outcome = await runAction(timing, request);
28804
+ loggedOutcome = outcome.ok ? "posted" : `refused:${timing.refusalReason ?? "action-refused"}`;
28805
+ return outcome;
28741
28806
  } catch (error) {
28742
28807
  log.warn(`[${TEAM_REVIEW_LANE_ID}] action failed for ${request.key}: ${errorMessage(error)}`);
28743
28808
  return {
@@ -28745,7 +28810,14 @@ function createTeamReviewActions({ drafts, github, store, log = console, telemet
28745
28810
  error: errorMessage(error)
28746
28811
  };
28747
28812
  } finally {
28748
- actionsInFlight.delete(request.key);
28813
+ if (hasActionLock) actionsInFlight.delete(request.key);
28814
+ const durationMs = Math.max(0, Math.round(now() - startedAt));
28815
+ if (shouldLogTiming) log.warn(`[${TEAM_REVIEW_LANE_ID}] ${request.action} ${request.key} ${loggedOutcome} in ${durationMs}ms: ${timing.steps.join(", ") || "no steps"}`.replace(/[\r\n]+/g, " "));
28816
+ if (timing.refusalReason && !timing.settled) telemetry?.capture("team_review_post_refused", {
28817
+ reason: timing.refusalReason,
28818
+ duration_ms: durationMs
28819
+ });
28820
+ if (timing.settled) captureSettled(timing.settled.outcome, timing.settled.draft, timing.settled.postedCommentCount, durationMs);
28749
28821
  }
28750
28822
  }
28751
28823
  return { submitAction };
@@ -28971,12 +29043,12 @@ function createTeamReviewWiring({ config, store, reviewSessions, closeSessionDat
28971
29043
  const separatorIndex = key.lastIndexOf("#");
28972
29044
  const repo = key.slice(0, separatorIndex);
28973
29045
  const number = Number(key.slice(separatorIndex + 1));
28974
- const headRead = await store.requestPrHead(repo, number, "no-wait");
29046
+ const headRead = await store.requestPrHead(repo, number, "priority");
28975
29047
  if (headRead.isRateLimited) return {
28976
29048
  ok: false,
28977
29049
  error: githubStoreRateLimitedError(headRead.waitMs)
28978
29050
  };
28979
- const detailRead = headRead.value ? await store.requestPrView(repo, number, headRead.value, "no-wait") : {
29051
+ const detailRead = headRead.value ? await store.requestPrView(repo, number, headRead.value, "priority") : {
28980
29052
  isRateLimited: false,
28981
29053
  value: null
28982
29054
  };
@@ -51969,7 +52041,7 @@ function registerControlHandlers(controlWss, deps) {
51969
52041
  const issueOpenQueue = createKeyedSerialQueue();
51970
52042
  async function handleIssueDetail(request, ws) {
51971
52043
  try {
51972
- const issueRead = await requestIssue(request.issueNumber, request.repo, "no-wait");
52044
+ const issueRead = await requestIssue(request.issueNumber, request.repo, "priority");
51973
52045
  if (issueRead.isRateLimited) {
51974
52046
  replyTo(ws, request, "issue-detail-result", {
51975
52047
  ok: false,
@@ -52035,7 +52107,7 @@ function registerControlHandlers(controlWss, deps) {
52035
52107
  });
52036
52108
  return;
52037
52109
  }
52038
- const issueRead = await requestIssue(issueNumber, repo, "no-wait");
52110
+ const issueRead = await requestIssue(issueNumber, repo, "priority");
52039
52111
  if (issueRead.isRateLimited) {
52040
52112
  reply({ error: githubStoreRateLimitedError(issueRead.waitMs, "the issue") });
52041
52113
  return;
@@ -1,6 +1,6 @@
1
1
  import { r as errorMessage } from "./text-DoirglWV.js";
2
- import { c as resolveConfigPath } from "./config-store-CBjnq-OI.js";
3
- import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-BdCTswa1.js";
2
+ import { c as resolveConfigPath } from "./config-store-2noiIsTg.js";
3
+ import { c as defaultPairingsPath, i as REVOCATION_PROPAGATION_SECONDS, l as defaultSeenPath, n as normalizeRemoteConfig, o as createPairingsStore, s as createSeenStore } from "./remote-config-DZWZ5fVJ.js";
4
4
  import fs from "node:fs";
5
5
  //#region server/text-format.ts
6
6
  function trimIso(iso) {
@@ -3,7 +3,7 @@ import { n as equalsIgnoringCaseOnWindows } from "./paths-Bu4eH1Yd.js";
3
3
  import { n as isRecord } from "./coerce-NSst8oRP.js";
4
4
  import { n as unrefTimer, t as DEFAULT_TIMER_FNS } from "./timer-deps-u2DAQLok.js";
5
5
  import { a as jsonStateLoadError, d as writeJsonAtomicSync, l as sleepSync, s as loadJsonStateFileSync, u as writeJsonAtomic } from "./json-file-DFCTvPjj.js";
6
- import { o as glimmervoidHomeDir, ot as canonicalizePath } from "./config-store-CBjnq-OI.js";
6
+ import { o as glimmervoidHomeDir, ot as canonicalizePath } from "./config-store-2noiIsTg.js";
7
7
  import fs from "node:fs";
8
8
  import path from "node:path";
9
9
  import crypto from "node:crypto";
@@ -3,9 +3,9 @@ import { d as AgentSettingsReply } from "./session-BUcx9uJa.js";
3
3
  import { t as renderTable } from "./ascii-figure-core-pDAwtlKO.js";
4
4
  import { n as glimmervoidHomeDir, t as decideConfigPath } from "./config-path-core-DFt-TemS.js";
5
5
  import { n as isRecord } from "./coerce-NSst8oRP.js";
6
- import { C as deleteValueAtPath, D as scoreSettingsSearch, E as parsePosthogProjectSelection, N as SETTINGS_REGISTRY, O as setValueAtPath, Q as withEnvSecrets, S as cloneValue, X as readEnvSecrets, Y as ENV_SECRET_BINDINGS, j as valueAtPath, l as saveConfigFileOnce, s as loadConfigFile, u as validateConfig } from "./config-store-CBjnq-OI.js";
7
- import { m as BrowserConfig } from "./contracts-BJGgl8et.js";
8
- import { a as fail, c as listSettings, d as renderSectionTables, f as requireConfigFileSetting, g as valueText, h as succeed, i as describeSetting, l as readSetting, m as settingsRequestForServer, n as configFileViewOf, o as fitColumn, p as sectionOf, r as defaultText, s as getSetting, t as ALL_SETTINGS } from "./settings-readout-core-CBqSjZiW.js";
6
+ import { C as deleteValueAtPath, D as scoreSettingsSearch, E as parsePosthogProjectSelection, N as SETTINGS_REGISTRY, O as setValueAtPath, Q as withEnvSecrets, S as cloneValue, X as readEnvSecrets, Y as ENV_SECRET_BINDINGS, j as valueAtPath, l as saveConfigFileOnce, s as loadConfigFile, u as validateConfig } from "./config-store-2noiIsTg.js";
7
+ import { m as BrowserConfig } from "./contracts-CFm0dprb.js";
8
+ import { a as fail, c as listSettings, d as renderSectionTables, f as requireConfigFileSetting, g as valueText, h as succeed, i as describeSetting, l as readSetting, m as settingsRequestForServer, n as configFileViewOf, o as fitColumn, p as sectionOf, r as defaultText, s as getSetting, t as ALL_SETTINGS } from "./settings-readout-core-NoTHBGL6.js";
9
9
  import fs from "node:fs";
10
10
  import os from "node:os";
11
11
  import { parseArgs } from "node:util";
@@ -1,6 +1,6 @@
1
1
  import { f as AgentSettingsRequest } from "./session-BUcx9uJa.js";
2
2
  import { t as renderTable } from "./ascii-figure-core-pDAwtlKO.js";
3
- import { A as settingsOf, M as FILE_ONLY_GROUPS, N as SETTINGS_REGISTRY, S as cloneValue, T as hasScaledUnit, X as readEnvSecrets, j as valueAtPath, k as settingsGroupOf, w as displayText, x as SETTINGS_INDEX } from "./config-store-CBjnq-OI.js";
3
+ import { A as settingsOf, M as FILE_ONLY_GROUPS, N as SETTINGS_REGISTRY, S as cloneValue, T as hasScaledUnit, X as readEnvSecrets, j as valueAtPath, k as settingsGroupOf, w as displayText, x as SETTINGS_INDEX } from "./config-store-2noiIsTg.js";
4
4
  import { parseArgs } from "node:util";
5
5
  //#region server/core/settings-readout-core.ts
6
6
  var VALUE_COLUMN_WIDTH = 40;