@jungjaehoon/mama-os 0.47.1 → 0.48.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 (150) hide show
  1. package/dist/agent/agent-loop.d.ts.map +1 -1
  2. package/dist/agent/agent-loop.js +9 -11
  3. package/dist/agent/agent-loop.js.map +1 -1
  4. package/dist/agent/code-act/constants.d.ts +2 -1
  5. package/dist/agent/code-act/constants.d.ts.map +1 -1
  6. package/dist/agent/code-act/constants.js +27 -92
  7. package/dist/agent/code-act/constants.js.map +1 -1
  8. package/dist/agent/code-act/host-bridge.d.ts +2 -1
  9. package/dist/agent/code-act/host-bridge.d.ts.map +1 -1
  10. package/dist/agent/code-act/host-bridge.js +263 -29
  11. package/dist/agent/code-act/host-bridge.js.map +1 -1
  12. package/dist/agent/code-act/sandbox.d.ts.map +1 -1
  13. package/dist/agent/code-act/sandbox.js +6 -2
  14. package/dist/agent/code-act/sandbox.js.map +1 -1
  15. package/dist/agent/code-act/tool-catalog.d.ts +28 -0
  16. package/dist/agent/code-act/tool-catalog.d.ts.map +1 -0
  17. package/dist/agent/code-act/tool-catalog.js +146 -0
  18. package/dist/agent/code-act/tool-catalog.js.map +1 -0
  19. package/dist/agent/code-act/tool-policy.d.ts +2 -1
  20. package/dist/agent/code-act/tool-policy.d.ts.map +1 -1
  21. package/dist/agent/code-act/tool-policy.js +2 -1
  22. package/dist/agent/code-act/tool-policy.js.map +1 -1
  23. package/dist/agent/code-act/type-definition-generator.d.ts +6 -0
  24. package/dist/agent/code-act/type-definition-generator.d.ts.map +1 -1
  25. package/dist/agent/code-act/type-definition-generator.js +40 -21
  26. package/dist/agent/code-act/type-definition-generator.js.map +1 -1
  27. package/dist/agent/gateway-tool-executor.d.ts +6 -0
  28. package/dist/agent/gateway-tool-executor.d.ts.map +1 -1
  29. package/dist/agent/gateway-tool-executor.js +175 -58
  30. package/dist/agent/gateway-tool-executor.js.map +1 -1
  31. package/dist/agent/gateway-tools.md +8 -7
  32. package/dist/agent/tool-registry.d.ts.map +1 -1
  33. package/dist/agent/tool-registry.js +41 -14
  34. package/dist/agent/tool-registry.js.map +1 -1
  35. package/dist/agent/types.d.ts +1 -1
  36. package/dist/agent/types.d.ts.map +1 -1
  37. package/dist/agent/types.js.map +1 -1
  38. package/dist/api/graph-api-types.d.ts +3 -0
  39. package/dist/api/graph-api-types.d.ts.map +1 -1
  40. package/dist/cli/commands/start.d.ts.map +1 -1
  41. package/dist/cli/commands/start.js +24 -3
  42. package/dist/cli/commands/start.js.map +1 -1
  43. package/dist/cli/config/types.d.ts.map +1 -1
  44. package/dist/cli/config/types.js +1 -0
  45. package/dist/cli/config/types.js.map +1 -1
  46. package/dist/cli/runtime/api-routes-init.d.ts.map +1 -1
  47. package/dist/cli/runtime/api-routes-init.js +142 -15
  48. package/dist/cli/runtime/api-routes-init.js.map +1 -1
  49. package/dist/cli/runtime/code-act-executor.d.ts.map +1 -1
  50. package/dist/cli/runtime/code-act-executor.js +5 -0
  51. package/dist/cli/runtime/code-act-executor.js.map +1 -1
  52. package/dist/connectors/kagemusha/query-tools.d.ts +57 -0
  53. package/dist/connectors/kagemusha/query-tools.d.ts.map +1 -1
  54. package/dist/connectors/kagemusha/query-tools.js +247 -0
  55. package/dist/connectors/kagemusha/query-tools.js.map +1 -1
  56. package/dist/connectors/private-connector-policy.d.ts +32 -6
  57. package/dist/connectors/private-connector-policy.d.ts.map +1 -1
  58. package/dist/connectors/private-connector-policy.js +40 -5
  59. package/dist/connectors/private-connector-policy.js.map +1 -1
  60. package/dist/connectors/trello/query-tools.d.ts +148 -16
  61. package/dist/connectors/trello/query-tools.d.ts.map +1 -1
  62. package/dist/connectors/trello/query-tools.js +453 -65
  63. package/dist/connectors/trello/query-tools.js.map +1 -1
  64. package/dist/db/migrations/operator-task-classification.d.ts +15 -0
  65. package/dist/db/migrations/operator-task-classification.d.ts.map +1 -0
  66. package/dist/db/migrations/operator-task-classification.js +25 -0
  67. package/dist/db/migrations/operator-task-classification.js.map +1 -0
  68. package/dist/evidence/effects.d.ts +2 -1
  69. package/dist/evidence/effects.d.ts.map +1 -1
  70. package/dist/evidence/effects.js.map +1 -1
  71. package/dist/gateways/message-router.d.ts.map +1 -1
  72. package/dist/gateways/message-router.js +2 -1
  73. package/dist/gateways/message-router.js.map +1 -1
  74. package/dist/mcp/code-act-api-client.d.ts +1 -0
  75. package/dist/mcp/code-act-api-client.d.ts.map +1 -1
  76. package/dist/mcp/code-act-api-client.js.map +1 -1
  77. package/dist/mcp/code-act-server.js +6 -5
  78. package/dist/mcp/code-act-server.js.map +1 -1
  79. package/dist/mcp/code-act-terminal-transport.d.ts +2 -0
  80. package/dist/mcp/code-act-terminal-transport.d.ts.map +1 -1
  81. package/dist/mcp/code-act-terminal-transport.js +18 -6
  82. package/dist/mcp/code-act-terminal-transport.js.map +1 -1
  83. package/dist/multi-agent/agent-process-manager.d.ts.map +1 -1
  84. package/dist/multi-agent/agent-process-manager.js +1 -5
  85. package/dist/multi-agent/agent-process-manager.js.map +1 -1
  86. package/dist/multi-agent/dashboard-agent-persona.d.ts.map +1 -1
  87. package/dist/multi-agent/dashboard-agent-persona.js +7 -8
  88. package/dist/multi-agent/dashboard-agent-persona.js.map +1 -1
  89. package/dist/multi-agent/wiki-agent-persona.d.ts +7 -6
  90. package/dist/multi-agent/wiki-agent-persona.d.ts.map +1 -1
  91. package/dist/multi-agent/wiki-agent-persona.js +9 -93
  92. package/dist/multi-agent/wiki-agent-persona.js.map +1 -1
  93. package/dist/operator/action-verifier.d.ts +1 -1
  94. package/dist/operator/action-verifier.d.ts.map +1 -1
  95. package/dist/operator/action-verifier.js +4 -0
  96. package/dist/operator/action-verifier.js.map +1 -1
  97. package/dist/operator/board-read-views.d.ts +49 -0
  98. package/dist/operator/board-read-views.d.ts.map +1 -0
  99. package/dist/operator/board-read-views.js +207 -0
  100. package/dist/operator/board-read-views.js.map +1 -0
  101. package/dist/operator/board-reconcile.d.ts +1 -1
  102. package/dist/operator/board-reconcile.js +1 -1
  103. package/dist/operator/owner-event-outcome.d.ts +6 -0
  104. package/dist/operator/owner-event-outcome.d.ts.map +1 -1
  105. package/dist/operator/owner-event-outcome.js +6 -3
  106. package/dist/operator/owner-event-outcome.js.map +1 -1
  107. package/dist/operator/owner-event-policy.d.ts.map +1 -1
  108. package/dist/operator/owner-event-policy.js +9 -4
  109. package/dist/operator/owner-event-policy.js.map +1 -1
  110. package/dist/operator/owner-event-prompt.d.ts.map +1 -1
  111. package/dist/operator/owner-event-prompt.js +4 -0
  112. package/dist/operator/owner-event-prompt.js.map +1 -1
  113. package/dist/operator/task-ledger.d.ts +169 -1
  114. package/dist/operator/task-ledger.d.ts.map +1 -1
  115. package/dist/operator/task-ledger.js +409 -8
  116. package/dist/operator/task-ledger.js.map +1 -1
  117. package/dist/operator/task-list-views.d.ts +91 -0
  118. package/dist/operator/task-list-views.d.ts.map +1 -0
  119. package/dist/operator/task-list-views.js +505 -0
  120. package/dist/operator/task-list-views.js.map +1 -0
  121. package/dist/operator/temporal-reconcile.d.ts +1 -0
  122. package/dist/operator/temporal-reconcile.d.ts.map +1 -1
  123. package/dist/operator/temporal-reconcile.js +1 -0
  124. package/dist/operator/temporal-reconcile.js.map +1 -1
  125. package/dist/operator/wiki-continuity.d.ts +149 -0
  126. package/dist/operator/wiki-continuity.d.ts.map +1 -0
  127. package/dist/operator/wiki-continuity.js +214 -0
  128. package/dist/operator/wiki-continuity.js.map +1 -0
  129. package/dist/operator/worker-run.js +1 -1
  130. package/dist/operator/worker-run.js.map +1 -1
  131. package/dist/operator/workorder-consumer.d.ts.map +1 -1
  132. package/dist/operator/workorder-consumer.js +10 -7
  133. package/dist/operator/workorder-consumer.js.map +1 -1
  134. package/dist/operator/workorder-hooks.d.ts +1 -1
  135. package/dist/operator/workorder-publishers.d.ts +26 -4
  136. package/dist/operator/workorder-publishers.d.ts.map +1 -1
  137. package/dist/operator/workorder-publishers.js +122 -1
  138. package/dist/operator/workorder-publishers.js.map +1 -1
  139. package/dist/sqlite.d.ts +7 -0
  140. package/dist/sqlite.d.ts.map +1 -1
  141. package/dist/sqlite.js +8 -0
  142. package/dist/sqlite.js.map +1 -1
  143. package/dist/wiki/obsidian-writer.d.ts.map +1 -1
  144. package/dist/wiki/obsidian-writer.js +14 -2
  145. package/dist/wiki/obsidian-writer.js.map +1 -1
  146. package/dist/wiki/wiki-turn-contract.d.ts +19 -0
  147. package/dist/wiki/wiki-turn-contract.d.ts.map +1 -0
  148. package/dist/wiki/wiki-turn-contract.js +58 -0
  149. package/dist/wiki/wiki-turn-contract.js.map +1 -0
  150. package/package.json +2 -1
