@jungjaehoon/mama-os 0.32.0 → 0.32.1

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 (173) hide show
  1. package/dist/agent/agent-loop.d.ts +5 -1
  2. package/dist/agent/agent-loop.d.ts.map +1 -1
  3. package/dist/agent/agent-loop.js +62 -49
  4. package/dist/agent/agent-loop.js.map +1 -1
  5. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  6. package/dist/agent/code-act/host-bridge.js +35 -74
  7. package/dist/agent/code-act/host-bridge.js.map +1 -1
  8. package/dist/agent/gateway-tool-catalog.d.ts +14 -0
  9. package/dist/agent/gateway-tool-catalog.d.ts.map +1 -0
  10. package/dist/agent/gateway-tool-catalog.js +41 -0
  11. package/dist/agent/gateway-tool-catalog.js.map +1 -0
  12. package/dist/agent/gateway-tool-executor.d.ts +12 -1
  13. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  14. package/dist/agent/gateway-tool-executor.js +149 -15
  15. package/dist/agent/gateway-tool-executor.js.map +1 -1
  16. package/dist/agent/gateway-tools.md +5 -7
  17. package/dist/agent/tool-registry.d.ts +6 -4
  18. package/dist/agent/tool-registry.d.ts.map +1 -1
  19. package/dist/agent/tool-registry.js +62 -30
  20. package/dist/agent/tool-registry.js.map +1 -1
  21. package/dist/agent/types.d.ts +18 -2
  22. package/dist/agent/types.d.ts.map +1 -1
  23. package/dist/agent/types.js.map +1 -1
  24. package/dist/api/index.d.ts +10 -0
  25. package/dist/api/index.d.ts.map +1 -1
  26. package/dist/api/index.js +7 -16
  27. package/dist/api/index.js.map +1 -1
  28. package/dist/cli/commands/connector.d.ts +6 -1
  29. package/dist/cli/commands/connector.d.ts.map +1 -1
  30. package/dist/cli/commands/connector.js +61 -45
  31. package/dist/cli/commands/connector.js.map +1 -1
  32. package/dist/cli/commands/start.d.ts +11 -8
  33. package/dist/cli/commands/start.d.ts.map +1 -1
  34. package/dist/cli/commands/start.js +155 -88
  35. package/dist/cli/commands/start.js.map +1 -1
  36. package/dist/cli/config/types.d.ts.map +1 -1
  37. package/dist/cli/config/types.js +0 -4
  38. package/dist/cli/config/types.js.map +1 -1
  39. package/dist/cli/runtime/api-routes-init.d.ts +38 -1
  40. package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
  41. package/dist/cli/runtime/api-routes-init.js +150 -30
  42. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  43. package/dist/cli/runtime/api-server-init.d.ts +4 -0
  44. package/dist/cli/runtime/api-server-init.d.ts.map +1 -1
  45. package/dist/cli/runtime/api-server-init.js +3 -1
  46. package/dist/cli/runtime/api-server-init.js.map +1 -1
  47. package/dist/cli/runtime/connector-bootstrap.d.ts +8 -0
  48. package/dist/cli/runtime/connector-bootstrap.d.ts.map +1 -0
  49. package/dist/cli/runtime/connector-bootstrap.js +14 -0
  50. package/dist/cli/runtime/connector-bootstrap.js.map +1 -0
  51. package/dist/cli/runtime/connector-init.d.ts +4 -1
  52. package/dist/cli/runtime/connector-init.d.ts.map +1 -1
  53. package/dist/cli/runtime/connector-init.js +2 -8
  54. package/dist/cli/runtime/connector-init.js.map +1 -1
  55. package/dist/cli/runtime/envelope-bootstrap.d.ts +2 -1
  56. package/dist/cli/runtime/envelope-bootstrap.d.ts.map +1 -1
  57. package/dist/cli/runtime/envelope-bootstrap.js +7 -15
  58. package/dist/cli/runtime/envelope-bootstrap.js.map +1 -1
  59. package/dist/connectors/index.d.ts +4 -1
  60. package/dist/connectors/index.d.ts.map +1 -1
  61. package/dist/connectors/index.js +3 -2
  62. package/dist/connectors/index.js.map +1 -1
  63. package/dist/connectors/private-connector-policy.d.ts +150 -0
  64. package/dist/connectors/private-connector-policy.d.ts.map +1 -0
  65. package/dist/connectors/private-connector-policy.js +289 -0
  66. package/dist/connectors/private-connector-policy.js.map +1 -0
  67. package/dist/connectors/private-prompt-overlay.d.ts +17 -0
  68. package/dist/connectors/private-prompt-overlay.d.ts.map +1 -0
  69. package/dist/connectors/private-prompt-overlay.js +156 -0
  70. package/dist/connectors/private-prompt-overlay.js.map +1 -0
  71. package/dist/db/migrations/operator-task-external-lifecycle.d.ts +8 -0
  72. package/dist/db/migrations/operator-task-external-lifecycle.d.ts.map +1 -0
  73. package/dist/db/migrations/operator-task-external-lifecycle.js +169 -0
  74. package/dist/db/migrations/operator-task-external-lifecycle.js.map +1 -0
  75. package/dist/envelope/enforcer.js +8 -7
  76. package/dist/envelope/enforcer.js.map +1 -1
  77. package/dist/envelope/reactive-config.d.ts.map +1 -1
  78. package/dist/envelope/reactive-config.js +2 -1
  79. package/dist/envelope/reactive-config.js.map +1 -1
  80. package/dist/envelope/tool-connector-scope.d.ts.map +1 -1
  81. package/dist/envelope/tool-connector-scope.js +4 -0
  82. package/dist/envelope/tool-connector-scope.js.map +1 -1
  83. package/dist/gateways/message-router.d.ts +11 -1
  84. package/dist/gateways/message-router.d.ts.map +1 -1
  85. package/dist/gateways/message-router.js +121 -41
  86. package/dist/gateways/message-router.js.map +1 -1
  87. package/dist/gateways/telegram-message-ledger.d.ts +8 -1
  88. package/dist/gateways/telegram-message-ledger.d.ts.map +1 -1
  89. package/dist/gateways/telegram-message-ledger.js +141 -24
  90. package/dist/gateways/telegram-message-ledger.js.map +1 -1
  91. package/dist/gateways/telegram.d.ts +2 -0
  92. package/dist/gateways/telegram.d.ts.map +1 -1
  93. package/dist/gateways/telegram.js +19 -12
  94. package/dist/gateways/telegram.js.map +1 -1
  95. package/dist/multi-agent/agent-process-manager.d.ts +9 -1
  96. package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
  97. package/dist/multi-agent/agent-process-manager.js +48 -20
  98. package/dist/multi-agent/agent-process-manager.js.map +1 -1
  99. package/dist/multi-agent/dashboard-agent-persona.d.ts +3 -3
  100. package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
  101. package/dist/multi-agent/dashboard-agent-persona.js +10 -13
  102. package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
  103. package/dist/multi-agent/memory-agent-persona.d.ts +1 -1
  104. package/dist/multi-agent/memory-agent-persona.d.ts.map +1 -1
  105. package/dist/multi-agent/memory-agent-persona.js +1 -1
  106. package/dist/multi-agent/wiki-agent-persona.d.ts +2 -2
  107. package/dist/multi-agent/wiki-agent-persona.js +2 -2
  108. package/dist/operator/board-slot-instructions.d.ts +1 -1
  109. package/dist/operator/board-slot-instructions.js +2 -2
  110. package/dist/operator/board-slot-instructions.js.map +1 -1
  111. package/dist/operator/briefs.d.ts +3 -0
  112. package/dist/operator/briefs.d.ts.map +1 -1
  113. package/dist/operator/briefs.js +64 -3
  114. package/dist/operator/briefs.js.map +1 -1
  115. package/dist/operator/console-brief.d.ts +6 -3
  116. package/dist/operator/console-brief.d.ts.map +1 -1
  117. package/dist/operator/console-brief.js +39 -9
  118. package/dist/operator/console-brief.js.map +1 -1
  119. package/dist/operator/external-lifecycle-candidates.d.ts +56 -0
  120. package/dist/operator/external-lifecycle-candidates.d.ts.map +1 -0
  121. package/dist/operator/external-lifecycle-candidates.js +415 -0
  122. package/dist/operator/external-lifecycle-candidates.js.map +1 -0
  123. package/dist/operator/external-lifecycle.d.ts +82 -0
  124. package/dist/operator/external-lifecycle.d.ts.map +1 -0
  125. package/dist/operator/external-lifecycle.js +27 -0
  126. package/dist/operator/external-lifecycle.js.map +1 -0
  127. package/dist/operator/file-coordination.d.ts +7 -0
  128. package/dist/operator/file-coordination.d.ts.map +1 -0
  129. package/dist/operator/file-coordination.js +84 -0
  130. package/dist/operator/file-coordination.js.map +1 -0
  131. package/dist/operator/operator-trigger-loop.d.ts +19 -4
  132. package/dist/operator/operator-trigger-loop.d.ts.map +1 -1
  133. package/dist/operator/operator-trigger-loop.js +151 -23
  134. package/dist/operator/operator-trigger-loop.js.map +1 -1
  135. package/dist/operator/pending-report-store.d.ts +62 -3
  136. package/dist/operator/pending-report-store.d.ts.map +1 -1
  137. package/dist/operator/pending-report-store.js +297 -40
  138. package/dist/operator/pending-report-store.js.map +1 -1
  139. package/dist/operator/report-carry-delivery.d.ts +35 -0
  140. package/dist/operator/report-carry-delivery.d.ts.map +1 -0
  141. package/dist/operator/report-carry-delivery.js +55 -0
  142. package/dist/operator/report-carry-delivery.js.map +1 -0
  143. package/dist/operator/report-carry.d.ts +50 -30
  144. package/dist/operator/report-carry.d.ts.map +1 -1
  145. package/dist/operator/report-carry.js +323 -71
  146. package/dist/operator/report-carry.js.map +1 -1
  147. package/dist/operator/situation-report.d.ts +30 -11
  148. package/dist/operator/situation-report.d.ts.map +1 -1
  149. package/dist/operator/situation-report.js +42 -13
  150. package/dist/operator/situation-report.js.map +1 -1
  151. package/dist/operator/task-ledger.d.ts +101 -0
  152. package/dist/operator/task-ledger.d.ts.map +1 -1
  153. package/dist/operator/task-ledger.js +599 -124
  154. package/dist/operator/task-ledger.js.map +1 -1
  155. package/dist/operator/temporal-worker.js +1 -1
  156. package/dist/operator/worker-run.d.ts +1 -1
  157. package/dist/operator/worker-run.d.ts.map +1 -1
  158. package/dist/operator/worker-run.js +17 -5
  159. package/dist/operator/worker-run.js.map +1 -1
  160. package/dist/operator/workorder-consumer.d.ts +12 -1
  161. package/dist/operator/workorder-consumer.d.ts.map +1 -1
  162. package/dist/operator/workorder-consumer.js +125 -6
  163. package/dist/operator/workorder-consumer.js.map +1 -1
  164. package/dist/operator/workorder-hooks.d.ts +7 -2
  165. package/dist/operator/workorder-hooks.d.ts.map +1 -1
  166. package/dist/operator/workorder-hooks.js +22 -0
  167. package/dist/operator/workorder-hooks.js.map +1 -1
  168. package/dist/operator/workorder-publishers.d.ts +9 -2
  169. package/dist/operator/workorder-publishers.d.ts.map +1 -1
  170. package/dist/operator/workorder-publishers.js +167 -5
  171. package/dist/operator/workorder-publishers.js.map +1 -1
  172. package/package.json +2 -2
  173. package/scripts/generate-gateway-tools.ts +13 -3
