@integrity-labs/agt-cli 0.28.981 → 0.28.983

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/agt.js CHANGED
@@ -40,12 +40,12 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-AT643QAO.js";
43
+ } from "../chunk-62VGEG77.js";
44
44
  import {
45
45
  getProjectDir,
46
46
  isSessionResumeDisabled,
47
47
  readDirectChatSessionState
48
- } from "../chunk-KTFN2AIB.js";
48
+ } from "../chunk-2JWJZSMK.js";
49
49
  import {
50
50
  AnchorSessionClient,
51
51
  CHANNEL_REGISTRY,
@@ -79,7 +79,7 @@ import {
79
79
  serializeManifestForSlackCli,
80
80
  sessionFileExists,
81
81
  sessionTranscriptDir
82
- } from "../chunk-VF5BT7BP.js";
82
+ } from "../chunk-3GL4ZO25.js";
83
83
  import "../chunk-DHWNVVX4.js";
84
84
  import "../chunk-XWVM4KPK.js";
85
85
 
@@ -5472,7 +5472,7 @@ import { execFileSync, execSync } from "child_process";
5472
5472
  import { existsSync as existsSync11, realpathSync as realpathSync2 } from "fs";
5473
5473
  import chalk18 from "chalk";
5474
5474
  import ora16 from "ora";
