@botbuddy/cli 1.64.20 → 1.64.23

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.
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.64.20",
3
- "source_commit": "88727144e4d431316a3805841f3c961913e9bd01",
4
- "source_sha256": "6d248826ccf32a9651e8e5cb16714e627f62c2df50b4a75b76d4df6bf1b83170",
2
+ "release_version": "1.64.23",
3
+ "source_commit": "7ddae49af589d2fd829eb0a418114a16d69bde05",
4
+ "source_sha256": "1516cc538b4b9d9dd1d81a6a5403bbdca1f2238385126993852e342a817c5c85",
5
5
  "target": "darwin-arm64",
6
- "sha256": "729b7f3001812627b43b55f5786352f0abaab8aa22a427c3f19bd2ceab72b9fb"
6
+ "sha256": "44289087b95f9f27b0b68743543ff65667849be9817f1dad2dc4c22ed5c8c4f0"
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
- "release_version": "1.64.20",
3
- "source_commit": "88727144e4d431316a3805841f3c961913e9bd01",
4
- "source_sha256": "6d248826ccf32a9651e8e5cb16714e627f62c2df50b4a75b76d4df6bf1b83170",
2
+ "release_version": "1.64.23",
3
+ "source_commit": "7ddae49af589d2fd829eb0a418114a16d69bde05",
4
+ "source_sha256": "1516cc538b4b9d9dd1d81a6a5403bbdca1f2238385126993852e342a817c5c85",
5
5
  "target": "linux-x64",
6
- "sha256": "98d279c28da1bf0b3046a5eba886fdac9321f577e2d4819eebcf7a5dd02b66dd"
6
+ "sha256": "4f8a4996d9254a1c621bf4cd3c76cb5f676f7f2af9fe0700f2598ee4fce1728c"
7
7
  }
