borgmcp 5.1.2 → 5.3.0

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.
Files changed (71) hide show
  1. package/dist/agent-runtime.d.ts +2 -4
  2. package/dist/agent-runtime.d.ts.map +1 -1
  3. package/dist/agent-runtime.js +3 -5
  4. package/dist/agent-runtime.js.map +1 -1
  5. package/dist/assimilate-cmd.d.ts +1 -11
  6. package/dist/assimilate-cmd.d.ts.map +1 -1
  7. package/dist/assimilate-cmd.js +37 -48
  8. package/dist/assimilate-cmd.js.map +1 -1
  9. package/dist/assimilate-deps.d.ts.map +1 -1
  10. package/dist/assimilate-deps.js +1 -4
  11. package/dist/assimilate-deps.js.map +1 -1
  12. package/dist/claude.d.ts.map +1 -1
  13. package/dist/claude.js +36 -77
  14. package/dist/claude.js.map +1 -1
  15. package/dist/codex-app-server.d.ts +4 -6
  16. package/dist/codex-app-server.d.ts.map +1 -1
  17. package/dist/codex-app-server.js +4 -25
  18. package/dist/codex-app-server.js.map +1 -1
  19. package/dist/codex-app-wake.d.ts +8 -10
  20. package/dist/codex-app-wake.d.ts.map +1 -1
  21. package/dist/codex-app-wake.js +49 -66
  22. package/dist/codex-app-wake.js.map +1 -1
  23. package/dist/codex-launch.d.ts +15 -24
  24. package/dist/codex-launch.d.ts.map +1 -1
  25. package/dist/codex-launch.js +29 -55
  26. package/dist/codex-launch.js.map +1 -1
  27. package/dist/codex-remote.d.ts +15 -8
  28. package/dist/codex-remote.d.ts.map +1 -1
  29. package/dist/codex-remote.js +71 -70
  30. package/dist/codex-remote.js.map +1 -1
  31. package/dist/codex-wake-resolve.d.ts +12 -31
  32. package/dist/codex-wake-resolve.d.ts.map +1 -1
  33. package/dist/codex-wake-resolve.js +21 -38
  34. package/dist/codex-wake-resolve.js.map +1 -1
  35. package/dist/config-utils.js +2 -2
  36. package/dist/config-utils.js.map +1 -1
  37. package/dist/cubes.d.ts +0 -17
  38. package/dist/cubes.d.ts.map +1 -1
  39. package/dist/cubes.js +0 -81
  40. package/dist/cubes.js.map +1 -1
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +3 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/log-stream.d.ts.map +1 -1
  45. package/dist/log-stream.js +4 -1
  46. package/dist/log-stream.js.map +1 -1
  47. package/dist/regen-format.d.ts +3 -1
  48. package/dist/regen-format.d.ts.map +1 -1
  49. package/dist/regen-format.js +24 -4
  50. package/dist/regen-format.js.map +1 -1
  51. package/dist/remote-client.d.ts +4 -3
  52. package/dist/remote-client.d.ts.map +1 -1
  53. package/dist/remote-client.js +9 -3
  54. package/dist/remote-client.js.map +1 -1
  55. package/docs/RELEASING.md +2 -2
  56. package/package.json +2 -2
  57. package/src/agent-runtime.ts +3 -5
  58. package/src/assimilate-cmd.ts +35 -58
  59. package/src/assimilate-deps.ts +0 -4
  60. package/src/claude.ts +34 -81
  61. package/src/codex-app-server.ts +8 -25
  62. package/src/codex-app-wake.ts +46 -73
  63. package/src/codex-launch.ts +43 -76
  64. package/src/codex-remote.ts +90 -82
  65. package/src/codex-wake-resolve.ts +26 -47
  66. package/src/config-utils.ts +2 -2
  67. package/src/cubes.ts +2 -100
  68. package/src/index.ts +3 -1
  69. package/src/log-stream.ts +4 -1
  70. package/src/regen-format.ts +28 -6
  71. package/src/remote-client.ts +14 -6
