yaml-flow 5.4.2 → 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 (199) hide show
  1. package/board-live-cards-cli.js +2 -2
  2. package/board-livecards-server-runtime.js +486 -547
  3. package/browser/asset-integrity.json +10 -0
  4. package/browser/board-livegraph-engine.js +2 -1676
  5. package/browser/board-livegraph-engine.js.map +1 -1
  6. package/browser/live-cards.js +347 -26
  7. package/browser/live-cards.schema.json +418 -132
  8. package/card-store.js +37 -0
  9. package/dist/batch/index.cjs +1 -108
  10. package/dist/batch/index.cjs.map +1 -1
  11. package/dist/batch/index.js +1 -106
  12. package/dist/batch/index.js.map +1 -1
  13. package/dist/board-live-cards-lib-Bg6EvCo5.d.cts +136 -0
  14. package/dist/board-live-cards-lib-jM2uYG1v.d.ts +136 -0
  15. package/dist/board-live-cards-public-CltXYgaY.d.cts +314 -0
  16. package/dist/board-live-cards-public-f-E-FAyp.d.ts +314 -0
  17. package/dist/board-livegraph-runtime/index.cjs +2 -1671
  18. package/dist/board-livegraph-runtime/index.cjs.map +1 -1
  19. package/dist/board-livegraph-runtime/index.d.cts +1 -2
  20. package/dist/board-livegraph-runtime/index.d.ts +1 -2
  21. package/dist/board-livegraph-runtime/index.js +2 -1662
  22. package/dist/board-livegraph-runtime/index.js.map +1 -1
  23. package/dist/board-livegraph-runtime/jsonata-sync.cjs +7587 -0
  24. package/dist/card-compute/index.cjs +9 -7159
  25. package/dist/card-compute/index.cjs.map +1 -1
  26. package/dist/card-compute/index.d.cts +22 -0
  27. package/dist/card-compute/index.d.ts +22 -0
  28. package/dist/card-compute/index.js +9 -7145
  29. package/dist/card-compute/index.js.map +1 -1
  30. package/dist/card-compute/jsonata-sync.cjs +7587 -0
  31. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs +2 -0
  32. package/dist/cli/browser-api/board-live-cards-browser-adapter.cjs.map +1 -0
  33. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.cts +24 -0
  34. package/dist/cli/browser-api/board-live-cards-browser-adapter.d.ts +24 -0
  35. package/dist/cli/browser-api/board-live-cards-browser-adapter.js +2 -0
  36. package/dist/cli/browser-api/board-live-cards-browser-adapter.js.map +1 -0
  37. package/dist/cli/browser-api/card-store-browser-api.cjs +2 -0
  38. package/dist/cli/browser-api/card-store-browser-api.cjs.map +1 -0
  39. package/dist/cli/browser-api/card-store-browser-api.d.cts +26 -0
  40. package/dist/cli/browser-api/card-store-browser-api.d.ts +26 -0
  41. package/dist/cli/browser-api/card-store-browser-api.js +2 -0
  42. package/dist/cli/browser-api/card-store-browser-api.js.map +1 -0
  43. package/dist/cli/browser-api/jsonata-sync.cjs +7587 -0
  44. package/dist/cli/node/artifacts-store-cli.cjs +11 -0
  45. package/dist/cli/node/artifacts-store-cli.cjs.map +1 -0
  46. package/dist/cli/node/artifacts-store-cli.d.cts +8 -0
  47. package/dist/cli/node/artifacts-store-cli.d.ts +8 -0
  48. package/dist/cli/node/artifacts-store-cli.js +11 -0
  49. package/dist/cli/node/artifacts-store-cli.js.map +1 -0
  50. package/dist/cli/node/board-live-cards-cli.cjs +15 -0
  51. package/dist/cli/node/board-live-cards-cli.cjs.map +1 -0
  52. package/dist/cli/node/board-live-cards-cli.d.cts +20 -0
  53. package/dist/cli/node/board-live-cards-cli.d.ts +20 -0
  54. package/dist/cli/node/board-live-cards-cli.js +15 -0
  55. package/dist/cli/node/board-live-cards-cli.js.map +1 -0
  56. package/dist/cli/node/card-store-cli.cjs +8 -0
  57. package/dist/cli/node/card-store-cli.cjs.map +1 -0
  58. package/dist/cli/node/card-store-cli.d.cts +15 -0
  59. package/dist/cli/node/card-store-cli.d.ts +15 -0
  60. package/dist/cli/node/card-store-cli.js +8 -0
  61. package/dist/cli/node/card-store-cli.js.map +1 -0
  62. package/dist/cli/node/fs-board-adapter.cjs +14 -0
  63. package/dist/cli/node/fs-board-adapter.cjs.map +1 -0
  64. package/dist/cli/node/fs-board-adapter.d.cts +204 -0
  65. package/dist/cli/node/fs-board-adapter.d.ts +204 -0
  66. package/dist/cli/node/fs-board-adapter.js +14 -0
  67. package/dist/cli/node/fs-board-adapter.js.map +1 -0
  68. package/dist/cli/node/jsonata-sync.cjs +7587 -0
  69. package/dist/cli/node/source-cli-task-executor.cjs +11 -0
  70. package/dist/cli/node/source-cli-task-executor.cjs.map +1 -0
  71. package/dist/cli/node/source-cli-task-executor.d.cts +1 -0
  72. package/dist/cli/node/source-cli-task-executor.d.ts +1 -0
  73. package/dist/cli/node/source-cli-task-executor.js +11 -0
  74. package/dist/cli/node/source-cli-task-executor.js.map +1 -0
  75. package/dist/config/index.cjs +1 -79
  76. package/dist/config/index.cjs.map +1 -1
  77. package/dist/config/index.js +1 -76
  78. package/dist/config/index.js.map +1 -1
  79. package/dist/continuous-event-graph/index.cjs +2 -2129
  80. package/dist/continuous-event-graph/index.cjs.map +1 -1
  81. package/dist/continuous-event-graph/index.d.cts +81 -5
  82. package/dist/continuous-event-graph/index.d.ts +81 -5
  83. package/dist/continuous-event-graph/index.js +2 -2088
  84. package/dist/continuous-event-graph/index.js.map +1 -1
  85. package/dist/continuous-event-graph/jsonata-sync.cjs +7587 -0
  86. package/dist/event-graph/index.cjs +22 -8292
  87. package/dist/event-graph/index.cjs.map +1 -1
  88. package/dist/event-graph/index.js +22 -8237
  89. package/dist/event-graph/index.js.map +1 -1
  90. package/dist/execution-refs.cjs +2 -0
  91. package/dist/execution-refs.cjs.map +1 -0
  92. package/dist/execution-refs.d.cts +222 -0
  93. package/dist/execution-refs.d.ts +222 -0
  94. package/dist/execution-refs.js +2 -0
  95. package/dist/execution-refs.js.map +1 -0
  96. package/dist/index.cjs +29 -13221
  97. package/dist/index.cjs.map +1 -1
  98. package/dist/index.d.cts +2 -4
  99. package/dist/index.d.ts +2 -4
  100. package/dist/index.js +29 -13112
  101. package/dist/index.js.map +1 -1
  102. package/dist/inference/index.cjs +5 -617
  103. package/dist/inference/index.cjs.map +1 -1
  104. package/dist/inference/index.js +5 -610
  105. package/dist/inference/index.js.map +1 -1
  106. package/dist/jsonata-sync.cjs +7587 -0
  107. package/dist/{live-cards-bridge-x5XREkXm.d.cts → live-cards-bridge-BXbVTsna.d.cts} +27 -4
  108. package/dist/{live-cards-bridge-EQjytzI_.d.ts → live-cards-bridge-Ds28XR15.d.ts} +27 -4
  109. package/dist/pycli/quickjs-board-runtime.global.js +9 -0
  110. package/dist/pycli/quickjs-board-runtime.global.js.map +1 -0
  111. package/dist/pycli/quickjs-step-machine-runtime.global.js +5 -0
  112. package/dist/pycli/quickjs-step-machine-runtime.global.js.map +1 -0
  113. package/dist/step-machine/index.cjs +11 -7129
  114. package/dist/step-machine/index.cjs.map +1 -1
  115. package/dist/step-machine/index.js +11 -7113
  116. package/dist/step-machine/index.js.map +1 -1
  117. package/dist/storage-refs.cjs +10 -0
  118. package/dist/storage-refs.cjs.map +1 -0
  119. package/dist/storage-refs.d.cts +92 -0
  120. package/dist/storage-refs.d.ts +92 -0
  121. package/dist/storage-refs.js +10 -0
  122. package/dist/storage-refs.js.map +1 -0
  123. package/dist/stores/file.cjs +1 -114
  124. package/dist/stores/file.cjs.map +1 -1
  125. package/dist/stores/file.js +1 -112
  126. package/dist/stores/file.js.map +1 -1
  127. package/dist/stores/index.cjs +1 -231
  128. package/dist/stores/index.cjs.map +1 -1
  129. package/dist/stores/index.js +1 -227
  130. package/dist/stores/index.js.map +1 -1
  131. package/dist/stores/localStorage.cjs +1 -76
  132. package/dist/stores/localStorage.cjs.map +1 -1
  133. package/dist/stores/localStorage.js +1 -74
  134. package/dist/stores/localStorage.js.map +1 -1
  135. package/dist/stores/memory.cjs +1 -47
  136. package/dist/stores/memory.cjs.map +1 -1
  137. package/dist/stores/memory.js +1 -45
  138. package/dist/stores/memory.js.map +1 -1
  139. package/examples/browser/boards/portfolio-tracker/portfolio-t4.js +292 -0
  140. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.js +218 -0
  141. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-fetch-prices.py +201 -0
  142. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-inference-adapter.js +25 -16
  143. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-public.js +553 -0
  144. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.py +365 -0
  145. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/.runtime-out +1 -0
  146. package/examples/cli/step-machine-cli/portfolio-tracker/--base-ref/board-graph.json +32 -0
  147. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +53 -1
  148. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +15 -6
  149. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +6 -1
  150. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/poll-status-cli.js +57 -0
  151. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +1 -1
  152. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +1 -1
  153. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +7 -2
  154. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +6 -2
  155. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/_board_pycli.py +97 -0
  156. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/add-cards.py +50 -0
  157. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/init-board.py +44 -0
  158. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/poll-status.py +70 -0
  159. package/examples/cli/step-machine-cli/portfolio-tracker/handlers-py/reset-board-dir.py +36 -0
  160. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-demo.flow.yaml +26 -0
  161. package/examples/cli/step-machine-cli/portfolio-tracker/inline-python-handlers.py +39 -0
  162. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker-pycli.flow.yaml +80 -0
  163. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +25 -172
  164. package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +40 -34
  165. package/examples/cli/step-machine-cli/portfolio-tracker/run-inline-python-demo-pycli.py +46 -0
  166. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker-pycli.py +77 -0
  167. package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  168. package/examples/example-board/agent-instructions.md +11 -5
  169. package/examples/example-board/demo-chat-handler.js +14 -4
  170. package/examples/example-board/demo-server-config.json +1 -0
  171. package/examples/example-board/demo-server.js +14 -7
  172. package/examples/example-board/demo-shell-browser.html +5 -4
  173. package/examples/example-board/demo-shell-with-server.html +6 -5
  174. package/examples/example-board/demo-task-executor.js +81 -35
  175. package/examples/index.html +0 -14
  176. package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +0 -1
  177. package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +1 -2
  178. package/package.json +39 -3
  179. package/schema/live-cards.schema.json +418 -132
  180. package/dist/cli/board-live-cards-cli.cjs +0 -10650
  181. package/dist/cli/board-live-cards-cli.cjs.map +0 -1
  182. package/dist/cli/board-live-cards-cli.d.cts +0 -179
  183. package/dist/cli/board-live-cards-cli.d.ts +0 -179
  184. package/dist/cli/board-live-cards-cli.js +0 -10598
  185. package/dist/cli/board-live-cards-cli.js.map +0 -1
  186. package/dist/journal-9HEgs7dU.d.ts +0 -28
  187. package/dist/journal-B-JCfQnh.d.cts +0 -28
  188. package/dist/schedule-Cszq9LYY.d.ts +0 -21
  189. package/dist/schedule-qWNL0RQh.d.cts +0 -21
  190. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +0 -22
  191. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +0 -16
  192. package/examples/browser/boards/portfolio-tracker/cards/portfolio-risk-assessment.json +0 -28
  193. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +0 -15
  194. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +0 -15
  195. package/examples/browser/boards/portfolio-tracker/cards/rebalancing-strategy.json +0 -28
  196. package/examples/browser/boards/portfolio-tracker/fetch-prices.js +0 -43
  197. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +0 -96
  198. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +0 -7
  199. 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 = 90000, 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
- })();