yaml-flow 4.0.0 → 5.1.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 (96) hide show
  1. package/browser/board-livegraph-runtime.js +1453 -0
  2. package/browser/board-livegraph-runtime.js.map +1 -0
  3. package/browser/card-compute.js +36 -17
  4. package/browser/live-cards.js +848 -109
  5. package/browser/live-cards.schema.json +46 -21
  6. package/dist/board-livegraph-runtime/index.cjs +1448 -0
  7. package/dist/board-livegraph-runtime/index.cjs.map +1 -0
  8. package/dist/board-livegraph-runtime/index.d.cts +101 -0
  9. package/dist/board-livegraph-runtime/index.d.ts +101 -0
  10. package/dist/board-livegraph-runtime/index.js +1441 -0
  11. package/dist/board-livegraph-runtime/index.js.map +1 -0
  12. package/dist/card-compute/index.cjs +159 -44
  13. package/dist/card-compute/index.cjs.map +1 -1
  14. package/dist/card-compute/index.d.cts +36 -11
  15. package/dist/card-compute/index.d.ts +36 -11
  16. package/dist/card-compute/index.js +156 -44
  17. package/dist/card-compute/index.js.map +1 -1
  18. package/dist/cli/board-live-cards-cli.cjs +476 -105
  19. package/dist/cli/board-live-cards-cli.cjs.map +1 -1
  20. package/dist/cli/board-live-cards-cli.d.cts +8 -16
  21. package/dist/cli/board-live-cards-cli.d.ts +8 -16
  22. package/dist/cli/board-live-cards-cli.js +476 -106
  23. package/dist/cli/board-live-cards-cli.js.map +1 -1
  24. package/dist/continuous-event-graph/index.cjs +74 -33
  25. package/dist/continuous-event-graph/index.cjs.map +1 -1
  26. package/dist/continuous-event-graph/index.d.cts +7 -23
  27. package/dist/continuous-event-graph/index.d.ts +7 -23
  28. package/dist/continuous-event-graph/index.js +73 -32
  29. package/dist/continuous-event-graph/index.js.map +1 -1
  30. package/dist/index.cjs +1440 -56
  31. package/dist/index.cjs.map +1 -1
  32. package/dist/index.d.cts +21 -3
  33. package/dist/index.d.ts +21 -3
  34. package/dist/index.js +1434 -56
  35. package/dist/index.js.map +1 -1
  36. package/dist/journal-DRfJiheM.d.cts +28 -0
  37. package/dist/journal-NLYuqege.d.ts +28 -0
  38. package/dist/{journal-B_2JnBMF.d.ts → live-cards-bridge-Or7fdEJV.d.ts} +5 -32
  39. package/dist/{journal-BJDjWb5Q.d.cts → live-cards-bridge-vGJ6tMzN.d.cts} +5 -32
  40. package/dist/schedule-CMcZe5Ny.d.ts +21 -0
  41. package/dist/schedule-CiucyCan.d.cts +21 -0
  42. package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +1 -1
  43. package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +3 -3
  44. package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +1 -1
  45. package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +3 -3
  46. package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  47. package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +33 -5
  48. package/examples/browser/livecards-browser/index.html +37 -684
  49. package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  50. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
  51. package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  52. package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +3 -3
  53. package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +2 -2
  54. package/examples/example-board/board.yaml +23 -0
  55. package/examples/example-board/bootstrap_payload.json +1 -0
  56. package/examples/example-board/cards/card-chain-region-alert.json +39 -0
  57. package/examples/example-board/cards/card-chain-region-totals.json +26 -0
  58. package/examples/example-board/cards/card-chain-top-region.json +24 -0
  59. package/examples/example-board/cards/card-ex-actions.json +32 -0
  60. package/examples/example-board/cards/card-ex-chart.json +30 -0
  61. package/examples/example-board/cards/card-ex-filter.json +36 -0
  62. package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
  63. package/examples/example-board/cards/card-ex-form.json +91 -0
  64. package/examples/example-board/cards/card-ex-list.json +22 -0
  65. package/examples/example-board/cards/card-ex-markdown.json +17 -0
  66. package/examples/example-board/cards/card-ex-metric.json +19 -0
  67. package/examples/example-board/cards/card-ex-narrative.json +36 -0
  68. package/examples/example-board/cards/card-ex-source-http.json +28 -0
  69. package/examples/example-board/cards/card-ex-source.json +21 -0
  70. package/examples/example-board/cards/card-ex-status.json +35 -0
  71. package/examples/example-board/cards/card-ex-table.json +30 -0
  72. package/examples/example-board/cards/card-ex-todo.json +29 -0
  73. package/examples/example-board/demo-chat-handler.js +69 -0
  74. package/examples/example-board/demo-server-config.json +7 -0
  75. package/examples/example-board/demo-server.js +124 -0
  76. package/examples/example-board/demo-shell-browser.html +806 -0
  77. package/examples/example-board/demo-shell-with-server.html +280 -0
  78. package/examples/example-board/demo-shell.html +62 -0
  79. package/examples/example-board/demo-task-executor.js +255 -0
  80. package/examples/example-board/mock.db +15 -0
  81. package/examples/example-board/reusable-board-runtime-client.js +265 -0
  82. package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
  83. package/examples/example-board/reusable-server-runtime.js +1341 -0
  84. package/examples/index.html +16 -9
  85. package/examples/npm-libs/continuous-event-graph/live-cards-board.ts +17 -17
  86. package/examples/npm-libs/continuous-event-graph/live-portfolio-dashboard.ts +23 -23
  87. package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +1 -1
  88. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +3 -3
  89. package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +1 -1
  90. package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +1 -1
  91. package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
  92. package/package.json +16 -2
  93. package/schema/card-runtime.schema.json +25 -0
  94. package/schema/live-cards.schema.json +46 -21
  95. package/browser/ingest-board.js +0 -296
  96. package/examples/ingest.js +0 -733
