yaml-flow 5.4.0 → 6.0.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 (200) hide show
  1. package/board-live-cards-cli.js +2 -2
  2. package/board-livecards-server-runtime.js +488 -551
  3. package/browser/asset-integrity.json +10 -0
  4. package/browser/board-livecards-runtime-client.js +0 -6
  5. package/browser/board-livegraph-engine.js +2 -1676
  6. package/browser/board-livegraph-engine.js.map +1 -1
  7. package/browser/live-cards.js +347 -26
  8. package/browser/live-cards.schema.json +418 -132
  9. package/card-store.js +37 -0
  10. package/dist/batch/index.cjs +1 -108
  11. package/dist/batch/index.cjs.map +1 -1
  12. package/dist/batch/index.js +1 -106
  13. package/dist/batch/index.js.map +1 -1
  14. package/dist/board-live-cards-lib-Bg6EvCo5.d.cts +136 -0
  15. package/dist/board-live-cards-lib-jM2uYG1v.d.ts +136 -0
  16. package/dist/board-live-cards-public-CltXYgaY.d.cts +314 -0
  17. package/dist/board-live-cards-public-f-E-FAyp.d.ts +314 -0
  18. package/dist/board-livegraph-runtime/index.cjs +2 -1671
  19. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  20. package/dist/board-livegraph-runtime/index.d.cts +1 -2
  21. package/dist/board-livegraph-runtime/index.d.ts +1 -2
  22. package/dist/board-livegraph-runtime/index.js +2 -1662
  23. package/dist/board-livegraph-runtime/index.js.map +1 -1
  24. package/dist/board-livegraph-runtime/jsonata-sync.cjs +7587 -0
  25. package/dist/card-compute/index.cjs +9 -7159
  26. package/dist/card-compute/index.cjs.map +1 -1
  27. package/dist/card-compute/index.d.cts +22 -0
  28. package/dist/card-compute/index.d.ts +22 -0
  29. package/dist/card-compute/index.js +9 -7145
  30. package/dist/card-compute/index.js.map +1 -1
  31. package/dist/card-compute/jsonata-sync.cjs +7587 -0
  32. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +2 -0
  33. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -0
  34. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +24 -0
  35. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +24 -0
  36. package/dist/cli/browser-api/board-live-cards-browser-adapter.js +2 -0
  37. package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -0
  38. package/dist/cli/browser-api/card-store-browser-api.cjs +2 -0
  39. package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -0
  40. package/dist/cli/browser-api/card-store-browser-api.d.cts +26 -0
  41. package/dist/cli/browser-api/card-store-browser-api.d.ts +26 -0
  42. package/dist/cli/browser-api/card-store-browser-api.js +2 -0
  43. package/dist/cli/browser-api/card-store-browser-api.js.map +1 -0
  44. package/dist/cli/browser-api/jsonata-sync.cjs +7587 -0
  45. package/dist/cli/node/artifacts-store-cli.cjs +11 -0
  46. package/dist/cli/node/artifacts-store-cli.cjs.map +1 -0
  47. package/dist/cli/node/artifacts-store-cli.d.cts +8 -0
  48. package/dist/cli/node/artifacts-store-cli.d.ts +8 -0
  49. package/dist/cli/node/artifacts-store-cli.js +11 -0
  50. package/dist/cli/node/artifacts-store-cli.js.map +1 -0
  51. package/dist/cli/node/board-live-cards-cli.cjs +15 -0
  52. package/dist/cli/node/board-live-cards-cli.cjs.map +1 -0
  53. package/dist/cli/node/board-live-cards-cli.d.cts +20 -0
  54. package/dist/cli/node/board-live-cards-cli.d.ts +20 -0
  55. package/dist/cli/node/board-live-cards-cli.js +15 -0
  56. package/dist/cli/node/board-live-cards-cli.js.map +1 -0
  57. package/dist/cli/node/card-store-cli.cjs +8 -0
  58. package/dist/cli/node/card-store-cli.cjs.map +1 -0
  59. package/dist/cli/node/card-store-cli.d.cts +15 -0
  60. package/dist/cli/node/card-store-cli.d.ts +15 -0
  61. package/dist/cli/node/card-store-cli.js +8 -0
  62. package/dist/cli/node/card-store-cli.js.map +1 -0
  63. package/dist/cli/node/fs-board-adapter.cjs +14 -0
  64. package/dist/cli/node/fs-board-adapter.cjs.map +1 -0
  65. package/dist/cli/node/fs-board-adapter.d.cts +204 -0
  66. package/dist/cli/node/fs-board-adapter.d.ts +204 -0
  67. package/dist/cli/node/fs-board-adapter.js +14 -0
  68. package/dist/cli/node/fs-board-adapter.js.map +1 -0
  69. package/dist/cli/node/jsonata-sync.cjs +7587 -0
  70. package/dist/cli/node/source-cli-task-executor.cjs +11 -0
  71. package/dist/cli/node/source-cli-task-executor.cjs.map +1 -0
  72. package/dist/cli/node/source-cli-task-executor.d.cts +1 -0
  73. package/dist/cli/node/source-cli-task-executor.d.ts +1 -0
  74. package/dist/cli/node/source-cli-task-executor.js +11 -0
  75. package/dist/cli/node/source-cli-task-executor.js.map +1 -0
  76. package/dist/config/index.cjs +1 -79
  77. package/dist/config/index.cjs.map +1 -1
  78. package/dist/config/index.js +1 -76
  79. package/dist/config/index.js.map +1 -1
  80. package/dist/continuous-event-graph/index.cjs +2 -2129
  81. package/dist/continuous-event-graph/index.cjs.map +1 -1
  82. package/dist/continuous-event-graph/index.d.cts +81 -5
  83. package/dist/continuous-event-graph/index.d.ts +81 -5
  84. package/dist/continuous-event-graph/index.js +2 -2088
  85. package/dist/continuous-event-graph/index.js.map +1 -1
  86. package/dist/continuous-event-graph/jsonata-sync.cjs +7587 -0
  87. package/dist/event-graph/index.cjs +22 -8292
  88. package/dist/event-graph/index.cjs.map +1 -1
  89. package/dist/event-graph/index.js +22 -8237
  90. package/dist/event-graph/index.js.map +1 -1
  91. package/dist/execution-refs.cjs +2 -0
  92. package/dist/execution-refs.cjs.map +1 -0
  93. package/dist/execution-refs.d.cts +222 -0
  94. package/dist/execution-refs.d.ts +222 -0
  95. package/dist/execution-refs.js +2 -0
  96. package/dist/execution-refs.js.map +1 -0
  97. package/dist/index.cjs +29 -13221
  98. package/dist/index.cjs.map +1 -1
  99. package/dist/index.d.cts +2 -4
  100. package/dist/index.d.ts +2 -4
  101. package/dist/index.js +29 -13112
  102. package/dist/index.js.map +1 -1
  103. package/dist/inference/index.cjs +5 -617
  104. package/dist/inference/index.cjs.map +1 -1
  105. package/dist/inference/index.js +5 -610
  106. package/dist/inference/index.js.map +1 -1
  107. package/dist/jsonata-sync.cjs +7587 -0
  108. package/dist/{live-cards-bridge-x5XREkXm.d.cts → live-cards-bridge-BXbVTsna.d.cts} +27 -4
  109. package/dist/{live-cards-bridge-EQjytzI_.d.ts → live-cards-bridge-Ds28XR15.d.ts} +27 -4
  110. package/dist/pycli/quickjs-board-runtime.global.js +9 -0
  111. package/dist/pycli/quickjs-board-runtime.global.js.map +1 -0
  112. package/dist/pycli/quickjs-step-machine-runtime.global.js +5 -0
  113. package/dist/pycli/quickjs-step-machine-runtime.global.js.map +1 -0
  114. package/dist/step-machine/index.cjs +11 -7129
  115. package/dist/step-machine/index.cjs.map +1 -1
  116. package/dist/step-machine/index.js +11 -7113
  117. package/dist/step-machine/index.js.map +1 -1
  118. package/dist/storage-refs.cjs +10 -0
  119. package/dist/storage-refs.cjs.map +1 -0
  120. package/dist/storage-refs.d.cts +92 -0
  121. package/dist/storage-refs.d.ts +92 -0
  122. package/dist/storage-refs.js +10 -0
  123. package/dist/storage-refs.js.map +1 -0
  124. package/dist/stores/file.cjs +1 -114
  125. package/dist/stores/file.cjs.map +1 -1
  126. package/dist/stores/file.js +1 -112
  127. package/dist/stores/file.js.map +1 -1
  128. package/dist/stores/index.cjs +1 -231
  129. package/dist/stores/index.cjs.map +1 -1
  130. package/dist/stores/index.js +1 -227
  131. package/dist/stores/index.js.map +1 -1
  132. package/dist/stores/localStorage.cjs +1 -76
  133. package/dist/stores/localStorage.cjs.map +1 -1
  134. package/dist/stores/localStorage.js +1 -74
  135. package/dist/stores/localStorage.js.map +1 -1
  136. package/dist/stores/memory.cjs +1 -47
  137. package/dist/stores/memory.cjs.map +1 -1
  138. package/dist/stores/memory.js +1 -45
  139. package/dist/stores/memory.js.map +1 -1
  140. package/examples/browser/boards/portfolio-tracker/portfolio-t4.js +292 -0
  141. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.js +218 -0
  142. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.py +201 -0
  143. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +25 -16
  144. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-public.js +553 -0
  145. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +365 -0
  146. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/.runtime-out +1 -0
  147. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/board-graph.json +32 -0
  148. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +53 -1
  149. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +15 -6
  150. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +6 -1
  151. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +57 -0
  152. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +1 -1
  153. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +1 -1
  154. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +7 -2
  155. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +6 -2
  156. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +97 -0
  157. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +50 -0
  158. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +44 -0
  159. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +70 -0
  160. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/reset-board-dir.py +36 -0
  161. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-demo.flow.yaml +26 -0
  162. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-handlers.py +39 -0
  163. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker-pycli.flow.yaml +80 -0
  164. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +25 -172
  165. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +40 -34
  166. package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +46 -0
  167. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker-pycli.py +77 -0
  168. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  169. package/examples/example-board/agent-instructions.md +11 -5
  170. package/examples/example-board/demo-chat-handler.js +14 -4
  171. package/examples/example-board/demo-server-config.json +1 -0
  172. package/examples/example-board/demo-server.js +19 -34
  173. package/examples/example-board/demo-shell-browser.html +5 -4
  174. package/examples/example-board/demo-shell-with-server.html +10 -6
  175. package/examples/example-board/demo-task-executor.js +81 -35
  176. package/examples/index.html +0 -14
  177. package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -1
  178. package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  179. package/package.json +39 -3
  180. package/schema/live-cards.schema.json +418 -132
  181. package/dist/cli/board-live-cards-cli.cjs +0 -10644
  182. package/dist/cli/board-live-cards-cli.cjs.map +0 -1
  183. package/dist/cli/board-live-cards-cli.d.cts +0 -179
  184. package/dist/cli/board-live-cards-cli.d.ts +0 -179
  185. package/dist/cli/board-live-cards-cli.js +0 -10592
  186. package/dist/cli/board-live-cards-cli.js.map +0 -1
  187. package/dist/journal-9HEgs7dU.d.ts +0 -28
  188. package/dist/journal-B-JCfQnh.d.cts +0 -28
  189. package/dist/schedule-Cszq9LYY.d.ts +0 -21
  190. package/dist/schedule-qWNL0RQh.d.cts +0 -21
  191. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +0 -22
  192. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +0 -16
  193. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +0 -28
  194. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +0 -15
  195. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +0 -15
  196. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +0 -28
  197. package/examples/browser/boards/portfolio-tracker/fetch-prices.js +0 -43
  198. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +0 -96
  199. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +0 -7
  200. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +0 -351
