-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
475 lines (457 loc) · 36.4 KB
/
Copy pathindex.html
File metadata and controls
475 lines (457 loc) · 36.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
<meta name="description" content="GraphABI is Semantic Compatibility Infrastructure for agent graphs. Find the first edge where valid structure carries incompatible meaning.">
<meta name="theme-color" content="#FBFCFD" media="(prefers-color-scheme: light)">
<meta name="theme-color" content="#0B0F14" media="(prefers-color-scheme: dark)">
<meta name="color-scheme" content="light dark">
<meta property="og:type" content="website">
<meta property="og:url" content="https://graphabi.github.io/">
<meta property="og:title" content="GraphABI: Your schema passed. Your agent still broke.">
<meta property="og:description" content="Find the first semantic break, inspect the recorded witness, and trace everything downstream.">
<meta property="og:image" content="https://graphabi.github.io/assets/open-graph.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta name="twitter:card" content="summary_large_image">
<link rel="canonical" href="https://graphabi.github.io/">
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="styles.css">
<title>GraphABI: Semantic Compatibility Infrastructure</title>
<script type="application/ld+json">{"@context":"https://schema.org","@type":"SoftwareSourceCode","name":"GraphABI","description":"Semantic Compatibility Infrastructure for agent graphs.","codeRepository":"https://github.com/graphabi/graphabi","license":"https://www.apache.org/licenses/LICENSE-2.0","programmingLanguage":"Python","url":"https://graphabi.github.io/"}</script>
<!-- Scroll-revealed state is only hidden when there is something able to
reveal it, so the page is complete without JavaScript. -->
<script>document.documentElement.classList.add("js")</script>
<script defer src="field.js"></script>
<script defer src="motion.js"></script>
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<!--
The ambient field is the unbounded semantic flow of a live agent graph:
organic, continuous, never resolving. Every product surface below it is
the opposite by design: precise, deterministic, and it stops.
-->
<canvas class="field" data-field aria-hidden="true"></canvas>
<div class="field-veil" aria-hidden="true"></div>
<header class="site-header">
<nav class="shell nav" aria-label="Primary navigation">
<a class="brand" href="#top">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 64 64" width="30" height="30" focusable="false">
<circle cx="9" cy="32" r="5" class="m-live"/>
<path d="M14 32H28" class="m-live-stroke"/>
<path d="M36 32H50" class="m-dead-stroke"/>
<circle cx="55" cy="32" r="5" class="m-dead"/>
<path d="M29 26L35 31M29 33L35 38" class="m-cut"/>
</svg>
</span>
<span class="brand-word">GraphABI</span>
</a>
<div class="nav-links">
<a href="#contracts"><span>Contracts</span></a>
<a href="#architecture"><span>Architecture</span></a>
<a href="https://github.com/graphabi/graphabi/tree/main/docs"><span>Docs</span></a>
<a class="nav-github" href="https://github.com/graphabi/graphabi">GitHub <svg viewBox="0 0 12 12" width="11" height="11" aria-hidden="true" focusable="false"><path d="M3 9L9 3M9 3H4M9 3V8"/></svg></a>
</div>
</nav>
</header>
<main id="main">
<section id="top" class="hero shell" aria-labelledby="hero-title">
<div class="hero-copy">
<p class="eyebrow"><i aria-hidden="true"></i>Semantic Compatibility Infrastructure</p>
<h1 id="hero-title"><span class="line">Your schema passed.</span><span class="line">Your agent still <em>broke.</em></span></h1>
<p class="hero-lede">GraphABI finds the first edge where meaning changed, shows the exact recorded witness, and traces every downstream node that may be affected.</p>
<div class="hero-actions">
<button class="button primary" type="button" data-open-setup>Try GraphABI</button>
<a class="button secondary" href="https://github.com/graphabi/graphabi">View on GitHub <svg viewBox="0 0 12 12" width="11" height="11" aria-hidden="true" focusable="false"><path d="M3 9L9 3M9 3H4M9 3V8"/></svg></a>
</div>
<div class="install-line">
<span class="install-prompt" aria-hidden="true">$</span>
<code data-copy-source tabindex="0" role="region" aria-label="Demo command; scroll horizontally if needed">uvx --from git+https://github.com/graphabi/graphabi graphabi demo --allow-breaking</code>
<button class="install-copy" type="button" data-copy-inline aria-label="Copy demo command">
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false" class="i-copy"><rect x="5.5" y="5.5" width="8" height="8" rx="1.6"/><path d="M10.5 3.5H3.5a1 1 0 0 0-1 1v7"/></svg>
<svg viewBox="0 0 16 16" width="14" height="14" aria-hidden="true" focusable="false" class="i-done"><path d="M3.5 8.5L6.5 11.5L12.5 5"/></svg>
</button>
</div>
</div>
<div class="pulse-scene is-complete" data-pulse-scene>
<div class="scene-toolbar">
<div class="scene-meta">
<span class="scene-kicker">Recorded graph</span>
<span class="scene-phase" data-scene-phase>Break found · researcher → verifier</span>
</div>
<button class="replay" type="button" data-replay>
<svg viewBox="0 0 16 16" width="13" height="13" aria-hidden="true" focusable="false"><path d="M13 8a5 5 0 1 1-1.7-3.8"/><path d="M13.2 2.4V5.2H10.4"/></svg>
Replay semantic flow
</button>
</div>
<div class="scene-status" role="group" aria-label="Compatibility result">
<div class="status schema-status"><span>Schema</span><strong>✓ PASS</strong><small>same ResearchResult</small></div>
<div class="status semantic-status"><span>Semantics</span><strong>× BREAKING</strong><small>trace-backed</small></div>
</div>
<div class="graph-flow" role="img" aria-label="The semantic pulse stops between researcher and verifier. Verifier, decision maker, and publisher are affected downstream.">
<div class="graph-node producer" style="--n:0"><span class="node-dot" aria-hidden="true"></span><strong>researcher</strong><small>candidate producer</small></div>
<div class="graph-edge first-edge" style="--e:0"><span class="rail" aria-hidden="true"></span><span class="rail-live" aria-hidden="true"></span><span class="pulse" aria-hidden="true"></span><span class="break-mark" aria-hidden="true"><i></i><i></i></span><span class="edge-caption">First break</span></div>
<div class="graph-node direct" style="--n:1"><span class="node-dot" aria-hidden="true"></span><strong>verifier</strong><small>directly affected</small></div>
<div class="graph-edge blast-edge" style="--e:1"><span class="rail" aria-hidden="true"></span><span class="rail-live" aria-hidden="true"></span><span class="pulse" aria-hidden="true"></span></div>
<div class="graph-node affected" style="--n:2"><span class="node-dot" aria-hidden="true"></span><strong>decision_maker</strong><small>affected downstream</small></div>
<div class="graph-edge blast-edge" style="--e:2"><span class="rail" aria-hidden="true"></span><span class="rail-live" aria-hidden="true"></span><span class="pulse" aria-hidden="true"></span></div>
<div class="graph-node affected terminal" style="--n:3"><span class="node-dot" aria-hidden="true"></span><strong>publisher</strong><small>terminal · side effect</small></div>
</div>
<div class="scene-witness" data-scene-witness>
<div class="witness-heading">
<span class="witness-tag"><i aria-hidden="true"></i>Trace-backed witness · candidate-003</span>
<strong><code>verified=true</code> arrived without an opened supporting source.</strong>
</div>
<div class="witness-values">
<div><span>Contract expected</span><code class="ok">opened_sources_count > 0</code></div>
<div><span>Trace observed</span><code class="bad">opened_sources_count = 0</code></div>
</div>
<p>Repair before <b>verifier</b> · affected path reaches <b>publisher</b></p>
</div>
<p class="sr-only" aria-live="polite" data-scene-live></p>
</div>
</section>
<section id="playground" class="section" data-rail-node="Playground" aria-labelledby="playground-title">
<div class="shell">
<div class="section-heading bug-heading">
<div><p class="eyebrow"><i aria-hidden="true"></i>Graph playground</p><h2 id="playground-title">Run the edge check.</h2></div>
<p>Choose the recorded producer output, then watch the semantic pulse travel toward the verifier. The candidate keeps its schema and breaks its meaning.</p>
</div>
<div class="playground" data-playground>
<div class="playground-toolbar" role="group" aria-label="Producer output">
<div class="segmented">
<button class="playground-choice is-selected" type="button" data-play-choice="baseline" aria-pressed="true">Baseline</button>
<button class="playground-choice" type="button" data-play-choice="candidate" aria-pressed="false">Candidate regression</button>
<span class="segment-thumb" aria-hidden="true"></span>
</div>
<button class="button secondary playground-run" type="button" data-play-run>Run semantic check</button>
</div>
<div class="playground-graph" role="img" aria-label="A recorded producer output crosses a contract edge to verifier. The baseline passes. The candidate stops at researcher to verifier and marks verifier, decision maker, and publisher as affected.">
<div class="playground-node playground-node-detail" data-play-node="producer">
<span class="node-dot" aria-hidden="true"></span>
<strong>researcher</strong>
<small>recorded producer output</small>
<dl class="node-values">
<div><dt>output.verified</dt><dd data-play-verified>true</dd></div>
<div><dt>metadata.opened_sources_count</dt><dd data-play-sources>1</dd></div>
</dl>
</div>
<div class="playground-edge playground-edge-primary" data-play-edge>
<span class="rail" aria-hidden="true"></span><span class="rail-live" aria-hidden="true"></span>
<span class="playground-pulse" aria-hidden="true"></span>
<span class="playground-break" aria-hidden="true"><i></i><i></i></span>
<small>verified_requires_opened_supporting_source</small>
</div>
<div class="playground-node playground-node-detail" data-play-node="consumer">
<span class="node-dot" aria-hidden="true"></span>
<strong>verifier</strong>
<small>declares the contract</small>
<dl class="node-values">
<div><dt>when</dt><dd>output.verified = true</dd></div>
<div><dt>require</dt><dd>opened_sources_count > 0</dd></div>
</dl>
</div>
<div class="playground-edge playground-edge-impact" aria-hidden="true"><span class="rail"></span></div>
<div class="playground-node playground-node-impact" data-play-node="decision"><span class="node-dot" aria-hidden="true"></span><strong>decision_maker</strong><small>affected downstream</small></div>
<div class="playground-edge playground-edge-impact" aria-hidden="true"><span class="rail"></span></div>
<div class="playground-node playground-node-impact" data-play-node="publisher"><span class="node-dot" aria-hidden="true"></span><strong>publisher</strong><small>terminal side effect</small></div>
</div>
<div class="playground-result" data-play-result aria-live="polite"><strong>Select an output and run the check.</strong><span>The graph will report the observed contract state here.</span></div>
<article class="playground-witness" data-play-witness hidden>
<div><span>Trace-backed witness · candidate-003</span><strong><code>verified=true</code> arrived without an opened supporting source.</strong></div>
<dl>
<div><dt>Expected</dt><dd><code>opened_sources_count > 0</code></dd></div>
<div><dt>Observed</dt><dd><code>opened_sources_count = 0</code></dd></div>
<div><dt>Repair</dt><dd>Before <code>verifier</code></dd></div>
<div><dt>Affected</dt><dd><code>verifier → decision_maker → publisher</code></dd></div>
</dl>
</article>
</div>
</div>
</section>
<section class="section bug-section" data-rail-node="The bug" aria-labelledby="bug-title">
<div class="shell">
<div class="section-heading">
<div><p class="eyebrow"><i aria-hidden="true"></i>The bug normal tests miss</p><h2 id="bug-title">Same shape.<br>Different contract.</h2></div>
<p>Pydantic can validate a boolean. It cannot prove the boolean still means what the next node assumes.</p>
</div>
<div class="meaning-diff">
<div class="payload baseline-payload">
<div class="payload-header"><span>Baseline output</span><span class="badge pass">✓ Valid</span></div>
<pre tabindex="0" role="region" aria-label="Baseline payload JSON"><code>{
<span class="k">"verified"</span>: <span class="b">true</span>,
<span class="k">"confidence"</span>: <span class="n">0.92</span>,
<span class="k">"sources"</span>: [<span class="s">"source-1"</span>]
}</code></pre>
<p><span class="flow-dot" aria-hidden="true"></span> Source opened and shown to support the claim.</p>
</div>
<div class="contract-cut" aria-hidden="true"><span class="cut-rail"></span><i></i><i></i></div>
<div class="payload candidate-payload">
<div class="payload-header"><span>Candidate output</span><span class="badge pass">✓ Valid</span></div>
<pre tabindex="0" role="region" aria-label="Candidate payload JSON"><code>{
<span class="k">"verified"</span>: <span class="b">true</span>,
<span class="k">"confidence"</span>: <span class="n">0.92</span>,
<span class="k">"sources"</span>: [<span class="s">"source-1"</span>]
}</code></pre>
<p><span class="break-dot" aria-hidden="true"></span> Source access failed; the claim merely sounded plausible.</p>
</div>
</div>
<p class="diff-caption"><strong>The JSON is identical.</strong> The meaning at <code>researcher → verifier</code> is not.</p>
</div>
</section>
<section class="section method" data-rail-node="Method" aria-labelledby="method-title">
<div class="shell">
<div class="section-heading"><div><p class="eyebrow"><i aria-hidden="true"></i>How GraphABI works</p><h2 id="method-title">One causal sequence.</h2></div><p>Every interface follows the same reasoning path. Nothing animates without explaining a step.</p></div>
<ol class="method-rail">
<li data-step="1"><span>01</span><strong>Flow</strong><p>Record what crosses each graph edge.</p></li>
<li data-step="2"><span>02</span><strong>Check</strong><p>Evaluate what the consumer relies on.</p></li>
<li data-step="3" class="step-break"><span>03</span><i class="rail-cut" aria-hidden="true"><b></b><b></b></i><strong>Break</strong><p>Stop at the first incompatible meaning.</p></li>
<li data-step="4"><span>04</span><strong>Trace</strong><p>Calculate downstream terminal paths.</p></li>
<li data-step="5"><span>05</span><strong>Explain</strong><p>Show the exact run and conflicting value.</p></li>
<li data-step="6"><span>06</span><strong>Fix</strong><p>Name the nearest repair location.</p></li>
</ol>
</div>
</section>
<section id="contracts" class="section contract-section" data-rail-node="Contracts" aria-labelledby="contract-title">
<div class="shell">
<div class="section-heading"><div><p class="eyebrow"><i aria-hidden="true"></i>Consumer-driven edge contracts</p><h2 id="contract-title">Write the assumption down.</h2></div><p>The verifier defines what it needs from the researcher. Evaluators stay deterministic and independently extensible.</p></div>
<div class="code-layout">
<div class="code-pane">
<div class="pane-bar"><span class="pane-dot" aria-hidden="true"></span><strong>graphabi.contracts.yaml</strong></div>
<pre class="yaml" tabindex="0" role="region" aria-label="Edge contract YAML; scroll if needed"><code><span class="key">version:</span> <span class="string">"0.2"</span>
<span class="key">graph:</span> research_demo
<span class="key">edges:</span>
- <span class="key">id:</span> researcher_to_verifier
<span class="key">producer:</span> researcher
<span class="key">consumer:</span> verifier
<span class="key">invariants:</span>
- <span class="key">id:</span> verified_requires_opened_supporting_source
<span class="key">evaluator:</span> provenance
<span class="key">severity:</span> <span class="sev">breaking</span>
<span class="key">rule:</span> opened_supporting_source</code></pre>
</div>
<div class="evaluator-list contract-anatomy">
<p class="list-label">Contract anatomy</p>
<ul>
<li><span>01</span><div><strong>Producer</strong><small><code>researcher</code></small></div></li>
<li><span>02</span><div><strong>Consumer</strong><small><code>verifier</code></small></div></li>
<li><span>03</span><div><strong>Explicit invariant</strong><small><code>verified</code> requires source access</small></div></li>
<li><span>04</span><div><strong>Severity</strong><small>breaking</small></div></li>
<li><span>05</span><div><strong>Observed witness</strong><small><code>candidate-003</code></small></div></li>
</ul>
<a class="edge-link" href="https://github.com/graphabi/graphabi/blob/main/docs/contract-format.md">Read the contract format <svg viewBox="0 0 12 12" width="11" height="11" aria-hidden="true" focusable="false"><path d="M3 9L9 3M9 3H4M9 3V8"/></svg></a>
</div>
</div>
</div>
</section>
<section class="section terminal-section" data-rail-node="Terminal" aria-labelledby="terminal-title">
<div class="shell">
<div class="section-heading"><div><p class="eyebrow"><i aria-hidden="true"></i>Run the proof locally</p><h2 id="terminal-title">The failure is real output.</h2></div><p>The demo executes baseline and candidate LangGraphs, records both in SQLite, and generates offline JSON and HTML.</p></div>
<div class="terminal">
<div class="terminal-bar"><span class="tl"></span><span class="tl"></span><span class="tl"></span><strong>graphabi demo --allow-breaking</strong></div>
<pre tabindex="0" aria-label="Terminal output; scroll horizontally if needed"><code><span class="muted">GraphABI semantic compatibility report</span>
Structural compatibility: <span class="pass">PASS</span>
Semantic compatibility: <span class="fail">FAIL</span>
First breaking edge: <span class="fail">researcher → verifier</span>
Breaking contract: verified_requires_opened_supporting_source
Witness: run candidate-003
Affected downstream nodes: verifier, decision_maker, publisher
<span class="muted">Reports:</span>
.graphabi/reports/latest/report.json
.graphabi/reports/latest/index.html</code></pre>
</div>
</div>
</section>
<section id="architecture" class="section architecture-section" data-rail-node="Architecture" aria-labelledby="architecture-title">
<div class="shell">
<div class="section-heading"><div><p class="eyebrow"><i aria-hidden="true"></i>Framework-independent core</p><h2 id="architecture-title">Adapters observe.<br>Core decides.</h2></div><p>Framework integrations end at a versioned trace boundary. Contracts, comparison, impact, and reporting do not import framework types.</p></div>
<div class="arch-frame">
<p class="pane-label">Framework-independent semantic compatibility pipeline</p>
<ol class="pipeline">
<li class="stage stage-outside">
<span class="stage-tag">Flow</span>
<strong>Trace inputs</strong>
<small>LangGraph · OpenAI Agents · local OTLP</small>
</li>
<li class="stage-edge" aria-hidden="true"><span class="rail"></span><em>TraceBundle 0.2</em></li>
<li class="stage">
<span class="stage-tag">Record</span>
<strong>Trace model</strong>
<small>SQLite · JSONL</small>
</li>
<li class="stage-edge" aria-hidden="true"><span class="rail"></span></li>
<li class="stage stage-check">
<span class="stage-tag">Check</span>
<strong>Contracts</strong>
<small>Evaluator registry</small>
</li>
<li class="stage-edge" aria-hidden="true"><span class="rail"></span></li>
<li class="stage stage-trace">
<span class="stage-tag">Trace</span>
<strong>Impact</strong>
<small>NetworkX paths</small>
</li>
<li class="stage-edge" aria-hidden="true"><span class="rail"></span><em>CompatibilityReport 0.3</em></li>
<li class="stage stage-explain">
<span class="stage-tag">Explain</span>
<strong>Reports</strong>
<small>JSON · HTML</small>
</li>
<li class="bracket bracket-outside" aria-hidden="true"><span>Framework-facing</span></li>
<li class="bracket bracket-core" aria-hidden="true"><span>Framework-independent core</span></li>
</ol>
<p class="arch-note">Framework types stop at the adapter boundary. Report presentation never decides compatibility.</p>
</div>
</div>
</section>
<section class="section report-section" data-rail-node="Report" aria-labelledby="report-title">
<div class="shell">
<div class="section-heading"><div><p class="eyebrow"><i aria-hidden="true"></i>A report that explains causality</p><h2 id="report-title">Not a score.<br>A repairable witness.</h2></div><p>Machine-readable JSON and a self-contained HTML report come from one redacted report model. Coverage is explicit and never presented as correctness.</p></div>
<div class="report-split">
<div class="report-pane">
<div class="pane-bar"><span class="pane-dot" aria-hidden="true"></span><strong>report.json</strong><span class="pane-note">machine-readable excerpt</span></div>
<pre class="yaml" tabindex="0" role="region" aria-label="Report JSON; scroll if needed"><code>{
<span class="key">"schema_version"</span>: <span class="string">"0.3"</span>,
<span class="key">"structural"</span>: { <span class="key">"status"</span>: <span class="string">"PASS"</span> },
<span class="key">"semantic"</span>: {
<span class="key">"status"</span>: <span class="sev">"FAIL"</span>,
<span class="key">"first_breaking_edge"</span>: <span class="string">"researcher_to_verifier"</span>,
<span class="key">"coverage"</span>: { <span class="key">"summary"</span>: {
<span class="key">"total_graph_edges"</span>: <span class="num">3</span>,
<span class="key">"contracted_and_observed"</span>: <span class="num">3</span>,
<span class="key">"observed_contract_coverage_percent"</span>: <span class="num">100.0</span>,
<span class="key">"coverage_is_correctness"</span>: <span class="string">false</span>
} },
<span class="key">"findings"</span>: [{
<span class="key">"contract_id"</span>: <span class="string">"research_demo:researcher_to_verifier:verified_requires_opened_supporting_source"</span>,
<span class="key">"affected_downstream_nodes"</span>: [<span class="string">"verifier"</span>, <span class="string">"decision_maker"</span>, <span class="string">"publisher"</span>]
}]
}
}</code></pre>
</div>
<div class="report-pane">
<div class="pane-bar"><span class="pane-dot" aria-hidden="true"></span><strong>index.html</strong><span class="pane-note">offline, self-contained</span></div>
<div class="report-mock">
<div class="mock-verdict">
<div><span>Structural</span><strong class="pass">✓ PASS</strong></div>
<div><span>Semantic</span><strong class="fail">× BREAKING</strong></div>
</div>
<div class="mock-row">
<span class="mock-label">First breaking edge</span>
<p class="mock-edge"><b>researcher</b><i aria-hidden="true"></i><b>verifier</b></p>
</div>
<div class="mock-row">
<span class="mock-label">Witness · candidate-003</span>
<p><code class="ok">opened_sources_count > 0</code> expected, <code class="bad">0</code> observed.</p>
</div>
<div class="mock-row">
<span class="mock-label">Downstream</span>
<p class="mock-chips"><em>verifier</em><em>decision_maker</em><em>publisher</em></p>
</div>
<div class="mock-row mock-repair">
<span class="mock-label">Repair location</span>
<p>Before <b>verifier</b></p>
</div>
</div>
</div>
</div>
<p class="diff-caption"><strong>One redacted report model.</strong> Both renderings are generated from it, and neither can disagree with the other.</p>
</div>
</section>
<section class="section proof-section" data-rail-node="Proof" aria-labelledby="proof-title">
<div class="shell">
<div class="proof-intro"><p class="eyebrow"><i aria-hidden="true"></i>Measured technical proof</p><h2 id="proof-title">Small surface.<br>Serious checks.</h2><p>Current branch measurements, linked to the source that enforces them.</p></div>
<dl class="proof-grid">
<div><dt>Tests</dt><dd><strong data-proof="tests">194</strong><small>passing locally</small></dd></div>
<div><dt>Coverage</dt><dd><strong data-proof="coverage">91.37%</strong><small>90% CI floor</small></dd></div>
<div><dt>Python CI</dt><dd><strong data-proof="python">3.12 · 3.13</strong><small>both required</small></dd></div>
<div><dt>Evaluators</dt><dd><strong data-proof="evaluators">7 types</strong><small>deterministic registry</small></dd></div>
<div><dt>Runtime</dt><dd><strong>Local-first</strong><small>no required API key</small></dd></div>
<div><dt>Adapters</dt><dd><strong>2 maintained</strong><small>LangGraph + OpenAI Agents</small></dd></div>
</dl>
<p class="proof-note">Recorded model, prompt, and tool migrations plus a ten-case semantic regression corpus exercise the same comparison engine. The corpus is project test data, not an industry benchmark. <a href="https://github.com/graphabi/graphabi/tree/main/regression_corpus">Inspect every case.</a> <a href="https://github.com/graphabi/graphabi/blob/main/docs/github-action.md">Run the reusable GitHub Action.</a></p>
</div>
</section>
<section class="section limitations-section" data-rail-node="Limits" aria-labelledby="limitations-title">
<div class="shell">
<div class="limitations-lead"><span>Proof boundary</span><h2 id="limitations-title">What GraphABI does not prove.</h2><p>Honest uncertainty is part of the interface.</p></div>
<ul class="limitations-list">
<li><span>01</span><p>GraphABI evaluates explicit contracts. It does not understand arbitrary meaning.</p></li>
<li><span>02</span><p>A passing observed edge does not prove unobserved branches or inputs are compatible.</p></li>
<li><span>03</span><p>Repeated occurrences require explicit causal identities. Ambiguous duplicates remain invalid.</p></li>
<li><span>04</span><p>Telemetry import supports only documented span shapes, and ambiguous mappings remain UNKNOWN.</p></li>
</ul>
<a class="limitations-link" href="https://github.com/graphabi/graphabi/blob/main/docs/limitations.md">Read every current limitation <span aria-hidden="true">↗</span></a>
</div>
</section>
<section class="section contribution-section" data-rail-node="Contribute" aria-labelledby="contribution-title">
<div class="shell">
<div class="contribution-lead"><p class="eyebrow"><i aria-hidden="true"></i>Choose a real edge</p><h2 id="contribution-title">Three useful ways in.</h2><p>Each path has an architecture boundary, acceptance criteria, and a maintainer review point.</p></div>
<div class="contribution-paths">
<a href="https://github.com/graphabi/graphabi/blob/main/docs/extensions.md"><span>Evaluator</span><strong>Add one deterministic contract family.</strong><small>Start with the registry and adversarial tests.</small></a>
<a href="https://github.com/graphabi/graphabi/issues/new?template=adapter_proposal.yml"><span>Adapter</span><strong>Propose another deterministic trace boundary.</strong><small>Document exact mappings, unsupported cases, and version bounds.</small></a>
<a href="https://github.com/graphabi/graphabi/tree/main/regression_corpus"><span>Corpus</span><strong>Add a focused semantic regression case.</strong><small>Keep the baseline, candidate, contract, and expected finding inspectable.</small></a>
</div>
<p class="contribution-footer"><a href="https://github.com/graphabi/graphabi/issues">Browse all issues</a><a href="https://github.com/graphabi/graphabi/blob/main/CONTRIBUTING.md">Read contributing</a><a href="https://github.com/graphabi/graphabi/discussions">Open a design discussion</a></p>
</div>
</section>
<section class="section final-cta-section" data-rail-node="Start" aria-labelledby="cta-title">
<div class="shell">
<div class="final-cta">
<div class="cta-mark" aria-hidden="true"><span class="cta-rail"></span><i></i><i></i></div>
<p class="eyebrow"><i aria-hidden="true"></i>Semantic Compatibility Infrastructure</p>
<h2 id="cta-title">Catch the first broken edge.</h2>
<p class="cta-lede">Run the local demo, read the contract, and inspect the trace-backed witness.</p>
<div class="hero-actions"><button class="button primary" type="button" data-open-setup>Try demo</button><a class="button secondary" href="https://github.com/graphabi/graphabi/blob/main/docs/contract-format.md">Read contracts</a><a class="button secondary" href="https://github.com/graphabi/graphabi">Star on GitHub</a></div>
</div>
</div>
</section>
</main>
<div class="setup-modal" data-setup-modal hidden>
<div class="modal-backdrop" data-close-setup></div>
<section class="setup-dialog" role="dialog" aria-modal="true" aria-labelledby="setup-title" aria-describedby="setup-description" tabindex="-1">
<div class="setup-dialog-header">
<div><p class="eyebrow"><i aria-hidden="true"></i>Local setup</p><h2 id="setup-title">Put a semantic check in motion.</h2><p id="setup-description">Choose a setup path that works today. GraphABI is installed from Git until package publication is approved.</p></div>
<button class="modal-close" type="button" data-close-setup aria-label="Close setup"><svg viewBox="0 0 16 16" width="15" height="15" aria-hidden="true" focusable="false"><path d="M4 4L12 12M12 4L4 12"/></svg></button>
</div>
<div class="setup-tabs" role="tablist" aria-label="Setup options">
<button class="setup-tab is-active" type="button" role="tab" aria-selected="true" aria-controls="setup-panel-uv" id="setup-tab-uv" data-setup-option="uv">uv</button>
<button class="setup-tab" type="button" role="tab" tabindex="-1" aria-selected="false" aria-controls="setup-panel-pipx" id="setup-tab-pipx" data-setup-option="pipx">pipx</button>
<button class="setup-tab" type="button" role="tab" tabindex="-1" aria-selected="false" aria-controls="setup-panel-source" id="setup-tab-source" data-setup-option="source">Source</button>
<button class="setup-tab" type="button" role="tab" tabindex="-1" aria-selected="false" aria-controls="setup-panel-langgraph" id="setup-tab-langgraph" data-setup-option="langgraph">LangGraph</button>
<span class="tab-rail" aria-hidden="true"></span>
</div>
<div class="setup-panels">
<div class="setup-panel is-active" role="tabpanel" tabindex="0" id="setup-panel-uv" aria-labelledby="setup-tab-uv" data-setup-panel="uv"><div class="setup-panel-meta"><strong>Run from Git with uv</strong><span class="support-badge available">Available now</span></div><p>Run the deterministic demo without a local install or API key.</p><div class="command-line"><span class="install-prompt" aria-hidden="true">$</span><code data-setup-command>uvx --from git+https://github.com/graphabi/graphabi graphabi demo --allow-breaking</code><button class="copy-button" type="button" data-copy-command aria-label="Copy uv command">Copy</button></div><span class="copy-feedback" data-copy-feedback aria-live="polite"></span></div>
<div class="setup-panel" role="tabpanel" tabindex="0" id="setup-panel-pipx" aria-labelledby="setup-tab-pipx" data-setup-panel="pipx" hidden><div class="setup-panel-meta"><strong>Run from Git with pipx</strong><span class="support-badge available">Available now</span></div><p>Use pipx to run the CLI directly from the public repository. GraphABI is not published to PyPI.</p><div class="command-line"><span class="install-prompt" aria-hidden="true">$</span><code data-setup-command>pipx run --spec git+https://github.com/graphabi/graphabi graphabi demo --allow-breaking</code><button class="copy-button" type="button" data-copy-command aria-label="Copy pipx command">Copy</button></div><span class="copy-feedback" data-copy-feedback aria-live="polite"></span></div>
<div class="setup-panel" role="tabpanel" tabindex="0" id="setup-panel-source" aria-labelledby="setup-tab-source" data-setup-panel="source" hidden><div class="setup-panel-meta"><strong>Clone and sync the repository</strong><span class="support-badge available">Available now</span></div><p>Use the locked development environment for examples, tests, and contribution work.</p><div class="command-line"><span class="install-prompt" aria-hidden="true">$</span><code data-setup-command>git clone https://github.com/graphabi/graphabi.git && cd graphabi && make bootstrap</code><button class="copy-button" type="button" data-copy-command aria-label="Copy source setup command">Copy</button></div><span class="copy-feedback" data-copy-feedback aria-live="polite"></span></div>
<div class="setup-panel" role="tabpanel" tabindex="0" id="setup-panel-langgraph" aria-labelledby="setup-tab-langgraph" data-setup-panel="langgraph" hidden><div class="setup-panel-meta"><strong>Instrument LangGraph</strong><span class="support-badge available">Adapter available</span></div><p>Install GraphABI from Git, then run the included LangGraph research graph or add the adapter to your trace boundary.</p><div class="command-line"><span class="install-prompt" aria-hidden="true">$</span><code data-setup-command>uv add "graphabi @ git+https://github.com/graphabi/graphabi"</code><button class="copy-button" type="button" data-copy-command aria-label="Copy LangGraph command">Copy</button></div><span class="copy-feedback" data-copy-feedback aria-live="polite"></span></div>
</div>
</section>
</div>
<footer class="site-footer">
<div class="shell footer-inner">
<div class="footer-brand">
<span class="brand-mark" aria-hidden="true">
<svg viewBox="0 0 64 64" width="26" height="26" focusable="false">
<circle cx="9" cy="32" r="5" class="m-live"/>
<path d="M14 32H28" class="m-live-stroke"/>
<path d="M36 32H50" class="m-dead-stroke"/>
<circle cx="55" cy="32" r="5" class="m-dead"/>
<path d="M29 26L35 31M29 33L35 38" class="m-cut"/>
</svg>
</span>
<span>GraphABI · Apache-2.0 · Public alpha</span>
</div>
<nav aria-label="Footer navigation">
<a href="https://github.com/graphabi/graphabi/tree/main/docs">Documentation</a>
<a href="https://github.com/graphabi/graphabi/blob/main/SECURITY.md">Security</a>
<a href="https://github.com/graphabi/graphabi/discussions">Discussions</a>
</nav>
</div>
</footer>
</body>
</html>