@@ -0,0 +1,28 @@
1
+ import { f as GraphEvent } from './types-CMFSIjpc.cjs';
2
+
3
+ /**
4
+ * Continuous Event Graph — Journal
5
+ *
6
+ * Append-only event log for the reactive layer.
7
+ * Handlers append events here; drain() reads and clears atomically.
8
+ *
9
+ * Adapter:
10
+ * - MemoryJournal: in-process array (default)
11
+ */
12
+
13
+ interface Journal {
14
+ /** Append an event to the journal. Safe to call from concurrent callbacks. */
15
+ append(event: GraphEvent): void;
16
+ /** Read all pending events and clear the journal atomically. */
17
+ drain(): GraphEvent[];
18
+ /** Number of pending events (for observability). */
19
+ readonly size: number;
20
+ }
21
+ declare class MemoryJournal implements Journal {
22
+ private buffer;
23
+ append(event: GraphEvent): void;
24
+ drain(): GraphEvent[];
25
+ get size(): number;
26
+ }
27
+
28
+ export { type Journal as J, MemoryJournal as M };
@@ -0,0 +1,28 @@
1
+ import { f as GraphEvent } from './types-CMFSIjpc.js';
2
+
3
+ /**
4
+ * Continuous Event Graph — Journal
5
+ *
6
+ * Append-only event log for the reactive layer.
7
+ * Handlers append events here; drain() reads and clears atomically.
8
+ *
9
+ * Adapter:
10
+ * - MemoryJournal: in-process array (default)
11
+ */
12
+
13
+ interface Journal {
14
+ /** Append an event to the journal. Safe to call from concurrent callbacks. */
15
+ append(event: GraphEvent): void;
16
+ /** Read all pending events and clear the journal atomically. */
17
+ drain(): GraphEvent[];
18
+ /** Number of pending events (for observability). */
19
+ readonly size: number;
20
+ }
21
+ declare class MemoryJournal implements Journal {
22
+ private buffer;
23
+ append(event: GraphEvent): void;
24
+ drain(): GraphEvent[];
25
+ get size(): number;
26
+ }
27
+
28
+ export { type Journal as J, MemoryJournal as M };
@@ -1,5 +1,5 @@
1
- import { e as GraphEngineStore, T as TaskConfig, f as GraphEvent, G as GraphConfig } from './types-CMFSIjpc.js';
2
- import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './types-C2eJ7DAV.js';
1
+ import { f as GraphEvent, T as TaskConfig, e as GraphEngineStore, G as GraphConfig } from './types-CMFSIjpc.js';
2
+ import { b as LiveGraphSnapshot, L as LiveGraph, S as ScheduleResult } from './types-C2eJ7DAV.js';
3
3
 
