yaml-flow 8.7.1 → 8.8.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 (182) hide show
  1. package/browser/adapters/firebase-storage.js +2 -2
  2. package/browser/adapters/firestore-storage.js +2 -2
  3. package/browser/adapters/localstorage-storage.js +3 -3
  4. package/browser/asset-integrity.json +9 -13
  5. package/browser/server-runtime-controlface.js +5 -5
  6. package/examples/ARCHITECTURE.md +0 -27
  7. package/examples/board/server/board-server.js +150 -100
  8. package/examples/board/server/board-worker/source_def_flows.json +0 -8
  9. package/examples/board/server/board-worker/task-executor.js +1 -3
  10. package/examples/board/test/server-http-test.js +108 -73
  11. package/examples/board-firestore/server/worker.js +8 -0
  12. package/examples/portfolio-tracker/portfolio-tracker.js +11 -1
  13. package/examples/portfolio-tracker/test/portfolio-t4.js +12 -2
  14. package/lib/{artifacts-store-lib-D9nMkVcE.d.cts → artifacts-store-lib-C6qBpMfU.d.cts} +1 -1
  15. package/lib/{artifacts-store-lib-DSSMqVL2.d.ts → artifacts-store-lib-D4qf7Q-7.d.ts} +1 -1
  16. package/lib/artifacts-store-public.d.cts +3 -3
  17. package/lib/artifacts-store-public.d.ts +3 -3
  18. package/lib/board-live-cards-mcp.cjs +1 -1
  19. package/lib/board-live-cards-mcp.d.cts +6 -7
  20. package/lib/board-live-cards-mcp.d.ts +6 -7
  21. package/lib/board-live-cards-mcp.js +1 -1
  22. package/lib/board-live-cards-node.cjs +8 -8
  23. package/lib/board-live-cards-node.d.cts +15 -14
  24. package/lib/board-live-cards-node.d.ts +15 -14
  25. package/lib/board-live-cards-node.js +8 -8
  26. package/lib/{board-live-cards-public-LlVUQPL2.d.cts → board-live-cards-public-BT5HrgqZ.d.cts} +82 -59
  27. package/lib/{board-live-cards-public-JNRKfBZy.d.ts → board-live-cards-public-DSRamFm8.d.ts} +82 -59
  28. package/lib/{board-live-cards-public-async-Di9QB141.d.cts → board-live-cards-public-async-CYjr4mgX.d.cts} +18 -8
  29. package/lib/{board-live-cards-public-async-fwd1QI82.d.ts → board-live-cards-public-async-DlyC3PgC.d.ts} +18 -8
  30. package/lib/board-live-cards-public.cjs +1 -1
  31. package/lib/board-live-cards-public.d.cts +2 -2
  32. package/lib/board-live-cards-public.d.ts +2 -2
  33. package/lib/board-live-cards-public.js +1 -1
  34. package/lib/board-live-cards-server-runtime.cjs +1 -1
  35. package/lib/board-live-cards-server-runtime.d.cts +6 -8
  36. package/lib/board-live-cards-server-runtime.d.ts +6 -8
  37. package/lib/board-live-cards-server-runtime.js +1 -1
  38. package/lib/{board-platform-adapter-async-BfHmHdx2.d.cts → board-platform-adapter-async-BZIftm36.d.cts} +18 -14
  39. package/lib/{board-platform-adapter-async-DYahVzIK.d.ts → board-platform-adapter-async-JP9V-U5E.d.ts} +18 -14
  40. package/lib/board-worker-adapter.cjs +1 -24
  41. package/lib/board-worker-adapter.d.cts +68 -3
  42. package/lib/board-worker-adapter.d.ts +68 -3
  43. package/lib/board-worker-adapter.js +1 -24
  44. package/lib/card-store-public.d.cts +2 -2
  45. package/lib/card-store-public.d.ts +2 -2
  46. package/lib/chat-store-public.cjs +1 -1
  47. package/lib/chat-store-public.d.cts +20 -20
  48. package/lib/chat-store-public.d.ts +20 -20
  49. package/lib/chat-store-public.js +1 -1
  50. package/lib/chunk-2GSI6C45.js +7 -0
  51. package/lib/chunk-35N7ONTH.js +2 -0
  52. package/lib/chunk-37HDEW26.cjs +2 -0
  53. package/lib/{chunk-PMUSJQSR.cjs → chunk-3CZCGNY4.cjs} +2 -2
  54. package/lib/{chunk-BQS3EIEK.js → chunk-44L64VQ2.js} +3 -3
  55. package/lib/chunk-6OPXQPSC.js +2 -0
  56. package/lib/chunk-7BTZCOT5.js +2 -0
  57. package/lib/{chunk-U2N6MCD5.cjs → chunk-7JVHYHT2.cjs} +2 -2
  58. package/lib/chunk-7QZ267XP.cjs +2 -0
  59. package/lib/{chunk-XQRNDX4Q.js → chunk-ANKA7HEJ.js} +2 -2
  60. package/lib/{chunk-KAWQPLIE.cjs → chunk-BQUQTOPB.cjs} +2 -2
  61. package/lib/chunk-CMFD27ZC.cjs +3 -0
  62. package/lib/chunk-DOFNXJ4C.js +3 -0
  63. package/lib/chunk-ETW3BXHD.cjs +2 -0
  64. package/lib/{chunk-SGV7PU4H.js → chunk-FOFGEABN.js} +2 -2
  65. package/lib/chunk-GPCMBPLK.cjs +2 -0
  66. package/lib/chunk-GU3T75C4.js +3 -0
  67. package/lib/chunk-H3EHFCDZ.js +3 -0
  68. package/lib/chunk-H4TYOSMD.cjs +45 -0
  69. package/lib/chunk-HFW7E2Z7.cjs +4 -0
  70. package/lib/chunk-IQIZA7TN.cjs +7 -0
  71. package/lib/chunk-J4MHQ7JF.js +45 -0
  72. package/lib/chunk-MCPADH33.cjs +2 -0
  73. package/lib/chunk-NBJTYAYN.cjs +2 -0
  74. package/lib/chunk-NDAKMJQK.cjs +3 -0
  75. package/lib/chunk-NNSBBO5R.js +2 -0
  76. package/lib/chunk-NU5NO5NM.js +2 -0
  77. package/lib/chunk-O4RKTQBP.cjs +3 -0
  78. package/lib/chunk-O5UYCGIN.js +2 -0
  79. package/lib/chunk-Q3OTUDIE.js +2 -0
  80. package/lib/chunk-R44X3RQB.cjs +2 -0
  81. package/lib/chunk-RKKSVOP2.js +2 -0
  82. package/lib/chunk-UB54HZA4.cjs +2 -0
  83. package/lib/{chunk-CIAJNUR4.js → chunk-VGDLSS2H.js} +2 -2
  84. package/lib/{chunk-SFVO2LB2.cjs → chunk-VQCIOKJV.cjs} +3 -3
  85. package/lib/chunk-VS3BXEYK.js +4 -0
  86. package/lib/chunk-Y4WK7HE4.js +2 -0
  87. package/lib/chunk-ZK3E7L4Y.cjs +2 -0
  88. package/lib/cloud-storage.cjs +1 -1
  89. package/lib/cloud-storage.d.cts +6 -6
  90. package/lib/cloud-storage.d.ts +6 -6
  91. package/lib/cloud-storage.js +1 -1
  92. package/lib/execution-refs.cjs +1 -1
  93. package/lib/execution-refs.js +1 -1
  94. package/lib/firebase-storage/index.cjs +2 -2
  95. package/lib/firebase-storage/index.d.cts +2 -2
  96. package/lib/firebase-storage/index.d.ts +2 -2
  97. package/lib/firebase-storage/index.js +2 -2
  98. package/lib/firestore-storage/index.cjs +2 -2
  99. package/lib/firestore-storage/index.d.cts +12 -10
  100. package/lib/firestore-storage/index.d.ts +12 -10
  101. package/lib/firestore-storage/index.js +2 -2
  102. package/lib/index.d.cts +1 -1
  103. package/lib/index.d.ts +1 -1
  104. package/lib/localstorage-storage/index.cjs +1 -1
  105. package/lib/localstorage-storage/index.d.cts +10 -6
  106. package/lib/localstorage-storage/index.d.ts +10 -6
  107. package/lib/localstorage-storage/index.js +1 -1
  108. package/lib/{mcp-tool-registries-W3TRj6O5.d.cts → mcp-tool-registries-CRtea2x4.d.cts} +3 -0
  109. package/lib/{mcp-tool-registries-BBObLYga.d.ts → mcp-tool-registries-D3rWSppt.d.ts} +3 -0
  110. package/lib/server-jobs-queue-runner/index.cjs +1 -1
  111. package/lib/server-jobs-queue-runner/index.d.cts +12 -9
  112. package/lib/server-jobs-queue-runner/index.d.ts +12 -9
  113. package/lib/server-jobs-queue-runner/index.js +1 -1
  114. package/lib/server-runtime/index.cjs +1 -1
  115. package/lib/server-runtime/index.d.cts +7 -9
  116. package/lib/server-runtime/index.d.ts +7 -9
  117. package/lib/server-runtime/index.js +1 -1
  118. package/lib/server-runtime-agentface/index.d.cts +7 -9
  119. package/lib/server-runtime-agentface/index.d.ts +7 -9
  120. package/lib/server-runtime-controlface/index.cjs +1 -1
  121. package/lib/server-runtime-controlface/index.d.cts +8 -9
  122. package/lib/server-runtime-controlface/index.d.ts +8 -9
  123. package/lib/server-runtime-controlface/index.js +1 -1
  124. package/lib/server-runtime-core/index.cjs +1 -1
  125. package/lib/server-runtime-core/index.d.cts +59 -21
  126. package/lib/server-runtime-core/index.d.ts +59 -21
  127. package/lib/server-runtime-core/index.js +1 -1
  128. package/lib/server-runtime-watchers/index.cjs +1 -1
  129. package/lib/server-runtime-watchers/index.d.cts +9 -65
  130. package/lib/server-runtime-watchers/index.d.ts +9 -65
  131. package/lib/server-runtime-watchers/index.js +1 -1
  132. package/lib/server-runtime-webhooks/index.d.cts +7 -9
  133. package/lib/server-runtime-webhooks/index.d.ts +7 -9
  134. package/lib/sse-hub-CYXisfXJ.d.cts +63 -0
  135. package/lib/sse-hub-Dodwtc3_.d.ts +63 -0
  136. package/lib/step-machine-public/index.cjs +1 -1
  137. package/lib/step-machine-public/index.d.cts +1 -1
  138. package/lib/step-machine-public/index.d.ts +1 -1
  139. package/lib/step-machine-public/index.js +1 -1
  140. package/lib/{storage-async-interface-BRR4eBjx.d.cts → storage-async-interface-CG0bMqvE.d.ts} +20 -1
  141. package/lib/{storage-async-interface-DhlOVPSp.d.ts → storage-async-interface-CyO-zwVQ.d.cts} +20 -1
  142. package/lib/{storage-interface-BFiD3kyB.d.ts → storage-interface-D-iEiTJA.d.cts} +45 -1
  143. package/lib/{storage-interface-BFiD3kyB.d.cts → storage-interface-D-iEiTJA.d.ts} +45 -1
  144. package/lib/stores/index.d.cts +1 -1
  145. package/lib/stores/index.d.ts +1 -1
  146. package/lib/stores/kv.d.cts +1 -1
  147. package/lib/stores/kv.d.ts +1 -1
  148. package/lib/{types-SO5OZm4s.d.ts → types-BtH3scgE.d.ts} +64 -29
  149. package/lib/{types-Ba8H5_Wo.d.cts → types-Ch0u3FKP.d.cts} +64 -29
  150. package/package.json +4 -5
  151. package/browser/board-livecards-client.js +0 -2
  152. package/examples/board/demo-shell-with-server.html +0 -272
  153. package/examples/board/doc.html +0 -465
  154. package/examples/board/server-config.json +0 -24
  155. package/lib/chat-storage-lib-B9Q34Dyv.d.cts +0 -54
  156. package/lib/chat-storage-lib-DB9iSai2.d.ts +0 -54
  157. package/lib/chunk-5XHOHTLZ.cjs +0 -2
  158. package/lib/chunk-6APH25VI.js +0 -2
  159. package/lib/chunk-76C7N4YT.js +0 -3
  160. package/lib/chunk-76ON3V7R.js +0 -2
  161. package/lib/chunk-7ICPAABP.cjs +0 -7
  162. package/lib/chunk-ASR44K7H.cjs +0 -3
  163. package/lib/chunk-CPAXTVBQ.cjs +0 -2
  164. package/lib/chunk-EGRHWZRV.js +0 -2
  165. package/lib/chunk-EZENHAVZ.cjs +0 -2
  166. package/lib/chunk-GL2OHR2E.cjs +0 -2
  167. package/lib/chunk-GYQXDNNI.cjs +0 -2
  168. package/lib/chunk-IPLSRN6P.cjs +0 -4
  169. package/lib/chunk-J6EGN6S4.cjs +0 -3
  170. package/lib/chunk-JH37NJGP.js +0 -3
  171. package/lib/chunk-JJL5VOQZ.cjs +0 -3
  172. package/lib/chunk-NJJ7WEDT.cjs +0 -2
  173. package/lib/chunk-NKIQRCOM.cjs +0 -2
  174. package/lib/chunk-PBOQ4HYB.cjs +0 -2
  175. package/lib/chunk-PRKRXAVN.js +0 -3
  176. package/lib/chunk-QJVR3FWQ.js +0 -2
  177. package/lib/chunk-S44QZUDX.js +0 -2
  178. package/lib/chunk-TSN3RTXT.js +0 -4
  179. package/lib/chunk-VXJHBWK3.js +0 -2
  180. package/lib/chunk-WHDEBJLT.js +0 -7
  181. package/lib/chunk-YGALANRO.js +0 -2
  182. package/lib/chunk-ZCNN6XPV.js +0 -2
