@integrity-labs/agt-cli 0.28.539 → 0.28.541

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.
@@ -42,7 +42,7 @@ import {
42
42
  resolveConnectivityProbe,
43
43
  worseConnectivityOutcome,
44
44
  wrapScheduledTaskPrompt
45
- } from "./chunk-N6HD5UG4.js";
45
+ } from "./chunk-F63RM2RQ.js";
46
46
  import {
47
47
  parsePsRows
48
48
  } from "./chunk-XWVM4KPK.js";
@@ -5549,7 +5549,7 @@ function exchangeFailureKind(err) {
5549
5549
  }
5550
5550
 
5551
5551
  // src/lib/api-client.ts
5552
- var agtCliVersion = true ? "0.28.539" : "dev";
5552
+ var agtCliVersion = true ? "0.28.541" : "dev";
5553
5553
  var lastConfigHash = null;
5554
5554
  function setConfigHash(hash) {
5555
5555
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8861,4 +8861,4 @@ export {
8861
8861
  managerInstallSystemUnitCommand,
8862
8862
  managerUninstallSystemUnitCommand
8863
8863
  };
8864
- //# sourceMappingURL=chunk-TR2H3AGK.js.map
8864
+ //# sourceMappingURL=chunk-JQNSKZIC.js.map
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
100
100
  return { ok: true };
101
101
  } catch {
102
102
  }
103
- const { resolveClaudeBinary } = await import("./persistent-session-D47WOTHA.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-7GPDXRPK.js");
104
104
  const claudeBin = resolveClaudeBinary();
105
105
  const pairEnv = {
106
106
  ...process.env,
@@ -373,4 +373,4 @@ export {
373
373
  startClaudePair,
374
374
  submitClaudePairCode
375
375
  };
376
- //# sourceMappingURL=claude-pair-runtime-FHNWMTUH.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-2UU67Q2T.js.map
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-TR2H3AGK.js";
56
+ } from "../chunk-JQNSKZIC.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -66,6 +66,7 @@ import {
66
66
  AnchorSessionClient,
67
67
  CLAUDE_MD_MAX_CHARS,
68
68
  CONVERSATION_FAILURE_CATEGORIES,
69
+ ChildProcessError,
69
70
  DEFAULT_FRAMEWORK,
70
71
  DEFAULT_NEIGHBOURHOOD_MS,
71
72
  FLAGS_SCHEMA_VERSION,
@@ -180,7 +181,7 @@ import {
180
181
  toOpencodeModel,
181
182
  transcriptActivityAgeSeconds,
182
183
  writeEgressAllowlist
183
- } from "../chunk-N6HD5UG4.js";
184
+ } from "../chunk-F63RM2RQ.js";
184
185
  import {
185
186
  reapOrphanChannelMcps
186
187
  } from "../chunk-XWVM4KPK.js";
@@ -4498,6 +4499,65 @@ async function applyClaudeAuthToEnv(childEnv, label) {
4498
4499
  }
4499
4500
  }
4500
4501
 