4
4
  /**
5
5
  * Continuous Event Graph — Reactive Layer
@@ -20,7 +20,7 @@ import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './t
20
20
 
21
21
  /**
22
22
  * Deterministic hash of a data payload.
23
- * Recursively-sorted JSON → SHA-256 hex (first 16 chars for compactness).
23
+ * Recursively-sorted JSON → stable 64-bit hex.
24
24
  * Used to auto-compute dataHash when the handler doesn't provide one.
25
25
  * Exported so handler authors can pre-compute or test hashes.
26
26
  */
@@ -211,7 +211,7 @@ interface LiveCard {
211
211
  title?: string;
212
212
  tags?: string[];
213
213
  };
214
- state?: Record<string, unknown>;
214
+ card_data?: Record<string, unknown>;
215
215
  compute?: {
216
216
  bindTo: string;
217
217
  fn: string;
@@ -219,14 +219,12 @@ interface LiveCard {
219
219
  }[];
220
220
  sources?: {
221
221
  cli?: string;
222
- script?: string;
223
222
  bindTo: string;
224
223
  kind?: 'api' | 'websocket' | 'static' | 'llm';
225
224
  [key: string]: unknown;
226
225
  }[];
227
226
  optionalSources?: {
228
227
  cli?: string;
229
- script?: string;
230
228
  bindTo: string;
231
229
  kind?: 'api' | 'websocket' | 'static' | 'llm';
232
230
  [key: string]: unknown;
@@ -315,29 +313,4 @@ interface LiveCardsToReactiveResult {
315
313
  */
316
314
  declare function liveCardsToReactiveGraph(input: LiveCard[] | LiveBoard, options?: LiveCardsToReactiveOptions): LiveCardsToReactiveResult;
317
315
 
318
- /**
319
- * Continuous Event Graph — Journal
320
- *
321
- * Append-only event log for the reactive layer.
322
- * Handlers append events here; drain() reads and clears atomically.
323
- *
324
- * Adapter:
325
- * - MemoryJournal: in-process array (default)
326
- */
327
-
328
- interface Journal {
329
- /** Append an event to the journal. Safe to call from concurrent callbacks. */
330
- append(event: GraphEvent): void;
331
- /** Read all pending events and clear the journal atomically. */
332
- drain(): GraphEvent[];
333
- /** Number of pending events (for observability). */
334
- readonly size: number;
335
- }
336
- declare class MemoryJournal implements Journal {
337
- private buffer;
338
- append(event: GraphEvent): void;
339
- drain(): GraphEvent[];
340
- get size(): number;
341
- }
342
-
343
- export { type Journal as J, type LiveBoard as L, MemoryJournal as M, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
316
+ export { type LiveBoard as L, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
@@ -1,5 +1,5 @@
1
- import { e as GraphEngineStore, T as TaskConfig, f as GraphEvent, G as GraphConfig } from './types-CMFSIjpc.cjs';
2
- import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './types-BzLD8bjb.cjs';
1
+ import { f as GraphEvent, T as TaskConfig, e as GraphEngineStore, G as GraphConfig } from './types-CMFSIjpc.cjs';
2
+ import { b as LiveGraphSnapshot, L as LiveGraph, S as ScheduleResult } from './types-BzLD8bjb.cjs';
3
3
 
4
4
  /**
5
5
  * Continuous Event Graph — Reactive Layer
@@ -20,7 +20,7 @@ import { L as LiveGraph, S as ScheduleResult, b as LiveGraphSnapshot } from './t
20
20
 
21
21
  /**
22
22
  * Deterministic hash of a data payload.
23
- * Recursively-sorted JSON → SHA-256 hex (first 16 chars for compactness).
23
+ * Recursively-sorted JSON → stable 64-bit hex.
24
24
  * Used to auto-compute dataHash when the handler doesn't provide one.
25
25
  * Exported so handler authors can pre-compute or test hashes.
26
26
  */
@@ -211,7 +211,7 @@ interface LiveCard {
211
211
  title?: string;
212
212
  tags?: string[];
213
213
  };
214
- state?: Record<string, unknown>;
214
+ card_data?: Record<string, unknown>;
215
215
  compute?: {
216
216
  bindTo: string;
217
217
  fn: string;
@@ -219,14 +219,12 @@ interface LiveCard {
219
219
  }[];
220
220
  sources?: {
221
221
  cli?: string;
222
- script?: string;
223
222
  bindTo: string;
224
223
  kind?: 'api' | 'websocket' | 'static' | 'llm';
225
224
  [key: string]: unknown;
226
225
  }[];
227
226
  optionalSources?: {
228
227
  cli?: string;
229
- script?: string;
230
228
  bindTo: string;
231
229
  kind?: 'api' | 'websocket' | 'static' | 'llm';
232
230
  [key: string]: unknown;
@@ -315,29 +313,4 @@ interface LiveCardsToReactiveResult {
315
313
  */
316
314
  declare function liveCardsToReactiveGraph(input: LiveCard[] | LiveBoard, options?: LiveCardsToReactiveOptions): LiveCardsToReactiveResult;
317
315
 
318
- /**
319
- * Continuous Event Graph — Journal
320
- *
321
- * Append-only event log for the reactive layer.
322
- * Handlers append events here; drain() reads and clears atomically.
323
- *
324
- * Adapter:
325
- * - MemoryJournal: in-process array (default)
326
- */
327
-
328
- interface Journal {
329
- /** Append an event to the journal. Safe to call from concurrent callbacks. */
330
- append(event: GraphEvent): void;
331
- /** Read all pending events and clear the journal atomically. */
332
- drain(): GraphEvent[];
333
- /** Number of pending events (for observability). */
334
- readonly size: number;
335
- }
336
- declare class MemoryJournal implements Journal {
337
- private buffer;
338
- append(event: GraphEvent): void;
339
- drain(): GraphEvent[];
340
- get size(): number;
341
- }
342
-
343
- export { type Journal as J, type LiveBoard as L, MemoryJournal as M, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
316
+ export { type LiveBoard as L, type ReactiveGraph as R, type TaskHandlerFn as T, type LiveCard as a, type LiveCardsToReactiveOptions as b, type LiveCardsToReactiveResult as c, type ReactiveGraphOptions as d, type TaskHandlerInput as e, type TaskHandlerReturn as f, createReactiveGraph as g, computeDataHash as h, liveCardsToReactiveGraph as l };
@@ -0,0 +1,21 @@
1
+ import { L as LiveGraph, S as ScheduleResult } from './types-C2eJ7DAV.js';
2
+
3
+ /**
4
+ * Continuous Event Graph — Schedule
5
+ *
6
+ * Pure read-only projection: LiveGraph → ScheduleResult
7
+ *
8
+ * Classifies every non-terminal task into one of:
9
+ * - eligible: all requires satisfied, ready to dispatch
10
+ * - pending: requires not yet met, but a viable producer exists (normal waiting)
11
+ * - unresolved: requires not met, NO task in the graph can produce them (caller's problem)
12
+ * - blocked: requires not met because the producing task FAILED (caller's problem)
13
+ */
14
+
15
+ /**
16
+ * Compute the scheduling status of every task in the live graph.
17
+ * Pure function — no side effects.
18
+ */
19
+ declare function schedule(live: LiveGraph): ScheduleResult;
20
+
21
+ export { schedule as s };
@@ -0,0 +1,21 @@
1
+ import { L as LiveGraph, S as ScheduleResult } from './types-BzLD8bjb.cjs';
2
+
3
+ /**
4
+ * Continuous Event Graph — Schedule
5
+ *
6
+ * Pure read-only projection: LiveGraph → ScheduleResult
7
+ *
8
+ * Classifies every non-terminal task into one of:
9
+ * - eligible: all requires satisfied, ready to dispatch
10
+ * - pending: requires not yet met, but a viable producer exists (normal waiting)
11
+ * - unresolved: requires not met, NO task in the graph can produce them (caller's problem)
12
+ * - blocked: requires not met because the producing task FAILED (caller's problem)
13
+ */
14
+
15
+ /**
16
+ * Compute the scheduling status of every task in the live graph.
17
+ * Pure function — no side effects.
18
+ */
19
+ declare function schedule(live: LiveGraph): ScheduleResult;
20
+
21
+ export { schedule as s };
@@ -3,7 +3,7 @@
3
3
  "meta": { "title": "Holdings Table" },
4
4
  "requires": ["holdings", "prices"],
5
5
  "provides": [{ "bindTo": "table", "src": "computed_values.table" }],
6
- "state": {},
6
+ "card_data": {},
7
7
  "compute": [
8
8
  {
9
9
  "bindTo": "table",
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "id": "portfolio-form",
3
3
  "meta": { "title": "Portfolio Holdings Form" },
4
- "provides": [{ "bindTo": "holdings", "src": "state.holdings" }],
5
- "state": {
4
+ "provides": [{ "bindTo": "holdings", "src": "card_data.holdings" }],
5
+ "card_data": {
6
6
  "holdings": [
7
7
  { "symbol": "AAPL", "qty": 50 },
8
8
  { "symbol": "MSFT", "qty": 30 }
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "view": {
12
12
  "elements": [
13
- { "kind": "table", "label": "Holdings", "data": { "bind": "state.holdings", "columns": ["symbol", "qty"] } }
13
+ { "kind": "table", "label": "Holdings", "data": { "bind": "card_data.holdings", "columns": ["symbol", "qty"] } }
14
14
  ]
15
15
  }
16
16
  }
@@ -3,7 +3,7 @@
3
3
  "meta": { "title": "Portfolio Total Value" },
4
4
  "requires": ["table"],
5
5
  "provides": [{ "bindTo": "totalValue", "src": "computed_values.totalValue" }],
6
- "state": {},
6
+ "card_data": {},
7
7
  "compute": [
8
8
  { "bindTo": "totalValue", "expr": "$sum(requires.table.rows.value)" }
9
9
  ],
@@ -2,14 +2,14 @@
2
2
  "id": "price-fetch",
3
3
  "meta": { "title": "Fetch Market Prices" },
4
4
  "requires": ["holdings"],
5
- "provides": [{ "bindTo": "prices", "src": "sources.prices" }],
6
- "state": {},
5
+ "provides": [{ "bindTo": "prices", "src": "fetched_sources.prices" }],
6
+ "card_data": {},
7
7
  "sources": [
8
8
  { "cli": "node ../fetch-prices.js", "bindTo": "prices", "outputFile": "prices.json" }
9
9
  ],
10
10
  "view": {
11
11
  "elements": [
12
- { "kind": "table", "label": "Market Prices", "data": { "bind": "sources.prices" } }
12
+ { "kind": "table", "label": "Market Prices", "data": { "bind": "fetched_sources.prices" } }
13
13
  ]
14
14
  }
15
15
  }
@@ -0,0 +1,96 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Portfolio Tracker Task-Executor
4
+ *
5
+ * Implements the run-source-fetch protocol for board-live-cards.
6
+ * This script acts as an external task-executor that can be registered via .task-executor file.
7
+ *
8
+ * Contract:
9
+ * portfolio-tracker-task-executor.js run-source-fetch --in <defFile> --out <resultFile> --err <errFile>
10
+ *
11
+ * Input (--in file):
12
+ * JSON source definition with { cli: "...", bindTo: "...", outputFile: "...", ... }
13
+ *
14
+ * Output (on success):
15
+ * --out file contains the execution result
16
+ * Exit code: 0
17
+ *
18
+ * Output (on error):
19
+ * --err file contains error message
20
+ * Exit code: 1
21
+ */
22
+
23
+ const fs = require('fs');
24
+ const path = require('path');
25
+ const { execSync } = require('child_process');
26
+
27
+ // Parse command line arguments
28
+ const args = process.argv.slice(2);
29
+ let subcommand = '';
30
+ let inFile = '';
31
+ let outFile = '';
32
+ let errFile = '';
33
+
34
+ for (let i = 0; i < args.length; i++) {
35
+ if (args[i] === 'run-source-fetch') {
36
+ subcommand = 'run-source-fetch';
37
+ } else if (args[i] === '--in' && i + 1 < args.length) {
38
+ inFile = args[i + 1];
39
+ } else if (args[i] === '--out' && i + 1 < args.length) {
40
+ outFile = args[i + 1];
41
+ } else if (args[i] === '--err' && i + 1 < args.length) {
42
+ errFile = args[i + 1];
43
+ }
44
+ }
45
+
46
+ if (subcommand !== 'run-source-fetch' || !inFile || !outFile || !errFile) {
47
+ console.error('Usage: portfolio-tracker-task-executor.js run-source-fetch --in <defFile> --out <resultFile> --err <errFile>');
48
+ process.exit(1);
49
+ }
50
+
51
+ try {
52
+ // 1. Read source definition from --in file
53
+ console.log(`[portfolio-tracker-task-executor] Reading source definition from ${inFile}`);
54
+ const sourceDefStr = fs.readFileSync(inFile, 'utf-8');
55
+ const sourceDef = JSON.parse(sourceDefStr);
56
+
57
+ // 2. Extract cli command from source definition
58
+ const { cli: sourceCliCommand } = sourceDef;
59
+ if (!sourceCliCommand) {
60
+ throw new Error('cli is required in source definition');
61
+ }
62
+
63
+ console.log(`[portfolio-tracker-task-executor] Executing: ${sourceCliCommand}`);
64
+
65
+ // 3. Execute source.cli synchronously and capture output
66
+ let output;
67
+ try {
68
+ output = execSync(sourceCliCommand, {
69
+ encoding: 'utf-8',
70
+ timeout: (sourceDef.timeout ?? 120) * 1000, // Convert to ms
71
+ cwd: sourceDef.cwd,
72
+ shell: true,
73
+ stdio: ['pipe', 'pipe', 'pipe'], // Capture stdout/stderr
74
+ });
75
+ } catch (execErr) {
76
+ // Even on error, try to use what output we got
77
+ output = execErr.stdout || '';
78
+ if (!output) {
79
+ throw new Error(`Command execution failed: ${execErr.message}`);
80
+ }
81
+ }
82
+
83
+ // 4. Write output to --out file
84
+ console.log(`[portfolio-tracker-task-executor] Writing result to ${outFile}`);
85
+ fs.writeFileSync(outFile, output.trim(), 'utf-8');
86
+
87
+ console.log(`[portfolio-tracker-task-executor] Success`);
88
+ process.exit(0);
89
+ } catch (error) {
90
+ // 3a. On error: write error message to --err file and exit non-zero
91
+ const errorMsg = error instanceof Error ? error.message : String(error);
92
+ console.error(`[portfolio-tracker-task-executor] Error:`, errorMsg);
93
+
94
+ fs.writeFileSync(errFile, errorMsg, 'utf-8');
95
+ process.exit(1);
96
+ }
@@ -6,7 +6,9 @@
6
6
  * This is a BLACK-BOX client of board-live-cards CLI.
7
7
  * It only calls CLI commands and does NOT inspect board internals.
8
8
  *
9
- * Usage: node portfolio-tracker.js
9
+ * Usage:
10
+ * node portfolio-tracker.js
11
+ * node portfolio-tracker.js --task-executor <path>
10
12
  */
11
13
 
12
14
  import * as fs from 'node:fs';
@@ -30,6 +32,28 @@ const BOARD = path.join(RUNTIME_ROOT, 'board-runtime');
30
32
  const CARDS = path.join(RUNTIME_ROOT, 'cards');
31
33
  const TMP_FILE = path.join(BOARD, 'tmp_file1');
32
34
 
35
+ function parseArgs(argv) {
36
+ let taskExecutor;
37
+ for (let i = 0; i < argv.length; i++) {
38
+ const arg = argv[i];
39
+ if (arg === '--task-executor') {
40
+ const value = argv[i + 1];
41
+ if (!value || value.startsWith('--')) {
42
+ console.error('[ERROR] Missing value for --task-executor');
43
+ process.exit(1);
44
+ }
45
+ taskExecutor = value;
46
+ i += 1;
47
+ continue;
48
+ }
49
+ console.error(`[ERROR] Unknown argument: ${arg}`);
50
+ process.exit(1);
51
+ }
52
+ return { taskExecutor };
53
+ }
54
+
55
+ const options = parseArgs(process.argv.slice(2));
56
+
33
57
  console.log(`Runtime root: ${RUNTIME_ROOT}`);
34
58
 
35
59
  function sleep(ms) {
@@ -131,7 +155,11 @@ function setupRuntimeCards() {
131
155
  console.log('\n=== T0: Init board ===');
132
156
  fs.rmSync(BOARD, { recursive: true, force: true });
133
157
 
134
- cli('init', BOARD);
158
+ if (options.taskExecutor) {
159
+ cli('init', BOARD, '--task-executor', options.taskExecutor);
160
+ } else {
161
+ cli('init', BOARD);
162
+ }
135
163
  cli('add-cards', '--rg', BOARD, '--card-glob', path.join(CARDS, '*.json'));
136
164
 
137
165
  console.log('\n--- T0 Status (after add-cards) ---');
@@ -149,8 +177,8 @@ function setupRuntimeCards() {
149
177
  const portfolioFormV2 = {
150
178
  id: 'portfolio-form',
151
179
  meta: { title: 'Portfolio Holdings Form' },
152
- provides: [{ bindTo: 'holdings', src: 'state.holdings' }],
153
- state: {
180
+ provides: [{ bindTo: 'holdings', src: 'card_data.holdings' }],
181
+ card_data: {
154
182
  holdings: [
155
183
  { symbol: 'AAPL', qty: 50 },
156
184
  { symbol: 'MSFT', qty: 30 },
@@ -159,7 +187,7 @@ function setupRuntimeCards() {
159
187
  },
160
188
  view: {
161
189
  elements: [
162
- { kind: 'table', label: 'Holdings', data: { bind: 'state.holdings', columns: ['symbol', 'qty'] } },
190
+ { kind: 'table', label: 'Holdings', data: { bind: 'card_data.holdings', columns: ['symbol', 'qty'] } },
163
191
  ],
164
192
  },
165
193
  };