@@ -49,6 +49,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
49
49
  };
50
50
  Object.defineProperty(exports, "__esModule", { value: true });
51
51
  exports.GatewayToolExecutor = void 0;
52
+ exports.serializeCodeActModelResult = serializeCodeActModelResult;
52
53
  const fs_1 = require("fs");
53
54
  const async_hooks_1 = require("async_hooks");
54
55
  const crypto_1 = require("crypto");
@@ -73,6 +74,7 @@ const attachment_text_extractor_js_1 = require("./attachment-text-extractor.js")
73
74
  const untrusted_content_js_1 = require("../utils/untrusted-content.js");
74
75
  const types_js_1 = require("./types.js");
75
76
  const external_lifecycle_candidates_js_1 = require("../operator/external-lifecycle-candidates.js");
77
+ const task_ledger_js_1 = require("../operator/task-ledger.js");
76
78
  const sqlite_js_1 = __importDefault(require("../sqlite.js"));
77
79
  const mama_tool_handlers_js_1 = require("./mama-tool-handlers.js");
78
80
  const role_manager_js_1 = require("./role-manager.js");
@@ -81,6 +83,8 @@ const agent_store_js_1 = require("../db/agent-store.js");
81
83
  const index_js_1 = require("../envelope/index.js");
82
84
  const wiki_publish_adapter_js_1 = require("../wiki-artifacts/wiki-publish-adapter.js");