@@ -1,21 +1,21 @@
1
1
  {
2
2
  "schema_version": 1,
3
- "release_version": "1.64.20",
4
- "source_commit": "88727144e4d431316a3805841f3c961913e9bd01",
5
- "source_sha256": "6d248826ccf32a9651e8e5cb16714e627f62c2df50b4a75b76d4df6bf1b83170",
3
+ "release_version": "1.64.23",
4
+ "source_commit": "7ddae49af589d2fd829eb0a418114a16d69bde05",
5
+ "source_sha256": "1516cc538b4b9d9dd1d81a6a5403bbdca1f2238385126993852e342a817c5c85",
6
6
  "targets": {
7
7
  "darwin-arm64": {
8
8
  "goos": "darwin",
9
9
  "goarch": "arm64",
10
10
  "binary": "daemon/bin/darwin-arm64/botbuddy-daemon",
11
- "sha256": "729b7f3001812627b43b55f5786352f0abaab8aa22a427c3f19bd2ceab72b9fb",
11
+ "sha256": "44289087b95f9f27b0b68743543ff65667849be9817f1dad2dc4c22ed5c8c4f0",
12
12
  "mode": "0755"
13
13
  },
14
14
  "linux-x64": {
15
15
  "goos": "linux",
16
16
  "goarch": "amd64",
17
17
  "binary": "daemon/bin/linux-x64/botbuddy-daemon",
18
- "sha256": "98d279c28da1bf0b3046a5eba886fdac9321f577e2d4819eebcf7a5dd02b66dd",
18
+ "sha256": "4f8a4996d9254a1c621bf4cd3c76cb5f676f7f2af9fe0700f2598ee4fce1728c",
19
19
  "mode": "0755"
20
20
  }
21
21
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@botbuddy/cli",
3
- "version": "1.64.20",
3
+ "version": "1.64.23",
4
4
  "description": "BotBuddy \u2014 Swarm coordination CLI for multi-agent workflows",
5
5
  "type": "module",
6
6
  "bin": {
@@ -202,6 +202,10 @@ export async function doctorAgentAuth({
202
202
  machine_id_readable: Boolean(machineUuidFn()),
203
203
  capability: "unverified",
204
204
  },
205
+ session_linking: {
206
+ ticketed_native_identity: "enforced",
207
+ remediation: "ticketed Codex requires --codex-thread-id <UUID>; ticketed Claude Desktop requires CLAUDE_CODE_HOST_SESSION_ID=local_<uuid>; use --no-ticket-reason for terminal or cloud work without a native link",
208
+ },
205
209
  };
206
210
  let credential = fresh
207
211
  ? { token: state.agent_session_token, sessionId: state.session_id, agentId: state.agent_id, source: "cache" }
@@ -324,6 +324,11 @@ export async function selfHealAgentSession({
324
324
  // number) so the minted session keeps its dashboard deep link and the server
325
325
  // can reconcile a replacement agent by thread identity if the cache is lost.
326
326
  const codexThreadId = env.CODEX_THREAD_ID || undefined;
327
+ // A native Codex thread is proof that this is a Codex harness, rather than a
328
+ // generic CLI caller. Keep the type and deep-link identity paired so a
329
+ // ticketed renewal is accepted by the server's verified-owner contract.
330
+ const claudeDesktopSessionId = env.CLAUDE_CODE_HOST_SESSION_ID || undefined;
331
+ const agentType = codexThreadId ? "codex" : claudeDesktopSessionId ? "claude" : "custom";
327
332
  const prNumber = Number.parseInt(env.BOTBUDDY_PR_NUMBER ?? env.CODEX_PR_NUMBER ?? "", 10);
328
333
  // BOT-2425: present the session-lifetime identity. The cached agent_id is only
329
334
  // this session's when the cache belongs to its harness session; otherwise the
@@ -336,7 +341,7 @@ export async function selfHealAgentSession({
336
341
  : envHarness ?? (ownCache ? current?.harness_session_id : null) ?? null;
337
342
  const response = await call("register_agent", {
338
343
  name: workAgentName,
339
- type: "custom",
344
+ type: agentType,
340
345
  host: resolvedHost,
341
346
  worktree: registrationWorktree,
342
347
  // BOT-1750 (AC-4): attest the machine so the worktree's stack-lease capability
@@ -354,6 +359,7 @@ export async function selfHealAgentSession({
354
359
  model: env.BOTBUDDY_MODEL || undefined,
355
360
  effort: env.BOTBUDDY_EFFORT || undefined,
356
361
  codex_thread_id: codexThreadId,
362
+ claude_desktop_session_id: claudeDesktopSessionId,
357
363
  pr_number: Number.isInteger(prNumber) ? prNumber : undefined,
358
364
  // BOT-1649 (Codex round-6 P2): a self-heal only ever consumes the returned
359
365
  // short-lived session token — never the durable `bb_agent_` key. Declare
package/src/commands.mjs CHANGED
@@ -1157,6 +1157,7 @@ export async function cmdBootstrap(args, {
1157
1157
  clearHarnessSession: clearSession = clearHarnessSession,
1158
1158
  bootstrapHarnessSession: bootstrapSession = bootstrapHarnessSession,
1159
1159
  getConfig: getCfg = getConfig,
1160
+ env = process.env,
1160
1161
  log = (line) => console.log(line),
1161
1162
  die: fail = die,
1162
1163
  } = {}) {
@@ -1196,7 +1197,7 @@ export async function cmdBootstrap(args, {
1196
1197
  // Claude Desktop injects this only for a desktop-hosted agent session. The
1197
1198
  // CLI deliberately treats every other environment as absent, so terminal and
1198
1199
  // cloud Claude sessions never manufacture a deep link.
1199
- const claudeDesktopSessionId = process.env.CLAUDE_CODE_HOST_SESSION_ID || null;
1200
+ let claudeDesktopSessionId = env.CLAUDE_CODE_HOST_SESSION_ID || null;
1200
1201
  let branch = null;
1201
1202
  let ticketId = null;
1202
1203
  let ticketUrl = null;
@@ -1229,6 +1230,8 @@ export async function cmdBootstrap(args, {
1229
1230
  if (linkageError) fail(linkageError);
1230
1231
  ticketId = ticketId?.trim() || null;
1231
1232
  noTicketReason = noTicketReason?.trim() || null;
1233
+ const nativeIdentityError = validateBootstrapNativeIdentity({ type, ticketId, codexThreadId, claudeDesktopSessionId });
1234
+ if (nativeIdentityError) fail(nativeIdentityError);
1232
1235
  if (!nameExplicit) name = `${name}-${harnessSessionId.slice(0, 8)}`;
1233
1236
  const state = await bootstrapSession({
1234
1237
  name,
@@ -1256,6 +1259,18 @@ export async function cmdBootstrap(args, {
1256
1259
  log(JSON.stringify({ agent_id: state.agent_id, display_name: state.display_name, session_id: state.session_id, expires_at: state.expires_at, ...(state.ticket_signals?.concurrency ? { ticket_session_warning: state.ticket_signals.concurrency } : {}), ...(state.replaced_cached_session ? { replaced_cached_session: state.replaced_cached_session } : {}) }));
1257
1260
  }
1258
1261
 
1262
+ /** BOT-2457: local preflight mirrors the server's ticket-link identity gate. */
1263
+ export function validateBootstrapNativeIdentity({ type, ticketId, codexThreadId, claudeDesktopSessionId }) {
1264
+ if (!ticketId) return null;
1265
+ const codex = typeof codexThreadId === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(codexThreadId);
1266
+ const claude = typeof claudeDesktopSessionId === "string" && /^local_[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(claudeDesktopSessionId);
1267
+ if (type === "codex" && codex && !claude) return null;
1268
+ if (type === "claude" && claude && !codex) return null;
1269
+ if (type === "codex") return "Ticketed Codex bootstrap requires exactly one --codex-thread-id <canonical UUID>; do not pass a URL, name, or Claude identity.";
1270
+ if (type === "claude") return "Ticketed Claude Desktop bootstrap requires CLAUDE_CODE_HOST_SESSION_ID=local_<uuid>; terminal and cloud Claude sessions must use --no-ticket-reason.";
1271
+ return "Ticketed bootstrap requires type=codex with one --codex-thread-id or type=claude with one CLAUDE_CODE_HOST_SESSION_ID; use --no-ticket-reason for ticketless custom, terminal, or cloud work.";
1272
+ }
1273
+
1259
1274
  // BOT-1566 A4: after the local-metadata lines, ask the SERVER whether the stored
1260
1275
  // credential is actually accepted. `status` used to decode only local metadata,
1261
1276
  // so a Keychain item holding a typed password (the BOT-1566 incident) was