@@ -1,351 +0,0 @@
1
- /**
2
- * portfolio-tracker.js
3
- *
4
- * Runs the full T0-T4 lifecycle of the portfolio board demo.
5
- *
6
- * This is a BLACK-BOX client of board-live-cards CLI.
7
- * It only calls CLI commands and does NOT inspect board internals.
8
- *
9
- * Usage:
10
- * node portfolio-tracker.js
11
- * node portfolio-tracker.js --task-executor <path>
12
- */
13
-
14
- import * as fs from 'node:fs';
15
- import * as os from 'node:os';
16
- import * as path from 'node:path';
17
- import { spawnSync } from 'node:child_process';
18
- import { fileURLToPath } from 'node:url';
19
-
20
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
21
-
22
- const CARDS_TEMPLATE = path.join(__dirname, 'cards');
23
- const REPO_ROOT = path.join(__dirname, '..', '..', '..', '..');
24
- const CLI_WRAPPER = path.join(REPO_ROOT, 'board-live-cards-cli.js');
25
- const CLI_TS = path.join(REPO_ROOT, 'src', 'cli', 'board-live-cards-cli.ts');
26
- const CLI_JS = path.join(REPO_ROOT, 'dist', 'cli', 'board-live-cards-cli.js');
27
- const TSX_CLI = path.join(REPO_ROOT, 'node_modules', 'tsx', 'dist', 'cli.mjs');
28
-
29
- // Keep runtime artifacts out of the repository.
30
- const RUNTIME_ROOT = fs.mkdtempSync(path.join(os.tmpdir(), 'portfolio-tracker-'));
31
- const BOARD = path.join(RUNTIME_ROOT, 'board-runtime');
32
- const CARDS = path.join(RUNTIME_ROOT, 'cards');
33
- const TMP_FILE = path.join(BOARD, 'tmp_file1');
34
- const INFERENCE_TMP_FILE_2 = path.join(BOARD, 'tmp_file2');
35
- const INFERENCE_TMP_FILE_3 = path.join(BOARD, 'tmp_file3');
36
- const INFERENCE_ADAPTER = path.join(RUNTIME_ROOT, 'portfolio-tracker-inference-adapter.js');
37
-
38
- function parseArgs(argv) {
39
- let taskExecutor;
40
- for (let i = 0; i < argv.length; i++) {
41
- const arg = argv[i];
42
- if (arg === '--task-executor') {
43
- const value = argv[i + 1];
44
- if (!value || value.startsWith('--')) {
45
- console.error('[ERROR] Missing value for --task-executor');
46
- process.exit(1);
47
- }
48
- taskExecutor = value;
49
- i += 1;
50
- continue;
51
- }
52
- console.error(`[ERROR] Unknown argument: ${arg}`);
53
- process.exit(1);
54
- }
55
- return { taskExecutor };
56
- }
57
-
58
- const options = parseArgs(process.argv.slice(2));
59
-
60
- console.log(`Runtime root: ${RUNTIME_ROOT}`);
61
-
62
- function sleep(ms) {
63
- return new Promise(resolve => setTimeout(resolve, ms));
64
- }
65
-
66
- function cliCommand() {
67
- // Prefer node+tsx CLI on Windows to avoid flashing transient cmd windows.
68
- if (fs.existsSync(CLI_TS) && fs.existsSync(TSX_CLI)) {
69
- return { cmd: process.execPath, prefixArgs: [TSX_CLI, CLI_TS] };
70
- }
71
- if (fs.existsSync(CLI_WRAPPER)) {
72
- return { cmd: process.execPath, prefixArgs: [CLI_WRAPPER] };
73
- }
74
- if (fs.existsSync(CLI_JS)) {
75
- return { cmd: process.execPath, prefixArgs: [CLI_JS] };
76
- }
77
- return { cmd: process.execPath, prefixArgs: [CLI_WRAPPER] };
78
- }
79
-
80
- function runCli(args, capture = false) {
81
- const { cmd, prefixArgs } = cliCommand();
82
- const env = { ...process.env };
83
- // This demo needs real worker dispatch; suppressing spawn keeps source/inference tasks in running state.
84
- delete env.BOARD_LIVE_CARDS_NO_SPAWN;
85
- const result = spawnSync(cmd, [...prefixArgs, ...args], {
86
- stdio: capture ? 'pipe' : 'inherit',
87
- shell: false,
88
- windowsHide: true,
89
- env,
90
- encoding: capture ? 'utf-8' : undefined,
91
- });
92
-
93
- if (result.error) {
94
- console.error(`[ERROR] Failed to run CLI ${args[0]}: ${result.error.message}`);
95
- process.exit(1);
96
- }
97
-
98
- if (result.status !== 0) {
99
- if (capture && result.stdout) process.stdout.write(result.stdout);
100
- if (capture && result.stderr) process.stderr.write(result.stderr);
101
- console.error(`\n[ERROR] board-live-cards-cli ${args[0]} exited with status ${result.status}`);
102
- process.exit(1);
103
- }
104
-
105
- return capture ? result.stdout : undefined;
106
- }
107
-
108
- function cli(...args) {
109
- runCli(args, false);
110
- }
111
-
112
- function statusText() {
113
- return runCli(['status', '--rg', BOARD], true) ?? '';
114
- }
115
-
116
- async function waitForAllCompleted(label, timeoutMs = 30000, pollMs = 500) {
117
- const start = Date.now();
118
- const includeInferenceCards = fs.existsSync(path.join(CARDS, 'portfolio-risk-assessment.json'))
119
- && fs.existsSync(path.join(CARDS, 'rebalancing-strategy.json'));
120
-
121
- while (Date.now() - start < timeoutMs) {
122
- const out = statusText();
123
- const requiredCards = [
124
- /\bcompleted\s+portfolio-form\b/.test(out),
125
- /\bcompleted\s+price-fetch\b/.test(out),
126
- /\bcompleted\s+holdings-table\b/.test(out),
127
- /\bcompleted\s+portfolio-value\b/.test(out),
128
- ];
129
- if (includeInferenceCards) {
130
- requiredCards.push(
131
- /\bcompleted\s+portfolio-risk-assessment\b/.test(out),
132
- /\bcompleted\s+rebalancing-strategy\b/.test(out),
133
- );
134
- }
135
- const completed = requiredCards.every(Boolean);
136
-
137
- if (completed) {
138
- console.log(`${label}: all cards completed.`);
139
- return;
140
- }
141
-
142
- await sleep(pollMs);
143
- }
144
-
145
- console.error(`[ERROR] ${label}: timed out waiting for all cards to complete.`);
146
- console.error(statusText());
147
- process.exit(1);
148
- }
149
-
150
- function writePrices(prices) {
151
- if (!fs.existsSync(BOARD)) {
152
- fs.mkdirSync(BOARD, { recursive: true });
153
- }
154
- fs.writeFileSync(TMP_FILE, JSON.stringify(prices), 'utf-8');
155
- console.log(`Wrote prices: ${JSON.stringify(prices)}`);
156
- }
157
-
158
- function releaseInferenceAdapters(label) {
159
- if (!fs.existsSync(BOARD)) {
160
- fs.mkdirSync(BOARD, { recursive: true });
161
- }
162
- const signal = JSON.stringify({ stage: label, releasedAt: new Date().toISOString() });
163
- fs.writeFileSync(INFERENCE_TMP_FILE_2, signal, 'utf-8');
164
- fs.writeFileSync(INFERENCE_TMP_FILE_3, signal, 'utf-8');
165
- console.log(`Released inference adapters for ${label}`);
166
- }
167
-
168
- function setupRuntimeCards() {
169
- fs.rmSync(CARDS, { recursive: true, force: true });
170
- fs.mkdirSync(RUNTIME_ROOT, { recursive: true });
171
- fs.cpSync(CARDS_TEMPLATE, CARDS, { recursive: true });
172
- fs.copyFileSync(path.join(__dirname, 'fetch-prices.js'), path.join(RUNTIME_ROOT, 'fetch-prices.js'));
173
- fs.copyFileSync(path.join(__dirname, 'portfolio-tracker-inference-adapter.js'), INFERENCE_ADAPTER);
174
- }
175
-
176
- function printTaskExecutorLog() {
177
- console.log('\n=== Task Executor Log (board-dir) ===');
178
- const candidates = fs
179
- .readdirSync(BOARD, { withFileTypes: true })
180
- .filter(entry => entry.isFile() && entry.name.endsWith('.jsonl') && entry.name.includes('executor'))
181
- .map(entry => path.join(BOARD, entry.name));
182
- const taskExecutorLog = candidates.find(p => path.basename(p) === 'task-executor.jsonl') ?? candidates[0];
183
- if (!taskExecutorLog) {
184
- console.log(`No task executor log found in board-dir: ${BOARD}`);
185
- return;
186
- }
187
-
188
- console.log(`Log file: ${taskExecutorLog}`);
189
- const content = fs.readFileSync(taskExecutorLog, 'utf-8');
190
- process.stdout.write(content || '(empty)\n');
191
- }
192
-
193
- (async () => {
194
- setupRuntimeCards();
195
-
196
- console.log('\n=== T0: Init board ===');
197
- fs.rmSync(BOARD, { recursive: true, force: true });
198
-
199
- if (options.taskExecutor) {
200
- cli('init', BOARD, '--task-executor', options.taskExecutor, '--inference-adapter', INFERENCE_ADAPTER);
201
- } else {
202
- cli('init', BOARD, '--inference-adapter', INFERENCE_ADAPTER);
203
- }
204
- cli('upsert-card', '--rg', BOARD, '--card-glob', path.join(CARDS, '*.json'));
205
-
206
- console.log('\n--- T0 Status (after upsert-card) ---');
207
- process.stdout.write(statusText());
208
-
209
- console.log('\n=== T1: Writing market prices ===');
210
- writePrices({ AAPL: 198.50, MSFT: 425.30, GOOG: 178.90, AMZN: 192.40, TSLA: 168.75 });
211
- releaseInferenceAdapters('T1');
212
- await waitForAllCompleted('T1');
213
-
214
- console.log('\n--- T1 Status ---');
215
- process.stdout.write(statusText());
216
-
217
- console.log('\n=== T2: Adding GOOG (100 shares) ===');
218
- const portfolioFormPath = path.join(CARDS, 'portfolio-form.json');
219
- const portfolioFormV2 = {
220
- id: 'portfolio-form',
221
- meta: { title: 'Portfolio Holdings Form' },
222
- provides: [{ bindTo: 'holdings', ref: 'card_data.holdings' }],
223
- card_data: {
224
- holdings: [
225
- { symbol: 'AAPL', qty: 50 },
226
- { symbol: 'MSFT', qty: 30 },
227
- { symbol: 'GOOG', qty: 100 },
228
- ],
229
- },
230
- view: {
231
- elements: [
232
- { kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
233
- ],
234
- },
235
- };
236
- fs.writeFileSync(portfolioFormPath, JSON.stringify(portfolioFormV2, null, 2));
237
-
238
- cli('upsert-card', '--rg', BOARD, '--card', portfolioFormPath, '--restart');
239
- await sleep(500);
240
- writePrices({ AAPL: 198.50, MSFT: 425.30, GOOG: 178.90, AMZN: 192.40, TSLA: 168.75 });
241
- releaseInferenceAdapters('T2');
242
- await waitForAllCompleted('T2');
243
-
244
- console.log('\n--- T2 Status ---');
245
- process.stdout.write(statusText());
246
-
247
- console.log('\n=== T3: Force price refresh — AAPL now 205.00 ===');
248
- cli('retrigger', '--rg', BOARD, '--task', 'price-fetch');
249
- await sleep(500);
250
- writePrices({ AAPL: 205.00, MSFT: 425.30, GOOG: 178.90, AMZN: 192.40, TSLA: 168.75 });
251
- releaseInferenceAdapters('T3');
252
- await waitForAllCompleted('T3');
253
-
254
- console.log('\n--- T3 Status ---');
255
- process.stdout.write(statusText());
256
-
257
- console.log('\n=== T4: Rapid successive portfolio updates (3x queue stress) ===');
258
- fs.writeFileSync(TMP_FILE, '', 'utf-8');
259
-
260
- const portfolioFormV3 = {
261
- id: 'portfolio-form',
262
- meta: { title: 'Portfolio Holdings Form' },
263
- provides: [{ bindTo: 'holdings', ref: 'card_data.holdings' }],
264
- card_data: {
265
- holdings: [
266
- { symbol: 'AAPL', qty: 50 },
267
- { symbol: 'MSFT', qty: 30 },
268
- { symbol: 'GOOG', qty: 100 },
269
- { symbol: 'AMZN', qty: 40 },
270
- ],
271
- },
272
- view: {
273
- elements: [
274
- { kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
275
- ],
276
- },
277
- };
278
-
279
- const portfolioFormV4 = {
280
- id: 'portfolio-form',
281
- meta: { title: 'Portfolio Holdings Form' },
282
- provides: [{ bindTo: 'holdings', ref: 'card_data.holdings' }],
283
- card_data: {
284
- holdings: [
285
- { symbol: 'AAPL', qty: 45 },
286
- { symbol: 'MSFT', qty: 30 },
287
- { symbol: 'GOOG', qty: 110 },
288
- { symbol: 'TSLA', qty: 60 },
289
- ],
290
- },
291
- view: {
292
- elements: [
293
- { kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
294
- ],
295
- },
296
- };
297
-
298
- const portfolioFormV5 = {
299
- id: 'portfolio-form',
300
- meta: { title: 'Portfolio Holdings Form' },
301
- provides: [{ bindTo: 'holdings', ref: 'card_data.holdings' }],
302
- card_data: {
303
- holdings: [
304
- { symbol: 'AAPL', qty: 40 },
305
- { symbol: 'MSFT', qty: 35 },
306
- { symbol: 'GOOG', qty: 120 },
307
- { symbol: 'TSLA', qty: 70 },
308
- ],
309
- },
310
- view: {
311
- elements: [
312
- { kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
313
- ],
314
- },
315
- };
316
-
317
- // First update starts a source fetch request.
318
- fs.writeFileSync(portfolioFormPath, JSON.stringify(portfolioFormV3, null, 2));
319
- cli('upsert-card', '--rg', BOARD, '--card', portfolioFormPath, '--restart');
320
-
321
- // Immediate second update should queue a newer checksum while the first request is in-flight.
322
- fs.writeFileSync(portfolioFormPath, JSON.stringify(portfolioFormV4, null, 2));
323
- cli('upsert-card', '--rg', BOARD, '--card', portfolioFormPath, '--restart');
324
-
325
- // Immediate third update should overwrite queued checksum (latest-state wins).
326
- fs.writeFileSync(portfolioFormPath, JSON.stringify(portfolioFormV5, null, 2));
327
- cli('upsert-card', '--rg', BOARD, '--card', portfolioFormPath, '--restart');
328
-
329
- // 7) wait for first request, then 8) write response prices for update #1 tickers.
330
- // await readFetchRequest('T4 first fetch', ['AAPL', 'MSFT', 'GOOG', 'AMZN']);
331
- writePrices({ AAPL: 205.00, MSFT: 425.30, GOOG: 178.90, AMZN: 192.40 });
332
- releaseInferenceAdapters('T4-first');
333
- await sleep(5000);
334
-
335
- // 9) wait for second request, then 10) write response prices for update #5 tickers.
336
- // await readFetchRequest('T4 second fetch', ['AAPL', 'MSFT', 'GOOG', 'TSLA']);
337
- writePrices({ AAPL: 206.00, MSFT: 426.00, GOOG: 179.50, TSLA: 169.20 });
338
- releaseInferenceAdapters('T4-second');
339
-
340
- await waitForAllCompleted('T4');
341
-
342
- console.log('\n--- T4 Status ---');
343
- process.stdout.write(statusText());
344
-
345
- console.log('\n=== T5: Final board status ===');
346
- process.stdout.write(statusText());
347
-
348
- printTaskExecutorLog();
349
-
350
- console.log('\nPortfolio tracker completed successfully');
351
- })();