4502
+ // src/lib/claude-runtime-auth-probe.ts
4503
+ var RUNTIME_AUTH_SENTINEL = "AGTAUTHOK";
4504
+ var RUNTIME_AUTH_PROBE_PROMPT = `Reply with exactly this and nothing else: ${RUNTIME_AUTH_SENTINEL}`;
4505
+ var AUTH_REFUSAL_MARKERS = [
4506
+ "failed to authenticate",
4507
+ "oauth session expired",
4508
+ "could not be refreshed",
4509
+ "invalid api key",
4510
+ "authentication_error",
4511
+ "please run /login",
4512
+ "please run `claude /login`"
4513
+ ];
4514
+ function safeDetail(raw) {
4515
+ return raw.replace(/\bsk-[a-zA-Z0-9-]+/g, "sk-<redacted>").replace(/\b(Bearer|token|refreshToken|accessToken)\s*[:=]?\s*\S+/gi, "$1 <redacted>").replace(/\s+/g, " ").trim().slice(0, 200);
4516
+ }
4517
+ function classifyRuntimeAuthProbe(input) {
4518
+ const { exitCode, stdout, stderr, timedOut } = input;
4519
+ const combined = `${stdout}
4520
+ ${stderr}`;
4521
+ const haystack = combined.toLowerCase();
4522
+ if (timedOut) {
4523
+ return { verdict: "inconclusive", detail: "probe timed out" };
4524
+ }
4525
+ const marker = AUTH_REFUSAL_MARKERS.find((m) => haystack.includes(m));
4526
+ if (marker) {
4527
+ return {
4528
+ verdict: "not-authenticated",
4529
+ detail: safeDetail(combined) || `matched: ${marker}`
4530
+ };
4531
+ }
4532
+ if (exitCode === 0 && stdout.includes(RUNTIME_AUTH_SENTINEL)) {
4533
+ return { verdict: "authenticated", detail: "sentinel returned" };
4534
+ }
4535
+ if (exitCode === 0) {
4536
+ return { verdict: "inconclusive", detail: "exit 0 but sentinel absent" };
4537
+ }
4538
+ return {
4539
+ verdict: "inconclusive",
4540
+ detail: safeDetail(`exit ${exitCode ?? "null"}: ${combined}`)
4541
+ };
4542
+ }
4543
+ function foldRuntimeAuthVerdict(input) {
4544
+ const { verdict, previous, consecutiveFailures, requiredConsecutiveFailures } = input;
4545
+ if (verdict === "authenticated") {
4546
+ return { reported: true, consecutiveFailures: 0 };
4547
+ }
4548
+ if (verdict === "not-authenticated") {
4549
+ const next = consecutiveFailures + 1;
4550
+ return {
4551
+ reported: next >= requiredConsecutiveFailures ? false : previous,
4552
+ consecutiveFailures: next
4553
+ };
4554
+ }
4555
+ return { reported: previous, consecutiveFailures };
4556
+ }
4557
+ function heartbeatRuntimeAuthReport(probeVerdict) {
4558
+ return probeVerdict ?? void 0;
4559
+ }
4560
+
4501
4561
  // src/lib/manager/kanban/parsers.ts
4502
4562
  import { existsSync as existsSync8, readFileSync as readFileSync15 } from "fs";
4503
4563
  import { join as join20 } from "path";
@@ -10369,7 +10429,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
10369
10429
  var lastVersionCheckAt = 0;
10370
10430
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
10371
10431
  var lastResponsivenessProbeAt = 0;