@@ -6,7 +6,7 @@
6
6
  * Targets the 'live' board with --cards-pattern cardT* to load only the 3
7
7
  * test cards (cardT-portfolio, cardT-market-prices, cardT-portfolio-value).
8
8
  *
9
- * T0: init-board → SSE initial payload → wait for all cards to complete
9
+ * T0: /sse?one-shot bootstrap → SSE initial payload → wait for all cards to complete
10
10
  * T1: PATCH holdings (+1 row) → verify recomputation (holdings +1, positions +1)
11
11
  *
12
12
  * Usage:
@@ -14,7 +14,6 @@
14
14
  */
15
15
 
16
16
  import { spawn, spawnSync } from 'node:child_process';
17
- import { Worker } from 'node:worker_threads';
18
17
  import { fileURLToPath } from 'node:url';
19
18
  import path from 'node:path';
20
19
  import http from 'node:http';
@@ -51,8 +50,17 @@ const RUN_ID = `run-${Date.now()}-${process.pid}-${Math.random().toString(36).sl
51
50
  const BOARD_ID = 'live';
52
51
  const BOARD_DIR = path.resolve(__dirname, '..');
53
52
  const SERVER_SCRIPT = path.resolve(BOARD_DIR, 'server', 'board-server.js');
54
- const SSE_WORKER_SCRIPT = path.join(__dirname, 'sse-worker.js');
55
- const CARD_PATTERN = 'cardT*';
53
+ // Force the board server to start with zero cards; the test upserts the
54
+ // three cardT-* fixtures itself in T0 so the SSE upsert/delta path is
55
+ // exercised end-to-end.
56
+ const CARD_PATTERN = '__none__*';
57
+ const CARDS_DIR = path.resolve(BOARD_DIR, 'cards');
58
+ const T0_CARD_FILES = [
59
+ 'cardT-portfolio.json',
60
+ 'cardT-market-prices.json',
61
+ 'cardT-portfolio-value.json',
62
+ ];
63
+ const T0_EXPECTED_CARD_IDS = ['card-market-prices', 'card-portfolio', 'card-portfolio-value'];
56
64
  const T2_FILE_CARD_ID = 'card-market-prices';
57
65
  const CHAT_CARD_ID = 'card-portfolio';
58
66
 
@@ -92,7 +100,6 @@ if (fs.existsSync(SETUP_DIR)) {
92
100
  // ---------------------------------------------------------------------------
93
101
 
94
102
  const NS = {
95
- initialPayload: null,
96
103
  statusSummary: null,
97
104
  statusGeneration: 0,
98
105
  computedValues: {},
@@ -102,9 +109,6 @@ const NS = {
102
109
 
103
110
  function applyFrame(payload) {
104
111
  if (payload && Array.isArray(payload.cardDefinitions)) {
105
- if (!NS.initialPayload && payload.cardDefinitions.length > 0) {
106
- NS.initialPayload = payload;
107
- }
108
112
  const summary = payload.statusSnapshot && payload.statusSnapshot.summary;
109
113
  if (summary) {
110
114
  NS.statusSummary = summary;
@@ -267,9 +271,6 @@ async function stopChildProcess(proc, label) {
267
271
  }
268
272
  }
269
273
 
270
- const waitForInitialPayload = (ms = 15_000) =>
271
- waitUntil(() => NS.initialPayload || false, ms, 'initial SSE payload');
272
-
273
274
  const waitForAllCompleted = (ms = 60_000, label = 'all completed') =>
274
275
  waitUntil(() => {
275
276
  const s = NS.statusSummary;
@@ -502,12 +503,12 @@ console.log(`target: ${BASE}`);
502
503
  console.log(`card pattern: ${CARD_PATTERN}`);
503
504
 
504
505
  const serverProc = await startServer(PORT);
505
- let sseWorker = null;
506
+ let boardSseClient = null;
506
507
  let chatSseClient = null;
507
508
  let chatSseClientId = '';
508
509
 
509
510
  try {
510
- // ── T0: init-board, SSE connect, wait for initial completion ──
511
+ // ── T0: one-shot bootstrap, SSE connect, wait for initial completion ──
511
512
 
512
513
  // Register the 'live' board via POST (v8 runtime requires explicit registration)
513
514
  const regRes = await httpJson('POST', `http://127.0.0.1:${PORT}/api/boards`, { id: BOARD_ID, label: 'Live' });