83
85
  const changes_projection_js_1 = require("../operator/changes-projection.js");
86
+ const task_list_views_js_1 = require("../operator/task-list-views.js");
87
+ const board_read_views_js_1 = require("../operator/board-read-views.js");
84
88
  const read_js_1 = require("../evidence/read.js");
85
89
  const private_connector_policy_js_1 = require("../connectors/private-connector-policy.js");
86
90
  const member_candidate_store_js_1 = require("../gateways/member-candidate-store.js");
@@ -93,19 +97,6 @@ const DEFAULT_PRIVATE_CONNECTOR_POLICY = (0, private_connector_policy_js_1.resol
93
97
  function isReportPublishResult(value) {
94
98
  return value !== undefined && !Array.isArray(value);
95
99
  }
96
- function serializeTaskToolRecord(task) {
97
- return {
98
- ...task,
99
- due_at: task.dueAt === null ? null : new Date(task.dueAt).toISOString(),
100
- deadline_offset_minutes: task.deadlineOffsetMinutes,
101
- temporal_epoch: task.temporalEpoch,
102
- temporal_reconciled_occurrence_key: task.temporalReconciledOccurrenceKey,
103
- last_temporal_checked_at: task.lastTemporalCheckedAt,
104
- next_temporal_check_at: task.nextTemporalCheckAt,
105
- last_temporal_attempt_id: task.lastTemporalAttemptId,
106
- temporal_state: task.temporalState,
107
- };
108
- }
109
100
  function temporalContextPacketBinding(context) {
110
101
  return `temporal:${context.taskId}:${context.generationKey}`;
111
102
  }
@@ -206,6 +197,7 @@ const TEMPORAL_WRITE_TOOLS = new Set([
206
197
  'obsidian',
207
198
  'task_create',
208
199
  'task_update',
200
+ 'task_reclassify',
209
201
  'contract_no_update',
210
202
  'task_temporal_reconcile',
211
203
  'Write',
@@ -229,8 +221,31 @@ const TASK_UPDATE_PUBLIC_FIELDS = [
229
221
  'expected_revision',
230
222
  'context_packet_id',
231
223
  'review_anchor_ref',
224
+ 'completion_criteria',
232
225
  ];
233
226
  const TASK_UPDATE_PUBLIC_FIELD_SET = new Set(TASK_UPDATE_PUBLIC_FIELDS);
227
+ /**
228
+ * Records and tasks are separate. `completion_criteria` is REQUIRED here (not in
229
+ * the ledger) so the public agent boundary refuses a title-only row while
230
+ * internal/system seeding stays backward compatible.
231
+ */
232
+ const TASK_CREATE_PUBLIC_FIELDS = [
233
+ 'title',
234
+ 'completion_criteria',
235
+ 'status',
236
+ 'priority',
237
+ 'assignee',
238
+ 'deadline',
239
+ 'due_at',
240
+ 'source_channel',
241
+ 'source_event_id',
242
+ 'latest_event',
243
+ 'confirmed',
244
+ 'expected_revision',
245
+ ];
246
+ const TASK_CREATE_PUBLIC_FIELD_SET = new Set(TASK_CREATE_PUBLIC_FIELDS);
247
+ const TASK_RECLASSIFY_PUBLIC_FIELDS = ['id', 'disposition', 'reason', 'expected_revision'];
248
+ const TASK_RECLASSIFY_PUBLIC_FIELD_SET = new Set(TASK_RECLASSIFY_PUBLIC_FIELDS);
234
249
  const MEMORY_READ_PERMISSION_BEFORE_ENVELOPE_TOOLS = new Set([
235
250
  'mama_save',
236
251
  'mama_search',
@@ -255,6 +270,30 @@ const OWNER_CONSOLE_MEMBER_TOOLS = new Set([
255
270
  ]);
256
271
  class ContextPacketProvenanceError extends Error {
257
272
  }
273
+ /**
274
+ * Compact model boundary for Code-Act; internal receipts retain the richer result object.
275
+ * The JSON root (success, audit ledger, terminal codes) stays machine-readable; when the run
276
+ * read external evidence only the value/logs payload is fenced as untrusted data.
277
+ */
278
+ function serializeCodeActModelResult(result) {
279
+ const record = result;
280
+ const { message, untrustedExternalEvidence, value, logs, ...modelResult } = record;
281
+ if (typeof message === 'string' && value === undefined && typeof modelResult.error !== 'string') {
282
+ modelResult.message = message;
283
+ }
284
+ const payload = {
285
+ ...(value !== undefined ? { value } : {}),
286
+ ...(logs !== undefined ? { logs } : {}),
287
+ };
288
+ if (untrustedExternalEvidence === true) {
289
+ return JSON.stringify({
290
+ ...modelResult,
291
+ untrustedExternalEvidence: true,
292
+ payload: (0, untrusted_content_js_1.wrapUntrustedContent)('external-evidence-code-act', JSON.stringify(payload)),
293
+ });
294
+ }
295
+ return JSON.stringify({ ...modelResult, ...payload });
296
+ }
258
297
  function asRecord(value) {
259
298
  return value && typeof value === 'object' && !Array.isArray(value)
260
299
  ? value
@@ -2522,8 +2561,9 @@ class GatewayToolExecutor {
2522
2561
  error: 'Report store not wired (board_read requires the API server report store).',
2523
2562
  };
2524
2563
  }
2525
- const slots = this.reportReader();
2526
- return { success: true, slots };
2564
+ // Default returns slot descriptors only; a named slot pages its text/html
2565
+ // by code points so a long slot is fully reachable, never silently sliced.
2566
+ return (0, board_read_views_js_1.readBoardView)(input, this.reportReader());
2527
2567
  }
2528
2568
  case 'audit_findings_read': {
2529
2569
  const auditStatePath = (0, path_1.join)(process.env.HOME || (0, os_1.homedir)(), '.mama', 'state', 'audit-findings.json');
@@ -2618,14 +2658,17 @@ class GatewayToolExecutor {
2618
2658
  // kagemusha_*: state questions read the source live, never the
2619
2659
  // connector change-log projection (2026-07-24 incident chain).
2620
2660
  case 'trello_search': {
2621
- const { searchTrelloCards } = await import('../connectors/trello/query-tools.js');
2661
+ const { searchTrelloBoardCards } = await import('../connectors/trello/query-tools.js');
2622
2662
  const searchInput = input;
2623
2663
  try {
2624
- const cards = await searchTrelloCards({
2664
+ // Progressive: honest full match total + continuation + per-board coverage,
2665
+ // not a hidden 20-result cap. Paged over the cached board snapshot.
2666
+ const page = await searchTrelloBoardCards({
2625
2667
  query: searchInput.query ?? '',
2626
2668
  limit: searchInput.limit,
2669
+ cursor: searchInput.cursor,
2627
2670
  });
2628
- return { success: true, cards };
2671
+ return { success: true, ...page };
2629
2672
  }
2630
2673
  catch (err) {
2631
2674
  return {
@@ -2636,10 +2679,19 @@ class GatewayToolExecutor {
2636
2679
  }
2637
2680
  }
2638
2681
  case 'trello_card': {
2639
- const { getTrelloCard } = await import('../connectors/trello/query-tools.js');
2682
+ const { getTrelloCardDetail } = await import('../connectors/trello/query-tools.js');
2640
2683
  const cardInput = input;
2641
2684
  try {
2642
- const card = await getTrelloCard({ cardId: cardInput.cardId ?? '' });
2685
+ // Sectioned detail (summary|description|checklists|checklist_items) with
2686
+ // explicit continuation; the board allowlist is enforced before any field.
2687
+ const card = await getTrelloCardDetail({
2688
+ cardId: cardInput.cardId ?? '',
2689
+ section: cardInput.section,
2690
+ offset: cardInput.offset,
2691
+ limit: cardInput.limit,
2692
+ checklistId: cardInput.checklistId,
2693
+ readVersion: cardInput.readVersion,
2694
+ });
2643
2695
  return { success: true, card };
2644
2696
  }
2645
2697
  catch (err) {
@@ -2651,16 +2703,23 @@ class GatewayToolExecutor {
2651
2703
  }
2652
2704
  }
2653
2705
  case 'trello_kanban': {
2654
- const { getTrelloKanban } = await import('../connectors/trello/query-tools.js');
2706
+ const { getTrelloBoardsOverview, getTrelloListCards } = await import('../connectors/trello/query-tools.js');
2655
2707
  const kanbanInput = input;
2656
2708
  try {
2657
- // Coverage rides alongside the data: `complete`/`boards`/`truncated`/
2658
- // `observedAt` are what let a caller tell a truly empty board from one it
2659
- // failed to read, and a whole column from a sliced one.
2660
- const snapshot = await getTrelloKanban({
2661
- maxCardsPerList: kanbanInput.maxCardsPerList,
2662
- });
2663
- return { success: true, ...snapshot };
2709
+ // Default returns the board/list overview with counts and coverage - NO
2710
+ // card arrays. A named (boardId, listId) pages that list's open cards
2711
+ // beyond the old kanban ceiling, cursor pinned to the read snapshot.
2712
+ if (kanbanInput.boardId !== undefined || kanbanInput.listId !== undefined) {
2713
+ const cards = await getTrelloListCards({
2714
+ boardId: kanbanInput.boardId ?? '',
2715
+ listId: kanbanInput.listId ?? '',
2716
+ limit: kanbanInput.limit,
2717
+ cursor: kanbanInput.cursor,
2718
+ });
2719
+ return { success: true, ...cards };
2720
+ }
2721
+ const overview = await getTrelloBoardsOverview();
2722
+ return { success: true, ...overview };
2664
2723
  }
2665
2724
  catch (err) {
2666
2725
  return {
@@ -2671,12 +2730,14 @@ class GatewayToolExecutor {
2671
2730
  }
2672
2731
  }
2673
2732
  case 'kagemusha_messages': {
2674
- const { queryMessages } = await import('../connectors/kagemusha/query-tools.js');
2733
+ const { queryMessagesPage } = await import('../connectors/kagemusha/query-tools.js');
2675
2734
  const msgInput = input;
2676
2735
  if (!msgInput.channelId) {
2677
2736
  throw new types_js_1.AgentError('kagemusha_messages requires channelId', 'TOOL_ERROR', undefined, false);
2678
2737
  }
2679
- return { success: true, messages: queryMessages(msgInput) };
2738
+ // Progressive: (created_at,id) keyset over an append-only asOf bound with
2739
+ // total/returned/nextCursor; an unknown channel is a loud missing-source error.
2740
+ return { success: true, ...queryMessagesPage(msgInput) };
2680
2741
  }
2681
2742
  case 'changes_read': {
2682
2743
  if (!this.taskLedger) {
@@ -2692,37 +2753,23 @@ class GatewayToolExecutor {
2692
2753
  if (!this.taskLedger) {
2693
2754
  return { success: false, error: 'Task ledger not configured' };
2694
2755
  }
2756
+ // Under a Temporal work context the universe is exactly the one host-bound
2757
+ // owner task; the views observe/count only it and treat every other id as
2758
+ // generic missing. Fetch it here so an unavailable bound task stays the same
2759
+ // superseded signal it was before the progressive views.
2695
2760
  const temporalContext = this.getExecutionState().temporalWorkContext;
2761
+ let boundTask;
2696
2762
  if (temporalContext) {
2697
- const boundTask = this.taskLedger.getById(temporalContext.taskId);
2698
- if (!boundTask) {
2763
+ const found = this.taskLedger.getById(temporalContext.taskId);
2764
+ if (!found) {
2699
2765
  throw new types_js_1.AgentError('Host-bound temporal owner task is unavailable', 'WORKORDER_SUPERSEDED', undefined, false);
2700
2766
  }
2701
- return {
2702
- success: true,
2703
- tasks: [serializeTaskToolRecord(boundTask)],
2704
- };
2767
+ boundTask = found;
2705
2768
  }
2706
- const listInput = input;
2707
- // total/returned/nextCursor ride with the rows: a read with a caller-passed
2708
- // limit is otherwise indistinguishable from the whole board, and a report
2709
- // that says "the open items are..." from one page states more than it read.
2710
- const page = this.taskLedger.listPage({
2711
- status: listInput.status,
2712
- includeTerminal: listInput.include_terminal,
2713
- channel: listInput.channel,
2714
- search: listInput.search,
2715
- limit: listInput.limit,
2716
- order: listInput.order ?? 'deadline_priority',
2717
- cursor: listInput.cursor,
2769
+ return (0, task_list_views_js_1.runTaskListView)(input, {
2770
+ ledger: this.taskLedger,
2771
+ boundTask,
2718
2772
  });
2719
- return {
2720
- success: true,
2721
- tasks: page.tasks.map(serializeTaskToolRecord),
2722
- total: page.total,
2723
- returned: page.returned,
2724
- nextCursor: page.nextCursor,
2725
- };
2726
2773
  }
2727
2774
  case 'task_external_correlation': {
2728
2775
  if (!this.taskLedger) {
@@ -2867,9 +2914,27 @@ class GatewayToolExecutor {
2867
2914
  if (!this.taskLedger) {
2868
2915
  return { success: false, error: 'Task ledger not configured' };
2869
2916
  }
2917
+ const rawTaskCreate = input;
2918
+ const unsupportedCreateFields = Object.keys(rawTaskCreate).filter((field) => !TASK_CREATE_PUBLIC_FIELD_SET.has(field));
2919
+ if (unsupportedCreateFields.length > 0) {
2920
+ throw new types_js_1.AgentError(`task_create unsupported field(s): ${unsupportedCreateFields.join(', ')}. ` +
2921
+ `Supported fields: ${TASK_CREATE_PUBLIC_FIELDS.join(', ')}.`, 'TOOL_ERROR', undefined, false);
2922
+ }
2923
+ // The records-vs-tasks boundary. A row without a concrete, finite
2924
+ // completion condition is a RECORD, and a record must not become a task.
2925
+ const completionCriteria = rawTaskCreate.completion_criteria;
2926
+ if (typeof completionCriteria !== 'string' || completionCriteria.trim().length === 0) {
2927
+ throw new types_js_1.AgentError('task_create requires a non-empty completion_criteria: name the concrete, finite ' +
2928
+ 'condition under which this is finished. Observations, lessons, principles, ' +
2929
+ 'aspirations and open questions are records or memory, not tasks - do not create ' +
2930
+ 'a row for them.', 'TOOL_ERROR', undefined, false);
2931
+ }
2932
+ if (completionCriteria.trim().length > task_ledger_js_1.TASK_COMPLETION_CRITERIA_MAX_LENGTH) {
2933
+ throw new types_js_1.AgentError(`task_create completion_criteria must be at most ${task_ledger_js_1.TASK_COMPLETION_CRITERIA_MAX_LENGTH} characters`, 'TOOL_ERROR', undefined, false);
2934
+ }
2870
2935
  return {
2871
2936
  success: true,
2872
- task: serializeTaskToolRecord(
2937
+ task: (0, task_list_views_js_1.serializeTaskToolRecord)(
2873
2938
  // The run id comes from trusted execution state, never from the tool call:
2874
2939
  // an agent that can name its own run in the effect ledger can sign someone
2875
2940
  // else's work with it.
@@ -2882,6 +2947,46 @@ class GatewayToolExecutor {
2882
2947
  })),
2883
2948
  };
2884
2949
  }
2950
+ case 'task_reclassify': {
2951
+ if (!this.taskLedger) {
2952
+ return { success: false, error: 'Task ledger not configured' };
2953
+ }
2954
+ const rawReclassify = input;
2955
+ const unsupportedReclassifyFields = Object.keys(rawReclassify).filter((field) => !TASK_RECLASSIFY_PUBLIC_FIELD_SET.has(field));
2956
+ if (unsupportedReclassifyFields.length > 0) {
2957
+ throw new types_js_1.AgentError(`task_reclassify unsupported field(s): ${unsupportedReclassifyFields.join(', ')}. ` +
2958
+ `Supported fields: ${TASK_RECLASSIFY_PUBLIC_FIELDS.join(', ')}.`, 'TOOL_ERROR', undefined, false);
2959
+ }
2960
+ const rawReclassifyId = rawReclassify.id;
2961
+ const reclassifyId = typeof rawReclassifyId === 'string'
2962
+ ? Number(rawReclassifyId.trim())
2963
+ : rawReclassifyId;
2964
+ if (!Number.isInteger(reclassifyId) || reclassifyId <= 0) {
2965
+ throw new types_js_1.AgentError(`task_reclassify requires a numeric id, got: ${String(rawReclassifyId)}`, 'TOOL_ERROR', undefined, false);
2966
+ }
2967
+ try {
2968
+ return {
2969
+ success: true,
2970
+ task: (0, task_list_views_js_1.serializeTaskToolRecord)(this.taskLedger.reclassify(reclassifyId, {
2971
+ disposition: rawReclassify.disposition,
2972
+ reason: rawReclassify.reason,
2973
+ expected_revision: rawReclassify.expected_revision,
2974
+ }, {
2975
+ // Same trusted-identity rule as task_update: the run and the
2976
+ // board attempt come from execution state, never the tool call.
2977
+ runId: this.getExecutionState().modelRunId ?? null,
2978
+ workOrderAttemptId: this.getExecutionState().workorderAttemptId,
2979
+ requiresExpectedRevision: this.getExecutionState().workorderAttemptId !== undefined,
2980
+ causeEventIds: this.getExecutionState().causeEventIds,
2981
+ causeKind: this.getExecutionState().source === 'operator' ? 'clock' : 'owner_message',
2982
+ reclassificationCauseBound: this.getExecutionState().source === 'owner-event',
2983
+ })),
2984
+ };
2985
+ }
2986
+ catch (error) {
2987
+ throw new types_js_1.AgentError(error instanceof Error ? error.message : 'task_reclassify failed', 'TOOL_ERROR', error instanceof Error ? error : undefined, false);
2988
+ }
2989
+ }
2885
2990
  case 'task_update': {
2886
2991
  if (!this.taskLedger) {
2887
2992
  return { success: false, error: 'Task ledger not configured' };
@@ -2902,6 +3007,17 @@ class GatewayToolExecutor {
2902
3007
  `Supported fields: ${TASK_UPDATE_PUBLIC_FIELDS.join(', ')}. ` +
2903
3008
  'Use latest_event for input; responses return latestEvent.', 'TOOL_ERROR', undefined, false);
2904
3009
  }
3010
+ if (Object.prototype.hasOwnProperty.call(rawTaskUpdate, 'completion_criteria')) {
3011
+ if (this.getExecutionState().source === 'owner-event') {
3012
+ throw new types_js_1.AgentError('task_update completion_criteria is unavailable on owner-event turns; full Board maintenance or the owner conversation owns qualification', 'TOOL_ERROR', undefined, false);
3013
+ }
3014
+ const criteria = rawTaskUpdate.completion_criteria;
3015
+ if (typeof criteria !== 'string' ||
3016
+ criteria.trim().length === 0 ||
3017
+ criteria.trim().length > task_ledger_js_1.TASK_COMPLETION_CRITERIA_MAX_LENGTH) {
3018
+ throw new types_js_1.AgentError(`task_update completion_criteria must be a non-empty string of at most ${task_ledger_js_1.TASK_COMPLETION_CRITERIA_MAX_LENGTH} characters`, 'TOOL_ERROR', undefined, false);
3019
+ }
3020
+ }
2905
3021
  const { id: rawId, context_packet_id: contextPacketId, review_anchor_ref: reviewAnchorRef, ...patch } = rawTaskUpdate;
2906
3022
  // Agents routinely pass "12"; coerce, reject non-numeric with a typed error.
2907
3023
  const id = typeof rawId === 'string' ? Number(rawId.trim()) : rawId;
@@ -2976,7 +3092,7 @@ class GatewayToolExecutor {
2976
3092
  causeKind: this.getExecutionState().source === 'operator' ? 'clock' : 'owner_message',
2977
3093
  ...(verifiedReviewEvidence ? { verifiedReviewEvidence } : {}),
2978
3094
  });
2979
- return { success: true, task: serializeTaskToolRecord(updated) };
3095
+ return { success: true, task: (0, task_list_views_js_1.serializeTaskToolRecord)(updated) };
2980
3096
  }
2981
3097
  case 'task_temporal_reconcile': {
2982
3098
  if (!this.taskLedger) {
@@ -3908,7 +4024,7 @@ class GatewayToolExecutor {
3908
4024
  usedUntrustedExternalEvidence = true;
3909
4025
  }
3910
4026
  };
3911
- bridge.injectInto(sandbox, policy.names);
4027
+ bridge.injectInto(sandbox, policy);
3912
4028
  const result = await sandbox.execute(input.code, { signal: state.signal });
3913
4029
  const terminalMutationCodes = new Set([
3914
4030
  CODE_ACT_MUTATION_COMMITTED_AFTER_ABORT,
@@ -3943,6 +4059,7 @@ class GatewayToolExecutor {
3943
4059
  metrics: result.metrics,
3944
4060
  hostToolExecutions,
3945
4061
  hostToolsInvoked,
4062
+ ...(usedUntrustedExternalEvidence ? { untrustedExternalEvidence: true } : {}),
3946
4063
  message: result.success
3947
4064
  ? usedUntrustedExternalEvidence
3948
4065
  ? (0, untrusted_content_js_1.wrapUntrustedContent)('external-evidence-code-act', successfulMessage)