@integrity-labs/agt-cli 0.27.75 → 0.27.77

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.
@@ -21,7 +21,7 @@ import {
21
21
  stopPersistentSession,
22
22
  takeZombieDetection,
23
23
  writePersistentClaudeWrapper
24
- } from "./chunk-VTAXNSGS.js";
24
+ } from "./chunk-FAR2FJBQ.js";
25
25
  import "./chunk-5SWHKUL3.js";
26
26
  import "./chunk-XWVM4KPK.js";
27
27
  export {
@@ -48,4 +48,4 @@ export {
48
48
  takeZombieDetection,
49
49
  writePersistentClaudeWrapper
50
50
  };
51
- //# sourceMappingURL=persistent-session-CXKB7FU3.js.map
51
+ //# sourceMappingURL=persistent-session-4HYXVGKO.js.map
@@ -0,0 +1,73 @@
1
+ import {
2
+ paneLogPath
3
+ } from "./chunk-FAR2FJBQ.js";
4
+ import "./chunk-5SWHKUL3.js";
5
+ import "./chunk-XWVM4KPK.js";
6
+
7
+ // src/lib/responsiveness-probe.ts
8
+ import { readdirSync, statSync } from "fs";
9
+ import { dirname, join } from "path";
10
+ var DEFAULT_INTERVAL_MS = 5 * 60 * 1e3;
11
+ function getResponsivenessIntervalMs() {
12
+ const raw = process.env.AUGMENTED_RESPONSIVENESS_INTERVAL_MS;
13
+ if (!raw) return DEFAULT_INTERVAL_MS;
14
+ const parsed = Number.parseInt(raw, 10);
15
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INTERVAL_MS;
16
+ }
17
+ function oldestPendingInboundMtimeMs(agentHomeDir) {
18
+ let oldest = null;
19
+ let entries;
20
+ try {
21
+ entries = readdirSync(agentHomeDir, { withFileTypes: true });
22
+ } catch {
23
+ return null;
24
+ }
25
+ for (const entry of entries) {
26
+ if (!entry.isDirectory() || !entry.name.endsWith("-pending-inbound")) continue;
27
+ const dir = join(agentHomeDir, entry.name);
28
+ let files;
29
+ try {
30
+ files = readdirSync(dir);
31
+ } catch {
32
+ continue;
33
+ }
34
+ for (const file of files) {
35
+ try {
36
+ const mtimeMs = statSync(join(dir, file)).mtimeMs;
37
+ if (oldest === null || mtimeMs < oldest) oldest = mtimeMs;
38
+ } catch {
39
+ }
40
+ }
41
+ }
42
+ return oldest;
43
+ }
44
+ function collectResponsivenessProbes(codeNames, now = /* @__PURE__ */ new Date()) {
45
+ const nowMs = now.getTime();
46
+ const results = [];
47
+ for (const codeName of codeNames) {
48
+ try {
49
+ const panePath = paneLogPath(codeName);
50
+ const mtimeMs = statSync(panePath).mtimeMs;
51
+ const ageSeconds = Math.max(0, Math.floor((nowMs - mtimeMs) / 1e3));
52
+ const result = {
53
+ code_name: codeName,
54
+ pane_activity_age_seconds: ageSeconds
55
+ };
56
+ const oldestMarkerMs = oldestPendingInboundMtimeMs(dirname(panePath));
57
+ if (oldestMarkerMs !== null) {
58
+ result.pending_inbound_oldest_age_seconds = Math.max(
59
+ 0,
60
+ Math.floor((nowMs - oldestMarkerMs) / 1e3)
61
+ );
62
+ }
63
+ results.push(result);
64
+ } catch {
65
+ }
66
+ }
67
+ return results;
68
+ }
69
+ export {
70
+ collectResponsivenessProbes,
71
+ getResponsivenessIntervalMs
72
+ };
73
+ //# sourceMappingURL=responsiveness-probe-NUGYDDMS.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/responsiveness-probe.ts"],"sourcesContent":["/**\n * ENG-5399 — Tier 1 responsiveness probe (manager-side).\n *\n * Cheap, fast-cadence canary that catches \"agent went silent\" inside\n * minutes, well before the existing synthetic-probe cron's ~35 min\n * staleness window (`SyntheticReplyAgeSeconds`, ENG-5122).\n *\n * Mechanism: for each managed agent, read the mtime of the agent's\n * `pane.log` and report `now - mtime` as `PaneActivityAgeSeconds` via\n * a new `/host/responsiveness-probe` endpoint. `pane.log` is the\n * tmux pipe-pane sink set up by `setupPaneLog()` — any visible\n * activity (assistant turns, tool calls, in-place progress\n * heartbeats) bumps its mtime. A silent agent has a steadily\n * climbing age that lands in CloudWatch and trips a per-agent alarm.\n *\n * ENG-6017 adds a second per-agent signal on the same cadence:\n * `pending_inbound_oldest_age_seconds` — the age of the oldest marker\n * file across the agent's `*-pending-inbound/` directories (written by\n * the channel MCP servers for inbounds awaiting delivery). This is the\n * one artifact of the \"message typed but never submitted\" failure mode\n * that every other canary is blind to: in the koda incident\n * (2026-06-04) an operator Slack DM sat undelivered for 40+ minutes\n * while pane-activity stayed fresh (health checks), synthetic probes\n * were answered by the one-shot fallback, and heartbeat/session-alive\n * only reflect manager health. The field is OMITTED (not zero) when the\n * agent has no pending-inbound markers — the API treats absent as\n * \"no signal\", never as \"healthy\" (absent-vs-zero matters for\n * mixed-version fleets where old CLIs don't report it at all).\n *\n * Run from `pollCycle()` in `manager-worker.ts` on a configurable\n * interval (default 5 min via `AUGMENTED_RESPONSIVENESS_INTERVAL_MS`).\n */\n\nimport { readdirSync, statSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { paneLogPath } from './persistent-session.js';\n\nexport interface ResponsivenessProbeResult {\n code_name: string;\n pane_activity_age_seconds: number;\n /**\n * ENG-6017: age (s) of the oldest marker file across the agent's\n * `*-pending-inbound/` directories. Omitted when no markers exist —\n * absent means \"no signal\", NOT \"zero / healthy\".\n */\n pending_inbound_oldest_age_seconds?: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 5 * 60 * 1000;\n\nexport function getResponsivenessIntervalMs(): number {\n const raw = process.env.AUGMENTED_RESPONSIVENESS_INTERVAL_MS;\n if (!raw) return DEFAULT_INTERVAL_MS;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INTERVAL_MS;\n}\n\n/**\n * ENG-6017: oldest pending-inbound marker mtime (ms epoch) for an agent,\n * or null when the agent has no markers / no pending-inbound dirs.\n *\n * The channel MCP servers (slack-channel, telegram-channel, …) write one\n * marker file per inbound into `~/.augmented/<codeName>/<channel>-pending-\n * inbound/` and clear it when the agent acknowledges the message. The\n * directory layout is the contract here — read-only, no IPC with the MCP\n * (the MCP and CLI release independently; file mtimes need no protocol).\n */\nfunction oldestPendingInboundMtimeMs(agentHomeDir: string): number | null {\n let oldest: number | null = null;\n let entries;\n try {\n entries = readdirSync(agentHomeDir, { withFileTypes: true });\n } catch {\n return null; // agent home missing — nothing to report\n }\n for (const entry of entries) {\n if (!entry.isDirectory() || !entry.name.endsWith('-pending-inbound')) continue;\n const dir = join(agentHomeDir, entry.name);\n let files;\n try {\n files = readdirSync(dir);\n } catch {\n continue;\n }\n for (const file of files) {\n try {\n const mtimeMs = statSync(join(dir, file)).mtimeMs;\n if (oldest === null || mtimeMs < oldest) oldest = mtimeMs;\n } catch {\n // Marker drained between readdir and stat — that's the happy path.\n }\n }\n }\n return oldest;\n}\n\n/**\n * Compute the pane.log age for each agent. Missing or unreadable\n * pane.log returns null — the caller should drop those entries\n * rather than fabricate a \"fresh\" or \"ancient\" value. A missing\n * file means the agent has never spawned in this manager generation,\n * which is a separate problem covered by SessionAliveAgeSeconds.\n */\nexport function collectResponsivenessProbes(\n codeNames: string[],\n now: Date = new Date(),\n): ResponsivenessProbeResult[] {\n const nowMs = now.getTime();\n const results: ResponsivenessProbeResult[] = [];\n for (const codeName of codeNames) {\n try {\n const panePath = paneLogPath(codeName);\n const mtimeMs = statSync(panePath).mtimeMs;\n const ageSeconds = Math.max(0, Math.floor((nowMs - mtimeMs) / 1000));\n const result: ResponsivenessProbeResult = {\n code_name: codeName,\n pane_activity_age_seconds: ageSeconds,\n };\n // ENG-6017: piggyback the pending-inbound drain-age scan on the same\n // cadence. Field omitted (not 0) when there are no markers.\n const oldestMarkerMs = oldestPendingInboundMtimeMs(dirname(panePath));\n if (oldestMarkerMs !== null) {\n result.pending_inbound_oldest_age_seconds = Math.max(\n 0,\n Math.floor((nowMs - oldestMarkerMs) / 1000),\n );\n }\n results.push(result);\n } catch {\n // No pane.log yet (fresh agent, never spawned) — skip. The\n // session-alive monitor already covers the \"should be running\n // but isn't\" case.\n }\n }\n return results;\n}\n"],"mappings":";;;;;;;AAiCA,SAAS,aAAa,gBAAgB;AACtC,SAAS,SAAS,YAAY;AAc9B,IAAM,sBAAsB,IAAI,KAAK;AAE9B,SAAS,8BAAsC;AACpD,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,SAAS,OAAO,SAAS,KAAK,EAAE;AACtC,SAAO,OAAO,SAAS,MAAM,KAAK,SAAS,IAAI,SAAS;AAC1D;AAYA,SAAS,4BAA4B,cAAqC;AACxE,MAAI,SAAwB;AAC5B,MAAI;AACJ,MAAI;AACF,cAAU,YAAY,cAAc,EAAE,eAAe,KAAK,CAAC;AAAA,EAC7D,QAAQ;AACN,WAAO;AAAA,EACT;AACA,aAAW,SAAS,SAAS;AAC3B,QAAI,CAAC,MAAM,YAAY,KAAK,CAAC,MAAM,KAAK,SAAS,kBAAkB,EAAG;AACtE,UAAM,MAAM,KAAK,cAAc,MAAM,IAAI;AACzC,QAAI;AACJ,QAAI;AACF,cAAQ,YAAY,GAAG;AAAA,IACzB,QAAQ;AACN;AAAA,IACF;AACA,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAM,UAAU,SAAS,KAAK,KAAK,IAAI,CAAC,EAAE;AAC1C,YAAI,WAAW,QAAQ,UAAU,OAAQ,UAAS;AAAA,MACpD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AASO,SAAS,4BACd,WACA,MAAY,oBAAI,KAAK,GACQ;AAC7B,QAAM,QAAQ,IAAI,QAAQ;AAC1B,QAAM,UAAuC,CAAC;AAC9C,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,YAAM,WAAW,YAAY,QAAQ;AACrC,YAAM,UAAU,SAAS,QAAQ,EAAE;AACnC,YAAM,aAAa,KAAK,IAAI,GAAG,KAAK,OAAO,QAAQ,WAAW,GAAI,CAAC;AACnE,YAAM,SAAoC;AAAA,QACxC,WAAW;AAAA,QACX,2BAA2B;AAAA,MAC7B;AAGA,YAAM,iBAAiB,4BAA4B,QAAQ,QAAQ,CAAC;AACpE,UAAI,mBAAmB,MAAM;AAC3B,eAAO,qCAAqC,KAAK;AAAA,UAC/C;AAAA,UACA,KAAK,OAAO,QAAQ,kBAAkB,GAAI;AAAA,QAC5C;AAAA,MACF;AACA,cAAQ,KAAK,MAAM;AAAA,IACrB,QAAQ;AAAA,IAIR;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.27.75",
3
+ "version": "0.27.77",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {
@@ -1,33 +0,0 @@
1
- import {
2
- paneLogPath
3
- } from "./chunk-VTAXNSGS.js";
4
- import "./chunk-5SWHKUL3.js";
5
- import "./chunk-XWVM4KPK.js";
6
-
7
- // src/lib/responsiveness-probe.ts
8
- import { statSync } from "fs";
9
- var DEFAULT_INTERVAL_MS = 5 * 60 * 1e3;
10
- function getResponsivenessIntervalMs() {
11
- const raw = process.env.AUGMENTED_RESPONSIVENESS_INTERVAL_MS;
12
- if (!raw) return DEFAULT_INTERVAL_MS;
13
- const parsed = Number.parseInt(raw, 10);
14
- return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INTERVAL_MS;
15
- }
16
- function collectResponsivenessProbes(codeNames, now = /* @__PURE__ */ new Date()) {
17
- const nowMs = now.getTime();
18
- const results = [];
19
- for (const codeName of codeNames) {
20
- try {
21
- const mtimeMs = statSync(paneLogPath(codeName)).mtimeMs;
22
- const ageSeconds = Math.max(0, Math.floor((nowMs - mtimeMs) / 1e3));
23
- results.push({ code_name: codeName, pane_activity_age_seconds: ageSeconds });
24
- } catch {
25
- }
26
- }
27
- return results;
28
- }
29
- export {
30
- collectResponsivenessProbes,
31
- getResponsivenessIntervalMs
32
- };
33
- //# sourceMappingURL=responsiveness-probe-EKB5VBCX.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/lib/responsiveness-probe.ts"],"sourcesContent":["/**\n * ENG-5399 — Tier 1 responsiveness probe (manager-side).\n *\n * Cheap, fast-cadence canary that catches \"agent went silent\" inside\n * minutes, well before the existing synthetic-probe cron's ~35 min\n * staleness window (`SyntheticReplyAgeSeconds`, ENG-5122).\n *\n * Mechanism: for each managed agent, read the mtime of the agent's\n * `pane.log` and report `now - mtime` as `PaneActivityAgeSeconds` via\n * a new `/host/responsiveness-probe` endpoint. `pane.log` is the\n * tmux pipe-pane sink set up by `setupPaneLog()` — any visible\n * activity (assistant turns, tool calls, in-place progress\n * heartbeats) bumps its mtime. A silent agent has a steadily\n * climbing age that lands in CloudWatch and trips a per-agent alarm.\n *\n * Run from `pollCycle()` in `manager-worker.ts` on a configurable\n * interval (default 5 min via `AUGMENTED_RESPONSIVENESS_INTERVAL_MS`).\n */\n\nimport { statSync } from 'node:fs';\nimport { paneLogPath } from './persistent-session.js';\n\nexport interface ResponsivenessProbeResult {\n code_name: string;\n pane_activity_age_seconds: number;\n}\n\nconst DEFAULT_INTERVAL_MS = 5 * 60 * 1000;\n\nexport function getResponsivenessIntervalMs(): number {\n const raw = process.env.AUGMENTED_RESPONSIVENESS_INTERVAL_MS;\n if (!raw) return DEFAULT_INTERVAL_MS;\n const parsed = Number.parseInt(raw, 10);\n return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_INTERVAL_MS;\n}\n\n/**\n * Compute the pane.log age for each agent. Missing or unreadable\n * pane.log returns null — the caller should drop those entries\n * rather than fabricate a \"fresh\" or \"ancient\" value. A missing\n * file means the agent has never spawned in this manager generation,\n * which is a separate problem covered by SessionAliveAgeSeconds.\n */\nexport function collectResponsivenessProbes(\n codeNames: string[],\n now: Date = new Date(),\n): ResponsivenessProbeResult[] {\n const nowMs = now.getTime();\n const results: ResponsivenessProbeResult[] = [];\n for (const codeName of codeNames) {\n try {\n const mtimeMs = statSync(paneLogPath(codeName)).mtimeMs;\n const ageSeconds = Math.max(0, Math.floor((nowMs - mtimeMs) / 1000));\n results.push({ code_name: codeName, pane_activity_age_seconds: ageSeconds });\n } catch {\n // No pane.log yet (fresh agent, never spawned) — skip. The\n // session-alive monitor already covers the \"should be running\n // but isn't\" case.\n }\n }\n return results;\n}\n"],"mappings":";;;;;;;AAmBA,SAAS,gBAAgB;AAQzB,IAAM,sBAAsB,IAAI,KAAK;AAE9B,SAAS,8BAAsC;AACpD,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,CAAC,IAAK,QAAO;AACjB,QAAM,SAAS,OAAO,SAAS,KAAK,EAAE;AACtC,SAAO,OAAO,SAAS,MAAM,KAAK,SAAS,IAAI,SAAS;AAC1D;AASO,SAAS,4BACd,WACA,MAAY,oBAAI,KAAK,GACQ;AAC7B,QAAM,QAAQ,IAAI,QAAQ;AAC1B,QAAM,UAAuC,CAAC;AAC9C,aAAW,YAAY,WAAW;AAChC,QAAI;AACF,YAAM,UAAU,SAAS,YAAY,QAAQ,CAAC,EAAE;AAChD,YAAM,aAAa,KAAK,IAAI,GAAG,KAAK,OAAO,QAAQ,WAAW,GAAI,CAAC;AACnE,cAAQ,KAAK,EAAE,WAAW,UAAU,2BAA2B,WAAW,CAAC;AAAA,IAC7E,QAAQ;AAAA,IAIR;AAAA,EACF;AACA,SAAO;AACT;","names":[]}