eyeling 1.16.3 → 1.16.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/README.md +0 -1
  2. package/package.json +2 -3
  3. package/arctifacts/README.md +0 -59
  4. package/arctifacts/ackermann.html +0 -678
  5. package/arctifacts/auroracare.html +0 -1297
  6. package/arctifacts/bike-trip.html +0 -752
  7. package/arctifacts/binomial-theorem.html +0 -631
  8. package/arctifacts/bmi.html +0 -511
  9. package/arctifacts/building-performance.html +0 -750
  10. package/arctifacts/clinical-care.html +0 -726
  11. package/arctifacts/collatz.html +0 -403
  12. package/arctifacts/complex.html +0 -321
  13. package/arctifacts/control-system.html +0 -482
  14. package/arctifacts/delfour.html +0 -849
  15. package/arctifacts/earthquake-epicenter.html +0 -982
  16. package/arctifacts/eco-route.html +0 -662
  17. package/arctifacts/euclid-infinitude.html +0 -564
  18. package/arctifacts/euler-identity.html +0 -667
  19. package/arctifacts/exoplanet-transit.html +0 -1000
  20. package/arctifacts/faltings-theorem.html +0 -1046
  21. package/arctifacts/fibonacci.html +0 -299
  22. package/arctifacts/fundamental-theorem-arithmetic.html +0 -398
  23. package/arctifacts/godel-numbering.html +0 -743
  24. package/arctifacts/gps-bike.html +0 -759
  25. package/arctifacts/gps-clinical-bench.html +0 -792
  26. package/arctifacts/graph-french.html +0 -449
  27. package/arctifacts/grass-molecular.html +0 -592
  28. package/arctifacts/group-theory.html +0 -740
  29. package/arctifacts/health-info.html +0 -833
  30. package/arctifacts/kaprekar-constant.html +0 -576
  31. package/arctifacts/lee.html +0 -805
  32. package/arctifacts/linked-lists.html +0 -502
  33. package/arctifacts/lldm.html +0 -612
  34. package/arctifacts/matrix-multiplication.html +0 -502
  35. package/arctifacts/matrix.html +0 -651
  36. package/arctifacts/newton-raphson.html +0 -944
  37. package/arctifacts/peano-factorial.html +0 -456
  38. package/arctifacts/pi.html +0 -363
  39. package/arctifacts/polynomial.html +0 -646
  40. package/arctifacts/prime.html +0 -366
  41. package/arctifacts/pythagorean-theorem.html +0 -468
  42. package/arctifacts/rest-path.html +0 -469
  43. package/arctifacts/roots-of-unity.html +0 -363
  44. package/arctifacts/turing.html +0 -409
  45. package/arctifacts/wind-turbines.html +0 -726