@@ -73,6 +73,7 @@ const gateway_tool_executor_js_1 = require("../../agent/gateway-tool-executor.js
73
73
  const context_compile_service_js_1 = require("../../agent/context-compile-service.js");
74
74
  const read_js_1 = require("../../evidence/read.js");
75
75
  const tool_registry_js_1 = require("../../agent/tool-registry.js");
76
+ const gateway_tool_catalog_js_1 = require("../../agent/gateway-tool-catalog.js");
76
77
  const tool_policy_js_1 = require("../../agent/code-act/tool-policy.js");
77
78
  const run_context_registry_js_1 = require("../../agent/code-act/run-context-registry.js");
78
79
  const index_js_2 = require("../../gateways/index.js");
@@ -100,6 +101,9 @@ const api_routes_init_js_1 = require("../runtime/api-routes-init.js");
100
101
  const server_start_js_1 = require("../runtime/server-start.js");
101
102
  const shutdown_js_1 = require("../runtime/shutdown.js");
102
103
  const envelope_bootstrap_js_1 = require("../runtime/envelope-bootstrap.js");
104
+ const config_loader_js_1 = require("../../connectors/config-loader.js");
105
+ const connector_bootstrap_js_1 = require("../runtime/connector-bootstrap.js");
106
+ const private_connector_policy_js_1 = require("../../connectors/private-connector-policy.js");
103
107
  const message_router_config_js_1 = require("../runtime/message-router-config.js");
104
108
  const reactive_config_js_1 = require("../../envelope/reactive-config.js");
105
109
  const scope_context_js_1 = require("../../memory/scope-context.js");
@@ -109,6 +113,7 @@ const node_crypto_1 = require("node:crypto");
109
113
  const debugLogger = __importStar(require("@jungjaehoon/mama-core/debug-logger"));
110
114
  const mama_core_1 = require("@jungjaehoon/mama-core");
111
115
  const report_run_js_1 = require("../../operator/report-run.js");
116
+ const report_carry_js_1 = require("../../operator/report-carry.js");
112
117
  const console_brief_js_1 = require("../../operator/console-brief.js");
113
118
  const task_ledger_js_1 = require("../../operator/task-ledger.js");
114
119
  const conductor_inbox_js_1 = require("../../operator/conductor-inbox.js");
@@ -125,6 +130,11 @@ const workorder_consumer_js_1 = require("../../operator/workorder-consumer.js");
125
130
  const { DebugLogger } = debugLogger;
126
131
  const codeActLogger = new DebugLogger('CodeAct');
127
132
  const temporalLogger = new DebugLogger('TemporalReconcile');
133
+ const DISABLED_PRIVATE_CONNECTOR_POLICY = (0, private_connector_policy_js_1.resolvePrivateConnectorPolicy)({
134
+ ok: true,
135
+ config: {},
136
+ enabledNames: [],
137
+ });
128
138
  function requireRuntimeBackend(value) {
129
139
  if (value === 'claude' || value === 'codex') {
130
140
  return value;
@@ -343,15 +353,19 @@ function causeEventIdsFromPayload(payload) {
343
353
  }
344
354
  function workOrderEnvelopeScope(input) {
345
355
  const isTemporal = input.workKind === 'temporal';
356
+ const surface = (0, private_connector_policy_js_1.resolveWorkOrderPrivateSurface)(input.workKind);
357
+ const candidateConnectors = isTemporal
358
+ ? input.temporalBinding
359
+ ? [input.temporalBinding.connector]
360
+ : []
361
+ : input.laneConnectors;
346
362
  return {
347
363
  project_refs: [{ kind: 'project', id: input.projectId }],
348
364
  // A temporal run reads its task's connector or nothing. Every other lane keeps the
349
365
  // connectors it was configured with.
350
- raw_connectors: isTemporal
351
- ? input.temporalBinding
352
- ? [input.temporalBinding.connector]
353
- : []
354
- : input.laneConnectors,
366
+ raw_connectors: [
367
+ ...input.privateConnectorPolicy.projectRawConnectors(surface, candidateConnectors),
368
+ ],
355
369
  memory_scopes: [
356
370
  ...(0, scope_context_js_1.deriveMemoryScopes)({
357
371
  source: 'operator',
@@ -410,13 +424,11 @@ exports.WORKORDER_TOOL_POLICIES = {
410
424
  'changes_read',
411
425
  'context_compile',
412
426
  'contract_no_update',
413
- 'kagemusha_entities',
414
- 'kagemusha_messages',
415
- 'kagemusha_overview',
416
- 'kagemusha_tasks',
417
427
  'mama_search',
418
428
  'report_publish',
419
429
  'task_create',
430
+ 'task_external_bind',
431
+ 'task_lifecycle_reconcile',
420
432
  'task_list',
421
433
  'task_update',
422
434
  'trello_card',
@@ -430,23 +442,13 @@ exports.WORKORDER_TOOL_POLICIES = {
430
442
  },
431
443
  'memory-curation': {
432
444
  roleName: 'workorder-memory-curation',
433
- allowedTools: [
434
- 'agent_notices',
435
- 'kagemusha_entities',
436
- 'kagemusha_messages',
437
- 'mama_save',
438
- 'mama_search',
439
- ],
445
+ allowedTools: ['agent_notices', 'mama_save', 'mama_search'],
440
446
  },
441
447
  temporal: {
442
448
  roleName: 'workorder-temporal',
443
449
  allowedTools: [
444
450
  'agent_notices',
445
451
  'context_compile',
446
- 'kagemusha_entities',
447
- 'kagemusha_messages',
448
- 'kagemusha_overview',
449
- 'kagemusha_tasks',
450
452
  'schedule_upcoming',
451
453
  'task_list',
452
454
  'task_temporal_reconcile',
@@ -484,10 +486,6 @@ exports.OPERATOR_REPORT_TOOL_POLICY = {
484
486
  // answer that was to re-read current state and infer the delta, which is how a
485
487
  // report ends up restating the board instead of naming the change.
486
488
  'changes_read',
487
- 'kagemusha_entities',
488
- 'kagemusha_messages',
489
- 'kagemusha_overview',
490
- 'kagemusha_tasks',
491
489
  'mama_provenance',
492
490
  'mama_recall',
493
491
  'mama_save',
@@ -499,6 +497,28 @@ exports.OPERATOR_REPORT_TOOL_POLICY = {
499
497
  'trello_kanban',
500
498
  ],
501
499
  };
500
+ function requirePrivateConnectorPolicy(privateConnectorPolicy) {
501
+ if (!privateConnectorPolicy) {
502
+ throw new Error('privateConnectorPolicy is required');
503
+ }
504
+ return privateConnectorPolicy;
505
+ }
506
+ function buildProjectedLaneRole(surface, allowedTools, privateConnectorPolicy) {
507
+ return privateConnectorPolicy.projectRole(surface, {
508
+ allowedTools: [...allowedTools],
509
+ blockedTools: [],
510
+ allowedPaths: [],
511
+ systemControl: false,
512
+ sensitiveAccess: false,
513
+ });
514
+ }
515
+ function buildProjectedLanePrompt(innerTools, surface, privateConnectorPolicy) {
516
+ return (0, gateway_tool_catalog_js_1.buildGatewayToolCatalog)({
517
+ surface,
518
+ allowedTools: innerTools,
519
+ privateConnectorPolicy,
520
+ }).prompt;
521
+ }
502
522
  /**
503
523
  * The conductor's grant (S1). Reads and judgment surfaces plus the ONE write
504
524
  * family the spec's center names: committing work orders and board cards. No
@@ -520,7 +540,7 @@ exports.CONDUCTOR_TOOL_POLICY = {
520
540
  ],
521
541
  };
522
542
  /** Mirrors buildOperatorReportAgentPolicy - same shape, conductor grant. */
523
- function buildConductorAgentPolicy(model, backend) {
543
+ function buildConductorAgentPolicy(model, backend, privateConnectorPolicy) {
524
544
  const blockedTools = [];
525
545
  const innerTools = uniqueToolList(exports.CONDUCTOR_TOOL_POLICY.allowedTools);
526
546
  const allowedTools = uniqueToolList([...innerTools]);
@@ -547,7 +567,15 @@ function buildConductorAgentPolicy(model, backend) {
547
567
  tier: 2,
548
568
  backend,
549
569
  };
550
- return { agentContext, gatewayToolsPrompt: tool_registry_js_1.ToolRegistry.generatePrompt(innerTools) };
570
+ return {
571
+ agentContext,
572
+ gatewayToolsPrompt: (0, gateway_tool_catalog_js_1.buildGatewayToolCatalog)({
573
+ surface: 'multi-agent-generic',
574
+ allowedTools: innerTools,
575
+ privateConnectorPolicy,
576
+ }).prompt,
577
+ briefProjectionPolicy: DISABLED_PRIVATE_CONNECTOR_POLICY,
578
+ };
551
579
  }
552
580
  /**
553
581
  * Merge + validate the conductor config at boot. No-fallback: a malformed
@@ -581,22 +609,18 @@ function resolveConductorConfig(config) {
581
609
  * logs "executed NO gateway gather tools" while still being delivered. Mirrors
582
610
  * buildWorkOrderAgentPolicy so both operator job families get their permissions the same way.
583
611
  */
584
- function buildOperatorReportAgentPolicy(model, backend) {
585
- const blockedTools = [];
586
- const innerTools = uniqueToolList(exports.OPERATOR_REPORT_TOOL_POLICY.allowedTools);
612
+ function buildOperatorReportAgentPolicy(model, backend, privateConnectorPolicy) {
613
+ const requiredPrivatePolicy = requirePrivateConnectorPolicy(privateConnectorPolicy);
614
+ const surface = 'operator-report';
615
+ const projectedRole = buildProjectedLaneRole(surface, exports.OPERATOR_REPORT_TOOL_POLICY.allowedTools, requiredPrivatePolicy);
616
+ const blockedTools = [...(projectedRole.blockedTools ?? [])];
617
+ const innerTools = uniqueToolList(projectedRole.allowedTools);
587
618
  const allowedTools = uniqueToolList(['code_act', ...innerTools]);
588
619
  const agentContext = {
589
620
  source: 'operator',
590
621
  platform: 'cli',
591
622
  roleName: exports.OPERATOR_REPORT_TOOL_POLICY.roleName,
592
- role: {
593
- allowedTools,
594
- blockedTools,
595
- allowedPaths: [],
596
- systemControl: false,
597
- sensitiveAccess: false,
598
- model,
599
- },
623
+ role: { ...projectedRole, allowedTools, blockedTools, model },
600
624
  session: {
601
625
  sessionId: report_run_js_1.OPERATOR_REPORT_SESSION_KEY,
602
626
  channelId: 'report',
@@ -609,28 +633,34 @@ function buildOperatorReportAgentPolicy(model, backend) {
609
633
  tier: 2,
610
634
  backend,
611
635
  };
612
- return { agentContext, gatewayToolsPrompt: tool_registry_js_1.ToolRegistry.generatePrompt(innerTools) };
636
+ return {
637
+ agentContext,
638
+ gatewayToolsPrompt: buildProjectedLanePrompt(innerTools, surface, requiredPrivatePolicy),
639
+ briefProjectionPolicy: requiredPrivatePolicy,
640
+ };
613
641
  }
614
- function buildWorkOrderAgentPolicy(kind, model, backend) {
642
+ function buildWorkOrderAgentPolicy(kind, model, backend, privateConnectorPolicy, rawConnectorScope) {
643
+ const requiredPrivatePolicy = requirePrivateConnectorPolicy(privateConnectorPolicy);
644
+ if (!rawConnectorScope) {
645
+ throw new Error('rawConnectorScope is required');
646
+ }
615
647
  const policy = exports.WORKORDER_TOOL_POLICIES[kind];
616
648
  if (!policy) {
617
649
  throw new Error(`Missing built-in workorder tool policy for '${kind}'`);
618
650
  }
619
- const blockedTools = [];
620
- const innerTools = uniqueToolList(policy.allowedTools);
651
+ const surface = (0, private_connector_policy_js_1.resolveWorkOrderPrivateSurface)(kind);
652
+ const scopedSurface = requiredPrivatePolicy.enabledPrivateConnectors.some((name) => rawConnectorScope.includes(name))
653
+ ? surface
654
+ : 'multi-agent-generic';
655
+ const projectedRole = buildProjectedLaneRole(scopedSurface, policy.allowedTools, requiredPrivatePolicy);
656
+ const blockedTools = [...(projectedRole.blockedTools ?? [])];
657
+ const innerTools = uniqueToolList(projectedRole.allowedTools);
621
658
  const allowedTools = uniqueToolList(['code_act', ...innerTools]);
622
659
  const agentContext = {
623
660
  source: 'operator',
624
661
  platform: 'cli',
625
662
  roleName: policy.roleName,
626
- role: {
627
- allowedTools,
628
- blockedTools,
629
- allowedPaths: [],
630
- systemControl: false,
631
- sensitiveAccess: false,
632
- model,
633
- },
663
+ role: { ...projectedRole, allowedTools, blockedTools, model },
634
664
  session: {
635
665
  sessionId: `operator:worker:${kind}`,
636
666
  channelId: `worker:${kind}`,
@@ -643,7 +673,10 @@ function buildWorkOrderAgentPolicy(kind, model, backend) {
643
673
  };
644
674
  return {
645
675
  agentContext,
646
- gatewayToolsPrompt: tool_registry_js_1.ToolRegistry.generatePrompt(innerTools),
676
+ gatewayToolsPrompt: buildProjectedLanePrompt(innerTools, scopedSurface, requiredPrivatePolicy),
677
+ briefProjectionPolicy: scopedSurface === 'multi-agent-generic'
678
+ ? DISABLED_PRIVATE_CONNECTOR_POLICY
679
+ : requiredPrivatePolicy,
647
680
  };
648
681
  }
649
682
  function bindCodeActParentModelRun(adapter, executionContext, options) {
@@ -821,8 +854,9 @@ async function runAgentLoop(config, options = {}) {
821
854
  // (workorders are the only run path since v0.28.0).
822
855
  const temporalStartup = (0, temporal_runtime_js_1.preflightTemporalStartup)(process.env);
823
856
  const runtimeBackend = requireRuntimeBackend(config.agent.backend);
857
+ const { connectorConfigLoadResult, privateConnectorPolicy } = (0, connector_bootstrap_js_1.resolveRuntimeConnectorBootstrap)((0, config_loader_js_1.loadConnectorConfig)());
824
858
  const temporalPolicy = temporalStartup.temporalFlag === 'on'
825
- ? buildWorkOrderAgentPolicy('temporal', config.agent.model, runtimeBackend)
859
+ ? buildWorkOrderAgentPolicy('temporal', config.agent.model, runtimeBackend, privateConnectorPolicy, [])
826
860
  : null;
827
861
  const temporalEffectiveTools = temporalPolicy
828
862
  ? (0, tool_policy_js_1.projectCodeActToolPolicy)({
@@ -867,7 +901,7 @@ async function runAgentLoop(config, options = {}) {
867
901
  process.env.MAMA_WORKSPACE = workspaceRoot;
868
902
  // Initialize channel history with SQLite persistence (Sprint 3 F5)
869
903
  (0, index_js_2.initChannelHistory)(db);
870
- const envelopeBootstrap = (0, envelope_bootstrap_js_1.buildRuntimeEnvelopeBootstrap)(db, config, process.env);
904
+ const envelopeBootstrap = (0, envelope_bootstrap_js_1.buildRuntimeEnvelopeBootstrap)(db, config, process.env, connectorConfigLoadResult);
871
905
  const mamaDbPath = (0, config_manager_js_1.expandPath)(config.database.path);
872
906
  const toolExecutor = new gateway_tool_executor_js_1.GatewayToolExecutor({
873
907
  mamaDbPath: mamaDbPath,
@@ -875,6 +909,7 @@ async function runAgentLoop(config, options = {}) {
875
909
  rolesConfig: config.roles, // Pass roles from config.yaml
876
910
  envelopeIssuanceMode: envelopeBootstrap.metadata.issuance,
877
911
  metricsStore,
912
+ privateConnectorPolicy,
878
913
  });
879
914
  process.env.MAMA_BACKEND = runtimeBackend;
880
915
  const agentLoopBackend = runtimeBackend;
@@ -903,7 +938,7 @@ async function runAgentLoop(config, options = {}) {
903
938
  toolExecutor.setContextCompileService(contextCompileService);
904
939
  agentLoop.setContextCompileService(contextCompileService);
905
940
  // ── Phase 4: Memory Agent + MessageRouter ─────────────────────────────────
906
- const messageRouter = new index_js_2.MessageRouter(sessionStore, agentLoopClient, mamaApiClient, (0, message_router_config_js_1.resolveMessageRouterConfig)(config, runtimeBackend), envelopeBootstrap.envelopeConfig, envelopeBootstrap.envelopeAuthority);
941
+ const messageRouter = new index_js_2.MessageRouter(sessionStore, agentLoopClient, mamaApiClient, (0, message_router_config_js_1.resolveMessageRouterConfig)(config, runtimeBackend), envelopeBootstrap.envelopeConfig, envelopeBootstrap.envelopeAuthority, { privateConnectorPolicy, reportCarry: new report_carry_js_1.FileReportCarryStore() });
907
942
  messageRouter.setSessionsDb(db);
908
943
  // validationService wired after creation (Phase 5 below)
909
944
  const { memoryAgentLoop } = await (0, memory_agent_init_js_1.initMemoryAgent)(oauthManager, config, mamaApi, mamaApiClient, messageRouter, agentLoopBackend, toolExecutor);
@@ -918,7 +953,7 @@ async function runAgentLoop(config, options = {}) {
918
953
  sessionsDb: db,
919
954
  uiCommandQueue,
920
955
  };
921
- let codeActRawConnectors = [];
956
+ const codeActRawConnectors = resolveCodeActRawConnectors(connectorConfigLoadResult.enabledNames);
922
957
  // Wire uiCommandQueue into messageRouter for page context awareness
923
958
  messageRouter.setUICommandQueue(uiCommandQueue);
924
959
  // Wire sessionsDb into gateway tool executor
@@ -929,13 +964,16 @@ async function runAgentLoop(config, options = {}) {
929
964
  const executeLegacyCodeAct = async (code, codeActContext) => {
930
965
  const { CodeActSandbox, HostBridge } = await import('../../agent/code-act/index.js');
931
966
  const sandbox = new CodeActSandbox();
932
- const resolvedCodeActPolicy = resolveCodeActAgentPolicy(codeActContext, config.multi_agent?.agents, config.multi_agent?.default_agent || 'conductor');
967
+ const legacyRequestContext = codeActContext
968
+ ? { ...codeActContext, agentId: undefined }
969
+ : undefined;
970
+ const resolvedCodeActPolicy = resolveCodeActAgentPolicy(legacyRequestContext, config.multi_agent?.agents, config.multi_agent?.default_agent || 'conductor');
933
971
  if (resolvedCodeActPolicy.error) {
934
972
  return { success: false, error: resolvedCodeActPolicy.error };
935
973
  }
936
974
  const codeActAgentId = resolvedCodeActPolicy.agentId;
937
975
  const codeActPolicy = resolvedCodeActPolicy.policy ?? {};
938
- const codeActRole = buildCodeActRole(codeActPolicy);
976
+ const codeActRole = privateConnectorPolicy.projectRole('legacy-unbound', buildCodeActRole(codeActPolicy));
939
977
  const codeActReadOnly = isTruthyEnvValue(process.env.MAMA_CODE_ACT_READ_ONLY);
940
978
  const codeActTier = codeActReadOnly ? 3 : 2;
941
979
  const instanceId = (0, node_crypto_1.randomUUID)();
@@ -958,7 +996,9 @@ async function runAgentLoop(config, options = {}) {
958
996
  trigger_context: { user_text: '<api-code-act invocation>' },
959
997
  scope: {
960
998
  project_refs: [projectRef],
961
- raw_connectors: codeActRawConnectors,
999
+ raw_connectors: [
1000
+ ...privateConnectorPolicy.projectRawConnectors('legacy-unbound', codeActRawConnectors),
1001
+ ],
962
1002
  memory_scopes: memoryScopes,
963
1003
  allowed_destinations: [],
964
1004
  },
@@ -1172,6 +1212,7 @@ async function runAgentLoop(config, options = {}) {
1172
1212
  const pm = new AgentProcessManager(fallbackMultiAgentConfig, buildSystemAgentProcessDefaults(config), {
1173
1213
  backend: runtimeBackend,
1174
1214
  model: config.agent.model,
1215
+ privateConnectorPolicy,
1175
1216
  });
1176
1217
  toolExecutor.setAgentProcessManager(pm);
1177
1218
  agentLoop.setAgentProcessManager(pm);
@@ -1332,15 +1373,35 @@ async function runAgentLoop(config, options = {}) {
1332
1373
  noticeOwner: (summary) => messageRouter.enqueueOperatorNotice(summary),
1333
1374
  opsAlarm,
1334
1375
  runOptionsFor: async (wo) => {
1376
+ // Resolve the run's raw binding before constructing either backend's
1377
+ // role/catalog. The catalog and execution envelope must use the same
1378
+ // projection so an unbound or non-private run never advertises private
1379
+ // connector tools it cannot execute.
1380
+ const workOrderBatch = causeEventIdsFromPayload(wo.payload);
1381
+ let temporalContext;
1382
+ let temporalBinding = null;
1383
+ if (wo.workKind === 'temporal') {
1384
+ temporalContext = (0, temporal_worker_js_1.buildTemporalWorkerContext)(taskLedger, wo);
1385
+ temporalBinding = temporalTaskBinding(taskLedger, temporalContext.taskId);
1386
+ }
1387
+ const projectId = (0, reactive_config_js_1.resolveReactiveProjectRoot)(config, process.env);
1388
+ const workOrderScope = workOrderEnvelopeScope({
1389
+ workKind: wo.workKind,
1390
+ projectId,
1391
+ laneConnectors: codeActRawConnectors,
1392
+ temporalBinding,
1393
+ privateConnectorPolicy,
1394
+ });
1335
1395
  // Worker prompt selects the provider's supported tool path: Claude's
1336
1396
  // text gateway or Codex's injected native host tools. Both avoid the
1337
1397
  // spawn-default code-act path, where per-run envelope/capture overrides
1338
1398
  // cannot reach (shadow-gate §8.2).
1339
1399
  const { buildWorkerSystemPrompt } = await import('../../operator/worker-run.js');
1340
- const workOrderPolicy = buildWorkOrderAgentPolicy(wo.workKind, config.agent.model, runtimeBackend);
1400
+ const workOrderPolicy = buildWorkOrderAgentPolicy(wo.workKind, config.agent.model, runtimeBackend, privateConnectorPolicy, workOrderScope.raw_connectors);
1341
1401
  const runOptions = attachWorkOrderAttemptContext({
1342
1402
  systemPrompt: buildWorkerSystemPrompt(workOrderPolicy.gatewayToolsPrompt, runtimeBackend, wo.workKind),
1343
1403
  agentContext: workOrderPolicy.agentContext,
1404
+ workOrderBriefProjectionPolicy: workOrderPolicy.briefProjectionPolicy,
1344
1405
  }, wo.id);
1345
1406
  // A temporal run is bound to ONE task on ONE channel, and the packet check
1346
1407
  // (temporalPacketRawSourcesWithinBoundSource) enforces exactly that: every raw ref
@@ -1359,15 +1420,11 @@ async function runAgentLoop(config, options = {}) {
1359
1420
  // durable change the run produces rest on it WITHOUT the agent restating anything -
1360
1421
  // the system knew the batch before the run began. This is the whole difference
1361
1422
  // between a bounded run and an unbounded one.
1362
- const workOrderBatch = causeEventIdsFromPayload(wo.payload);
1363
1423
  if (workOrderBatch.length > 0) {
1364
1424
  runOptions.causeEventIds = workOrderBatch;
1365
1425
  }
1366
- let temporalBinding = null;
1367
- if (wo.workKind === 'temporal') {
1368
- const temporalContext = (0, temporal_worker_js_1.buildTemporalWorkerContext)(taskLedger, wo);
1426
+ if (temporalContext) {
1369
1427
  runOptions.temporalWorkContext = temporalContext;
1370
- temporalBinding = temporalTaskBinding(taskLedger, temporalContext.taskId);
1371
1428
  }
1372
1429
  // Per-run scoped envelope (live-gate finding, 2026-07-18): gateway
1373
1430
  // 'model_tool' executions are envelope-gated, and workerRun is a new
@@ -1376,7 +1433,6 @@ async function runAgentLoop(config, options = {}) {
1376
1433
  // lane's issuance (createPersonaReportAsk wiring below); issuance
1377
1434
  // failure rejects -> failWorkOrder (no envelope-less fallback run).
1378
1435
  if (envelopeBootstrap.envelopeAuthority && envelopeBootstrap.metadata.issuance !== 'off') {
1379
- const projectId = (0, reactive_config_js_1.resolveReactiveProjectRoot)(config, process.env);
1380
1436
  const wallSeconds = Math.min(Math.max(Number(process.env.MAMA_REPORT_WALL_SECONDS) || 900, 60), 1800);
1381
1437
  runOptions.envelope = await envelopeBootstrap.envelopeAuthority.buildAndPersist({
1382
1438
  agent_id: `workorder-${wo.workKind}`,
@@ -1386,16 +1442,8 @@ async function runAgentLoop(config, options = {}) {
1386
1442
  source: 'watch',
1387
1443
  channel_id: `worker:${wo.workKind}`,
1388
1444
  trigger_context: { user_text: `<stage2 workorder ${wo.workKind}#${wo.id}>` },
1389
- scope: (() => {
1390
- const scope = workOrderEnvelopeScope({
1391
- workKind: wo.workKind,
1392
- projectId,
1393
- laneConnectors: codeActRawConnectors,
1394
- temporalBinding,
1395
- });
1396
- // Identity scopes only - the read mirror is enforcement-layer.
1397
- return scope;
1398
- })(),
1445
+ // Identity scopes only - the read mirror is enforcement-layer.
1446
+ scope: workOrderScope,
1399
1447
  tier: 2,
1400
1448
  budget: { wall_seconds: wallSeconds },
1401
1449
  expires_at: new Date(Date.now() + wallSeconds * 1000 + 30_000).toISOString(),
@@ -1490,8 +1538,10 @@ async function runAgentLoop(config, options = {}) {
1490
1538
  log: (line) => temporalLogger.info(line),
1491
1539
  });
1492
1540
  temporalRuntime = temporalAssembly.runtime;
1493
- const { rawStoreForApi, enabledConnectorNames, connectorSchedulerStop } = await (0, connector_init_js_1.initConnectors)(connectorExtractionFn, { nudge: () => triggerLoopNudge.current?.() });
1494
- codeActRawConnectors = resolveCodeActRawConnectors(enabledConnectorNames);
1541
+ const { rawStoreForApi, enabledConnectorNames, connectorSchedulerStop } = await (0, connector_init_js_1.initConnectors)(connectorExtractionFn, {
1542
+ connectorConfigLoadResult,
1543
+ nudge: () => triggerLoopNudge.current?.(),
1544
+ });
1495
1545
  // Inject rawStore into tool executor for agent_test connector data access
1496
1546
  if (rawStoreForApi) {
1497
1547
  toolExecutor.setRawStore(rawStoreForApi);
@@ -1525,7 +1575,7 @@ async function runAgentLoop(config, options = {}) {
1525
1575
  const { createTriggerAgentRuntime } = await import('../../operator/trigger-author.js');
1526
1576
  const { reviewTriggerCLI } = await import('../../operator/trigger-review.js');
1527
1577
  const { ReportScheduler, FileReportScheduleStore, parseReportHours } = await import('../../operator/report-scheduler.js');
1528
- const { persistLastFullReport } = await import('../../operator/report-carry.js');
1578
+ const { createTelegramReportCarryDelivery, createTelegramReportOutput } = await import('../../operator/report-carry-delivery.js');
1529
1579
  // Set when a report is composed, read when that same report is delivered. Safe
1530
1580
  // because ALL operator work serializes on the operator lane (SOURCE_GLOBAL_LANES),
1531
1581
  // so compose and deliver cannot interleave with another report - stated here
@@ -1542,10 +1592,14 @@ async function runAgentLoop(config, options = {}) {
1542
1592
  // Owner-report leg (M1.5): destination chat comes from env (~/.mama/start.sh),
1543
1593
  // never source. No chat configured or no telegram gateway -> loop stays read-only.
1544
1594
  const reportChatId = resolveOperatorReportChatId(process.env, config.telegram?.allowed_chats);
1595
+ const persistReportCarry = reportChatId
1596
+ ? createTelegramReportCarryDelivery({
1597
+ reportChatId,
1598
+ carryStore: new report_carry_js_1.FileReportCarryStore(),
1599
+ })
1600
+ : undefined;
1545
1601
  const reportOutput = reportChatId && telegramGateway
1546
- ? {
1547
- send: (text, deliveryId) => telegramGateway.sendMessage(reportChatId, text, deliveryId ?? `operator-report:legacy:${(0, node_crypto_1.randomUUID)()}`),
1548
- }
1602
+ ? createTelegramReportOutput({ reportChatId, telegramSender: telegramGateway })
1549
1603
  : undefined;
1550
1604
  // Scheduled full-report leg (M2): local hours from env (~/.mama/start.sh), never source.
1551
1605
  // Empty/absent -> [] -> leg off. Requires the same telegram sink as the digest leg.
@@ -1610,7 +1664,9 @@ async function runAgentLoop(config, options = {}) {
1610
1664
  // read authority is bounded per tool by envelope/tool-connector-scope.ts
1611
1665
  // against the connectors granted here.
1612
1666
  project_refs: [{ kind: 'project', id: projectId }],
1613
- raw_connectors: codeActRawConnectors,
1667
+ raw_connectors: [
1668
+ ...privateConnectorPolicy.projectRawConnectors('operator-report', codeActRawConnectors),
1669
+ ],
1614
1670
  memory_scopes: uniqueMemoryScopes((0, scope_context_js_1.deriveMemoryScopes)({ source: 'operator', channelId: 'report', projectId })),
1615
1671
  allowed_destinations: [],
1616
1672
  },
@@ -1621,6 +1677,7 @@ async function runAgentLoop(config, options = {}) {
1621
1677
  }
1622
1678
  : undefined,
1623
1679
  run: async (prompt, envelope) => {
1680
+ const reportAgentPolicy = buildOperatorReportAgentPolicy(config.agent.model, runtimeBackend, privateConnectorPolicy);
1624
1681
  const result = await agentLoop.runWithContent([{ type: 'text', text: prompt }], {
1625
1682
  sessionKey: report_run_js_1.OPERATOR_REPORT_SESSION_KEY,
1626
1683
  source: 'operator',
@@ -1630,8 +1687,8 @@ async function runAgentLoop(config, options = {}) {
1630
1687
  // gather no matter what the prompt instructs (roleAllowsOuterCodeAct
1631
1688
  // fails closed on an absent role - agent-loop.ts). Same built-in
1632
1689
  // least-privilege treatment the Stage-2 workers get.
1633
- agentContext: buildOperatorReportAgentPolicy(config.agent.model, runtimeBackend)
1634
- .agentContext,
1690
+ agentContext: reportAgentPolicy.agentContext,
1691
+ gatewayToolsPrompt: reportAgentPolicy.gatewayToolsPrompt,
1635
1692
  // Stateless report lane: each run starts on a fresh session so the
1636
1693
  // continuous session no longer accumulates every run's gather dumps
1637
1694
  // (measured 146s -> 521s growth over 3 days). Continuity comes from
@@ -1667,11 +1724,15 @@ async function runAgentLoop(config, options = {}) {
1667
1724
  // Kagemusha dual output: the same scheduled run updates the /ui operator board
1668
1725
  // slots via report_publish, then writes the plain-text owner report.
1669
1726
  fullReportBoardLines: buildBoardPublishLines(),
1670
- // S1-T4 context carry: the delivered FULL report persists so the owner
1671
- // console references it per turn instead of fabricating status.
1672
- persistLastFullReport: (iso, text) => {
1727
+ // TG-06: composition supplies provenance immediately to the prepared
1728
+ // delivery; this callback receives that durable artifact only after send success.
1729
+ fullReportProvenance: () => lastReportProvenance,
1730
+ persistLastFullReport: (report) => {
1673
1731
  (0, leg_cadence_js_1.getLegCadence)()?.beat('full-report');
1674
- return persistLastFullReport(iso, text, lastReportProvenance);
1732
+ if (!persistReportCarry) {
1733
+ throw new Error('Cannot persist full report carry without a Telegram report chat');
1734
+ }
1735
+ persistReportCarry(report);
1675
1736
  },
1676
1737
  pendingReportStore: new FilePendingReportStore((0, config_manager_js_1.expandPath)('~/.mama/operator/pending-owner-reports.json'), (line) => console.error(line)),
1677
1738
  config: {
@@ -1725,7 +1786,7 @@ async function runAgentLoop(config, options = {}) {
1725
1786
  maxTurns: conductorConfig.maxTurns,
1726
1787
  maxTokens: conductorConfig.maxTokens,
1727
1788
  });
1728
- const conductorPolicy = buildConductorAgentPolicy(config.agent.model, runtimeBackend);
1789
+ const conductorPolicy = buildConductorAgentPolicy(config.agent.model, runtimeBackend, privateConnectorPolicy);
1729
1790
  // Per-run envelope, mirroring the report lane: without it every
1730
1791
  // model_tool call dies 'envelope_missing' while the run resolves and
1731
1792
  // acks the batch - zero work, green ledger (review F2).
@@ -1819,6 +1880,8 @@ async function runAgentLoop(config, options = {}) {
1819
1880
  envelopeMetadata: envelopeBootstrap.metadata,
1820
1881
  envelopeAuthority: envelopeBootstrap.envelopeAuthority,
1821
1882
  contextCompileService,
1883
+ connectorConfigLoadResult,
1884
+ privateConnectorPolicy,
1822
1885
  });
1823
1886
  channelDeltaSink.current = (channelKey, lines, eventIds) => eventBus.emit({ type: 'operator:channel-delta', channelKey, lines, eventIds });
1824
1887
  await (0, api_routes_init_js_1.registerApiRoutes)({
@@ -1834,6 +1897,10 @@ async function runAgentLoop(config, options = {}) {
1834
1897
  slackGateway,
1835
1898
  graphHandler,
1836
1899
  getAdapter,
1900
+ privateConnectorPolicy,
1901
+ rawConnectorScope: [
1902
+ ...privateConnectorPolicy.projectRawConnectors('workorder-board', codeActRawConnectors),
1903
+ ],
1837
1904
  sessionsDb: db,
1838
1905
  workOrderConsumer: workOrderConsumer ?? undefined,
1839
1906
  });