automategraph 1.5.0 → 1.5.3
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.
- package/CHANGELOG.md +20 -0
- package/UPGRADE-PROPOSAL.md +141 -0
- package/docs/diagrams/c19-resilience-scenario.md +61 -0
- package/docs/diagrams/c19-resilience-scenario.mmd +28 -0
- package/docs/diagrams/c19-resilience-scenario.svg +181 -0
- package/examples/README.md +206 -0
- package/examples/branching-edges.ts +192 -0
- package/examples/branching-graph.ts +333 -0
- package/examples/branching-router.ts +475 -0
- package/examples/json-graph.ts +231 -0
- package/examples/json-scripts.ts +152 -0
- package/examples/order-flow.functions.cjs +32 -0
- package/examples/order-flow.graph.json +27 -0
- package/examples/order-flow.scripted.graph.json +68 -0
- package/js/examples/branching-edges.js +133 -0
- package/js/examples/branching-edges.js.map +1 -0
- package/js/examples/branching-graph.js +232 -0
- package/js/examples/branching-graph.js.map +1 -0
- package/js/examples/branching-router.js +305 -0
- package/js/examples/branching-router.js.map +1 -0
- package/js/examples/json-graph.js +197 -0
- package/js/examples/json-graph.js.map +1 -0
- package/js/examples/json-scripts.js +131 -0
- package/js/examples/json-scripts.js.map +1 -0
- package/js/tests/async.test.js +592 -0
- package/js/tests/async.test.js.map +1 -0
- package/js/tests/complex.test.js +972 -0
- package/js/tests/complex.test.js.map +1 -0
- package/js/tests/conformance.test.js +365 -0
- package/js/tests/conformance.test.js.map +1 -0
- package/js/tests/edges.test.js +702 -0
- package/js/tests/edges.test.js.map +1 -0
- package/js/tests/graphjson.test.js +504 -0
- package/js/tests/graphjson.test.js.map +1 -0
- package/js/tests/harness.js +192 -0
- package/js/tests/harness.js.map +1 -0
- package/js/tests/helpers.js +136 -0
- package/js/tests/helpers.js.map +1 -0
- package/js/tests/lint.test.js +317 -0
- package/js/tests/lint.test.js.map +1 -0
- package/js/tests/registry.test.js +705 -0
- package/js/tests/registry.test.js.map +1 -0
- package/js/tests/report.js +422 -0
- package/js/tests/report.js.map +1 -0
- package/js/tests/runner.js +67 -0
- package/js/tests/runner.js.map +1 -0
- package/js/tests/scripts.test.js +552 -0
- package/js/tests/scripts.test.js.map +1 -0
- package/js/tests/unit.test.js +1239 -0
- package/js/tests/unit.test.js.map +1 -0
- package/js/tests/upgrade.test.js +618 -0
- package/js/tests/upgrade.test.js.map +1 -0
- package/package.json +2 -9
- package/report/index.html +3727 -0
- package/report/report.json +3053 -0
- package/tests/async.test.ts +668 -0
- package/tests/complex.test.ts +1123 -0
- package/tests/conformance.test.ts +442 -0
- package/tests/edges.test.ts +848 -0
- package/tests/fixtures/scripts/bad-registration.cjs +4 -0
- package/tests/fixtures/scripts/broken.cjs +2 -0
- package/tests/fixtures/scripts/cjs-default.js +4 -0
- package/tests/fixtures/scripts/collide-a.cjs +4 -0
- package/tests/fixtures/scripts/collide-b.cjs +4 -0
- package/tests/fixtures/scripts/empty.cjs +2 -0
- package/tests/fixtures/scripts/esm-functions.mjs +10 -0
- package/tests/fixtures/scripts/esm-syntax.js +3 -0
- package/tests/fixtures/scripts/global-channel.cjs +6 -0
- package/tests/fixtures/scripts/global-channel.mjs +7 -0
- package/tests/fixtures/scripts/mismatch.cjs +4 -0
- package/tests/fixtures/scripts/needs-sibling.cjs +7 -0
- package/tests/fixtures/scripts/order.cjs +14 -0
- package/tests/fixtures/scripts/sibling-helper.cjs +3 -0
- package/tests/fixtures/scripts/throwing-global.mjs +6 -0
- package/tests/graphjson.test.ts +737 -0
- package/tests/harness.ts +291 -0
- package/tests/helpers.ts +216 -0
- package/tests/lint.test.ts +381 -0
- package/tests/registry.test.ts +1134 -0
- package/tests/report.ts +452 -0
- package/tests/runner.ts +58 -0
- package/tests/scripts.test.ts +970 -0
- package/tests/unit.test.ts +1192 -0
- package/tests/upgrade.test.ts +725 -0
- package/tools/server.mjs +152 -0
- package/tsconfig.browser.json +19 -0
- package/tsconfig.json +18 -0
- package/tsconfig.publish.json +13 -0
|
@@ -0,0 +1,3727 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8"/>
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
6
|
+
<title>AutomateGraph Execution Engine — Test Report (282 tests)</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root{
|
|
9
|
+
--bg:#0b1020; --panel:#121a33; --panel2:#0f1730; --line:#24304f;
|
|
10
|
+
--txt:#e7ecf7; --muted:#94a3c4; --accent:#6ea8fe; --ok:#31c48d; --bad:#f4645f;
|
|
11
|
+
--warn:#f0b429; --unit:#7c9cff; --complex:#c084fc; --async:#4fd1c5;
|
|
12
|
+
--upgrade:#f0b429; --conformance:#31c48d;
|
|
13
|
+
}
|
|
14
|
+
*{box-sizing:border-box}
|
|
15
|
+
body{margin:0;background:radial-gradient(1200px 600px at 15% -10%,#16224a 0%,var(--bg) 55%);color:var(--txt);
|
|
16
|
+
font:15px/1.55 ui-sans-serif,system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}
|
|
17
|
+
.wrap{max-width:1180px;margin:0 auto;padding:32px 20px 80px}
|
|
18
|
+
h1{font-size:30px;margin:0 0 6px;letter-spacing:-.4px}
|
|
19
|
+
h2{font-size:19px;margin:34px 0 12px;letter-spacing:-.2px}
|
|
20
|
+
h3{font-size:14px;margin:20px 0 8px;color:var(--muted);text-transform:uppercase;letter-spacing:.07em}
|
|
21
|
+
.sub{color:var(--muted);margin:0 0 22px}
|
|
22
|
+
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:12px;margin:22px 0 8px}
|
|
23
|
+
.card{background:linear-gradient(180deg,var(--panel),var(--panel2));border:1px solid var(--line);
|
|
24
|
+
border-radius:14px;padding:14px 16px}
|
|
25
|
+
.card .k{color:var(--muted);font-size:12px;text-transform:uppercase;letter-spacing:.08em}
|
|
26
|
+
.card .v{font-size:25px;font-weight:700;margin-top:4px}
|
|
27
|
+
.card.good .v{color:var(--ok)} .card.bad .v{color:var(--bad)}
|
|
28
|
+
.barrow{display:grid;grid-template-columns:340px 1fr 130px;gap:12px;align-items:center;padding:6px 0;border-bottom:1px dashed #1c2540}
|
|
29
|
+
.barlabel{font-size:13.5px}
|
|
30
|
+
.track{background:#0a1024;border:1px solid var(--line);border-radius:999px;height:16px;overflow:hidden}
|
|
31
|
+
.fill{height:100%;background:linear-gradient(90deg,#2f7cf6,#31c48d);color:#04122b;font-size:10.5px;
|
|
32
|
+
font-weight:700;text-align:right;padding-right:6px;line-height:16px}
|
|
33
|
+
.fill.warn{background:linear-gradient(90deg,#f0b429,#f4645f)}
|
|
34
|
+
.barmeta{color:var(--muted);font-size:12.5px;text-align:right}
|
|
35
|
+
.badge{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.06em;padding:2px 7px;border-radius:6px;vertical-align:middle}
|
|
36
|
+
.badge.unit{background:#1b2a55;color:var(--unit)}
|
|
37
|
+
.badge.integration{background:#331b55;color:var(--complex)}
|
|
38
|
+
.badge.async{background:#123a3a;color:var(--async)}
|
|
39
|
+
.badge.upgrade{background:#3a2b0d;color:var(--upgrade)}
|
|
40
|
+
.badge.conformance{background:#0f3627;color:var(--conformance)}
|
|
41
|
+
.badge.lint{background:#3a2410;color:#fb923c}
|
|
42
|
+
.badge.edges{background:#0d2a3a;color:#38bdf8}
|
|
43
|
+
.badge.registry{background:#2a1f45;color:#a78bfa}
|
|
44
|
+
.badge.graphjson{background:#0e3229;color:#34d399}
|
|
45
|
+
.badge.scripts{background:#3d1f2f;color:#f472b6}
|
|
46
|
+
.pill{display:inline-block;font-size:11px;font-weight:700;padding:2px 8px;border-radius:999px}
|
|
47
|
+
.pill.passed{background:#10322a;color:var(--ok);border:1px solid #1c5b46}
|
|
48
|
+
.pill.failed{background:#3a1620;color:var(--bad);border:1px solid #7a2b32}
|
|
49
|
+
.findings{display:grid;grid-template-columns:repeat(auto-fit,minmax(320px,1fr));gap:12px}
|
|
50
|
+
.fcard{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--warn);border-radius:12px;padding:12px 14px}
|
|
51
|
+
.fcard .fid{color:var(--warn);font-weight:700;font-size:12px}
|
|
52
|
+
.fcard .ftitle{font-weight:600;margin:2px 0 6px}
|
|
53
|
+
.fcard .fbody{color:#c8d3ec;font-size:13.5px}
|
|
54
|
+
.toolbar{display:flex;gap:10px;flex-wrap:wrap;align-items:center;margin:14px 0}
|
|
55
|
+
.btn{background:#16204a;border:1px solid var(--line);color:var(--txt);border-radius:999px;padding:6px 13px;
|
|
56
|
+
font-size:13px;cursor:pointer}
|
|
57
|
+
.btn.active{background:#233b7a;border-color:#3b57a6}
|
|
58
|
+
input[type=search]{background:#0d142c;border:1px solid var(--line);color:var(--txt);border-radius:999px;
|
|
59
|
+
padding:7px 14px;min-width:260px;font-size:13.5px}
|
|
60
|
+
.row{border:1px solid var(--line);border-radius:10px;margin:6px 0;background:var(--panel2)}
|
|
61
|
+
.row summary{display:grid;grid-template-columns:64px 62px 210px 1fr 74px 78px;gap:10px;align-items:center;
|
|
62
|
+
padding:9px 12px;cursor:pointer;list-style:none}
|
|
63
|
+
.row summary::-webkit-details-marker{display:none}
|
|
64
|
+
.row.ok{border-left:3px solid var(--ok)} .row.bad{border-left:3px solid var(--bad)}
|
|
65
|
+
.row .id{color:var(--muted);font-size:12.5px;font-variant-numeric:tabular-nums}
|
|
66
|
+
.row .cat{color:#b9c6e6;font-size:13px}
|
|
67
|
+
.row .name{font-size:13.5px}
|
|
68
|
+
.row .ms{color:var(--muted);font-size:12px;text-align:right}
|
|
69
|
+
.row .star{color:var(--warn);font-size:11px;border:1px solid #5f4a12;background:#2a2208;border-radius:6px;
|
|
70
|
+
padding:1px 6px;justify-self:start}
|
|
71
|
+
.detail{padding:10px 14px 12px;border-top:1px solid #1a2340;font-size:13.5px;color:#c8d3ec}
|
|
72
|
+
.detail .tag{display:inline-block;font-size:10.5px;font-weight:700;letter-spacing:.06em;color:#8fa6d8;
|
|
73
|
+
text-transform:uppercase;margin-right:8px}
|
|
74
|
+
.detail ul{margin:6px 0 0 18px;padding:0}
|
|
75
|
+
.detail.error .errline{color:#ffb3b0;font-weight:600}
|
|
76
|
+
pre{background:#080d1c;border:1px solid #1c2540;border-radius:8px;padding:10px;overflow:auto;font-size:12.5px;color:#b9c6e6}
|
|
77
|
+
.muted{color:var(--muted)}
|
|
78
|
+
table{width:100%;border-collapse:collapse;font-size:13.5px}
|
|
79
|
+
th,td{text-align:left;padding:8px 10px;border-bottom:1px solid #1c2540;vertical-align:top}
|
|
80
|
+
th{color:var(--muted);font-weight:600;font-size:12px;text-transform:uppercase;letter-spacing:.06em}
|
|
81
|
+
code{background:#0d142c;border:1px solid #1c2540;border-radius:6px;padding:1px 6px;font-size:12.5px}
|
|
82
|
+
.note{background:#101a38;border:1px solid var(--line);border-radius:12px;padding:12px 16px;color:#c8d3ec;font-size:13.5px}
|
|
83
|
+
.note.warn{border-color:#5f4a12;background:#241d09}
|
|
84
|
+
footer{color:var(--muted);font-size:12.5px;margin-top:28px;border-top:1px solid #1c2540;padding-top:14px}
|
|
85
|
+
</style>
|
|
86
|
+
</head>
|
|
87
|
+
<body>
|
|
88
|
+
<div class="wrap">
|
|
89
|
+
<h1>AutomateGraph Execution Engine v1.5 — Test Report</h1>
|
|
90
|
+
<p class="sub">282 tests (100 unit + 20 complex + 20 async + 19 upgrade + 11 conformance + 13 lint + 26 edges + 28 registry + 19 json + 26 scripts) executed against the single-file isomorphic core.
|
|
91
|
+
Generated 2026-10-13T14:22:25.409Z · Node v20.20.2 · wall clock 4019.24 ms.</p>
|
|
92
|
+
|
|
93
|
+
<div class="cards">
|
|
94
|
+
<div class="card"><div class="k">Total</div><div class="v">282</div></div>
|
|
95
|
+
<div class="card good"><div class="k">Passed</div><div class="v">282</div></div>
|
|
96
|
+
<div class="card good"><div class="k">Failed</div><div class="v">0</div></div>
|
|
97
|
+
<div class="card"><div class="k">UNIT</div><div class="v">100/100</div></div><div class="card"><div class="k">COMPLEX</div><div class="v">20/20</div></div><div class="card"><div class="k">ASYNC</div><div class="v">20/20</div></div><div class="card"><div class="k">UPGRADE</div><div class="v">19/19</div></div><div class="card"><div class="k">CONFORMANCE</div><div class="v">11/11</div></div><div class="card"><div class="k">LINT</div><div class="v">13/13</div></div><div class="card"><div class="k">EDGES</div><div class="v">26/26</div></div><div class="card"><div class="k">REGISTRY</div><div class="v">28/28</div></div><div class="card"><div class="k">JSON</div><div class="v">19/19</div></div><div class="card"><div class="k">SCRIPTS</div><div class="v">26/26</div></div>
|
|
98
|
+
<div class="card"><div class="k">Findings</div><div class="v">56</div></div>
|
|
99
|
+
<div class="card"><div class="k">Duration</div><div class="v">4.02s</div></div>
|
|
100
|
+
</div>
|
|
101
|
+
|
|
102
|
+
<p class="note">Process hygiene on shutdown: <span class="pill passed">clean</span> no unhandled rejections observed during the run. Each test runs in sequence with a per-test
|
|
103
|
+
timeout, so a hang or a leaked promise surfaces in this report instead of hanging the suite.</p>
|
|
104
|
+
|
|
105
|
+
<p class="note warn"><strong>v1.1 changed two observable behaviours:</strong> a cooperative callback that
|
|
106
|
+
<em>rejects because of</em> an abort now settles <code>CANCELLED</code> (was <code>FAILED</code> + unhandled error), and
|
|
107
|
+
<code>FAIL_FAST</code> is sticky at node level (was a one-off queue flush). <strong>v1.2 added the
|
|
108
|
+
<code>SUCCESS_DEAD_END</code> lint error.</strong> <strong>v1.3 adds typed edges</strong> — <code>next</code> now accepts
|
|
109
|
+
<code>{ nextNode, result, test, parallel }</code> objects (exclusive, ordered, first-match-wins, deep
|
|
110
|
+
equality) alongside the original strings (parallel, unchanged), plus explicit routing via
|
|
111
|
+
<code>return new Next(target, value)</code> or <code>context.goto(target)</code>. <strong>v1.4 adds the
|
|
112
|
+
function registry</strong> — <code>run</code> and edge <code>test</code> may name a registered function,
|
|
113
|
+
resolved lazily at evaluation time, with <code>{ fingerprint, names }</code> reported on
|
|
114
|
+
every run — plus a JSON loader (<code>src/graph-json.ts</code>) that turns a graph
|
|
115
|
+
document into a definition with total, path-carrying validation. <strong>v1.5 loads scripts</strong> —
|
|
116
|
+
a document may declare where its functions live (<code>path</code>, inline
|
|
117
|
+
<code>source</code> or <code>url</code>), the script either exports them or registers itself through
|
|
118
|
+
<code>globalThis.GraphEngine.registerEngineNamespace()</code>, and a namespace is frozen once per
|
|
119
|
+
process. Purely additive: every v1.0–v1.4 graph keeps its behaviour. See
|
|
120
|
+
<code>CHANGELOG.md</code>.</p>
|
|
121
|
+
|
|
122
|
+
<h2>Results by category</h2>
|
|
123
|
+
|
|
124
|
+
<div class="barrow">
|
|
125
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Graph validation</div>
|
|
126
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
127
|
+
<div class="barmeta">12/12 · 4.14 ms</div>
|
|
128
|
+
</div>
|
|
129
|
+
<div class="barrow">
|
|
130
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Error classes & utilities</div>
|
|
131
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
132
|
+
<div class="barmeta">9/9 · 0.56 ms</div>
|
|
133
|
+
</div>
|
|
134
|
+
<div class="barrow">
|
|
135
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Utilities</div>
|
|
136
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
137
|
+
<div class="barmeta">10/10 · 4.74 ms</div>
|
|
138
|
+
</div>
|
|
139
|
+
<div class="barrow">
|
|
140
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> EventBus</div>
|
|
141
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
142
|
+
<div class="barmeta">12/12 · 114.16 ms</div>
|
|
143
|
+
</div>
|
|
144
|
+
<div class="barrow">
|
|
145
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> InMemoryStorage</div>
|
|
146
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
147
|
+
<div class="barmeta">8/8 · 0.81 ms</div>
|
|
148
|
+
</div>
|
|
149
|
+
<div class="barrow">
|
|
150
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Graph freezing</div>
|
|
151
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
152
|
+
<div class="barmeta">8/8 · 1.75 ms</div>
|
|
153
|
+
</div>
|
|
154
|
+
<div class="barrow">
|
|
155
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Engine lifecycle</div>
|
|
156
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
157
|
+
<div class="barmeta">10/10 · 2.94 ms</div>
|
|
158
|
+
</div>
|
|
159
|
+
<div class="barrow">
|
|
160
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Execution & scheduler</div>
|
|
161
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
162
|
+
<div class="barmeta">20/20 · 19.49 ms</div>
|
|
163
|
+
</div>
|
|
164
|
+
<div class="barrow">
|
|
165
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Retry</div>
|
|
166
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
167
|
+
<div class="barmeta">6/6 · 90.62 ms</div>
|
|
168
|
+
</div>
|
|
169
|
+
<div class="barrow">
|
|
170
|
+
<div class="barlabel"><span class="badge unit">UNIT</span> Cancellation</div>
|
|
171
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
172
|
+
<div class="barmeta">5/5 · 71.66 ms</div>
|
|
173
|
+
</div>
|
|
174
|
+
<div class="barrow">
|
|
175
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> E2E pipelines</div>
|
|
176
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
177
|
+
<div class="barmeta">3/3 · 58.96 ms</div>
|
|
178
|
+
</div>
|
|
179
|
+
<div class="barrow">
|
|
180
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> Failure semantics</div>
|
|
181
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
182
|
+
<div class="barmeta">7/7 · 399.37 ms</div>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="barrow">
|
|
185
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> Concurrency & scale</div>
|
|
186
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
187
|
+
<div class="barmeta">3/3 · 91.98 ms</div>
|
|
188
|
+
</div>
|
|
189
|
+
<div class="barrow">
|
|
190
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> Cancellation & cycles</div>
|
|
191
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
192
|
+
<div class="barmeta">2/2 · 202.55 ms</div>
|
|
193
|
+
</div>
|
|
194
|
+
<div class="barrow">
|
|
195
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> Events & listeners</div>
|
|
196
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
197
|
+
<div class="barmeta">2/2 · 23.6 ms</div>
|
|
198
|
+
</div>
|
|
199
|
+
<div class="barrow">
|
|
200
|
+
<div class="barlabel"><span class="badge integration">COMPLEX</span> Lifecycle & plugins</div>
|
|
201
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
202
|
+
<div class="barmeta">3/3 · 54.22 ms</div>
|
|
203
|
+
</div>
|
|
204
|
+
<div class="barrow">
|
|
205
|
+
<div class="barlabel"><span class="badge async">ASYNC</span> Node callbacks (async)</div>
|
|
206
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
207
|
+
<div class="barmeta">20/20 · 619.64 ms</div>
|
|
208
|
+
</div>
|
|
209
|
+
<div class="barrow">
|
|
210
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A2 · drain deadline</div>
|
|
211
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
212
|
+
<div class="barmeta">2/2 · 542.36 ms</div>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="barrow">
|
|
215
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A3 · completion policy</div>
|
|
216
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
217
|
+
<div class="barmeta">4/4 · 78.41 ms</div>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="barrow">
|
|
220
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A4/A5 · FAIL_FAST & FALLBACK</div>
|
|
221
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
222
|
+
<div class="barmeta">4/4 · 30.91 ms</div>
|
|
223
|
+
</div>
|
|
224
|
+
<div class="barrow">
|
|
225
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A6/A10 · results & hygiene</div>
|
|
226
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
227
|
+
<div class="barmeta">3/3 · 147.37 ms</div>
|
|
228
|
+
</div>
|
|
229
|
+
<div class="barrow">
|
|
230
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A8 · concurrency & budget</div>
|
|
231
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
232
|
+
<div class="barmeta">3/3 · 29.41 ms</div>
|
|
233
|
+
</div>
|
|
234
|
+
<div class="barrow">
|
|
235
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> A9 · graph linting</div>
|
|
236
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
237
|
+
<div class="barmeta">2/2 · 1.06 ms</div>
|
|
238
|
+
</div>
|
|
239
|
+
<div class="barrow">
|
|
240
|
+
<div class="barlabel"><span class="badge upgrade">UPGRADE</span> Isomorphic build</div>
|
|
241
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
242
|
+
<div class="barmeta">1/1 · 1292.28 ms</div>
|
|
243
|
+
</div>
|
|
244
|
+
<div class="barrow">
|
|
245
|
+
<div class="barlabel"><span class="badge conformance">CONFORMANCE</span> Storage adapter contract</div>
|
|
246
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
247
|
+
<div class="barmeta">7/7 · 4.14 ms</div>
|
|
248
|
+
</div>
|
|
249
|
+
<div class="barrow">
|
|
250
|
+
<div class="barlabel"><span class="badge conformance">CONFORMANCE</span> Snapshot wire format</div>
|
|
251
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
252
|
+
<div class="barmeta">4/4 · 0.56 ms</div>
|
|
253
|
+
</div>
|
|
254
|
+
<div class="barrow">
|
|
255
|
+
<div class="barlabel"><span class="badge lint">LINT</span> Success dead-end rule</div>
|
|
256
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
257
|
+
<div class="barmeta">13/13 · 28.47 ms</div>
|
|
258
|
+
</div>
|
|
259
|
+
<div class="barrow">
|
|
260
|
+
<div class="barlabel"><span class="badge edges">EDGES</span> Typed edges & routing</div>
|
|
261
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
262
|
+
<div class="barmeta">26/26 · 23.34 ms</div>
|
|
263
|
+
</div>
|
|
264
|
+
<div class="barrow">
|
|
265
|
+
<div class="barlabel"><span class="badge registry">REGISTRY</span> Function registry</div>
|
|
266
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
267
|
+
<div class="barmeta">28/28 · 36.5 ms</div>
|
|
268
|
+
</div>
|
|
269
|
+
<div class="barrow">
|
|
270
|
+
<div class="barlabel"><span class="badge graphjson">JSON</span> Graph JSON loader</div>
|
|
271
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
272
|
+
<div class="barmeta">19/19 · 5.72 ms</div>
|
|
273
|
+
</div>
|
|
274
|
+
<div class="barrow">
|
|
275
|
+
<div class="barlabel"><span class="badge scripts">SCRIPTS</span> Script loading</div>
|
|
276
|
+
<div class="track"><div class="fill " style="width:100%">100%</div></div>
|
|
277
|
+
<div class="barmeta">26/26 · 25.46 ms</div>
|
|
278
|
+
</div>
|
|
279
|
+
|
|
280
|
+
<h2>Engine semantics documented by the findings (56)</h2>
|
|
281
|
+
<div class="findings">
|
|
282
|
+
<div class="fcard">
|
|
283
|
+
<div class="fid">I3 · COMPLEX</div>
|
|
284
|
+
<div class="ftitle">resilience scenario: timeout is routed to a fallback so the run completes</div>
|
|
285
|
+
<div class="fbody">fan-in runs the join node once per incoming edge (decide runs = 2)</div>
|
|
286
|
+
</div><div class="fcard">
|
|
287
|
+
<div class="fid">I4 · COMPLEX</div>
|
|
288
|
+
<div class="ftitle">graph-level FAIL_FAST stops not-yet-scheduled successors on independent branches</div>
|
|
289
|
+
<div class="fbody">an already-started sibling still observes its own completion before the graph settles as FAILED</div>
|
|
290
|
+
</div><div class="fcard">
|
|
291
|
+
<div class="fid">I6 · COMPLEX</div>
|
|
292
|
+
<div class="ftitle">diamond fan-in executes the join node once per incoming activation (no dedup)</div>
|
|
293
|
+
<div class="fbody">no join/dedup semantics — the join node ran once per incoming edge</div>
|
|
294
|
+
</div><div class="fcard">
|
|
295
|
+
<div class="fid">I7 · COMPLEX</div>
|
|
296
|
+
<div class="ftitle">cyclic graph iterates via next + ONTHROW exit and keeps a growing path</div>
|
|
297
|
+
<div class="fbody">cycles are legal (no validation) and terminate only via ONTHROW</div>
|
|
298
|
+
</div><div class="fcard">
|
|
299
|
+
<div class="fid">I8 · COMPLEX</div>
|
|
300
|
+
<div class="ftitle">250-node fan-out satisfies a full-concurrency barrier (no hidden cap)</div>
|
|
301
|
+
<div class="fbody">scheduler concurrency is unbounded (MAX_SAFE_INTEGER)</div>
|
|
302
|
+
</div><div class="fcard">
|
|
303
|
+
<div class="fid">I11 · COMPLEX</div>
|
|
304
|
+
<div class="ftitle">faulty non-required listeners are isolated; a failing required listener is contained</div>
|
|
305
|
+
<div class="fbody">graph.finished is the only emit whose rejection is caught by the engine; a failing required listener elsewhere (e.g. node.failed) escapes into the node error path</div>
|
|
306
|
+
</div><div class="fcard">
|
|
307
|
+
<div class="fid">I15 · COMPLEX</div>
|
|
308
|
+
<div class="ftitle">checkpoint failure on the 2nd save blocks scheduling and freezes the last valid snapshot</div>
|
|
309
|
+
<div class="fbody">the checkpoint failure surfaces twice per node (CHECKPOINT_SAVE_FAILED plus a NODE_EXECUTION_ERROR for the raw persistence error) and marks those nodes FAILED</div>
|
|
310
|
+
</div><div class="fcard">
|
|
311
|
+
<div class="fid">I16 · COMPLEX</div>
|
|
312
|
+
<div class="ftitle">node timeout settles the graph while the abandoned node keeps running (cooperative abort)</div>
|
|
313
|
+
<div class="fbody">JavaScript cannot kill a running node; the engine reports TIMED_OUT and moves on</div>
|
|
314
|
+
</div><div class="fcard">
|
|
315
|
+
<div class="fid">I17 · COMPLEX</div>
|
|
316
|
+
<div class="ftitle">policy matrix: RETRY loops, CONTINUE ignores maxAttempts, FALLBACK has no distinct path</div>
|
|
317
|
+
<div class="fbody">FALLBACK is accepted but treated as CONTINUE — no alternative-route mechanism exists</div>
|
|
318
|
+
</div><div class="fcard">
|
|
319
|
+
<div class="fid">I18 · COMPLEX</div>
|
|
320
|
+
<div class="ftitle">final-state precedence: terminal reached + unhandled errors still yields FAILED</div>
|
|
321
|
+
<div class="fbody">settlement order is cancellation > checkpoint failure > unhandled errors > logical completion; FAILED silently wins over a completed terminal</div>
|
|
322
|
+
</div><div class="fcard">
|
|
323
|
+
<div class="fid">I18 · COMPLEX</div>
|
|
324
|
+
<div class="ftitle">final-state precedence: terminal reached + unhandled errors still yields FAILED</div>
|
|
325
|
+
<div class="fbody">once any branch reaches a terminal node, pending activations (including ONTHROW recovery paths) are cleared and never executed, yet their errors stay marked handled</div>
|
|
326
|
+
</div><div class="fcard">
|
|
327
|
+
<div class="fid">I19 · COMPLEX</div>
|
|
328
|
+
<div class="ftitle">policy resolution: every FAIL_FAST is sticky and halts the scheduler</div>
|
|
329
|
+
<div class="fbody">FAIL_FAST is sticky at both levels since v1.1 (A4) — the old node-level behaviour was a one-off queue flush that did nothing under unbounded concurrency; a node-level CONTINUE still cannot shield other branches from a graph-level FAIL_FAST</div>
|
|
330
|
+
</div><div class="fcard">
|
|
331
|
+
<div class="fid">I20 · COMPLEX</div>
|
|
332
|
+
<div class="ftitle">cancelling a fan-out aborts in-flight nodes and never starts their successors</div>
|
|
333
|
+
<div class="fbody">cancel() returns immediately but the report waits for cooperative drain</div>
|
|
334
|
+
</div><div class="fcard">
|
|
335
|
+
<div class="fid">A1 · ASYNC</div>
|
|
336
|
+
<div class="ftitle">an async node callback is awaited and its resolved value becomes the output</div>
|
|
337
|
+
<div class="fbody">NodeContext signals are typed as AbortSignal even in older @types/node DOM-less libs, so async callbacks can consume context.signal without casting</div>
|
|
338
|
+
</div><div class="fcard">
|
|
339
|
+
<div class="fid">A5 · ASYNC</div>
|
|
340
|
+
<div class="ftitle">async rejections with AutomateGraphError preserve code and details</div>
|
|
341
|
+
<div class="fbody">TimeoutError is identified by class OR by a NODE_TIMEOUT-family code, so async rejections carrying that code are classified as TIMED_OUT</div>
|
|
342
|
+
</div><div class="fcard">
|
|
343
|
+
<div class="fid">A9 · ASYNC</div>
|
|
344
|
+
<div class="ftitle">a slow async callback is preempted by timeoutMs and reported TIMED_OUT</div>
|
|
345
|
+
<div class="fbody">on timeout the async callback's later resolution is discarded — no output is recorded</div>
|
|
346
|
+
</div><div class="fcard">
|
|
347
|
+
<div class="fid">A10 · ASYNC</div>
|
|
348
|
+
<div class="ftitle">a cooperative async callback observes the abort and rejects; the run settles CANCELLED</div>
|
|
349
|
+
<div class="fbody">since v1.1 (A1) cooperative cancellation is symmetric — a callback that rejects because of the abort settles CANCELLED with a handled GRAPH_CANCELLED record, exactly like one that resolves after it; result.error now carries the record (A6)</div>
|
|
350
|
+
</div><div class="fcard">
|
|
351
|
+
<div class="fid">A18 · ASYNC</div>
|
|
352
|
+
<div class="ftitle">an unrelated execution started after an abandoned async node is unaffected</div>
|
|
353
|
+
<div class="fbody">the abandoned async node still performed its side effect after settlement — async cancellation is cooperative only; nothing can stop an in-flight promise</div>
|
|
354
|
+
</div><div class="fcard">
|
|
355
|
+
<div class="fid">U1 · UPGRADE</div>
|
|
356
|
+
<div class="ftitle">cancellationTimeoutMs bounds the drain and abandons in-flight work</div>
|
|
357
|
+
<div class="fbody">without cancellationTimeoutMs the engine still waits forever (v1.0 behaviour); setting it converts an unbounded drain into a bounded, reported one</div>
|
|
358
|
+
</div><div class="fcard">
|
|
359
|
+
<div class="fid">U3 · UPGRADE</div>
|
|
360
|
+
<div class="ftitle">ALL_TERMINALS waits for every declared terminal before latching completion</div>
|
|
361
|
+
<div class="fbody">ALL_TERMINALS gives fan-in style completion semantics without extra plumbing</div>
|
|
362
|
+
</div><div class="fcard">
|
|
363
|
+
<div class="fid">U4 · UPGRADE</div>
|
|
364
|
+
<div class="ftitle">DRAIN keeps scheduling after a terminal, so ONTHROW recovery is no longer dropped</div>
|
|
365
|
+
<div class="fbody">DRAIN is the opt-in fix for the v1.0 silent-drop behaviour (finding C-15/C-19) — the run executes every reachable activation before settling</div>
|
|
366
|
+
</div><div class="fcard">
|
|
367
|
+
<div class="fid">U5 · UPGRADE</div>
|
|
368
|
+
<div class="ftitle">FIRST_TERMINAL (default) drops pending work but now reports it via activation.dropped</div>
|
|
369
|
+
<div class="fbody">dropped work is now observable, so silent data loss in the default mode is detectable</div>
|
|
370
|
+
</div><div class="fcard">
|
|
371
|
+
<div class="fid">U19 · UPGRADE</div>
|
|
372
|
+
<div class="ftitle">the engine core compiles with DOM-only libs and no Node types (browser-safe)</div>
|
|
373
|
+
<div class="fbody">the engine core is isomorphic — no Node APIs, no Buffers, timers via setTimeout only</div>
|
|
374
|
+
</div><div class="fcard">
|
|
375
|
+
<div class="fid">C4 · CONFORMANCE</div>
|
|
376
|
+
<div class="ftitle">the checker catches a torn write that commits before failing</div>
|
|
377
|
+
<div class="fbody">the conformance suite distinguishes 'rejects' from 'rejects without corrupting state' — adapters must checkpoint before commit, not after</div>
|
|
378
|
+
</div><div class="fcard">
|
|
379
|
+
<div class="fid">L1 · LINT</div>
|
|
380
|
+
<div class="ftitle">the exact C-19 fixture is flagged: slow-vendor succeeds into a void</div>
|
|
381
|
+
<div class="fbody">a node can declare onThrow and still be unreachable on its success path — the previous DEAD_END_NODE rule only asked whether *any* transition existed</div>
|
|
382
|
+
</div><div class="fcard">
|
|
383
|
+
<div class="fid">L11 · LINT</div>
|
|
384
|
+
<div class="ftitle">lint: "error" rejects the C-19 graph before any node runs</div>
|
|
385
|
+
<div class="fbody">lint enforcement is a pre-flight gate — the graph is rejected before initialization finishes, so no side effects from node callbacks can occur</div>
|
|
386
|
+
</div><div class="fcard">
|
|
387
|
+
<div class="fid">E1 · EDGES</div>
|
|
388
|
+
<div class="ftitle">string edges keep the v1.0 meaning: unconditional fan-out</div>
|
|
389
|
+
<div class="fbody">`next: ["b","c"]` normalizes to two parallel edges — every existing graph keeps its behaviour</div>
|
|
390
|
+
</div><div class="fcard">
|
|
391
|
+
<div class="fid">E3 · EDGES</div>
|
|
392
|
+
<div class="ftitle">deep equality matches nested objects regardless of key order</div>
|
|
393
|
+
<div class="fbody">result uses structural equality (key order, nesting and array order aware)</div>
|
|
394
|
+
</div><div class="fcard">
|
|
395
|
+
<div class="fid">E5 · EDGES</div>
|
|
396
|
+
<div class="ftitle">result: undefined matches an undefined output (presence, not truthiness)</div>
|
|
397
|
+
<div class="fbody">hasResult tracks key presence, so an undefined output is matchable</div>
|
|
398
|
+
</div><div class="fcard">
|
|
399
|
+
<div class="fid">E10 · EDGES</div>
|
|
400
|
+
<div class="ftitle">no match is silent: nothing is scheduled, no routing error is recorded</div>
|
|
401
|
+
<div class="fbody">an unmatched conditional chain is silent by design (no NO_EDGE_MATCHED error)</div>
|
|
402
|
+
</div><div class="fcard">
|
|
403
|
+
<div class="fid">E14 · EDGES</div>
|
|
404
|
+
<div class="ftitle">returning new Next(target, value) routes and successors see the unwrapped value</div>
|
|
405
|
+
<div class="fbody">Next carries both destination and payload — successors and matchers see the payload</div>
|
|
406
|
+
</div><div class="fcard">
|
|
407
|
+
<div class="fid">E17 · EDGES</div>
|
|
408
|
+
<div class="ftitle">an explicit route replaces the whole edge list, parallel edges included</div>
|
|
409
|
+
<div class="fbody">an explicit route is authoritative — declared edges (and parallel ones) are ignored</div>
|
|
410
|
+
</div><div class="fcard">
|
|
411
|
+
<div class="fid">E22 · EDGES</div>
|
|
412
|
+
<div class="ftitle">a terminal node ignores its edges and its routing, and lint warns about it</div>
|
|
413
|
+
<div class="fbody">terminal detection happens before routing — a terminal node never schedules successors</div>
|
|
414
|
+
</div><div class="fcard">
|
|
415
|
+
<div class="fid">E23 · EDGES</div>
|
|
416
|
+
<div class="ftitle">lint flags an exclusive edge declared after an else edge as unreachable</div>
|
|
417
|
+
<div class="fbody">an else edge shadows every exclusive edge declared after it — runtime agrees with lint</div>
|
|
418
|
+
</div><div class="fcard">
|
|
419
|
+
<div class="fid">E25 · EDGES</div>
|
|
420
|
+
<div class="ftitle">the a → b/c/d/e/f picture runs as ONE execution — the router is no longer needed</div>
|
|
421
|
+
<div class="fbody">with typed edges the whole picture is ONE execution and lint-clean — no router, no gate, no DRAIN policy needed</div>
|
|
422
|
+
</div><div class="fcard">
|
|
423
|
+
<div class="fid">R1 · REGISTRY</div>
|
|
424
|
+
<div class="ftitle">a node whose run is a registered NAME executes that function</div>
|
|
425
|
+
<div class="fbody">report.results[i].fn — not report.results[i].output — is the audit link to the registered source</div>
|
|
426
|
+
</div><div class="fcard">
|
|
427
|
+
<div class="fid">R4 · REGISTRY</div>
|
|
428
|
+
<div class="ftitle">registerFunction() after construction is honoured (resolution is lazy)</div>
|
|
429
|
+
<div class="fbody">an engine with an empty registry reports no `registry` field, but registerFunction() makes it appear</div>
|
|
430
|
+
</div><div class="fcard">
|
|
431
|
+
<div class="fid">R8 · REGISTRY</div>
|
|
432
|
+
<div class="ftitle">a registered node can route explicitly with Next and with context.goto</div>
|
|
433
|
+
<div class="fbody">`new Next(target, value)` sets the ROUTER's output to `value` (that is what edge matchers and context.outputs see); the target node still executes its own function</div>
|
|
434
|
+
</div><div class="fcard">
|
|
435
|
+
<div class="fid">R11 · REGISTRY</div>
|
|
436
|
+
<div class="ftitle">a missing run name is PERMANENT: no retry, no onThrow, no fallback</div>
|
|
437
|
+
<div class="fbody">retry/onThrow/fallback are error RECOVERY; a name that was never registered is a wiring defect, so the engine refuses to recover from it</div>
|
|
438
|
+
</div><div class="fcard">
|
|
439
|
+
<div class="fid">R16 · REGISTRY</div>
|
|
440
|
+
<div class="ftitle">an unresolvable edge test never matches, is recorded once, and lets the else edge run</div>
|
|
441
|
+
<div class="fbody">an unresolvable test is loud but not fatal to ROUTING — the rest of the chain still evaluates; the run itself settles FAILED because the error stays unhandled (terminal-reached + unhandled error = FAILED, as in v1.2)</div>
|
|
442
|
+
</div><div class="fcard">
|
|
443
|
+
<div class="fid">R18 · REGISTRY</div>
|
|
444
|
+
<div class="ftitle">lint treats a NAMED test as conditional — no false UNREACHABLE_EDGE</div>
|
|
445
|
+
<div class="fbody">regression guard — before edgeHasMatcher() was shared, a named test looked like an else edge to the lint and every later edge was reported UNREACHABLE_EDGE</div>
|
|
446
|
+
</div><div class="fcard">
|
|
447
|
+
<div class="fid">R23 · REGISTRY</div>
|
|
448
|
+
<div class="ftitle">the fingerprint is stable, order-independent, and source-sensitive</div>
|
|
449
|
+
<div class="fbody">the fingerprint covers names + function SOURCE TEXT — two closures of the same source share it, while a captured value that changes at runtime does not show up</div>
|
|
450
|
+
</div><div class="fcard">
|
|
451
|
+
<div class="fid">R26 · REGISTRY</div>
|
|
452
|
+
<div class="ftitle">nodeFunctions()/edgeTests() restore per-signature inference</div>
|
|
453
|
+
<div class="fbody">one table holds both signatures; a bare literal cannot infer a parameter type from the union, hence nodeFunctions()/edgeTests()</div>
|
|
454
|
+
</div><div class="fcard">
|
|
455
|
+
<div class="fid">G1 · JSON</div>
|
|
456
|
+
<div class="ftitle">a valid document parses into a GraphDefinition (string and object input agree)</div>
|
|
457
|
+
<div class="fbody">parsing never needs the registry — a data file is valid even when a function name is unknown; the engine decides that at run time</div>
|
|
458
|
+
</div><div class="fcard">
|
|
459
|
+
<div class="fid">G15 · JSON</div>
|
|
460
|
+
<div class="ftitle">EVERY issue is collected — one throw carries them all</div>
|
|
461
|
+
<div class="fbody">one document reported 5 problems in a single throw — no fix-one-rerun loop</div>
|
|
462
|
+
</div><div class="fcard">
|
|
463
|
+
<div class="fid">G18 · JSON</div>
|
|
464
|
+
<div class="ftitle">a parsed document with dangling ids is still caught by the engine if it is hand-edited</div>
|
|
465
|
+
<div class="fbody">the loader and the engine validate different layers (paths vs. final shape) — both stay in force</div>
|
|
466
|
+
</div><div class="fcard">
|
|
467
|
+
<div class="fid">S1 · SCRIPTS</div>
|
|
468
|
+
<div class="ftitle">a .cjs script is required and its export table becomes the registry</div>
|
|
469
|
+
<div class="fbody">a registered name is not rewritten — `classifyOrder` stays `classifyOrder`, the namespace only owns the claim</div>
|
|
470
|
+
</div><div class="fcard">
|
|
471
|
+
<div class="fid">S3 · SCRIPTS</div>
|
|
472
|
+
<div class="ftitle">a .js script with ESM syntax is detected as ESM; without it, as CommonJS</div>
|
|
473
|
+
<div class="fbody">.js detection is a source hint with a fallback — the other format is attempted before failing, so a mis-hint costs one retry, never a failed load</div>
|
|
474
|
+
</div><div class="fcard">
|
|
475
|
+
<div class="fid">S8 · SCRIPTS</div>
|
|
476
|
+
<div class="ftitle">a script can register itself through globalThis.GraphEngine</div>
|
|
477
|
+
<div class="fbody">the engine global is a per-CALL slot (registerEngineNamespace), not a shared mutable table — a script can only ever add its own namespace, and only once</div>
|
|
478
|
+
</div><div class="fcard">
|
|
479
|
+
<div class="fid">S13 · SCRIPTS</div>
|
|
480
|
+
<div class="ftitle">a namespace can be claimed only once per process (exports path)</div>
|
|
481
|
+
<div class="fbody">the freeze is PROCESS-global by design — one document, one engine per namespace. Loading the same graph file into a second engine throws until the claims are reset</div>
|
|
482
|
+
</div><div class="fcard">
|
|
483
|
+
<div class="fid">S15 · SCRIPTS</div>
|
|
484
|
+
<div class="ftitle">a claim made before a crashing script survives; the load still fails</div>
|
|
485
|
+
<div class="fbody">claims are made at registration time, not at load end — a script that registers and then throws leaves its namespace claimed (reload needs resetGraphScriptNamespaces)</div>
|
|
486
|
+
</div><div class="fcard">
|
|
487
|
+
<div class="fid">S16 · SCRIPTS</div>
|
|
488
|
+
<div class="ftitle">a script that throws is not replayed in the other format</div>
|
|
489
|
+
<div class="fbody">format fallback replays the script body, so it is reserved for module-format failures (ERR_REQUIRE_ESM, ESM syntax in CJS). A script that throws — or registers and then throws — is never re-executed; it ran once and its claim stands</div>
|
|
490
|
+
</div><div class="fcard">
|
|
491
|
+
<div class="fid">S17 · SCRIPTS</div>
|
|
492
|
+
<div class="ftitle">two scripts providing the same name collide; override is opt-in</div>
|
|
493
|
+
<div class="fbody">claims and name collisions are separate gates — the freeze stops the namespace, collisions stop the merged table, and only the second one has an override</div>
|
|
494
|
+
</div><div class="fcard">
|
|
495
|
+
<div class="fid">S20 · SCRIPTS</div>
|
|
496
|
+
<div class="ftitle">a scripted document still parses with the v1.4 entry point</div>
|
|
497
|
+
<div class="fbody">`scripts` is validated by the isomorphic parser and executed by the Node loader — parseGraphJSON (sync, v1.4) keeps working on scripted documents</div>
|
|
498
|
+
</div><div class="fcard">
|
|
499
|
+
<div class="fid">S23 · SCRIPTS</div>
|
|
500
|
+
<div class="ftitle">a scripted document runs: the script provides the node and edge functions</div>
|
|
501
|
+
<div class="fbody">end-to-end, 6 functions arrive from path:./order.cjs and the engine reports fnr1:6:b43eadc7</div>
|
|
502
|
+
</div><div class="fcard">
|
|
503
|
+
<div class="fid">S25 · SCRIPTS</div>
|
|
504
|
+
<div class="ftitle">inline scripts compose with path scripts in one document</div>
|
|
505
|
+
<div class="fbody">the three media (path, source, url) are interchangeable — one pipeline merges them into a single table with one fingerprint</div>
|
|
506
|
+
</div>
|
|
507
|
+
</div>
|
|
508
|
+
|
|
509
|
+
<h2>Test inventory</h2>
|
|
510
|
+
<h3>9 unit categories (100 tests)</h3>
|
|
511
|
+
<table>
|
|
512
|
+
<tr><th>Category</th><th>Focus</th><th>Count</th><th>Time</th></tr>
|
|
513
|
+
<tr><td>Graph validation</td><td class="muted">Constructor-time rejection of malformed graph definitions</td><td>12</td><td>4.14 ms</td></tr><tr><td>Error classes & utilities</td><td class="muted">Error hierarchy, codes, id/time generation, throw coercion</td><td>9</td><td>0.56 ms</td></tr><tr><td>EventBus</td><td class="muted">Required vs non-required listeners, ordering, isolation, teardown</td><td>12</td><td>114.16 ms</td></tr><tr><td>InMemoryStorage</td><td class="muted">Atomic snapshot semantics and copy isolation</td><td>8</td><td>0.81 ms</td></tr><tr><td>Graph freezing</td><td class="muted">Immutability of definitions after construction</td><td>8</td><td>1.75 ms</td></tr><tr><td>Engine lifecycle</td><td class="muted">State machine, single-run guard, plugin init/shutdown</td><td>10</td><td>2.94 ms</td></tr><tr><td>Execution & scheduler</td><td class="muted">Scheduling, fan-out, contexts, events, checkpoints, settlement</td><td>20</td><td>19.49 ms</td></tr><tr><td>Retry</td><td class="muted">RETRY policy looping, delays, attempt accounting</td><td>6</td><td>90.62 ms</td></tr><tr><td>Cancellation</td><td class="muted">Cooperative abort, cancellation events, terminal no-ops</td><td>5</td><td>71.66 ms</td></tr>
|
|
514
|
+
</table>
|
|
515
|
+
|
|
516
|
+
<h3>20 COMPLEX cases — end-to-end pipelines, failure semantics, concurrency & scale, listeners, plugin lifecycle, cancellation</h3>
|
|
517
|
+
<table>
|
|
518
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
519
|
+
<tr><td>I1</td><td>multi-branch order pipeline completes with a checkpoint per successful node</td><td class="muted">E2E pipelines</td><td>0.73 ms</td></tr><tr><td>I2</td><td>chaos graph: retry recovery plus ONTHROW repair still completes</td><td class="muted">E2E pipelines</td><td>11.54 ms</td></tr><tr><td>I3</td><td>resilience scenario: timeout is routed to a fallback so the run completes</td><td class="muted">E2E pipelines</td><td>46.69 ms</td></tr><tr><td>I4</td><td>graph-level FAIL_FAST stops not-yet-scheduled successors on independent branches</td><td class="muted">Failure semantics</td><td>31.03 ms</td></tr><tr><td>I5</td><td>ONTHROW routes to a repair node and the failing node is never re-attempted</td><td class="muted">Failure semantics</td><td>0.65 ms</td></tr><tr><td>I6</td><td>diamond fan-in executes the join node once per incoming activation (no dedup)</td><td class="muted">Concurrency & scale</td><td>0.52 ms</td></tr><tr><td>I7</td><td>cyclic graph iterates via next + ONTHROW exit and keeps a growing path</td><td class="muted">Cancellation & cycles</td><td>0.43 ms</td></tr><tr><td>I8</td><td>250-node fan-out satisfies a full-concurrency barrier (no hidden cap)</td><td class="muted">Concurrency & scale</td><td>88.81 ms</td></tr><tr><td>I9</td><td>40-node chain produces monotone, gap-free checkpoints in execution order</td><td class="muted">Concurrency & scale</td><td>2.65 ms</td></tr><tr><td>I10</td><td>required listeners observe a deterministic lifecycle event order</td><td class="muted">Events & listeners</td><td>2.17 ms</td></tr><tr><td>I11</td><td>faulty non-required listeners are isolated; a failing required listener is contained</td><td class="muted">Events & listeners</td><td>21.43 ms</td></tr><tr><td>I12</td><td>plugins close in reverse order and shutdown failures are collected, not fatal</td><td class="muted">Lifecycle & plugins</td><td>6.33 ms</td></tr><tr><td>I13</td><td>plugin shutdown is time-boxed by cancellationTimeoutMs</td><td class="muted">Lifecycle & plugins</td><td>31.36 ms</td></tr><tr><td>I14</td><td>two concurrent executions keep ids, snapshots and results isolated</td><td class="muted">Lifecycle & plugins</td><td>16.53 ms</td></tr><tr><td>I15</td><td>checkpoint failure on the 2nd save blocks scheduling and freezes the last valid snapshot</td><td class="muted">Failure semantics</td><td>15.28 ms</td></tr><tr><td>I16</td><td>node timeout settles the graph while the abandoned node keeps running (cooperative abort)</td><td class="muted">Failure semantics</td><td>240.69 ms</td></tr><tr><td>I17</td><td>policy matrix: RETRY loops, CONTINUE ignores maxAttempts, FALLBACK has no distinct path</td><td class="muted">Failure semantics</td><td>21.88 ms</td></tr><tr><td>I18</td><td>final-state precedence: terminal reached + unhandled errors still yields FAILED</td><td class="muted">Failure semantics</td><td>36.37 ms</td></tr><tr><td>I19</td><td>policy resolution: every FAIL_FAST is sticky and halts the scheduler</td><td class="muted">Failure semantics</td><td>53.47 ms</td></tr><tr><td>I20</td><td>cancelling a fan-out aborts in-flight nodes and never starts their successors</td><td class="muted">Cancellation & cycles</td><td>202.12 ms</td></tr>
|
|
520
|
+
</table>
|
|
521
|
+
<h3>20 ASYNC cases — async node callbacks across every path: success, retry, ONTHROW, timeout, abort, fan-out, checkpoints</h3>
|
|
522
|
+
<table>
|
|
523
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
524
|
+
<tr><td>A1</td><td>an async node callback is awaited and its resolved value becomes the output</td><td class="muted">Node callbacks (async)</td><td>10.64 ms</td></tr><tr><td>A2</td><td>a non-async callback that returns a thenable is also awaited</td><td class="muted">Node callbacks (async)</td><td>5.65 ms</td></tr><tr><td>A3</td><td>async callback with no return value produces an undefined output</td><td class="muted">Node callbacks (async)</td><td>5.56 ms</td></tr><tr><td>A4</td><td>a rejected async callback is captured with code, stack and path</td><td class="muted">Node callbacks (async)</td><td>5.87 ms</td></tr><tr><td>A5</td><td>async rejections with AutomateGraphError preserve code and details</td><td class="muted">Node callbacks (async)</td><td>5.58 ms</td></tr><tr><td>A6</td><td>async retry callback recovers on a later attempt inside one activation</td><td class="muted">Node callbacks (async)</td><td>26.59 ms</td></tr><tr><td>A7</td><td>async callback can be retried by a custom node errorPolicy (RETRY)</td><td class="muted">Node callbacks (async)</td><td>8.06 ms</td></tr><tr><td>A8</td><td>async rejection routes through ONTHROW into an async repair callback</td><td class="muted">Node callbacks (async)</td><td>11.06 ms</td></tr><tr><td>A9</td><td>a slow async callback is preempted by timeoutMs and reported TIMED_OUT</td><td class="muted">Node callbacks (async)</td><td>165.49 ms</td></tr><tr><td>A10</td><td>a cooperative async callback observes the abort and rejects; the run settles CANCELLED</td><td class="muted">Node callbacks (async)</td><td>16.63 ms</td></tr><tr><td>A11</td><td>an async callback that ignores the signal delays settlement; successors stay unscheduled</td><td class="muted">Node callbacks (async)</td><td>60.17 ms</td></tr><tr><td>A12</td><td>async completion triggers exactly one checkpoint per successful node</td><td class="muted">Node callbacks (async)</td><td>16.28 ms</td></tr><tr><td>A13</td><td>context.emit from an async callback is awaited and ordered</td><td class="muted">Node callbacks (async)</td><td>3.7 ms</td></tr><tr><td>A14</td><td>async callbacks on independent branches execute in parallel</td><td class="muted">Node callbacks (async)</td><td>41.03 ms</td></tr><tr><td>A15</td><td>mixed sync and async nodes run together in one pipeline</td><td class="muted">Node callbacks (async)</td><td>11.09 ms</td></tr><tr><td>A16</td><td>async callback composes success, retry and failure across a three-branch graph</td><td class="muted">Node callbacks (async)</td><td>12.39 ms</td></tr><tr><td>A17</td><td>an async callback returning a marker drives a synchronous state-machine successor</td><td class="muted">Node callbacks (async)</td><td>5.7 ms</td></tr><tr><td>A18</td><td>an unrelated execution started after an abandoned async node is unaffected</td><td class="muted">Node callbacks (async)</td><td>181.69 ms</td></tr><tr><td>A19</td><td>diverse async callbacks (timers, microtasks, thenables) are classified correctly</td><td class="muted">Node callbacks (async)</td><td>3.24 ms</td></tr><tr><td>A20</td><td>async callbacks integrate with plugins, storage snapshots and the execution report</td><td class="muted">Node callbacks (async)</td><td>23.22 ms</td></tr>
|
|
525
|
+
</table>
|
|
526
|
+
<h3>19 UPGRADE cases — Wave 1 (v1.1) guarantees: drain deadline, completion policies, sticky FAIL_FAST, FALLBACK routing, budgets, linting, isomorphic build</h3>
|
|
527
|
+
<table>
|
|
528
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
529
|
+
<tr><td>U1</td><td>cancellationTimeoutMs bounds the drain and abandons in-flight work</td><td class="muted">A2 · drain deadline</td><td>481.07 ms</td></tr><tr><td>U2</td><td>without cancellationTimeoutMs the run waits for cooperative drain</td><td class="muted">A2 · drain deadline</td><td>61.29 ms</td></tr><tr><td>U3</td><td>ALL_TERMINALS waits for every declared terminal before latching completion</td><td class="muted">A3 · completion policy</td><td>26.35 ms</td></tr><tr><td>U4</td><td>DRAIN keeps scheduling after a terminal, so ONTHROW recovery is no longer dropped</td><td class="muted">A3 · completion policy</td><td>26.01 ms</td></tr><tr><td>U5</td><td>FIRST_TERMINAL (default) drops pending work but now reports it via activation.dropped</td><td class="muted">A3 · completion policy</td><td>25.88 ms</td></tr><tr><td>U6</td><td>an unknown completionPolicy is rejected at construction time</td><td class="muted">A3 · completion policy</td><td>0.17 ms</td></tr><tr><td>U7</td><td>node-level FAIL_FAST is sticky and drops successors via activation.dropped</td><td class="muted">A4/A5 · FAIL_FAST & FALLBACK</td><td>30.1 ms</td></tr><tr><td>U8</td><td>FALLBACK routes to the fallback node and marks the error handled</td><td class="muted">A4/A5 · FAIL_FAST & FALLBACK</td><td>0.43 ms</td></tr><tr><td>U9</td><td>a fallback target is ignored unless the effective policy is FALLBACK</td><td class="muted">A4/A5 · FAIL_FAST & FALLBACK</td><td>0.25 ms</td></tr><tr><td>U10</td><td>an unknown fallback target is rejected at construction time</td><td class="muted">A4/A5 · FAIL_FAST & FALLBACK</td><td>0.13 ms</td></tr><tr><td>U11</td><td>NodeResult.error carries the failure record and matches the report errors</td><td class="muted">A6/A10 · results & hygiene</td><td>0.18 ms</td></tr><tr><td>U12</td><td>a timed-out node exposes NODE_TIMEOUT on its own result</td><td class="muted">A6/A10 · results & hygiene</td><td>116.21 ms</td></tr><tr><td>U13</td><td>in-flight activation tracking is empty before and after a run</td><td class="muted">A6/A10 · results & hygiene</td><td>30.98 ms</td></tr><tr><td>U14</td><td>maxConcurrency bounds parallelism and preserves completion</td><td class="muted">A8 · concurrency & budget</td><td>28.62 ms</td></tr><tr><td>U15</td><td>maxActivations stops a runaway cycle with STEP_BUDGET_EXCEEDED</td><td class="muted">A8 · concurrency & budget</td><td>0.59 ms</td></tr><tr><td>U16</td><td>invalid concurrency and budget options are rejected</td><td class="muted">A8 · concurrency & budget</td><td>0.2 ms</td></tr><tr><td>U17</td><td>lintGraph reports unreachable nodes, unreachable terminals, dead ends and duplicates</td><td class="muted">A9 · graph linting</td><td>0.43 ms</td></tr><tr><td>U18</td><td>lint: "warn" logs issues, lint: "error" rejects only on error-level issues</td><td class="muted">A9 · graph linting</td><td>0.63 ms</td></tr><tr><td>U19</td><td>the engine core compiles with DOM-only libs and no Node types (browser-safe)</td><td class="muted">Isomorphic build</td><td>1292.28 ms</td></tr>
|
|
530
|
+
</table>
|
|
531
|
+
<h3>11 CONFORMANCE cases — the storage adapter contract is enforced by a checker with teeth, plus the snapshot wire format</h3>
|
|
532
|
+
<table>
|
|
533
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
534
|
+
<tr><td>C1</td><td>InMemoryStorage passes the full conformance suite with zero violations</td><td class="muted">Storage adapter contract</td><td>1.84 ms</td></tr><tr><td>C2</td><td>an adapter with fault injection proves atomicity instead of skipping it</td><td class="muted">Storage adapter contract</td><td>0.52 ms</td></tr><tr><td>C3</td><td>the checker catches aliasing, broken listing and broken deletion</td><td class="muted">Storage adapter contract</td><td>0.41 ms</td></tr><tr><td>C4</td><td>the checker catches a torn write that commits before failing</td><td class="muted">Storage adapter contract</td><td>0.68 ms</td></tr><tr><td>C5</td><td>missing required members are reported as SHAPE violations</td><td class="muted">Storage adapter contract</td><td>0.12 ms</td></tr><tr><td>C6</td><td>an adapter that claims a capability it does not implement is rejected (defineStorageAdapter)</td><td class="muted">Storage adapter contract</td><td>0.11 ms</td></tr><tr><td>C7</td><td>the engine accepts any conformant adapter as its storage plugin</td><td class="muted">Storage adapter contract</td><td>0.46 ms</td></tr><tr><td>C8</td><td>serializeSnapshot is deterministic and round-trips through JSON</td><td class="muted">Snapshot wire format</td><td>0.17 ms</td></tr><tr><td>C9</td><td>corrupt or unsupported snapshots are rejected with typed errors</td><td class="muted">Snapshot wire format</td><td>0.15 ms</td></tr><tr><td>C10</td><td>snapshotShapeViolations pinpoints every malformed field</td><td class="muted">Snapshot wire format</td><td>0.09 ms</td></tr><tr><td>C11</td><td>compareSnapshots reports structural differences precisely</td><td class="muted">Snapshot wire format</td><td>0.15 ms</td></tr>
|
|
535
|
+
</table>
|
|
536
|
+
<h3>13 LINT cases — the SUCCESS_DEAD_END rule: non-terminal nodes whose success path has nowhere to go</h3>
|
|
537
|
+
<table>
|
|
538
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
539
|
+
<tr><td>L1</td><td>the exact C-19 fixture is flagged: slow-vendor succeeds into a void</td><td class="muted">Success dead-end rule</td><td>0.52 ms</td></tr><tr><td>L2</td><td>the fix suggested by the message clears the issue (next declared)</td><td class="muted">Success dead-end rule</td><td>0.13 ms</td></tr><tr><td>L3</td><td>declared terminal nodes are never flagged, even without next</td><td class="muted">Success dead-end rule</td><td>0.08 ms</td></tr><tr><td>L4</td><td>a node with no transitions at all is DEAD_END_NODE, not SUCCESS_DEAD_END</td><td class="muted">Success dead-end rule</td><td>0.07 ms</td></tr><tr><td>L5</td><td>an ignored fallback does not count as a live error transition</td><td class="muted">Success dead-end rule</td><td>0.1 ms</td></tr><tr><td>L6</td><td>a live fallback (policy FALLBACK) makes it SUCCESS_DEAD_END, not a total dead end</td><td class="muted">Success dead-end rule</td><td>0.09 ms</td></tr><tr><td>L7</td><td>onThrow alone is treated as a live error transition</td><td class="muted">Success dead-end rule</td><td>0.06 ms</td></tr><tr><td>L8</td><td>unreachable nodes with a success path stay unreachable-only (no noise)</td><td class="muted">Success dead-end rule</td><td>0.06 ms</td></tr><tr><td>L9</td><td>every issue has a stable shape and a known code</td><td class="muted">Success dead-end rule</td><td>0.18 ms</td></tr><tr><td>L10</td><td>lint: "warn" logs SUCCESS_DEAD_END and still completes the C-19 run</td><td class="muted">Success dead-end rule</td><td>26.19 ms</td></tr><tr><td>L11</td><td>lint: "error" rejects the C-19 graph before any node runs</td><td class="muted">Success dead-end rule</td><td>0.33 ms</td></tr><tr><td>L12</td><td>the C-01 order-pipeline fixture flags audit as DEAD_END_NODE (documented gotcha)</td><td class="muted">Success dead-end rule</td><td>0.41 ms</td></tr><tr><td>L13</td><td>a graph with no transition problems lints clean and runs</td><td class="muted">Success dead-end rule</td><td>0.25 ms</td></tr>
|
|
540
|
+
</table>
|
|
541
|
+
<h3>26 EDGES cases — typed edges: deep-equality/t predicate routing, else edges, parallel edges and explicit Next/goto routing</h3>
|
|
542
|
+
<table>
|
|
543
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
544
|
+
<tr><td>E1</td><td>string edges keep the v1.0 meaning: unconditional fan-out</td><td class="muted">Typed edges & routing</td><td>0.24 ms</td></tr><tr><td>E2</td><td>result matches by deep equality and only the first matching edge fires</td><td class="muted">Typed edges & routing</td><td>0.41 ms</td></tr><tr><td>E3</td><td>deep equality matches nested objects regardless of key order</td><td class="muted">Typed edges & routing</td><td>0.23 ms</td></tr><tr><td>E4</td><td>result: NaN matches a NaN output (Object.is semantics)</td><td class="muted">Typed edges & routing</td><td>0.22 ms</td></tr><tr><td>E5</td><td>result: undefined matches an undefined output (presence, not truthiness)</td><td class="muted">Typed edges & routing</td><td>0.21 ms</td></tr><tr><td>E6</td><td>test predicate routes the activation</td><td class="muted">Typed edges & routing</td><td>0.18 ms</td></tr><tr><td>E7</td><td>two matching conditionals: declaration order wins</td><td class="muted">Typed edges & routing</td><td>0.17 ms</td></tr><tr><td>E8</td><td>result + test on one edge must both pass (AND)</td><td class="muted">Typed edges & routing</td><td>0.23 ms</td></tr><tr><td>E9</td><td>the else edge (no matcher) fires when nothing earlier matched</td><td class="muted">Typed edges & routing</td><td>0.19 ms</td></tr><tr><td>E10</td><td>no match is silent: nothing is scheduled, no routing error is recorded</td><td class="muted">Typed edges & routing</td><td>0.27 ms</td></tr><tr><td>E11</td><td>parallel edges fire alongside the winning conditional</td><td class="muted">Typed edges & routing</td><td>0.22 ms</td></tr><tr><td>E12</td><td>a parallel edge is never blocked, even after a conditional match</td><td class="muted">Typed edges & routing</td><td>0.24 ms</td></tr><tr><td>E13</td><td>a parallel edge with a matcher is still unconditional (matcher ignored, lint warns)</td><td class="muted">Typed edges & routing</td><td>0.25 ms</td></tr><tr><td>E14</td><td>returning new Next(target, value) routes and successors see the unwrapped value</td><td class="muted">Typed edges & routing</td><td>0.25 ms</td></tr><tr><td>E15</td><td>context.goto(target) + return value routes for void/imperative nodes</td><td class="muted">Typed edges & routing</td><td>0.16 ms</td></tr><tr><td>E16</td><td>a void node can route with goto alone</td><td class="muted">Typed edges & routing</td><td>0.2 ms</td></tr><tr><td>E17</td><td>an explicit route replaces the whole edge list, parallel edges included</td><td class="muted">Typed edges & routing</td><td>0.2 ms</td></tr><tr><td>E18</td><td>return new Next wins over context.goto when both are used</td><td class="muted">Typed edges & routing</td><td>0.15 ms</td></tr><tr><td>E19</td><td>goto works per attempt: the route is taken by the successful attempt</td><td class="muted">Typed edges & routing</td><td>5.6 ms</td></tr><tr><td>E20</td><td>routing to an unknown node records INVALID_GOTO_TARGET and schedules nothing</td><td class="muted">Typed edges & routing</td><td>0.45 ms</td></tr><tr><td>E21</td><td>new Next with an empty target throws INVALID_NEXT_TARGET immediately</td><td class="muted">Typed edges & routing</td><td>0.06 ms</td></tr><tr><td>E22</td><td>a terminal node ignores its edges and its routing, and lint warns about it</td><td class="muted">Typed edges & routing</td><td>0.22 ms</td></tr><tr><td>E23</td><td>lint flags an exclusive edge declared after an else edge as unreachable</td><td class="muted">Typed edges & routing</td><td>0.34 ms</td></tr><tr><td>E24</td><td>malformed edge entries are rejected at construction time</td><td class="muted">Typed edges & routing</td><td>0.41 ms</td></tr><tr><td>E25</td><td>the a → b/c/d/e/f picture runs as ONE execution — the router is no longer needed</td><td class="muted">Typed edges & routing</td><td>11.8 ms</td></tr><tr><td>E26</td><td>lint is clean for the payoff graph (routes declared, no dead edges)</td><td class="muted">Typed edges & routing</td><td>0.44 ms</td></tr>
|
|
545
|
+
</table>
|
|
546
|
+
<h3>28 REGISTRY cases — the function registry: run/test by name, lazy resolution, UNKNOWN_FUNCTION, fingerprints</h3>
|
|
547
|
+
<table>
|
|
548
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
549
|
+
<tr><td>R1</td><td>a node whose run is a registered NAME executes that function</td><td class="muted">Function registry</td><td>0.67 ms</td></tr><tr><td>R2</td><td>a graph-local function overrides the engine's shared entry</td><td class="muted">Function registry</td><td>0.45 ms</td></tr><tr><td>R3</td><td>graph-local functions work with no engine registry at all</td><td class="muted">Function registry</td><td>0.2 ms</td></tr><tr><td>R4</td><td>registerFunction() after construction is honoured (resolution is lazy)</td><td class="muted">Function registry</td><td>0.26 ms</td></tr><tr><td>R5</td><td>inline functions and registered names coexist in one graph</td><td class="muted">Function registry</td><td>0.24 ms</td></tr><tr><td>R6</td><td>a registered node function receives a full NodeContext</td><td class="muted">Function registry</td><td>0.24 ms</td></tr><tr><td>R7</td><td>a registered async function is awaited</td><td class="muted">Function registry</td><td>5.47 ms</td></tr><tr><td>R8</td><td>a registered node can route explicitly with Next and with context.goto</td><td class="muted">Function registry</td><td>0.67 ms</td></tr><tr><td>R9</td><td>timeouts and retries apply to registered functions exactly as to inline ones</td><td class="muted">Function registry</td><td>21.6 ms</td></tr><tr><td>R10</td><td>a missing run name records UNKNOWN_FUNCTION (unhandled) and schedules nothing</td><td class="muted">Function registry</td><td>0.48 ms</td></tr><tr><td>R11</td><td>a missing run name is PERMANENT: no retry, no onThrow, no fallback</td><td class="muted">Function registry</td><td>0.26 ms</td></tr><tr><td>R12</td><td>a missing run name ignores FALLBACK policy as well</td><td class="muted">Function registry</td><td>0.19 ms</td></tr><tr><td>R13</td><td>registering the missing name mid-run lets the next activation succeed</td><td class="muted">Function registry</td><td>0.28 ms</td></tr><tr><td>R14</td><td>a named edge test decides the branch, and result + test still AND</td><td class="muted">Function registry</td><td>0.35 ms</td></tr><tr><td>R15</td><td>inline and named tests mix in one chain, in declaration order</td><td class="muted">Function registry</td><td>0.28 ms</td></tr><tr><td>R16</td><td>an unresolvable edge test never matches, is recorded once, and lets the else edge run</td><td class="muted">Function registry</td><td>0.3 ms</td></tr><tr><td>R17</td><td>a repeated evaluation reports a missing test only once (retry path)</td><td class="muted">Function registry</td><td>1.65 ms</td></tr><tr><td>R18</td><td>lint treats a NAMED test as conditional — no false UNREACHABLE_EDGE</td><td class="muted">Function registry</td><td>0.3 ms</td></tr><tr><td>R19</td><td>a PARALLEL edge with a named test still warns PARALLEL_EDGE_MATCHER_IGNORED</td><td class="muted">Function registry</td><td>0.27 ms</td></tr><tr><td>R20</td><td>graph.ready and the report carry { fingerprint, names }; both are absent without a registry</td><td class="muted">Function registry</td><td>0.4 ms</td></tr><tr><td>R21</td><td>every checkpoint carries the registry identity</td><td class="muted">Function registry</td><td>0.35 ms</td></tr><tr><td>R22</td><td>FunctionRegistry: register/extend/has/get/names/snapshot stay consistent</td><td class="muted">Function registry</td><td>0.18 ms</td></tr><tr><td>R23</td><td>the fingerprint is stable, order-independent, and source-sensitive</td><td class="muted">Function registry</td><td>0.19 ms</td></tr><tr><td>R24</td><td>invalid registrations fail immediately</td><td class="muted">Function registry</td><td>0.16 ms</td></tr><tr><td>R25</td><td>malformed run values and graph tables are rejected at construction</td><td class="muted">Function registry</td><td>0.2 ms</td></tr><tr><td>R26</td><td>nodeFunctions()/edgeTests() restore per-signature inference</td><td class="muted">Function registry</td><td>0.28 ms</td></tr><tr><td>R27</td><td>the report stays JSON-serializable with a registry configured</td><td class="muted">Function registry</td><td>0.31 ms</td></tr><tr><td>R28</td><td>the UNKNOWN_FUNCTION record is self-describing</td><td class="muted">Function registry</td><td>0.27 ms</td></tr>
|
|
550
|
+
</table>
|
|
551
|
+
<h3>19 JSON cases — graph data files: parsing a document into a definition, total validation, engine from JSON</h3>
|
|
552
|
+
<table>
|
|
553
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
554
|
+
<tr><td>G1</td><td>a valid document parses into a GraphDefinition (string and object input agree)</td><td class="muted">Graph JSON loader</td><td>1.22 ms</td></tr><tr><td>G2</td><td>node ids default to their keys, and a mismatching explicit id is an issue</td><td class="muted">Graph JSON loader</td><td>0.29 ms</td></tr><tr><td>G3</td><td>deep-equality results, named tests and parallel flags survive the round trip</td><td class="muted">Graph JSON loader</td><td>0.14 ms</td></tr><tr><td>G4</td><td>createEngineFromJSON runs the data file and reports the registry fingerprint</td><td class="muted">Graph JSON loader</td><td>0.56 ms</td></tr><tr><td>G5</td><td>a named test in the document routes via the supplied registry</td><td class="muted">Graph JSON loader</td><td>0.33 ms</td></tr><tr><td>G6</td><td>a data file with an unknown name runs and fails with UNKNOWN_FUNCTION</td><td class="muted">Graph JSON loader</td><td>0.57 ms</td></tr><tr><td>G7</td><td>the parsed definition is accepted by the engine unchanged</td><td class="muted">Graph JSON loader</td><td>0.36 ms</td></tr><tr><td>G8</td><td>invalid JSON text is a single, clear GraphJSONError</td><td class="muted">Graph JSON loader</td><td>0.12 ms</td></tr><tr><td>G9</td><td>a non-object document is rejected with one issue</td><td class="muted">Graph JSON loader</td><td>0.08 ms</td></tr><tr><td>G10</td><td>unknown properties are rejected at every level</td><td class="muted">Graph JSON loader</td><td>0.18 ms</td></tr><tr><td>G11</td><td>functions cannot live in the document — the issue points at the engine options</td><td class="muted">Graph JSON loader</td><td>0.11 ms</td></tr><tr><td>G12</td><td>dangling references are reported with their paths</td><td class="muted">Graph JSON loader</td><td>0.13 ms</td></tr><tr><td>G13</td><td>malformed edges are rejected entry by entry</td><td class="muted">Graph JSON loader</td><td>0.19 ms</td></tr><tr><td>G14</td><td>invalid scalars, policies and retry blocks are rejected</td><td class="muted">Graph JSON loader</td><td>0.19 ms</td></tr><tr><td>G15</td><td>EVERY issue is collected — one throw carries them all</td><td class="muted">Graph JSON loader</td><td>0.18 ms</td></tr><tr><td>G16</td><td>isGraphJSON() is a cheap shape probe, not a validator</td><td class="muted">Graph JSON loader</td><td>0.13 ms</td></tr><tr><td>G17</td><td>an in-memory object may pass real functions through (escape hatch)</td><td class="muted">Graph JSON loader</td><td>0.24 ms</td></tr><tr><td>G18</td><td>a parsed document with dangling ids is still caught by the engine if it is hand-edited</td><td class="muted">Graph JSON loader</td><td>0.17 ms</td></tr><tr><td>G19</td><td>the loader example document is valid (regression: the shipped .json file)</td><td class="muted">Graph JSON loader</td><td>0.53 ms</td></tr>
|
|
555
|
+
</table>
|
|
556
|
+
<h3>26 SCRIPTS cases — script loading: exported and self-registered functions, format detection, process-global namespace freeze</h3>
|
|
557
|
+
<table>
|
|
558
|
+
<tr><th>#</th><th>Case</th><th>Area</th><th>Time</th></tr>
|
|
559
|
+
<tr><td>S1</td><td>a .cjs script is required and its export table becomes the registry</td><td class="muted">Script loading</td><td>1.62 ms</td></tr><tr><td>S2</td><td>an .mjs script is imported as an ES module</td><td class="muted">Script loading</td><td>5.98 ms</td></tr><tr><td>S3</td><td>a .js script with ESM syntax is detected as ESM; without it, as CommonJS</td><td class="muted">Script loading</td><td>2.16 ms</td></tr><tr><td>S4</td><td>an explicit format is honoured and never retried in the other format</td><td class="muted">Script loading</td><td>4.02 ms</td></tr><tr><td>S5</td><td>inline CommonJS source runs with a real require and module</td><td class="muted">Script loading</td><td>0.44 ms</td></tr><tr><td>S6</td><td>inline ESM source is evaluated from a data URL</td><td class="muted">Script loading</td><td>0.69 ms</td></tr><tr><td>S7</td><td>URL scripts are fetched and evaluated (CJS by default, ESM by hint)</td><td class="muted">Script loading</td><td>0.83 ms</td></tr><tr><td>S8</td><td>a script can register itself through globalThis.GraphEngine</td><td class="muted">Script loading</td><td>0.65 ms</td></tr><tr><td>S9</td><td>the realm is restored after the load — the engine global does not leak</td><td class="muted">Script loading</td><td>0.83 ms</td></tr><tr><td>S10</td><td>a script can both self-register and export; both land in the namespace</td><td class="muted">Script loading</td><td>0.84 ms</td></tr><tr><td>S11</td><td>the declared namespace must match what the script registers</td><td class="muted">Script loading</td><td>0.31 ms</td></tr><tr><td>S12</td><td>a registration error from inside the script surfaces unwrapped</td><td class="muted">Script loading</td><td>0.38 ms</td></tr><tr><td>S13</td><td>a namespace can be claimed only once per process (exports path)</td><td class="muted">Script loading</td><td>0.67 ms</td></tr><tr><td>S14</td><td>a self-registering script throws on the duplicate claim FROM INSIDE the script</td><td class="muted">Script loading</td><td>0.46 ms</td></tr><tr><td>S15</td><td>a claim made before a crashing script survives; the load still fails</td><td class="muted">Script loading</td><td>0.99 ms</td></tr><tr><td>S16</td><td>a script that throws is not replayed in the other format</td><td class="muted">Script loading</td><td>0.43 ms</td></tr><tr><td>S17</td><td>two scripts providing the same name collide; override is opt-in</td><td class="muted">Script loading</td><td>0.73 ms</td></tr><tr><td>S18</td><td>script declarations are validated, with JSON paths</td><td class="muted">Script loading</td><td>0.32 ms</td></tr><tr><td>S19</td><td>the same namespace twice in one document is a parse issue</td><td class="muted">Script loading</td><td>0.1 ms</td></tr><tr><td>S20</td><td>a scripted document still parses with the v1.4 entry point</td><td class="muted">Script loading</td><td>0.12 ms</td></tr><tr><td>S21</td><td>the document is validated BEFORE any script executes</td><td class="muted">Script loading</td><td>0.14 ms</td></tr><tr><td>S22</td><td>a missing file, a crashing script and a function-less script fail clearly</td><td class="muted">Script loading</td><td>0.65 ms</td></tr><tr><td>S23</td><td>a scripted document runs: the script provides the node and edge functions</td><td class="muted">Script loading</td><td>0.65 ms</td></tr><tr><td>S24</td><td>a script's own sibling requires resolve from the script's directory</td><td class="muted">Script loading</td><td>0.56 ms</td></tr><tr><td>S25</td><td>inline scripts compose with path scripts in one document</td><td class="muted">Script loading</td><td>0.43 ms</td></tr><tr><td>S26</td><td>the loaded table is frozen and the engine can be built from it directly</td><td class="muted">Script loading</td><td>0.46 ms</td></tr>
|
|
560
|
+
</table>
|
|
561
|
+
|
|
562
|
+
<h2>All test results</h2>
|
|
563
|
+
<div class="toolbar">
|
|
564
|
+
<button class="btn active" data-filter="all">All (282)</button>
|
|
565
|
+
<button class="btn" data-filter="unit">UNIT (100)</button><button class="btn" data-filter="integration">COMPLEX (20)</button><button class="btn" data-filter="async">ASYNC (20)</button><button class="btn" data-filter="upgrade">UPGRADE (19)</button><button class="btn" data-filter="conformance">CONFORMANCE (11)</button><button class="btn" data-filter="lint">LINT (13)</button><button class="btn" data-filter="edges">EDGES (26)</button><button class="btn" data-filter="registry">REGISTRY (28)</button><button class="btn" data-filter="graphjson">JSON (19)</button><button class="btn" data-filter="scripts">SCRIPTS (26)</button>
|
|
566
|
+
<button class="btn" data-filter="failed">Failed (0)</button>
|
|
567
|
+
<button class="btn" data-filter="finding">Findings (56)</button>
|
|
568
|
+
<input type="search" id="q" placeholder="Search id, category, test name…"/>
|
|
569
|
+
</div>
|
|
570
|
+
<div id="rows">
|
|
571
|
+
|
|
572
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u1 graph validation throws graphvalidationerror when graph.id is empty ">
|
|
573
|
+
<summary>
|
|
574
|
+
<span class="pill passed">PASS</span>
|
|
575
|
+
<span class="id">U1</span>
|
|
576
|
+
<span class="cat">Graph validation</span>
|
|
577
|
+
<span class="name">throws GraphValidationError when graph.id is empty</span>
|
|
578
|
+
|
|
579
|
+
<span class="ms">2.91 ms</span>
|
|
580
|
+
</summary>
|
|
581
|
+
<div class="detail muted">No additional observations.</div>
|
|
582
|
+
</details>
|
|
583
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u2 graph validation throws when graph.id is only whitespace ">
|
|
584
|
+
<summary>
|
|
585
|
+
<span class="pill passed">PASS</span>
|
|
586
|
+
<span class="id">U2</span>
|
|
587
|
+
<span class="cat">Graph validation</span>
|
|
588
|
+
<span class="name">throws when graph.id is only whitespace</span>
|
|
589
|
+
|
|
590
|
+
<span class="ms">0.11 ms</span>
|
|
591
|
+
</summary>
|
|
592
|
+
<div class="detail muted">No additional observations.</div>
|
|
593
|
+
</details>
|
|
594
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u3 graph validation throws when graph.version is empty ">
|
|
595
|
+
<summary>
|
|
596
|
+
<span class="pill passed">PASS</span>
|
|
597
|
+
<span class="id">U3</span>
|
|
598
|
+
<span class="cat">Graph validation</span>
|
|
599
|
+
<span class="name">throws when graph.version is empty</span>
|
|
600
|
+
|
|
601
|
+
<span class="ms">0.08 ms</span>
|
|
602
|
+
</summary>
|
|
603
|
+
<div class="detail muted">No additional observations.</div>
|
|
604
|
+
</details>
|
|
605
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u4 graph validation throws when there are no entry nodes ">
|
|
606
|
+
<summary>
|
|
607
|
+
<span class="pill passed">PASS</span>
|
|
608
|
+
<span class="id">U4</span>
|
|
609
|
+
<span class="cat">Graph validation</span>
|
|
610
|
+
<span class="name">throws when there are no entry nodes</span>
|
|
611
|
+
|
|
612
|
+
<span class="ms">0.07 ms</span>
|
|
613
|
+
</summary>
|
|
614
|
+
<div class="detail muted">No additional observations.</div>
|
|
615
|
+
</details>
|
|
616
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u5 graph validation throws when there are no terminal nodes ">
|
|
617
|
+
<summary>
|
|
618
|
+
<span class="pill passed">PASS</span>
|
|
619
|
+
<span class="id">U5</span>
|
|
620
|
+
<span class="cat">Graph validation</span>
|
|
621
|
+
<span class="name">throws when there are no terminal nodes</span>
|
|
622
|
+
|
|
623
|
+
<span class="ms">0.07 ms</span>
|
|
624
|
+
</summary>
|
|
625
|
+
<div class="detail muted">No additional observations.</div>
|
|
626
|
+
</details>
|
|
627
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u6 graph validation throws when a node key does not match node.id ">
|
|
628
|
+
<summary>
|
|
629
|
+
<span class="pill passed">PASS</span>
|
|
630
|
+
<span class="id">U6</span>
|
|
631
|
+
<span class="cat">Graph validation</span>
|
|
632
|
+
<span class="name">throws when a node key does not match Node.id</span>
|
|
633
|
+
|
|
634
|
+
<span class="ms">0.09 ms</span>
|
|
635
|
+
</summary>
|
|
636
|
+
<div class="detail muted">No additional observations.</div>
|
|
637
|
+
</details>
|
|
638
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u7 graph validation throws when next references an unknown node ">
|
|
639
|
+
<summary>
|
|
640
|
+
<span class="pill passed">PASS</span>
|
|
641
|
+
<span class="id">U7</span>
|
|
642
|
+
<span class="cat">Graph validation</span>
|
|
643
|
+
<span class="name">throws when next references an unknown node</span>
|
|
644
|
+
|
|
645
|
+
<span class="ms">0.09 ms</span>
|
|
646
|
+
</summary>
|
|
647
|
+
<div class="detail muted">No additional observations.</div>
|
|
648
|
+
</details>
|
|
649
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u8 graph validation throws when onthrow references an unknown node ">
|
|
650
|
+
<summary>
|
|
651
|
+
<span class="pill passed">PASS</span>
|
|
652
|
+
<span class="id">U8</span>
|
|
653
|
+
<span class="cat">Graph validation</span>
|
|
654
|
+
<span class="name">throws when onThrow references an unknown node</span>
|
|
655
|
+
|
|
656
|
+
<span class="ms">0.08 ms</span>
|
|
657
|
+
</summary>
|
|
658
|
+
<div class="detail muted">No additional observations.</div>
|
|
659
|
+
</details>
|
|
660
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u9 graph validation throws when node timeoutms is zero ">
|
|
661
|
+
<summary>
|
|
662
|
+
<span class="pill passed">PASS</span>
|
|
663
|
+
<span class="id">U9</span>
|
|
664
|
+
<span class="cat">Graph validation</span>
|
|
665
|
+
<span class="name">throws when node timeoutMs is zero</span>
|
|
666
|
+
|
|
667
|
+
<span class="ms">0.17 ms</span>
|
|
668
|
+
</summary>
|
|
669
|
+
<div class="detail muted">No additional observations.</div>
|
|
670
|
+
</details>
|
|
671
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u10 graph validation throws when node timeoutms is negative ">
|
|
672
|
+
<summary>
|
|
673
|
+
<span class="pill passed">PASS</span>
|
|
674
|
+
<span class="id">U10</span>
|
|
675
|
+
<span class="cat">Graph validation</span>
|
|
676
|
+
<span class="name">throws when node timeoutMs is negative</span>
|
|
677
|
+
|
|
678
|
+
<span class="ms">0.19 ms</span>
|
|
679
|
+
</summary>
|
|
680
|
+
<div class="detail muted">No additional observations.</div>
|
|
681
|
+
</details>
|
|
682
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u11 graph validation throws when retry.maxattempts is not an integer ">
|
|
683
|
+
<summary>
|
|
684
|
+
<span class="pill passed">PASS</span>
|
|
685
|
+
<span class="id">U11</span>
|
|
686
|
+
<span class="cat">Graph validation</span>
|
|
687
|
+
<span class="name">throws when retry.maxAttempts is not an integer</span>
|
|
688
|
+
|
|
689
|
+
<span class="ms">0.15 ms</span>
|
|
690
|
+
</summary>
|
|
691
|
+
<div class="detail muted">No additional observations.</div>
|
|
692
|
+
</details>
|
|
693
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u12 graph validation throws when entry or terminal node is unknown ">
|
|
694
|
+
<summary>
|
|
695
|
+
<span class="pill passed">PASS</span>
|
|
696
|
+
<span class="id">U12</span>
|
|
697
|
+
<span class="cat">Graph validation</span>
|
|
698
|
+
<span class="name">throws when entry or terminal node is unknown</span>
|
|
699
|
+
|
|
700
|
+
<span class="ms">0.13 ms</span>
|
|
701
|
+
</summary>
|
|
702
|
+
<div class="detail muted">No additional observations.</div>
|
|
703
|
+
</details>
|
|
704
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u13 error classes & utilities automategrapherror carries message, code and details ">
|
|
705
|
+
<summary>
|
|
706
|
+
<span class="pill passed">PASS</span>
|
|
707
|
+
<span class="id">U13</span>
|
|
708
|
+
<span class="cat">Error classes & utilities</span>
|
|
709
|
+
<span class="name">AutomateGraphError carries message, code and details</span>
|
|
710
|
+
|
|
711
|
+
<span class="ms">0.1 ms</span>
|
|
712
|
+
</summary>
|
|
713
|
+
<div class="detail muted">No additional observations.</div>
|
|
714
|
+
</details>
|
|
715
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u14 error classes & utilities graphvalidationerror uses the graph_validation_error code ">
|
|
716
|
+
<summary>
|
|
717
|
+
<span class="pill passed">PASS</span>
|
|
718
|
+
<span class="id">U14</span>
|
|
719
|
+
<span class="cat">Error classes & utilities</span>
|
|
720
|
+
<span class="name">GraphValidationError uses the GRAPH_VALIDATION_ERROR code</span>
|
|
721
|
+
|
|
722
|
+
<span class="ms">0.05 ms</span>
|
|
723
|
+
</summary>
|
|
724
|
+
<div class="detail muted">No additional observations.</div>
|
|
725
|
+
</details>
|
|
726
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u15 error classes & utilities timeouterror composes a readable message and details ">
|
|
727
|
+
<summary>
|
|
728
|
+
<span class="pill passed">PASS</span>
|
|
729
|
+
<span class="id">U15</span>
|
|
730
|
+
<span class="cat">Error classes & utilities</span>
|
|
731
|
+
<span class="name">TimeoutError composes a readable message and details</span>
|
|
732
|
+
|
|
733
|
+
<span class="ms">0.08 ms</span>
|
|
734
|
+
</summary>
|
|
735
|
+
<div class="detail muted">No additional observations.</div>
|
|
736
|
+
</details>
|
|
737
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u16 error classes & utilities plugininitializationerror reports the plugin id and keeps the cause ">
|
|
738
|
+
<summary>
|
|
739
|
+
<span class="pill passed">PASS</span>
|
|
740
|
+
<span class="id">U16</span>
|
|
741
|
+
<span class="cat">Error classes & utilities</span>
|
|
742
|
+
<span class="name">PluginInitializationError reports the plugin id and keeps the cause</span>
|
|
743
|
+
|
|
744
|
+
<span class="ms">0.07 ms</span>
|
|
745
|
+
</summary>
|
|
746
|
+
<div class="detail muted">No additional observations.</div>
|
|
747
|
+
</details>
|
|
748
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u17 error classes & utilities inheritance chain: timeouterror -> automategrapherror -> error ">
|
|
749
|
+
<summary>
|
|
750
|
+
<span class="pill passed">PASS</span>
|
|
751
|
+
<span class="id">U17</span>
|
|
752
|
+
<span class="cat">Error classes & utilities</span>
|
|
753
|
+
<span class="name">inheritance chain: TimeoutError -> AutomateGraphError -> Error</span>
|
|
754
|
+
|
|
755
|
+
<span class="ms">0.04 ms</span>
|
|
756
|
+
</summary>
|
|
757
|
+
<div class="detail muted">No additional observations.</div>
|
|
758
|
+
</details>
|
|
759
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u18 error classes & utilities plugininitializationerror is an automategrapherror ">
|
|
760
|
+
<summary>
|
|
761
|
+
<span class="pill passed">PASS</span>
|
|
762
|
+
<span class="id">U18</span>
|
|
763
|
+
<span class="cat">Error classes & utilities</span>
|
|
764
|
+
<span class="name">PluginInitializationError is an AutomateGraphError</span>
|
|
765
|
+
|
|
766
|
+
<span class="ms">0.11 ms</span>
|
|
767
|
+
</summary>
|
|
768
|
+
<div class="detail muted">No additional observations.</div>
|
|
769
|
+
</details>
|
|
770
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u19 error classes & utilities automategrapherror is not a graphvalidationerror (distinct subclass) ">
|
|
771
|
+
<summary>
|
|
772
|
+
<span class="pill passed">PASS</span>
|
|
773
|
+
<span class="id">U19</span>
|
|
774
|
+
<span class="cat">Error classes & utilities</span>
|
|
775
|
+
<span class="name">AutomateGraphError is not a GraphValidationError (distinct subclass)</span>
|
|
776
|
+
|
|
777
|
+
<span class="ms">0.04 ms</span>
|
|
778
|
+
</summary>
|
|
779
|
+
<div class="detail muted">No additional observations.</div>
|
|
780
|
+
</details>
|
|
781
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u20 error classes & utilities automategrapherror allows optional details to be omitted ">
|
|
782
|
+
<summary>
|
|
783
|
+
<span class="pill passed">PASS</span>
|
|
784
|
+
<span class="id">U20</span>
|
|
785
|
+
<span class="cat">Error classes & utilities</span>
|
|
786
|
+
<span class="name">AutomateGraphError allows optional details to be omitted</span>
|
|
787
|
+
|
|
788
|
+
<span class="ms">0.03 ms</span>
|
|
789
|
+
</summary>
|
|
790
|
+
<div class="detail muted">No additional observations.</div>
|
|
791
|
+
</details>
|
|
792
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u21 error classes & utilities error classes expose stable constructor.name values ">
|
|
793
|
+
<summary>
|
|
794
|
+
<span class="pill passed">PASS</span>
|
|
795
|
+
<span class="id">U21</span>
|
|
796
|
+
<span class="cat">Error classes & utilities</span>
|
|
797
|
+
<span class="name">Error classes expose stable constructor.name values</span>
|
|
798
|
+
|
|
799
|
+
<span class="ms">0.04 ms</span>
|
|
800
|
+
</summary>
|
|
801
|
+
<div class="detail muted">No additional observations.</div>
|
|
802
|
+
</details>
|
|
803
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u22 utilities engine executionid is a stable 36-char uuid-ish string ">
|
|
804
|
+
<summary>
|
|
805
|
+
<span class="pill passed">PASS</span>
|
|
806
|
+
<span class="id">U22</span>
|
|
807
|
+
<span class="cat">Utilities</span>
|
|
808
|
+
<span class="name">engine executionId is a stable 36-char UUID-ish string</span>
|
|
809
|
+
|
|
810
|
+
<span class="ms">0.32 ms</span>
|
|
811
|
+
</summary>
|
|
812
|
+
<div class="detail muted">No additional observations.</div>
|
|
813
|
+
</details>
|
|
814
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u23 utilities executionids are unique across engines ">
|
|
815
|
+
<summary>
|
|
816
|
+
<span class="pill passed">PASS</span>
|
|
817
|
+
<span class="id">U23</span>
|
|
818
|
+
<span class="cat">Utilities</span>
|
|
819
|
+
<span class="name">executionIds are unique across engines</span>
|
|
820
|
+
|
|
821
|
+
<span class="ms">0.88 ms</span>
|
|
822
|
+
</summary>
|
|
823
|
+
<div class="detail muted">No additional observations.</div>
|
|
824
|
+
</details>
|
|
825
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u24 utilities report.startedat is an iso-8601 timestamp ">
|
|
826
|
+
<summary>
|
|
827
|
+
<span class="pill passed">PASS</span>
|
|
828
|
+
<span class="id">U24</span>
|
|
829
|
+
<span class="cat">Utilities</span>
|
|
830
|
+
<span class="name">report.startedAt is an ISO-8601 timestamp</span>
|
|
831
|
+
|
|
832
|
+
<span class="ms">1.28 ms</span>
|
|
833
|
+
</summary>
|
|
834
|
+
<div class="detail muted">No additional observations.</div>
|
|
835
|
+
</details>
|
|
836
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u25 utilities report.finishedat >= report.startedat ">
|
|
837
|
+
<summary>
|
|
838
|
+
<span class="pill passed">PASS</span>
|
|
839
|
+
<span class="id">U25</span>
|
|
840
|
+
<span class="cat">Utilities</span>
|
|
841
|
+
<span class="name">report.finishedAt >= report.startedAt</span>
|
|
842
|
+
|
|
843
|
+
<span class="ms">0.17 ms</span>
|
|
844
|
+
</summary>
|
|
845
|
+
<div class="detail muted">No additional observations.</div>
|
|
846
|
+
</details>
|
|
847
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u26 utilities node result startedat <= finishedat ">
|
|
848
|
+
<summary>
|
|
849
|
+
<span class="pill passed">PASS</span>
|
|
850
|
+
<span class="id">U26</span>
|
|
851
|
+
<span class="cat">Utilities</span>
|
|
852
|
+
<span class="name">node result startedAt <= finishedAt</span>
|
|
853
|
+
|
|
854
|
+
<span class="ms">0.15 ms</span>
|
|
855
|
+
</summary>
|
|
856
|
+
<div class="detail muted">No additional observations.</div>
|
|
857
|
+
</details>
|
|
858
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u27 utilities error records carry iso timestamps ">
|
|
859
|
+
<summary>
|
|
860
|
+
<span class="pill passed">PASS</span>
|
|
861
|
+
<span class="id">U27</span>
|
|
862
|
+
<span class="cat">Utilities</span>
|
|
863
|
+
<span class="name">error records carry ISO timestamps</span>
|
|
864
|
+
|
|
865
|
+
<span class="ms">0.79 ms</span>
|
|
866
|
+
</summary>
|
|
867
|
+
<div class="detail muted">No additional observations.</div>
|
|
868
|
+
</details>
|
|
869
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u28 utilities string throws are converted to error instances ">
|
|
870
|
+
<summary>
|
|
871
|
+
<span class="pill passed">PASS</span>
|
|
872
|
+
<span class="id">U28</span>
|
|
873
|
+
<span class="cat">Utilities</span>
|
|
874
|
+
<span class="name">string throws are converted to Error instances</span>
|
|
875
|
+
|
|
876
|
+
<span class="ms">0.47 ms</span>
|
|
877
|
+
</summary>
|
|
878
|
+
<div class="detail muted">No additional observations.</div>
|
|
879
|
+
</details>
|
|
880
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u29 utilities throwing a non-error object stringifies via toerror ">
|
|
881
|
+
<summary>
|
|
882
|
+
<span class="pill passed">PASS</span>
|
|
883
|
+
<span class="id">U29</span>
|
|
884
|
+
<span class="cat">Utilities</span>
|
|
885
|
+
<span class="name">throwing a non-Error object stringifies via toError</span>
|
|
886
|
+
|
|
887
|
+
<span class="ms">0.25 ms</span>
|
|
888
|
+
</summary>
|
|
889
|
+
<div class="detail muted">No additional observations.</div>
|
|
890
|
+
</details>
|
|
891
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u30 utilities error records expose a stack trace for real errors ">
|
|
892
|
+
<summary>
|
|
893
|
+
<span class="pill passed">PASS</span>
|
|
894
|
+
<span class="id">U30</span>
|
|
895
|
+
<span class="cat">Utilities</span>
|
|
896
|
+
<span class="name">error records expose a stack trace for real errors</span>
|
|
897
|
+
|
|
898
|
+
<span class="ms">0.21 ms</span>
|
|
899
|
+
</summary>
|
|
900
|
+
<div class="detail muted">No additional observations.</div>
|
|
901
|
+
</details>
|
|
902
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u31 utilities graph id/version of the report mirror the definition ">
|
|
903
|
+
<summary>
|
|
904
|
+
<span class="pill passed">PASS</span>
|
|
905
|
+
<span class="id">U31</span>
|
|
906
|
+
<span class="cat">Utilities</span>
|
|
907
|
+
<span class="name">graph id/version of the report mirror the definition</span>
|
|
908
|
+
|
|
909
|
+
<span class="ms">0.22 ms</span>
|
|
910
|
+
</summary>
|
|
911
|
+
<div class="detail muted">No additional observations.</div>
|
|
912
|
+
</details>
|
|
913
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u32 eventbus emit with no listeners resolves ">
|
|
914
|
+
<summary>
|
|
915
|
+
<span class="pill passed">PASS</span>
|
|
916
|
+
<span class="id">U32</span>
|
|
917
|
+
<span class="cat">EventBus</span>
|
|
918
|
+
<span class="name">emit with no listeners resolves</span>
|
|
919
|
+
|
|
920
|
+
<span class="ms">0.06 ms</span>
|
|
921
|
+
</summary>
|
|
922
|
+
<div class="detail muted">No additional observations.</div>
|
|
923
|
+
</details>
|
|
924
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u33 eventbus required listeners receive the payload and are awaited ">
|
|
925
|
+
<summary>
|
|
926
|
+
<span class="pill passed">PASS</span>
|
|
927
|
+
<span class="id">U33</span>
|
|
928
|
+
<span class="cat">EventBus</span>
|
|
929
|
+
<span class="name">required listeners receive the payload and are awaited</span>
|
|
930
|
+
|
|
931
|
+
<span class="ms">5.69 ms</span>
|
|
932
|
+
</summary>
|
|
933
|
+
<div class="detail muted">No additional observations.</div>
|
|
934
|
+
</details>
|
|
935
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u34 eventbus required listeners run in registration order ">
|
|
936
|
+
<summary>
|
|
937
|
+
<span class="pill passed">PASS</span>
|
|
938
|
+
<span class="id">U34</span>
|
|
939
|
+
<span class="cat">EventBus</span>
|
|
940
|
+
<span class="name">required listeners run in registration order</span>
|
|
941
|
+
|
|
942
|
+
<span class="ms">0.15 ms</span>
|
|
943
|
+
</summary>
|
|
944
|
+
<div class="detail muted">No additional observations.</div>
|
|
945
|
+
</details>
|
|
946
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u35 eventbus plain listeners are not awaited — emit resolves first ">
|
|
947
|
+
<summary>
|
|
948
|
+
<span class="pill passed">PASS</span>
|
|
949
|
+
<span class="id">U35</span>
|
|
950
|
+
<span class="cat">EventBus</span>
|
|
951
|
+
<span class="name">plain listeners are NOT awaited — emit resolves first</span>
|
|
952
|
+
|
|
953
|
+
<span class="ms">60.58 ms</span>
|
|
954
|
+
</summary>
|
|
955
|
+
<div class="detail muted">No additional observations.</div>
|
|
956
|
+
</details>
|
|
957
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u36 eventbus unsubscribe stops delivery ">
|
|
958
|
+
<summary>
|
|
959
|
+
<span class="pill passed">PASS</span>
|
|
960
|
+
<span class="id">U36</span>
|
|
961
|
+
<span class="cat">EventBus</span>
|
|
962
|
+
<span class="name">unsubscribe stops delivery</span>
|
|
963
|
+
|
|
964
|
+
<span class="ms">0.22 ms</span>
|
|
965
|
+
</summary>
|
|
966
|
+
<div class="detail muted">No additional observations.</div>
|
|
967
|
+
</details>
|
|
968
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u37 eventbus unsubscribing the last listener removes the event key ">
|
|
969
|
+
<summary>
|
|
970
|
+
<span class="pill passed">PASS</span>
|
|
971
|
+
<span class="id">U37</span>
|
|
972
|
+
<span class="cat">EventBus</span>
|
|
973
|
+
<span class="name">unsubscribing the last listener removes the event key</span>
|
|
974
|
+
|
|
975
|
+
<span class="ms">0.05 ms</span>
|
|
976
|
+
</summary>
|
|
977
|
+
<div class="detail muted">No additional observations.</div>
|
|
978
|
+
</details>
|
|
979
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u38 eventbus duplicate handlers registered as distinct listeners both fire ">
|
|
980
|
+
<summary>
|
|
981
|
+
<span class="pill passed">PASS</span>
|
|
982
|
+
<span class="id">U38</span>
|
|
983
|
+
<span class="cat">EventBus</span>
|
|
984
|
+
<span class="name">duplicate handlers registered as distinct listeners both fire</span>
|
|
985
|
+
|
|
986
|
+
<span class="ms">0.18 ms</span>
|
|
987
|
+
</summary>
|
|
988
|
+
<div class="detail muted">No additional observations.</div>
|
|
989
|
+
</details>
|
|
990
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u39 eventbus a throwing plain listener does not reject emit (isolated) ">
|
|
991
|
+
<summary>
|
|
992
|
+
<span class="pill passed">PASS</span>
|
|
993
|
+
<span class="id">U39</span>
|
|
994
|
+
<span class="cat">EventBus</span>
|
|
995
|
+
<span class="name">a throwing plain listener does not reject emit (isolated)</span>
|
|
996
|
+
|
|
997
|
+
<span class="ms">10.65 ms</span>
|
|
998
|
+
</summary>
|
|
999
|
+
<div class="detail muted">No additional observations.</div>
|
|
1000
|
+
</details>
|
|
1001
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u40 eventbus a failing plain listener is reported through onlog ">
|
|
1002
|
+
<summary>
|
|
1003
|
+
<span class="pill passed">PASS</span>
|
|
1004
|
+
<span class="id">U40</span>
|
|
1005
|
+
<span class="cat">EventBus</span>
|
|
1006
|
+
<span class="name">a failing plain listener is reported through onLog</span>
|
|
1007
|
+
|
|
1008
|
+
<span class="ms">15.53 ms</span>
|
|
1009
|
+
</summary>
|
|
1010
|
+
<div class="detail muted">No additional observations.</div>
|
|
1011
|
+
</details>
|
|
1012
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u41 eventbus a throwing required listener propagates to the emitter ">
|
|
1013
|
+
<summary>
|
|
1014
|
+
<span class="pill passed">PASS</span>
|
|
1015
|
+
<span class="id">U41</span>
|
|
1016
|
+
<span class="cat">EventBus</span>
|
|
1017
|
+
<span class="name">a throwing REQUIRED listener propagates to the emitter</span>
|
|
1018
|
+
|
|
1019
|
+
<span class="ms">0.27 ms</span>
|
|
1020
|
+
</summary>
|
|
1021
|
+
<div class="detail muted">No additional observations.</div>
|
|
1022
|
+
</details>
|
|
1023
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u42 eventbus mixed required/plain: required first, plain afterwards (async) ">
|
|
1024
|
+
<summary>
|
|
1025
|
+
<span class="pill passed">PASS</span>
|
|
1026
|
+
<span class="id">U42</span>
|
|
1027
|
+
<span class="cat">EventBus</span>
|
|
1028
|
+
<span class="name">mixed required/plain: required first, plain afterwards (async)</span>
|
|
1029
|
+
|
|
1030
|
+
<span class="ms">20.58 ms</span>
|
|
1031
|
+
</summary>
|
|
1032
|
+
<div class="detail muted">No additional observations.</div>
|
|
1033
|
+
</details>
|
|
1034
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u43 eventbus clear() removes every listener ">
|
|
1035
|
+
<summary>
|
|
1036
|
+
<span class="pill passed">PASS</span>
|
|
1037
|
+
<span class="id">U43</span>
|
|
1038
|
+
<span class="cat">EventBus</span>
|
|
1039
|
+
<span class="name">clear() removes every listener</span>
|
|
1040
|
+
|
|
1041
|
+
<span class="ms">0.2 ms</span>
|
|
1042
|
+
</summary>
|
|
1043
|
+
<div class="detail muted">No additional observations.</div>
|
|
1044
|
+
</details>
|
|
1045
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u44 inmemorystorage storage advertises a stable id and version ">
|
|
1046
|
+
<summary>
|
|
1047
|
+
<span class="pill passed">PASS</span>
|
|
1048
|
+
<span class="id">U44</span>
|
|
1049
|
+
<span class="cat">InMemoryStorage</span>
|
|
1050
|
+
<span class="name">storage advertises a stable id and version</span>
|
|
1051
|
+
|
|
1052
|
+
<span class="ms">0.04 ms</span>
|
|
1053
|
+
</summary>
|
|
1054
|
+
<div class="detail muted">No additional observations.</div>
|
|
1055
|
+
</details>
|
|
1056
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u45 inmemorystorage load returns null for an unknown executionid ">
|
|
1057
|
+
<summary>
|
|
1058
|
+
<span class="pill passed">PASS</span>
|
|
1059
|
+
<span class="id">U45</span>
|
|
1060
|
+
<span class="cat">InMemoryStorage</span>
|
|
1061
|
+
<span class="name">load returns null for an unknown executionId</span>
|
|
1062
|
+
|
|
1063
|
+
<span class="ms">0.11 ms</span>
|
|
1064
|
+
</summary>
|
|
1065
|
+
<div class="detail muted">No additional observations.</div>
|
|
1066
|
+
</details>
|
|
1067
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u46 inmemorystorage saveatomic then load returns the snapshot ">
|
|
1068
|
+
<summary>
|
|
1069
|
+
<span class="pill passed">PASS</span>
|
|
1070
|
+
<span class="id">U46</span>
|
|
1071
|
+
<span class="cat">InMemoryStorage</span>
|
|
1072
|
+
<span class="name">saveAtomic then load returns the snapshot</span>
|
|
1073
|
+
|
|
1074
|
+
<span class="ms">0.14 ms</span>
|
|
1075
|
+
</summary>
|
|
1076
|
+
<div class="detail muted">No additional observations.</div>
|
|
1077
|
+
</details>
|
|
1078
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u47 inmemorystorage saveatomic deep-copies the incoming snapshot (caller later mutates) ">
|
|
1079
|
+
<summary>
|
|
1080
|
+
<span class="pill passed">PASS</span>
|
|
1081
|
+
<span class="id">U47</span>
|
|
1082
|
+
<span class="cat">InMemoryStorage</span>
|
|
1083
|
+
<span class="name">saveAtomic deep-copies the incoming snapshot (caller later mutates)</span>
|
|
1084
|
+
|
|
1085
|
+
<span class="ms">0.09 ms</span>
|
|
1086
|
+
</summary>
|
|
1087
|
+
<div class="detail muted">No additional observations.</div>
|
|
1088
|
+
</details>
|
|
1089
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u48 inmemorystorage load returns an isolated copy (mutation of the returned object is inert) ">
|
|
1090
|
+
<summary>
|
|
1091
|
+
<span class="pill passed">PASS</span>
|
|
1092
|
+
<span class="id">U48</span>
|
|
1093
|
+
<span class="cat">InMemoryStorage</span>
|
|
1094
|
+
<span class="name">load returns an isolated copy (mutation of the returned object is inert)</span>
|
|
1095
|
+
|
|
1096
|
+
<span class="ms">0.06 ms</span>
|
|
1097
|
+
</summary>
|
|
1098
|
+
<div class="detail muted">No additional observations.</div>
|
|
1099
|
+
</details>
|
|
1100
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u49 inmemorystorage repeated saves replace the previous snapshot ">
|
|
1101
|
+
<summary>
|
|
1102
|
+
<span class="pill passed">PASS</span>
|
|
1103
|
+
<span class="id">U49</span>
|
|
1104
|
+
<span class="cat">InMemoryStorage</span>
|
|
1105
|
+
<span class="name">repeated saves replace the previous snapshot</span>
|
|
1106
|
+
|
|
1107
|
+
<span class="ms">0.07 ms</span>
|
|
1108
|
+
</summary>
|
|
1109
|
+
<div class="detail muted">No additional observations.</div>
|
|
1110
|
+
</details>
|
|
1111
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u50 inmemorystorage snapshots for different executions stay isolated ">
|
|
1112
|
+
<summary>
|
|
1113
|
+
<span class="pill passed">PASS</span>
|
|
1114
|
+
<span class="id">U50</span>
|
|
1115
|
+
<span class="cat">InMemoryStorage</span>
|
|
1116
|
+
<span class="name">snapshots for different executions stay isolated</span>
|
|
1117
|
+
|
|
1118
|
+
<span class="ms">0.08 ms</span>
|
|
1119
|
+
</summary>
|
|
1120
|
+
<div class="detail muted">No additional observations.</div>
|
|
1121
|
+
</details>
|
|
1122
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u51 inmemorystorage concurrent saveatomic calls never interleave partial data ">
|
|
1123
|
+
<summary>
|
|
1124
|
+
<span class="pill passed">PASS</span>
|
|
1125
|
+
<span class="id">U51</span>
|
|
1126
|
+
<span class="cat">InMemoryStorage</span>
|
|
1127
|
+
<span class="name">concurrent saveAtomic calls never interleave partial data</span>
|
|
1128
|
+
|
|
1129
|
+
<span class="ms">0.22 ms</span>
|
|
1130
|
+
</summary>
|
|
1131
|
+
<div class="detail muted">No additional observations.</div>
|
|
1132
|
+
</details>
|
|
1133
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u52 graph freezing getgraphdefinition returns a frozen object ">
|
|
1134
|
+
<summary>
|
|
1135
|
+
<span class="pill passed">PASS</span>
|
|
1136
|
+
<span class="id">U52</span>
|
|
1137
|
+
<span class="cat">Graph freezing</span>
|
|
1138
|
+
<span class="name">getGraphDefinition returns a frozen object</span>
|
|
1139
|
+
|
|
1140
|
+
<span class="ms">0.24 ms</span>
|
|
1141
|
+
</summary>
|
|
1142
|
+
<div class="detail muted">No additional observations.</div>
|
|
1143
|
+
</details>
|
|
1144
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u53 graph freezing entrynodes and terminalnodes arrays are frozen ">
|
|
1145
|
+
<summary>
|
|
1146
|
+
<span class="pill passed">PASS</span>
|
|
1147
|
+
<span class="id">U53</span>
|
|
1148
|
+
<span class="cat">Graph freezing</span>
|
|
1149
|
+
<span class="name">entryNodes and terminalNodes arrays are frozen</span>
|
|
1150
|
+
|
|
1151
|
+
<span class="ms">0.1 ms</span>
|
|
1152
|
+
</summary>
|
|
1153
|
+
<div class="detail muted">No additional observations.</div>
|
|
1154
|
+
</details>
|
|
1155
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u54 graph freezing the nodes record is frozen ">
|
|
1156
|
+
<summary>
|
|
1157
|
+
<span class="pill passed">PASS</span>
|
|
1158
|
+
<span class="id">U54</span>
|
|
1159
|
+
<span class="cat">Graph freezing</span>
|
|
1160
|
+
<span class="name">the nodes record is frozen</span>
|
|
1161
|
+
|
|
1162
|
+
<span class="ms">0.13 ms</span>
|
|
1163
|
+
</summary>
|
|
1164
|
+
<div class="detail muted">No additional observations.</div>
|
|
1165
|
+
</details>
|
|
1166
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u55 graph freezing mutating the definition after construction does not affect the engine ">
|
|
1167
|
+
<summary>
|
|
1168
|
+
<span class="pill passed">PASS</span>
|
|
1169
|
+
<span class="id">U55</span>
|
|
1170
|
+
<span class="cat">Graph freezing</span>
|
|
1171
|
+
<span class="name">mutating the definition after construction does not affect the engine</span>
|
|
1172
|
+
|
|
1173
|
+
<span class="ms">0.45 ms</span>
|
|
1174
|
+
</summary>
|
|
1175
|
+
<div class="detail muted">No additional observations.</div>
|
|
1176
|
+
</details>
|
|
1177
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u56 graph freezing mutating a node's next array after construction is ignored ">
|
|
1178
|
+
<summary>
|
|
1179
|
+
<span class="pill passed">PASS</span>
|
|
1180
|
+
<span class="id">U56</span>
|
|
1181
|
+
<span class="cat">Graph freezing</span>
|
|
1182
|
+
<span class="name">mutating a node's next array after construction is ignored</span>
|
|
1183
|
+
|
|
1184
|
+
<span class="ms">0.32 ms</span>
|
|
1185
|
+
</summary>
|
|
1186
|
+
<div class="detail muted">No additional observations.</div>
|
|
1187
|
+
</details>
|
|
1188
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u57 graph freezing getgraphdefinition is referentially identical across calls ">
|
|
1189
|
+
<summary>
|
|
1190
|
+
<span class="pill passed">PASS</span>
|
|
1191
|
+
<span class="id">U57</span>
|
|
1192
|
+
<span class="cat">Graph freezing</span>
|
|
1193
|
+
<span class="name">getGraphDefinition is referentially identical across calls</span>
|
|
1194
|
+
|
|
1195
|
+
<span class="ms">0.12 ms</span>
|
|
1196
|
+
</summary>
|
|
1197
|
+
<div class="detail muted">No additional observations.</div>
|
|
1198
|
+
</details>
|
|
1199
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u58 graph freezing deep-frozen graphs are accepted (idempotent freezing) ">
|
|
1200
|
+
<summary>
|
|
1201
|
+
<span class="pill passed">PASS</span>
|
|
1202
|
+
<span class="id">U58</span>
|
|
1203
|
+
<span class="cat">Graph freezing</span>
|
|
1204
|
+
<span class="name">deep-frozen graphs are accepted (idempotent freezing)</span>
|
|
1205
|
+
|
|
1206
|
+
<span class="ms">0.29 ms</span>
|
|
1207
|
+
</summary>
|
|
1208
|
+
<div class="detail muted">No additional observations.</div>
|
|
1209
|
+
</details>
|
|
1210
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u59 graph freezing frozen node objects reject mutation at runtime (strict mode) ">
|
|
1211
|
+
<summary>
|
|
1212
|
+
<span class="pill passed">PASS</span>
|
|
1213
|
+
<span class="id">U59</span>
|
|
1214
|
+
<span class="cat">Graph freezing</span>
|
|
1215
|
+
<span class="name">frozen node objects reject mutation at runtime (strict mode)</span>
|
|
1216
|
+
|
|
1217
|
+
<span class="ms">0.1 ms</span>
|
|
1218
|
+
</summary>
|
|
1219
|
+
<div class="detail muted">No additional observations.</div>
|
|
1220
|
+
</details>
|
|
1221
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u60 engine lifecycle getstate() is created before run() ">
|
|
1222
|
+
<summary>
|
|
1223
|
+
<span class="pill passed">PASS</span>
|
|
1224
|
+
<span class="id">U60</span>
|
|
1225
|
+
<span class="cat">Engine lifecycle</span>
|
|
1226
|
+
<span class="name">getState() is CREATED before run()</span>
|
|
1227
|
+
|
|
1228
|
+
<span class="ms">0.08 ms</span>
|
|
1229
|
+
</summary>
|
|
1230
|
+
<div class="detail muted">No additional observations.</div>
|
|
1231
|
+
</details>
|
|
1232
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u61 engine lifecycle calling run() twice throws execution_already_started ">
|
|
1233
|
+
<summary>
|
|
1234
|
+
<span class="pill passed">PASS</span>
|
|
1235
|
+
<span class="id">U61</span>
|
|
1236
|
+
<span class="cat">Engine lifecycle</span>
|
|
1237
|
+
<span class="name">calling run() twice throws EXECUTION_ALREADY_STARTED</span>
|
|
1238
|
+
|
|
1239
|
+
<span class="ms">0.2 ms</span>
|
|
1240
|
+
</summary>
|
|
1241
|
+
<div class="detail muted">No additional observations.</div>
|
|
1242
|
+
</details>
|
|
1243
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u62 engine lifecycle run() returns a promise ">
|
|
1244
|
+
<summary>
|
|
1245
|
+
<span class="pill passed">PASS</span>
|
|
1246
|
+
<span class="id">U62</span>
|
|
1247
|
+
<span class="cat">Engine lifecycle</span>
|
|
1248
|
+
<span class="name">run() returns a Promise</span>
|
|
1249
|
+
|
|
1250
|
+
<span class="ms">0.17 ms</span>
|
|
1251
|
+
</summary>
|
|
1252
|
+
<div class="detail muted">No additional observations.</div>
|
|
1253
|
+
</details>
|
|
1254
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u63 engine lifecycle read-only accessors return defensive copies of errors ">
|
|
1255
|
+
<summary>
|
|
1256
|
+
<span class="pill passed">PASS</span>
|
|
1257
|
+
<span class="id">U63</span>
|
|
1258
|
+
<span class="cat">Engine lifecycle</span>
|
|
1259
|
+
<span class="name">read-only accessors return defensive copies of errors</span>
|
|
1260
|
+
|
|
1261
|
+
<span class="ms">0.24 ms</span>
|
|
1262
|
+
</summary>
|
|
1263
|
+
<div class="detail muted">No additional observations.</div>
|
|
1264
|
+
</details>
|
|
1265
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u64 engine lifecycle read-only accessors return defensive copies of results ">
|
|
1266
|
+
<summary>
|
|
1267
|
+
<span class="pill passed">PASS</span>
|
|
1268
|
+
<span class="id">U64</span>
|
|
1269
|
+
<span class="cat">Engine lifecycle</span>
|
|
1270
|
+
<span class="name">read-only accessors return defensive copies of results</span>
|
|
1271
|
+
|
|
1272
|
+
<span class="ms">0.4 ms</span>
|
|
1273
|
+
</summary>
|
|
1274
|
+
<div class="detail muted">No additional observations.</div>
|
|
1275
|
+
</details>
|
|
1276
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u65 engine lifecycle duplicate plugin ids are rejected with duplicate_plugin ">
|
|
1277
|
+
<summary>
|
|
1278
|
+
<span class="pill passed">PASS</span>
|
|
1279
|
+
<span class="id">U65</span>
|
|
1280
|
+
<span class="cat">Engine lifecycle</span>
|
|
1281
|
+
<span class="name">duplicate plugin ids are rejected with DUPLICATE_PLUGIN</span>
|
|
1282
|
+
|
|
1283
|
+
<span class="ms">0.4 ms</span>
|
|
1284
|
+
</summary>
|
|
1285
|
+
<div class="detail muted">No additional observations.</div>
|
|
1286
|
+
</details>
|
|
1287
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u66 engine lifecycle a plugin reusing the storage id is rejected in the constructor ">
|
|
1288
|
+
<summary>
|
|
1289
|
+
<span class="pill passed">PASS</span>
|
|
1290
|
+
<span class="id">U66</span>
|
|
1291
|
+
<span class="cat">Engine lifecycle</span>
|
|
1292
|
+
<span class="name">a plugin reusing the storage id is rejected in the constructor</span>
|
|
1293
|
+
|
|
1294
|
+
<span class="ms">0.17 ms</span>
|
|
1295
|
+
</summary>
|
|
1296
|
+
<div class="detail muted">No additional observations.</div>
|
|
1297
|
+
</details>
|
|
1298
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u67 engine lifecycle optional plugin failure is tolerated and logged ">
|
|
1299
|
+
<summary>
|
|
1300
|
+
<span class="pill passed">PASS</span>
|
|
1301
|
+
<span class="id">U67</span>
|
|
1302
|
+
<span class="cat">Engine lifecycle</span>
|
|
1303
|
+
<span class="name">optional plugin failure is tolerated and logged</span>
|
|
1304
|
+
|
|
1305
|
+
<span class="ms">0.54 ms</span>
|
|
1306
|
+
</summary>
|
|
1307
|
+
<div class="detail muted">No additional observations.</div>
|
|
1308
|
+
</details>
|
|
1309
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u68 engine lifecycle a required plugin failure rejects the run and shuts down initialized plugins ">
|
|
1310
|
+
<summary>
|
|
1311
|
+
<span class="pill passed">PASS</span>
|
|
1312
|
+
<span class="id">U68</span>
|
|
1313
|
+
<span class="cat">Engine lifecycle</span>
|
|
1314
|
+
<span class="name">a required plugin failure REJECTS the run and shuts down initialized plugins</span>
|
|
1315
|
+
|
|
1316
|
+
<span class="ms">0.36 ms</span>
|
|
1317
|
+
</summary>
|
|
1318
|
+
<div class="detail muted">No additional observations.</div>
|
|
1319
|
+
</details>
|
|
1320
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u69 engine lifecycle plugins close in reverse initialization order after a successful run ">
|
|
1321
|
+
<summary>
|
|
1322
|
+
<span class="pill passed">PASS</span>
|
|
1323
|
+
<span class="id">U69</span>
|
|
1324
|
+
<span class="cat">Engine lifecycle</span>
|
|
1325
|
+
<span class="name">plugins close in reverse initialization order after a successful run</span>
|
|
1326
|
+
|
|
1327
|
+
<span class="ms">0.38 ms</span>
|
|
1328
|
+
</summary>
|
|
1329
|
+
<div class="detail muted">No additional observations.</div>
|
|
1330
|
+
</details>
|
|
1331
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u70 execution & scheduler single-node graph completes and stores its output ">
|
|
1332
|
+
<summary>
|
|
1333
|
+
<span class="pill passed">PASS</span>
|
|
1334
|
+
<span class="id">U70</span>
|
|
1335
|
+
<span class="cat">Execution & scheduler</span>
|
|
1336
|
+
<span class="name">single-node graph completes and stores its output</span>
|
|
1337
|
+
|
|
1338
|
+
<span class="ms">0.15 ms</span>
|
|
1339
|
+
</summary>
|
|
1340
|
+
<div class="detail muted">No additional observations.</div>
|
|
1341
|
+
</details>
|
|
1342
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u71 execution & scheduler linear graph runs every node in order ">
|
|
1343
|
+
<summary>
|
|
1344
|
+
<span class="pill passed">PASS</span>
|
|
1345
|
+
<span class="id">U71</span>
|
|
1346
|
+
<span class="cat">Execution & scheduler</span>
|
|
1347
|
+
<span class="name">linear graph runs every node in order</span>
|
|
1348
|
+
|
|
1349
|
+
<span class="ms">0.27 ms</span>
|
|
1350
|
+
</summary>
|
|
1351
|
+
<div class="detail muted">No additional observations.</div>
|
|
1352
|
+
</details>
|
|
1353
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u72 execution & scheduler diamond graph fans out and converges ">
|
|
1354
|
+
<summary>
|
|
1355
|
+
<span class="pill passed">PASS</span>
|
|
1356
|
+
<span class="id">U72</span>
|
|
1357
|
+
<span class="cat">Execution & scheduler</span>
|
|
1358
|
+
<span class="name">diamond graph fans out and converges</span>
|
|
1359
|
+
|
|
1360
|
+
<span class="ms">0.3 ms</span>
|
|
1361
|
+
</summary>
|
|
1362
|
+
<div class="detail muted">No additional observations.</div>
|
|
1363
|
+
</details>
|
|
1364
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u73 execution & scheduler independent entry nodes both execute ">
|
|
1365
|
+
<summary>
|
|
1366
|
+
<span class="pill passed">PASS</span>
|
|
1367
|
+
<span class="id">U73</span>
|
|
1368
|
+
<span class="cat">Execution & scheduler</span>
|
|
1369
|
+
<span class="name">independent entry nodes both execute</span>
|
|
1370
|
+
|
|
1371
|
+
<span class="ms">0.22 ms</span>
|
|
1372
|
+
</summary>
|
|
1373
|
+
<div class="detail muted">No additional observations.</div>
|
|
1374
|
+
</details>
|
|
1375
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u74 execution & scheduler multiple terminal nodes are both recognized ">
|
|
1376
|
+
<summary>
|
|
1377
|
+
<span class="pill passed">PASS</span>
|
|
1378
|
+
<span class="id">U74</span>
|
|
1379
|
+
<span class="cat">Execution & scheduler</span>
|
|
1380
|
+
<span class="name">multiple terminal nodes are both recognized</span>
|
|
1381
|
+
|
|
1382
|
+
<span class="ms">0.27 ms</span>
|
|
1383
|
+
</summary>
|
|
1384
|
+
<div class="detail muted">No additional observations.</div>
|
|
1385
|
+
</details>
|
|
1386
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u75 execution & scheduler node context exposes execution metadata ">
|
|
1387
|
+
<summary>
|
|
1388
|
+
<span class="pill passed">PASS</span>
|
|
1389
|
+
<span class="id">U75</span>
|
|
1390
|
+
<span class="cat">Execution & scheduler</span>
|
|
1391
|
+
<span class="name">node context exposes execution metadata</span>
|
|
1392
|
+
|
|
1393
|
+
<span class="ms">0.19 ms</span>
|
|
1394
|
+
</summary>
|
|
1395
|
+
<div class="detail muted">No additional observations.</div>
|
|
1396
|
+
</details>
|
|
1397
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u76 execution & scheduler activationid is unique per activation ">
|
|
1398
|
+
<summary>
|
|
1399
|
+
<span class="pill passed">PASS</span>
|
|
1400
|
+
<span class="id">U76</span>
|
|
1401
|
+
<span class="cat">Execution & scheduler</span>
|
|
1402
|
+
<span class="name">activationId is unique per activation</span>
|
|
1403
|
+
|
|
1404
|
+
<span class="ms">0.45 ms</span>
|
|
1405
|
+
</summary>
|
|
1406
|
+
<div class="detail muted">No additional observations.</div>
|
|
1407
|
+
</details>
|
|
1408
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u77 execution & scheduler node output can be read from a successor's context.outputs ">
|
|
1409
|
+
<summary>
|
|
1410
|
+
<span class="pill passed">PASS</span>
|
|
1411
|
+
<span class="id">U77</span>
|
|
1412
|
+
<span class="cat">Execution & scheduler</span>
|
|
1413
|
+
<span class="name">node output can be read from a successor's context.outputs</span>
|
|
1414
|
+
|
|
1415
|
+
<span class="ms">0.27 ms</span>
|
|
1416
|
+
</summary>
|
|
1417
|
+
<div class="detail muted">No additional observations.</div>
|
|
1418
|
+
</details>
|
|
1419
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u78 execution & scheduler context.outputs freezing blocks mutation (strict runtime) ">
|
|
1420
|
+
<summary>
|
|
1421
|
+
<span class="pill passed">PASS</span>
|
|
1422
|
+
<span class="id">U78</span>
|
|
1423
|
+
<span class="cat">Execution & scheduler</span>
|
|
1424
|
+
<span class="name">context.outputs freezing blocks mutation (strict runtime)</span>
|
|
1425
|
+
|
|
1426
|
+
<span class="ms">0.2 ms</span>
|
|
1427
|
+
</summary>
|
|
1428
|
+
<div class="detail muted">No additional observations.</div>
|
|
1429
|
+
</details>
|
|
1430
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u79 execution & scheduler async node functions are awaited ">
|
|
1431
|
+
<summary>
|
|
1432
|
+
<span class="pill passed">PASS</span>
|
|
1433
|
+
<span class="id">U79</span>
|
|
1434
|
+
<span class="cat">Execution & scheduler</span>
|
|
1435
|
+
<span class="name">async node functions are awaited</span>
|
|
1436
|
+
|
|
1437
|
+
<span class="ms">15.05 ms</span>
|
|
1438
|
+
</summary>
|
|
1439
|
+
<div class="detail muted">No additional observations.</div>
|
|
1440
|
+
</details>
|
|
1441
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u80 execution & scheduler reaching the terminal marks logicallycompleted and stops scheduling ">
|
|
1442
|
+
<summary>
|
|
1443
|
+
<span class="pill passed">PASS</span>
|
|
1444
|
+
<span class="id">U80</span>
|
|
1445
|
+
<span class="cat">Execution & scheduler</span>
|
|
1446
|
+
<span class="name">reaching the terminal marks logicallyCompleted and stops scheduling</span>
|
|
1447
|
+
|
|
1448
|
+
<span class="ms">0.29 ms</span>
|
|
1449
|
+
</summary>
|
|
1450
|
+
<div class="detail muted">No additional observations.</div>
|
|
1451
|
+
</details>
|
|
1452
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u81 execution & scheduler the graph exhausts without a terminal => failed + graph_terminal_not_reached ">
|
|
1453
|
+
<summary>
|
|
1454
|
+
<span class="pill passed">PASS</span>
|
|
1455
|
+
<span class="id">U81</span>
|
|
1456
|
+
<span class="cat">Execution & scheduler</span>
|
|
1457
|
+
<span class="name">the graph exhausts without a terminal => FAILED + GRAPH_TERMINAL_NOT_REACHED</span>
|
|
1458
|
+
|
|
1459
|
+
<span class="ms">0.27 ms</span>
|
|
1460
|
+
</summary>
|
|
1461
|
+
<div class="detail muted">No additional observations.</div>
|
|
1462
|
+
</details>
|
|
1463
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u82 execution & scheduler node.started / node.succeeded events fire with payloads ">
|
|
1464
|
+
<summary>
|
|
1465
|
+
<span class="pill passed">PASS</span>
|
|
1466
|
+
<span class="id">U82</span>
|
|
1467
|
+
<span class="cat">Execution & scheduler</span>
|
|
1468
|
+
<span class="name">node.started / node.succeeded events fire with payloads</span>
|
|
1469
|
+
|
|
1470
|
+
<span class="ms">0.27 ms</span>
|
|
1471
|
+
</summary>
|
|
1472
|
+
<div class="detail muted">No additional observations.</div>
|
|
1473
|
+
</details>
|
|
1474
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u83 execution & scheduler node.started precedes node.succeeded per node ">
|
|
1475
|
+
<summary>
|
|
1476
|
+
<span class="pill passed">PASS</span>
|
|
1477
|
+
<span class="id">U83</span>
|
|
1478
|
+
<span class="cat">Execution & scheduler</span>
|
|
1479
|
+
<span class="name">node.started precedes node.succeeded per node</span>
|
|
1480
|
+
|
|
1481
|
+
<span class="ms">0.12 ms</span>
|
|
1482
|
+
</summary>
|
|
1483
|
+
<div class="detail muted">No additional observations.</div>
|
|
1484
|
+
</details>
|
|
1485
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u84 execution & scheduler context.emit() forwards to the bus ">
|
|
1486
|
+
<summary>
|
|
1487
|
+
<span class="pill passed">PASS</span>
|
|
1488
|
+
<span class="id">U84</span>
|
|
1489
|
+
<span class="cat">Execution & scheduler</span>
|
|
1490
|
+
<span class="name">context.emit() forwards to the bus</span>
|
|
1491
|
+
|
|
1492
|
+
<span class="ms">0.16 ms</span>
|
|
1493
|
+
</summary>
|
|
1494
|
+
<div class="detail muted">No additional observations.</div>
|
|
1495
|
+
</details>
|
|
1496
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u85 execution & scheduler checkpoints are written once per successful node by default ">
|
|
1497
|
+
<summary>
|
|
1498
|
+
<span class="pill passed">PASS</span>
|
|
1499
|
+
<span class="id">U85</span>
|
|
1500
|
+
<span class="cat">Execution & scheduler</span>
|
|
1501
|
+
<span class="name">checkpoints are written once per successful node by default</span>
|
|
1502
|
+
|
|
1503
|
+
<span class="ms">0.32 ms</span>
|
|
1504
|
+
</summary>
|
|
1505
|
+
<div class="detail muted">No additional observations.</div>
|
|
1506
|
+
</details>
|
|
1507
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u86 execution & scheduler checkpointeverynode: false disables node checkpoints ">
|
|
1508
|
+
<summary>
|
|
1509
|
+
<span class="pill passed">PASS</span>
|
|
1510
|
+
<span class="id">U86</span>
|
|
1511
|
+
<span class="cat">Execution & scheduler</span>
|
|
1512
|
+
<span class="name">checkpointEveryNode: false disables node checkpoints</span>
|
|
1513
|
+
|
|
1514
|
+
<span class="ms">0.17 ms</span>
|
|
1515
|
+
</summary>
|
|
1516
|
+
<div class="detail muted">No additional observations.</div>
|
|
1517
|
+
</details>
|
|
1518
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u87 execution & scheduler snapshots record outputs, plugin versions and the execution id ">
|
|
1519
|
+
<summary>
|
|
1520
|
+
<span class="pill passed">PASS</span>
|
|
1521
|
+
<span class="id">U87</span>
|
|
1522
|
+
<span class="cat">Execution & scheduler</span>
|
|
1523
|
+
<span class="name">snapshots record outputs, plugin versions and the execution id</span>
|
|
1524
|
+
|
|
1525
|
+
<span class="ms">0.22 ms</span>
|
|
1526
|
+
</summary>
|
|
1527
|
+
<div class="detail muted">No additional observations.</div>
|
|
1528
|
+
</details>
|
|
1529
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u88 execution & scheduler successful run yields zero errors and cloneable outputs ">
|
|
1530
|
+
<summary>
|
|
1531
|
+
<span class="pill passed">PASS</span>
|
|
1532
|
+
<span class="id">U88</span>
|
|
1533
|
+
<span class="cat">Execution & scheduler</span>
|
|
1534
|
+
<span class="name">successful run yields zero errors and cloneable outputs</span>
|
|
1535
|
+
|
|
1536
|
+
<span class="ms">0.15 ms</span>
|
|
1537
|
+
</summary>
|
|
1538
|
+
<div class="detail muted">No additional observations.</div>
|
|
1539
|
+
</details>
|
|
1540
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u89 execution & scheduler node.started listener sees the context emitted by nodecontext.emit ">
|
|
1541
|
+
<summary>
|
|
1542
|
+
<span class="pill passed">PASS</span>
|
|
1543
|
+
<span class="id">U89</span>
|
|
1544
|
+
<span class="cat">Execution & scheduler</span>
|
|
1545
|
+
<span class="name">node.started listener sees the context emitted by NodeContext.emit</span>
|
|
1546
|
+
|
|
1547
|
+
<span class="ms">0.15 ms</span>
|
|
1548
|
+
</summary>
|
|
1549
|
+
<div class="detail muted">No additional observations.</div>
|
|
1550
|
+
</details>
|
|
1551
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u90 retry errorpolicy retry re-runs until success and records the final attempt ">
|
|
1552
|
+
<summary>
|
|
1553
|
+
<span class="pill passed">PASS</span>
|
|
1554
|
+
<span class="id">U90</span>
|
|
1555
|
+
<span class="cat">Retry</span>
|
|
1556
|
+
<span class="name">errorPolicy RETRY re-runs until success and records the final attempt</span>
|
|
1557
|
+
|
|
1558
|
+
<span class="ms">2.89 ms</span>
|
|
1559
|
+
</summary>
|
|
1560
|
+
<div class="detail muted">No additional observations.</div>
|
|
1561
|
+
</details>
|
|
1562
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u91 retry retry respects delayms between attempts ">
|
|
1563
|
+
<summary>
|
|
1564
|
+
<span class="pill passed">PASS</span>
|
|
1565
|
+
<span class="id">U91</span>
|
|
1566
|
+
<span class="cat">Retry</span>
|
|
1567
|
+
<span class="name">RETRY respects delayMs between attempts</span>
|
|
1568
|
+
|
|
1569
|
+
<span class="ms">81.1 ms</span>
|
|
1570
|
+
</summary>
|
|
1571
|
+
<div class="detail muted">No additional observations.</div>
|
|
1572
|
+
</details>
|
|
1573
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u92 retry exhausting maxattempts records one unhandled error and terminates ">
|
|
1574
|
+
<summary>
|
|
1575
|
+
<span class="pill passed">PASS</span>
|
|
1576
|
+
<span class="id">U92</span>
|
|
1577
|
+
<span class="cat">Retry</span>
|
|
1578
|
+
<span class="name">exhausting maxAttempts records one unhandled error and terminates</span>
|
|
1579
|
+
|
|
1580
|
+
<span class="ms">3.02 ms</span>
|
|
1581
|
+
</summary>
|
|
1582
|
+
<div class="detail muted">No additional observations.</div>
|
|
1583
|
+
</details>
|
|
1584
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u93 retry retry without delayms retries without added latency ">
|
|
1585
|
+
<summary>
|
|
1586
|
+
<span class="pill passed">PASS</span>
|
|
1587
|
+
<span class="id">U93</span>
|
|
1588
|
+
<span class="cat">Retry</span>
|
|
1589
|
+
<span class="name">RETRY without delayMs retries without added latency</span>
|
|
1590
|
+
|
|
1591
|
+
<span class="ms">1.55 ms</span>
|
|
1592
|
+
</summary>
|
|
1593
|
+
<div class="detail muted">No additional observations.</div>
|
|
1594
|
+
</details>
|
|
1595
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u94 retry retry maxattempts=1 means a single execution ">
|
|
1596
|
+
<summary>
|
|
1597
|
+
<span class="pill passed">PASS</span>
|
|
1598
|
+
<span class="id">U94</span>
|
|
1599
|
+
<span class="cat">Retry</span>
|
|
1600
|
+
<span class="name">retry maxAttempts=1 means a single execution</span>
|
|
1601
|
+
|
|
1602
|
+
<span class="ms">0.5 ms</span>
|
|
1603
|
+
</summary>
|
|
1604
|
+
<div class="detail muted">No additional observations.</div>
|
|
1605
|
+
</details>
|
|
1606
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u95 retry once retries succeed the successor nodes are scheduled ">
|
|
1607
|
+
<summary>
|
|
1608
|
+
<span class="pill passed">PASS</span>
|
|
1609
|
+
<span class="id">U95</span>
|
|
1610
|
+
<span class="cat">Retry</span>
|
|
1611
|
+
<span class="name">once retries succeed the successor nodes are scheduled</span>
|
|
1612
|
+
|
|
1613
|
+
<span class="ms">1.56 ms</span>
|
|
1614
|
+
</summary>
|
|
1615
|
+
<div class="detail muted">No additional observations.</div>
|
|
1616
|
+
</details>
|
|
1617
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u96 cancellation cancel() on a created engine produces cancelled ">
|
|
1618
|
+
<summary>
|
|
1619
|
+
<span class="pill passed">PASS</span>
|
|
1620
|
+
<span class="id">U96</span>
|
|
1621
|
+
<span class="cat">Cancellation</span>
|
|
1622
|
+
<span class="name">cancel() on a CREATED engine produces CANCELLED</span>
|
|
1623
|
+
|
|
1624
|
+
<span class="ms">0.34 ms</span>
|
|
1625
|
+
</summary>
|
|
1626
|
+
<div class="detail muted">No additional observations.</div>
|
|
1627
|
+
</details>
|
|
1628
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u97 cancellation cancel() aborts the execution signal exposed to running nodes ">
|
|
1629
|
+
<summary>
|
|
1630
|
+
<span class="pill passed">PASS</span>
|
|
1631
|
+
<span class="id">U97</span>
|
|
1632
|
+
<span class="cat">Cancellation</span>
|
|
1633
|
+
<span class="name">cancel() aborts the execution signal exposed to running nodes</span>
|
|
1634
|
+
|
|
1635
|
+
<span class="ms">30.18 ms</span>
|
|
1636
|
+
</summary>
|
|
1637
|
+
<div class="detail muted">No additional observations.</div>
|
|
1638
|
+
</details>
|
|
1639
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u98 cancellation cancel() emits graph.cancellationrequested ">
|
|
1640
|
+
<summary>
|
|
1641
|
+
<span class="pill passed">PASS</span>
|
|
1642
|
+
<span class="id">U98</span>
|
|
1643
|
+
<span class="cat">Cancellation</span>
|
|
1644
|
+
<span class="name">cancel() emits graph.cancellationRequested</span>
|
|
1645
|
+
|
|
1646
|
+
<span class="ms">0.15 ms</span>
|
|
1647
|
+
</summary>
|
|
1648
|
+
<div class="detail muted">No additional observations.</div>
|
|
1649
|
+
</details>
|
|
1650
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u99 cancellation nodes in flight when cancelling settle as cancelled ">
|
|
1651
|
+
<summary>
|
|
1652
|
+
<span class="pill passed">PASS</span>
|
|
1653
|
+
<span class="id">U99</span>
|
|
1654
|
+
<span class="cat">Cancellation</span>
|
|
1655
|
+
<span class="name">nodes in flight when cancelling settle as CANCELLED</span>
|
|
1656
|
+
|
|
1657
|
+
<span class="ms">40.73 ms</span>
|
|
1658
|
+
</summary>
|
|
1659
|
+
<div class="detail muted">No additional observations.</div>
|
|
1660
|
+
</details>
|
|
1661
|
+
<details class="row ok unit" data-kind="unit" data-status="passed" data-finding="false" data-search="u100 cancellation cancel() after completed is a no-op ">
|
|
1662
|
+
<summary>
|
|
1663
|
+
<span class="pill passed">PASS</span>
|
|
1664
|
+
<span class="id">U100</span>
|
|
1665
|
+
<span class="cat">Cancellation</span>
|
|
1666
|
+
<span class="name">cancel() after COMPLETED is a no-op</span>
|
|
1667
|
+
|
|
1668
|
+
<span class="ms">0.26 ms</span>
|
|
1669
|
+
</summary>
|
|
1670
|
+
<div class="detail muted">No additional observations.</div>
|
|
1671
|
+
</details>
|
|
1672
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i1 e2e pipelines multi-branch order pipeline completes with a checkpoint per successful node ">
|
|
1673
|
+
<summary>
|
|
1674
|
+
<span class="pill passed">PASS</span>
|
|
1675
|
+
<span class="id">I1</span>
|
|
1676
|
+
<span class="cat">E2E pipelines</span>
|
|
1677
|
+
<span class="name">multi-branch order pipeline completes with a checkpoint per successful node</span>
|
|
1678
|
+
|
|
1679
|
+
<span class="ms">0.73 ms</span>
|
|
1680
|
+
</summary>
|
|
1681
|
+
<div class="detail"><span class="tag">observations</span><ul><li>checkpoints written :: 6</li><li>critical path :: "validate -> fraud -> charge -> ship -> notify"</li></ul></div>
|
|
1682
|
+
</details>
|
|
1683
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i2 e2e pipelines chaos graph: retry recovery plus onthrow repair still completes ">
|
|
1684
|
+
<summary>
|
|
1685
|
+
<span class="pill passed">PASS</span>
|
|
1686
|
+
<span class="id">I2</span>
|
|
1687
|
+
<span class="cat">E2E pipelines</span>
|
|
1688
|
+
<span class="name">chaos graph: retry recovery plus ONTHROW repair still completes</span>
|
|
1689
|
+
|
|
1690
|
+
<span class="ms">11.54 ms</span>
|
|
1691
|
+
</summary>
|
|
1692
|
+
<div class="detail"><span class="tag">observations</span><ul><li>error path :: ["root","risky","check"]</li><li>handled :: true</li></ul></div>
|
|
1693
|
+
</details>
|
|
1694
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i3 e2e pipelines resilience scenario: timeout is routed to a fallback so the run completes fan-in runs the join node once per incoming edge (decide runs = 2)">
|
|
1695
|
+
<summary>
|
|
1696
|
+
<span class="pill passed">PASS</span>
|
|
1697
|
+
<span class="id">I3</span>
|
|
1698
|
+
<span class="cat">E2E pipelines</span>
|
|
1699
|
+
<span class="name">resilience scenario: timeout is routed to a fallback so the run completes</span>
|
|
1700
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1701
|
+
<span class="ms">46.69 ms</span>
|
|
1702
|
+
</summary>
|
|
1703
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>fan-in runs the join node once per incoming edge (decide runs = 2)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>timeout details :: {"nodeId":"slow-vendor","timeoutMs":25}</li><li>succeeded nodes :: 7</li><li>finding: fan-in runs the join node once per incoming edge (decide runs = 2)</li></ul></div>
|
|
1704
|
+
</details>
|
|
1705
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i4 failure semantics graph-level fail_fast stops not-yet-scheduled successors on independent branches an already-started sibling still observes its own completion before the graph settles as failed">
|
|
1706
|
+
<summary>
|
|
1707
|
+
<span class="pill passed">PASS</span>
|
|
1708
|
+
<span class="id">I4</span>
|
|
1709
|
+
<span class="cat">Failure semantics</span>
|
|
1710
|
+
<span class="name">graph-level FAIL_FAST stops not-yet-scheduled successors on independent branches</span>
|
|
1711
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1712
|
+
<span class="ms">31.03 ms</span>
|
|
1713
|
+
</summary>
|
|
1714
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an already-started sibling still observes its own completion before the graph settles as FAILED</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an already-started sibling still observes its own completion before the graph settles as FAILED</li></ul></div>
|
|
1715
|
+
</details>
|
|
1716
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i5 failure semantics onthrow routes to a repair node and the failing node is never re-attempted ">
|
|
1717
|
+
<summary>
|
|
1718
|
+
<span class="pill passed">PASS</span>
|
|
1719
|
+
<span class="id">I5</span>
|
|
1720
|
+
<span class="cat">Failure semantics</span>
|
|
1721
|
+
<span class="name">ONTHROW routes to a repair node and the failing node is never re-attempted</span>
|
|
1722
|
+
|
|
1723
|
+
<span class="ms">0.65 ms</span>
|
|
1724
|
+
</summary>
|
|
1725
|
+
<div class="detail"><span class="tag">observations</span><ul><li>activation order :: "root,risky,repair,verify,finish"</li></ul></div>
|
|
1726
|
+
</details>
|
|
1727
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i6 concurrency & scale diamond fan-in executes the join node once per incoming activation (no dedup) no join/dedup semantics — the join node ran once per incoming edge">
|
|
1728
|
+
<summary>
|
|
1729
|
+
<span class="pill passed">PASS</span>
|
|
1730
|
+
<span class="id">I6</span>
|
|
1731
|
+
<span class="cat">Concurrency & scale</span>
|
|
1732
|
+
<span class="name">diamond fan-in executes the join node once per incoming activation (no dedup)</span>
|
|
1733
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1734
|
+
<span class="ms">0.52 ms</span>
|
|
1735
|
+
</summary>
|
|
1736
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>no join/dedup semantics — the join node ran once per incoming edge</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: no join/dedup semantics — the join node ran once per incoming edge</li><li>final outputs.d (last writer wins) :: "d(seen b=B, c=C)"</li></ul></div>
|
|
1737
|
+
</details>
|
|
1738
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i7 cancellation & cycles cyclic graph iterates via next + onthrow exit and keeps a growing path cycles are legal (no validation) and terminate only via onthrow">
|
|
1739
|
+
<summary>
|
|
1740
|
+
<span class="pill passed">PASS</span>
|
|
1741
|
+
<span class="id">I7</span>
|
|
1742
|
+
<span class="cat">Cancellation & cycles</span>
|
|
1743
|
+
<span class="name">cyclic graph iterates via next + ONTHROW exit and keeps a growing path</span>
|
|
1744
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1745
|
+
<span class="ms">0.43 ms</span>
|
|
1746
|
+
</summary>
|
|
1747
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>cycles are legal (no validation) and terminate only via ONTHROW</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: cycles are legal (no validation) and terminate only via ONTHROW</li><li>loop error path :: "loop -> loop -> loop -> loop -> loop -> loop"</li></ul></div>
|
|
1748
|
+
</details>
|
|
1749
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i8 concurrency & scale 250-node fan-out satisfies a full-concurrency barrier (no hidden cap) scheduler concurrency is unbounded (max_safe_integer)">
|
|
1750
|
+
<summary>
|
|
1751
|
+
<span class="pill passed">PASS</span>
|
|
1752
|
+
<span class="id">I8</span>
|
|
1753
|
+
<span class="cat">Concurrency & scale</span>
|
|
1754
|
+
<span class="name">250-node fan-out satisfies a full-concurrency barrier (no hidden cap)</span>
|
|
1755
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1756
|
+
<span class="ms">88.81 ms</span>
|
|
1757
|
+
</summary>
|
|
1758
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>scheduler concurrency is unbounded (MAX_SAFE_INTEGER)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: scheduler concurrency is unbounded (MAX_SAFE_INTEGER)</li><li>throughput proof: all 250 nodes were simultaneously in flight (the barrier could only be released once every leaf had started), so wall time is ~1 node, not 250</li><li>wall time :: "89ms (serial lower bound would be >= 1250ms if capped)"</li></ul></div>
|
|
1759
|
+
</details>
|
|
1760
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i9 concurrency & scale 40-node chain produces monotone, gap-free checkpoints in execution order ">
|
|
1761
|
+
<summary>
|
|
1762
|
+
<span class="pill passed">PASS</span>
|
|
1763
|
+
<span class="id">I9</span>
|
|
1764
|
+
<span class="cat">Concurrency & scale</span>
|
|
1765
|
+
<span class="name">40-node chain produces monotone, gap-free checkpoints in execution order</span>
|
|
1766
|
+
|
|
1767
|
+
<span class="ms">2.65 ms</span>
|
|
1768
|
+
</summary>
|
|
1769
|
+
<div class="detail"><span class="tag">observations</span><ul><li>snapshots :: 40</li><li>final outputs :: 40</li></ul></div>
|
|
1770
|
+
</details>
|
|
1771
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i10 events & listeners required listeners observe a deterministic lifecycle event order ">
|
|
1772
|
+
<summary>
|
|
1773
|
+
<span class="pill passed">PASS</span>
|
|
1774
|
+
<span class="id">I10</span>
|
|
1775
|
+
<span class="cat">Events & listeners</span>
|
|
1776
|
+
<span class="name">required listeners observe a deterministic lifecycle event order</span>
|
|
1777
|
+
|
|
1778
|
+
<span class="ms">2.17 ms</span>
|
|
1779
|
+
</summary>
|
|
1780
|
+
<div class="detail"><span class="tag">observations</span><ul><li>event sequence :: "graph.ready -> node.started:a -> node.succeeded:a -> node.started:b -> node.succeeded:b -> graph.logicallyCompleted -> graph.finished"</li><li>run duration :: "2ms"</li></ul></div>
|
|
1781
|
+
</details>
|
|
1782
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i11 events & listeners faulty non-required listeners are isolated; a failing required listener is contained graph.finished is the only emit whose rejection is caught by the engine; a failing required listener elsewhere (e.g. node.failed) escapes into the node error path">
|
|
1783
|
+
<summary>
|
|
1784
|
+
<span class="pill passed">PASS</span>
|
|
1785
|
+
<span class="id">I11</span>
|
|
1786
|
+
<span class="cat">Events & listeners</span>
|
|
1787
|
+
<span class="name">faulty non-required listeners are isolated; a failing required listener is contained</span>
|
|
1788
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1789
|
+
<span class="ms">21.43 ms</span>
|
|
1790
|
+
</summary>
|
|
1791
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>graph.finished is the only emit whose rejection is caught by the engine; a failing required listener elsewhere (e.g. node.failed) escapes into the node error path</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>isolated listener failures :: 4</li><li>finding: graph.finished is the only emit whose rejection is caught by the engine; a failing required listener elsewhere (e.g. node.failed) escapes into the node error path</li></ul></div>
|
|
1792
|
+
</details>
|
|
1793
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i12 lifecycle & plugins plugins close in reverse order and shutdown failures are collected, not fatal ">
|
|
1794
|
+
<summary>
|
|
1795
|
+
<span class="pill passed">PASS</span>
|
|
1796
|
+
<span class="id">I12</span>
|
|
1797
|
+
<span class="cat">Lifecycle & plugins</span>
|
|
1798
|
+
<span class="name">plugins close in reverse order and shutdown failures are collected, not fatal</span>
|
|
1799
|
+
|
|
1800
|
+
<span class="ms">6.33 ms</span>
|
|
1801
|
+
</summary>
|
|
1802
|
+
<div class="detail"><span class="tag">observations</span><ul><li>shutdown errors :: ["Plugin \"telemetry\" shutdown failed: socket already closed"]</li></ul></div>
|
|
1803
|
+
</details>
|
|
1804
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i13 lifecycle & plugins plugin shutdown is time-boxed by cancellationtimeoutms ">
|
|
1805
|
+
<summary>
|
|
1806
|
+
<span class="pill passed">PASS</span>
|
|
1807
|
+
<span class="id">I13</span>
|
|
1808
|
+
<span class="cat">Lifecycle & plugins</span>
|
|
1809
|
+
<span class="name">plugin shutdown is time-boxed by cancellationTimeoutMs</span>
|
|
1810
|
+
|
|
1811
|
+
<span class="ms">31.36 ms</span>
|
|
1812
|
+
</summary>
|
|
1813
|
+
<div class="detail"><span class="tag">observations</span><ul><li>run duration :: "31ms"</li><li>shutdown errors :: 1</li></ul></div>
|
|
1814
|
+
</details>
|
|
1815
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="false" data-search="i14 lifecycle & plugins two concurrent executions keep ids, snapshots and results isolated ">
|
|
1816
|
+
<summary>
|
|
1817
|
+
<span class="pill passed">PASS</span>
|
|
1818
|
+
<span class="id">I14</span>
|
|
1819
|
+
<span class="cat">Lifecycle & plugins</span>
|
|
1820
|
+
<span class="name">two concurrent executions keep ids, snapshots and results isolated</span>
|
|
1821
|
+
|
|
1822
|
+
<span class="ms">16.53 ms</span>
|
|
1823
|
+
</summary>
|
|
1824
|
+
<div class="detail"><span class="tag">observations</span><ul><li>execution ids :: ["35eddd7b","d5609b14"]</li></ul></div>
|
|
1825
|
+
</details>
|
|
1826
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i15 failure semantics checkpoint failure on the 2nd save blocks scheduling and freezes the last valid snapshot the checkpoint failure surfaces twice per node (checkpoint_save_failed plus a node_execution_error for the raw persistence error) and marks those nodes failed">
|
|
1827
|
+
<summary>
|
|
1828
|
+
<span class="pill passed">PASS</span>
|
|
1829
|
+
<span class="id">I15</span>
|
|
1830
|
+
<span class="cat">Failure semantics</span>
|
|
1831
|
+
<span class="name">checkpoint failure on the 2nd save blocks scheduling and freezes the last valid snapshot</span>
|
|
1832
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1833
|
+
<span class="ms">15.28 ms</span>
|
|
1834
|
+
</summary>
|
|
1835
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the checkpoint failure surfaces twice per node (CHECKPOINT_SAVE_FAILED plus a NODE_EXECUTION_ERROR for the raw persistence error) and marks those nodes FAILED</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>checkpoint errors :: 2</li><li>finding: the checkpoint failure surfaces twice per node (CHECKPOINT_SAVE_FAILED plus a NODE_EXECUTION_ERROR for the raw persistence error) and marks those nodes FAILED</li></ul></div>
|
|
1836
|
+
</details>
|
|
1837
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i16 failure semantics node timeout settles the graph while the abandoned node keeps running (cooperative abort) javascript cannot kill a running node; the engine reports timed_out and moves on">
|
|
1838
|
+
<summary>
|
|
1839
|
+
<span class="pill passed">PASS</span>
|
|
1840
|
+
<span class="id">I16</span>
|
|
1841
|
+
<span class="cat">Failure semantics</span>
|
|
1842
|
+
<span class="name">node timeout settles the graph while the abandoned node keeps running (cooperative abort)</span>
|
|
1843
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1844
|
+
<span class="ms">240.69 ms</span>
|
|
1845
|
+
</summary>
|
|
1846
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>JavaScript cannot kill a running node; the engine reports TIMED_OUT and moves on</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>run duration :: "41ms (node keeps running for 150ms)"</li><li>abort reason :: "TimeoutError"</li><li>finding: JavaScript cannot kill a running node; the engine reports TIMED_OUT and moves on</li></ul></div>
|
|
1847
|
+
</details>
|
|
1848
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i17 failure semantics policy matrix: retry loops, continue ignores maxattempts, fallback has no distinct path fallback is accepted but treated as continue — no alternative-route mechanism exists">
|
|
1849
|
+
<summary>
|
|
1850
|
+
<span class="pill passed">PASS</span>
|
|
1851
|
+
<span class="id">I17</span>
|
|
1852
|
+
<span class="cat">Failure semantics</span>
|
|
1853
|
+
<span class="name">policy matrix: RETRY loops, CONTINUE ignores maxAttempts, FALLBACK has no distinct path</span>
|
|
1854
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1855
|
+
<span class="ms">21.88 ms</span>
|
|
1856
|
+
</summary>
|
|
1857
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>FALLBACK is accepted but treated as CONTINUE — no alternative-route mechanism exists</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>(a) RETRY attempts :: 3</li><li>(b) CONTINUE attempts :: 1</li><li>(c) FALLBACK attempts :: 1</li><li>finding: FALLBACK is accepted but treated as CONTINUE — no alternative-route mechanism exists</li></ul></div>
|
|
1858
|
+
</details>
|
|
1859
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i18 failure semantics final-state precedence: terminal reached + unhandled errors still yields failed settlement order is cancellation > checkpoint failure > unhandled errors > logical completion; failed silently wins over a completed terminal once any branch reaches a terminal node, pending activations (including onthrow recovery paths) are cleared and never executed, yet their errors stay marked handled">
|
|
1860
|
+
<summary>
|
|
1861
|
+
<span class="pill passed">PASS</span>
|
|
1862
|
+
<span class="id">I18</span>
|
|
1863
|
+
<span class="cat">Failure semantics</span>
|
|
1864
|
+
<span class="name">final-state precedence: terminal reached + unhandled errors still yields FAILED</span>
|
|
1865
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1866
|
+
<span class="ms">36.37 ms</span>
|
|
1867
|
+
</summary>
|
|
1868
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>settlement order is cancellation > checkpoint failure > unhandled errors > logical completion; FAILED silently wins over a completed terminal</li><li>once any branch reaches a terminal node, pending activations (including ONTHROW recovery paths) are cleared and never executed, yet their errors stay marked handled</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>(1) dead-end status :: "FAILED"</li><li>(2) logical completion :: true ; "status" ; "FAILED"</li><li>(4) recovery dropped but error marked handled :: true</li><li>finding: settlement order is cancellation > checkpoint failure > unhandled errors > logical completion; FAILED silently wins over a completed terminal</li><li>finding: once any branch reaches a terminal node, pending activations (including ONTHROW recovery paths) are cleared and never executed, yet their errors stay marked handled</li></ul></div>
|
|
1869
|
+
</details>
|
|
1870
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i19 failure semantics policy resolution: every fail_fast is sticky and halts the scheduler fail_fast is sticky at both levels since v1.1 (a4) — the old node-level behaviour was a one-off queue flush that did nothing under unbounded concurrency; a node-level continue still cannot shield other branches from a graph-level fail_fast">
|
|
1871
|
+
<summary>
|
|
1872
|
+
<span class="pill passed">PASS</span>
|
|
1873
|
+
<span class="id">I19</span>
|
|
1874
|
+
<span class="cat">Failure semantics</span>
|
|
1875
|
+
<span class="name">policy resolution: every FAIL_FAST is sticky and halts the scheduler</span>
|
|
1876
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1877
|
+
<span class="ms">53.47 ms</span>
|
|
1878
|
+
</summary>
|
|
1879
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>FAIL_FAST is sticky at both levels since v1.1 (A4) — the old node-level behaviour was a one-off queue flush that did nothing under unbounded concurrency; a node-level CONTINUE still cannot shield other branches from a graph-level FAIL_FAST</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: FAIL_FAST is sticky at both levels since v1.1 (A4) — the old node-level behaviour was a one-off queue flush that did nothing under unbounded concurrency; a node-level CONTINUE still cannot shield other branches from a graph-level FAIL_FAST</li><li>(a) node override FAIL_FAST -> sibling successor dropped :: true</li><li>(b) graph FAIL_FAST -> sibling successor dropped :: true</li><li>(c) retry attempts under node override :: 2</li></ul></div>
|
|
1880
|
+
</details>
|
|
1881
|
+
<details class="row ok integration" data-kind="integration" data-status="passed" data-finding="true" data-search="i20 cancellation & cycles cancelling a fan-out aborts in-flight nodes and never starts their successors cancel() returns immediately but the report waits for cooperative drain">
|
|
1882
|
+
<summary>
|
|
1883
|
+
<span class="pill passed">PASS</span>
|
|
1884
|
+
<span class="id">I20</span>
|
|
1885
|
+
<span class="cat">Cancellation & cycles</span>
|
|
1886
|
+
<span class="name">cancelling a fan-out aborts in-flight nodes and never starts their successors</span>
|
|
1887
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1888
|
+
<span class="ms">202.12 ms</span>
|
|
1889
|
+
</summary>
|
|
1890
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>cancel() returns immediately but the report waits for cooperative drain</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>cancel() latency :: "1ms"</li><li>run() drain time :: "201ms (workers sleep 200ms)"</li><li>finding: cancel() returns immediately but the report waits for cooperative drain</li></ul></div>
|
|
1891
|
+
</details>
|
|
1892
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="true" data-search="a1 node callbacks (async) an async node callback is awaited and its resolved value becomes the output nodecontext signals are typed as abortsignal even in older @types/node dom-less libs, so async callbacks can consume context.signal without casting">
|
|
1893
|
+
<summary>
|
|
1894
|
+
<span class="pill passed">PASS</span>
|
|
1895
|
+
<span class="id">A1</span>
|
|
1896
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1897
|
+
<span class="name">an async node callback is awaited and its resolved value becomes the output</span>
|
|
1898
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1899
|
+
<span class="ms">10.64 ms</span>
|
|
1900
|
+
</summary>
|
|
1901
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>NodeContext signals are typed as AbortSignal even in older @types/node DOM-less libs, so async callbacks can consume context.signal without casting</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: NodeContext signals are typed as AbortSignal even in older @types/node DOM-less libs, so async callbacks can consume context.signal without casting</li></ul></div>
|
|
1902
|
+
</details>
|
|
1903
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a2 node callbacks (async) a non-async callback that returns a thenable is also awaited ">
|
|
1904
|
+
<summary>
|
|
1905
|
+
<span class="pill passed">PASS</span>
|
|
1906
|
+
<span class="id">A2</span>
|
|
1907
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1908
|
+
<span class="name">a non-async callback that returns a thenable is also awaited</span>
|
|
1909
|
+
|
|
1910
|
+
<span class="ms">5.65 ms</span>
|
|
1911
|
+
</summary>
|
|
1912
|
+
<div class="detail muted">No additional observations.</div>
|
|
1913
|
+
</details>
|
|
1914
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a3 node callbacks (async) async callback with no return value produces an undefined output ">
|
|
1915
|
+
<summary>
|
|
1916
|
+
<span class="pill passed">PASS</span>
|
|
1917
|
+
<span class="id">A3</span>
|
|
1918
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1919
|
+
<span class="name">async callback with no return value produces an undefined output</span>
|
|
1920
|
+
|
|
1921
|
+
<span class="ms">5.56 ms</span>
|
|
1922
|
+
</summary>
|
|
1923
|
+
<div class="detail muted">No additional observations.</div>
|
|
1924
|
+
</details>
|
|
1925
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a4 node callbacks (async) a rejected async callback is captured with code, stack and path ">
|
|
1926
|
+
<summary>
|
|
1927
|
+
<span class="pill passed">PASS</span>
|
|
1928
|
+
<span class="id">A4</span>
|
|
1929
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1930
|
+
<span class="name">a rejected async callback is captured with code, stack and path</span>
|
|
1931
|
+
|
|
1932
|
+
<span class="ms">5.87 ms</span>
|
|
1933
|
+
</summary>
|
|
1934
|
+
<div class="detail"><span class="tag">observations</span><ul><li>captured stack head :: "Error: async-rejection"</li></ul></div>
|
|
1935
|
+
</details>
|
|
1936
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="true" data-search="a5 node callbacks (async) async rejections with automategrapherror preserve code and details timeouterror is identified by class or by a node_timeout-family code, so async rejections carrying that code are classified as timed_out">
|
|
1937
|
+
<summary>
|
|
1938
|
+
<span class="pill passed">PASS</span>
|
|
1939
|
+
<span class="id">A5</span>
|
|
1940
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1941
|
+
<span class="name">async rejections with AutomateGraphError preserve code and details</span>
|
|
1942
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1943
|
+
<span class="ms">5.58 ms</span>
|
|
1944
|
+
</summary>
|
|
1945
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>TimeoutError is identified by class OR by a NODE_TIMEOUT-family code, so async rejections carrying that code are classified as TIMED_OUT</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: TimeoutError is identified by class OR by a NODE_TIMEOUT-family code, so async rejections carrying that code are classified as TIMED_OUT</li></ul></div>
|
|
1946
|
+
</details>
|
|
1947
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a6 node callbacks (async) async retry callback recovers on a later attempt inside one activation ">
|
|
1948
|
+
<summary>
|
|
1949
|
+
<span class="pill passed">PASS</span>
|
|
1950
|
+
<span class="id">A6</span>
|
|
1951
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1952
|
+
<span class="name">async retry callback recovers on a later attempt inside one activation</span>
|
|
1953
|
+
|
|
1954
|
+
<span class="ms">26.59 ms</span>
|
|
1955
|
+
</summary>
|
|
1956
|
+
<div class="detail muted">No additional observations.</div>
|
|
1957
|
+
</details>
|
|
1958
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a7 node callbacks (async) async callback can be retried by a custom node errorpolicy (retry) ">
|
|
1959
|
+
<summary>
|
|
1960
|
+
<span class="pill passed">PASS</span>
|
|
1961
|
+
<span class="id">A7</span>
|
|
1962
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1963
|
+
<span class="name">async callback can be retried by a custom node errorPolicy (RETRY)</span>
|
|
1964
|
+
|
|
1965
|
+
<span class="ms">8.06 ms</span>
|
|
1966
|
+
</summary>
|
|
1967
|
+
<div class="detail muted">No additional observations.</div>
|
|
1968
|
+
</details>
|
|
1969
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a8 node callbacks (async) async rejection routes through onthrow into an async repair callback ">
|
|
1970
|
+
<summary>
|
|
1971
|
+
<span class="pill passed">PASS</span>
|
|
1972
|
+
<span class="id">A8</span>
|
|
1973
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1974
|
+
<span class="name">async rejection routes through ONTHROW into an async repair callback</span>
|
|
1975
|
+
|
|
1976
|
+
<span class="ms">11.06 ms</span>
|
|
1977
|
+
</summary>
|
|
1978
|
+
<div class="detail muted">No additional observations.</div>
|
|
1979
|
+
</details>
|
|
1980
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="true" data-search="a9 node callbacks (async) a slow async callback is preempted by timeoutms and reported timed_out on timeout the async callback's later resolution is discarded — no output is recorded">
|
|
1981
|
+
<summary>
|
|
1982
|
+
<span class="pill passed">PASS</span>
|
|
1983
|
+
<span class="id">A9</span>
|
|
1984
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1985
|
+
<span class="name">a slow async callback is preempted by timeoutMs and reported TIMED_OUT</span>
|
|
1986
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1987
|
+
<span class="ms">165.49 ms</span>
|
|
1988
|
+
</summary>
|
|
1989
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>on timeout the async callback's later resolution is discarded — no output is recorded</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>run duration :: "26ms (callback keeps running for 120ms)"</li><li>finding: on timeout the async callback's later resolution is discarded — no output is recorded</li></ul></div>
|
|
1990
|
+
</details>
|
|
1991
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="true" data-search="a10 node callbacks (async) a cooperative async callback observes the abort and rejects; the run settles cancelled since v1.1 (a1) cooperative cancellation is symmetric — a callback that rejects because of the abort settles cancelled with a handled graph_cancelled record, exactly like one that resolves after it; result.error now carries the record (a6)">
|
|
1992
|
+
<summary>
|
|
1993
|
+
<span class="pill passed">PASS</span>
|
|
1994
|
+
<span class="id">A10</span>
|
|
1995
|
+
<span class="cat">Node callbacks (async)</span>
|
|
1996
|
+
<span class="name">a cooperative async callback observes the abort and rejects; the run settles CANCELLED</span>
|
|
1997
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
1998
|
+
<span class="ms">16.63 ms</span>
|
|
1999
|
+
</summary>
|
|
2000
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>since v1.1 (A1) cooperative cancellation is symmetric — a callback that rejects because of the abort settles CANCELLED with a handled GRAPH_CANCELLED record, exactly like one that resolves after it; result.error now carries the record (A6)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>graph status :: "CANCELLED" ; "| node status" ; "CANCELLED"</li><li>error record :: "GRAPH_CANCELLED handled=true"</li><li>finding: since v1.1 (A1) cooperative cancellation is symmetric — a callback that rejects because of the abort settles CANCELLED with a handled GRAPH_CANCELLED record, exactly like one that resolves after it; result.error now carries the record (A6)</li></ul></div>
|
|
2001
|
+
</details>
|
|
2002
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a11 node callbacks (async) an async callback that ignores the signal delays settlement; successors stay unscheduled ">
|
|
2003
|
+
<summary>
|
|
2004
|
+
<span class="pill passed">PASS</span>
|
|
2005
|
+
<span class="id">A11</span>
|
|
2006
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2007
|
+
<span class="name">an async callback that ignores the signal delays settlement; successors stay unscheduled</span>
|
|
2008
|
+
|
|
2009
|
+
<span class="ms">60.17 ms</span>
|
|
2010
|
+
</summary>
|
|
2011
|
+
<div class="detail"><span class="tag">observations</span><ul><li>drain time :: "59ms (callback sleeps 60ms and ignores the abort)"</li></ul></div>
|
|
2012
|
+
</details>
|
|
2013
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a12 node callbacks (async) async completion triggers exactly one checkpoint per successful node ">
|
|
2014
|
+
<summary>
|
|
2015
|
+
<span class="pill passed">PASS</span>
|
|
2016
|
+
<span class="id">A12</span>
|
|
2017
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2018
|
+
<span class="name">async completion triggers exactly one checkpoint per successful node</span>
|
|
2019
|
+
|
|
2020
|
+
<span class="ms">16.28 ms</span>
|
|
2021
|
+
</summary>
|
|
2022
|
+
<div class="detail muted">No additional observations.</div>
|
|
2023
|
+
</details>
|
|
2024
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a13 node callbacks (async) context.emit from an async callback is awaited and ordered ">
|
|
2025
|
+
<summary>
|
|
2026
|
+
<span class="pill passed">PASS</span>
|
|
2027
|
+
<span class="id">A13</span>
|
|
2028
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2029
|
+
<span class="name">context.emit from an async callback is awaited and ordered</span>
|
|
2030
|
+
|
|
2031
|
+
<span class="ms">3.7 ms</span>
|
|
2032
|
+
</summary>
|
|
2033
|
+
<div class="detail muted">No additional observations.</div>
|
|
2034
|
+
</details>
|
|
2035
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a14 node callbacks (async) async callbacks on independent branches execute in parallel ">
|
|
2036
|
+
<summary>
|
|
2037
|
+
<span class="pill passed">PASS</span>
|
|
2038
|
+
<span class="id">A14</span>
|
|
2039
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2040
|
+
<span class="name">async callbacks on independent branches execute in parallel</span>
|
|
2041
|
+
|
|
2042
|
+
<span class="ms">41.03 ms</span>
|
|
2043
|
+
</summary>
|
|
2044
|
+
<div class="detail"><span class="tag">observations</span><ul><li>wall time :: "41ms (serial would be ~160ms)"</li></ul></div>
|
|
2045
|
+
</details>
|
|
2046
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a15 node callbacks (async) mixed sync and async nodes run together in one pipeline ">
|
|
2047
|
+
<summary>
|
|
2048
|
+
<span class="pill passed">PASS</span>
|
|
2049
|
+
<span class="id">A15</span>
|
|
2050
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2051
|
+
<span class="name">mixed sync and async nodes run together in one pipeline</span>
|
|
2052
|
+
|
|
2053
|
+
<span class="ms">11.09 ms</span>
|
|
2054
|
+
</summary>
|
|
2055
|
+
<div class="detail muted">No additional observations.</div>
|
|
2056
|
+
</details>
|
|
2057
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a16 node callbacks (async) async callback composes success, retry and failure across a three-branch graph ">
|
|
2058
|
+
<summary>
|
|
2059
|
+
<span class="pill passed">PASS</span>
|
|
2060
|
+
<span class="id">A16</span>
|
|
2061
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2062
|
+
<span class="name">async callback composes success, retry and failure across a three-branch graph</span>
|
|
2063
|
+
|
|
2064
|
+
<span class="ms">12.39 ms</span>
|
|
2065
|
+
</summary>
|
|
2066
|
+
<div class="detail"><span class="tag">observations</span><ul><li>fatal error path :: "root/async-fatal"</li></ul></div>
|
|
2067
|
+
</details>
|
|
2068
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a17 node callbacks (async) an async callback returning a marker drives a synchronous state-machine successor ">
|
|
2069
|
+
<summary>
|
|
2070
|
+
<span class="pill passed">PASS</span>
|
|
2071
|
+
<span class="id">A17</span>
|
|
2072
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2073
|
+
<span class="name">an async callback returning a marker drives a synchronous state-machine successor</span>
|
|
2074
|
+
|
|
2075
|
+
<span class="ms">5.7 ms</span>
|
|
2076
|
+
</summary>
|
|
2077
|
+
<div class="detail muted">No additional observations.</div>
|
|
2078
|
+
</details>
|
|
2079
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="true" data-search="a18 node callbacks (async) an unrelated execution started after an abandoned async node is unaffected the abandoned async node still performed its side effect after settlement — async cancellation is cooperative only; nothing can stop an in-flight promise">
|
|
2080
|
+
<summary>
|
|
2081
|
+
<span class="pill passed">PASS</span>
|
|
2082
|
+
<span class="id">A18</span>
|
|
2083
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2084
|
+
<span class="name">an unrelated execution started after an abandoned async node is unaffected</span>
|
|
2085
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2086
|
+
<span class="ms">181.69 ms</span>
|
|
2087
|
+
</summary>
|
|
2088
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the abandoned async node still performed its side effect after settlement — async cancellation is cooperative only; nothing can stop an in-flight promise</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the abandoned async node still performed its side effect after settlement — async cancellation is cooperative only; nothing can stop an in-flight promise</li></ul></div>
|
|
2089
|
+
</details>
|
|
2090
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a19 node callbacks (async) diverse async callbacks (timers, microtasks, thenables) are classified correctly ">
|
|
2091
|
+
<summary>
|
|
2092
|
+
<span class="pill passed">PASS</span>
|
|
2093
|
+
<span class="id">A19</span>
|
|
2094
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2095
|
+
<span class="name">diverse async callbacks (timers, microtasks, thenables) are classified correctly</span>
|
|
2096
|
+
|
|
2097
|
+
<span class="ms">3.24 ms</span>
|
|
2098
|
+
</summary>
|
|
2099
|
+
<div class="detail muted">No additional observations.</div>
|
|
2100
|
+
</details>
|
|
2101
|
+
<details class="row ok async" data-kind="async" data-status="passed" data-finding="false" data-search="a20 node callbacks (async) async callbacks integrate with plugins, storage snapshots and the execution report ">
|
|
2102
|
+
<summary>
|
|
2103
|
+
<span class="pill passed">PASS</span>
|
|
2104
|
+
<span class="id">A20</span>
|
|
2105
|
+
<span class="cat">Node callbacks (async)</span>
|
|
2106
|
+
<span class="name">async callbacks integrate with plugins, storage snapshots and the execution report</span>
|
|
2107
|
+
|
|
2108
|
+
<span class="ms">23.22 ms</span>
|
|
2109
|
+
</summary>
|
|
2110
|
+
<div class="detail"><span class="tag">observations</span><ul><li>checkpoints :: 3</li><li>plugin lifecycle :: "init -> close"</li></ul></div>
|
|
2111
|
+
</details>
|
|
2112
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="true" data-search="u1 a2 · drain deadline cancellationtimeoutms bounds the drain and abandons in-flight work without cancellationtimeoutms the engine still waits forever (v1.0 behaviour); setting it converts an unbounded drain into a bounded, reported one">
|
|
2113
|
+
<summary>
|
|
2114
|
+
<span class="pill passed">PASS</span>
|
|
2115
|
+
<span class="id">U1</span>
|
|
2116
|
+
<span class="cat">A2 · drain deadline</span>
|
|
2117
|
+
<span class="name">cancellationTimeoutMs bounds the drain and abandons in-flight work</span>
|
|
2118
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2119
|
+
<span class="ms">481.07 ms</span>
|
|
2120
|
+
</summary>
|
|
2121
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>without cancellationTimeoutMs the engine still waits forever (v1.0 behaviour); setting it converts an unbounded drain into a bounded, reported one</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>run duration :: "51ms (node sleeps 400ms)"</li><li>finding: without cancellationTimeoutMs the engine still waits forever (v1.0 behaviour); setting it converts an unbounded drain into a bounded, reported one</li></ul></div>
|
|
2122
|
+
</details>
|
|
2123
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u2 a2 · drain deadline without cancellationtimeoutms the run waits for cooperative drain ">
|
|
2124
|
+
<summary>
|
|
2125
|
+
<span class="pill passed">PASS</span>
|
|
2126
|
+
<span class="id">U2</span>
|
|
2127
|
+
<span class="cat">A2 · drain deadline</span>
|
|
2128
|
+
<span class="name">without cancellationTimeoutMs the run waits for cooperative drain</span>
|
|
2129
|
+
|
|
2130
|
+
<span class="ms">61.29 ms</span>
|
|
2131
|
+
</summary>
|
|
2132
|
+
<div class="detail muted">No additional observations.</div>
|
|
2133
|
+
</details>
|
|
2134
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="true" data-search="u3 a3 · completion policy all_terminals waits for every declared terminal before latching completion all_terminals gives fan-in style completion semantics without extra plumbing">
|
|
2135
|
+
<summary>
|
|
2136
|
+
<span class="pill passed">PASS</span>
|
|
2137
|
+
<span class="id">U3</span>
|
|
2138
|
+
<span class="cat">A3 · completion policy</span>
|
|
2139
|
+
<span class="name">ALL_TERMINALS waits for every declared terminal before latching completion</span>
|
|
2140
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2141
|
+
<span class="ms">26.35 ms</span>
|
|
2142
|
+
</summary>
|
|
2143
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>ALL_TERMINALS gives fan-in style completion semantics without extra plumbing</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: ALL_TERMINALS gives fan-in style completion semantics without extra plumbing</li></ul></div>
|
|
2144
|
+
</details>
|
|
2145
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="true" data-search="u4 a3 · completion policy drain keeps scheduling after a terminal, so onthrow recovery is no longer dropped drain is the opt-in fix for the v1.0 silent-drop behaviour (finding c-15/c-19) — the run executes every reachable activation before settling">
|
|
2146
|
+
<summary>
|
|
2147
|
+
<span class="pill passed">PASS</span>
|
|
2148
|
+
<span class="id">U4</span>
|
|
2149
|
+
<span class="cat">A3 · completion policy</span>
|
|
2150
|
+
<span class="name">DRAIN keeps scheduling after a terminal, so ONTHROW recovery is no longer dropped</span>
|
|
2151
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2152
|
+
<span class="ms">26.01 ms</span>
|
|
2153
|
+
</summary>
|
|
2154
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>DRAIN is the opt-in fix for the v1.0 silent-drop behaviour (finding C-15/C-19) — the run executes every reachable activation before settling</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: DRAIN is the opt-in fix for the v1.0 silent-drop behaviour (finding C-15/C-19) — the run executes every reachable activation before settling</li></ul></div>
|
|
2155
|
+
</details>
|
|
2156
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="true" data-search="u5 a3 · completion policy first_terminal (default) drops pending work but now reports it via activation.dropped dropped work is now observable, so silent data loss in the default mode is detectable">
|
|
2157
|
+
<summary>
|
|
2158
|
+
<span class="pill passed">PASS</span>
|
|
2159
|
+
<span class="id">U5</span>
|
|
2160
|
+
<span class="cat">A3 · completion policy</span>
|
|
2161
|
+
<span class="name">FIRST_TERMINAL (default) drops pending work but now reports it via activation.dropped</span>
|
|
2162
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2163
|
+
<span class="ms">25.88 ms</span>
|
|
2164
|
+
</summary>
|
|
2165
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>dropped work is now observable, so silent data loss in the default mode is detectable</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: dropped work is now observable, so silent data loss in the default mode is detectable</li></ul></div>
|
|
2166
|
+
</details>
|
|
2167
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u6 a3 · completion policy an unknown completionpolicy is rejected at construction time ">
|
|
2168
|
+
<summary>
|
|
2169
|
+
<span class="pill passed">PASS</span>
|
|
2170
|
+
<span class="id">U6</span>
|
|
2171
|
+
<span class="cat">A3 · completion policy</span>
|
|
2172
|
+
<span class="name">an unknown completionPolicy is rejected at construction time</span>
|
|
2173
|
+
|
|
2174
|
+
<span class="ms">0.17 ms</span>
|
|
2175
|
+
</summary>
|
|
2176
|
+
<div class="detail muted">No additional observations.</div>
|
|
2177
|
+
</details>
|
|
2178
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u7 a4/a5 · fail_fast & fallback node-level fail_fast is sticky and drops successors via activation.dropped ">
|
|
2179
|
+
<summary>
|
|
2180
|
+
<span class="pill passed">PASS</span>
|
|
2181
|
+
<span class="id">U7</span>
|
|
2182
|
+
<span class="cat">A4/A5 · FAIL_FAST & FALLBACK</span>
|
|
2183
|
+
<span class="name">node-level FAIL_FAST is sticky and drops successors via activation.dropped</span>
|
|
2184
|
+
|
|
2185
|
+
<span class="ms">30.1 ms</span>
|
|
2186
|
+
</summary>
|
|
2187
|
+
<div class="detail muted">No additional observations.</div>
|
|
2188
|
+
</details>
|
|
2189
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u8 a4/a5 · fail_fast & fallback fallback routes to the fallback node and marks the error handled ">
|
|
2190
|
+
<summary>
|
|
2191
|
+
<span class="pill passed">PASS</span>
|
|
2192
|
+
<span class="id">U8</span>
|
|
2193
|
+
<span class="cat">A4/A5 · FAIL_FAST & FALLBACK</span>
|
|
2194
|
+
<span class="name">FALLBACK routes to the fallback node and marks the error handled</span>
|
|
2195
|
+
|
|
2196
|
+
<span class="ms">0.43 ms</span>
|
|
2197
|
+
</summary>
|
|
2198
|
+
<div class="detail muted">No additional observations.</div>
|
|
2199
|
+
</details>
|
|
2200
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u9 a4/a5 · fail_fast & fallback a fallback target is ignored unless the effective policy is fallback ">
|
|
2201
|
+
<summary>
|
|
2202
|
+
<span class="pill passed">PASS</span>
|
|
2203
|
+
<span class="id">U9</span>
|
|
2204
|
+
<span class="cat">A4/A5 · FAIL_FAST & FALLBACK</span>
|
|
2205
|
+
<span class="name">a fallback target is ignored unless the effective policy is FALLBACK</span>
|
|
2206
|
+
|
|
2207
|
+
<span class="ms">0.25 ms</span>
|
|
2208
|
+
</summary>
|
|
2209
|
+
<div class="detail muted">No additional observations.</div>
|
|
2210
|
+
</details>
|
|
2211
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u10 a4/a5 · fail_fast & fallback an unknown fallback target is rejected at construction time ">
|
|
2212
|
+
<summary>
|
|
2213
|
+
<span class="pill passed">PASS</span>
|
|
2214
|
+
<span class="id">U10</span>
|
|
2215
|
+
<span class="cat">A4/A5 · FAIL_FAST & FALLBACK</span>
|
|
2216
|
+
<span class="name">an unknown fallback target is rejected at construction time</span>
|
|
2217
|
+
|
|
2218
|
+
<span class="ms">0.13 ms</span>
|
|
2219
|
+
</summary>
|
|
2220
|
+
<div class="detail muted">No additional observations.</div>
|
|
2221
|
+
</details>
|
|
2222
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u11 a6/a10 · results & hygiene noderesult.error carries the failure record and matches the report errors ">
|
|
2223
|
+
<summary>
|
|
2224
|
+
<span class="pill passed">PASS</span>
|
|
2225
|
+
<span class="id">U11</span>
|
|
2226
|
+
<span class="cat">A6/A10 · results & hygiene</span>
|
|
2227
|
+
<span class="name">NodeResult.error carries the failure record and matches the report errors</span>
|
|
2228
|
+
|
|
2229
|
+
<span class="ms">0.18 ms</span>
|
|
2230
|
+
</summary>
|
|
2231
|
+
<div class="detail muted">No additional observations.</div>
|
|
2232
|
+
</details>
|
|
2233
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u12 a6/a10 · results & hygiene a timed-out node exposes node_timeout on its own result ">
|
|
2234
|
+
<summary>
|
|
2235
|
+
<span class="pill passed">PASS</span>
|
|
2236
|
+
<span class="id">U12</span>
|
|
2237
|
+
<span class="cat">A6/A10 · results & hygiene</span>
|
|
2238
|
+
<span class="name">a timed-out node exposes NODE_TIMEOUT on its own result</span>
|
|
2239
|
+
|
|
2240
|
+
<span class="ms">116.21 ms</span>
|
|
2241
|
+
</summary>
|
|
2242
|
+
<div class="detail muted">No additional observations.</div>
|
|
2243
|
+
</details>
|
|
2244
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u13 a6/a10 · results & hygiene in-flight activation tracking is empty before and after a run ">
|
|
2245
|
+
<summary>
|
|
2246
|
+
<span class="pill passed">PASS</span>
|
|
2247
|
+
<span class="id">U13</span>
|
|
2248
|
+
<span class="cat">A6/A10 · results & hygiene</span>
|
|
2249
|
+
<span class="name">in-flight activation tracking is empty before and after a run</span>
|
|
2250
|
+
|
|
2251
|
+
<span class="ms">30.98 ms</span>
|
|
2252
|
+
</summary>
|
|
2253
|
+
<div class="detail muted">No additional observations.</div>
|
|
2254
|
+
</details>
|
|
2255
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u14 a8 · concurrency & budget maxconcurrency bounds parallelism and preserves completion ">
|
|
2256
|
+
<summary>
|
|
2257
|
+
<span class="pill passed">PASS</span>
|
|
2258
|
+
<span class="id">U14</span>
|
|
2259
|
+
<span class="cat">A8 · concurrency & budget</span>
|
|
2260
|
+
<span class="name">maxConcurrency bounds parallelism and preserves completion</span>
|
|
2261
|
+
|
|
2262
|
+
<span class="ms">28.62 ms</span>
|
|
2263
|
+
</summary>
|
|
2264
|
+
<div class="detail"><span class="tag">observations</span><ul><li>bounded :: 2 ; "| unbounded default" ; 8</li></ul></div>
|
|
2265
|
+
</details>
|
|
2266
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u15 a8 · concurrency & budget maxactivations stops a runaway cycle with step_budget_exceeded ">
|
|
2267
|
+
<summary>
|
|
2268
|
+
<span class="pill passed">PASS</span>
|
|
2269
|
+
<span class="id">U15</span>
|
|
2270
|
+
<span class="cat">A8 · concurrency & budget</span>
|
|
2271
|
+
<span class="name">maxActivations stops a runaway cycle with STEP_BUDGET_EXCEEDED</span>
|
|
2272
|
+
|
|
2273
|
+
<span class="ms">0.59 ms</span>
|
|
2274
|
+
</summary>
|
|
2275
|
+
<div class="detail"><span class="tag">observations</span><ul><li>activations executed :: 6 ; "| duration" ; "0ms"</li></ul></div>
|
|
2276
|
+
</details>
|
|
2277
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u16 a8 · concurrency & budget invalid concurrency and budget options are rejected ">
|
|
2278
|
+
<summary>
|
|
2279
|
+
<span class="pill passed">PASS</span>
|
|
2280
|
+
<span class="id">U16</span>
|
|
2281
|
+
<span class="cat">A8 · concurrency & budget</span>
|
|
2282
|
+
<span class="name">invalid concurrency and budget options are rejected</span>
|
|
2283
|
+
|
|
2284
|
+
<span class="ms">0.2 ms</span>
|
|
2285
|
+
</summary>
|
|
2286
|
+
<div class="detail muted">No additional observations.</div>
|
|
2287
|
+
</details>
|
|
2288
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u17 a9 · graph linting lintgraph reports unreachable nodes, unreachable terminals, dead ends and duplicates ">
|
|
2289
|
+
<summary>
|
|
2290
|
+
<span class="pill passed">PASS</span>
|
|
2291
|
+
<span class="id">U17</span>
|
|
2292
|
+
<span class="cat">A9 · graph linting</span>
|
|
2293
|
+
<span class="name">lintGraph reports unreachable nodes, unreachable terminals, dead ends and duplicates</span>
|
|
2294
|
+
|
|
2295
|
+
<span class="ms">0.43 ms</span>
|
|
2296
|
+
</summary>
|
|
2297
|
+
<div class="detail muted">No additional observations.</div>
|
|
2298
|
+
</details>
|
|
2299
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="false" data-search="u18 a9 · graph linting lint: "warn" logs issues, lint: "error" rejects only on error-level issues ">
|
|
2300
|
+
<summary>
|
|
2301
|
+
<span class="pill passed">PASS</span>
|
|
2302
|
+
<span class="id">U18</span>
|
|
2303
|
+
<span class="cat">A9 · graph linting</span>
|
|
2304
|
+
<span class="name">lint: "warn" logs issues, lint: "error" rejects only on error-level issues</span>
|
|
2305
|
+
|
|
2306
|
+
<span class="ms">0.63 ms</span>
|
|
2307
|
+
</summary>
|
|
2308
|
+
<div class="detail"><span class="tag">observations</span><ul><li>lint issues in the rejected report :: "DEAD_END_NODE"</li></ul></div>
|
|
2309
|
+
</details>
|
|
2310
|
+
<details class="row ok upgrade" data-kind="upgrade" data-status="passed" data-finding="true" data-search="u19 isomorphic build the engine core compiles with dom-only libs and no node types (browser-safe) the engine core is isomorphic — no node apis, no buffers, timers via settimeout only">
|
|
2311
|
+
<summary>
|
|
2312
|
+
<span class="pill passed">PASS</span>
|
|
2313
|
+
<span class="id">U19</span>
|
|
2314
|
+
<span class="cat">Isomorphic build</span>
|
|
2315
|
+
<span class="name">the engine core compiles with DOM-only libs and no Node types (browser-safe)</span>
|
|
2316
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2317
|
+
<span class="ms">1292.28 ms</span>
|
|
2318
|
+
</summary>
|
|
2319
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the engine core is isomorphic — no Node APIs, no Buffers, timers via setTimeout only</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the engine core is isomorphic — no Node APIs, no Buffers, timers via setTimeout only</li></ul></div>
|
|
2320
|
+
</details>
|
|
2321
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c1 storage adapter contract inmemorystorage passes the full conformance suite with zero violations ">
|
|
2322
|
+
<summary>
|
|
2323
|
+
<span class="pill passed">PASS</span>
|
|
2324
|
+
<span class="id">C1</span>
|
|
2325
|
+
<span class="cat">Storage adapter contract</span>
|
|
2326
|
+
<span class="name">InMemoryStorage passes the full conformance suite with zero violations</span>
|
|
2327
|
+
|
|
2328
|
+
<span class="ms">1.84 ms</span>
|
|
2329
|
+
</summary>
|
|
2330
|
+
<div class="detail"><span class="tag">observations</span><ul><li>checks executed :: 12</li><li>skipped :: 1 ; ["FAILED_SAVE_PRESERVES_PREVIOUS (fixture provides no failNextSave)"]</li></ul></div>
|
|
2331
|
+
</details>
|
|
2332
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c2 storage adapter contract an adapter with fault injection proves atomicity instead of skipping it ">
|
|
2333
|
+
<summary>
|
|
2334
|
+
<span class="pill passed">PASS</span>
|
|
2335
|
+
<span class="id">C2</span>
|
|
2336
|
+
<span class="cat">Storage adapter contract</span>
|
|
2337
|
+
<span class="name">an adapter with fault injection proves atomicity instead of skipping it</span>
|
|
2338
|
+
|
|
2339
|
+
<span class="ms">0.52 ms</span>
|
|
2340
|
+
</summary>
|
|
2341
|
+
<div class="detail"><span class="tag">observations</span><ul><li>checks executed :: 12</li><li>skipped :: []</li></ul></div>
|
|
2342
|
+
</details>
|
|
2343
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c3 storage adapter contract the checker catches aliasing, broken listing and broken deletion ">
|
|
2344
|
+
<summary>
|
|
2345
|
+
<span class="pill passed">PASS</span>
|
|
2346
|
+
<span class="id">C3</span>
|
|
2347
|
+
<span class="cat">Storage adapter contract</span>
|
|
2348
|
+
<span class="name">the checker catches aliasing, broken listing and broken deletion</span>
|
|
2349
|
+
|
|
2350
|
+
<span class="ms">0.41 ms</span>
|
|
2351
|
+
</summary>
|
|
2352
|
+
<div class="detail"><span class="tag">observations</span><ul><li>violations detected :: "NO_ALIASING_ON_SAVE, NO_ALIASING_ON_SAVE, NO_ALIASING_ON_LOAD, NO_ALIASING_ON_LOAD, LIST, LIST, LIST, DELETE_IDEMPOTENT, DELETE_IDEMPOTENT"</li></ul></div>
|
|
2353
|
+
</details>
|
|
2354
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="true" data-search="c4 storage adapter contract the checker catches a torn write that commits before failing the conformance suite distinguishes 'rejects' from 'rejects without corrupting state' — adapters must checkpoint before commit, not after">
|
|
2355
|
+
<summary>
|
|
2356
|
+
<span class="pill passed">PASS</span>
|
|
2357
|
+
<span class="id">C4</span>
|
|
2358
|
+
<span class="cat">Storage adapter contract</span>
|
|
2359
|
+
<span class="name">the checker catches a torn write that commits before failing</span>
|
|
2360
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2361
|
+
<span class="ms">0.68 ms</span>
|
|
2362
|
+
</summary>
|
|
2363
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the conformance suite distinguishes 'rejects' from 'rejects without corrupting state' — adapters must checkpoint before commit, not after</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the conformance suite distinguishes 'rejects' from 'rejects without corrupting state' — adapters must checkpoint before commit, not after</li></ul></div>
|
|
2364
|
+
</details>
|
|
2365
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c5 storage adapter contract missing required members are reported as shape violations ">
|
|
2366
|
+
<summary>
|
|
2367
|
+
<span class="pill passed">PASS</span>
|
|
2368
|
+
<span class="id">C5</span>
|
|
2369
|
+
<span class="cat">Storage adapter contract</span>
|
|
2370
|
+
<span class="name">missing required members are reported as SHAPE violations</span>
|
|
2371
|
+
|
|
2372
|
+
<span class="ms">0.12 ms</span>
|
|
2373
|
+
</summary>
|
|
2374
|
+
<div class="detail muted">No additional observations.</div>
|
|
2375
|
+
</details>
|
|
2376
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c6 storage adapter contract an adapter that claims a capability it does not implement is rejected (definestorageadapter) ">
|
|
2377
|
+
<summary>
|
|
2378
|
+
<span class="pill passed">PASS</span>
|
|
2379
|
+
<span class="id">C6</span>
|
|
2380
|
+
<span class="cat">Storage adapter contract</span>
|
|
2381
|
+
<span class="name">an adapter that claims a capability it does not implement is rejected (defineStorageAdapter)</span>
|
|
2382
|
+
|
|
2383
|
+
<span class="ms">0.11 ms</span>
|
|
2384
|
+
</summary>
|
|
2385
|
+
<div class="detail muted">No additional observations.</div>
|
|
2386
|
+
</details>
|
|
2387
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c7 storage adapter contract the engine accepts any conformant adapter as its storage plugin ">
|
|
2388
|
+
<summary>
|
|
2389
|
+
<span class="pill passed">PASS</span>
|
|
2390
|
+
<span class="id">C7</span>
|
|
2391
|
+
<span class="cat">Storage adapter contract</span>
|
|
2392
|
+
<span class="name">the engine accepts any conformant adapter as its storage plugin</span>
|
|
2393
|
+
|
|
2394
|
+
<span class="ms">0.46 ms</span>
|
|
2395
|
+
</summary>
|
|
2396
|
+
<div class="detail"><span class="tag">observations</span><ul><li>snapshots stored :: 1</li></ul></div>
|
|
2397
|
+
</details>
|
|
2398
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c8 snapshot wire format serializesnapshot is deterministic and round-trips through json ">
|
|
2399
|
+
<summary>
|
|
2400
|
+
<span class="pill passed">PASS</span>
|
|
2401
|
+
<span class="id">C8</span>
|
|
2402
|
+
<span class="cat">Snapshot wire format</span>
|
|
2403
|
+
<span class="name">serializeSnapshot is deterministic and round-trips through JSON</span>
|
|
2404
|
+
|
|
2405
|
+
<span class="ms">0.17 ms</span>
|
|
2406
|
+
</summary>
|
|
2407
|
+
<div class="detail muted">No additional observations.</div>
|
|
2408
|
+
</details>
|
|
2409
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c9 snapshot wire format corrupt or unsupported snapshots are rejected with typed errors ">
|
|
2410
|
+
<summary>
|
|
2411
|
+
<span class="pill passed">PASS</span>
|
|
2412
|
+
<span class="id">C9</span>
|
|
2413
|
+
<span class="cat">Snapshot wire format</span>
|
|
2414
|
+
<span class="name">corrupt or unsupported snapshots are rejected with typed errors</span>
|
|
2415
|
+
|
|
2416
|
+
<span class="ms">0.15 ms</span>
|
|
2417
|
+
</summary>
|
|
2418
|
+
<div class="detail muted">No additional observations.</div>
|
|
2419
|
+
</details>
|
|
2420
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c10 snapshot wire format snapshotshapeviolations pinpoints every malformed field ">
|
|
2421
|
+
<summary>
|
|
2422
|
+
<span class="pill passed">PASS</span>
|
|
2423
|
+
<span class="id">C10</span>
|
|
2424
|
+
<span class="cat">Snapshot wire format</span>
|
|
2425
|
+
<span class="name">snapshotShapeViolations pinpoints every malformed field</span>
|
|
2426
|
+
|
|
2427
|
+
<span class="ms">0.09 ms</span>
|
|
2428
|
+
</summary>
|
|
2429
|
+
<div class="detail muted">No additional observations.</div>
|
|
2430
|
+
</details>
|
|
2431
|
+
<details class="row ok conformance" data-kind="conformance" data-status="passed" data-finding="false" data-search="c11 snapshot wire format comparesnapshots reports structural differences precisely ">
|
|
2432
|
+
<summary>
|
|
2433
|
+
<span class="pill passed">PASS</span>
|
|
2434
|
+
<span class="id">C11</span>
|
|
2435
|
+
<span class="cat">Snapshot wire format</span>
|
|
2436
|
+
<span class="name">compareSnapshots reports structural differences precisely</span>
|
|
2437
|
+
|
|
2438
|
+
<span class="ms">0.15 ms</span>
|
|
2439
|
+
</summary>
|
|
2440
|
+
<div class="detail muted">No additional observations.</div>
|
|
2441
|
+
</details>
|
|
2442
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="true" data-search="l1 success dead-end rule the exact c-19 fixture is flagged: slow-vendor succeeds into a void a node can declare onthrow and still be unreachable on its success path — the previous dead_end_node rule only asked whether *any* transition existed">
|
|
2443
|
+
<summary>
|
|
2444
|
+
<span class="pill passed">PASS</span>
|
|
2445
|
+
<span class="id">L1</span>
|
|
2446
|
+
<span class="cat">Success dead-end rule</span>
|
|
2447
|
+
<span class="name">the exact C-19 fixture is flagged: slow-vendor succeeds into a void</span>
|
|
2448
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2449
|
+
<span class="ms">0.52 ms</span>
|
|
2450
|
+
</summary>
|
|
2451
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>a node can declare onThrow and still be unreachable on its success path — the previous DEAD_END_NODE rule only asked whether *any* transition existed</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>issue :: "error/SUCCESS_DEAD_END @ slow-vendor"</li><li>finding: a node can declare onThrow and still be unreachable on its success path — the previous DEAD_END_NODE rule only asked whether *any* transition existed</li></ul></div>
|
|
2452
|
+
</details>
|
|
2453
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l2 success dead-end rule the fix suggested by the message clears the issue (next declared) ">
|
|
2454
|
+
<summary>
|
|
2455
|
+
<span class="pill passed">PASS</span>
|
|
2456
|
+
<span class="id">L2</span>
|
|
2457
|
+
<span class="cat">Success dead-end rule</span>
|
|
2458
|
+
<span class="name">the fix suggested by the message clears the issue (next declared)</span>
|
|
2459
|
+
|
|
2460
|
+
<span class="ms">0.13 ms</span>
|
|
2461
|
+
</summary>
|
|
2462
|
+
<div class="detail"><span class="tag">observations</span><ul><li>slow-vendor issues after adding next :: 0</li></ul></div>
|
|
2463
|
+
</details>
|
|
2464
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l3 success dead-end rule declared terminal nodes are never flagged, even without next ">
|
|
2465
|
+
<summary>
|
|
2466
|
+
<span class="pill passed">PASS</span>
|
|
2467
|
+
<span class="id">L3</span>
|
|
2468
|
+
<span class="cat">Success dead-end rule</span>
|
|
2469
|
+
<span class="name">declared terminal nodes are never flagged, even without next</span>
|
|
2470
|
+
|
|
2471
|
+
<span class="ms">0.08 ms</span>
|
|
2472
|
+
</summary>
|
|
2473
|
+
<div class="detail muted">No additional observations.</div>
|
|
2474
|
+
</details>
|
|
2475
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l4 success dead-end rule a node with no transitions at all is dead_end_node, not success_dead_end ">
|
|
2476
|
+
<summary>
|
|
2477
|
+
<span class="pill passed">PASS</span>
|
|
2478
|
+
<span class="id">L4</span>
|
|
2479
|
+
<span class="cat">Success dead-end rule</span>
|
|
2480
|
+
<span class="name">a node with no transitions at all is DEAD_END_NODE, not SUCCESS_DEAD_END</span>
|
|
2481
|
+
|
|
2482
|
+
<span class="ms">0.07 ms</span>
|
|
2483
|
+
</summary>
|
|
2484
|
+
<div class="detail muted">No additional observations.</div>
|
|
2485
|
+
</details>
|
|
2486
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l5 success dead-end rule an ignored fallback does not count as a live error transition ">
|
|
2487
|
+
<summary>
|
|
2488
|
+
<span class="pill passed">PASS</span>
|
|
2489
|
+
<span class="id">L5</span>
|
|
2490
|
+
<span class="cat">Success dead-end rule</span>
|
|
2491
|
+
<span class="name">an ignored fallback does not count as a live error transition</span>
|
|
2492
|
+
|
|
2493
|
+
<span class="ms">0.1 ms</span>
|
|
2494
|
+
</summary>
|
|
2495
|
+
<div class="detail muted">No additional observations.</div>
|
|
2496
|
+
</details>
|
|
2497
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l6 success dead-end rule a live fallback (policy fallback) makes it success_dead_end, not a total dead end ">
|
|
2498
|
+
<summary>
|
|
2499
|
+
<span class="pill passed">PASS</span>
|
|
2500
|
+
<span class="id">L6</span>
|
|
2501
|
+
<span class="cat">Success dead-end rule</span>
|
|
2502
|
+
<span class="name">a live fallback (policy FALLBACK) makes it SUCCESS_DEAD_END, not a total dead end</span>
|
|
2503
|
+
|
|
2504
|
+
<span class="ms">0.09 ms</span>
|
|
2505
|
+
</summary>
|
|
2506
|
+
<div class="detail muted">No additional observations.</div>
|
|
2507
|
+
</details>
|
|
2508
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l7 success dead-end rule onthrow alone is treated as a live error transition ">
|
|
2509
|
+
<summary>
|
|
2510
|
+
<span class="pill passed">PASS</span>
|
|
2511
|
+
<span class="id">L7</span>
|
|
2512
|
+
<span class="cat">Success dead-end rule</span>
|
|
2513
|
+
<span class="name">onThrow alone is treated as a live error transition</span>
|
|
2514
|
+
|
|
2515
|
+
<span class="ms">0.06 ms</span>
|
|
2516
|
+
</summary>
|
|
2517
|
+
<div class="detail muted">No additional observations.</div>
|
|
2518
|
+
</details>
|
|
2519
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l8 success dead-end rule unreachable nodes with a success path stay unreachable-only (no noise) ">
|
|
2520
|
+
<summary>
|
|
2521
|
+
<span class="pill passed">PASS</span>
|
|
2522
|
+
<span class="id">L8</span>
|
|
2523
|
+
<span class="cat">Success dead-end rule</span>
|
|
2524
|
+
<span class="name">unreachable nodes with a success path stay unreachable-only (no noise)</span>
|
|
2525
|
+
|
|
2526
|
+
<span class="ms">0.06 ms</span>
|
|
2527
|
+
</summary>
|
|
2528
|
+
<div class="detail muted">No additional observations.</div>
|
|
2529
|
+
</details>
|
|
2530
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l9 success dead-end rule every issue has a stable shape and a known code ">
|
|
2531
|
+
<summary>
|
|
2532
|
+
<span class="pill passed">PASS</span>
|
|
2533
|
+
<span class="id">L9</span>
|
|
2534
|
+
<span class="cat">Success dead-end rule</span>
|
|
2535
|
+
<span class="name">every issue has a stable shape and a known code</span>
|
|
2536
|
+
|
|
2537
|
+
<span class="ms">0.18 ms</span>
|
|
2538
|
+
</summary>
|
|
2539
|
+
<div class="detail"><span class="tag">observations</span><ul><li>codes observed :: "DUPLICATE_ENTRY, SUCCESS_DEAD_END, DEAD_END_NODE"</li></ul></div>
|
|
2540
|
+
</details>
|
|
2541
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l10 success dead-end rule lint: "warn" logs success_dead_end and still completes the c-19 run ">
|
|
2542
|
+
<summary>
|
|
2543
|
+
<span class="pill passed">PASS</span>
|
|
2544
|
+
<span class="id">L10</span>
|
|
2545
|
+
<span class="cat">Success dead-end rule</span>
|
|
2546
|
+
<span class="name">lint: "warn" logs SUCCESS_DEAD_END and still completes the C-19 run</span>
|
|
2547
|
+
|
|
2548
|
+
<span class="ms">26.19 ms</span>
|
|
2549
|
+
</summary>
|
|
2550
|
+
<div class="detail"><span class="tag">observations</span><ul><li>run status :: "COMPLETED" ; "| issue logged at severity 'error' but not enforced in warn mode"</li></ul></div>
|
|
2551
|
+
</details>
|
|
2552
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="true" data-search="l11 success dead-end rule lint: "error" rejects the c-19 graph before any node runs lint enforcement is a pre-flight gate — the graph is rejected before initialization finishes, so no side effects from node callbacks can occur">
|
|
2553
|
+
<summary>
|
|
2554
|
+
<span class="pill passed">PASS</span>
|
|
2555
|
+
<span class="id">L11</span>
|
|
2556
|
+
<span class="cat">Success dead-end rule</span>
|
|
2557
|
+
<span class="name">lint: "error" rejects the C-19 graph before any node runs</span>
|
|
2558
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2559
|
+
<span class="ms">0.33 ms</span>
|
|
2560
|
+
</summary>
|
|
2561
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>lint enforcement is a pre-flight gate — the graph is rejected before initialization finishes, so no side effects from node callbacks can occur</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: lint enforcement is a pre-flight gate — the graph is rejected before initialization finishes, so no side effects from node callbacks can occur</li></ul></div>
|
|
2562
|
+
</details>
|
|
2563
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l12 success dead-end rule the c-01 order-pipeline fixture flags audit as dead_end_node (documented gotcha) ">
|
|
2564
|
+
<summary>
|
|
2565
|
+
<span class="pill passed">PASS</span>
|
|
2566
|
+
<span class="id">L12</span>
|
|
2567
|
+
<span class="cat">Success dead-end rule</span>
|
|
2568
|
+
<span class="name">the C-01 order-pipeline fixture flags audit as DEAD_END_NODE (documented gotcha)</span>
|
|
2569
|
+
|
|
2570
|
+
<span class="ms">0.41 ms</span>
|
|
2571
|
+
</summary>
|
|
2572
|
+
<div class="detail"><span class="tag">observations</span><ul><li>audit :: "error/DEAD_END_NODE" ; "| run" ; "COMPLETED"</li></ul></div>
|
|
2573
|
+
</details>
|
|
2574
|
+
<details class="row ok lint" data-kind="lint" data-status="passed" data-finding="false" data-search="l13 success dead-end rule a graph with no transition problems lints clean and runs ">
|
|
2575
|
+
<summary>
|
|
2576
|
+
<span class="pill passed">PASS</span>
|
|
2577
|
+
<span class="id">L13</span>
|
|
2578
|
+
<span class="cat">Success dead-end rule</span>
|
|
2579
|
+
<span class="name">a graph with no transition problems lints clean and runs</span>
|
|
2580
|
+
|
|
2581
|
+
<span class="ms">0.25 ms</span>
|
|
2582
|
+
</summary>
|
|
2583
|
+
<div class="detail muted">No additional observations.</div>
|
|
2584
|
+
</details>
|
|
2585
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e1 typed edges & routing string edges keep the v1.0 meaning: unconditional fan-out `next: ["b","c"]` normalizes to two parallel edges — every existing graph keeps its behaviour">
|
|
2586
|
+
<summary>
|
|
2587
|
+
<span class="pill passed">PASS</span>
|
|
2588
|
+
<span class="id">E1</span>
|
|
2589
|
+
<span class="cat">Typed edges & routing</span>
|
|
2590
|
+
<span class="name">string edges keep the v1.0 meaning: unconditional fan-out</span>
|
|
2591
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2592
|
+
<span class="ms">0.24 ms</span>
|
|
2593
|
+
</summary>
|
|
2594
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>`next: ["b","c"]` normalizes to two parallel edges — every existing graph keeps its behaviour</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: `next: ["b","c"]` normalizes to two parallel edges — every existing graph keeps its behaviour</li></ul></div>
|
|
2595
|
+
</details>
|
|
2596
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e2 typed edges & routing result matches by deep equality and only the first matching edge fires ">
|
|
2597
|
+
<summary>
|
|
2598
|
+
<span class="pill passed">PASS</span>
|
|
2599
|
+
<span class="id">E2</span>
|
|
2600
|
+
<span class="cat">Typed edges & routing</span>
|
|
2601
|
+
<span class="name">result matches by deep equality and only the first matching edge fires</span>
|
|
2602
|
+
|
|
2603
|
+
<span class="ms">0.41 ms</span>
|
|
2604
|
+
</summary>
|
|
2605
|
+
<div class="detail muted">No additional observations.</div>
|
|
2606
|
+
</details>
|
|
2607
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e3 typed edges & routing deep equality matches nested objects regardless of key order result uses structural equality (key order, nesting and array order aware)">
|
|
2608
|
+
<summary>
|
|
2609
|
+
<span class="pill passed">PASS</span>
|
|
2610
|
+
<span class="id">E3</span>
|
|
2611
|
+
<span class="cat">Typed edges & routing</span>
|
|
2612
|
+
<span class="name">deep equality matches nested objects regardless of key order</span>
|
|
2613
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2614
|
+
<span class="ms">0.23 ms</span>
|
|
2615
|
+
</summary>
|
|
2616
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>result uses structural equality (key order, nesting and array order aware)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: result uses structural equality (key order, nesting and array order aware)</li></ul></div>
|
|
2617
|
+
</details>
|
|
2618
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e4 typed edges & routing result: nan matches a nan output (object.is semantics) ">
|
|
2619
|
+
<summary>
|
|
2620
|
+
<span class="pill passed">PASS</span>
|
|
2621
|
+
<span class="id">E4</span>
|
|
2622
|
+
<span class="cat">Typed edges & routing</span>
|
|
2623
|
+
<span class="name">result: NaN matches a NaN output (Object.is semantics)</span>
|
|
2624
|
+
|
|
2625
|
+
<span class="ms">0.22 ms</span>
|
|
2626
|
+
</summary>
|
|
2627
|
+
<div class="detail muted">No additional observations.</div>
|
|
2628
|
+
</details>
|
|
2629
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e5 typed edges & routing result: undefined matches an undefined output (presence, not truthiness) hasresult tracks key presence, so an undefined output is matchable">
|
|
2630
|
+
<summary>
|
|
2631
|
+
<span class="pill passed">PASS</span>
|
|
2632
|
+
<span class="id">E5</span>
|
|
2633
|
+
<span class="cat">Typed edges & routing</span>
|
|
2634
|
+
<span class="name">result: undefined matches an undefined output (presence, not truthiness)</span>
|
|
2635
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2636
|
+
<span class="ms">0.21 ms</span>
|
|
2637
|
+
</summary>
|
|
2638
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>hasResult tracks key presence, so an undefined output is matchable</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: hasResult tracks key presence, so an undefined output is matchable</li></ul></div>
|
|
2639
|
+
</details>
|
|
2640
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e6 typed edges & routing test predicate routes the activation ">
|
|
2641
|
+
<summary>
|
|
2642
|
+
<span class="pill passed">PASS</span>
|
|
2643
|
+
<span class="id">E6</span>
|
|
2644
|
+
<span class="cat">Typed edges & routing</span>
|
|
2645
|
+
<span class="name">test predicate routes the activation</span>
|
|
2646
|
+
|
|
2647
|
+
<span class="ms">0.18 ms</span>
|
|
2648
|
+
</summary>
|
|
2649
|
+
<div class="detail muted">No additional observations.</div>
|
|
2650
|
+
</details>
|
|
2651
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e7 typed edges & routing two matching conditionals: declaration order wins ">
|
|
2652
|
+
<summary>
|
|
2653
|
+
<span class="pill passed">PASS</span>
|
|
2654
|
+
<span class="id">E7</span>
|
|
2655
|
+
<span class="cat">Typed edges & routing</span>
|
|
2656
|
+
<span class="name">two matching conditionals: declaration order wins</span>
|
|
2657
|
+
|
|
2658
|
+
<span class="ms">0.17 ms</span>
|
|
2659
|
+
</summary>
|
|
2660
|
+
<div class="detail muted">No additional observations.</div>
|
|
2661
|
+
</details>
|
|
2662
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e8 typed edges & routing result + test on one edge must both pass (and) ">
|
|
2663
|
+
<summary>
|
|
2664
|
+
<span class="pill passed">PASS</span>
|
|
2665
|
+
<span class="id">E8</span>
|
|
2666
|
+
<span class="cat">Typed edges & routing</span>
|
|
2667
|
+
<span class="name">result + test on one edge must both pass (AND)</span>
|
|
2668
|
+
|
|
2669
|
+
<span class="ms">0.23 ms</span>
|
|
2670
|
+
</summary>
|
|
2671
|
+
<div class="detail muted">No additional observations.</div>
|
|
2672
|
+
</details>
|
|
2673
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e9 typed edges & routing the else edge (no matcher) fires when nothing earlier matched ">
|
|
2674
|
+
<summary>
|
|
2675
|
+
<span class="pill passed">PASS</span>
|
|
2676
|
+
<span class="id">E9</span>
|
|
2677
|
+
<span class="cat">Typed edges & routing</span>
|
|
2678
|
+
<span class="name">the else edge (no matcher) fires when nothing earlier matched</span>
|
|
2679
|
+
|
|
2680
|
+
<span class="ms">0.19 ms</span>
|
|
2681
|
+
</summary>
|
|
2682
|
+
<div class="detail muted">No additional observations.</div>
|
|
2683
|
+
</details>
|
|
2684
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e10 typed edges & routing no match is silent: nothing is scheduled, no routing error is recorded an unmatched conditional chain is silent by design (no no_edge_matched error)">
|
|
2685
|
+
<summary>
|
|
2686
|
+
<span class="pill passed">PASS</span>
|
|
2687
|
+
<span class="id">E10</span>
|
|
2688
|
+
<span class="cat">Typed edges & routing</span>
|
|
2689
|
+
<span class="name">no match is silent: nothing is scheduled, no routing error is recorded</span>
|
|
2690
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2691
|
+
<span class="ms">0.27 ms</span>
|
|
2692
|
+
</summary>
|
|
2693
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an unmatched conditional chain is silent by design (no NO_EDGE_MATCHED error)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an unmatched conditional chain is silent by design (no NO_EDGE_MATCHED error)</li></ul></div>
|
|
2694
|
+
</details>
|
|
2695
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e11 typed edges & routing parallel edges fire alongside the winning conditional ">
|
|
2696
|
+
<summary>
|
|
2697
|
+
<span class="pill passed">PASS</span>
|
|
2698
|
+
<span class="id">E11</span>
|
|
2699
|
+
<span class="cat">Typed edges & routing</span>
|
|
2700
|
+
<span class="name">parallel edges fire alongside the winning conditional</span>
|
|
2701
|
+
|
|
2702
|
+
<span class="ms">0.22 ms</span>
|
|
2703
|
+
</summary>
|
|
2704
|
+
<div class="detail muted">No additional observations.</div>
|
|
2705
|
+
</details>
|
|
2706
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e12 typed edges & routing a parallel edge is never blocked, even after a conditional match ">
|
|
2707
|
+
<summary>
|
|
2708
|
+
<span class="pill passed">PASS</span>
|
|
2709
|
+
<span class="id">E12</span>
|
|
2710
|
+
<span class="cat">Typed edges & routing</span>
|
|
2711
|
+
<span class="name">a parallel edge is never blocked, even after a conditional match</span>
|
|
2712
|
+
|
|
2713
|
+
<span class="ms">0.24 ms</span>
|
|
2714
|
+
</summary>
|
|
2715
|
+
<div class="detail muted">No additional observations.</div>
|
|
2716
|
+
</details>
|
|
2717
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e13 typed edges & routing a parallel edge with a matcher is still unconditional (matcher ignored, lint warns) ">
|
|
2718
|
+
<summary>
|
|
2719
|
+
<span class="pill passed">PASS</span>
|
|
2720
|
+
<span class="id">E13</span>
|
|
2721
|
+
<span class="cat">Typed edges & routing</span>
|
|
2722
|
+
<span class="name">a parallel edge with a matcher is still unconditional (matcher ignored, lint warns)</span>
|
|
2723
|
+
|
|
2724
|
+
<span class="ms">0.25 ms</span>
|
|
2725
|
+
</summary>
|
|
2726
|
+
<div class="detail muted">No additional observations.</div>
|
|
2727
|
+
</details>
|
|
2728
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e14 typed edges & routing returning new next(target, value) routes and successors see the unwrapped value next carries both destination and payload — successors and matchers see the payload">
|
|
2729
|
+
<summary>
|
|
2730
|
+
<span class="pill passed">PASS</span>
|
|
2731
|
+
<span class="id">E14</span>
|
|
2732
|
+
<span class="cat">Typed edges & routing</span>
|
|
2733
|
+
<span class="name">returning new Next(target, value) routes and successors see the unwrapped value</span>
|
|
2734
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2735
|
+
<span class="ms">0.25 ms</span>
|
|
2736
|
+
</summary>
|
|
2737
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>Next carries both destination and payload — successors and matchers see the payload</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: Next carries both destination and payload — successors and matchers see the payload</li></ul></div>
|
|
2738
|
+
</details>
|
|
2739
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e15 typed edges & routing context.goto(target) + return value routes for void/imperative nodes ">
|
|
2740
|
+
<summary>
|
|
2741
|
+
<span class="pill passed">PASS</span>
|
|
2742
|
+
<span class="id">E15</span>
|
|
2743
|
+
<span class="cat">Typed edges & routing</span>
|
|
2744
|
+
<span class="name">context.goto(target) + return value routes for void/imperative nodes</span>
|
|
2745
|
+
|
|
2746
|
+
<span class="ms">0.16 ms</span>
|
|
2747
|
+
</summary>
|
|
2748
|
+
<div class="detail muted">No additional observations.</div>
|
|
2749
|
+
</details>
|
|
2750
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e16 typed edges & routing a void node can route with goto alone ">
|
|
2751
|
+
<summary>
|
|
2752
|
+
<span class="pill passed">PASS</span>
|
|
2753
|
+
<span class="id">E16</span>
|
|
2754
|
+
<span class="cat">Typed edges & routing</span>
|
|
2755
|
+
<span class="name">a void node can route with goto alone</span>
|
|
2756
|
+
|
|
2757
|
+
<span class="ms">0.2 ms</span>
|
|
2758
|
+
</summary>
|
|
2759
|
+
<div class="detail muted">No additional observations.</div>
|
|
2760
|
+
</details>
|
|
2761
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e17 typed edges & routing an explicit route replaces the whole edge list, parallel edges included an explicit route is authoritative — declared edges (and parallel ones) are ignored">
|
|
2762
|
+
<summary>
|
|
2763
|
+
<span class="pill passed">PASS</span>
|
|
2764
|
+
<span class="id">E17</span>
|
|
2765
|
+
<span class="cat">Typed edges & routing</span>
|
|
2766
|
+
<span class="name">an explicit route replaces the whole edge list, parallel edges included</span>
|
|
2767
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2768
|
+
<span class="ms">0.2 ms</span>
|
|
2769
|
+
</summary>
|
|
2770
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an explicit route is authoritative — declared edges (and parallel ones) are ignored</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an explicit route is authoritative — declared edges (and parallel ones) are ignored</li></ul></div>
|
|
2771
|
+
</details>
|
|
2772
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e18 typed edges & routing return new next wins over context.goto when both are used ">
|
|
2773
|
+
<summary>
|
|
2774
|
+
<span class="pill passed">PASS</span>
|
|
2775
|
+
<span class="id">E18</span>
|
|
2776
|
+
<span class="cat">Typed edges & routing</span>
|
|
2777
|
+
<span class="name">return new Next wins over context.goto when both are used</span>
|
|
2778
|
+
|
|
2779
|
+
<span class="ms">0.15 ms</span>
|
|
2780
|
+
</summary>
|
|
2781
|
+
<div class="detail muted">No additional observations.</div>
|
|
2782
|
+
</details>
|
|
2783
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e19 typed edges & routing goto works per attempt: the route is taken by the successful attempt ">
|
|
2784
|
+
<summary>
|
|
2785
|
+
<span class="pill passed">PASS</span>
|
|
2786
|
+
<span class="id">E19</span>
|
|
2787
|
+
<span class="cat">Typed edges & routing</span>
|
|
2788
|
+
<span class="name">goto works per attempt: the route is taken by the successful attempt</span>
|
|
2789
|
+
|
|
2790
|
+
<span class="ms">5.6 ms</span>
|
|
2791
|
+
</summary>
|
|
2792
|
+
<div class="detail muted">No additional observations.</div>
|
|
2793
|
+
</details>
|
|
2794
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e20 typed edges & routing routing to an unknown node records invalid_goto_target and schedules nothing ">
|
|
2795
|
+
<summary>
|
|
2796
|
+
<span class="pill passed">PASS</span>
|
|
2797
|
+
<span class="id">E20</span>
|
|
2798
|
+
<span class="cat">Typed edges & routing</span>
|
|
2799
|
+
<span class="name">routing to an unknown node records INVALID_GOTO_TARGET and schedules nothing</span>
|
|
2800
|
+
|
|
2801
|
+
<span class="ms">0.45 ms</span>
|
|
2802
|
+
</summary>
|
|
2803
|
+
<div class="detail muted">No additional observations.</div>
|
|
2804
|
+
</details>
|
|
2805
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e21 typed edges & routing new next with an empty target throws invalid_next_target immediately ">
|
|
2806
|
+
<summary>
|
|
2807
|
+
<span class="pill passed">PASS</span>
|
|
2808
|
+
<span class="id">E21</span>
|
|
2809
|
+
<span class="cat">Typed edges & routing</span>
|
|
2810
|
+
<span class="name">new Next with an empty target throws INVALID_NEXT_TARGET immediately</span>
|
|
2811
|
+
|
|
2812
|
+
<span class="ms">0.06 ms</span>
|
|
2813
|
+
</summary>
|
|
2814
|
+
<div class="detail muted">No additional observations.</div>
|
|
2815
|
+
</details>
|
|
2816
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e22 typed edges & routing a terminal node ignores its edges and its routing, and lint warns about it terminal detection happens before routing — a terminal node never schedules successors">
|
|
2817
|
+
<summary>
|
|
2818
|
+
<span class="pill passed">PASS</span>
|
|
2819
|
+
<span class="id">E22</span>
|
|
2820
|
+
<span class="cat">Typed edges & routing</span>
|
|
2821
|
+
<span class="name">a terminal node ignores its edges and its routing, and lint warns about it</span>
|
|
2822
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2823
|
+
<span class="ms">0.22 ms</span>
|
|
2824
|
+
</summary>
|
|
2825
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>terminal detection happens before routing — a terminal node never schedules successors</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: terminal detection happens before routing — a terminal node never schedules successors</li></ul></div>
|
|
2826
|
+
</details>
|
|
2827
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e23 typed edges & routing lint flags an exclusive edge declared after an else edge as unreachable an else edge shadows every exclusive edge declared after it — runtime agrees with lint">
|
|
2828
|
+
<summary>
|
|
2829
|
+
<span class="pill passed">PASS</span>
|
|
2830
|
+
<span class="id">E23</span>
|
|
2831
|
+
<span class="cat">Typed edges & routing</span>
|
|
2832
|
+
<span class="name">lint flags an exclusive edge declared after an else edge as unreachable</span>
|
|
2833
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2834
|
+
<span class="ms">0.34 ms</span>
|
|
2835
|
+
</summary>
|
|
2836
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an else edge shadows every exclusive edge declared after it — runtime agrees with lint</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an else edge shadows every exclusive edge declared after it — runtime agrees with lint</li></ul></div>
|
|
2837
|
+
</details>
|
|
2838
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e24 typed edges & routing malformed edge entries are rejected at construction time ">
|
|
2839
|
+
<summary>
|
|
2840
|
+
<span class="pill passed">PASS</span>
|
|
2841
|
+
<span class="id">E24</span>
|
|
2842
|
+
<span class="cat">Typed edges & routing</span>
|
|
2843
|
+
<span class="name">malformed edge entries are rejected at construction time</span>
|
|
2844
|
+
|
|
2845
|
+
<span class="ms">0.41 ms</span>
|
|
2846
|
+
</summary>
|
|
2847
|
+
<div class="detail muted">No additional observations.</div>
|
|
2848
|
+
</details>
|
|
2849
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="true" data-search="e25 typed edges & routing the a → b/c/d/e/f picture runs as one execution — the router is no longer needed with typed edges the whole picture is one execution and lint-clean — no router, no gate, no drain policy needed">
|
|
2850
|
+
<summary>
|
|
2851
|
+
<span class="pill passed">PASS</span>
|
|
2852
|
+
<span class="id">E25</span>
|
|
2853
|
+
<span class="cat">Typed edges & routing</span>
|
|
2854
|
+
<span class="name">the a → b/c/d/e/f picture runs as ONE execution — the router is no longer needed</span>
|
|
2855
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2856
|
+
<span class="ms">11.8 ms</span>
|
|
2857
|
+
</summary>
|
|
2858
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>with typed edges the whole picture is ONE execution and lint-clean — no router, no gate, no DRAIN policy needed</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>seed 1 :: "a,b,f (attempts 1)"</li><li>seed 2 :: "a,c (attempts 1)"</li><li>seed 3 :: "a,d (attempts 1)"</li><li>seed "throw" :: "a,e (attempts 2)"</li><li>seed "retry" :: "a,f (attempts 2)"</li><li>finding: with typed edges the whole picture is ONE execution and lint-clean — no router, no gate, no DRAIN policy needed</li></ul></div>
|
|
2859
|
+
</details>
|
|
2860
|
+
<details class="row ok edges" data-kind="edges" data-status="passed" data-finding="false" data-search="e26 typed edges & routing lint is clean for the payoff graph (routes declared, no dead edges) ">
|
|
2861
|
+
<summary>
|
|
2862
|
+
<span class="pill passed">PASS</span>
|
|
2863
|
+
<span class="id">E26</span>
|
|
2864
|
+
<span class="cat">Typed edges & routing</span>
|
|
2865
|
+
<span class="name">lint is clean for the payoff graph (routes declared, no dead edges)</span>
|
|
2866
|
+
|
|
2867
|
+
<span class="ms">0.44 ms</span>
|
|
2868
|
+
</summary>
|
|
2869
|
+
<div class="detail"><span class="tag">observations</span><ul><li>graph linted clean and ran under lint: "error"</li></ul></div>
|
|
2870
|
+
</details>
|
|
2871
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r1 function registry a node whose run is a registered name executes that function report.results[i].fn — not report.results[i].output — is the audit link to the registered source">
|
|
2872
|
+
<summary>
|
|
2873
|
+
<span class="pill passed">PASS</span>
|
|
2874
|
+
<span class="id">R1</span>
|
|
2875
|
+
<span class="cat">Function registry</span>
|
|
2876
|
+
<span class="name">a node whose run is a registered NAME executes that function</span>
|
|
2877
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2878
|
+
<span class="ms">0.67 ms</span>
|
|
2879
|
+
</summary>
|
|
2880
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>report.results[i].fn — not report.results[i].output — is the audit link to the registered source</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: report.results[i].fn — not report.results[i].output — is the audit link to the registered source</li></ul></div>
|
|
2881
|
+
</details>
|
|
2882
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r2 function registry a graph-local function overrides the engine's shared entry ">
|
|
2883
|
+
<summary>
|
|
2884
|
+
<span class="pill passed">PASS</span>
|
|
2885
|
+
<span class="id">R2</span>
|
|
2886
|
+
<span class="cat">Function registry</span>
|
|
2887
|
+
<span class="name">a graph-local function overrides the engine's shared entry</span>
|
|
2888
|
+
|
|
2889
|
+
<span class="ms">0.45 ms</span>
|
|
2890
|
+
</summary>
|
|
2891
|
+
<div class="detail muted">No additional observations.</div>
|
|
2892
|
+
</details>
|
|
2893
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r3 function registry graph-local functions work with no engine registry at all ">
|
|
2894
|
+
<summary>
|
|
2895
|
+
<span class="pill passed">PASS</span>
|
|
2896
|
+
<span class="id">R3</span>
|
|
2897
|
+
<span class="cat">Function registry</span>
|
|
2898
|
+
<span class="name">graph-local functions work with no engine registry at all</span>
|
|
2899
|
+
|
|
2900
|
+
<span class="ms">0.2 ms</span>
|
|
2901
|
+
</summary>
|
|
2902
|
+
<div class="detail muted">No additional observations.</div>
|
|
2903
|
+
</details>
|
|
2904
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r4 function registry registerfunction() after construction is honoured (resolution is lazy) an engine with an empty registry reports no `registry` field, but registerfunction() makes it appear">
|
|
2905
|
+
<summary>
|
|
2906
|
+
<span class="pill passed">PASS</span>
|
|
2907
|
+
<span class="id">R4</span>
|
|
2908
|
+
<span class="cat">Function registry</span>
|
|
2909
|
+
<span class="name">registerFunction() after construction is honoured (resolution is lazy)</span>
|
|
2910
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2911
|
+
<span class="ms">0.26 ms</span>
|
|
2912
|
+
</summary>
|
|
2913
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an engine with an empty registry reports no `registry` field, but registerFunction() makes it appear</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an engine with an empty registry reports no `registry` field, but registerFunction() makes it appear</li></ul></div>
|
|
2914
|
+
</details>
|
|
2915
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r5 function registry inline functions and registered names coexist in one graph ">
|
|
2916
|
+
<summary>
|
|
2917
|
+
<span class="pill passed">PASS</span>
|
|
2918
|
+
<span class="id">R5</span>
|
|
2919
|
+
<span class="cat">Function registry</span>
|
|
2920
|
+
<span class="name">inline functions and registered names coexist in one graph</span>
|
|
2921
|
+
|
|
2922
|
+
<span class="ms">0.24 ms</span>
|
|
2923
|
+
</summary>
|
|
2924
|
+
<div class="detail muted">No additional observations.</div>
|
|
2925
|
+
</details>
|
|
2926
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r6 function registry a registered node function receives a full nodecontext ">
|
|
2927
|
+
<summary>
|
|
2928
|
+
<span class="pill passed">PASS</span>
|
|
2929
|
+
<span class="id">R6</span>
|
|
2930
|
+
<span class="cat">Function registry</span>
|
|
2931
|
+
<span class="name">a registered node function receives a full NodeContext</span>
|
|
2932
|
+
|
|
2933
|
+
<span class="ms">0.24 ms</span>
|
|
2934
|
+
</summary>
|
|
2935
|
+
<div class="detail muted">No additional observations.</div>
|
|
2936
|
+
</details>
|
|
2937
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r7 function registry a registered async function is awaited ">
|
|
2938
|
+
<summary>
|
|
2939
|
+
<span class="pill passed">PASS</span>
|
|
2940
|
+
<span class="id">R7</span>
|
|
2941
|
+
<span class="cat">Function registry</span>
|
|
2942
|
+
<span class="name">a registered async function is awaited</span>
|
|
2943
|
+
|
|
2944
|
+
<span class="ms">5.47 ms</span>
|
|
2945
|
+
</summary>
|
|
2946
|
+
<div class="detail muted">No additional observations.</div>
|
|
2947
|
+
</details>
|
|
2948
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r8 function registry a registered node can route explicitly with next and with context.goto `new next(target, value)` sets the router's output to `value` (that is what edge matchers and context.outputs see); the target node still executes its own function">
|
|
2949
|
+
<summary>
|
|
2950
|
+
<span class="pill passed">PASS</span>
|
|
2951
|
+
<span class="id">R8</span>
|
|
2952
|
+
<span class="cat">Function registry</span>
|
|
2953
|
+
<span class="name">a registered node can route explicitly with Next and with context.goto</span>
|
|
2954
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2955
|
+
<span class="ms">0.67 ms</span>
|
|
2956
|
+
</summary>
|
|
2957
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>`new Next(target, value)` sets the ROUTER's output to `value` (that is what edge matchers and context.outputs see); the target node still executes its own function</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: `new Next(target, value)` sets the ROUTER's output to `value` (that is what edge matchers and context.outputs see); the target node still executes its own function</li></ul></div>
|
|
2958
|
+
</details>
|
|
2959
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r9 function registry timeouts and retries apply to registered functions exactly as to inline ones ">
|
|
2960
|
+
<summary>
|
|
2961
|
+
<span class="pill passed">PASS</span>
|
|
2962
|
+
<span class="id">R9</span>
|
|
2963
|
+
<span class="cat">Function registry</span>
|
|
2964
|
+
<span class="name">timeouts and retries apply to registered functions exactly as to inline ones</span>
|
|
2965
|
+
|
|
2966
|
+
<span class="ms">21.6 ms</span>
|
|
2967
|
+
</summary>
|
|
2968
|
+
<div class="detail muted">No additional observations.</div>
|
|
2969
|
+
</details>
|
|
2970
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r10 function registry a missing run name records unknown_function (unhandled) and schedules nothing ">
|
|
2971
|
+
<summary>
|
|
2972
|
+
<span class="pill passed">PASS</span>
|
|
2973
|
+
<span class="id">R10</span>
|
|
2974
|
+
<span class="cat">Function registry</span>
|
|
2975
|
+
<span class="name">a missing run name records UNKNOWN_FUNCTION (unhandled) and schedules nothing</span>
|
|
2976
|
+
|
|
2977
|
+
<span class="ms">0.48 ms</span>
|
|
2978
|
+
</summary>
|
|
2979
|
+
<div class="detail muted">No additional observations.</div>
|
|
2980
|
+
</details>
|
|
2981
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r11 function registry a missing run name is permanent: no retry, no onthrow, no fallback retry/onthrow/fallback are error recovery; a name that was never registered is a wiring defect, so the engine refuses to recover from it">
|
|
2982
|
+
<summary>
|
|
2983
|
+
<span class="pill passed">PASS</span>
|
|
2984
|
+
<span class="id">R11</span>
|
|
2985
|
+
<span class="cat">Function registry</span>
|
|
2986
|
+
<span class="name">a missing run name is PERMANENT: no retry, no onThrow, no fallback</span>
|
|
2987
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
2988
|
+
<span class="ms">0.26 ms</span>
|
|
2989
|
+
</summary>
|
|
2990
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>retry/onThrow/fallback are error RECOVERY; a name that was never registered is a wiring defect, so the engine refuses to recover from it</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: retry/onThrow/fallback are error RECOVERY; a name that was never registered is a wiring defect, so the engine refuses to recover from it</li></ul></div>
|
|
2991
|
+
</details>
|
|
2992
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r12 function registry a missing run name ignores fallback policy as well ">
|
|
2993
|
+
<summary>
|
|
2994
|
+
<span class="pill passed">PASS</span>
|
|
2995
|
+
<span class="id">R12</span>
|
|
2996
|
+
<span class="cat">Function registry</span>
|
|
2997
|
+
<span class="name">a missing run name ignores FALLBACK policy as well</span>
|
|
2998
|
+
|
|
2999
|
+
<span class="ms">0.19 ms</span>
|
|
3000
|
+
</summary>
|
|
3001
|
+
<div class="detail muted">No additional observations.</div>
|
|
3002
|
+
</details>
|
|
3003
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r13 function registry registering the missing name mid-run lets the next activation succeed ">
|
|
3004
|
+
<summary>
|
|
3005
|
+
<span class="pill passed">PASS</span>
|
|
3006
|
+
<span class="id">R13</span>
|
|
3007
|
+
<span class="cat">Function registry</span>
|
|
3008
|
+
<span class="name">registering the missing name mid-run lets the next activation succeed</span>
|
|
3009
|
+
|
|
3010
|
+
<span class="ms">0.28 ms</span>
|
|
3011
|
+
</summary>
|
|
3012
|
+
<div class="detail muted">No additional observations.</div>
|
|
3013
|
+
</details>
|
|
3014
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r14 function registry a named edge test decides the branch, and result + test still and ">
|
|
3015
|
+
<summary>
|
|
3016
|
+
<span class="pill passed">PASS</span>
|
|
3017
|
+
<span class="id">R14</span>
|
|
3018
|
+
<span class="cat">Function registry</span>
|
|
3019
|
+
<span class="name">a named edge test decides the branch, and result + test still AND</span>
|
|
3020
|
+
|
|
3021
|
+
<span class="ms">0.35 ms</span>
|
|
3022
|
+
</summary>
|
|
3023
|
+
<div class="detail muted">No additional observations.</div>
|
|
3024
|
+
</details>
|
|
3025
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r15 function registry inline and named tests mix in one chain, in declaration order ">
|
|
3026
|
+
<summary>
|
|
3027
|
+
<span class="pill passed">PASS</span>
|
|
3028
|
+
<span class="id">R15</span>
|
|
3029
|
+
<span class="cat">Function registry</span>
|
|
3030
|
+
<span class="name">inline and named tests mix in one chain, in declaration order</span>
|
|
3031
|
+
|
|
3032
|
+
<span class="ms">0.28 ms</span>
|
|
3033
|
+
</summary>
|
|
3034
|
+
<div class="detail muted">No additional observations.</div>
|
|
3035
|
+
</details>
|
|
3036
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r16 function registry an unresolvable edge test never matches, is recorded once, and lets the else edge run an unresolvable test is loud but not fatal to routing — the rest of the chain still evaluates; the run itself settles failed because the error stays unhandled (terminal-reached + unhandled error = failed, as in v1.2)">
|
|
3037
|
+
<summary>
|
|
3038
|
+
<span class="pill passed">PASS</span>
|
|
3039
|
+
<span class="id">R16</span>
|
|
3040
|
+
<span class="cat">Function registry</span>
|
|
3041
|
+
<span class="name">an unresolvable edge test never matches, is recorded once, and lets the else edge run</span>
|
|
3042
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3043
|
+
<span class="ms">0.3 ms</span>
|
|
3044
|
+
</summary>
|
|
3045
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>an unresolvable test is loud but not fatal to ROUTING — the rest of the chain still evaluates; the run itself settles FAILED because the error stays unhandled (terminal-reached + unhandled error = FAILED, as in v1.2)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: an unresolvable test is loud but not fatal to ROUTING — the rest of the chain still evaluates; the run itself settles FAILED because the error stays unhandled (terminal-reached + unhandled error = FAILED, as in v1.2)</li></ul></div>
|
|
3046
|
+
</details>
|
|
3047
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r17 function registry a repeated evaluation reports a missing test only once (retry path) ">
|
|
3048
|
+
<summary>
|
|
3049
|
+
<span class="pill passed">PASS</span>
|
|
3050
|
+
<span class="id">R17</span>
|
|
3051
|
+
<span class="cat">Function registry</span>
|
|
3052
|
+
<span class="name">a repeated evaluation reports a missing test only once (retry path)</span>
|
|
3053
|
+
|
|
3054
|
+
<span class="ms">1.65 ms</span>
|
|
3055
|
+
</summary>
|
|
3056
|
+
<div class="detail muted">No additional observations.</div>
|
|
3057
|
+
</details>
|
|
3058
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r18 function registry lint treats a named test as conditional — no false unreachable_edge regression guard — before edgehasmatcher() was shared, a named test looked like an else edge to the lint and every later edge was reported unreachable_edge">
|
|
3059
|
+
<summary>
|
|
3060
|
+
<span class="pill passed">PASS</span>
|
|
3061
|
+
<span class="id">R18</span>
|
|
3062
|
+
<span class="cat">Function registry</span>
|
|
3063
|
+
<span class="name">lint treats a NAMED test as conditional — no false UNREACHABLE_EDGE</span>
|
|
3064
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3065
|
+
<span class="ms">0.3 ms</span>
|
|
3066
|
+
</summary>
|
|
3067
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>regression guard — before edgeHasMatcher() was shared, a named test looked like an else edge to the lint and every later edge was reported UNREACHABLE_EDGE</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: regression guard — before edgeHasMatcher() was shared, a named test looked like an else edge to the lint and every later edge was reported UNREACHABLE_EDGE</li></ul></div>
|
|
3068
|
+
</details>
|
|
3069
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r19 function registry a parallel edge with a named test still warns parallel_edge_matcher_ignored ">
|
|
3070
|
+
<summary>
|
|
3071
|
+
<span class="pill passed">PASS</span>
|
|
3072
|
+
<span class="id">R19</span>
|
|
3073
|
+
<span class="cat">Function registry</span>
|
|
3074
|
+
<span class="name">a PARALLEL edge with a named test still warns PARALLEL_EDGE_MATCHER_IGNORED</span>
|
|
3075
|
+
|
|
3076
|
+
<span class="ms">0.27 ms</span>
|
|
3077
|
+
</summary>
|
|
3078
|
+
<div class="detail muted">No additional observations.</div>
|
|
3079
|
+
</details>
|
|
3080
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r20 function registry graph.ready and the report carry { fingerprint, names }; both are absent without a registry ">
|
|
3081
|
+
<summary>
|
|
3082
|
+
<span class="pill passed">PASS</span>
|
|
3083
|
+
<span class="id">R20</span>
|
|
3084
|
+
<span class="cat">Function registry</span>
|
|
3085
|
+
<span class="name">graph.ready and the report carry { fingerprint, names }; both are absent without a registry</span>
|
|
3086
|
+
|
|
3087
|
+
<span class="ms">0.4 ms</span>
|
|
3088
|
+
</summary>
|
|
3089
|
+
<div class="detail muted">No additional observations.</div>
|
|
3090
|
+
</details>
|
|
3091
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r21 function registry every checkpoint carries the registry identity ">
|
|
3092
|
+
<summary>
|
|
3093
|
+
<span class="pill passed">PASS</span>
|
|
3094
|
+
<span class="id">R21</span>
|
|
3095
|
+
<span class="cat">Function registry</span>
|
|
3096
|
+
<span class="name">every checkpoint carries the registry identity</span>
|
|
3097
|
+
|
|
3098
|
+
<span class="ms">0.35 ms</span>
|
|
3099
|
+
</summary>
|
|
3100
|
+
<div class="detail muted">No additional observations.</div>
|
|
3101
|
+
</details>
|
|
3102
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r22 function registry functionregistry: register/extend/has/get/names/snapshot stay consistent ">
|
|
3103
|
+
<summary>
|
|
3104
|
+
<span class="pill passed">PASS</span>
|
|
3105
|
+
<span class="id">R22</span>
|
|
3106
|
+
<span class="cat">Function registry</span>
|
|
3107
|
+
<span class="name">FunctionRegistry: register/extend/has/get/names/snapshot stay consistent</span>
|
|
3108
|
+
|
|
3109
|
+
<span class="ms">0.18 ms</span>
|
|
3110
|
+
</summary>
|
|
3111
|
+
<div class="detail muted">No additional observations.</div>
|
|
3112
|
+
</details>
|
|
3113
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r23 function registry the fingerprint is stable, order-independent, and source-sensitive the fingerprint covers names + function source text — two closures of the same source share it, while a captured value that changes at runtime does not show up">
|
|
3114
|
+
<summary>
|
|
3115
|
+
<span class="pill passed">PASS</span>
|
|
3116
|
+
<span class="id">R23</span>
|
|
3117
|
+
<span class="cat">Function registry</span>
|
|
3118
|
+
<span class="name">the fingerprint is stable, order-independent, and source-sensitive</span>
|
|
3119
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3120
|
+
<span class="ms">0.19 ms</span>
|
|
3121
|
+
</summary>
|
|
3122
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the fingerprint covers names + function SOURCE TEXT — two closures of the same source share it, while a captured value that changes at runtime does not show up</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the fingerprint covers names + function SOURCE TEXT — two closures of the same source share it, while a captured value that changes at runtime does not show up</li></ul></div>
|
|
3123
|
+
</details>
|
|
3124
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r24 function registry invalid registrations fail immediately ">
|
|
3125
|
+
<summary>
|
|
3126
|
+
<span class="pill passed">PASS</span>
|
|
3127
|
+
<span class="id">R24</span>
|
|
3128
|
+
<span class="cat">Function registry</span>
|
|
3129
|
+
<span class="name">invalid registrations fail immediately</span>
|
|
3130
|
+
|
|
3131
|
+
<span class="ms">0.16 ms</span>
|
|
3132
|
+
</summary>
|
|
3133
|
+
<div class="detail muted">No additional observations.</div>
|
|
3134
|
+
</details>
|
|
3135
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r25 function registry malformed run values and graph tables are rejected at construction ">
|
|
3136
|
+
<summary>
|
|
3137
|
+
<span class="pill passed">PASS</span>
|
|
3138
|
+
<span class="id">R25</span>
|
|
3139
|
+
<span class="cat">Function registry</span>
|
|
3140
|
+
<span class="name">malformed run values and graph tables are rejected at construction</span>
|
|
3141
|
+
|
|
3142
|
+
<span class="ms">0.2 ms</span>
|
|
3143
|
+
</summary>
|
|
3144
|
+
<div class="detail muted">No additional observations.</div>
|
|
3145
|
+
</details>
|
|
3146
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="true" data-search="r26 function registry nodefunctions()/edgetests() restore per-signature inference one table holds both signatures; a bare literal cannot infer a parameter type from the union, hence nodefunctions()/edgetests()">
|
|
3147
|
+
<summary>
|
|
3148
|
+
<span class="pill passed">PASS</span>
|
|
3149
|
+
<span class="id">R26</span>
|
|
3150
|
+
<span class="cat">Function registry</span>
|
|
3151
|
+
<span class="name">nodeFunctions()/edgeTests() restore per-signature inference</span>
|
|
3152
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3153
|
+
<span class="ms">0.28 ms</span>
|
|
3154
|
+
</summary>
|
|
3155
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>one table holds both signatures; a bare literal cannot infer a parameter type from the union, hence nodeFunctions()/edgeTests()</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: one table holds both signatures; a bare literal cannot infer a parameter type from the union, hence nodeFunctions()/edgeTests()</li></ul></div>
|
|
3156
|
+
</details>
|
|
3157
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r27 function registry the report stays json-serializable with a registry configured ">
|
|
3158
|
+
<summary>
|
|
3159
|
+
<span class="pill passed">PASS</span>
|
|
3160
|
+
<span class="id">R27</span>
|
|
3161
|
+
<span class="cat">Function registry</span>
|
|
3162
|
+
<span class="name">the report stays JSON-serializable with a registry configured</span>
|
|
3163
|
+
|
|
3164
|
+
<span class="ms">0.31 ms</span>
|
|
3165
|
+
</summary>
|
|
3166
|
+
<div class="detail muted">No additional observations.</div>
|
|
3167
|
+
</details>
|
|
3168
|
+
<details class="row ok registry" data-kind="registry" data-status="passed" data-finding="false" data-search="r28 function registry the unknown_function record is self-describing ">
|
|
3169
|
+
<summary>
|
|
3170
|
+
<span class="pill passed">PASS</span>
|
|
3171
|
+
<span class="id">R28</span>
|
|
3172
|
+
<span class="cat">Function registry</span>
|
|
3173
|
+
<span class="name">the UNKNOWN_FUNCTION record is self-describing</span>
|
|
3174
|
+
|
|
3175
|
+
<span class="ms">0.27 ms</span>
|
|
3176
|
+
</summary>
|
|
3177
|
+
<div class="detail muted">No additional observations.</div>
|
|
3178
|
+
</details>
|
|
3179
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="true" data-search="g1 graph json loader a valid document parses into a graphdefinition (string and object input agree) parsing never needs the registry — a data file is valid even when a function name is unknown; the engine decides that at run time">
|
|
3180
|
+
<summary>
|
|
3181
|
+
<span class="pill passed">PASS</span>
|
|
3182
|
+
<span class="id">G1</span>
|
|
3183
|
+
<span class="cat">Graph JSON loader</span>
|
|
3184
|
+
<span class="name">a valid document parses into a GraphDefinition (string and object input agree)</span>
|
|
3185
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3186
|
+
<span class="ms">1.22 ms</span>
|
|
3187
|
+
</summary>
|
|
3188
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>parsing never needs the registry — a data file is valid even when a function name is unknown; the engine decides that at run time</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: parsing never needs the registry — a data file is valid even when a function name is unknown; the engine decides that at run time</li></ul></div>
|
|
3189
|
+
</details>
|
|
3190
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g2 graph json loader node ids default to their keys, and a mismatching explicit id is an issue ">
|
|
3191
|
+
<summary>
|
|
3192
|
+
<span class="pill passed">PASS</span>
|
|
3193
|
+
<span class="id">G2</span>
|
|
3194
|
+
<span class="cat">Graph JSON loader</span>
|
|
3195
|
+
<span class="name">node ids default to their keys, and a mismatching explicit id is an issue</span>
|
|
3196
|
+
|
|
3197
|
+
<span class="ms">0.29 ms</span>
|
|
3198
|
+
</summary>
|
|
3199
|
+
<div class="detail muted">No additional observations.</div>
|
|
3200
|
+
</details>
|
|
3201
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g3 graph json loader deep-equality results, named tests and parallel flags survive the round trip ">
|
|
3202
|
+
<summary>
|
|
3203
|
+
<span class="pill passed">PASS</span>
|
|
3204
|
+
<span class="id">G3</span>
|
|
3205
|
+
<span class="cat">Graph JSON loader</span>
|
|
3206
|
+
<span class="name">deep-equality results, named tests and parallel flags survive the round trip</span>
|
|
3207
|
+
|
|
3208
|
+
<span class="ms">0.14 ms</span>
|
|
3209
|
+
</summary>
|
|
3210
|
+
<div class="detail muted">No additional observations.</div>
|
|
3211
|
+
</details>
|
|
3212
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g4 graph json loader createenginefromjson runs the data file and reports the registry fingerprint ">
|
|
3213
|
+
<summary>
|
|
3214
|
+
<span class="pill passed">PASS</span>
|
|
3215
|
+
<span class="id">G4</span>
|
|
3216
|
+
<span class="cat">Graph JSON loader</span>
|
|
3217
|
+
<span class="name">createEngineFromJSON runs the data file and reports the registry fingerprint</span>
|
|
3218
|
+
|
|
3219
|
+
<span class="ms">0.56 ms</span>
|
|
3220
|
+
</summary>
|
|
3221
|
+
<div class="detail muted">No additional observations.</div>
|
|
3222
|
+
</details>
|
|
3223
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g5 graph json loader a named test in the document routes via the supplied registry ">
|
|
3224
|
+
<summary>
|
|
3225
|
+
<span class="pill passed">PASS</span>
|
|
3226
|
+
<span class="id">G5</span>
|
|
3227
|
+
<span class="cat">Graph JSON loader</span>
|
|
3228
|
+
<span class="name">a named test in the document routes via the supplied registry</span>
|
|
3229
|
+
|
|
3230
|
+
<span class="ms">0.33 ms</span>
|
|
3231
|
+
</summary>
|
|
3232
|
+
<div class="detail muted">No additional observations.</div>
|
|
3233
|
+
</details>
|
|
3234
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g6 graph json loader a data file with an unknown name runs and fails with unknown_function ">
|
|
3235
|
+
<summary>
|
|
3236
|
+
<span class="pill passed">PASS</span>
|
|
3237
|
+
<span class="id">G6</span>
|
|
3238
|
+
<span class="cat">Graph JSON loader</span>
|
|
3239
|
+
<span class="name">a data file with an unknown name runs and fails with UNKNOWN_FUNCTION</span>
|
|
3240
|
+
|
|
3241
|
+
<span class="ms">0.57 ms</span>
|
|
3242
|
+
</summary>
|
|
3243
|
+
<div class="detail muted">No additional observations.</div>
|
|
3244
|
+
</details>
|
|
3245
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g7 graph json loader the parsed definition is accepted by the engine unchanged ">
|
|
3246
|
+
<summary>
|
|
3247
|
+
<span class="pill passed">PASS</span>
|
|
3248
|
+
<span class="id">G7</span>
|
|
3249
|
+
<span class="cat">Graph JSON loader</span>
|
|
3250
|
+
<span class="name">the parsed definition is accepted by the engine unchanged</span>
|
|
3251
|
+
|
|
3252
|
+
<span class="ms">0.36 ms</span>
|
|
3253
|
+
</summary>
|
|
3254
|
+
<div class="detail muted">No additional observations.</div>
|
|
3255
|
+
</details>
|
|
3256
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g8 graph json loader invalid json text is a single, clear graphjsonerror ">
|
|
3257
|
+
<summary>
|
|
3258
|
+
<span class="pill passed">PASS</span>
|
|
3259
|
+
<span class="id">G8</span>
|
|
3260
|
+
<span class="cat">Graph JSON loader</span>
|
|
3261
|
+
<span class="name">invalid JSON text is a single, clear GraphJSONError</span>
|
|
3262
|
+
|
|
3263
|
+
<span class="ms">0.12 ms</span>
|
|
3264
|
+
</summary>
|
|
3265
|
+
<div class="detail muted">No additional observations.</div>
|
|
3266
|
+
</details>
|
|
3267
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g9 graph json loader a non-object document is rejected with one issue ">
|
|
3268
|
+
<summary>
|
|
3269
|
+
<span class="pill passed">PASS</span>
|
|
3270
|
+
<span class="id">G9</span>
|
|
3271
|
+
<span class="cat">Graph JSON loader</span>
|
|
3272
|
+
<span class="name">a non-object document is rejected with one issue</span>
|
|
3273
|
+
|
|
3274
|
+
<span class="ms">0.08 ms</span>
|
|
3275
|
+
</summary>
|
|
3276
|
+
<div class="detail muted">No additional observations.</div>
|
|
3277
|
+
</details>
|
|
3278
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g10 graph json loader unknown properties are rejected at every level ">
|
|
3279
|
+
<summary>
|
|
3280
|
+
<span class="pill passed">PASS</span>
|
|
3281
|
+
<span class="id">G10</span>
|
|
3282
|
+
<span class="cat">Graph JSON loader</span>
|
|
3283
|
+
<span class="name">unknown properties are rejected at every level</span>
|
|
3284
|
+
|
|
3285
|
+
<span class="ms">0.18 ms</span>
|
|
3286
|
+
</summary>
|
|
3287
|
+
<div class="detail muted">No additional observations.</div>
|
|
3288
|
+
</details>
|
|
3289
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g11 graph json loader functions cannot live in the document — the issue points at the engine options ">
|
|
3290
|
+
<summary>
|
|
3291
|
+
<span class="pill passed">PASS</span>
|
|
3292
|
+
<span class="id">G11</span>
|
|
3293
|
+
<span class="cat">Graph JSON loader</span>
|
|
3294
|
+
<span class="name">functions cannot live in the document — the issue points at the engine options</span>
|
|
3295
|
+
|
|
3296
|
+
<span class="ms">0.11 ms</span>
|
|
3297
|
+
</summary>
|
|
3298
|
+
<div class="detail muted">No additional observations.</div>
|
|
3299
|
+
</details>
|
|
3300
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g12 graph json loader dangling references are reported with their paths ">
|
|
3301
|
+
<summary>
|
|
3302
|
+
<span class="pill passed">PASS</span>
|
|
3303
|
+
<span class="id">G12</span>
|
|
3304
|
+
<span class="cat">Graph JSON loader</span>
|
|
3305
|
+
<span class="name">dangling references are reported with their paths</span>
|
|
3306
|
+
|
|
3307
|
+
<span class="ms">0.13 ms</span>
|
|
3308
|
+
</summary>
|
|
3309
|
+
<div class="detail muted">No additional observations.</div>
|
|
3310
|
+
</details>
|
|
3311
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g13 graph json loader malformed edges are rejected entry by entry ">
|
|
3312
|
+
<summary>
|
|
3313
|
+
<span class="pill passed">PASS</span>
|
|
3314
|
+
<span class="id">G13</span>
|
|
3315
|
+
<span class="cat">Graph JSON loader</span>
|
|
3316
|
+
<span class="name">malformed edges are rejected entry by entry</span>
|
|
3317
|
+
|
|
3318
|
+
<span class="ms">0.19 ms</span>
|
|
3319
|
+
</summary>
|
|
3320
|
+
<div class="detail muted">No additional observations.</div>
|
|
3321
|
+
</details>
|
|
3322
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g14 graph json loader invalid scalars, policies and retry blocks are rejected ">
|
|
3323
|
+
<summary>
|
|
3324
|
+
<span class="pill passed">PASS</span>
|
|
3325
|
+
<span class="id">G14</span>
|
|
3326
|
+
<span class="cat">Graph JSON loader</span>
|
|
3327
|
+
<span class="name">invalid scalars, policies and retry blocks are rejected</span>
|
|
3328
|
+
|
|
3329
|
+
<span class="ms">0.19 ms</span>
|
|
3330
|
+
</summary>
|
|
3331
|
+
<div class="detail muted">No additional observations.</div>
|
|
3332
|
+
</details>
|
|
3333
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="true" data-search="g15 graph json loader every issue is collected — one throw carries them all one document reported 5 problems in a single throw — no fix-one-rerun loop">
|
|
3334
|
+
<summary>
|
|
3335
|
+
<span class="pill passed">PASS</span>
|
|
3336
|
+
<span class="id">G15</span>
|
|
3337
|
+
<span class="cat">Graph JSON loader</span>
|
|
3338
|
+
<span class="name">EVERY issue is collected — one throw carries them all</span>
|
|
3339
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3340
|
+
<span class="ms">0.18 ms</span>
|
|
3341
|
+
</summary>
|
|
3342
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>one document reported 5 problems in a single throw — no fix-one-rerun loop</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: one document reported 5 problems in a single throw — no fix-one-rerun loop</li></ul></div>
|
|
3343
|
+
</details>
|
|
3344
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g16 graph json loader isgraphjson() is a cheap shape probe, not a validator ">
|
|
3345
|
+
<summary>
|
|
3346
|
+
<span class="pill passed">PASS</span>
|
|
3347
|
+
<span class="id">G16</span>
|
|
3348
|
+
<span class="cat">Graph JSON loader</span>
|
|
3349
|
+
<span class="name">isGraphJSON() is a cheap shape probe, not a validator</span>
|
|
3350
|
+
|
|
3351
|
+
<span class="ms">0.13 ms</span>
|
|
3352
|
+
</summary>
|
|
3353
|
+
<div class="detail muted">No additional observations.</div>
|
|
3354
|
+
</details>
|
|
3355
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g17 graph json loader an in-memory object may pass real functions through (escape hatch) ">
|
|
3356
|
+
<summary>
|
|
3357
|
+
<span class="pill passed">PASS</span>
|
|
3358
|
+
<span class="id">G17</span>
|
|
3359
|
+
<span class="cat">Graph JSON loader</span>
|
|
3360
|
+
<span class="name">an in-memory object may pass real functions through (escape hatch)</span>
|
|
3361
|
+
|
|
3362
|
+
<span class="ms">0.24 ms</span>
|
|
3363
|
+
</summary>
|
|
3364
|
+
<div class="detail muted">No additional observations.</div>
|
|
3365
|
+
</details>
|
|
3366
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="true" data-search="g18 graph json loader a parsed document with dangling ids is still caught by the engine if it is hand-edited the loader and the engine validate different layers (paths vs. final shape) — both stay in force">
|
|
3367
|
+
<summary>
|
|
3368
|
+
<span class="pill passed">PASS</span>
|
|
3369
|
+
<span class="id">G18</span>
|
|
3370
|
+
<span class="cat">Graph JSON loader</span>
|
|
3371
|
+
<span class="name">a parsed document with dangling ids is still caught by the engine if it is hand-edited</span>
|
|
3372
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3373
|
+
<span class="ms">0.17 ms</span>
|
|
3374
|
+
</summary>
|
|
3375
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the loader and the engine validate different layers (paths vs. final shape) — both stay in force</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the loader and the engine validate different layers (paths vs. final shape) — both stay in force</li></ul></div>
|
|
3376
|
+
</details>
|
|
3377
|
+
<details class="row ok graphjson" data-kind="graphjson" data-status="passed" data-finding="false" data-search="g19 graph json loader the loader example document is valid (regression: the shipped .json file) ">
|
|
3378
|
+
<summary>
|
|
3379
|
+
<span class="pill passed">PASS</span>
|
|
3380
|
+
<span class="id">G19</span>
|
|
3381
|
+
<span class="cat">Graph JSON loader</span>
|
|
3382
|
+
<span class="name">the loader example document is valid (regression: the shipped .json file)</span>
|
|
3383
|
+
|
|
3384
|
+
<span class="ms">0.53 ms</span>
|
|
3385
|
+
</summary>
|
|
3386
|
+
<div class="detail muted">No additional observations.</div>
|
|
3387
|
+
</details>
|
|
3388
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s1 script loading a .cjs script is required and its export table becomes the registry a registered name is not rewritten — `classifyorder` stays `classifyorder`, the namespace only owns the claim">
|
|
3389
|
+
<summary>
|
|
3390
|
+
<span class="pill passed">PASS</span>
|
|
3391
|
+
<span class="id">S1</span>
|
|
3392
|
+
<span class="cat">Script loading</span>
|
|
3393
|
+
<span class="name">a .cjs script is required and its export table becomes the registry</span>
|
|
3394
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3395
|
+
<span class="ms">1.62 ms</span>
|
|
3396
|
+
</summary>
|
|
3397
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>a registered name is not rewritten — `classifyOrder` stays `classifyOrder`, the namespace only owns the claim</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: a registered name is not rewritten — `classifyOrder` stays `classifyOrder`, the namespace only owns the claim</li></ul></div>
|
|
3398
|
+
</details>
|
|
3399
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s2 script loading an .mjs script is imported as an es module ">
|
|
3400
|
+
<summary>
|
|
3401
|
+
<span class="pill passed">PASS</span>
|
|
3402
|
+
<span class="id">S2</span>
|
|
3403
|
+
<span class="cat">Script loading</span>
|
|
3404
|
+
<span class="name">an .mjs script is imported as an ES module</span>
|
|
3405
|
+
|
|
3406
|
+
<span class="ms">5.98 ms</span>
|
|
3407
|
+
</summary>
|
|
3408
|
+
<div class="detail muted">No additional observations.</div>
|
|
3409
|
+
</details>
|
|
3410
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s3 script loading a .js script with esm syntax is detected as esm; without it, as commonjs .js detection is a source hint with a fallback — the other format is attempted before failing, so a mis-hint costs one retry, never a failed load">
|
|
3411
|
+
<summary>
|
|
3412
|
+
<span class="pill passed">PASS</span>
|
|
3413
|
+
<span class="id">S3</span>
|
|
3414
|
+
<span class="cat">Script loading</span>
|
|
3415
|
+
<span class="name">a .js script with ESM syntax is detected as ESM; without it, as CommonJS</span>
|
|
3416
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3417
|
+
<span class="ms">2.16 ms</span>
|
|
3418
|
+
</summary>
|
|
3419
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>.js detection is a source hint with a fallback — the other format is attempted before failing, so a mis-hint costs one retry, never a failed load</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: .js detection is a source hint with a fallback — the other format is attempted before failing, so a mis-hint costs one retry, never a failed load</li></ul></div>
|
|
3420
|
+
</details>
|
|
3421
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s4 script loading an explicit format is honoured and never retried in the other format ">
|
|
3422
|
+
<summary>
|
|
3423
|
+
<span class="pill passed">PASS</span>
|
|
3424
|
+
<span class="id">S4</span>
|
|
3425
|
+
<span class="cat">Script loading</span>
|
|
3426
|
+
<span class="name">an explicit format is honoured and never retried in the other format</span>
|
|
3427
|
+
|
|
3428
|
+
<span class="ms">4.02 ms</span>
|
|
3429
|
+
</summary>
|
|
3430
|
+
<div class="detail muted">No additional observations.</div>
|
|
3431
|
+
</details>
|
|
3432
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s5 script loading inline commonjs source runs with a real require and module ">
|
|
3433
|
+
<summary>
|
|
3434
|
+
<span class="pill passed">PASS</span>
|
|
3435
|
+
<span class="id">S5</span>
|
|
3436
|
+
<span class="cat">Script loading</span>
|
|
3437
|
+
<span class="name">inline CommonJS source runs with a real require and module</span>
|
|
3438
|
+
|
|
3439
|
+
<span class="ms">0.44 ms</span>
|
|
3440
|
+
</summary>
|
|
3441
|
+
<div class="detail muted">No additional observations.</div>
|
|
3442
|
+
</details>
|
|
3443
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s6 script loading inline esm source is evaluated from a data url ">
|
|
3444
|
+
<summary>
|
|
3445
|
+
<span class="pill passed">PASS</span>
|
|
3446
|
+
<span class="id">S6</span>
|
|
3447
|
+
<span class="cat">Script loading</span>
|
|
3448
|
+
<span class="name">inline ESM source is evaluated from a data URL</span>
|
|
3449
|
+
|
|
3450
|
+
<span class="ms">0.69 ms</span>
|
|
3451
|
+
</summary>
|
|
3452
|
+
<div class="detail muted">No additional observations.</div>
|
|
3453
|
+
</details>
|
|
3454
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s7 script loading url scripts are fetched and evaluated (cjs by default, esm by hint) ">
|
|
3455
|
+
<summary>
|
|
3456
|
+
<span class="pill passed">PASS</span>
|
|
3457
|
+
<span class="id">S7</span>
|
|
3458
|
+
<span class="cat">Script loading</span>
|
|
3459
|
+
<span class="name">URL scripts are fetched and evaluated (CJS by default, ESM by hint)</span>
|
|
3460
|
+
|
|
3461
|
+
<span class="ms">0.83 ms</span>
|
|
3462
|
+
</summary>
|
|
3463
|
+
<div class="detail muted">No additional observations.</div>
|
|
3464
|
+
</details>
|
|
3465
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s8 script loading a script can register itself through globalthis.graphengine the engine global is a per-call slot (registerenginenamespace), not a shared mutable table — a script can only ever add its own namespace, and only once">
|
|
3466
|
+
<summary>
|
|
3467
|
+
<span class="pill passed">PASS</span>
|
|
3468
|
+
<span class="id">S8</span>
|
|
3469
|
+
<span class="cat">Script loading</span>
|
|
3470
|
+
<span class="name">a script can register itself through globalThis.GraphEngine</span>
|
|
3471
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3472
|
+
<span class="ms">0.65 ms</span>
|
|
3473
|
+
</summary>
|
|
3474
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the engine global is a per-CALL slot (registerEngineNamespace), not a shared mutable table — a script can only ever add its own namespace, and only once</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the engine global is a per-CALL slot (registerEngineNamespace), not a shared mutable table — a script can only ever add its own namespace, and only once</li></ul></div>
|
|
3475
|
+
</details>
|
|
3476
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s9 script loading the realm is restored after the load — the engine global does not leak ">
|
|
3477
|
+
<summary>
|
|
3478
|
+
<span class="pill passed">PASS</span>
|
|
3479
|
+
<span class="id">S9</span>
|
|
3480
|
+
<span class="cat">Script loading</span>
|
|
3481
|
+
<span class="name">the realm is restored after the load — the engine global does not leak</span>
|
|
3482
|
+
|
|
3483
|
+
<span class="ms">0.83 ms</span>
|
|
3484
|
+
</summary>
|
|
3485
|
+
<div class="detail muted">No additional observations.</div>
|
|
3486
|
+
</details>
|
|
3487
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s10 script loading a script can both self-register and export; both land in the namespace ">
|
|
3488
|
+
<summary>
|
|
3489
|
+
<span class="pill passed">PASS</span>
|
|
3490
|
+
<span class="id">S10</span>
|
|
3491
|
+
<span class="cat">Script loading</span>
|
|
3492
|
+
<span class="name">a script can both self-register and export; both land in the namespace</span>
|
|
3493
|
+
|
|
3494
|
+
<span class="ms">0.84 ms</span>
|
|
3495
|
+
</summary>
|
|
3496
|
+
<div class="detail muted">No additional observations.</div>
|
|
3497
|
+
</details>
|
|
3498
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s11 script loading the declared namespace must match what the script registers ">
|
|
3499
|
+
<summary>
|
|
3500
|
+
<span class="pill passed">PASS</span>
|
|
3501
|
+
<span class="id">S11</span>
|
|
3502
|
+
<span class="cat">Script loading</span>
|
|
3503
|
+
<span class="name">the declared namespace must match what the script registers</span>
|
|
3504
|
+
|
|
3505
|
+
<span class="ms">0.31 ms</span>
|
|
3506
|
+
</summary>
|
|
3507
|
+
<div class="detail muted">No additional observations.</div>
|
|
3508
|
+
</details>
|
|
3509
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s12 script loading a registration error from inside the script surfaces unwrapped ">
|
|
3510
|
+
<summary>
|
|
3511
|
+
<span class="pill passed">PASS</span>
|
|
3512
|
+
<span class="id">S12</span>
|
|
3513
|
+
<span class="cat">Script loading</span>
|
|
3514
|
+
<span class="name">a registration error from inside the script surfaces unwrapped</span>
|
|
3515
|
+
|
|
3516
|
+
<span class="ms">0.38 ms</span>
|
|
3517
|
+
</summary>
|
|
3518
|
+
<div class="detail muted">No additional observations.</div>
|
|
3519
|
+
</details>
|
|
3520
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s13 script loading a namespace can be claimed only once per process (exports path) the freeze is process-global by design — one document, one engine per namespace. loading the same graph file into a second engine throws until the claims are reset">
|
|
3521
|
+
<summary>
|
|
3522
|
+
<span class="pill passed">PASS</span>
|
|
3523
|
+
<span class="id">S13</span>
|
|
3524
|
+
<span class="cat">Script loading</span>
|
|
3525
|
+
<span class="name">a namespace can be claimed only once per process (exports path)</span>
|
|
3526
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3527
|
+
<span class="ms">0.67 ms</span>
|
|
3528
|
+
</summary>
|
|
3529
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the freeze is PROCESS-global by design — one document, one engine per namespace. Loading the same graph file into a second engine throws until the claims are reset</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the freeze is PROCESS-global by design — one document, one engine per namespace. Loading the same graph file into a second engine throws until the claims are reset</li></ul></div>
|
|
3530
|
+
</details>
|
|
3531
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s14 script loading a self-registering script throws on the duplicate claim from inside the script ">
|
|
3532
|
+
<summary>
|
|
3533
|
+
<span class="pill passed">PASS</span>
|
|
3534
|
+
<span class="id">S14</span>
|
|
3535
|
+
<span class="cat">Script loading</span>
|
|
3536
|
+
<span class="name">a self-registering script throws on the duplicate claim FROM INSIDE the script</span>
|
|
3537
|
+
|
|
3538
|
+
<span class="ms">0.46 ms</span>
|
|
3539
|
+
</summary>
|
|
3540
|
+
<div class="detail muted">No additional observations.</div>
|
|
3541
|
+
</details>
|
|
3542
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s15 script loading a claim made before a crashing script survives; the load still fails claims are made at registration time, not at load end — a script that registers and then throws leaves its namespace claimed (reload needs resetgraphscriptnamespaces)">
|
|
3543
|
+
<summary>
|
|
3544
|
+
<span class="pill passed">PASS</span>
|
|
3545
|
+
<span class="id">S15</span>
|
|
3546
|
+
<span class="cat">Script loading</span>
|
|
3547
|
+
<span class="name">a claim made before a crashing script survives; the load still fails</span>
|
|
3548
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3549
|
+
<span class="ms">0.99 ms</span>
|
|
3550
|
+
</summary>
|
|
3551
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>claims are made at registration time, not at load end — a script that registers and then throws leaves its namespace claimed (reload needs resetGraphScriptNamespaces)</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: claims are made at registration time, not at load end — a script that registers and then throws leaves its namespace claimed (reload needs resetGraphScriptNamespaces)</li></ul></div>
|
|
3552
|
+
</details>
|
|
3553
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s16 script loading a script that throws is not replayed in the other format format fallback replays the script body, so it is reserved for module-format failures (err_require_esm, esm syntax in cjs). a script that throws — or registers and then throws — is never re-executed; it ran once and its claim stands">
|
|
3554
|
+
<summary>
|
|
3555
|
+
<span class="pill passed">PASS</span>
|
|
3556
|
+
<span class="id">S16</span>
|
|
3557
|
+
<span class="cat">Script loading</span>
|
|
3558
|
+
<span class="name">a script that throws is not replayed in the other format</span>
|
|
3559
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3560
|
+
<span class="ms">0.43 ms</span>
|
|
3561
|
+
</summary>
|
|
3562
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>format fallback replays the script body, so it is reserved for module-format failures (ERR_REQUIRE_ESM, ESM syntax in CJS). A script that throws — or registers and then throws — is never re-executed; it ran once and its claim stands</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: format fallback replays the script body, so it is reserved for module-format failures (ERR_REQUIRE_ESM, ESM syntax in CJS). A script that throws — or registers and then throws — is never re-executed; it ran once and its claim stands</li></ul></div>
|
|
3563
|
+
</details>
|
|
3564
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s17 script loading two scripts providing the same name collide; override is opt-in claims and name collisions are separate gates — the freeze stops the namespace, collisions stop the merged table, and only the second one has an override">
|
|
3565
|
+
<summary>
|
|
3566
|
+
<span class="pill passed">PASS</span>
|
|
3567
|
+
<span class="id">S17</span>
|
|
3568
|
+
<span class="cat">Script loading</span>
|
|
3569
|
+
<span class="name">two scripts providing the same name collide; override is opt-in</span>
|
|
3570
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3571
|
+
<span class="ms">0.73 ms</span>
|
|
3572
|
+
</summary>
|
|
3573
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>claims and name collisions are separate gates — the freeze stops the namespace, collisions stop the merged table, and only the second one has an override</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: claims and name collisions are separate gates — the freeze stops the namespace, collisions stop the merged table, and only the second one has an override</li></ul></div>
|
|
3574
|
+
</details>
|
|
3575
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s18 script loading script declarations are validated, with json paths ">
|
|
3576
|
+
<summary>
|
|
3577
|
+
<span class="pill passed">PASS</span>
|
|
3578
|
+
<span class="id">S18</span>
|
|
3579
|
+
<span class="cat">Script loading</span>
|
|
3580
|
+
<span class="name">script declarations are validated, with JSON paths</span>
|
|
3581
|
+
|
|
3582
|
+
<span class="ms">0.32 ms</span>
|
|
3583
|
+
</summary>
|
|
3584
|
+
<div class="detail muted">No additional observations.</div>
|
|
3585
|
+
</details>
|
|
3586
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s19 script loading the same namespace twice in one document is a parse issue ">
|
|
3587
|
+
<summary>
|
|
3588
|
+
<span class="pill passed">PASS</span>
|
|
3589
|
+
<span class="id">S19</span>
|
|
3590
|
+
<span class="cat">Script loading</span>
|
|
3591
|
+
<span class="name">the same namespace twice in one document is a parse issue</span>
|
|
3592
|
+
|
|
3593
|
+
<span class="ms">0.1 ms</span>
|
|
3594
|
+
</summary>
|
|
3595
|
+
<div class="detail muted">No additional observations.</div>
|
|
3596
|
+
</details>
|
|
3597
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s20 script loading a scripted document still parses with the v1.4 entry point `scripts` is validated by the isomorphic parser and executed by the node loader — parsegraphjson (sync, v1.4) keeps working on scripted documents">
|
|
3598
|
+
<summary>
|
|
3599
|
+
<span class="pill passed">PASS</span>
|
|
3600
|
+
<span class="id">S20</span>
|
|
3601
|
+
<span class="cat">Script loading</span>
|
|
3602
|
+
<span class="name">a scripted document still parses with the v1.4 entry point</span>
|
|
3603
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3604
|
+
<span class="ms">0.12 ms</span>
|
|
3605
|
+
</summary>
|
|
3606
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>`scripts` is validated by the isomorphic parser and executed by the Node loader — parseGraphJSON (sync, v1.4) keeps working on scripted documents</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: `scripts` is validated by the isomorphic parser and executed by the Node loader — parseGraphJSON (sync, v1.4) keeps working on scripted documents</li></ul></div>
|
|
3607
|
+
</details>
|
|
3608
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s21 script loading the document is validated before any script executes ">
|
|
3609
|
+
<summary>
|
|
3610
|
+
<span class="pill passed">PASS</span>
|
|
3611
|
+
<span class="id">S21</span>
|
|
3612
|
+
<span class="cat">Script loading</span>
|
|
3613
|
+
<span class="name">the document is validated BEFORE any script executes</span>
|
|
3614
|
+
|
|
3615
|
+
<span class="ms">0.14 ms</span>
|
|
3616
|
+
</summary>
|
|
3617
|
+
<div class="detail muted">No additional observations.</div>
|
|
3618
|
+
</details>
|
|
3619
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s22 script loading a missing file, a crashing script and a function-less script fail clearly ">
|
|
3620
|
+
<summary>
|
|
3621
|
+
<span class="pill passed">PASS</span>
|
|
3622
|
+
<span class="id">S22</span>
|
|
3623
|
+
<span class="cat">Script loading</span>
|
|
3624
|
+
<span class="name">a missing file, a crashing script and a function-less script fail clearly</span>
|
|
3625
|
+
|
|
3626
|
+
<span class="ms">0.65 ms</span>
|
|
3627
|
+
</summary>
|
|
3628
|
+
<div class="detail muted">No additional observations.</div>
|
|
3629
|
+
</details>
|
|
3630
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s23 script loading a scripted document runs: the script provides the node and edge functions end-to-end, 6 functions arrive from path:./order.cjs and the engine reports fnr1:6:b43eadc7">
|
|
3631
|
+
<summary>
|
|
3632
|
+
<span class="pill passed">PASS</span>
|
|
3633
|
+
<span class="id">S23</span>
|
|
3634
|
+
<span class="cat">Script loading</span>
|
|
3635
|
+
<span class="name">a scripted document runs: the script provides the node and edge functions</span>
|
|
3636
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3637
|
+
<span class="ms">0.65 ms</span>
|
|
3638
|
+
</summary>
|
|
3639
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>end-to-end, 6 functions arrive from path:./order.cjs and the engine reports fnr1:6:b43eadc7</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: end-to-end, 6 functions arrive from path:./order.cjs and the engine reports fnr1:6:b43eadc7</li></ul></div>
|
|
3640
|
+
</details>
|
|
3641
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s24 script loading a script's own sibling requires resolve from the script's directory ">
|
|
3642
|
+
<summary>
|
|
3643
|
+
<span class="pill passed">PASS</span>
|
|
3644
|
+
<span class="id">S24</span>
|
|
3645
|
+
<span class="cat">Script loading</span>
|
|
3646
|
+
<span class="name">a script's own sibling requires resolve from the script's directory</span>
|
|
3647
|
+
|
|
3648
|
+
<span class="ms">0.56 ms</span>
|
|
3649
|
+
</summary>
|
|
3650
|
+
<div class="detail muted">No additional observations.</div>
|
|
3651
|
+
</details>
|
|
3652
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="true" data-search="s25 script loading inline scripts compose with path scripts in one document the three media (path, source, url) are interchangeable — one pipeline merges them into a single table with one fingerprint">
|
|
3653
|
+
<summary>
|
|
3654
|
+
<span class="pill passed">PASS</span>
|
|
3655
|
+
<span class="id">S25</span>
|
|
3656
|
+
<span class="cat">Script loading</span>
|
|
3657
|
+
<span class="name">inline scripts compose with path scripts in one document</span>
|
|
3658
|
+
<span class="star" title="documents an engine semantic">finding</span>
|
|
3659
|
+
<span class="ms">0.43 ms</span>
|
|
3660
|
+
</summary>
|
|
3661
|
+
<div class="detail finding"><span class="tag">findings</span><ul><li>the three media (path, source, url) are interchangeable — one pipeline merges them into a single table with one fingerprint</li></ul></div><div class="detail"><span class="tag">observations</span><ul><li>finding: the three media (path, source, url) are interchangeable — one pipeline merges them into a single table with one fingerprint</li></ul></div>
|
|
3662
|
+
</details>
|
|
3663
|
+
<details class="row ok scripts" data-kind="scripts" data-status="passed" data-finding="false" data-search="s26 script loading the loaded table is frozen and the engine can be built from it directly ">
|
|
3664
|
+
<summary>
|
|
3665
|
+
<span class="pill passed">PASS</span>
|
|
3666
|
+
<span class="id">S26</span>
|
|
3667
|
+
<span class="cat">Script loading</span>
|
|
3668
|
+
<span class="name">the loaded table is frozen and the engine can be built from it directly</span>
|
|
3669
|
+
|
|
3670
|
+
<span class="ms">0.46 ms</span>
|
|
3671
|
+
</summary>
|
|
3672
|
+
<div class="detail muted">No additional observations.</div>
|
|
3673
|
+
</details>
|
|
3674
|
+
</div>
|
|
3675
|
+
|
|
3676
|
+
<h2>How the suite was run</h2>
|
|
3677
|
+
<div class="note">
|
|
3678
|
+
<p style="margin-top:0"><code>npx tsc -p tsconfig.json</code> compiles <code>src/</code> and the tests to <code>js/</code>,
|
|
3679
|
+
<code>npx tsc -p tsconfig.browser.json</code> proves the core is isomorphic (DOM libs, no Node types — asserted by the
|
|
3680
|
+
UPGRADE pack), then <code>node js/tests/runner.js</code> executes all 282 cases (100 unit + 20 complex + 20 async + 19 upgrade + 11 conformance + 13 lint + 26 edges + 28 registry + 19 json + 26 scripts) and writes
|
|
3681
|
+
<code>report/report.json</code> plus this page. No third-party test framework: <code>tests/harness.ts</code> provides
|
|
3682
|
+
exception-based checks, per-test timeouts and log capture.</p>
|
|
3683
|
+
<p>Artifacts: <code>src/automategraph.ts</code> (engine), <code>src/storage-adapter.ts</code> (adapter contract +
|
|
3684
|
+
wire format), <code>src/storage-conformance.ts</code> (adapter checker), <code>tests/unit.test.ts</code>,
|
|
3685
|
+
<code>tests/complex.test.ts</code>, <code>tests/async.test.ts</code>, <code>tests/upgrade.test.ts</code>,
|
|
3686
|
+
<code>tests/conformance.test.ts</code>, <code>tests/lint.test.ts</code>, <code>tests/edges.test.ts</code>, <code>tests/registry.test.ts</code>, <code>tests/graphjson.test.ts</code>, <code>tests/scripts.test.ts</code>, <code>docs/diagrams/</code>,
|
|
3687
|
+
<code>CHANGELOG.md</code>, <code>UPGRADE-PROPOSAL.md</code>.</p>
|
|
3688
|
+
</div>
|
|
3689
|
+
|
|
3690
|
+
<footer>
|
|
3691
|
+
All 282 tests passed. Findings above are deliberate documentation of observed engine behaviour, not failures.
|
|
3692
|
+
</footer>
|
|
3693
|
+
</div>
|
|
3694
|
+
<script>
|
|
3695
|
+
(function () {
|
|
3696
|
+
var active = "all";
|
|
3697
|
+
var buttons = Array.prototype.slice.call(document.querySelectorAll(".btn[data-filter]"));
|
|
3698
|
+
var rows = Array.prototype.slice.call(document.querySelectorAll("#rows > details"));
|
|
3699
|
+
var query = document.getElementById("q");
|
|
3700
|
+
|
|
3701
|
+
function apply() {
|
|
3702
|
+
var needle = (query.value || "").trim().toLowerCase();
|
|
3703
|
+
rows.forEach(function (row) {
|
|
3704
|
+
var kindOk =
|
|
3705
|
+
active === "all" ||
|
|
3706
|
+
(active === "failed" && row.dataset.status === "failed") ||
|
|
3707
|
+
(active === "finding" && row.dataset.finding === "true") ||
|
|
3708
|
+
row.dataset.kind === active;
|
|
3709
|
+
var textOk = needle === "" || row.dataset.search.indexOf(needle) !== -1;
|
|
3710
|
+
row.style.display = kindOk && textOk ? "" : "none";
|
|
3711
|
+
});
|
|
3712
|
+
}
|
|
3713
|
+
|
|
3714
|
+
buttons.forEach(function (button) {
|
|
3715
|
+
button.addEventListener("click", function () {
|
|
3716
|
+
active = button.dataset.filter;
|
|
3717
|
+
buttons.forEach(function (other) { other.classList.toggle("active", other === button); });
|
|
3718
|
+
apply();
|
|
3719
|
+
});
|
|
3720
|
+
});
|
|
3721
|
+
|
|
3722
|
+
query.addEventListener("input", apply);
|
|
3723
|
+
apply();
|
|
3724
|
+
})();
|
|
3725
|
+
</script>
|
|
3726
|
+
</body>
|
|
3727
|
+
</html>
|