@@ -1,792 +0,0 @@
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>GPS Clinical Bench</title>
7
- <style>
8
- :root {
9
- --bg: #f7fafc;
10
- --panel: #ffffff;
11
- --muted: #475569;
12
- --text: #0b1220;
13
- --accent: #2563eb;
14
- --good: #16a34a;
15
- --bad: #dc2626;
16
- --warn: #d97706;
17
- --chip: #eef2f7;
18
- }
19
- * {
20
- box-sizing: border-box;
21
- }
22
- body {
23
- margin: 0;
24
- font:
25
- 16px/1.5 system-ui,
26
- Segoe UI,
27
- Roboto,
28
- Inter,
29
- Helvetica,
30
- Arial,
31
- sans-serif;
32
- background: var(--bg);
33
- color: var(--text);
34
- }
35
- header {
36
- padding: 24px 20px;
37
- border-bottom: 1px solid #e5e7eb;
38
- background: linear-gradient(180deg, rgba(37, 99, 235, 0.08), transparent);
39
- }
40
- h1 {
41
- margin: 0;
42
- font-size: 24px;
43
- letter-spacing: 0.2px;
44
- }
45
- main {
46
- display: grid;
47
- grid-template-columns: 1fr;
48
- gap: 22px;
49
- padding: 20px;
50
- align-items: start;
51
- }
52
- section {
53
- background: var(--panel);
54
- border: 1px solid #e5e7eb;
55
- border-radius: 16px;
56
- padding: 16px;
57
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.06);
58
- }
59
- h2 {
60
- margin: 0 0 10px 0;
61
- font-size: 18px;
62
- }
63
- .row {
64
- display: flex;
65
- gap: 10px;
66
- flex-wrap: wrap;
67
- }
68
- .grid {
69
- display: grid;
70
- gap: 10px;
71
- }
72
- .pill {
73
- display: inline-flex;
74
- align-items: center;
75
- gap: 8px;
76
- padding: 8px 10px;
77
- border-radius: 999px;
78
- background: #ffffff;
79
- border: 1px solid #e5e7eb;
80
- }
81
- .small {
82
- font-size: 13px;
83
- color: var(--muted);
84
- }
85
- .mono {
86
- font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
87
- }
88
- .ok {
89
- color: var(--good);
90
- }
91
- .no {
92
- color: var(--bad);
93
- }
94
- .warn {
95
- color: var(--warn);
96
- }
97
- .kvs {
98
- display: grid;
99
- grid-template-columns: 160px 1fr;
100
- gap: 6px 10px;
101
- }
102
- .log {
103
- max-height: 260px;
104
- overflow: auto;
105
- background: #ffffff;
106
- border: 1px solid #e5e7eb;
107
- border-radius: 12px;
108
- padding: 10px;
109
- }
110
- .timeline {
111
- display: flex;
112
- flex-direction: column;
113
- gap: 10px;
114
- }
115
- .card {
116
- background: #ffffff;
117
- border: 1px solid #e5e7eb;
118
- border-radius: 12px;
119
- padding: 12px;
120
- }
121
- .muted {
122
- color: var(--muted);
123
- }
124
- .split {
125
- display: grid;
126
- grid-template-columns: 1fr auto;
127
- gap: 10px;
128
- align-items: center;
129
- }
130
- .btnrow {
131
- display: flex;
132
- gap: 10px;
133
- flex-wrap: wrap;
134
- }
135
- button {
136
- cursor: pointer;
137
- background: var(--accent);
138
- color: #fff;
139
- border: none;
140
- padding: 10px 14px;
141
- border-radius: 12px;
142
- font-weight: 600;
143
- }
144
- button.ghost {
145
- background: #f8fafc;
146
- color: var(--text);
147
- border: 1px solid #dbe2ea;
148
- }
149
- pre.wrap {
150
- white-space: pre-wrap;
151
- overflow-wrap: anywhere;
152
- word-break: break-word;
153
- overflow-x: hidden;
154
- overflow-y: auto;
155
- }
156
- /* New: nicer lists for Reason/Checks */
157
- .list {
158
- margin: 0.25rem 0 0.75rem 1.1rem;
159
- padding: 0;
160
- }
161
- .list li {
162
- margin: 0.1rem 0;
163
- }
164
- .list.compact li {
165
- margin: 0;
166
- }
167
- </style>
168
- </head>
169
- <body>
170
- <header>
171
- <h1>GPS Clinical Bench</h1>
172
- </header>
173
-
174
- <main>
175
- <section id="controls">
176
- <div class="split">
177
- <h2>Run Demo</h2>
178
- <div class="btnrow">
179
- <button id="btn-run">Evaluate</button>
180
- <button class="ghost" id="btn-copy">Copy result JSON</button>
181
- </div>
182
- </div>
183
- </section>
184
-
185
- <section id="decision">
186
- <h2>Decision</h2>
187
- <div class="kvs">
188
- <div class="muted">Answer</div>
189
- <div id="ans">—</div>
190
- <div class="muted">Reason why</div>
191
- <div id="why" class="wrap">Data & policies loaded. Click <em>Evaluate</em>.</div>
192
- <div class="muted">Check (harness)</div>
193
- <div id="check" class="wrap">—</div>
194
- </div>
195
- </section>
196
-
197
- <section id="data">
198
- <h2>Data (JSON)</h2>
199
- <pre class="mono wrap" id="data-json"></pre>
200
- </section>
201
-
202
- <section id="policies">
203
- <h2>Policies (declarative JSON rules)</h2>
204
- <pre class="mono wrap" id="policies-json"></pre>
205
- <h3>Machine Trace (debug)</h3>
206
- <!-- switched to <pre> to ensure one-per-line display -->
207
- <pre class="log mono" id="trace"></pre>
208
- </section>
209
-
210
- <section id="timeline">
211
- <h2>Timeline</h2>
212
- <div class="timeline" id="timeline-items">
213
- <div class="card muted">Run the demo to populate results.</div>
214
- </div>
215
- </section>
216
- </main>
217
-
218
- <script>
219
- /* Surface any runtime errors */
220
- window.onerror = function (msg, src, line, col, err) {
221
- var t = document.getElementById('trace');
222
- if (t) {
223
- t.textContent = 'JS error: ' + msg + ' @ ' + line + ':' + col + (err && err.stack ? '\n' + err.stack : '');
224
- }
225
- };
226
-
227
- /*** DATA (pure JSON) — patient, limits, start/goal, and domain transitions ***/
228
- var Data = {
229
- patient: { id: 'patient_001', gender: 'female', age: 45 },
230
- limits: { maxDays: 180, maxCost: 500, minSuccess: 0.35, minComfort: 0.35, maxStages: 10 },
231
- start: 'state_2',
232
- goal: 'state_6',
233
- actions: [
234
- {
235
- id: 'action:take_pill_Medication_16.',
236
- from: 'state_2',
237
- to: 'state_3',
238
- days: 1,
239
- cost: 69.0,
240
- succ: 0.489,
241
- comf: 0.632,
242
- gender: 'ANY',
243
- ageMin: 18,
244
- ageMax: 99,
245
- },
246
- {
247
- id: 'action:take_pill_Medication_33.',
248
- from: 'state_2',
249
- to: 'state_3',
250
- days: 1,
251
- cost: 57.0,
252
- succ: 0.387,
253
- comf: 0.422,
254
- gender: 'ANY',
255
- ageMin: 18,
256
- ageMax: 99,
257
- },
258
- {
259
- id: 'action:take_pill_Medication_35.',
260
- from: 'state_2',
261
- to: 'state_3',
262
- days: 1,
263
- cost: 81.0,
264
- succ: 0.381,
265
- comf: 0.796,
266
- gender: 'ANY',
267
- ageMin: 18,
268
- ageMax: 99,
269
- },
270
- {
271
- id: 'action:take_pill_Medication_37.',
272
- from: 'state_2',
273
- to: 'state_9',
274
- days: 1,
275
- cost: 53.0,
276
- succ: 0.934,
277
- comf: 0.466,
278
- gender: 'ANY',
279
- ageMin: 18,
280
- ageMax: 99,
281
- },
282
- {
283
- id: 'action:take_pill_Medication_39.',
284
- from: 'state_2',
285
- to: 'state_5',
286
- days: 1,
287
- cost: 2.0,
288
- succ: 0.771,
289
- comf: 0.815,
290
- gender: 'ANY',
291
- ageMin: 18,
292
- ageMax: 99,
293
- },
294
- {
295
- id: 'action:take_pill_Medication_49.',
296
- from: 'state_2',
297
- to: 'state_6',
298
- days: 1,
299
- cost: 44.0,
300
- succ: 0.374,
301
- comf: 0.45,
302
- gender: 'ANY',
303
- ageMin: 18,
304
- ageMax: 99,
305
- },
306
- {
307
- id: 'action:take_pill_Medication_58.',
308
- from: 'state_2',
309
- to: 'state_10',
310
- days: 1,
311
- cost: 87.0,
312
- succ: 0.69,
313
- comf: 0.55,
314
- gender: 'ANY',
315
- ageMin: 18,
316
- ageMax: 99,
317
- },
318
- {
319
- id: 'action:take_pill_Medication_60.',
320
- from: 'state_2',
321
- to: 'state_5',
322
- days: 1,
323
- cost: 12.0,
324
- succ: 0.723,
325
- comf: 0.85,
326
- gender: 'ANY',
327
- ageMin: 18,
328
- ageMax: 99,
329
- },
330
- ],
331
- };
332
-
333
- /*** ARC-style declarative rules (pure JSON) ***/
334
- var ARC_RULES = [
335
- {
336
- id: 'R1-ApplicableFromStart',
337
- if: [
338
- { pred: 'start', s: 'Req', o: '?S' },
339
- { pred: 'edge', s: '?S', o: '?A' },
340
- ],
341
- then: [{ pred: 'applicable', s: 'Req', o: '?A' }],
342
- explain:
343
- 'Any transition whose source equals the start state is applicable (patient filters are checked in JS).',
344
- },
345
- {
346
- id: 'R2-ReachesGoalInOneStep',
347
- if: [
348
- { pred: 'start', s: 'Req', o: '?S' },
349
- { pred: 'goal', s: 'Req', o: '?G' },
350
- { pred: 'edgeTo', s: '?A', o: '?T' },
351
- { pred: 'equals', s: '?T', o: '?G' },
352
- ],
353
- then: [{ pred: 'reachesGoalOne', s: 'Req', o: '?A' }],
354
- explain: 'An applicable transition reaches the goal in one step if its target equals the goal state.',
355
- },
356
- ];
357
-
358
- /*** Pretty printer for rules (inline IF/THEN atoms; per-line; wrapped) ***/
359
- function formatInlineObject(o) {
360
- var order = ['pred', 's', 'o', 'not'];
361
- var keys = Object.keys(o).sort(function (a, b) {
362
- var ai = order.indexOf(a),
363
- bi = order.indexOf(b);
364
- if (ai === -1 && bi === -1) return a < b ? -1 : a > b ? 1 : 0;
365
- if (ai === -1) return 1;
366
- if (bi === -1) return -1;
367
- return ai - bi;
368
- });
369
- var parts = keys.map(function (k) {
370
- var v = o[k],
371
- vs = typeof v === 'string' ? JSON.stringify(v) : typeof v === 'boolean' ? String(v) : JSON.stringify(v);
372
- return JSON.stringify(k) + ':' + vs;
373
- });
374
- return '{' + parts.join(',') + '}';
375
- }
376
- function formatRules(rules) {
377
- var out = ['['];
378
- for (var i = 0; i < rules.length; i++) {
379
- var r = rules[i];
380
- out.push(' {');
381
- out.push(' "id": ' + JSON.stringify(r.id) + ',');
382
- out.push(' "if": [ ' + (r.if || []).map(formatInlineObject).join(', ') + ' ],');
383
- var thenLine = ' "then": [ ' + (r.then || []).map(formatInlineObject).join(', ') + ' ]';
384
- if (r.explain !== undefined) thenLine += ',';
385
- out.push(thenLine);
386
- if (r.explain !== undefined) out.push(' "explain": ' + JSON.stringify(r.explain));
387
- out.push(' }' + (i < rules.length - 1 ? ',' : ''));
388
- }
389
- out.push(']');
390
- return out.join('\n');
391
- }
392
-
393
- /*** Minimal ARC forward-chainer (facts are {pred,s,o}) ***/
394
- function isVar(x) {
395
- return typeof x === 'string' && x[0] === '?';
396
- }
397
- function subst(term, theta) {
398
- var t = { pred: term.pred, s: term.s, o: term.o };
399
- if (isVar(t.s) && theta[t.s] !== undefined) t.s = theta[t.s];
400
- if (isVar(t.o) && theta[t.o] !== undefined) t.o = theta[t.o];
401
- return t;
402
- }
403
- function unifyAtom(pattern, fact, theta) {
404
- if (pattern.pred !== fact.pred) return null;
405
- var s = Object.assign({}, theta || {});
406
- function bind(pv, fv) {
407
- if (isVar(pv)) {
408
- if (s[pv] === undefined) {
409
- s[pv] = fv;
410
- return true;
411
- }
412
- return s[pv] === fv;
413
- }
414
- return pv === fv;
415
- }
416
- if (!bind(pattern.s, fact.s)) return null;
417
- if (!bind(pattern.o, fact.o)) return null;
418
- return s;
419
- }
420
- function matchBody(body, facts) {
421
- function extend(i, theta, acc) {
422
- if (i === body.length) {
423
- acc.push(theta);
424
- return;
425
- }
426
- var atom = body[i];
427
- if (atom.not) {
428
- var any = false;
429
- for (var k = 0; k < facts.length; k++) {
430
- if (unifyAtom(atom, facts[k], theta)) {
431
- any = true;
432
- break;
433
- }
434
- }
435
- if (!any) extend(i + 1, theta, acc);
436
- return;
437
- }
438
- for (var k = 0; k < facts.length; k++) {
439
- var t2 = unifyAtom(atom, facts[k], theta);
440
- if (t2) extend(i + 1, t2, acc);
441
- }
442
- }
443
- var out = [];
444
- extend(0, {}, out);
445
- return out;
446
- }
447
- function factKey(f) {
448
- return f.pred + '|' + JSON.stringify(f.s) + '|' + JSON.stringify(f.o);
449
- }
450
- function containsFact(facts, f) {
451
- var key = factKey(f);
452
- for (var i = 0; i < facts.length; i++) {
453
- if (factKey(facts[i]) === key) return true;
454
- }
455
- return false;
456
- }
457
- function derive(facts, rules) {
458
- var added = true,
459
- trace = [];
460
- while (added) {
461
- added = false;
462
- for (var r = 0; r < rules.length; r++) {
463
- var rule = rules[r];
464
- var thetas = matchBody(rule.if, facts);
465
- for (var t = 0; t < thetas.length; t++) {
466
- for (var j = 0; j < rule.then.length; j++) {
467
- var f = subst(rule.then[j], thetas[t]);
468
- if (!containsFact(facts, f)) {
469
- facts.push(f);
470
- trace.push('[' + rule.id + '] ' + JSON.stringify(f));
471
- added = true;
472
- }
473
- }
474
- }
475
- }
476
- }
477
- return { facts: facts, trace: trace };
478
- }
479
-
480
- /*** Build base facts from Data (edges and labels) ***/
481
- function factsFromData(d) {
482
- var F = [];
483
- function add(pred, s, o) {
484
- F.push({ pred: pred, s: s, o: o });
485
- }
486
- add('start', 'Req', d.start);
487
- add('goal', 'Req', d.goal);
488
- // Encode edges as facts the rules can see (source->action & action->target)
489
- d.actions.forEach(function (a) {
490
- add('edge', '' + a.from, a.id); // edge(from, actionId)
491
- add('edgeTo', a.id, '' + a.to); // edgeTo(actionId, to)
492
- });
493
- // Provide equality helper so R2 can check target==goal
494
- var states = new Set();
495
- states.add(d.start);
496
- states.add(d.goal);
497
- d.actions.forEach(function (a) {
498
- states.add(a.from);
499
- states.add(a.to);
500
- });
501
- states.forEach(function (s) {
502
- add('equals', s, s);
503
- });
504
- return F;
505
- }
506
-
507
- /*** Domain helpers ***/
508
- function fmtEuro(x) {
509
- return '€' + x.toFixed(2);
510
- }
511
- function applicableForPatient(a, patient) {
512
- var genderOk =
513
- a.gender === 'ANY' || a.gender === patient.gender.toUpperCase() || a.gender.toLowerCase() === patient.gender;
514
- var ageOk = patient.age >= a.ageMin && patient.age <= a.ageMax;
515
- return genderOk && ageOk;
516
- }
517
- function withinGlobalLimits(a, limits) {
518
- return (
519
- a.days <= limits.maxDays &&
520
- a.cost <= limits.maxCost &&
521
- a.succ >= limits.minSuccess &&
522
- a.comf >= limits.minComfort
523
- );
524
- }
525
- function escapeHTML(s) {
526
- return String(s).replace(/[&<>"']/g, function (c) {
527
- return { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c];
528
- });
529
- }
530
-
531
- /*** Main reasoning: list applicable, find one-step goal transitions, build messages ***/
532
- function runOnce() {
533
- try {
534
- // 1) Show Data & Policies
535
- document.getElementById('data-json').textContent = JSON.stringify(Data, null, 2);
536
- document.getElementById('policies-json').textContent = formatRules(ARC_RULES);
537
-
538
- // 2) Build facts & run ARC rules (for machine trace)
539
- var baseFacts = factsFromData(Data);
540
- var closure = derive(baseFacts.slice(), ARC_RULES);
541
-
542
- // 3) JS specialized reasoning
543
- var start = Data.start,
544
- goal = Data.goal,
545
- lim = Data.limits,
546
- pat = Data.patient;
547
-
548
- var applicable = Data.actions.filter(function (a) {
549
- return a.from === start && applicableForPatient(a, pat);
550
- });
551
- function bullet(a) {
552
- return (
553
- a.id +
554
- ' : ' +
555
- start +
556
- ' \u2192 care:' +
557
- a.to +
558
- '. (+1d, +' +
559
- fmtEuro(a.cost) +
560
- ', ×succ ' +
561
- a.succ.toFixed(3) +
562
- ', ×comf ' +
563
- a.comf.toFixed(3) +
564
- ')'
565
- );
566
- }
567
- var bullets = applicable.map(bullet);
568
-
569
- var oneStepGoals = applicable.filter(function (a) {
570
- return a.to === goal && withinGlobalLimits(a, lim);
571
- });
572
-
573
- // Reason: global limits + applicable list (pretty multi-line)
574
- var whyBox = document.getElementById('why');
575
- var limitsHTML =
576
- '<div><strong>Global limits:</strong></div>' +
577
- '<ul class="list compact mono small">' +
578
- '<li>duration ≤ ' +
579
- lim.maxDays +
580
- ' days</li>' +
581
- '<li>cost ≤ ' +
582
- fmtEuro(lim.maxCost) +
583
- '</li>' +
584
- '<li>success ≥ ' +
585
- lim.minSuccess.toFixed(2) +
586
- '</li>' +
587
- '<li>comfort ≥ ' +
588
- lim.minComfort.toFixed(2) +
589
- '</li>' +
590
- '<li>stagecount ≤ ' +
591
- lim.maxStages +
592
- '</li>' +
593
- '</ul>';
594
-
595
- var applicableHTML =
596
- '<div><strong>From the start state ' +
597
- escapeHTML(start) +
598
- ', applicable rules for this patient: ' +
599
- applicable.length +
600
- '</strong></div>' +
601
- '<ul class="list mono">' +
602
- bullets
603
- .map(function (t) {
604
- return '<li>' + escapeHTML(t) + '</li>';
605
- })
606
- .join('') +
607
- '</ul>';
608
-
609
- // Explanation lines
610
- var otherStates = Array.from(
611
- new Set(
612
- applicable
613
- .map(function (a) {
614
- return a.to;
615
- })
616
- .filter(function (s) {
617
- return s !== goal;
618
- }),
619
- ),
620
- ).slice(0, 3);
621
- var explHTML;
622
- if (oneStepGoals.length === 1) {
623
- var a = oneStepGoals[0];
624
- explHTML =
625
- '<div><strong>Explanation:</strong></div>' +
626
- '<ul class="list">' +
627
- '<li>The only applicable transition that reaches the goal in one step is<br>' +
628
- 'action ‘' +
629
- escapeHTML(a.id.replace(/\.$/, '')) +
630
- '’: ' +
631
- escapeHTML(start) +
632
- ' → ' +
633
- escapeHTML(goal) +
634
- '.</li>' +
635
- '<li>Other applicable first steps (e.g. to ' +
636
- escapeHTML(otherStates.join(', ')) +
637
- ') do not lead to ' +
638
- escapeHTML(goal) +
639
- ' under the gender/age filters and global limits in subsequent steps.</li>' +
640
- '</ul>';
641
- } else if (oneStepGoals.length > 1) {
642
- explHTML =
643
- '<div><strong>Explanation:</strong></div>' +
644
- '<ul class="list"><li>Multiple one-step transitions reach the goal. Choose by cost/success/comfort trade-off.</li></ul>';
645
- } else {
646
- explHTML =
647
- '<div><strong>Explanation:</strong></div>' +
648
- '<ul class="list"><li>No one-step transition reaches the goal under the global limits.</li></ul>';
649
- }
650
- whyBox.innerHTML = limitsHTML + applicableHTML + explHTML;
651
-
652
- // Checks (harness) — pretty bullet list
653
- var checksBox = document.getElementById('check');
654
- var checksItems = [];
655
- if (oneStepGoals.length === 1) {
656
- var g = oneStepGoals[0];
657
- checksItems.push(
658
- "Unique solution confirmed: ['" +
659
- g.id +
660
- "'] (succ=" +
661
- g.succ.toFixed(3) +
662
- ', cost=' +
663
- fmtEuro(g.cost) +
664
- ', dur=' +
665
- g.days +
666
- 'd, comf=' +
667
- g.comf.toFixed(3) +
668
- '). ✓',
669
- );
670
- checksItems.push('Harness complete: reasoning, applicability, limits, and optimality verified. ✓');
671
- } else if (oneStepGoals.length > 1) {
672
- checksItems.push('Multiple valid solutions found; harness notes non-uniqueness. ✓');
673
- } else {
674
- checksItems.push('No valid one-step solution within limits; harness notes infeasibility. ✓');
675
- }
676
- checksBox.innerHTML =
677
- '<ul class="list mono">' +
678
- checksItems
679
- .map(function (c) {
680
- return '<li>' + escapeHTML(c) + '</li>';
681
- })
682
- .join('') +
683
- '</ul>';
684
-
685
- // Decision
686
- var decision = oneStepGoals.length > 0 ? 'Allowed' : 'Denied';
687
- document.getElementById('ans').innerHTML =
688
- decision === 'Allowed' ? '<strong class="ok">✅ Allowed</strong>' : '<strong class="no">⛔ Denied</strong>';
689
-
690
- // Trace + Timeline + Stash
691
- document.getElementById('trace').textContent = closure.trace.join('\n');
692
- pushTimeline(
693
- { start: start, goal: goal },
694
- {
695
- answer: decision,
696
- reason: oneStepGoals.length ? 'Chosen: ' + oneStepGoals[0].id : 'No one-step solution',
697
- },
698
- );
699
- window.__lastResult = {
700
- data: Data,
701
- facts: baseFacts,
702
- derived: closure.facts,
703
- trace: closure.trace,
704
- start: start,
705
- goal: goal,
706
- applicable: applicable,
707
- oneStepGoals: oneStepGoals,
708
- decision: decision,
709
- ts: new Date().toISOString(),
710
- };
711
- } catch (e) {
712
- var t = document.getElementById('trace');
713
- if (t) t.textContent = 'Evaluate error: ' + ((e && e.stack) || e);
714
- }
715
- }
716
-
717
- /*** Timeline helper ***/
718
- function el(tag, attrs, children) {
719
- attrs = attrs || {};
720
- children = children || [];
721
- var n = document.createElement(tag);
722
- for (var k in attrs) {
723
- if (!attrs.hasOwnProperty(k)) continue;
724
- var v = attrs[k];
725
- if (k === 'class') n.className = v;
726
- else if (k === 'html') n.innerHTML = v;
727
- else if (k.indexOf('on') === 0) n.addEventListener(k.slice(2), v);
728
- else n.setAttribute(k, v);
729
- }
730
- for (var i = 0; i < children.length; i++) n.append(children[i]);
731
- return n;
732
- }
733
- function pushTimeline(meta, res) {
734
- var box = document.getElementById('timeline-items');
735
- var card = el('div', { class: 'card' });
736
- var when = new Date().toLocaleString();
737
- card.innerHTML =
738
- '<div class="row" style="justify-content:space-between"><strong>' +
739
- (res.answer === 'Allowed' ? '✅ Allowed' : '⛔ Denied') +
740
- '</strong><span class="muted small">' +
741
- when +
742
- '</span></div>' +
743
- '<div class="small muted">start=<span class="mono">' +
744
- meta.start +
745
- '</span> • goal=<span class="mono">' +
746
- meta.goal +
747
- '</span></div>' +
748
- '<div class="small">' +
749
- (res.reason || '') +
750
- '</div>';
751
- box.prepend(card);
752
- }
753
-
754
- /*** Boot ***/
755
- function boot() {
756
- document.getElementById('data-json').textContent = JSON.stringify(Data, null, 2);
757
- document.getElementById('policies-json').textContent = formatRules(ARC_RULES);
758
- document.getElementById('btn-run').addEventListener('click', runOnce);
759
- document.getElementById('btn-copy').addEventListener('click', function () {
760
- try {
761
- var payload = JSON.stringify(window.__lastResult || { error: 'no-result' }, null, 2);
762
- navigator.clipboard.writeText(payload);
763
- var b = document.getElementById('btn-copy');
764
- var old = b.textContent;
765
- b.textContent = 'Copied!';
766
- setTimeout(function () {
767
- b.textContent = old;
768
- }, 1000);
769
- } catch (e) {
770
- alert('Copy failed: ' + e.message);
771
- }
772
- });
773
- }
774
- window.addEventListener('DOMContentLoaded', function () {
775
- try {
776
- boot();
777
- } catch (e) {
778
- var t = document.getElementById('trace');
779
- if (t) t.textContent = 'Boot error: ' + ((e && e.stack) || e);
780
- }
781
- });
782
- if (document.readyState !== 'loading') {
783
- try {
784
- boot();
785
- } catch (e) {
786
- var t = document.getElementById('trace');
787
- if (t) t.textContent = 'Boot error: ' + ((e && e.stack) || e);
788
- }
789
- }
790
- </script>
791
- </body>
792
- </html>