@integrity-labs/agt-cli 0.28.714 → 0.28.716

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.
@@ -6,13 +6,14 @@ import {
6
6
  buildOAuthRemoteMcpProxyEntry,
7
7
  buildRemoteMcpEntry,
8
8
  expandTemplateVars,
9
+ getProjectDir,
9
10
  isolationMode,
10
11
  log,
11
12
  mergeEnvIntegrationsContent,
12
13
  parseEnvFileEntries,
13
14
  parseEnvIntegrations,
14
15
  shellQuote
15
- } from "./chunk-F6AZ6KPI.js";
16
+ } from "./chunk-ILDRNSOB.js";
16
17
  import {
17
18
  BIND_FAILURE_QUARANTINE_THRESHOLD,
18
19
  INTEGRATIONS_SECTION_END,
@@ -50,6 +51,7 @@ import {
50
51
  probeComposioMcpToolCall,
51
52
  probeHttpProvider,
52
53
  probeMcpHttp,
54
+ readDailySessionPin,
53
55
  readRemoteMcpAuthConfig,
54
56
  registerFramework,
55
57
  remoteMcpConnectionScopedEnvVar,
@@ -57,9 +59,10 @@ import {
57
59
  remoteMcpServerKey,
58
60
  resolveAvatarEnvUrl,
59
61
  resolveConnectivityProbe,
62
+ sessionTranscriptDir,
60
63
  worseConnectivityOutcome,
61
64
  wrapScheduledTaskPrompt
62
- } from "./chunk-FM63TWR3.js";
65
+ } from "./chunk-LHYYO4NY.js";
63
66
  import {
64
67
  parsePsRows
65
68
  } from "./chunk-XWVM4KPK.js";
@@ -939,11 +942,11 @@ function decodeValue(buf, offset) {
939
942
  if (end > buf.length)
940
943
  throw new CborDecodeError("cbor: truncated text string");
941
944
  const bytes = buf.subarray(head.next, end);
942
- const str = bytes.toString("utf8");
943
- if (!Buffer.from(str, "utf8").equals(bytes)) {
945
+ const str2 = bytes.toString("utf8");
946
+ if (!Buffer.from(str2, "utf8").equals(bytes)) {
944
947
  throw new CborDecodeError("cbor: invalid UTF-8 in text string");
945
948
  }
946
- return { value: str, next: end };
949
+ return { value: str2, next: end };
947
950
  }
948
951
  case MAJOR_ARRAY: {
949
952
  const arr = [];
@@ -1589,7 +1592,7 @@ function writeEnvIntegrationsForAgent(codeName, args) {
1589
1592
  } catch {
1590
1593
  }
1591
1594
  try {
1592
- const projectDir = getProjectDir(codeName);
1595
+ const projectDir = getProjectDir2(codeName);
1593
1596
  mkdirSync3(projectDir, { recursive: true });
1594
1597
  const dest = join3(projectDir, ".env.integrations");
1595
1598
  writeFileSync4(dest, content, { mode: SECRET_FILE_MODE });
@@ -1878,7 +1881,7 @@ function syncGitHubBrokerCredentialTooling(projectDir, enabled) {
1878
1881
  chmodSync4(shimPath, BROKER_SCRIPT_MODE);
1879
1882
  return buildGitCredentialEnv(helperPath);
1880
1883
  }
1881
- function getProjectDir(codeName) {
1884
+ function getProjectDir2(codeName) {
1882
1885
  return join3(getAgentDir(codeName), "project");
1883
1886
  }
1884
1887
  function getScratchDir(codeName) {
@@ -1954,7 +1957,7 @@ function isFreshWithin(path, cutoff) {
1954
1957
  }
1955
1958
  function syncMcpToProject(codeName) {
1956
1959
  const agentDir = getAgentDir(codeName);
1957
- const projectDir = getProjectDir(codeName);
1960
+ const projectDir = getProjectDir2(codeName);
1958
1961
  const provisionMcpPath = join3(agentDir, "provision", ".mcp.json");
1959
1962
  const projectMcpPath = join3(projectDir, ".mcp.json");
1960
1963
  try {
@@ -2001,7 +2004,7 @@ function readIntegrationsSummaryForAgent(codeName) {
2001
2004
  }
2002
2005
  function renderChannelMessageHandlerForAgent(codeName) {
2003
2006
  const agentDir = getAgentDir(codeName);
2004
- const projectDir = getProjectDir(codeName);
2007
+ const projectDir = getProjectDir2(codeName);
2005
2008
  const provisionMcpPath = join3(agentDir, "provision", ".mcp.json");
2006
2009
  let mcpServerKeys;
2007
2010
  try {
@@ -2089,7 +2092,7 @@ function ensureWorkspaceTrusted(projectDir) {
2089
2092
  }
2090
2093
  }
2091
2094
  function deployArtifactsToProject(codeName, provisionDir) {
2092
- const projectDir = getProjectDir(codeName);
2095
+ const projectDir = getProjectDir2(codeName);
2093
2096
  mkdirSync3(projectDir, { recursive: true });
2094
2097
  ensureWorkspaceTrusted(projectDir);
2095
2098
  try {
@@ -2280,7 +2283,7 @@ function deployArtifactsToProject(codeName, provisionDir) {
2280
2283
  }
2281
2284
  }
2282
2285
  function provisionStopHook(codeName) {
2283
- const projectDir = getProjectDir(codeName);
2286
+ const projectDir = getProjectDir2(codeName);
2284
2287
  const claudeDir = join3(projectDir, ".claude");
2285
2288
  mkdirSync3(claudeDir, { recursive: true });
2286
2289
  const hookScriptPath = join3(claudeDir, "agt-stop-hook.sh");
@@ -3209,7 +3212,7 @@ function provisionStopHook(codeName) {
3209
3212
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
3210
3213
  }
3211
3214
  function provisionIsolationHook(codeName, agentId) {
3212
- const projectDir = getProjectDir(codeName);
3215
+ const projectDir = getProjectDir2(codeName);
3213
3216
  const claudeDir = join3(projectDir, ".claude");
3214
3217
  mkdirSync3(claudeDir, { recursive: true });
3215
3218
  const hasAgentId = agentId !== void 0;
@@ -3295,7 +3298,7 @@ function provisionIsolationHook(codeName, agentId) {
3295
3298
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
3296
3299
  }
3297
3300
  function provisionBacklogPullHook(codeName) {
3298
- const projectDir = getProjectDir(codeName);
3301
+ const projectDir = getProjectDir2(codeName);
3299
3302
  const claudeDir = join3(projectDir, ".claude");
3300
3303
  mkdirSync3(claudeDir, { recursive: true });
3301
3304
  const hookScriptPath = join3(claudeDir, "agt-backlog-pull-hook.sh");
@@ -3464,7 +3467,7 @@ exit 0
3464
3467
  return hookScriptPath;
3465
3468
  }
3466
3469
  function provisionAutoKanbanProgressHook(codeName) {
3467
- const projectDir = getProjectDir(codeName);
3470
+ const projectDir = getProjectDir2(codeName);
3468
3471
  const claudeDir = join3(projectDir, ".claude");
3469
3472
  mkdirSync3(claudeDir, { recursive: true });
3470
3473
  const hookScriptPath = join3(claudeDir, "agt-auto-kanban-progress-hook.sh");
@@ -3594,7 +3597,7 @@ exit 0
3594
3597
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
3595
3598
  }
3596
3599
  function provisionChannelProgressHook(codeName) {
3597
- const projectDir = getProjectDir(codeName);
3600
+ const projectDir = getProjectDir2(codeName);
3598
3601
  const claudeDir = join3(projectDir, ".claude");
3599
3602
  mkdirSync3(claudeDir, { recursive: true });
3600
3603
  const hookScriptPath = join3(claudeDir, "agt-channel-progress-hook.sh");
@@ -3687,7 +3690,7 @@ exit 0
3687
3690
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
3688
3691
  }
3689
3692
  function provisionOrientHook(codeName) {
3690
- const projectDir = getProjectDir(codeName);
3693
+ const projectDir = getProjectDir2(codeName);
3691
3694
  const claudeDir = join3(projectDir, ".claude");
3692
3695
  mkdirSync3(claudeDir, { recursive: true });
3693
3696
  const agentDir = getAgentDir(codeName);
@@ -3868,7 +3871,7 @@ function provisionOrientHook(codeName) {
3868
3871
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
3869
3872
  }
3870
3873
  function provisionPreCompactHook(codeName) {
3871
- const projectDir = getProjectDir(codeName);
3874
+ const projectDir = getProjectDir2(codeName);
3872
3875
  const claudeDir = join3(projectDir, ".claude");
3873
3876
  mkdirSync3(claudeDir, { recursive: true });
3874
3877
  const agentDir = getAgentDir(codeName);
@@ -4005,7 +4008,7 @@ function provisionPreCompactHook(codeName) {
4005
4008
  writeFileSync4(settingsPath, JSON.stringify(settings, null, 2));
4006
4009
  }
4007
4010
  function provisionSessionStateHook(codeName) {
4008
- const projectDir = getProjectDir(codeName);
4011
+ const projectDir = getProjectDir2(codeName);
4009
4012
  const claudeDir = join3(projectDir, ".claude");
4010
4013
  mkdirSync3(claudeDir, { recursive: true });
4011
4014
  const agentDir = getAgentDir(codeName);
@@ -4218,7 +4221,7 @@ function buildSettingsJson(input) {
4218
4221
  }
4219
4222
  };
4220
4223
  settings["model"] = agent.primary_model || "claude-opus-4-7";
4221
- const projectDir = getProjectDir(agent.code_name);
4224
+ const projectDir = getProjectDir2(agent.code_name);
4222
4225
  const agentDir = getAgentDir(agent.code_name);
4223
4226
  const homeDir = getHomeDir();
4224
4227
  const codenameAliasDir = join3(homeDir, ".augmented", agent.code_name);
@@ -4347,7 +4350,7 @@ ${integrationsBlock}`;
4347
4350
  }
4348
4351
  function renderAugmentedWorkerForAgent(codeName) {
4349
4352
  const agentDir = getAgentDir(codeName);
4350
- const projectDir = getProjectDir(codeName);
4353
+ const projectDir = getProjectDir2(codeName);
4351
4354
  const provisionMcpPath = join3(agentDir, "provision", ".mcp.json");
4352
4355
  let mcpServerKeys;
4353
4356
  try {
@@ -4481,7 +4484,7 @@ function buildMcpJson(input) {
4481
4484
  // getProjectDir (the ADR-0049 seam), not the MCP child's inherited
4482
4485
  // cwd, so the path stays correct if Claude Code ever spawns the
4483
4486
  // server from somewhere else.
4484
- XERO_EXPORT_DIR: join3(getProjectDir(input.agent.code_name), "xero-exports"),
4487
+ XERO_EXPORT_DIR: join3(getProjectDir2(input.agent.code_name), "xero-exports"),
4485
4488
  PATH: process.env["PATH"] ?? "",
4486
4489
  HOME: process.env["HOME"] ?? ""
4487
4490
  }
@@ -4493,7 +4496,7 @@ function buildMcpJson(input) {
4493
4496
  }
4494
4497
  const remoteOAuthProxyPaths = {
4495
4498
  proxyPath: join3(getHomeDir(), ".augmented", "_mcp", "remote-oauth-proxy.js"),
4496
- tokenFile: join3(getProjectDir(input.agent.code_name), ".env.integrations")
4499
+ tokenFile: join3(getProjectDir2(input.agent.code_name), ".env.integrations")
4497
4500
  };
4498
4501
  for (const integration of input.integrations ?? []) {
4499
4502
  const connectionKey = integration.connection_key;
@@ -4877,7 +4880,7 @@ ${sections}`
4877
4880
  ensureIdKeyedLayout(codeName, agentId);
4878
4881
  }
4879
4882
  const agentDir = getAgentDir(codeName);
4880
- const projectDir = getProjectDir(codeName);
4883
+ const projectDir = getProjectDir2(codeName);
4881
4884
  mkdirSync3(agentDir, { recursive: true });
4882
4885
  mkdirSync3(projectDir, { recursive: true });
4883
4886
  writeFileSync4(join3(agentDir, "registration.json"), JSON.stringify({
@@ -5254,7 +5257,7 @@ ${sections}`
5254
5257
  return;
5255
5258
  }
5256
5259
  syncMcpToProject(codeName);
5257
- const staleChannelsPath = join3(getProjectDir(codeName), ".mcp-channels.json");
5260
+ const staleChannelsPath = join3(getProjectDir2(codeName), ".mcp-channels.json");
5258
5261
  if (existsSync4(staleChannelsPath)) {
5259
5262
  try {
5260
5263
  rmSync2(staleChannelsPath, { force: true });
@@ -5590,7 +5593,7 @@ ${sections}`
5590
5593
  },
5591
5594
  seedProfileConfig(codeName) {
5592
5595
  const agentDir = getAgentDir(codeName);
5593
- const projectDir = getProjectDir(codeName);
5596
+ const projectDir = getProjectDir2(codeName);
5594
5597
  mkdirSync3(join3(agentDir, "provision"), { recursive: true });
5595
5598
  mkdirSync3(projectDir, { recursive: true });
5596
5599
  },
@@ -5677,7 +5680,7 @@ ${sections}`
5677
5680
  envUpdates[scoped] = value;
5678
5681
  }
5679
5682
  }
5680
- Object.assign(envUpdates, syncGitHubBrokerCredentialTooling(getProjectDir(codeName), decryptedIntegrations.some((i) => i.definition_id === "github" && i.credentialDelivery === "broker")));
5683
+ Object.assign(envUpdates, syncGitHubBrokerCredentialTooling(getProjectDir2(codeName), decryptedIntegrations.some((i) => i.definition_id === "github" && i.credentialDelivery === "broker")));
5681
5684
  writeEnvIntegrationsForAgent(codeName, {
5682
5685
  mode: "replace-preserving",
5683
5686
  updates: envUpdates
@@ -5734,7 +5737,7 @@ ${sections}`
5734
5737
  }
5735
5738
  const remoteOAuthProxyPaths = {
5736
5739
  proxyPath: join3(getHomeDir(), ".augmented", "_mcp", "remote-oauth-proxy.js"),
5737
- tokenFile: join3(getProjectDir(codeName), ".env.integrations")
5740
+ tokenFile: join3(getProjectDir2(codeName), ".env.integrations")
5738
5741
  };
5739
5742
  for (const integration of integrations) {
5740
5743
  const connectionKey = integration.connection_key;
@@ -5968,7 +5971,7 @@ ${sections}`
5968
5971
  }
5969
5972
  }
5970
5973
  }
5971
- const projectDir = getProjectDir(codeName);
5974
+ const projectDir = getProjectDir2(codeName);
5972
5975
  const claudeMdPath = join3(projectDir, "CLAUDE.md");
5973
5976
  try {
5974
5977
  const existing = readFileSync4(claudeMdPath, "utf-8");
@@ -6101,7 +6104,7 @@ ${sections}`
6101
6104
  const READ_ONLY_MODE = 292;
6102
6105
  const READ_WRITE_MODE = 420;
6103
6106
  const agentDir = getAgentDir(codeName);
6104
- const projectDir = getProjectDir(codeName);
6107
+ const projectDir = getProjectDir2(codeName);
6105
6108
  for (const baseDir of [join3(agentDir, "skills"), join3(projectDir, ".claude", "skills")]) {
6106
6109
  const skillDir = join3(baseDir, skillId);
6107
6110
  mkdirSync3(skillDir, { recursive: true });
@@ -6163,7 +6166,7 @@ ${sections}`
6163
6166
  provisionPluginFull(codeName, plugin, contextValues, options) {
6164
6167
  assertValidCodeName(codeName);
6165
6168
  assertValidCodeName(plugin.slug);
6166
- const projectDir = getProjectDir(codeName);
6169
+ const projectDir = getProjectDir2(codeName);
6167
6170
  const claudeDir = join3(projectDir, ".claude");
6168
6171
  mkdirSync3(claudeDir, { recursive: true });
6169
6172
  const sourceSpec = options?.scriptSource ?? `augmented-plugin:${plugin.slug}`;
@@ -6246,7 +6249,7 @@ ${sections}`
6246
6249
  executePluginHook(ctx) {
6247
6250
  assertValidCodeName(ctx.codeName);
6248
6251
  const agentRootDir = join3(getHomeDir(), ".augmented", ctx.codeName);
6249
- const projectDir = getProjectDir(ctx.codeName);
6252
+ const projectDir = getProjectDir2(ctx.codeName);
6250
6253
  mkdirSync3(agentRootDir, { recursive: true });
6251
6254
  mkdirSync3(projectDir, { recursive: true });
6252
6255
  const startedAt = Date.now();
@@ -6425,7 +6428,7 @@ function exchangeFailureKind(err) {
6425
6428
  }
6426
6429
 
6427
6430
  // src/lib/api-client.ts
6428
- var agtCliVersion = true ? "0.28.714" : "dev";
6431
+ var agtCliVersion = true ? "0.28.716" : "dev";
6429
6432
  var lastConfigHash = null;
6430
6433
  function setConfigHash(hash) {
6431
6434
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -6735,8 +6738,8 @@ function writeFlagsCache(path, file) {
6735
6738
  atomicWriteFileSync(path, `${JSON.stringify(file, null, 2)}
6736
6739
  `);
6737
6740
  }
6738
- function flagsCacheAgeSeconds(cache, path, now = /* @__PURE__ */ new Date()) {
6739
- const fromRecorded = Date.parse(cache.updated_at);
6741
+ function flagsCacheAgeSeconds(cache2, path, now = /* @__PURE__ */ new Date()) {
6742
+ const fromRecorded = Date.parse(cache2.updated_at);
6740
6743
  if (!Number.isNaN(fromRecorded)) {
6741
6744
  return Math.max(0, (now.getTime() - fromRecorded) / 1e3);
6742
6745
  }
@@ -8930,6 +8933,14 @@ function deriveMcpServerKey(input) {
8930
8933
  if (isDefaultRemoteMcpConnection(input.connectionKey)) return base;
8931
8934
  return remoteMcpServerKey(input.definitionId, input.connectionKey);
8932
8935
  }
8936
+ var SYSTEM_PATH_FLOOR = [
8937
+ "/usr/local/sbin",
8938
+ "/usr/local/bin",
8939
+ "/usr/sbin",
8940
+ "/usr/bin",
8941
+ "/sbin",
8942
+ "/bin"
8943
+ ];
8933
8944
  function buildProbeEnv(projectDir, agentId) {
8934
8945
  const probeEnv = { ...process.env };
8935
8946
  try {
@@ -8945,7 +8956,14 @@ function buildProbeEnv(projectDir, agentId) {
8945
8956
  try {
8946
8957
  const agentBinDir = join6(projectDir, ".claude", "agt-bin");
8947
8958
  if (existsSync7(agentBinDir)) {
8948
- probeEnv.PATH = probeEnv.PATH ? `${agentBinDir}${pathDelimiter}${probeEnv.PATH}` : agentBinDir;
8959
+ const parts = probeEnv.PATH ? probeEnv.PATH.split(pathDelimiter) : [];
8960
+ parts.unshift(agentBinDir);
8961
+ if (process.platform !== "win32") {
8962
+ for (const dir of SYSTEM_PATH_FLOOR) {
8963
+ if (!parts.includes(dir)) parts.push(dir);
8964
+ }
8965
+ }
8966
+ probeEnv.PATH = [...new Set(parts.filter((p) => p.length > 0))].join(pathDelimiter);
8949
8967
  }
8950
8968
  } catch {
8951
8969
  }
@@ -9272,6 +9290,288 @@ function describeWorkerModuleFailure(err) {
9272
9290
  return `[startup] FATAL \u2014 the manager worker module failed to load, so this process will never poll. The pidfile it already wrote would otherwise make it look like a healthy manager forever (ENG-9129). Exiting so the supervisor can react. Cause: ${detail}`;
9273
9291
  }
9274
9292
 
9293
+ // src/lib/drain-transcript-flush.ts
9294
+ import { existsSync as existsSync8, readdirSync as readdirSync2 } from "fs";
9295
+ import { homedir as homedir5 } from "os";
9296
+ import { dirname as dirname6, join as join8, relative as relative2, sep } from "path";
9297
+ import { spawn as spawn2 } from "child_process";
9298
+
9299
+ // src/lib/host-archive-address.ts
9300
+ import { readFileSync as readFileSync9 } from "fs";
9301
+ var DEFAULT_ARCHIVE_ADDRESS_PATH = "/var/lib/augmented/session-archive-address.json";
9302
+ var CACHE_TTL_MS = 5 * 60 * 1e3;
9303
+ var cache = /* @__PURE__ */ new Map();
9304
+ function str(value) {
9305
+ if (typeof value !== "string") return null;
9306
+ const trimmed = value.trim();
9307
+ return trimmed.length > 0 ? trimmed : null;
9308
+ }
9309
+ function readHostArchiveAddress(path) {
9310
+ const file = path ?? process.env["ARCHIVE_ADDRESS_FILE"]?.trim() ?? process.env["AGT_SESSION_ARCHIVE_ADDRESS_FILE"]?.trim() ?? DEFAULT_ARCHIVE_ADDRESS_PATH;
9311
+ const now = Date.now();
9312
+ const hit = cache.get(file);
9313
+ if (hit && now - hit.at < CACHE_TTL_MS) return hit.value;
9314
+ let value = null;
9315
+ try {
9316
+ const raw = readFileSync9(file, "utf-8");
9317
+ const parsed = JSON.parse(raw);
9318
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
9319
+ const obj = parsed;
9320
+ const bucket = str(obj["bucket"]);
9321
+ const keyPrefix = str(obj["key_prefix"]);
9322
+ if (bucket && keyPrefix) {
9323
+ value = {
9324
+ bucket,
9325
+ region: str(obj["region"]),
9326
+ instanceId: str(obj["instance_id"]),
9327
+ keyPrefix
9328
+ };
9329
+ }
9330
+ }
9331
+ } catch {
9332
+ value = null;
9333
+ }
9334
+ cache.set(file, { at: now, value });
9335
+ return value;
9336
+ }
9337
+
9338
+ // src/lib/drain-transcript-flush.ts
9339
+ function sessionsBaseDir() {
9340
+ return join8(homedir5(), ".claude", "projects");
9341
+ }
9342
+ var PER_FILE_UPLOAD_TIMEOUT_MS = 3e4;
9343
+ var UPLOAD_CONCURRENCY = 4;
9344
+ var DRAIN_MANIFEST_VERSION = 1;
9345
+ var DRAIN_MANIFEST_FILENAME = "_augmented-drain-manifest.json";
9346
+ function listJsonlFiles(dir) {
9347
+ if (!existsSync8(dir)) return [];
9348
+ const out = [];
9349
+ const walk = (d) => {
9350
+ for (const entry of readdirSync2(d, { withFileTypes: true })) {
9351
+ const full = join8(d, entry.name);
9352
+ if (entry.isDirectory()) walk(full);
9353
+ else if (entry.isFile() && entry.name.endsWith(".jsonl")) out.push(full);
9354
+ }
9355
+ };
9356
+ try {
9357
+ walk(dir);
9358
+ } catch {
9359
+ }
9360
+ return out;
9361
+ }
9362
+ function transcriptObjectKey(keyPrefix, baseDir, file) {
9363
+ const rel = relative2(baseDir, file).split(sep).join("/");
9364
+ if (!rel || rel.startsWith("../") || rel === "..") return null;
9365
+ return `${keyPrefix.replace(/\/+$/, "")}/${rel}`;
9366
+ }
9367
+ function drainManifestObjectKey(keyPrefix, baseDir, transcriptDir) {
9368
+ return transcriptObjectKey(keyPrefix, baseDir, join8(transcriptDir, DRAIN_MANIFEST_FILENAME));
9369
+ }
9370
+ async function flushAgentTranscriptsOnDrain(codeName, deps) {
9371
+ const dir = deps.resolveTranscriptDir(codeName);
9372
+ const files = deps.listTranscripts(dir);
9373
+ if (files.length === 0) {
9374
+ return {
9375
+ status: "no-transcripts",
9376
+ uploaded: 0,
9377
+ failed: 0,
9378
+ total: 0,
9379
+ manifest: "skipped",
9380
+ manifestKey: null
9381
+ };
9382
+ }
9383
+ const address = deps.readAddress();
9384
+ if (!address || !address.bucket || !address.keyPrefix) {
9385
+ deps.log(
9386
+ `[drain-flush] NO S3 ADDRESS for '${codeName}' \u2014 ${files.length} transcript file(s) will NOT be shipped before teardown; this session may be lost (ENG-9491). The host archive address is unresolved (agt-session-archiver has published none).`
9387
+ );
9388
+ return {
9389
+ status: "no-address",
9390
+ uploaded: 0,
9391
+ failed: files.length,
9392
+ total: files.length,
9393
+ manifest: "skipped",
9394
+ manifestKey: null
9395
+ };
9396
+ }
9397
+ const { bucket, keyPrefix, region } = address;
9398
+ let uploaded = 0;
9399
+ let failed = 0;
9400
+ const keys = [];
9401
+ const missing = [];
9402
+ let cursor = 0;
9403
+ const worker = async () => {
9404
+ for (; ; ) {
9405
+ const i = cursor;
9406
+ cursor += 1;
9407
+ if (i >= files.length) return;
9408
+ const file = files[i];
9409
+ const key = transcriptObjectKey(keyPrefix, deps.baseDir, file);
9410
+ if (!key) {
9411
+ failed += 1;
9412
+ missing.push(file);
9413
+ deps.log(
9414
+ `[drain-flush] SKIP '${file}' for '${codeName}' \u2014 outside sessions base dir '${deps.baseDir}', cannot key it (ENG-9491)`
9415
+ );
9416
+ continue;
9417
+ }
9418
+ const res = await deps.uploadFile({ file, bucket, key, region });
9419
+ if (res.ok) {
9420
+ uploaded += 1;
9421
+ keys.push(key);
9422
+ } else {
9423
+ failed += 1;
9424
+ missing.push(file);
9425
+ deps.log(
9426
+ `[drain-flush] UPLOAD FAILED for '${codeName}' '${file}' \u2192 s3://${bucket}/${key}: ${res.detail} (ENG-9491)`
9427
+ );
9428
+ }
9429
+ }
9430
+ };
9431
+ await Promise.all(
9432
+ Array.from({ length: Math.min(UPLOAD_CONCURRENCY, files.length) }, () => worker())
9433
+ );
9434
+ const uploadStatus = failed === 0 ? "flushed" : uploaded === 0 ? "failed" : "partial";
9435
+ if (uploadStatus !== "flushed") {
9436
+ deps.log(
9437
+ `[drain-flush] INCOMPLETE for '${codeName}': ${uploaded}/${files.length} transcript file(s) shipped, ${failed} FAILED before teardown \u2014 session data may be lost (ENG-9491).`
9438
+ );
9439
+ }
9440
+ const { manifest, manifestKey } = await writeDrainManifest(codeName, deps, {
9441
+ bucket,
9442
+ keyPrefix,
9443
+ region,
9444
+ transcriptDir: dir,
9445
+ keys,
9446
+ missing,
9447
+ complete: failed === 0
9448
+ });
9449
+ const status = uploadStatus === "flushed" && manifest !== "written" ? "no-manifest" : uploadStatus;
9450
+ return { status, uploaded, failed, total: files.length, manifest, manifestKey };
9451
+ }
9452
+ async function writeDrainManifest(codeName, deps, ctx) {
9453
+ const manifestKey = drainManifestObjectKey(ctx.keyPrefix, deps.baseDir, ctx.transcriptDir);
9454
+ if (!manifestKey) {
9455
+ deps.log(
9456
+ `[drain-flush] NO MANIFEST for '${codeName}' \u2014 transcript dir '${ctx.transcriptDir}' is outside sessions base dir '${deps.baseDir}', so no manifest key could be computed. Any shipped object is UNRESTORABLE: nothing records the session pin or the source layout (ENG-9566).`
9457
+ );
9458
+ return { manifest: "unkeyable", manifestKey: null };
9459
+ }
9460
+ let layout = null;
9461
+ try {
9462
+ layout = deps.readSourceLayout(codeName);
9463
+ } catch (err) {
9464
+ deps.log(
9465
+ `[drain-flush] could not resolve source layout for '${codeName}': ${err.message} \u2014 manifest will record it as unknown (ENG-9566)`
9466
+ );
9467
+ }
9468
+ let sessionPin = null;
9469
+ try {
9470
+ sessionPin = deps.readSessionPin(codeName);
9471
+ } catch (err) {
9472
+ deps.log(
9473
+ `[drain-flush] could not read the session pin for '${codeName}': ${err.message} \u2014 a restore will not be able to identify the live conversation (ENG-9566)`
9474
+ );
9475
+ }
9476
+ const manifestBody = {
9477
+ version: DRAIN_MANIFEST_VERSION,
9478
+ codeName,
9479
+ writtenAt: deps.now().toISOString(),
9480
+ sourceLayout: layout?.layout ?? null,
9481
+ sourceAgentDir: layout?.agentDir ?? null,
9482
+ sourceTranscriptDir: ctx.transcriptDir,
9483
+ sourceBaseDir: deps.baseDir,
9484
+ bucket: ctx.bucket,
9485
+ keyPrefix: ctx.keyPrefix,
9486
+ keys: ctx.keys,
9487
+ missing: ctx.missing,
9488
+ complete: ctx.complete,
9489
+ sessionPin
9490
+ };
9491
+ const res = await deps.uploadManifest({
9492
+ body: `${JSON.stringify(manifestBody, null, 2)}
9493
+ `,
9494
+ bucket: ctx.bucket,
9495
+ key: manifestKey,
9496
+ region: ctx.region
9497
+ });
9498
+ if (!res.ok) {
9499
+ deps.log(
9500
+ `[drain-flush] MANIFEST UPLOAD FAILED for '${codeName}' \u2192 s3://${ctx.bucket}/${manifestKey}: ${res.detail}. ${ctx.keys.length} shipped object(s) are UNRESTORABLE without it (ENG-9566).`
9501
+ );
9502
+ return { manifest: "failed", manifestKey: null };
9503
+ }
9504
+ return { manifest: "written", manifestKey };
9505
+ }
9506
+ function drainTranscriptFlushDeps(log2) {
9507
+ return {
9508
+ resolveTranscriptDir: (codeName) => sessionTranscriptDir(getProjectDir(codeName)),
9509
+ readAddress: () => readHostArchiveAddress(),
9510
+ listTranscripts: listJsonlFiles,
9511
+ baseDir: sessionsBaseDir(),
9512
+ now: () => /* @__PURE__ */ new Date(),
9513
+ // ENG-9566: derive the layout from the seam's OUTPUT rather than re-running
9514
+ // its lstat. getProjectDir already resolved the codename symlink (or didn't);
9515
+ // if what came back is not under the codename dir, this host is id-keyed.
9516
+ // Observing the resolver keeps a second copy of ADR-0049's rule out of the
9517
+ // tree — the thing host-archive-address.ts's header warns about.
9518
+ readSourceLayout: (codeName) => {
9519
+ const agentDir = dirname6(getProjectDir(codeName));
9520
+ const codeNameDir = join8(homedir5(), ".augmented", codeName);
9521
+ return { layout: agentDir === codeNameDir ? "codename-keyed" : "id-keyed", agentDir };
9522
+ },
9523
+ readSessionPin: (codeName) => readDailySessionPin(codeName),
9524
+ uploadFile: ({ file, bucket, key, region }) => runAwsCp(awsCpArgs(file, bucket, key, region), null),
9525
+ uploadManifest: ({ body, bucket, key, region }) => (
9526
+ // `-` is `aws s3 cp`'s stdin source, so the manifest never touches disk.
9527
+ runAwsCp(
9528
+ [...awsCpArgs("-", bucket, key, region), "--content-type", "application/json"],
9529
+ body
9530
+ )
9531
+ ),
9532
+ log: log2
9533
+ };
9534
+ }
9535
+ function awsCpArgs(source, bucket, key, region) {
9536
+ const args = ["s3", "cp", source, `s3://${bucket}/${key}`, "--only-show-errors"];
9537
+ if (region) args.push("--region", region);
9538
+ return args;
9539
+ }
9540
+ function runAwsCp(args, body) {
9541
+ return new Promise((resolve) => {
9542
+ const child = spawn2("aws", args, {
9543
+ stdio: [body === null ? "ignore" : "pipe", "ignore", "pipe"]
9544
+ });
9545
+ let stderr = "";
9546
+ let settled = false;
9547
+ const finish = (r) => {
9548
+ if (settled) return;
9549
+ settled = true;
9550
+ clearTimeout(timer);
9551
+ resolve(r);
9552
+ };
9553
+ const timer = setTimeout(() => {
9554
+ child.kill("SIGKILL");
9555
+ finish({ ok: false, detail: `aws s3 cp timed out after ${PER_FILE_UPLOAD_TIMEOUT_MS}ms` });
9556
+ }, PER_FILE_UPLOAD_TIMEOUT_MS);
9557
+ child.stderr?.on("data", (d) => {
9558
+ stderr += String(d);
9559
+ });
9560
+ child.on("error", (err) => finish({ ok: false, detail: err.message }));
9561
+ child.on(
9562
+ "close",
9563
+ (code) => finish(
9564
+ code === 0 ? { ok: true, detail: "" } : { ok: false, detail: stderr.trim().slice(0, 500) || `aws exited with code ${code ?? "null"}` }
9565
+ )
9566
+ );
9567
+ if (body !== null) {
9568
+ child.stdin?.on("error", () => {
9569
+ });
9570
+ child.stdin?.end(body);
9571
+ }
9572
+ });
9573
+ }
9574
+
9275
9575
  // src/lib/self-update-pin.ts
9276
9576
  function isValidPinVersion(v) {
9277
9577
  return PIN_VERSION_RE.test(v);
@@ -9304,25 +9604,25 @@ function decidePin(opts) {
9304
9604
 
9305
9605
  // src/commands/manager.ts
9306
9606
  import chalk3 from "chalk";
9307
- import { existsSync as existsSync9, realpathSync as realpathSync2 } from "fs";
9308
- import { join as join9 } from "path";
9309
- import { homedir as homedir5, userInfo } from "os";
9310
- import { spawn as spawn3 } from "child_process";
9607
+ import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
9608
+ import { join as join10 } from "path";
9609
+ import { homedir as homedir6, userInfo } from "os";
9610
+ import { spawn as spawn4 } from "child_process";
9311
9611
 
9312
9612
  // src/lib/watchdog.ts
9313
- import { readFileSync as readFileSync9, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, existsSync as existsSync8, mkdirSync as mkdirSync6, openSync as openSync2, closeSync as closeSync2, chmodSync as chmodSync5 } from "fs";
9314
- import { join as join8 } from "path";
9315
- import { spawn as spawn2, execFileSync as execFileSync3 } from "child_process";
9316
- var DEFAULT_CONFIG_DIR = join8(process.env["HOME"] ?? "/tmp", ".augmented");
9613
+ import { readFileSync as readFileSync10, writeFileSync as writeFileSync6, unlinkSync as unlinkSync4, existsSync as existsSync9, mkdirSync as mkdirSync6, openSync as openSync2, closeSync as closeSync2, chmodSync as chmodSync5 } from "fs";
9614
+ import { join as join9 } from "path";
9615
+ import { spawn as spawn3, execFileSync as execFileSync3 } from "child_process";
9616
+ var DEFAULT_CONFIG_DIR = join9(process.env["HOME"] ?? "/tmp", ".augmented");
9317
9617
  function getManagerPaths(configDir) {
9318
9618
  return {
9319
- pidFile: join8(configDir, "manager.pid"),
9320
- stateFile: join8(configDir, "manager-state.json"),
9321
- logFile: join8(configDir, "manager.log")
9619
+ pidFile: join9(configDir, "manager.pid"),
9620
+ stateFile: join9(configDir, "manager-state.json"),
9621
+ logFile: join9(configDir, "manager.log")
9322
9622
  };
9323
9623
  }
9324
9624
  function ensureDir(configDir) {
9325
- if (!existsSync8(configDir)) {
9625
+ if (!existsSync9(configDir)) {
9326
9626
  mkdirSync6(configDir, { recursive: true });
9327
9627
  }
9328
9628
  }
@@ -9332,7 +9632,7 @@ function writePidFile(configDir, pid) {
9332
9632
  }
9333
9633
  function readPidFile(configDir) {
9334
9634
  try {
9335
- const raw = readFileSync9(getManagerPaths(configDir).pidFile, "utf-8").trim();
9635
+ const raw = readFileSync10(getManagerPaths(configDir).pidFile, "utf-8").trim();
9336
9636
  const pid = parseInt(raw, 10);
9337
9637
  return isNaN(pid) ? null : pid;
9338
9638
  } catch {
@@ -9378,7 +9678,7 @@ function defaultPgrep() {
9378
9678
  }
9379
9679
  function readStateFile(configDir) {
9380
9680
  try {
9381
- const raw = readFileSync9(getManagerPaths(configDir).stateFile, "utf-8");
9681
+ const raw = readFileSync10(getManagerPaths(configDir).stateFile, "utf-8");
9382
9682
  return JSON.parse(raw);
9383
9683
  } catch {
9384
9684
  return null;
@@ -9416,7 +9716,7 @@ function startWatchdog(opts) {
9416
9716
  } catch {
9417
9717
  }
9418
9718
  const intervalSec = String(Math.max(Math.floor(opts.intervalMs / 1e3), 5));
9419
- const child = spawn2(
9719
+ const child = spawn3(
9420
9720
  process.execPath,
9421
9721
  [process.argv[1], "manager", "start", "--interval", intervalSec, "--config-dir", configDir, "--supervise"],
9422
9722
  {
@@ -9434,7 +9734,7 @@ function startWatchdog(opts) {
9434
9734
  const deadline = Date.now() + 5e3;
9435
9735
  const sleepBuf = new Int32Array(new SharedArrayBuffer(4));
9436
9736
  while (Date.now() < deadline) {
9437
- if (existsSync8(pidFile)) {
9737
+ if (existsSync9(pidFile)) {
9438
9738
  return { pid: child.pid };
9439
9739
  }
9440
9740
  if (child.exitCode !== null) {
@@ -9540,7 +9840,7 @@ function normalizePinInEnv(env) {
9540
9840
  function managerStartCommand(opts) {
9541
9841
  const json = isJsonMode();
9542
9842
  if (!process.env.HOME || !process.env.HOME.trim()) {
9543
- const fallback = homedir5();
9843
+ const fallback = homedir6();
9544
9844
  process.env.HOME = fallback;
9545
9845
  if (!json) {
9546
9846
  info(`HOME was not set in the manager env \u2014 defaulting to ${fallback}.`);
@@ -9574,7 +9874,7 @@ function managerStartCommand(opts) {
9574
9874
  process.exitCode = 1;
9575
9875
  return;
9576
9876
  }
9577
- const configDir = opts.configDir ?? join9(homedir5(), ".augmented");
9877
+ const configDir = opts.configDir ?? join10(homedir6(), ".augmented");
9578
9878
  if (opts.supervise) {
9579
9879
  if (json) {
9580
9880
  jsonOutput({ ok: false, error: "--supervise is not supported with --json" });
@@ -9629,7 +9929,7 @@ function runSupervisorLoop(intervalSec, configDir) {
9629
9929
  process.on("SIGINT", forwardOrExit("SIGINT"));
9630
9930
  const runOne = () => {
9631
9931
  respawnTimer = null;
9632
- currentChild = spawn3(
9932
+ currentChild = spawn4(
9633
9933
  process.execPath,
9634
9934
  [process.argv[1], "manager", "start", "--interval", String(intervalSec), "--config-dir", configDir],
9635
9935
  { stdio: "inherit", env: process.env }
@@ -9670,7 +9970,7 @@ function runSupervisorLoop(intervalSec, configDir) {
9670
9970
  }
9671
9971
  async function managerStopCommand(opts = {}) {
9672
9972
  const json = isJsonMode();
9673
- const configDir = opts.configDir ?? join9(homedir5(), ".augmented");
9973
+ const configDir = opts.configDir ?? join10(homedir6(), ".augmented");
9674
9974
  try {
9675
9975
  const result = await stopWatchdog(configDir);
9676
9976
  if (!result.stopped && !result.pid) {
@@ -9698,7 +9998,7 @@ async function managerStopCommand(opts = {}) {
9698
9998
  }
9699
9999
  function managerStatusCommand(opts = {}) {
9700
10000
  const json = isJsonMode();
9701
- const configDir = opts.configDir ?? join9(homedir5(), ".augmented");
10001
+ const configDir = opts.configDir ?? join10(homedir6(), ".augmented");
9702
10002
  const status = getManagerStatus(configDir);
9703
10003
  if (!status) {
9704
10004
  if (json) {
@@ -9770,7 +10070,7 @@ function resolveStableAgtBin(rawPath) {
9770
10070
  if (!prefix || !formula) return rawPath;
9771
10071
  const candidates = [`${prefix}/bin/${formula}`, `${prefix}/bin/agt`];
9772
10072
  for (const candidate of candidates) {
9773
- if (!existsSync9(candidate)) continue;
10073
+ if (!existsSync10(candidate)) continue;
9774
10074
  try {
9775
10075
  realpathSync2(candidate);
9776
10076
  return candidate;
@@ -9790,7 +10090,7 @@ async function managerInstallCommand(opts = {}) {
9790
10090
  process.exitCode = 1;
9791
10091
  return;
9792
10092
  }
9793
- const configDir = opts.configDir ?? join9(homedir5(), ".augmented");
10093
+ const configDir = opts.configDir ?? join10(homedir6(), ".augmented");
9794
10094
  const rawAgtBin = process.argv[1];
9795
10095
  if (!rawAgtBin) {
9796
10096
  const msg = "Could not resolve the agt binary path from argv. Re-run via the installed `agt` command.";
@@ -9801,9 +10101,9 @@ async function managerInstallCommand(opts = {}) {
9801
10101
  }
9802
10102
  const agtBin = resolveStableAgtBin(rawAgtBin);
9803
10103
  if (process.platform === "darwin") {
9804
- const home = homedir5();
10104
+ const home = homedir6();
9805
10105
  const protectedRoots = ["Documents", "Downloads", "Desktop", "Movies", "Music", "Pictures"];
9806
- const offending = protectedRoots.map((r) => join9(home, r)).find((p) => agtBin === p || agtBin.startsWith(`${p}/`));
10106
+ const offending = protectedRoots.map((r) => join10(home, r)).find((p) => agtBin === p || agtBin.startsWith(`${p}/`));
9807
10107
  if (offending) {
9808
10108
  const msg = `agt binary at ${agtBin} sits inside a macOS TCC-protected folder (${offending}). launchd-spawned processes cannot read files there and the manager would EPERM on startup. Either install agt globally (\`npm install -g @integrity-labs/agt-cli\`) or copy the dist outside protected folders before running this command.`;
9809
10109
  if (json) jsonOutput({ ok: false, error: msg });
@@ -9816,7 +10116,7 @@ async function managerInstallCommand(opts = {}) {
9816
10116
  AGT_HOST: getHost(),
9817
10117
  // ?? alone wouldn't catch `HOME=""` from a stripped systemd env.
9818
10118
  // Treat empty / whitespace-only as missing.
9819
- HOME: process.env.HOME?.trim() || homedir5(),
10119
+ HOME: process.env.HOME?.trim() || homedir6(),
9820
10120
  USER: process.env.USER?.trim() || userInfo().username
9821
10121
  };
9822
10122
  const apiKey = getApiKey();
@@ -9872,7 +10172,7 @@ async function managerInstallSystemUnitCommand(opts = {}) {
9872
10172
  return;
9873
10173
  }
9874
10174
  const user = opts.user ?? "root";
9875
- const configDir = opts.configDir ?? (user === "root" ? "/root/.augmented" : join9("/home", user, ".augmented"));
10175
+ const configDir = opts.configDir ?? (user === "root" ? "/root/.augmented" : join10("/home", user, ".augmented"));
9876
10176
  const rawAgtBin = process.argv[1];
9877
10177
  if (!rawAgtBin) {
9878
10178
  const msg = "Could not resolve the agt binary path from argv. Re-run via the installed `agt` command.";
@@ -10149,6 +10449,10 @@ export {
10149
10449
  gatherSessionToolBindProbe,
10150
10450
  provision,
10151
10451
  describeStartupCompletion,
10452
+ readHostArchiveAddress,
10453
+ DRAIN_MANIFEST_FILENAME,
10454
+ flushAgentTranscriptsOnDrain,
10455
+ drainTranscriptFlushDeps,
10152
10456
  executeConnectivityProbe,
10153
10457
  isValidPinVersion,
10154
10458
  resolveEffectivePinRaw,
@@ -10166,4 +10470,4 @@ export {
10166
10470
  managerInstallSystemUnitCommand,
10167
10471
  managerUninstallSystemUnitCommand
10168
10472
  };
10169
- //# sourceMappingURL=chunk-FBYIO3Z6.js.map
10473
+ //# sourceMappingURL=chunk-OOYUWMTR.js.map