@integrity-labs/agt-cli 0.28.607 → 0.28.609

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,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-DYADWFBV.js";
43
+ } from "../chunk-ZJFDQNLN.js";
44
44
  import {
45
45
  readDirectChatSessionState
46
46
  } from "../chunk-DESCRVVM.js";
@@ -4909,7 +4909,7 @@ import { execFileSync, execSync } from "child_process";
4909
4909
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4910
4910
  import chalk18 from "chalk";
4911
4911
  import ora16 from "ora";
4912
- var cliVersion = true ? "0.28.607" : "dev";
4912
+ var cliVersion = true ? "0.28.609" : "dev";
4913
4913
  async function fetchLatestVersion() {
4914
4914
  const host2 = getHost();
4915
4915
  if (!host2) return null;
@@ -6089,7 +6089,7 @@ function handleError(err) {
6089
6089
  }
6090
6090
 
6091
6091
  // src/bin/agt.ts
6092
- var cliVersion2 = true ? "0.28.607" : "dev";
6092
+ var cliVersion2 = true ? "0.28.609" : "dev";
6093
6093
  var program = new Command();
6094
6094
  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");
6095
6095
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -6030,7 +6030,7 @@ function exchangeFailureKind(err) {
6030
6030
  }
6031
6031
 
6032
6032
  // src/lib/api-client.ts
6033
- var agtCliVersion = true ? "0.28.607" : "dev";
6033
+ var agtCliVersion = true ? "0.28.609" : "dev";
6034
6034
  var lastConfigHash = null;
6035
6035
  function setConfigHash(hash) {
6036
6036
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -9505,4 +9505,4 @@ export {
9505
9505
  managerInstallSystemUnitCommand,
9506
9506
  managerUninstallSystemUnitCommand
9507
9507
  };
9508
- //# sourceMappingURL=chunk-DYADWFBV.js.map
9508
+ //# sourceMappingURL=chunk-ZJFDQNLN.js.map
@@ -53,7 +53,7 @@ import {
53
53
  safeWriteJsonAtomic,
54
54
  setConfigHash,
55
55
  tripClass
56
- } from "../chunk-DYADWFBV.js";
56
+ } from "../chunk-ZJFDQNLN.js";
57
57
  import {
58
58
  getProjectDir as getProjectDir2,
59
59
  getReadyTasks,
@@ -7334,6 +7334,9 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
7334
7334
  // src/lib/occupancy-gate.ts
7335
7335
  import { closeSync as closeSync2, openSync as openSync2, readdirSync as readdirSync6, readSync as readSync2, statSync as statSync6 } from "fs";
7336
7336
  import { join as join30 } from "path";
7337
+ function rostersMeasuredZero(mode, attested, runtimeRunning) {
7338
+ return mode === "enforce" && attested && runtimeRunning;
7339
+ }
7337
7340
  var TAIL_BYTES = 256 * 1024;
7338
7341
  var MAX_RECORD_ALIGN_BYTES = 8 * 1024 * 1024;
7339
7342
  var GATE_MAX_BUCKET_AGE_MS = 30 * 6e4;
@@ -7531,6 +7534,13 @@ var SAMPLE_INTERVAL_MS = 1e4;
7531
7534
  var IDLE_GAP_MS = 12e4;
7532
7535
  var POST_IDLE_CREDIT_MS = 6e4;
7533
7536
  var lastMtimeMs = /* @__PURE__ */ new Map();
7537
+ var lastObservedAtMs = /* @__PURE__ */ new Map();
7538
+ var OBSERVATION_FRESH_MS = SAMPLE_INTERVAL_MS * 6;
7539
+ function hasFreshPaneObservation(codeName, nowMs, maxAgeMs = OBSERVATION_FRESH_MS) {
7540
+ const at = lastObservedAtMs.get(codeName);
7541
+ if (at == null) return false;
7542
+ return nowMs - at <= maxAgeMs;
7543
+ }
7534
7544
  function paneMtimeMs(codeName) {
7535
7545
  try {
7536
7546
  return statSync7(paneLogPath(codeName)).mtimeMs;
@@ -7541,11 +7551,13 @@ function paneMtimeMs(codeName) {
7541
7551
  function samplePaneOccupancyOnce(codeNames, opts = {}) {
7542
7552
  const ledger = opts.ledger ?? sharedBusyBuckets;
7543
7553
  const readMtime = opts.readMtime ?? paneMtimeMs;
7554
+ const nowMs = opts.nowMs ?? Date.now();
7544
7555
  const seen = /* @__PURE__ */ new Set();
7545
7556
  for (const codeName of codeNames) {
7546
7557
  seen.add(codeName);
7547
7558
  const mtime = readMtime(codeName);
7548
7559
  if (mtime == null) continue;
7560
+ lastObservedAtMs.set(codeName, nowMs);
7549
7561
  const prev = lastMtimeMs.get(codeName);
7550
7562
  lastMtimeMs.set(codeName, mtime);
7551
7563
  if (prev == null) continue;
@@ -7560,6 +7572,9 @@ function samplePaneOccupancyOnce(codeNames, opts = {}) {
7560
7572
  for (const codeName of [...lastMtimeMs.keys()]) {
7561
7573
  if (!seen.has(codeName)) lastMtimeMs.delete(codeName);
7562
7574
  }
7575
+ for (const codeName of [...lastObservedAtMs.keys()]) {
7576
+ if (!seen.has(codeName)) lastObservedAtMs.delete(codeName);
7577
+ }
7563
7578
  }
7564
7579
  var timer = null;
7565
7580
  function startPaneOccupancySampler(liveAgents) {
@@ -10814,6 +10829,7 @@ var dependencyRecoveryLedger = new DependencyRecoveryLedger();
10814
10829
  var unstableLatchUnreported = /* @__PURE__ */ new Set();
10815
10830
  var unstableLatchReportInFlight = /* @__PURE__ */ new Set();
10816
10831
  var killPausedCodeNames = /* @__PURE__ */ new Set();
10832
+ var notRunningCodeNames = /* @__PURE__ */ new Set();
10817
10833
  var BACK_ONLINE_GREETING_GUIDANCE = " When you reconnect, if you tell anyone you are back, start that message with a \u{1F44B} wave emoji and do not use a \u{1F7E2} green-light emoji.";
10818
10834
  function maybeAutoResume(agent) {
10819
10835
  const codeName = agent.code_name;
@@ -11268,6 +11284,28 @@ var DEFER_LOG_THROTTLE_MS = 6e5;
11268
11284
  var deferLogThrottle = /* @__PURE__ */ new Map();
11269
11285
  var lastInboundMs = /* @__PURE__ */ new Map();
11270
11286
  var pendingDayRolloverReset = /* @__PURE__ */ new Set();
11287
+ var dayRolloverInboundHold = /* @__PURE__ */ new Map();
11288
+ var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
11289
+ async function channelInboundActivityAgeSecondsFor(codeName) {
11290
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-Z7IFPQCU.js");
11291
+ const newest = newestPendingInboundActivityMtimeMs(dirname9(paneLogPath(codeName)));
11292
+ if (newest === null) return null;
11293
+ return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
11294
+ }
11295
+ function inboundHoldMinutes(prev, nowMs, episodeGapMs = INBOUND_HOLD_EPISODE_GAP_MS) {
11296
+ if (!prev) return 0;
11297
+ const gap = Math.max(0, nowMs - prev.lastHeldMs);
11298
+ if (gap > episodeGapMs) return 0;
11299
+ return (prev.accumulatedMs + gap) / 6e4;
11300
+ }
11301
+ function creditInboundHold(prev, nowMs, episodeGapMs = INBOUND_HOLD_EPISODE_GAP_MS) {
11302
+ const gap = prev ? Math.max(0, nowMs - prev.lastHeldMs) : Infinity;
11303
+ const accumulatedMs = !prev || gap > episodeGapMs ? 0 : prev.accumulatedMs + gap;
11304
+ return { accumulatedMs, lastHeldMs: nowMs };
11305
+ }
11306
+ function inboundHeldMinutesFor(codeName) {
11307
+ return inboundHoldMinutes(dayRolloverInboundHold.get(codeName), Date.now());
11308
+ }
11271
11309
  var consecutiveWedgeCycles = /* @__PURE__ */ new Map();
11272
11310
  var wedgeExemptionLogged = /* @__PURE__ */ new Set();
11273
11311
  var wedgeRestartsByCard = /* @__PURE__ */ new Map();
@@ -11282,7 +11320,15 @@ function inboundAgeSecondsFor(codeName) {
11282
11320
  function decideDayRolloverAction(i) {
11283
11321
  if (!i.staleForToday || !i.sessionHealthy || !i.hasCurrent) return "none";
11284
11322
  if (i.idle) return "defer-idle";
11285
- return i.overdueMin >= i.graceMin ? "force-reset" : "busy-wait";
11323
+ if (i.overdueMin < i.graceMin) return "busy-wait";
11324
+ const age = i.recentInboundAgeSec;
11325
+ const graceSec = i.inboundGraceSec ?? 0;
11326
+ const heldMin = i.inboundDeferredMin ?? 0;
11327
+ const maxHoldMin = i.inboundDeferMaxMin ?? 0;
11328
+ if (age !== null && age !== void 0 && age < graceSec && heldMin < maxHoldMin) {
11329
+ return "inbound-wait";
11330
+ }
11331
+ return "force-reset";
11286
11332
  }
11287
11333
  function classifyLazyDayRolloverReset(i) {
11288
11334
  if (!i.flagged) return "skip";
@@ -11880,7 +11926,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
11880
11926
  var lastVersionCheckAt = 0;
11881
11927
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
11882
11928
  var lastResponsivenessProbeAt = 0;
11883
- var agtCliVersion = true ? "0.28.607" : "dev";
11929
+ var agtCliVersion = true ? "0.28.609" : "dev";
11884
11930
  function resolveBrewPath(execFileSync3) {
11885
11931
  try {
11886
11932
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -13418,7 +13464,7 @@ async function pollCycle() {
13418
13464
  collectPanelessActivityProbes,
13419
13465
  getResponsivenessIntervalMs,
13420
13466
  occupancyQualificationClassifications
13421
- } = await import("../responsiveness-probe-KQGY6RMW.js");
13467
+ } = await import("../responsiveness-probe-Z7IFPQCU.js");
13422
13468
  const probeIntervalMs = getResponsivenessIntervalMs();
13423
13469
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
13424
13470
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -13434,12 +13480,22 @@ async function pollCycle() {
13434
13480
  const drainedBuckets = /* @__PURE__ */ new Map();
13435
13481
  const drainedCodeNames = /* @__PURE__ */ new Set();
13436
13482
  const qualifierMode = occupancyQualifierMode();
13483
+ const measuredCodeNames = /* @__PURE__ */ new Set();
13437
13484
  const takeBuckets = (codeName) => {
13438
13485
  if (drainedCodeNames.has(codeName)) return { buckets: [], classifications: null };
13439
13486
  drainedCodeNames.add(codeName);
13440
13487
  const nowMs = Date.now();
13441
13488
  const raw = sharedBusyBuckets.drainClosed(codeName, nowMs);
13442
- if (raw.length === 0) return { buckets: [], classifications: null };
13489
+ if (raw.length === 0) {
13490
+ if (rostersMeasuredZero(
13491
+ qualifierMode,
13492
+ hasFreshPaneObservation(codeName, nowMs),
13493
+ !notRunningCodeNames.has(codeName)
13494
+ )) {
13495
+ measuredCodeNames.add(codeName);
13496
+ }
13497
+ return { buckets: [], classifications: null };
13498
+ }
13443
13499
  let q;
13444
13500
  try {
13445
13501
  q = qualifyBuckets(raw, collectQualifyingTurns(codeName, nowMs), qualifierMode, nowMs);
@@ -13483,8 +13539,13 @@ async function pollCycle() {
13483
13539
  });
13484
13540
  }
13485
13541
  }
13486
- if (probes.length > 0) {
13487
- void api.post("/host/responsiveness-probe", { host_id: hostId, probes }).catch((err) => {
13542
+ const occupancyMeasuredCodeNames = [...measuredCodeNames];
13543
+ if (probes.length > 0 || occupancyMeasuredCodeNames.length > 0) {
13544
+ void api.post("/host/responsiveness-probe", {
13545
+ host_id: hostId,
13546
+ probes,
13547
+ ...occupancyMeasuredCodeNames.length > 0 ? { occupancy_measured_code_names: occupancyMeasuredCodeNames } : {}
13548
+ }).catch((err) => {
13488
13549
  for (const [codeName, count] of drainedGiveUps) {
13489
13550
  creditWatchdogGiveUpCount(codeName, count);
13490
13551
  }
@@ -13509,7 +13570,7 @@ async function pollCycle() {
13509
13570
  collectResponsivenessProbes,
13510
13571
  livePendingInboundOldestAgeSeconds,
13511
13572
  parkPendingInbound
13512
- } = await import("../responsiveness-probe-KQGY6RMW.js");
13573
+ } = await import("../responsiveness-probe-Z7IFPQCU.js");
13513
13574
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
13514
13575
  const wedgeNow = /* @__PURE__ */ new Date();
13515
13576
  const liveAgents = agentState.persistentSessionAgents;
@@ -14118,6 +14179,8 @@ async function processAgent(agent, agentStates, managedToolkits) {
14118
14179
  agent.enforcement_text ?? null
14119
14180
  );
14120
14181
  const previousKnownStatus = agentState.knownStatuses.get(agent.agent_id);
14182
+ if (agent.status === "active") notRunningCodeNames.delete(agent.code_name);
14183
+ else notRunningCodeNames.add(agent.code_name);
14121
14184
  agentState.agentDisplayNames.set(agent.code_name, agent.display_name);
14122
14185
  agentState.codeNameToAgentId.set(agent.code_name, agent.agent_id);
14123
14186
  maybeClearStaleTrip(agent);
@@ -16406,6 +16469,8 @@ var lastMcpFailedBannerCount = /* @__PURE__ */ new Map();
16406
16469
  var lastModelApiErrorSig = /* @__PURE__ */ new Map();
16407
16470
  var lastSessionAuthDetail = /* @__PURE__ */ new Map();
16408
16471
  var DAY_ROLLOVER_FORCE_GRACE_MIN = 30;
16472
+ var DAY_ROLLOVER_INBOUND_GRACE_SEC = 60;
16473
+ var DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN = 10;
16409
16474
  var persistentSessionStuckTracker = new PersistentSessionStuckTracker();
16410
16475
  var claudeAuthTupleBySession = /* @__PURE__ */ new Map();
16411
16476
  var opencodeCredentialFingerprintBySession = /* @__PURE__ */ new Map();
@@ -16662,13 +16727,19 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
16662
16727
  const rolloverSessionHealthy = isSessionHealthy(codeName);
16663
16728
  const rolloverCurrent = staleForToday && rolloverSessionHealthy ? peekCurrentSession(codeName) : null;
16664
16729
  const overdueMin = rolloverCurrent ? minutesSinceLocalMidnight(/* @__PURE__ */ new Date(), agentTimezone) : 0;
16730
+ const rolloverMayForce = staleForToday && rolloverSessionHealthy && rolloverCurrent !== null && overdueMin >= DAY_ROLLOVER_FORCE_GRACE_MIN;
16731
+ const rolloverInboundAgeSec = rolloverMayForce ? await channelInboundActivityAgeSecondsFor(codeName) : null;
16665
16732
  const rolloverDecision = decideDayRolloverAction({
16666
16733
  staleForToday,
16667
16734
  sessionHealthy: rolloverSessionHealthy,
16668
16735
  hasCurrent: rolloverCurrent !== null,
16669
16736
  idle: rolloverCurrent ? isAgentIdle(projectDir, rolloverCurrent.sessionId) : false,
16670
16737
  overdueMin,
16671
- graceMin: DAY_ROLLOVER_FORCE_GRACE_MIN
16738
+ graceMin: DAY_ROLLOVER_FORCE_GRACE_MIN,
16739
+ recentInboundAgeSec: rolloverInboundAgeSec,
16740
+ inboundGraceSec: DAY_ROLLOVER_INBOUND_GRACE_SEC,
16741
+ inboundDeferredMin: inboundHeldMinutesFor(codeName),
16742
+ inboundDeferMaxMin: DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN
16672
16743
  });
16673
16744
  if (rolloverDecision === "defer-idle" && rolloverCurrent) {
16674
16745
  if (!pendingDayRolloverReset.has(codeName)) {
@@ -16684,14 +16755,27 @@ async function ensurePersistentSession(agent, tasks, boardItems, refreshData) {
16684
16755
  stopPersistentSessionAndForgetMcpBaseline(codeName, "day-rollover");
16685
16756
  agentState.persistentSessionAgents.delete(codeName);
16686
16757
  pendingDayRolloverReset.delete(codeName);
16758
+ dayRolloverInboundHold.delete(codeName);
16687
16759
  restartTrigger = "day-rollover";
16688
16760
  dayRolloverForced = true;
16761
+ } else if (rolloverDecision === "inbound-wait" && rolloverCurrent) {
16762
+ const priorHold = dayRolloverInboundHold.get(codeName);
16763
+ dayRolloverInboundHold.set(codeName, creditInboundHold(priorHold, Date.now()));
16764
+ if (!priorHold) {
16765
+ log(
16766
+ `[persistent-session] Day rollover for '${codeName}' HELD \u2014 channel inbound ${rolloverInboundAgeSec}s ago (grace ${DAY_ROLLOVER_INBOUND_GRACE_SEC}s); not interrupting an agent mid-handoff, will force within ${DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN}m regardless [ENG-8881]`
16767
+ );
16768
+ }
16769
+ dayRolloverDeferred = true;
16689
16770
  } else if (rolloverDecision === "busy-wait" && rolloverCurrent) {
16690
16771
  log(
16691
16772
  `[persistent-session] Day rollover for '${codeName}' deferred \u2014 agent still active on session ${rolloverCurrent.sessionId} (${overdueMin}m past boundary, will force at ${DAY_ROLLOVER_FORCE_GRACE_MIN}m)`
16692
16773
  );
16693
16774
  dayRolloverDeferred = true;
16694
16775
  }
16776
+ if (rolloverDecision !== "inbound-wait") {
16777
+ dayRolloverInboundHold.delete(codeName);
16778
+ }
16695
16779
  if (restartTrigger === "day-rollover") {
16696
16780
  rotatePaneLogForDayRollover(codeName, log, agentTimezone);
16697
16781
  }
@@ -18711,6 +18795,8 @@ process.on("disconnect", () => {
18711
18795
  export {
18712
18796
  BACK_ONLINE_GREETING_GUIDANCE,
18713
18797
  DAY_ROLLOVER_FORCE_GRACE_MIN,
18798
+ DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN,
18799
+ DAY_ROLLOVER_INBOUND_GRACE_SEC,
18714
18800
  applyRestartAcks,
18715
18801
  cancelKanbanNoticeOnDrain,
18716
18802
  classifyLazyDayRolloverReset,
@@ -18718,12 +18804,14 @@ export {
18718
18804
  claudeCodeUpgradeThrottled,
18719
18805
  claudeManagedSettingsPath,
18720
18806
  createManagedToolkitReader,
18807
+ creditInboundHold,
18721
18808
  dashboardRestartBreakerReason,
18722
18809
  decideDayRolloverAction,
18723
18810
  ensureClaudeManagedSettings,
18724
18811
  extractCharterSlackPeers,
18725
18812
  extractCharterTelegramPeers,
18726
18813
  hasRevokedResiduals,
18814
+ inboundHoldMinutes,
18727
18815
  isOlderSemverTuple,
18728
18816
  isPrereleaseVersion,
18729
18817
  markAgentForFreshMemorySync,