@@ -515,31 +516,34 @@ try {
515
516
  `POST /api/boards returned ${regRes.status}: ${JSON.stringify(regRes.data)}`);
516
517
  console.log(`[setup] board '${BOARD_ID}' registered (${regRes.status})`);
517
518
 
518
- console.log('\n=== T0 Step 1: init-board ===');
519
- const initRes = await httpGet(`${BASE}/init-board`);
520
- assert(initRes.status === 200, `init-board returned ${initRes.status}`);
521
- console.log('[T0.1] init-board ok');
522
-
523
- console.log('\n=== T0 Step 2: start SSE worker ===');
519
+ console.log('\n=== T0 Step 1: start SSE client (board expected empty) ===');
524
520
  const sseClientId = `server-http-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
525
521
  const sseUrl = `${BASE}/sse?clientId=${encodeURIComponent(sseClientId)}`;
526
- sseWorker = new Worker(SSE_WORKER_SCRIPT, {
527
- workerData: { sseUrl },
528
- });
529
- sseWorker.on('message', (msg) => {
530
- if (msg.type === 'frame') applyFrame(msg.payload);
531
- else if (msg.type === 'error') console.error(`[sse-worker] ${msg.message}`);
532
- });
533
- sseWorker.on('error', (err) => console.error(`[sse-worker] uncaught: ${err.message}`));
534
-
535
- const initialPayload = await waitForInitialPayload();
536
- const cardCount = Array.isArray(initialPayload.cardDefinitions) ? initialPayload.cardDefinitions.length : 0;
537
- assert(cardCount === 3, `expected 3 cards (cardT*), got ${cardCount}`);
538
- const cardIds = initialPayload.cardDefinitions.map(c => c.id).sort();
539
- console.log(`[T0.2] SSE initial payload received (${cardCount} cards: ${cardIds.join(', ')})`);
522
+ boardSseClient = startSseClient(sseUrl, applyFrame);
523
+ // Give the streaming endpoint a moment to deliver the initial (empty) snapshot.
524
+ await wait(500);
525
+ console.log('[T0.1] SSE client connected');
526
+
527
+ console.log('\n=== T0 Step 2: upsert 3 cardT-* fixtures ===');
528
+ for (const fileName of T0_CARD_FILES) {
529
+ const cardJson = JSON.parse(fs.readFileSync(path.join(CARDS_DIR, fileName), 'utf-8'));
530
+ const cardId = cardJson?.id;
531
+ assert(typeof cardId === 'string' && cardId.length > 0, `fixture ${fileName} missing id`);
532
+ const upsertRes = await httpMcp('manage.upsert-card', {
533
+ card_id: cardId,
534
+ candidate_card_content: cardJson,
535
+ });
536
+ assert(upsertRes.status === 200, `manage.upsert-card(${cardId}) returned ${upsertRes.status}: ${JSON.stringify(upsertRes.data)}`);
537
+ assert(upsertRes.data?.status === 'success', `manage.upsert-card(${cardId}) failed: ${JSON.stringify(upsertRes.data)}`);
538
+ console.log(`[T0.2] upserted ${cardId}`);
539
+ }
540
540
 
541
- console.log('\n=== T0 Step 3: wait for all cards to complete ===');
542
- const t0Summary = await waitForAllCompleted(30_000, 'T0 initial completion');
541
+ console.log('\n=== T0 Step 3: wait for all 3 cards to complete via SSE ===');
542
+ const t0Summary = await waitUntil(() => {
543
+ const s = NS.statusSummary;
544
+ if (s && s.card_count === 3 && s.completed === 3) return s;
545
+ return false;
546
+ }, 60_000, 'T0 initial completion (3 cards)');
543
547
  assert(t0Summary.failed === 0, `T0 expected failed=0, got ${t0Summary.failed}`);
544
548
  console.log(`[T0.3] completed: ${JSON.stringify(t0Summary)}`);
545
549
 
@@ -549,6 +553,8 @@ try {
549
553
  assert(statusMcpRes.data?.status === 'success', `inspect.board-runtime-status failed: ${JSON.stringify(statusMcpRes.data)}`);
550
554
  const mcpSummary = statusMcpRes.data?.data?.summary;
551
555
  assert(mcpSummary, 'summary missing from inspect.board-runtime-status');
556
+ assert(mcpSummary.card_count === T0_EXPECTED_CARD_IDS.length,
557
+ `expected card_count=${T0_EXPECTED_CARD_IDS.length}, got ${mcpSummary.card_count}`);
552
558
  assert(mcpSummary.completed === mcpSummary.card_count, `not all complete: ${JSON.stringify(mcpSummary)}`);
553
559
  console.log(`[T0.4] board-status: ${JSON.stringify(mcpSummary)}`);
554
560
 
@@ -740,25 +746,34 @@ try {
740
746
 
741
747
  const t3TurnId = randomTurnId();
742
748
  t3Dbg(`step 4: posting probe chat-send (turn-id=${t3TurnId})`);
743
- const t2SendRes = await httpJson('POST', `${BASE}/cards/${CHAT_CARD_ID}/actions`, {
744
- actionType: 'chat-send',
745
- payload: {
746
- text: `${ECHO_PROBE_MARKER}${t2ProbePrompt}${ECHO_PROBE_MARKER}`,
747
- 'turn-id': t3TurnId,
749
+ const t2SendRes = await httpJson('POST', `${BASE}/mcp-actions`, {
750
+ tool: 'chat-send',
751
+ args: {
752
+ card_id: CHAT_CARD_ID,
753
+ payload: {
754
+ text: `${ECHO_PROBE_MARKER}${t2ProbePrompt}${ECHO_PROBE_MARKER}`,
755
+ 'turn-id': t3TurnId,
756
+ },
748
757
  },
749
758
  });
750
759
  t3Dbg(`step 4: chat-send returned status=${t2SendRes.status}`);
751
760
  assert(t2SendRes.status === 200, `T3 chat-send returned ${t2SendRes.status}`);
752
761
 
753
762
  t3Dbg('step 5: waiting for ordered probe lifecycle on chat SSE');
754
- const t2Lifecycle = await waitForChatPredicate((events) => {
755
- return matchOrderedProbeLifecycle(events.slice(t2EventStart), {
756
- beforeCount: t2BeforeCount,
757
- beforeProcessing: false,
758
- prompt: t2ProbePrompt,
759
- inProgressText: PROBE_IN_PROGRESS_TEXT,
760
- });
761
- }, 45_000, 'T3 ordered lifecycle');
763
+ let t2Lifecycle;
764
+ try {
765
+ t2Lifecycle = await waitForChatPredicate((events) => {
766
+ return matchOrderedProbeLifecycle(events.slice(t2EventStart), {
767
+ beforeCount: t2BeforeCount,
768
+ beforeProcessing: false,
769
+ prompt: t2ProbePrompt,
770
+ inProgressText: PROBE_IN_PROGRESS_TEXT,
771
+ });
772
+ }, 45_000, 'T3 ordered lifecycle');
773
+ } catch (error) {
774
+ t3Dbg(`step 5: lifecycle timeout; events=${JSON.stringify(NS.chatEvents.slice(t2EventStart), null, 2)}`);
775
+ throw error;
776
+ }
762
777
  t3Dbg('step 5: ordered lifecycle observed');
763
778
  assert(!!t2Lifecycle, 'T3 ordered lifecycle not observed');
764
779
 
@@ -818,14 +833,17 @@ try {
818
833
 
819
834
  const t3aTurnId = randomTurnId();
820
835
  t3aDbg(`step 2: posting non-probe chat-send (turn-id=${t3aTurnId})`);
821
- const t2aSendRes = await httpJson('POST', `${BASE}/cards/${CHAT_CARD_ID}/actions`, {
822
- actionType: 'chat-send',
823
- payload: {
824
- text: JSON.stringify({
825
- prompt: t2aPrompt,
826
- chatTimeoutMs: 180000,
827
- }),
828
- 'turn-id': t3aTurnId,
836
+ const t2aSendRes = await httpJson('POST', `${BASE}/mcp-actions`, {
837
+ tool: 'chat-send',
838
+ args: {
839
+ card_id: CHAT_CARD_ID,
840
+ payload: {
841
+ text: JSON.stringify({
842
+ prompt: t2aPrompt,
843
+ chatTimeoutMs: 180000,
844
+ }),
845
+ 'turn-id': t3aTurnId,
846
+ },
829
847
  },
830
848
  });
831
849
  t3aDbg(`step 2: chat-send returned status=${t2aSendRes.status}`);
@@ -910,12 +928,14 @@ try {
910
928
  const t2bEventStart = NS.chatEvents.length;
911
929
 
912
930
  const t2bPrompt = `probe echo file-upload validation ${Date.now()}`;
913
- const t2bSendRes = await httpJson('POST', `${BASE}/cards/${CHAT_CARD_ID}/actions`, {
914
- actionType: 'chat-send',
915
- payload: {
916
- text: `${ECHO_PROBE_MARKER}${t2bPrompt}${ECHO_PROBE_MARKER}`,
917
- files: [uploadedFile],
918
- 'turn-id': t3bTurnId,
931
+ const t2bSendRes = await httpJson('POST', `${BASE}/mcp-actions`, {
932
+ tool: 'chat-send',
933
+ args: {
934
+ card_id: CHAT_CARD_ID,
935
+ payload: {
936
+ text: `${ECHO_PROBE_MARKER}${t2bPrompt}${ECHO_PROBE_MARKER}`,
937
+ 'turn-id': t3bTurnId,
938
+ },
919
939
  },
920
940
  });
921
941
  assert(t2bSendRes.status === 200, `T3b chat-send returned ${t2bSendRes.status}`);
@@ -925,10 +945,22 @@ try {
925
945
  beforeCount: t2bSendBaseline,
926
946
  beforeProcessing: false,
927
947
  prompt: t2bPrompt,
928
- assistantText: 'tokyo',
929
948
  inProgressText: PROBE_IN_PROGRESS_TEXT,
930
949
  });
931
- }, 60_000, 'T3b ordered lifecycle');
950
+ }, 60_000, 'T3b ordered lifecycle').catch(async (err) => {
951
+ const t2bEvents = NS.chatEvents.slice(t2bEventStart);
952
+ const t2bMilestones = deriveProbeLifecycleMilestones(t2bEvents, {
953
+ beforeCount: t2bSendBaseline,
954
+ beforeProcessing: false,
955
+ prompt: t2bPrompt,
956
+ inProgressText: PROBE_IN_PROGRESS_TEXT,
957
+ });
958
+ const t2bCurrent = await httpMcp('inspect.chat-messages-on-cards', { card_id: CHAT_CARD_ID, all_turns: true });
959
+ console.error('[T3b.DBG timeout] milestones=', JSON.stringify(t2bMilestones));
960
+ console.error('[T3b.DBG timeout] events=', JSON.stringify(t2bEvents));
961
+ console.error('[T3b.DBG timeout] inspect=', JSON.stringify(t2bCurrent?.data ?? null));
962
+ throw err;
963
+ });
932
964
  assert(!!t2bLifecycle, 'T3b ordered lifecycle not observed');
933
965
 
934
966
  const t2bAfter = await httpMcp('inspect.chat-messages-on-cards', { card_id: CHAT_CARD_ID, all_turns: true });
@@ -944,9 +976,9 @@ try {
944
976
  assert(!!t2bUser && typeof t2bUser.id === 'string', 'T3b missing user chat message notification');
945
977
  assert(!!t2bInProgress && typeof t2bInProgress.id === 'string', 'T3b missing in-progress system chat message');
946
978
  assert(!!t2bAssistantMsg && typeof t2bAssistantMsg.id === 'string', 'T3b missing assistant chat message notification');
947
- assert(Array.isArray(t2bUser?.files) && t2bUser.files.length === 1, 'T3b user chat message missing uploaded file metadata');
948
- assert(String(t2bAssistantMsg?.text || '').trim() === 'tokyo', 'T3b assistant attachment content mismatch');
949
- console.log('[T3b] ok: upload protocol and ordered probe lifecycle observed with attachment-derived assistant reply');
979
+ assert(!Array.isArray(t2bUser?.files) || t2bUser.files.length === 0, 'T3b user chat message should remain text-only after add-chat-attachment upload');
980
+ assert(String(t2bAssistantMsg?.text || '').includes(`Echo: ${t2bPrompt}`), 'T3b assistant probe echo mismatch');
981
+ console.log('[T3b] ok: add-chat-attachment upload plus text-only chat-send preserved the normal probe lifecycle');
950
982
  }
951
983
 
952
984
  // ── T3d: probe-echo chat with one AI-generated attachment ──
@@ -982,11 +1014,14 @@ try {
982
1014
  const t3dTurnId = randomTurnId();
983
1015
  const t2dPrompt = `probe generated attachment validation ${Date.now()}`;
984
1016
  const t2dEventStart = NS.chatEvents.length;
985
- const t2dSendRes = await httpJson('POST', `${BASE}/cards/${CHAT_CARD_ID}/actions`, {
986
- actionType: 'chat-send',
987
- payload: {
988
- text: `${ECHO_PROBE_MARKER}[attach] ${t2dPrompt}${ECHO_PROBE_MARKER}`,
989
- 'turn-id': t3dTurnId,
1017
+ const t2dSendRes = await httpJson('POST', `${BASE}/mcp-actions`, {
1018
+ tool: 'chat-send',
1019
+ args: {
1020
+ card_id: CHAT_CARD_ID,
1021
+ payload: {
1022
+ text: `${ECHO_PROBE_MARKER}[attach] ${t2dPrompt}${ECHO_PROBE_MARKER}`,
1023
+ 'turn-id': t3dTurnId,
1024
+ },
990
1025
  },
991
1026
  });
992
1027
  assert(t2dSendRes.status === 200, `T3d chat-send returned ${t2dSendRes.status}`);
@@ -1643,8 +1678,8 @@ try {
1643
1678
  } catch { /* ignore */ }
1644
1679
  }
1645
1680
  if (chatSseClient) chatSseClient.close();
1681
+ if (boardSseClient) boardSseClient.close();
1646
1682
  await stopChildProcess(serverProc, 'demo board server');
1647
- if (sseWorker) await sseWorker.terminate();
1648
1683
 
1649
1684
  // Clean up the test setup directory
1650
1685
  if (fs.existsSync(SETUP_DIR)) {
@@ -55,8 +55,15 @@ const runtime = createSingleBoardServerRuntime({
55
55
  label: `Board — ${BOARD_ID}`,
56
56
  boardAdapter,
57
57
  baseRef: { kind: 'firestore', value: `boards/${BOARD_ID}` },
58
+ boardRuntimeStoreRef: makeRef('firestore', `boards/${BOARD_ID}/runtime-board`),
58
59
  cardStoreRef: makeRef('firestore', `boards/${BOARD_ID}/cards`),
59
60
  outputsStoreRef: makeRef('firestore', `boards/${BOARD_ID}/runtime-out`),
61
+ queueStoreRef: makeRef('firestore', `boards/${BOARD_ID}/runtime`),
62
+ fetchedSourcesStoreRef: makeRef('firestore', `boards/${BOARD_ID}/sources`),
63
+ chatStoreRef: makeRef('firestore', `boards/${BOARD_ID}/chat`),
64
+ artifactsStoreRef: makeRef('firestore', `boards/${BOARD_ID}/files`),
65
+ scratchStoreRef: makeRef('firestore', `boards/${BOARD_ID}/scratch`),
66
+ archiveStoreRef: makeRef('firestore', `boards/${BOARD_ID}/archive`),
60
67
  },
61
68
  ],
62
69
  invocationAdapter: {
@@ -80,6 +87,7 @@ const runtime = createSingleBoardServerRuntime({
80
87
  const stopRunners = startQueueLaneRunners(
81
88
  createHostedBoardQueueLaneRegistry({
82
89
  boardId: BOARD_ID,
90
+ queueStoreRef: makeRef('firestore', `boards/${BOARD_ID}/runtime`),
83
91
  runtime,
84
92
  boardAdapter,
85
93
  logger: {
@@ -38,10 +38,20 @@ const _TMP_BASE = path.join(os.tmpdir(), 'experiment-js');
38
38
  const CARDSTORE_DIR = path.join(_TMP_BASE, 'cardstore');
39
39
  const BOARDRUNTIME_DIR = path.join(_TMP_BASE, 'boardruntime');
40
40
  const OUTPUTS_DIR = path.join(_TMP_BASE, 'outputs');
41
+ const CHAT_DIR = path.join(_TMP_BASE, 'chat');
42
+ const FILES_DIR = path.join(_TMP_BASE, 'files');
43
+ const SOURCES_DIR = path.join(_TMP_BASE, 'sources');
44
+ const SCRATCH_DIR = path.join(_TMP_BASE, 'scratch');
45
+ const ARCHIVE_DIR = path.join(_TMP_BASE, 'archive');
41
46
 
42
47
  const CARDSTORE_REF = serializeRef({ kind: 'fs-path', value: CARDSTORE_DIR });
43
48
  const BOARDRUNTIME_REF = serializeRef({ kind: 'fs-path', value: BOARDRUNTIME_DIR });
44
49
  const OUTPUTS_REF = serializeRef({ kind: 'fs-path', value: OUTPUTS_DIR });
50
+ const CHAT_REF = serializeRef({ kind: 'fs-path', value: CHAT_DIR });
51
+ const FILES_REF = serializeRef({ kind: 'fs-path', value: FILES_DIR });
52
+ const SOURCES_REF = serializeRef({ kind: 'fs-path', value: SOURCES_DIR });
53
+ const SCRATCH_REF = serializeRef({ kind: 'fs-path', value: SCRATCH_DIR });
54
+ const ARCHIVE_REF = serializeRef({ kind: 'fs-path', value: ARCHIVE_DIR });
45
55
  const NOTIFY_CHANNEL = 'yaml-flow-board-notify-portfolio-tracker-public';
46
56
 
47
57
  // ── Card definitions ───────────────────────────────────────────────────────────
@@ -399,7 +409,7 @@ const pipeConsumer = await startPipeConsumer(NOTIFY_CHANNEL);
399
409
  console.log('\n=== T0b: Init board ===');
400
410
  checkResult(
401
411
  makeBoard().init({
402
- params: { cardStoreRef: CARDSTORE_REF, outputsStoreRef: OUTPUTS_REF },
412
+ params: { cardStoreRef: CARDSTORE_REF, outputsStoreRef: OUTPUTS_REF, chatStoreRef: CHAT_REF, artifactsStoreRef: FILES_REF, fetchedSourcesStoreRef: SOURCES_REF, scratchStoreRef: SCRATCH_REF, archiveStoreRef: ARCHIVE_REF },
403
413
  body: {
404
414
  'task-executor-ref': {
405
415
  meta: 'task-executor',
@@ -2,7 +2,7 @@
2
2
  /**
3
3
  * portfolio-t4.js — T4 rapid-fire test only.
4
4
  *
5
- * Public-examples variant. Runs T0 init, then fires 5 portfolio-form upserts
5
+ * Examples variant. Runs T0 init, then fires 5 portfolio-form upserts
6
6
  * back-to-back and waits for convergence.
7
7
  */
8
8
 
@@ -30,10 +30,20 @@ const _TMP_BASE = path.join(os.tmpdir(), 'experiment-js-t4');
30
30
  const CARDSTORE_DIR = path.join(_TMP_BASE, 'cardstore');
31
31
  const BOARDRUNTIME_DIR = path.join(_TMP_BASE, 'boardruntime');
32
32
  const OUTPUTS_DIR = path.join(_TMP_BASE, 'outputs');
33
+ const CHAT_DIR = path.join(_TMP_BASE, 'chat');
34
+ const FILES_DIR = path.join(_TMP_BASE, 'files');
35
+ const SOURCES_DIR = path.join(_TMP_BASE, 'sources');
36
+ const SCRATCH_DIR = path.join(_TMP_BASE, 'scratch');
37
+ const ARCHIVE_DIR = path.join(_TMP_BASE, 'archive');
33
38
 
34
39
  const CARDSTORE_REF = serializeRef({ kind: 'fs-path', value: CARDSTORE_DIR });
35
40
  const BOARDRUNTIME_REF = serializeRef({ kind: 'fs-path', value: BOARDRUNTIME_DIR });
36
41
  const OUTPUTS_REF = serializeRef({ kind: 'fs-path', value: OUTPUTS_DIR });
42
+ const CHAT_REF = serializeRef({ kind: 'fs-path', value: CHAT_DIR });
43
+ const FILES_REF = serializeRef({ kind: 'fs-path', value: FILES_DIR });
44
+ const SOURCES_REF = serializeRef({ kind: 'fs-path', value: SOURCES_DIR });
45
+ const SCRATCH_REF = serializeRef({ kind: 'fs-path', value: SCRATCH_DIR });
46
+ const ARCHIVE_REF = serializeRef({ kind: 'fs-path', value: ARCHIVE_DIR });
37
47
 
38
48
  const CARD_PORTFOLIO_FORM = {
39
49
  id: 'portfolio-form',
@@ -153,7 +163,7 @@ console.log(` runtime base: ${_TMP_BASE}`);
153
163
 
154
164
  checkResult(
155
165
  makeBoard().init({
156
- params: { cardStoreRef: CARDSTORE_REF, outputsStoreRef: OUTPUTS_REF },
166
+ params: { cardStoreRef: CARDSTORE_REF, outputsStoreRef: OUTPUTS_REF, chatStoreRef: CHAT_REF, artifactsStoreRef: FILES_REF, fetchedSourcesStoreRef: SOURCES_REF, scratchStoreRef: SCRATCH_REF, archiveStoreRef: ARCHIVE_REF },
157
167
  body: { 'task-executor-ref': { meta: 'task-executor', howToRun: 'local-node', whatToRun: serializeRef({ kind: 'fs-path', value: FETCH_PRICES_JS }) } },
158
168
  }),
159
169
  'init',
@@ -1,4 +1,4 @@
1
- import { B as BlobStorage } from './storage-interface-BFiD3kyB.cjs';
1
+ import { B as BlobStorage } from './storage-interface-D-iEiTJA.cjs';
2
2
 
3
3
  /**
4
4
  * artifacts-store-lib.ts
@@ -1,4 +1,4 @@
1
- import { B as BlobStorage } from './storage-interface-BFiD3kyB.js';
1
+ import { B as BlobStorage } from './storage-interface-D-iEiTJA.js';
2
2
 
3
3
  /**
4
4
  * artifacts-store-lib.ts
@@ -1,6 +1,6 @@
1
- import { C as CommandInput, a as CommandResult } from './board-live-cards-public-LlVUQPL2.cjs';
2
- import { A as ArtifactInfo, a as ArtifactsStore } from './artifacts-store-lib-D9nMkVcE.cjs';
3
- import './storage-interface-BFiD3kyB.cjs';
1
+ import { C as CommandInput, a as CommandResult } from './board-live-cards-public-BT5HrgqZ.cjs';
2
+ import { A as ArtifactInfo, a as ArtifactsStore } from './artifacts-store-lib-C6qBpMfU.cjs';
3
+ import './storage-interface-D-iEiTJA.cjs';
4
4
  import './execution-refs.cjs';
5
5
  import './types-BBhqYGhE.cjs';
6
6
 
@@ -1,6 +1,6 @@
1
- import { C as CommandInput, a as CommandResult } from './board-live-cards-public-JNRKfBZy.js';
2
- import { A as ArtifactInfo, a as ArtifactsStore } from './artifacts-store-lib-DSSMqVL2.js';
3
- import './storage-interface-BFiD3kyB.js';
1
+ import { C as CommandInput, a as CommandResult } from './board-live-cards-public-DSRamFm8.js';
2
+ import { A as ArtifactInfo, a as ArtifactsStore } from './artifacts-store-lib-D4qf7Q-7.js';
3
+ import './storage-interface-D-iEiTJA.js';
4
4
  import './execution-refs.js';
5
5
  import './types-BBhqYGhE.js';
6
6
 
@@ -1,2 +1,2 @@
1
- 'use strict';var chunkPBOQ4HYB_cjs=require('./chunk-PBOQ4HYB.cjs');require('./chunk-IXZG74EW.cjs'),require('./chunk-HWYMZK3N.cjs'),require('./chunk-UJ7ZTV4J.cjs'),require('./chunk-GNFE24S7.cjs');Object.defineProperty(exports,"createBoardLiveCardsMcp",{enumerable:true,get:function(){return chunkPBOQ4HYB_cjs.a}});//# sourceMappingURL=board-live-cards-mcp.cjs.map
1
+ 'use strict';var chunk7QZ267XP_cjs=require('./chunk-7QZ267XP.cjs');require('./chunk-IXZG74EW.cjs'),require('./chunk-HWYMZK3N.cjs'),require('./chunk-UJ7ZTV4J.cjs'),require('./chunk-GNFE24S7.cjs');Object.defineProperty(exports,"createBoardLiveCardsMcp",{enumerable:true,get:function(){return chunk7QZ267XP_cjs.a}});//# sourceMappingURL=board-live-cards-mcp.cjs.map
2
2
  //# sourceMappingURL=board-live-cards-mcp.cjs.map
@@ -1,7 +1,6 @@
1
- import { L as LiveCard, a as CommandResult } from './board-live-cards-public-LlVUQPL2.cjs';
1
+ import { L as LiveCard, g as ChatRecord, a as CommandResult } from './board-live-cards-public-BT5HrgqZ.cjs';
2
2
  import { ChatStorePublic } from './chat-store-public.cjs';
3
- import { a as ChatRecord } from './chat-storage-lib-B9Q34Dyv.cjs';
4
- import './storage-interface-BFiD3kyB.cjs';
3
+ import './storage-interface-D-iEiTJA.cjs';
5
4
  import './execution-refs.cjs';
6
5
  import './types-BBhqYGhE.cjs';
7
6
 
@@ -362,17 +361,17 @@ interface BoardLiveCardsMcp {
362
361
  }): Promise<BoardLiveCardsMcpManageUpsertCardResult>;
363
362
  getChatProcessing(args: {
364
363
  cardId: string;
365
- }): {
364
+ }): Promise<{
366
365
  cardId: string;
367
366
  active: boolean;
368
- };
367
+ }>;
369
368
  setChatProcessing(args: {
370
369
  cardId: string;
371
370
  active: boolean;
372
- }): {
371
+ }): Promise<{
373
372
  cardId: string;
374
373
  active: boolean;
375
- };
374
+ }>;
376
375
  webhookProcessAccumulated(): Promise<CommandResult<{
377
376
  runtime_result: unknown;
378
377
  }>>;
@@ -1,7 +1,6 @@
1
- import { L as LiveCard, a as CommandResult } from './board-live-cards-public-JNRKfBZy.js';
1
+ import { L as LiveCard, g as ChatRecord, a as CommandResult } from './board-live-cards-public-DSRamFm8.js';
2
2
  import { ChatStorePublic } from './chat-store-public.js';
3
- import { a as ChatRecord } from './chat-storage-lib-DB9iSai2.js';
4
- import './storage-interface-BFiD3kyB.js';
3
+ import './storage-interface-D-iEiTJA.js';
5
4
  import './execution-refs.js';
6
5
  import './types-BBhqYGhE.js';
7
6
 
@@ -362,17 +361,17 @@ interface BoardLiveCardsMcp {
362
361
  }): Promise<BoardLiveCardsMcpManageUpsertCardResult>;
363
362
  getChatProcessing(args: {
364
363
  cardId: string;
365
- }): {
364
+ }): Promise<{
366
365
  cardId: string;
367
366
  active: boolean;
368
- };
367
+ }>;
369
368
  setChatProcessing(args: {
370
369
  cardId: string;
371
370
  active: boolean;
372
- }): {
371
+ }): Promise<{
373
372
  cardId: string;
374
373
  active: boolean;
375
- };
374
+ }>;
376
375
  webhookProcessAccumulated(): Promise<CommandResult<{
377
376
  runtime_result: unknown;
378
377
  }>>;
@@ -1,2 +1,2 @@
1
- export{a as createBoardLiveCardsMcp}from'./chunk-ZCNN6XPV.js';import'./chunk-JMDHDY6M.js';import'./chunk-3KC6LBOG.js';import'./chunk-MNEOJWPS.js';import'./chunk-FW4363Y4.js';//# sourceMappingURL=board-live-cards-mcp.js.map
1
+ export{a as createBoardLiveCardsMcp}from'./chunk-35N7ONTH.js';import'./chunk-JMDHDY6M.js';import'./chunk-3KC6LBOG.js';import'./chunk-MNEOJWPS.js';import'./chunk-FW4363Y4.js';//# sourceMappingURL=board-live-cards-mcp.js.map
2
2
  //# sourceMappingURL=board-live-cards-mcp.js.map