package/src/index.ts CHANGED
@@ -606,7 +606,9 @@ export async function main() {
606
606
  drone: displayedResult.drone,
607
607
  role: displayedResult.role,
608
608
  behind_by: typeof displayedResult.behind_by === 'number' ? displayedResult.behind_by : null,
609
- decision_topics: (displayedResult.decisions ?? []).map((d: any) => d.topic),
609
+ ...(Array.isArray(displayedResult.decisions)
610
+ ? { decision_topics: displayedResult.decisions.map((d) => d.topic) }
611
+ : {}),
610
612
  running_version: getPackageVersion(),
611
613
  on_disk_version: onDiskVersion,
612
614
  wake_path_healthy: inboxMonitorHealthy,
package/src/log-stream.ts CHANGED
@@ -906,10 +906,13 @@ export async function streamOnce(
906
906
  // OpenCode queue. A still-unread re-ping may reconcile the prior attempt;
907
907
  // its source entry ID prevents a new nonce from resubmitting that prompt.
908
908
  if (isReping) {
909
- await injectOpenCode(
909
+ const openCodeDelivered = await injectOpenCode(
910
910
  formatOpenCodeWakePrompt(line), deliveryId, true, ev.id,
911
911
  () => hasPendingWakeEntry(active, ev.id),
912
912
  );
913
+ if (!openCodeDelivered) {
914
+ wakeCodex(formatCodexWakePrompt(line), ev.wake_nonce, ev.id);
915
+ }
913
916
  }
914
917
  markEventPersisted(ev.id, ev.data?.created_at ?? '');
915
918
  return 'persisted-skip';
@@ -22,6 +22,7 @@ import { shellEscape } from './shell-escape.js';
22
22
  import { OPENCODE_WAKE_PATH_GUIDANCE } from './opencode-wake-copy.js';
23
23
  import { isBorgSession } from './launch-gate.js';
24
24
  import type { AgentKind } from './agent-runtime.js';
25
+ import type { Decision } from 'borgmcp-shared/protocol';
25
26
 
26
27
  export type HandoverMode = 'origin' | 'local';
27
28
 
@@ -385,6 +386,14 @@ Any time you make a factual claim that could be verified — "this shipped as ve
385
386
  - Cube log state → \`borg_read-log unread_only=true\` for wake triage, draining until \`behind_by=0\`; don't cite from memory or from another drone's summary
386
387
  - Ratified cube decision → \`borg_decisions {topic}\` — cite the registry's active decision by topic; NEVER restate a ratified decision from memory (a memory restatement drifts on the axis). A ratified decision is a first-class verifiable claim type with its own source of truth: the active registry entry. Recording one is \`borg_decide\`: Coordinator/Queen are workflow-eligible to ratify, but role labels grant no server permission; the selected local client needs a live cube-manage grant.
387
388
 
389
+ **Durable layers:**
390
+ 1. Decision registry (\`borg_decide\` / \`borg_decisions\`): choices between alternatives that could be revisited, cited by topic, served into every drone's context, capped at 16,384 active bytes per cube.
391
+ 2. Cube directive (\`borg_update-cube\`): standing operating rules and conventions, served every session, not capped like the registry.
392
+ 3. Cube documents (\`borg_put-document\` / \`borg_get-document\`): large or detailed material — contracts, designs, evidence — cited by id, never inlined.
393
+ 4. Repository \`AGENTS.md\`: rules specific to one repository, read only by seats working there.
394
+
395
+ Rules: a registry entry that records a rule rather than a choice belongs in the directive — move it and remove the registry copy; on a cap refusal the order is relocate rules → supersede stale choices → remove obsolete; never archive playbook prose in the registry; detail goes to a document and is cited.
396
+
388
397
  **The discipline is universal to reviewer-class actions** (Code Reviewer formal gates + Security Auditor SR gates + PM-courtesy verifications + UX-courtesy reviews + any drone making a verification-worthy factual claim in their cube-log post). It lives in this universal playbook rather than any one role's text because it applies to ALL reviewers.
389
398
 
390
399
  **Four-surface propagation:**
@@ -554,7 +563,8 @@ export function formatRegenMarkdown(
554
563
  // gh#740: active ratified decisions for the cube. Rendered in the
555
564
  // always-shown band (lite + full) so the source of truth is in context at
556
565
  // mid-session restatement moments. Absent on a pre-gh#740 worker → omitted.
557
- decisions?: any[];
566
+ decisions?: Decision[];
567
+ decisions_error?: string;
558
568
  },
559
569
  opts: { mode?: RegenMode; handoverMode?: HandoverMode } = {}
560
570
  ): string {
@@ -612,16 +622,28 @@ export function formatRegenMarkdown(
612
622
  const taxonomyTip = nullTaxonomyTip(result.cube.message_taxonomy);
613
623
 
614
624
  // gh#740: render active ratified decisions concisely (one line each), capped
615
- // with an elision footer. Section omitted when there are none (or the field
616
- // is absent on a pre-gh#740 worker mixed-client safe). Lives in the
625
+ // with an elision footer. Empty and failed reads are explicit and distinct;
626
+ // an absent field from a pre-gh#740 worker is omitted. Lives in the
617
627
  // always-shown band below so it surfaces on LITE wakes (the mid-session
618
628
  // restatement moment), not just the session-start full regen (PM F1).
619
629
  const RATIFIED_DECISIONS_CAP = 12;
620
- const activeDecisions = Array.isArray(result.decisions) ? result.decisions : [];
621
630
  const decisionsSection = (() => {
622
- if (activeDecisions.length === 0) return '';
631
+ if (result.decisions_error !== undefined) {
632
+ const errorClass = /^[A-Za-z][A-Za-z0-9]*Error$/.test(result.decisions_error)
633
+ ? result.decisions_error
634
+ : 'UnknownError';
635
+ return [
636
+ '## Ratified decisions',
637
+ `The decision registry could not be read (${errorClass}). Active decisions are unavailable.`,
638
+ ].join('\n');
639
+ }
640
+ if (!Array.isArray(result.decisions)) return '';
641
+ const activeDecisions = result.decisions;
642
+ if (activeDecisions.length === 0) {
643
+ return ['## Ratified decisions', 'No active decisions are recorded.'].join('\n');
644
+ }
623
645
  const shown = activeDecisions.slice(0, RATIFIED_DECISIONS_CAP);
624
- const lines = shown.map((d: any) => `- **${d.topic}:** ${d.decision}`);
646
+ const lines = shown.map((d) => `- **${d.topic}:** ${d.decision}`);
625
647
  const remaining = activeDecisions.length - shown.length;
626
648
  if (remaining > 0) lines.push(`- _+${remaining} more — \`borg_decisions\`_`);
627
649
  return ['## Ratified decisions', 'Cite these by topic — do NOT restate a ratified decision from memory.', ...lines].join('\n');
@@ -57,6 +57,7 @@ import {
57
57
  type ListDocumentsResult,
58
58
  type RemoveDocumentResult,
59
59
  type CreateCubeRepository,
60
+ type Decision,
60
61
  } from 'borgmcp-shared/protocol';
61
62
  import { Buffer } from 'node:buffer';
62
63
  import { canonicalizeWorkingRepoIdentity } from './working-repo.js';
@@ -1261,9 +1262,9 @@ export async function listDecisions(
1261
1262
  apiUrl: string,
1262
1263
  topic?: string,
1263
1264
  serverTrustIdentity?: string,
1264
- ): Promise<{ decisions: any[] }> {
1265
+ ): Promise<{ decisions: Decision[] }> {
1265
1266
  const local = await localAuthorityContext(sessionToken, apiUrl, serverTrustIdentity);
1266
- const payload = await localServerRequest<{ decisions: any[] }>(
1267
+ const payload = await localServerRequest<{ decisions: Decision[] }>(
1267
1268
  local,
1268
1269
  `/api/cubes/${local.cubeId}/decisions`,
1269
1270
  'PUT',
@@ -1352,7 +1353,8 @@ export async function regen(
1352
1353
  behind_by?: number;
1353
1354
  // gh#740: active ratified decisions for the cube, rendered by regen-format.
1354
1355
  // Local regen composes these via listDecisions.
1355
- decisions?: any[];
1356
+ decisions?: Decision[];
1357
+ decisions_error?: string;
1356
1358
  }> {
1357
1359
  const local = await localAuthorityContext(
1358
1360
  sessionToken,
@@ -1382,7 +1384,8 @@ export async function regen(
1382
1384
  ? await getLocalServerCursor(localCursorBinding(local))
1383
1385
  : await resolveLocalLogCursor(local, opts.since);
1384
1386
  const page = await localReadLogPage(local, { cursor, limit: 1 });
1385
- let decisions: any[] = [];
1387
+ let decisions: Decision[] | undefined;
1388
+ let decisionsError: string | undefined;
1386
1389
  try {
1387
1390
  decisions = (await listDecisions(
1388
1391
  sessionToken,
@@ -1391,8 +1394,12 @@ export async function regen(
1391
1394
  opts.serverTrustIdentity,
1392
1395
  )).decisions;
1393
1396
  } catch (error) {
1397
+ const constructorName = error instanceof Error ? error.constructor.name : '';
1398
+ decisionsError = /^[A-Za-z][A-Za-z0-9]*Error$/.test(constructorName)
1399
+ ? constructorName
1400
+ : 'UnknownError';
1394
1401
  console.warn(
1395
- `Local regen: failed to fetch ratified decisions (${error instanceof Error ? error.message : String(error)}); continuing without them.`,
1402
+ `Local regen: failed to fetch ratified decisions (${decisionsError}); continuing without them.`,
1396
1403
  );
1397
1404
  }
1398
1405
  return {
@@ -1403,7 +1410,8 @@ export async function regen(
1403
1410
  drones: composed.drones,
1404
1411
  recentLog: [],
1405
1412
  behind_by: page.entries.length + page.behind_by,
1406
- decisions,
1413
+ ...(decisions === undefined ? {} : { decisions }),
1414
+ ...(decisionsError === undefined ? {} : { decisions_error: decisionsError }),
1407
1415
  };
1408
1416
  }
1409
1417