10372
- var agtCliVersion = true ? "0.28.539" : "dev";
10432
+ var agtCliVersion = true ? "0.28.541" : "dev";
10373
10433
  function resolveBrewPath(execFileSync2) {
10374
10434
  try {
10375
10435
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -11240,6 +11300,99 @@ function isOlderSemverTuple(local, remote) {
11240
11300
  }
11241
11301
  return false;
11242
11302
  }
11303
+ var RUNTIME_AUTH_PROBE_INTERVAL_MS = 15 * 60 * 1e3;
11304
+ var RUNTIME_AUTH_PROBE_TIMEOUT_MS = 6e4;
11305
+ var RUNTIME_AUTH_PROBE_FAILURES_TO_CONDEMN = 2;
11306
+ var lastRuntimeAuthProbeAt = 0;
11307
+ var runtimeAuthProbeInFlight = false;
11308
+ var runtimeAuthConsecutiveFailures = 0;
11309
+ var runtimeAuthProbeVerdict = null;
11310
+ function effectiveRuntimeAuthenticated() {
11311
+ return runtimeAuthProbeVerdict ?? agentRuntimeAuthenticated;
11312
+ }
11313
+ async function maybeProbeClaudeRuntimeAuth() {
11314
+ if (runtimeAuthProbeInFlight) return;
11315
+ if (Date.now() - lastRuntimeAuthProbeAt < RUNTIME_AUTH_PROBE_INTERVAL_MS) return;
11316
+ const { execFileSync: execFileSync2 } = await import("child_process");
11317
+ if (!claudeBinaryInstalled(execFileSync2)) return;
11318
+ runtimeAuthProbeInFlight = true;
11319
+ lastRuntimeAuthProbeAt = Date.now();
11320
+ try {
11321
+ const before = effectiveRuntimeAuthenticated();
11322
+ const result = await runClaudeRuntimeAuthProbe();
11323
+ const folded = foldRuntimeAuthVerdict({
11324
+ verdict: result.verdict,
11325
+ previous: before,
11326
+ consecutiveFailures: runtimeAuthConsecutiveFailures,
11327
+ requiredConsecutiveFailures: RUNTIME_AUTH_PROBE_FAILURES_TO_CONDEMN
11328
+ });
11329
+ runtimeAuthConsecutiveFailures = folded.consecutiveFailures;
11330
+ if (result.verdict === "authenticated" || folded.reported !== before) {
11331
+ runtimeAuthProbeVerdict = folded.reported;
11332
+ }
11333
+ if (folded.reported !== before) {
11334
+ log(
11335
+ `[runtime-auth-probe] reported authentication ${before} -> ${folded.reported} (verdict=${result.verdict}, consecutiveFailures=${folded.consecutiveFailures}): ${result.detail}`
11336
+ );
11337
+ } else if (result.verdict !== "authenticated") {
11338
+ log(
11339
+ `[runtime-auth-probe] verdict=${result.verdict} (consecutiveFailures=${runtimeAuthConsecutiveFailures}): ${result.detail}`
11340
+ );
11341
+ }
11342
+ } catch (err) {
11343
+ log(`[runtime-auth-probe] probe error (treated as inconclusive): ${err.message}`);
11344
+ } finally {
11345
+ runtimeAuthProbeInFlight = false;
11346
+ }
11347
+ }
11348
+ async function runClaudeRuntimeAuthProbe() {
11349
+ const childEnv = { ...process.env };
11350
+ await applyClaudeAuthToEnv(childEnv, "runtime-auth-probe");
11351
+ const emptyMcp = ensureEvalEmptyMcpConfig();
11352
+ const args = [
11353
+ "-p",
11354
+ RUNTIME_AUTH_PROBE_PROMPT,
11355
+ "--model",
11356
+ process.env["AGT_CONV_EVAL_CLAUDE_MODEL"]?.trim() || DEFAULT_CLAUDE_EVAL_MODEL,
11357
+ // feature-gate-allow: model tunable, not a gate
11358
+ "--output-format",
11359
+ "text",
11360
+ // Same isolation as conversation-eval: no project config, no MCP, no tools.
11361
+ // The probe must exercise AUTH and nothing else.
11362
+ "--mcp-config",
11363
+ emptyMcp,
11364
+ "--strict-mcp-config",
11365
+ "--permission-mode",
11366
+ "auto",
11367
+ "--allowedTools",
11368
+ ""
11369
+ ];
11370
+ try {
11371
+ const { stdout, stderr } = await execFilePromiseLong(resolveClaudeBinary(), args, {
11372
+ cwd: homedir12(),
11373
+ timeout: RUNTIME_AUTH_PROBE_TIMEOUT_MS,
11374
+ stdin: "ignore",
11375
+ env: childEnv,
11376
+ onSpawn: (pid) => registerClaudeSpawn({ pid, started_at: Date.now(), kind: "conv-eval" }),
11377
+ onExit: (pid) => unregisterClaudeSpawn(pid)
11378
+ });
11379
+ return classifyRuntimeAuthProbe({ exitCode: 0, stdout, stderr });
11380
+ } catch (err) {
11381
+ if (err instanceof ChildProcessError) {
11382
+ return classifyRuntimeAuthProbe({
11383
+ exitCode: err.code,
11384
+ stdout: err.stdout,
11385
+ stderr: err.stderr
11386
+ });
11387
+ }
11388
+ return classifyRuntimeAuthProbe({
11389
+ exitCode: null,
11390
+ stdout: "",
11391
+ stderr: err.message,
11392
+ timedOut: true
11393
+ });
11394
+ }
11395
+ }
11243
11396
  async function checkClaudeAuth() {
11244
11397
  try {
11245
11398
  const report = await detectClaudeAuth();
@@ -11580,7 +11733,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
11580
11733
  if (codeNames.length === 0) return;
11581
11734
  void (async () => {
11582
11735
  try {
11583
- const { collectDiagnostics } = await import("../persistent-session-D47WOTHA.js");
11736
+ const { collectDiagnostics } = await import("../persistent-session-7GPDXRPK.js");
11584
11737
  await api.post("/host/heartbeat", {
11585
11738
  host_id: hostId,
11586
11739
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
@@ -11666,6 +11819,7 @@ async function pollCycle() {
11666
11819
  checkAndUpdateCli().catch((err) => log(`[self-update] Check failed: ${err.message}`));
11667
11820
  }
11668
11821
  maybeUpgradeClaudeCode().catch((err) => log(`[claude-code-upgrade] Check failed: ${err.message}`));
11822
+ maybeProbeClaudeRuntimeAuth().catch((err) => log(`[runtime-auth-probe] Check failed: ${err.message}`));
11669
11823
  try {
11670
11824
  registeredAgentsCache.clear();
11671
11825
  const hostId = await getHostId();
@@ -11687,7 +11841,7 @@ async function pollCycle() {
11687
11841
  }
11688
11842
  try {
11689
11843
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
11690
- const { collectDiagnostics } = await import("../persistent-session-D47WOTHA.js");
11844
+ const { collectDiagnostics } = await import("../persistent-session-7GPDXRPK.js");
11691
11845
  const diagCodeNames = [...agentState.persistentSessionAgents];
11692
11846
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
11693
11847
  let tailscaleHostname;
@@ -11733,7 +11887,11 @@ async function pollCycle() {
11733
11887
  framework_version: cachedFrameworkVersion ?? void 0,
11734
11888
  agt_version: agtCliVersion,
11735
11889
  host_security: detectHostSecurity() ?? void 0,
11736
- agent_runtime_authenticated: agentRuntimeAuthenticated,
11890
+ // ENG-8623: the probe's verdict, or the field is OMITTED. The column is
11891
+ // named for a runtime observation and the API now stamps a freshness
11892
+ // timestamp beside it, so a file-derived value here would manufacture an
11893
+ // observation nobody made. See `heartbeatRuntimeAuthReport`.
11894
+ agent_runtime_authenticated: heartbeatRuntimeAuthReport(runtimeAuthProbeVerdict),
11737
11895
  agent_diagnostics: agentDiagnostics,
11738
11896
  hostname: tailscaleHostname,
11739
11897
  os_username: osUsername,
@@ -11803,7 +11961,7 @@ async function pollCycle() {
11803
11961
  collectPanelessActivityProbes,
11804
11962
  getResponsivenessIntervalMs,
11805
11963
  occupancyQualificationClassifications
11806
- } = await import("../responsiveness-probe-HZUQTMSG.js");
11964
+ } = await import("../responsiveness-probe-P52CE6K7.js");
11807
11965
  const probeIntervalMs = getResponsivenessIntervalMs();
11808
11966
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
11809
11967
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -11894,7 +12052,7 @@ async function pollCycle() {
11894
12052
  collectResponsivenessProbes,
11895
12053
  livePendingInboundOldestAgeSeconds,
11896
12054
  parkPendingInbound
11897
- } = await import("../responsiveness-probe-HZUQTMSG.js");
12055
+ } = await import("../responsiveness-probe-P52CE6K7.js");
11898
12056
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
11899
12057
  const wedgeNow = /* @__PURE__ */ new Date();
11900
12058
  const liveAgents = agentState.persistentSessionAgents;
@@ -15424,7 +15582,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
15424
15582
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
15425
15583
  void (async () => {
15426
15584
  try {
15427
- const { collectDiagnostics } = await import("../persistent-session-D47WOTHA.js");
15585
+ const { collectDiagnostics } = await import("../persistent-session-7GPDXRPK.js");
15428
15586
  await api.post("/host/heartbeat", {
15429
15587
  host_id: hostId,
15430
15588
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -15474,7 +15632,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
15474
15632
  }
15475
15633
  try {
15476
15634
  const hostId = await getHostId();
15477
- const { collectDiagnostics } = await import("../persistent-session-D47WOTHA.js");
15635
+ const { collectDiagnostics } = await import("../persistent-session-7GPDXRPK.js");
15478
15636
  await api.post("/host/heartbeat", {
15479
15637
  host_id: hostId,
15480
15638
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
@@ -15998,7 +16156,7 @@ async function processClaudePairSessions(agents) {
15998
16156
  killPairSession,
15999
16157
  pairTmuxSession,
16000
16158
  finalizeClaudePairOnboarding
16001
- } = await import("../claude-pair-runtime-FHNWMTUH.js");
16159
+ } = await import("../claude-pair-runtime-2UU67Q2T.js");
16002
16160
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
16003
16161
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
16004
16162
  const killed = await killPairSession(pairTmuxSession(pairId));
@@ -16942,6 +17100,7 @@ export {
16942
17100
  isPrereleaseVersion,
16943
17101
  markAgentForFreshMemorySync,
16944
17102
  maybeInjectKanbanCheck,
17103
+ maybeProbeClaudeRuntimeAuth,
16945
17104
  maybeUpgradeClaudeCode,
16946
17105
  refreshSkillsIndexInClaudeMd,
16947
17106
  reorderRestartedFirst,