5475
- var cliVersion = true ? "0.28.981" : "dev";
5475
+ var cliVersion = true ? "0.28.983" : "dev";
5476
5476
  async function fetchLatestVersion() {
5477
5477
  const host2 = getHost();
5478
5478
  if (!host2) return null;
@@ -6732,7 +6732,7 @@ function handleError(err) {
6732
6732
  }
6733
6733
 
6734
6734
  // src/bin/agt.ts
6735
- var cliVersion2 = true ? "0.28.981" : "dev";
6735
+ var cliVersion2 = true ? "0.28.983" : "dev";
6736
6736
  var program = new Command();
6737
6737
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
6738
6738
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -20,7 +20,7 @@ import {
20
20
  rotateDailySession,
21
21
  sessionFileExists,
22
22
  todayLocalIso
23
- } from "./chunk-VF5BT7BP.js";
23
+ } from "./chunk-3GL4ZO25.js";
24
24
  import {
25
25
  classifyUnanswerablePane,
26
26
  findUsageLimitResetHint,
@@ -5575,4 +5575,4 @@ export {
5575
5575
  stopAllSessionsAndWait,
5576
5576
  getProjectDir
5577
5577
  };
5578
- //# sourceMappingURL=chunk-KTFN2AIB.js.map
5578
+ //# sourceMappingURL=chunk-2JWJZSMK.js.map
@@ -15200,4 +15200,4 @@ export {
15200
15200
  peekCurrentSession,
15201
15201
  readDailySessionPin
15202
15202
  };
15203
- //# sourceMappingURL=chunk-VF5BT7BP.js.map
15203
+ //# sourceMappingURL=chunk-3GL4ZO25.js.map
@@ -14,7 +14,7 @@ import {
14
14
  parseEnvFileEntries,
15
15
  parseEnvIntegrations,
16
16
  shellQuote
17
- } from "./chunk-KTFN2AIB.js";
17
+ } from "./chunk-2JWJZSMK.js";
18
18
  import {
19
19
  BIND_FAILURE_QUARANTINE_THRESHOLD,
20
20
  INTEGRATIONS_SECTION_END,
@@ -74,7 +74,7 @@ import {
74
74
  sessionTranscriptDir,
75
75
  worseConnectivityOutcome,
76
76
  wrapScheduledTaskPrompt
77
- } from "./chunk-VF5BT7BP.js";
77
+ } from "./chunk-3GL4ZO25.js";
78
78
  import {
79
79
  classifyUnanswerablePane,
80
80
  summarizeUnanswerablePane
@@ -6967,7 +6967,7 @@ function exchangeFailureKind(err) {
6967
6967
  }
6968
6968
 
6969
6969
  // src/lib/api-client.ts
6970
- var agtCliVersion = true ? "0.28.981" : "dev";
6970
+ var agtCliVersion = true ? "0.28.983" : "dev";
6971
6971
  var lastConfigHash = null;
6972
6972
  function setConfigHash(hash) {
6973
6973
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -11709,4 +11709,4 @@ export {
11709
11709
  managerInstallSystemUnitCommand,
11710
11710
  managerUninstallSystemUnitCommand
11711
11711
  };
11712
- //# sourceMappingURL=chunk-AT643QAO.js.map
11712
+ //# sourceMappingURL=chunk-62VGEG77.js.map
@@ -258,7 +258,7 @@ async function spawnPairSession(session) {
258
258
  return { ok: true };
259
259
  } catch {
260
260
  }
261
- const { resolveClaudeBinary } = await import("./persistent-session-26W47NVS.js");
261
+ const { resolveClaudeBinary } = await import("./persistent-session-YKEY6ACQ.js");
262
262
  const claudeBin = resolveClaudeBinary();
263
263
  const pairEnv = {
264
264
  ...process.env,
@@ -580,4 +580,4 @@ export {
580
580
  startClaudePair,
581
581
  submitClaudePairCode
582
582
  };
583
- //# sourceMappingURL=claude-pair-runtime-5JPASWRO.js.map
583
+ //# sourceMappingURL=claude-pair-runtime-Q4MJOZ2J.js.map
@@ -63,7 +63,7 @@ import {
63
63
  safeWriteJsonAtomic,
64
64
  setConfigHash,
65
65
  tripClass
66
- } from "../chunk-AT643QAO.js";
66
+ } from "../chunk-62VGEG77.js";
67
67
  import {
68
68
  getProjectDir as getProjectDir2,
69
69
  getReadyTasks,
@@ -140,7 +140,7 @@ import {
140
140
  takeZombieDetection,
141
141
  toOpencodeModel,
142
142
  writeEgressAllowlist
143
- } from "../chunk-KTFN2AIB.js";
143
+ } from "../chunk-2JWJZSMK.js";
144
144
  import {
145
145
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
146
146
  AnchorSessionClient,
@@ -238,7 +238,7 @@ import {
238
238
  subagentActivityAgeSeconds,
239
239
  sumTranscriptUsageInWindow,
240
240
  transcriptActivityAgeSeconds
241
- } from "../chunk-VF5BT7BP.js";
241
+ } from "../chunk-3GL4ZO25.js";
242
242
  import "../chunk-DHWNVVX4.js";
243
243
  import {
244
244
  reapOrphanChannelMcps
@@ -6461,6 +6461,16 @@ import { join as join30 } from "path";
6461
6461
  function claudeDeviceStatePath(env = process.env) {
6462
6462
  return join30(env.HOME?.trim() || homedir13(), ".claude.json");
6463
6463
  }
6464
+ function probeClaudeDeviceStatePresence(path = claudeDeviceStatePath()) {
6465
+ try {
6466
+ return statSync9(path).isFile() ? { present: true } : { present: false, reason: "not-a-file" };
6467
+ } catch (err) {
6468
+ return {
6469
+ present: false,
6470
+ reason: err?.code === "ENOENT" ? "missing" : "unreadable"
6471
+ };
6472
+ }
6473
+ }
6464
6474
  function checkClaudeDeviceState(path = claudeDeviceStatePath()) {
6465
6475
  try {
6466
6476
  if (!statSync9(path).isFile()) return { usable: false, reason: "not-a-file" };
@@ -6489,10 +6499,18 @@ function checkClaudeDeviceState(path = claudeDeviceStatePath()) {
6489
6499
  return { usable: true };
6490
6500
  }
6491
6501
  var DeviceStateRotationGate = class {
6492
- constructor(check = () => checkClaudeDeviceState()) {
6502
+ constructor(check = () => checkClaudeDeviceState(), probe = () => probeClaudeDeviceStatePresence()) {
6493
6503
  this.check = check;
6504
+ this.probe = probe;
6494
6505
  }
6495
6506
  held = /* @__PURE__ */ new Map();
6507
+ /**
6508
+ * ENG-10730: when the CHEAP probe first saw the file gone with nothing held.
6509
+ * Separate from `held`, which records when each agent's rotation was stopped -
6510
+ * in this state no rotation has been stopped at all. Cleared whenever the file
6511
+ * is seen present again, so a later episode gets its own clock.
6512
+ */
6513
+ unusableSinceMs = null;
6496
6514
  /**
6497
6515
  * Ask before tearing `codeName`'s session down for a planned rotation.
6498
6516
  * Returns `ready: true` when the respawn can start; otherwise the rotation must
@@ -6510,22 +6528,62 @@ var DeviceStateRotationGate = class {
6510
6528
  return { ready: false, reason: verdict.reason, firstHold };
6511
6529
  }
6512
6530
  /**
6513
- * The value for the heartbeat. Re-checks the file while anything is held, so
6514
- * the alert closes on the next heartbeat after the operator pairs the host,
6515
- * not only when some agent's rollover next asks. Reads nothing when nothing is
6516
- * held, so a healthy host pays no file read per heartbeat.
6531
+ * The value for the heartbeat.
6532
+ *
6533
+ * ENG-10730. This used to open with `if (this.held.size === 0) return null;` -
6534
+ * it returned the affirmative all-clear WITHOUT LOOKING, and the docblock
6535
+ * defended that as "a healthy host pays no file read per heartbeat". The
6536
+ * saving was real and so was the hole: a host whose `~/.claude.json` had been
6537
+ * unlinked, and which had not happened to attempt a rotation since, reported
6538
+ * `null` every 30 seconds while already doomed. Nothing asked until some
6539
+ * agent's rollover did, which on ENG-10724 was the maintenance window - i.e.
6540
+ * the moment the agents were lost. The host was discovered one whole host at a
6541
+ * time, at whatever hour its window fell.
6542
+ *
6543
+ * So the heartbeat now always looks, and pays for it with ONE `statSync` -
6544
+ * `probeClaudeDeviceStatePresence`, no read, no parse. The original perf
6545
+ * objection is answered rather than overridden: what was rejected in PR #6250
6546
+ * was a multi-MB synchronous `JSON.parse` on every healthy host's event loop,
6547
+ * and that is still not happening here.
6548
+ *
6549
+ * THE TWO PATHS ARE NOT SYMMETRIC, AND THAT IS DELIBERATE.
6550
+ * - Something held: the FULL check, exactly as before. A hold must only clear
6551
+ * on a genuinely usable file, so a present-but-corrupt one cannot read as a
6552
+ * recovery and release a rotation onto a host that still cannot respawn.
6553
+ * - Nothing held: the CHEAP probe. It can only report that the file has GONE,
6554
+ * never that one is well - so it can raise this warning and it can clear
6555
+ * this warning, but it is never allowed to clear a hold.
6556
+ *
6557
+ * `deferred_agents: []` with a reason is therefore a THIRD state, distinct
6558
+ * from both `null` and a hold: the file is unusable and nothing has been
6559
+ * stopped yet. The API must not describe that as a hold - see
6560
+ * `summariseDeviceStateBlock`, which separates the two so the alert does not
6561
+ * claim the manager is holding work it is not.
6517
6562
  */
6518
- heartbeatField() {
6519
- if (this.held.size === 0) return null;
6520
- const verdict = this.check();
6521
- if (verdict.usable) {
6522
- this.held.clear();
6563
+ heartbeatField(nowMs = Date.now()) {
6564
+ if (this.held.size > 0) {
6565
+ const verdict = this.check();
6566
+ if (verdict.usable) {
6567
+ this.held.clear();
6568
+ this.unusableSinceMs = null;
6569
+ return null;
6570
+ }
6571
+ return {
6572
+ reason: verdict.reason,
6573
+ deferred_agents: [...this.held.keys()].sort(),
6574
+ blocked_since: new Date(Math.min(...this.held.values())).toISOString()
6575
+ };
6576
+ }
6577
+ const presence = this.probe();
6578
+ if (presence.present) {
6579
+ this.unusableSinceMs = null;
6523
6580
  return null;
6524
6581
  }
6582
+ if (this.unusableSinceMs === null) this.unusableSinceMs = nowMs;
6525
6583
  return {
6526
- reason: verdict.reason,
6527
- deferred_agents: [...this.held.keys()].sort(),
6528
- blocked_since: new Date(Math.min(...this.held.values())).toISOString()
6584
+ reason: presence.reason,
6585
+ deferred_agents: [],
6586
+ blocked_since: new Date(this.unusableSinceMs).toISOString()
6529
6587
  };
6530
6588
  }
6531
6589
  /** For tests and logs. */
@@ -13212,7 +13270,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
13212
13270
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
13213
13271
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
13214
13272
  async function channelInboundActivityAgeSecondsFor(codeName) {
13215
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-KMHYGGYP.js");
13273
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-2T6AKR7I.js");
13216
13274
  const newest = newestPendingInboundActivityMtimeMs(dirname11(paneLogPath(codeName)));
13217
13275
  if (newest === null) return null;
13218
13276
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -13955,7 +14013,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13955
14013
  var lastVersionCheckAt = 0;
13956
14014
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13957
14015
  var lastResponsivenessProbeAt = 0;
13958
- var agtCliVersion = true ? "0.28.981" : "dev";
14016
+ var agtCliVersion = true ? "0.28.983" : "dev";
13959
14017
  function resolveBrewPath(execFileSync2) {
13960
14018
  try {
13961
14019
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -15561,7 +15619,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15561
15619
  if (codeNames.length === 0) return;
15562
15620
  void (async () => {
15563
15621
  try {
15564
- const { collectDiagnostics } = await import("../persistent-session-26W47NVS.js");
15622
+ const { collectDiagnostics } = await import("../persistent-session-YKEY6ACQ.js");
15565
15623
  await api.post("/host/heartbeat", {
15566
15624
  host_id: hostId,
15567
15625
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -15703,7 +15761,7 @@ async function pollCycleInner() {
15703
15761
  }
15704
15762
  try {
15705
15763
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
15706
- const { collectDiagnostics } = await import("../persistent-session-26W47NVS.js");
15764
+ const { collectDiagnostics } = await import("../persistent-session-YKEY6ACQ.js");
15707
15765
  const diagCodeNames = [...agentState.persistentSessionAgents];
15708
15766
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
15709
15767
  let tailscaleHostname;
@@ -15879,7 +15937,7 @@ async function pollCycleInner() {
15879
15937
  collectPanelessActivityProbes,
15880
15938
  getResponsivenessIntervalMs,
15881
15939
  occupancyQualificationClassifications
15882
- } = await import("../responsiveness-probe-KMHYGGYP.js");
15940
+ } = await import("../responsiveness-probe-2T6AKR7I.js");
15883
15941
  const probeIntervalMs = getResponsivenessIntervalMs();
15884
15942
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
15885
15943
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -15996,7 +16054,7 @@ async function pollCycleInner() {
15996
16054
  collectResponsivenessProbes,
15997
16055
  livePendingInboundOldestAgeSeconds,
15998
16056
  parkPendingInbound
15999
- } = await import("../responsiveness-probe-KMHYGGYP.js");
16057
+ } = await import("../responsiveness-probe-2T6AKR7I.js");
16000
16058
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
16001
16059
  const wedgeNow = /* @__PURE__ */ new Date();
16002
16060
  const liveAgents = agentState.persistentSessionAgents;
@@ -16152,7 +16210,7 @@ async function pollCycleInner() {
16152
16210
  }
16153
16211
  try {
16154
16212
  const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
16155
- const { probeSessionAuth } = await import("../session-auth-dead-CRG2ESD2.js");
16213
+ const { probeSessionAuth } = await import("../session-auth-dead-S2XOP5EO.js");
16156
16214
  const observations = [];
16157
16215
  const pendingCacheCommits = [];
16158
16216
  const modelApiErrorReportingOn = hostFlagStore().getBoolean("model-api-error-reporting");
@@ -20428,7 +20486,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20428
20486
  try {
20429
20487
  const freshId = rotateSessionForWedge(codeName);
20430
20488
  consecutiveWedgeCycles.delete(codeName);
20431
- const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-KMHYGGYP.js");
20489
+ const { parkPendingInbound: parkForRestart } = await import("../responsiveness-probe-2T6AKR7I.js");
20432
20490
  const { parked, deadLettered } = parkForRestart(codeName, /* @__PURE__ */ new Date());
20433
20491
  const parkNote = parked > 0 ? `, ${parked} inbound parked` : "";
20434
20492
  const deadNote = deadLettered > 0 ? `, ${deadLettered} undeliverable dead-lettered` : "";
@@ -20471,7 +20529,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
20471
20529
  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}`));
20472
20530
  void (async () => {
20473
20531
  try {
20474
- const { collectDiagnostics } = await import("../persistent-session-26W47NVS.js");
20532
+ const { collectDiagnostics } = await import("../persistent-session-YKEY6ACQ.js");
20475
20533
  await api.post("/host/heartbeat", {
20476
20534
  host_id: hostId,
20477
20535
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20522,7 +20580,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
20522
20580
  }
20523
20581
  try {
20524
20582
  const hostId = await getHostId();
20525
- const { collectDiagnostics } = await import("../persistent-session-26W47NVS.js");
20583
+ const { collectDiagnostics } = await import("../persistent-session-YKEY6ACQ.js");
20526
20584
  await api.post("/host/heartbeat", {
20527
20585
  host_id: hostId,
20528
20586
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -21164,7 +21222,7 @@ async function processClaudePairSessions(agents) {
21164
21222
  killPairSession,
21165
21223
  pairTmuxSession,
21166
21224
  finalizeClaudePairOnboarding
21167
- } = await import("../claude-pair-runtime-5JPASWRO.js");
21225
+ } = await import("../claude-pair-runtime-Q4MJOZ2J.js");
21168
21226
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
21169
21227
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
21170
21228
  const killed = await killPairSession(pairTmuxSession(pairId));