Mayug Maniparambil Claude Opus 4.8 (1M context) commited on
Commit
1ecac33
·
1 Parent(s): 30865cf

Fix bridges crossing-cell bridge gap; add puzzle pipeline + e2e tests

Browse files

The bridges editor's bridgesBoardFromStates wrote "." for every empty
opportunity. When a vertical bridge passed through a cell also owned by an
unused horizontal opportunity (a crossing point), the later-processed empty
opportunity overwrote the shared cell back to ".", leaving a gap in the drawn
bridge. The board looked connected but failed verification ("not solved").
Fix: skip level-0 opportunities so they cannot clobber an active perpendicular
bridge's crossing cell.

Add a full-pipeline test harness to catch this class of editor encode/decode
bug across all six families:
- vitest round-trip: editor decode->encode of each dataset reference solution
(npm test). Fails on 7/15 bridges fixtures without the fix.
- verifier oracle: runs the real production verifier on every round-tripped
board (npm run test:pipeline) - 90 solutions + 90 round-trips verify SOLVED.
- Playwright smoke: draws the solution in the real UI and submits
(npm run test:e2e).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

.gitignore CHANGED
@@ -13,6 +13,7 @@ frontend/.npm-cache/
13
  dist/
14
  data/
15
  results/
 
16
  submodules/rlp/build/
17
  submodules/rlp/rlp.egg-info/
18
  submodules/rlp/rlp/constants*.so
 
13
  dist/
14
  data/
15
  results/
16
+ test-results/
17
  submodules/rlp/build/
18
  submodules/rlp/rlp.egg-info/
19
  submodules/rlp/rlp/constants*.so
frontend/.gitignore CHANGED
@@ -12,6 +12,11 @@ dist
12
  dist-ssr
13
  *.local
14
 
 
 
 
 
 
15
  # Editor directories and files
16
  .vscode/*
17
  !.vscode/extensions.json
 
12
  dist-ssr
13
  *.local
14
 
15
+ # Playwright / test outputs (transient)
16
+ test-results
17
+ playwright-report
18
+ test/pipeline/roundtrip_out.json
19
+
20
  # Editor directories and files
21
  .vscode/*
22
  !.vscode/extensions.json
frontend/e2e/bridges.spec.ts ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { readFileSync } from "node:fs";
2
+ import { test, expect } from "@playwright/test";
3
+
4
+ type Fixture = {
5
+ family: string;
6
+ difficulty: string;
7
+ filename: string;
8
+ args: string;
9
+ problem: string;
10
+ solution: string;
11
+ };
12
+
13
+ const fixtures: Fixture[] = JSON.parse(
14
+ readFileSync(new URL("./../test/pipeline/fixtures.json", import.meta.url), "utf8"),
15
+ );
16
+ // Click plan (ordered grid-button indices, repeated for double bridges) is
17
+ // precomputed by the vitest round-trip step from the real editor functions.
18
+ const clickPlan: Record<string, number[]> = JSON.parse(
19
+ readFileSync(new URL("./../test/pipeline/bridges_clickplan.json", import.meta.url), "utf8"),
20
+ );
21
+
22
+ const fixture =
23
+ fixtures.find((f) => f.family === "bridges" && f.difficulty === "medium") ??
24
+ fixtures.find((f) => f.family === "bridges");
25
+
26
+ test("bridges: drawing the reference solution in the real UI verifies as solved", async ({
27
+ page,
28
+ request,
29
+ }) => {
30
+ expect(fixture, "no bridges fixture available").toBeTruthy();
31
+ const f = fixture!;
32
+ const clicks = clickPlan[f.filename];
33
+ expect(clicks?.length, `no click plan for ${f.filename}`).toBeGreaterThan(0);
34
+
35
+ // Seed a deterministic session for this exact puzzle via the real API.
36
+ const res = await request.post("/api/sessions", {
37
+ data: {
38
+ player_name: "test", // 'test' players are excluded from the leaderboard
39
+ puzzle_type: "bridges",
40
+ difficulty: f.difficulty,
41
+ puzzle_id: f.filename,
42
+ },
43
+ });
44
+ expect(res.ok(), `create session failed: ${res.status()}`).toBeTruthy();
45
+ const session = await res.json();
46
+
47
+ await page.goto(`/play/${session.session_id}`);
48
+ const grid = page.locator(".bridges-grid");
49
+ await expect(grid).toBeVisible();
50
+ const buttons = grid.locator("button");
51
+
52
+ for (const idx of clicks) {
53
+ await buttons.nth(idx).click();
54
+ }
55
+
56
+ await page.getByRole("button", { name: "Submit" }).click();
57
+
58
+ // Solving navigates to /done/{id}; "not solved" would keep us on /play with a banner.
59
+ await expect(page).toHaveURL(/\/done\//, { timeout: 15_000 });
60
+ });
frontend/package-lock.json CHANGED
@@ -14,6 +14,7 @@
14
  },
15
  "devDependencies": {
16
  "@eslint/js": "^10.0.1",
 
17
  "@types/node": "^24.12.3",
18
  "@types/react": "^19.2.14",
19
  "@types/react-dom": "^19.2.3",
@@ -24,7 +25,8 @@
24
  "globals": "^17.6.0",
25
  "typescript": "~6.0.2",
26
  "typescript-eslint": "^8.59.2",
27
- "vite": "^8.0.12"
 
28
  }
29
  },
30
  "node_modules/@babel/code-frame": {
@@ -301,6 +303,448 @@
301
  "tslib": "^2.4.0"
302
  }
303
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
  "node_modules/@eslint-community/eslint-utils": {
305
  "version": "4.9.1",
306
  "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
@@ -517,67 +961,270 @@
517
  "@jridgewell/trace-mapping": "^0.3.24"
518
  }
519
  },
520
- "node_modules/@jridgewell/resolve-uri": {
521
- "version": "3.1.2",
522
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
523
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
524
  "dev": true,
525
  "license": "MIT",
 
 
 
 
526
  "engines": {
527
- "node": ">=6.0.0"
528
  }
529
  },
530
- "node_modules/@jridgewell/sourcemap-codec": {
531
- "version": "1.5.5",
532
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
533
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
534
- "dev": true,
535
- "license": "MIT"
536
- },
537
- "node_modules/@jridgewell/trace-mapping": {
538
- "version": "0.3.31",
539
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
540
- "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
541
  "dev": true,
542
  "license": "MIT",
543
- "dependencies": {
544
- "@jridgewell/resolve-uri": "^3.1.0",
545
- "@jridgewell/sourcemap-codec": "^1.4.14"
 
 
 
546
  }
547
  },
548
- "node_modules/@napi-rs/wasm-runtime": {
549
- "version": "1.1.4",
550
- "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
551
- "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
 
 
 
552
  "dev": true,
553
  "license": "MIT",
554
  "optional": true,
555
- "dependencies": {
556
- "@tybys/wasm-util": "^0.10.1"
557
- },
558
- "funding": {
559
- "type": "github",
560
- "url": "https://github.com/sponsors/Brooooooklyn"
561
- },
562
- "peerDependencies": {
563
- "@emnapi/core": "^1.7.1",
564
- "@emnapi/runtime": "^1.7.1"
565
  }
566
  },
567
- "node_modules/@oxc-project/types": {
568
- "version": "0.130.0",
569
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz",
570
- "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==",
 
 
 
571
  "dev": true,
572
  "license": "MIT",
573
- "funding": {
574
- "url": "https://github.com/sponsors/Boshen"
 
 
 
 
575
  }
576
  },
577
- "node_modules/@rolldown/binding-android-arm64": {
578
  "version": "1.0.1",
579
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz",
580
- "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==",
581
  "cpu": [
582
  "arm64"
583
  ],
@@ -585,16 +1232,35 @@
585
  "license": "MIT",
586
  "optional": true,
587
  "os": [
588
- "android"
589
  ],
590
  "engines": {
591
  "node": "^20.19.0 || >=22.12.0"
592
  }
593
  },
594
- "node_modules/@rolldown/binding-darwin-arm64": {
595
  "version": "1.0.1",
596
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz",
597
- "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
598
  "cpu": [
599
  "arm64"
600
  ],
@@ -602,16 +1268,16 @@
602
  "license": "MIT",
603
  "optional": true,
604
  "os": [
605
- "darwin"
606
  ],
607
  "engines": {
608
  "node": "^20.19.0 || >=22.12.0"
609
  }
610
  },
611
- "node_modules/@rolldown/binding-darwin-x64": {
612
  "version": "1.0.1",
613
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz",
614
- "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==",
615
  "cpu": [
616
  "x64"
617
  ],
@@ -619,33 +1285,107 @@
619
  "license": "MIT",
620
  "optional": true,
621
  "os": [
622
- "darwin"
623
  ],
624
  "engines": {
625
  "node": "^20.19.0 || >=22.12.0"
626
  }
627
  },
628
- "node_modules/@rolldown/binding-freebsd-x64": {
629
  "version": "1.0.1",
630
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz",
631
- "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
632
  "cpu": [
633
  "x64"
634
  ],
635
  "dev": true,
636
  "license": "MIT",
637
  "optional": true,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
638
  "os": [
639
  "freebsd"
 
 
 
 
 
 
 
 
640
  ],
641
- "engines": {
642
- "node": "^20.19.0 || >=22.12.0"
643
- }
 
 
 
644
  },
645
- "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
646
- "version": "1.0.1",
647
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz",
648
- "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==",
649
  "cpu": [
650
  "arm"
651
  ],
@@ -654,15 +1394,26 @@
654
  "optional": true,
655
  "os": [
656
  "linux"
 
 
 
 
 
 
 
 
657
  ],
658
- "engines": {
659
- "node": "^20.19.0 || >=22.12.0"
660
- }
 
 
 
661
  },
662
- "node_modules/@rolldown/binding-linux-arm64-gnu": {
663
- "version": "1.0.1",
664
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz",
665
- "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==",
666
  "cpu": [
667
  "arm64"
668
  ],
@@ -671,49 +1422,110 @@
671
  "optional": true,
672
  "os": [
673
  "linux"
 
 
 
 
 
 
 
 
674
  ],
675
- "engines": {
676
- "node": "^20.19.0 || >=22.12.0"
677
- }
 
 
 
678
  },
679
- "node_modules/@rolldown/binding-linux-arm64-musl": {
680
- "version": "1.0.1",
681
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz",
682
- "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
683
  "cpu": [
684
- "arm64"
685
  ],
686
  "dev": true,
687
  "license": "MIT",
688
  "optional": true,
689
  "os": [
690
  "linux"
691
- ],
692
- "engines": {
693
- "node": "^20.19.0 || >=22.12.0"
694
- }
695
  },
696
- "node_modules/@rolldown/binding-linux-ppc64-gnu": {
697
- "version": "1.0.1",
698
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz",
699
- "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==",
700
  "cpu": [
701
- "ppc64"
702
  ],
703
  "dev": true,
704
  "license": "MIT",
705
  "optional": true,
706
  "os": [
707
  "linux"
708
- ],
709
- "engines": {
710
- "node": "^20.19.0 || >=22.12.0"
711
- }
712
  },
713
- "node_modules/@rolldown/binding-linux-s390x-gnu": {
714
- "version": "1.0.1",
715
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz",
716
- "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==",
717
  "cpu": [
718
  "s390x"
719
  ],
@@ -722,15 +1534,12 @@
722
  "optional": true,
723
  "os": [
724
  "linux"
725
- ],
726
- "engines": {
727
- "node": "^20.19.0 || >=22.12.0"
728
- }
729
  },
730
- "node_modules/@rolldown/binding-linux-x64-gnu": {
731
- "version": "1.0.1",
732
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz",
733
- "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==",
734
  "cpu": [
735
  "x64"
736
  ],
@@ -739,15 +1548,12 @@
739
  "optional": true,
740
  "os": [
741
  "linux"
742
- ],
743
- "engines": {
744
- "node": "^20.19.0 || >=22.12.0"
745
- }
746
  },
747
- "node_modules/@rolldown/binding-linux-x64-musl": {
748
- "version": "1.0.1",
749
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz",
750
- "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==",
751
  "cpu": [
752
  "x64"
753
  ],
@@ -756,15 +1562,26 @@
756
  "optional": true,
757
  "os": [
758
  "linux"
 
 
 
 
 
 
 
 
759
  ],
760
- "engines": {
761
- "node": "^20.19.0 || >=22.12.0"
762
- }
 
 
 
763
  },
764
- "node_modules/@rolldown/binding-openharmony-arm64": {
765
- "version": "1.0.1",
766
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz",
767
- "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==",
768
  "cpu": [
769
  "arm64"
770
  ],
@@ -773,51 +1590,40 @@
773
  "optional": true,
774
  "os": [
775
  "openharmony"
776
- ],
777
- "engines": {
778
- "node": "^20.19.0 || >=22.12.0"
779
- }
780
  },
781
- "node_modules/@rolldown/binding-wasm32-wasi": {
782
- "version": "1.0.1",
783
- "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz",
784
- "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==",
785
  "cpu": [
786
- "wasm32"
787
  ],
788
  "dev": true,
789
  "license": "MIT",
790
  "optional": true,
791
- "dependencies": {
792
- "@emnapi/core": "1.10.0",
793
- "@emnapi/runtime": "1.10.0",
794
- "@napi-rs/wasm-runtime": "^1.1.4"
795
- },
796
- "engines": {
797
- "node": "^20.19.0 || >=22.12.0"
798
- }
799
  },
800
- "node_modules/@rolldown/binding-win32-arm64-msvc": {
801
- "version": "1.0.1",
802
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz",
803
- "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==",
804
  "cpu": [
805
- "arm64"
806
  ],
807
  "dev": true,
808
  "license": "MIT",
809
  "optional": true,
810
  "os": [
811
  "win32"
812
- ],
813
- "engines": {
814
- "node": "^20.19.0 || >=22.12.0"
815
- }
816
  },
817
- "node_modules/@rolldown/binding-win32-x64-msvc": {
818
- "version": "1.0.1",
819
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz",
820
- "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==",
821
  "cpu": [
822
  "x64"
823
  ],
@@ -826,17 +1632,21 @@
826
  "optional": true,
827
  "os": [
828
  "win32"
829
- ],
830
- "engines": {
831
- "node": "^20.19.0 || >=22.12.0"
832
- }
833
  },
834
- "node_modules/@rolldown/pluginutils": {
835
- "version": "1.0.1",
836
- "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
837
- "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
 
 
 
838
  "dev": true,
839
- "license": "MIT"
 
 
 
 
840
  },
841
  "node_modules/@tybys/wasm-util": {
842
  "version": "0.10.2",
@@ -849,6 +1659,24 @@
849
  "tslib": "^2.4.0"
850
  }
851
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
852
  "node_modules/@types/esrecurse": {
853
  "version": "4.3.1",
854
  "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
@@ -1169,6 +1997,94 @@
1169
  }
1170
  }
1171
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1172
  "node_modules/acorn": {
1173
  "version": "8.16.0",
1174
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
@@ -1209,6 +2125,16 @@
1209
  "url": "https://github.com/sponsors/epoberezkin"
1210
  }
1211
  },
 
 
 
 
 
 
 
 
 
 
1212
  "node_modules/balanced-match": {
1213
  "version": "4.0.4",
1214
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
@@ -1279,6 +2205,16 @@
1279
  "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
1280
  }
1281
  },
 
 
 
 
 
 
 
 
 
 
1282
  "node_modules/caniuse-lite": {
1283
  "version": "1.0.30001793",
1284
  "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
@@ -1300,6 +2236,33 @@
1300
  ],
1301
  "license": "CC-BY-4.0"
1302
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1303
  "node_modules/convert-source-map": {
1304
  "version": "2.0.0",
1305
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
@@ -1360,6 +2323,16 @@
1360
  }
1361
  }
1362
  },
 
 
 
 
 
 
 
 
 
 
1363
  "node_modules/deep-is": {
1364
  "version": "0.1.4",
1365
  "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -1384,6 +2357,55 @@
1384
  "dev": true,
1385
  "license": "ISC"
1386
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1387
  "node_modules/escalade": {
1388
  "version": "3.2.0",
1389
  "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
@@ -1579,6 +2601,16 @@
1579
  "node": ">=4.0"
1580
  }
1581
  },
 
 
 
 
 
 
 
 
 
 
1582
  "node_modules/esutils": {
1583
  "version": "2.0.3",
1584
  "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -1589,6 +2621,16 @@
1589
  "node": ">=0.10.0"
1590
  }
1591
  },
 
 
 
 
 
 
 
 
 
 
1592
  "node_modules/fast-deep-equal": {
1593
  "version": "3.1.3",
1594
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
@@ -2152,6 +3194,13 @@
2152
  "url": "https://github.com/sponsors/sindresorhus"
2153
  }
2154
  },
 
 
 
 
 
 
 
2155
  "node_modules/lru-cache": {
2156
  "version": "5.1.1",
2157
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -2162,6 +3211,16 @@
2162
  "yallist": "^3.0.2"
2163
  }
2164
  },
 
 
 
 
 
 
 
 
 
 
2165
  "node_modules/minimatch": {
2166
  "version": "10.2.5",
2167
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
@@ -2288,6 +3347,23 @@
2288
  "node": ">=8"
2289
  }
2290
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2291
  "node_modules/picocolors": {
2292
  "version": "1.1.1",
2293
  "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
@@ -2302,10 +3378,57 @@
2302
  "dev": true,
2303
  "license": "MIT",
2304
  "engines": {
2305
- "node": ">=12"
2306
- },
2307
- "funding": {
2308
- "url": "https://github.com/sponsors/jonschlinkert"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2309
  }
2310
  },
2311
  "node_modules/postcss": {
@@ -2450,6 +3573,51 @@
2450
  "@rolldown/binding-win32-x64-msvc": "1.0.1"
2451
  }
2452
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2453
  "node_modules/scheduler": {
2454
  "version": "0.27.0",
2455
  "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
@@ -2495,6 +3663,13 @@
2495
  "node": ">=8"
2496
  }
2497
  },
 
 
 
 
 
 
 
2498
  "node_modules/source-map-js": {
2499
  "version": "1.2.1",
2500
  "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -2505,6 +3680,54 @@
2505
  "node": ">=0.10.0"
2506
  }
2507
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2508
  "node_modules/tinyglobby": {
2509
  "version": "0.2.16",
2510
  "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
@@ -2522,6 +3745,36 @@
2522
  "url": "https://github.com/sponsors/SuperchupuDev"
2523
  }
2524
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2525
  "node_modules/ts-api-utils": {
2526
  "version": "2.5.0",
2527
  "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
@@ -2720,6 +3973,279 @@
2720
  }
2721
  }
2722
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2723
  "node_modules/which": {
2724
  "version": "2.0.2",
2725
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -2736,6 +4262,23 @@
2736
  "node": ">= 8"
2737
  }
2738
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2739
  "node_modules/word-wrap": {
2740
  "version": "1.2.5",
2741
  "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
 
14
  },
15
  "devDependencies": {
16
  "@eslint/js": "^10.0.1",
17
+ "@playwright/test": "^1.60.0",
18
  "@types/node": "^24.12.3",
19
  "@types/react": "^19.2.14",
20
  "@types/react-dom": "^19.2.3",
 
25
  "globals": "^17.6.0",
26
  "typescript": "~6.0.2",
27
  "typescript-eslint": "^8.59.2",
28
+ "vite": "^8.0.12",
29
+ "vitest": "^3.2.6"
30
  }
31
  },
32
  "node_modules/@babel/code-frame": {
 
303
  "tslib": "^2.4.0"
304
  }
305
  },
306
+ "node_modules/@esbuild/aix-ppc64": {
307
+ "version": "0.27.7",
308
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz",
309
+ "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==",
310
+ "cpu": [
311
+ "ppc64"
312
+ ],
313
+ "dev": true,
314
+ "license": "MIT",
315
+ "optional": true,
316
+ "os": [
317
+ "aix"
318
+ ],
319
+ "engines": {
320
+ "node": ">=18"
321
+ }
322
+ },
323
+ "node_modules/@esbuild/android-arm": {
324
+ "version": "0.27.7",
325
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz",
326
+ "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==",
327
+ "cpu": [
328
+ "arm"
329
+ ],
330
+ "dev": true,
331
+ "license": "MIT",
332
+ "optional": true,
333
+ "os": [
334
+ "android"
335
+ ],
336
+ "engines": {
337
+ "node": ">=18"
338
+ }
339
+ },
340
+ "node_modules/@esbuild/android-arm64": {
341
+ "version": "0.27.7",
342
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz",
343
+ "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==",
344
+ "cpu": [
345
+ "arm64"
346
+ ],
347
+ "dev": true,
348
+ "license": "MIT",
349
+ "optional": true,
350
+ "os": [
351
+ "android"
352
+ ],
353
+ "engines": {
354
+ "node": ">=18"
355
+ }
356
+ },
357
+ "node_modules/@esbuild/android-x64": {
358
+ "version": "0.27.7",
359
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz",
360
+ "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==",
361
+ "cpu": [
362
+ "x64"
363
+ ],
364
+ "dev": true,
365
+ "license": "MIT",
366
+ "optional": true,
367
+ "os": [
368
+ "android"
369
+ ],
370
+ "engines": {
371
+ "node": ">=18"
372
+ }
373
+ },
374
+ "node_modules/@esbuild/darwin-arm64": {
375
+ "version": "0.27.7",
376
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz",
377
+ "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==",
378
+ "cpu": [
379
+ "arm64"
380
+ ],
381
+ "dev": true,
382
+ "license": "MIT",
383
+ "optional": true,
384
+ "os": [
385
+ "darwin"
386
+ ],
387
+ "engines": {
388
+ "node": ">=18"
389
+ }
390
+ },
391
+ "node_modules/@esbuild/darwin-x64": {
392
+ "version": "0.27.7",
393
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz",
394
+ "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==",
395
+ "cpu": [
396
+ "x64"
397
+ ],
398
+ "dev": true,
399
+ "license": "MIT",
400
+ "optional": true,
401
+ "os": [
402
+ "darwin"
403
+ ],
404
+ "engines": {
405
+ "node": ">=18"
406
+ }
407
+ },
408
+ "node_modules/@esbuild/freebsd-arm64": {
409
+ "version": "0.27.7",
410
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz",
411
+ "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==",
412
+ "cpu": [
413
+ "arm64"
414
+ ],
415
+ "dev": true,
416
+ "license": "MIT",
417
+ "optional": true,
418
+ "os": [
419
+ "freebsd"
420
+ ],
421
+ "engines": {
422
+ "node": ">=18"
423
+ }
424
+ },
425
+ "node_modules/@esbuild/freebsd-x64": {
426
+ "version": "0.27.7",
427
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz",
428
+ "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==",
429
+ "cpu": [
430
+ "x64"
431
+ ],
432
+ "dev": true,
433
+ "license": "MIT",
434
+ "optional": true,
435
+ "os": [
436
+ "freebsd"
437
+ ],
438
+ "engines": {
439
+ "node": ">=18"
440
+ }
441
+ },
442
+ "node_modules/@esbuild/linux-arm": {
443
+ "version": "0.27.7",
444
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz",
445
+ "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==",
446
+ "cpu": [
447
+ "arm"
448
+ ],
449
+ "dev": true,
450
+ "license": "MIT",
451
+ "optional": true,
452
+ "os": [
453
+ "linux"
454
+ ],
455
+ "engines": {
456
+ "node": ">=18"
457
+ }
458
+ },
459
+ "node_modules/@esbuild/linux-arm64": {
460
+ "version": "0.27.7",
461
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz",
462
+ "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==",
463
+ "cpu": [
464
+ "arm64"
465
+ ],
466
+ "dev": true,
467
+ "license": "MIT",
468
+ "optional": true,
469
+ "os": [
470
+ "linux"
471
+ ],
472
+ "engines": {
473
+ "node": ">=18"
474
+ }
475
+ },
476
+ "node_modules/@esbuild/linux-ia32": {
477
+ "version": "0.27.7",
478
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz",
479
+ "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==",
480
+ "cpu": [
481
+ "ia32"
482
+ ],
483
+ "dev": true,
484
+ "license": "MIT",
485
+ "optional": true,
486
+ "os": [
487
+ "linux"
488
+ ],
489
+ "engines": {
490
+ "node": ">=18"
491
+ }
492
+ },
493
+ "node_modules/@esbuild/linux-loong64": {
494
+ "version": "0.27.7",
495
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz",
496
+ "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==",
497
+ "cpu": [
498
+ "loong64"
499
+ ],
500
+ "dev": true,
501
+ "license": "MIT",
502
+ "optional": true,
503
+ "os": [
504
+ "linux"
505
+ ],
506
+ "engines": {
507
+ "node": ">=18"
508
+ }
509
+ },
510
+ "node_modules/@esbuild/linux-mips64el": {
511
+ "version": "0.27.7",
512
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz",
513
+ "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==",
514
+ "cpu": [
515
+ "mips64el"
516
+ ],
517
+ "dev": true,
518
+ "license": "MIT",
519
+ "optional": true,
520
+ "os": [
521
+ "linux"
522
+ ],
523
+ "engines": {
524
+ "node": ">=18"
525
+ }
526
+ },
527
+ "node_modules/@esbuild/linux-ppc64": {
528
+ "version": "0.27.7",
529
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz",
530
+ "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==",
531
+ "cpu": [
532
+ "ppc64"
533
+ ],
534
+ "dev": true,
535
+ "license": "MIT",
536
+ "optional": true,
537
+ "os": [
538
+ "linux"
539
+ ],
540
+ "engines": {
541
+ "node": ">=18"
542
+ }
543
+ },
544
+ "node_modules/@esbuild/linux-riscv64": {
545
+ "version": "0.27.7",
546
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz",
547
+ "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==",
548
+ "cpu": [
549
+ "riscv64"
550
+ ],
551
+ "dev": true,
552
+ "license": "MIT",
553
+ "optional": true,
554
+ "os": [
555
+ "linux"
556
+ ],
557
+ "engines": {
558
+ "node": ">=18"
559
+ }
560
+ },
561
+ "node_modules/@esbuild/linux-s390x": {
562
+ "version": "0.27.7",
563
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz",
564
+ "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==",
565
+ "cpu": [
566
+ "s390x"
567
+ ],
568
+ "dev": true,
569
+ "license": "MIT",
570
+ "optional": true,
571
+ "os": [
572
+ "linux"
573
+ ],
574
+ "engines": {
575
+ "node": ">=18"
576
+ }
577
+ },
578
+ "node_modules/@esbuild/linux-x64": {
579
+ "version": "0.27.7",
580
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz",
581
+ "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==",
582
+ "cpu": [
583
+ "x64"
584
+ ],
585
+ "dev": true,
586
+ "license": "MIT",
587
+ "optional": true,
588
+ "os": [
589
+ "linux"
590
+ ],
591
+ "engines": {
592
+ "node": ">=18"
593
+ }
594
+ },
595
+ "node_modules/@esbuild/netbsd-arm64": {
596
+ "version": "0.27.7",
597
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz",
598
+ "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==",
599
+ "cpu": [
600
+ "arm64"
601
+ ],
602
+ "dev": true,
603
+ "license": "MIT",
604
+ "optional": true,
605
+ "os": [
606
+ "netbsd"
607
+ ],
608
+ "engines": {
609
+ "node": ">=18"
610
+ }
611
+ },
612
+ "node_modules/@esbuild/netbsd-x64": {
613
+ "version": "0.27.7",
614
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz",
615
+ "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==",
616
+ "cpu": [
617
+ "x64"
618
+ ],
619
+ "dev": true,
620
+ "license": "MIT",
621
+ "optional": true,
622
+ "os": [
623
+ "netbsd"
624
+ ],
625
+ "engines": {
626
+ "node": ">=18"
627
+ }
628
+ },
629
+ "node_modules/@esbuild/openbsd-arm64": {
630
+ "version": "0.27.7",
631
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz",
632
+ "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==",
633
+ "cpu": [
634
+ "arm64"
635
+ ],
636
+ "dev": true,
637
+ "license": "MIT",
638
+ "optional": true,
639
+ "os": [
640
+ "openbsd"
641
+ ],
642
+ "engines": {
643
+ "node": ">=18"
644
+ }
645
+ },
646
+ "node_modules/@esbuild/openbsd-x64": {
647
+ "version": "0.27.7",
648
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz",
649
+ "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==",
650
+ "cpu": [
651
+ "x64"
652
+ ],
653
+ "dev": true,
654
+ "license": "MIT",
655
+ "optional": true,
656
+ "os": [
657
+ "openbsd"
658
+ ],
659
+ "engines": {
660
+ "node": ">=18"
661
+ }
662
+ },
663
+ "node_modules/@esbuild/openharmony-arm64": {
664
+ "version": "0.27.7",
665
+ "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz",
666
+ "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==",
667
+ "cpu": [
668
+ "arm64"
669
+ ],
670
+ "dev": true,
671
+ "license": "MIT",
672
+ "optional": true,
673
+ "os": [
674
+ "openharmony"
675
+ ],
676
+ "engines": {
677
+ "node": ">=18"
678
+ }
679
+ },
680
+ "node_modules/@esbuild/sunos-x64": {
681
+ "version": "0.27.7",
682
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz",
683
+ "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==",
684
+ "cpu": [
685
+ "x64"
686
+ ],
687
+ "dev": true,
688
+ "license": "MIT",
689
+ "optional": true,
690
+ "os": [
691
+ "sunos"
692
+ ],
693
+ "engines": {
694
+ "node": ">=18"
695
+ }
696
+ },
697
+ "node_modules/@esbuild/win32-arm64": {
698
+ "version": "0.27.7",
699
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz",
700
+ "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==",
701
+ "cpu": [
702
+ "arm64"
703
+ ],
704
+ "dev": true,
705
+ "license": "MIT",
706
+ "optional": true,
707
+ "os": [
708
+ "win32"
709
+ ],
710
+ "engines": {
711
+ "node": ">=18"
712
+ }
713
+ },
714
+ "node_modules/@esbuild/win32-ia32": {
715
+ "version": "0.27.7",
716
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz",
717
+ "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==",
718
+ "cpu": [
719
+ "ia32"
720
+ ],
721
+ "dev": true,
722
+ "license": "MIT",
723
+ "optional": true,
724
+ "os": [
725
+ "win32"
726
+ ],
727
+ "engines": {
728
+ "node": ">=18"
729
+ }
730
+ },
731
+ "node_modules/@esbuild/win32-x64": {
732
+ "version": "0.27.7",
733
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz",
734
+ "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==",
735
+ "cpu": [
736
+ "x64"
737
+ ],
738
+ "dev": true,
739
+ "license": "MIT",
740
+ "optional": true,
741
+ "os": [
742
+ "win32"
743
+ ],
744
+ "engines": {
745
+ "node": ">=18"
746
+ }
747
+ },
748
  "node_modules/@eslint-community/eslint-utils": {
749
  "version": "4.9.1",
750
  "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
 
961
  "@jridgewell/trace-mapping": "^0.3.24"
962
  }
963
  },
964
+ "node_modules/@jridgewell/resolve-uri": {
965
+ "version": "3.1.2",
966
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
967
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
968
+ "dev": true,
969
+ "license": "MIT",
970
+ "engines": {
971
+ "node": ">=6.0.0"
972
+ }
973
+ },
974
+ "node_modules/@jridgewell/sourcemap-codec": {
975
+ "version": "1.5.5",
976
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
977
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
978
+ "dev": true,
979
+ "license": "MIT"
980
+ },
981
+ "node_modules/@jridgewell/trace-mapping": {
982
+ "version": "0.3.31",
983
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
984
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
985
+ "dev": true,
986
+ "license": "MIT",
987
+ "dependencies": {
988
+ "@jridgewell/resolve-uri": "^3.1.0",
989
+ "@jridgewell/sourcemap-codec": "^1.4.14"
990
+ }
991
+ },
992
+ "node_modules/@napi-rs/wasm-runtime": {
993
+ "version": "1.1.4",
994
+ "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.4.tgz",
995
+ "integrity": "sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==",
996
+ "dev": true,
997
+ "license": "MIT",
998
+ "optional": true,
999
+ "dependencies": {
1000
+ "@tybys/wasm-util": "^0.10.1"
1001
+ },
1002
+ "funding": {
1003
+ "type": "github",
1004
+ "url": "https://github.com/sponsors/Brooooooklyn"
1005
+ },
1006
+ "peerDependencies": {
1007
+ "@emnapi/core": "^1.7.1",
1008
+ "@emnapi/runtime": "^1.7.1"
1009
+ }
1010
+ },
1011
+ "node_modules/@oxc-project/types": {
1012
+ "version": "0.130.0",
1013
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.130.0.tgz",
1014
+ "integrity": "sha512-ibD2usx9JRu7f5pu2tMKMI4cpA4NgXJQoYRP4pQ7Pxmn1l6k/53qWtQWZayhYy3X4QZkt90Ot+mJEaeXouio6Q==",
1015
+ "dev": true,
1016
+ "license": "MIT",
1017
+ "funding": {
1018
+ "url": "https://github.com/sponsors/Boshen"
1019
+ }
1020
+ },
1021
+ "node_modules/@playwright/test": {
1022
+ "version": "1.60.0",
1023
+ "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz",
1024
+ "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==",
1025
+ "dev": true,
1026
+ "license": "Apache-2.0",
1027
+ "dependencies": {
1028
+ "playwright": "1.60.0"
1029
+ },
1030
+ "bin": {
1031
+ "playwright": "cli.js"
1032
+ },
1033
+ "engines": {
1034
+ "node": ">=18"
1035
+ }
1036
+ },
1037
+ "node_modules/@rolldown/binding-android-arm64": {
1038
+ "version": "1.0.1",
1039
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.0.1.tgz",
1040
+ "integrity": "sha512-fJI3I0r3C3Oj/zdBCpaCmBRZYf07xpaq4yCfDDoSFm+beWNzbIl26puW8RraUdugoJw/95zerNOn6jasAhzSmg==",
1041
+ "cpu": [
1042
+ "arm64"
1043
+ ],
1044
+ "dev": true,
1045
+ "license": "MIT",
1046
+ "optional": true,
1047
+ "os": [
1048
+ "android"
1049
+ ],
1050
+ "engines": {
1051
+ "node": "^20.19.0 || >=22.12.0"
1052
+ }
1053
+ },
1054
+ "node_modules/@rolldown/binding-darwin-arm64": {
1055
+ "version": "1.0.1",
1056
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.0.1.tgz",
1057
+ "integrity": "sha512-cKnAhWEsV7TPcA/5EAteDp6KcJZBQ2G+BqE7zayMMi7kMvwRsbv7WT9aOnn0WNl4SKEIf43vjS31iUPu80nzXg==",
1058
+ "cpu": [
1059
+ "arm64"
1060
+ ],
1061
+ "dev": true,
1062
+ "license": "MIT",
1063
+ "optional": true,
1064
+ "os": [
1065
+ "darwin"
1066
+ ],
1067
+ "engines": {
1068
+ "node": "^20.19.0 || >=22.12.0"
1069
+ }
1070
+ },
1071
+ "node_modules/@rolldown/binding-darwin-x64": {
1072
+ "version": "1.0.1",
1073
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.0.1.tgz",
1074
+ "integrity": "sha512-YKrVwQjIRBPo+5G/u03wGjbdy4q7pyzCe93DK9VJ7zkVmeg8LJ7GbgsiHWdR4xSoe4CAXRD7Bcjgbtr64bkXNg==",
1075
+ "cpu": [
1076
+ "x64"
1077
+ ],
1078
+ "dev": true,
1079
+ "license": "MIT",
1080
+ "optional": true,
1081
+ "os": [
1082
+ "darwin"
1083
+ ],
1084
+ "engines": {
1085
+ "node": "^20.19.0 || >=22.12.0"
1086
+ }
1087
+ },
1088
+ "node_modules/@rolldown/binding-freebsd-x64": {
1089
+ "version": "1.0.1",
1090
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.0.1.tgz",
1091
+ "integrity": "sha512-z/oBsREo46SsFqBwYtFe0kpJeBijAT48O/WXLI4suiCLBkr03RTtTJMCzSdDd2znlh8VJizL09XVkQgk8IZonw==",
1092
+ "cpu": [
1093
+ "x64"
1094
+ ],
1095
+ "dev": true,
1096
+ "license": "MIT",
1097
+ "optional": true,
1098
+ "os": [
1099
+ "freebsd"
1100
+ ],
1101
+ "engines": {
1102
+ "node": "^20.19.0 || >=22.12.0"
1103
+ }
1104
+ },
1105
+ "node_modules/@rolldown/binding-linux-arm-gnueabihf": {
1106
+ "version": "1.0.1",
1107
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.0.1.tgz",
1108
+ "integrity": "sha512-ik8q7GM11zxvYxFc2PeDcT6TBvhCQMaUxfph/M5l9sKuTs/Sjg3L+Byw0F7w0ZVLBZmx30P+gG0ECzzN+MFcmQ==",
1109
+ "cpu": [
1110
+ "arm"
1111
+ ],
1112
+ "dev": true,
1113
+ "license": "MIT",
1114
+ "optional": true,
1115
+ "os": [
1116
+ "linux"
1117
+ ],
1118
+ "engines": {
1119
+ "node": "^20.19.0 || >=22.12.0"
1120
+ }
1121
+ },
1122
+ "node_modules/@rolldown/binding-linux-arm64-gnu": {
1123
+ "version": "1.0.1",
1124
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.0.1.tgz",
1125
+ "integrity": "sha512-QoSx2EkyrrdZ6kcyE8stqZ62t0Yra8Fs5ia9lOxJrh6TMQJK7gQKmscdTHf7pOXKREKrVwOtJcQG3qVSfc866A==",
1126
+ "cpu": [
1127
+ "arm64"
1128
+ ],
1129
+ "dev": true,
1130
+ "license": "MIT",
1131
+ "optional": true,
1132
+ "os": [
1133
+ "linux"
1134
+ ],
1135
+ "engines": {
1136
+ "node": "^20.19.0 || >=22.12.0"
1137
+ }
1138
+ },
1139
+ "node_modules/@rolldown/binding-linux-arm64-musl": {
1140
+ "version": "1.0.1",
1141
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.0.1.tgz",
1142
+ "integrity": "sha512-uwNwFpwKeNiZawfAWBgg0VIztPTV3ihhh1vV334h9ivnNLorxnQMU6Fz8wG1Zb4Qh9LC1/MkcyT3YlDXG3Rsgg==",
1143
+ "cpu": [
1144
+ "arm64"
1145
+ ],
1146
+ "dev": true,
1147
+ "license": "MIT",
1148
+ "optional": true,
1149
+ "os": [
1150
+ "linux"
1151
+ ],
1152
+ "engines": {
1153
+ "node": "^20.19.0 || >=22.12.0"
1154
+ }
1155
+ },
1156
+ "node_modules/@rolldown/binding-linux-ppc64-gnu": {
1157
+ "version": "1.0.1",
1158
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.0.1.tgz",
1159
+ "integrity": "sha512-zY1bul7OWr7DFBiJ++wofXvnr8B45ce3QsQUhKrIhXsygAh7bTkwyeM1bi1a2g5C/yC/N8TZyGDEoMfm/l9mpg==",
1160
+ "cpu": [
1161
+ "ppc64"
1162
+ ],
1163
  "dev": true,
1164
  "license": "MIT",
1165
+ "optional": true,
1166
+ "os": [
1167
+ "linux"
1168
+ ],
1169
  "engines": {
1170
+ "node": "^20.19.0 || >=22.12.0"
1171
  }
1172
  },
1173
+ "node_modules/@rolldown/binding-linux-s390x-gnu": {
1174
+ "version": "1.0.1",
1175
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.0.1.tgz",
1176
+ "integrity": "sha512-0frlsT/f4Ft6I7SMESTKnF3cZsdicQn1dCMkF/jT9wDLE+gGoiQfv1nmT9e+s7s/fekvvy6tZM2jHvI2tkbJDQ==",
1177
+ "cpu": [
1178
+ "s390x"
1179
+ ],
 
 
 
 
1180
  "dev": true,
1181
  "license": "MIT",
1182
+ "optional": true,
1183
+ "os": [
1184
+ "linux"
1185
+ ],
1186
+ "engines": {
1187
+ "node": "^20.19.0 || >=22.12.0"
1188
  }
1189
  },
1190
+ "node_modules/@rolldown/binding-linux-x64-gnu": {
1191
+ "version": "1.0.1",
1192
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.0.1.tgz",
1193
+ "integrity": "sha512-XABVmGp9Tg0WspTVvwduTc4fpqy6JnAUrSQe6OuyqD/03nI7r0O9OWUkMIwFrjKAIqolvqoA4ZrJppgwE0Gxmw==",
1194
+ "cpu": [
1195
+ "x64"
1196
+ ],
1197
  "dev": true,
1198
  "license": "MIT",
1199
  "optional": true,
1200
+ "os": [
1201
+ "linux"
1202
+ ],
1203
+ "engines": {
1204
+ "node": "^20.19.0 || >=22.12.0"
 
 
 
 
 
1205
  }
1206
  },
1207
+ "node_modules/@rolldown/binding-linux-x64-musl": {
1208
+ "version": "1.0.1",
1209
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.0.1.tgz",
1210
+ "integrity": "sha512-bV4fzswuzVcKD90o/VM6QqKxnxlDq0g2BISDLNVmxrnhpv1DDbyPhCIjYfvzYLV+MvkKKnQt2Q6AO86SEBULUQ==",
1211
+ "cpu": [
1212
+ "x64"
1213
+ ],
1214
  "dev": true,
1215
  "license": "MIT",
1216
+ "optional": true,
1217
+ "os": [
1218
+ "linux"
1219
+ ],
1220
+ "engines": {
1221
+ "node": "^20.19.0 || >=22.12.0"
1222
  }
1223
  },
1224
+ "node_modules/@rolldown/binding-openharmony-arm64": {
1225
  "version": "1.0.1",
1226
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.0.1.tgz",
1227
+ "integrity": "sha512-/Mh0Zhq3OP7fVs0kcQHZP6lZEthMGTaSf8UBQYSFEZDWGXXlEC+nJ6EqenaK2t4LBXMe3A+K/G2BVXXdtOr4PQ==",
1228
  "cpu": [
1229
  "arm64"
1230
  ],
 
1232
  "license": "MIT",
1233
  "optional": true,
1234
  "os": [
1235
+ "openharmony"
1236
  ],
1237
  "engines": {
1238
  "node": "^20.19.0 || >=22.12.0"
1239
  }
1240
  },
1241
+ "node_modules/@rolldown/binding-wasm32-wasi": {
1242
  "version": "1.0.1",
1243
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.0.1.tgz",
1244
+ "integrity": "sha512-+1xc9X45l8ufsBAm6Gjvx2qDRIY9lTVt0cgWNcJ+1gdhXvkbxePA60yRTwSTuXL09CMhyJmjpV7E3NoyxbqFQQ==",
1245
+ "cpu": [
1246
+ "wasm32"
1247
+ ],
1248
+ "dev": true,
1249
+ "license": "MIT",
1250
+ "optional": true,
1251
+ "dependencies": {
1252
+ "@emnapi/core": "1.10.0",
1253
+ "@emnapi/runtime": "1.10.0",
1254
+ "@napi-rs/wasm-runtime": "^1.1.4"
1255
+ },
1256
+ "engines": {
1257
+ "node": "^20.19.0 || >=22.12.0"
1258
+ }
1259
+ },
1260
+ "node_modules/@rolldown/binding-win32-arm64-msvc": {
1261
+ "version": "1.0.1",
1262
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.0.1.tgz",
1263
+ "integrity": "sha512-1D+UqZdfnuR+Jy1GgMJwi85bD40H21uNmOPRWQhw4oRSuolZ/B5rixZ45DK2KXOTCvmVCecauWgEhbw8bI7tOw==",
1264
  "cpu": [
1265
  "arm64"
1266
  ],
 
1268
  "license": "MIT",
1269
  "optional": true,
1270
  "os": [
1271
+ "win32"
1272
  ],
1273
  "engines": {
1274
  "node": "^20.19.0 || >=22.12.0"
1275
  }
1276
  },
1277
+ "node_modules/@rolldown/binding-win32-x64-msvc": {
1278
  "version": "1.0.1",
1279
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.0.1.tgz",
1280
+ "integrity": "sha512-INAycaWuhlOK3wk4mRHGsdgwYWmd9cChdPdE9bwWmy6rn9VqVNYNFGhOdXrofXUxwHIncSiPNb8tNm8knDVIeQ==",
1281
  "cpu": [
1282
  "x64"
1283
  ],
 
1285
  "license": "MIT",
1286
  "optional": true,
1287
  "os": [
1288
+ "win32"
1289
  ],
1290
  "engines": {
1291
  "node": "^20.19.0 || >=22.12.0"
1292
  }
1293
  },
1294
+ "node_modules/@rolldown/pluginutils": {
1295
  "version": "1.0.1",
1296
+ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz",
1297
+ "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==",
1298
+ "dev": true,
1299
+ "license": "MIT"
1300
+ },
1301
+ "node_modules/@rollup/rollup-android-arm-eabi": {
1302
+ "version": "4.61.1",
1303
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.1.tgz",
1304
+ "integrity": "sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==",
1305
+ "cpu": [
1306
+ "arm"
1307
+ ],
1308
+ "dev": true,
1309
+ "license": "MIT",
1310
+ "optional": true,
1311
+ "os": [
1312
+ "android"
1313
+ ]
1314
+ },
1315
+ "node_modules/@rollup/rollup-android-arm64": {
1316
+ "version": "4.61.1",
1317
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.1.tgz",
1318
+ "integrity": "sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw==",
1319
+ "cpu": [
1320
+ "arm64"
1321
+ ],
1322
+ "dev": true,
1323
+ "license": "MIT",
1324
+ "optional": true,
1325
+ "os": [
1326
+ "android"
1327
+ ]
1328
+ },
1329
+ "node_modules/@rollup/rollup-darwin-arm64": {
1330
+ "version": "4.61.1",
1331
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.1.tgz",
1332
+ "integrity": "sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA==",
1333
+ "cpu": [
1334
+ "arm64"
1335
+ ],
1336
+ "dev": true,
1337
+ "license": "MIT",
1338
+ "optional": true,
1339
+ "os": [
1340
+ "darwin"
1341
+ ]
1342
+ },
1343
+ "node_modules/@rollup/rollup-darwin-x64": {
1344
+ "version": "4.61.1",
1345
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.1.tgz",
1346
+ "integrity": "sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ==",
1347
  "cpu": [
1348
  "x64"
1349
  ],
1350
  "dev": true,
1351
  "license": "MIT",
1352
  "optional": true,
1353
+ "os": [
1354
+ "darwin"
1355
+ ]
1356
+ },
1357
+ "node_modules/@rollup/rollup-freebsd-arm64": {
1358
+ "version": "4.61.1",
1359
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.1.tgz",
1360
+ "integrity": "sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw==",
1361
+ "cpu": [
1362
+ "arm64"
1363
+ ],
1364
+ "dev": true,
1365
+ "license": "MIT",
1366
+ "optional": true,
1367
  "os": [
1368
  "freebsd"
1369
+ ]
1370
+ },
1371
+ "node_modules/@rollup/rollup-freebsd-x64": {
1372
+ "version": "4.61.1",
1373
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.1.tgz",
1374
+ "integrity": "sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw==",
1375
+ "cpu": [
1376
+ "x64"
1377
  ],
1378
+ "dev": true,
1379
+ "license": "MIT",
1380
+ "optional": true,
1381
+ "os": [
1382
+ "freebsd"
1383
+ ]
1384
  },
1385
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
1386
+ "version": "4.61.1",
1387
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.1.tgz",
1388
+ "integrity": "sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA==",
1389
  "cpu": [
1390
  "arm"
1391
  ],
 
1394
  "optional": true,
1395
  "os": [
1396
  "linux"
1397
+ ]
1398
+ },
1399
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
1400
+ "version": "4.61.1",
1401
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.1.tgz",
1402
+ "integrity": "sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ==",
1403
+ "cpu": [
1404
+ "arm"
1405
  ],
1406
+ "dev": true,
1407
+ "license": "MIT",
1408
+ "optional": true,
1409
+ "os": [
1410
+ "linux"
1411
+ ]
1412
  },
1413
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
1414
+ "version": "4.61.1",
1415
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.1.tgz",
1416
+ "integrity": "sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg==",
1417
  "cpu": [
1418
  "arm64"
1419
  ],
 
1422
  "optional": true,
1423
  "os": [
1424
  "linux"
1425
+ ]
1426
+ },
1427
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
1428
+ "version": "4.61.1",
1429
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.1.tgz",
1430
+ "integrity": "sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w==",
1431
+ "cpu": [
1432
+ "arm64"
1433
  ],
1434
+ "dev": true,
1435
+ "license": "MIT",
1436
+ "optional": true,
1437
+ "os": [
1438
+ "linux"
1439
+ ]
1440
  },
1441
+ "node_modules/@rollup/rollup-linux-loong64-gnu": {
1442
+ "version": "4.61.1",
1443
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.1.tgz",
1444
+ "integrity": "sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ==",
1445
+ "cpu": [
1446
+ "loong64"
1447
+ ],
1448
+ "dev": true,
1449
+ "license": "MIT",
1450
+ "optional": true,
1451
+ "os": [
1452
+ "linux"
1453
+ ]
1454
+ },
1455
+ "node_modules/@rollup/rollup-linux-loong64-musl": {
1456
+ "version": "4.61.1",
1457
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.1.tgz",
1458
+ "integrity": "sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ==",
1459
+ "cpu": [
1460
+ "loong64"
1461
+ ],
1462
+ "dev": true,
1463
+ "license": "MIT",
1464
+ "optional": true,
1465
+ "os": [
1466
+ "linux"
1467
+ ]
1468
+ },
1469
+ "node_modules/@rollup/rollup-linux-ppc64-gnu": {
1470
+ "version": "4.61.1",
1471
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.1.tgz",
1472
+ "integrity": "sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g==",
1473
+ "cpu": [
1474
+ "ppc64"
1475
+ ],
1476
+ "dev": true,
1477
+ "license": "MIT",
1478
+ "optional": true,
1479
+ "os": [
1480
+ "linux"
1481
+ ]
1482
+ },
1483
+ "node_modules/@rollup/rollup-linux-ppc64-musl": {
1484
+ "version": "4.61.1",
1485
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.1.tgz",
1486
+ "integrity": "sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw==",
1487
+ "cpu": [
1488
+ "ppc64"
1489
+ ],
1490
+ "dev": true,
1491
+ "license": "MIT",
1492
+ "optional": true,
1493
+ "os": [
1494
+ "linux"
1495
+ ]
1496
+ },
1497
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
1498
+ "version": "4.61.1",
1499
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.1.tgz",
1500
+ "integrity": "sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g==",
1501
  "cpu": [
1502
+ "riscv64"
1503
  ],
1504
  "dev": true,
1505
  "license": "MIT",
1506
  "optional": true,
1507
  "os": [
1508
  "linux"
1509
+ ]
 
 
 
1510
  },
1511
+ "node_modules/@rollup/rollup-linux-riscv64-musl": {
1512
+ "version": "4.61.1",
1513
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.1.tgz",
1514
+ "integrity": "sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ==",
1515
  "cpu": [
1516
+ "riscv64"
1517
  ],
1518
  "dev": true,
1519
  "license": "MIT",
1520
  "optional": true,
1521
  "os": [
1522
  "linux"
1523
+ ]
 
 
 
1524
  },
1525
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
1526
+ "version": "4.61.1",
1527
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.1.tgz",
1528
+ "integrity": "sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g==",
1529
  "cpu": [
1530
  "s390x"
1531
  ],
 
1534
  "optional": true,
1535
  "os": [
1536
  "linux"
1537
+ ]
 
 
 
1538
  },
1539
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
1540
+ "version": "4.61.1",
1541
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.1.tgz",
1542
+ "integrity": "sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q==",
1543
  "cpu": [
1544
  "x64"
1545
  ],
 
1548
  "optional": true,
1549
  "os": [
1550
  "linux"
1551
+ ]
 
 
 
1552
  },
1553
+ "node_modules/@rollup/rollup-linux-x64-musl": {
1554
+ "version": "4.61.1",
1555
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.1.tgz",
1556
+ "integrity": "sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw==",
1557
  "cpu": [
1558
  "x64"
1559
  ],
 
1562
  "optional": true,
1563
  "os": [
1564
  "linux"
1565
+ ]
1566
+ },
1567
+ "node_modules/@rollup/rollup-openbsd-x64": {
1568
+ "version": "4.61.1",
1569
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.1.tgz",
1570
+ "integrity": "sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg==",
1571
+ "cpu": [
1572
+ "x64"
1573
  ],
1574
+ "dev": true,
1575
+ "license": "MIT",
1576
+ "optional": true,
1577
+ "os": [
1578
+ "openbsd"
1579
+ ]
1580
  },
1581
+ "node_modules/@rollup/rollup-openharmony-arm64": {
1582
+ "version": "4.61.1",
1583
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.1.tgz",
1584
+ "integrity": "sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA==",
1585
  "cpu": [
1586
  "arm64"
1587
  ],
 
1590
  "optional": true,
1591
  "os": [
1592
  "openharmony"
1593
+ ]
 
 
 
1594
  },
1595
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
1596
+ "version": "4.61.1",
1597
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.1.tgz",
1598
+ "integrity": "sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g==",
1599
  "cpu": [
1600
+ "arm64"
1601
  ],
1602
  "dev": true,
1603
  "license": "MIT",
1604
  "optional": true,
1605
+ "os": [
1606
+ "win32"
1607
+ ]
 
 
 
 
 
1608
  },
1609
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
1610
+ "version": "4.61.1",
1611
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.1.tgz",
1612
+ "integrity": "sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ==",
1613
  "cpu": [
1614
+ "ia32"
1615
  ],
1616
  "dev": true,
1617
  "license": "MIT",
1618
  "optional": true,
1619
  "os": [
1620
  "win32"
1621
+ ]
 
 
 
1622
  },
1623
+ "node_modules/@rollup/rollup-win32-x64-gnu": {
1624
+ "version": "4.61.1",
1625
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.1.tgz",
1626
+ "integrity": "sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ==",
1627
  "cpu": [
1628
  "x64"
1629
  ],
 
1632
  "optional": true,
1633
  "os": [
1634
  "win32"
1635
+ ]
 
 
 
1636
  },
1637
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
1638
+ "version": "4.61.1",
1639
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz",
1640
+ "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==",
1641
+ "cpu": [
1642
+ "x64"
1643
+ ],
1644
  "dev": true,
1645
+ "license": "MIT",
1646
+ "optional": true,
1647
+ "os": [
1648
+ "win32"
1649
+ ]
1650
  },
1651
  "node_modules/@tybys/wasm-util": {
1652
  "version": "0.10.2",
 
1659
  "tslib": "^2.4.0"
1660
  }
1661
  },
1662
+ "node_modules/@types/chai": {
1663
+ "version": "5.2.3",
1664
+ "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz",
1665
+ "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==",
1666
+ "dev": true,
1667
+ "license": "MIT",
1668
+ "dependencies": {
1669
+ "@types/deep-eql": "*",
1670
+ "assertion-error": "^2.0.1"
1671
+ }
1672
+ },
1673
+ "node_modules/@types/deep-eql": {
1674
+ "version": "4.0.2",
1675
+ "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz",
1676
+ "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==",
1677
+ "dev": true,
1678
+ "license": "MIT"
1679
+ },
1680
  "node_modules/@types/esrecurse": {
1681
  "version": "4.3.1",
1682
  "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
 
1997
  }
1998
  }
1999
  },
2000
+ "node_modules/@vitest/expect": {
2001
+ "version": "3.2.6",
2002
+ "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz",
2003
+ "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==",
2004
+ "dev": true,
2005
+ "license": "MIT",
2006
+ "dependencies": {
2007
+ "@types/chai": "^5.2.2",
2008
+ "@vitest/spy": "3.2.6",
2009
+ "@vitest/utils": "3.2.6",
2010
+ "chai": "^5.2.0",
2011
+ "tinyrainbow": "^2.0.0"
2012
+ },
2013
+ "funding": {
2014
+ "url": "https://opencollective.com/vitest"
2015
+ }
2016
+ },
2017
+ "node_modules/@vitest/pretty-format": {
2018
+ "version": "3.2.6",
2019
+ "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz",
2020
+ "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==",
2021
+ "dev": true,
2022
+ "license": "MIT",
2023
+ "dependencies": {
2024
+ "tinyrainbow": "^2.0.0"
2025
+ },
2026
+ "funding": {
2027
+ "url": "https://opencollective.com/vitest"
2028
+ }
2029
+ },
2030
+ "node_modules/@vitest/runner": {
2031
+ "version": "3.2.6",
2032
+ "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz",
2033
+ "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==",
2034
+ "dev": true,
2035
+ "license": "MIT",
2036
+ "dependencies": {
2037
+ "@vitest/utils": "3.2.6",
2038
+ "pathe": "^2.0.3",
2039
+ "strip-literal": "^3.0.0"
2040
+ },
2041
+ "funding": {
2042
+ "url": "https://opencollective.com/vitest"
2043
+ }
2044
+ },
2045
+ "node_modules/@vitest/snapshot": {
2046
+ "version": "3.2.6",
2047
+ "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz",
2048
+ "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==",
2049
+ "dev": true,
2050
+ "license": "MIT",
2051
+ "dependencies": {
2052
+ "@vitest/pretty-format": "3.2.6",
2053
+ "magic-string": "^0.30.17",
2054
+ "pathe": "^2.0.3"
2055
+ },
2056
+ "funding": {
2057
+ "url": "https://opencollective.com/vitest"
2058
+ }
2059
+ },
2060
+ "node_modules/@vitest/spy": {
2061
+ "version": "3.2.6",
2062
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz",
2063
+ "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==",
2064
+ "dev": true,
2065
+ "license": "MIT",
2066
+ "dependencies": {
2067
+ "tinyspy": "^4.0.3"
2068
+ },
2069
+ "funding": {
2070
+ "url": "https://opencollective.com/vitest"
2071
+ }
2072
+ },
2073
+ "node_modules/@vitest/utils": {
2074
+ "version": "3.2.6",
2075
+ "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz",
2076
+ "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==",
2077
+ "dev": true,
2078
+ "license": "MIT",
2079
+ "dependencies": {
2080
+ "@vitest/pretty-format": "3.2.6",
2081
+ "loupe": "^3.1.4",
2082
+ "tinyrainbow": "^2.0.0"
2083
+ },
2084
+ "funding": {
2085
+ "url": "https://opencollective.com/vitest"
2086
+ }
2087
+ },
2088
  "node_modules/acorn": {
2089
  "version": "8.16.0",
2090
  "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
 
2125
  "url": "https://github.com/sponsors/epoberezkin"
2126
  }
2127
  },
2128
+ "node_modules/assertion-error": {
2129
+ "version": "2.0.1",
2130
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz",
2131
+ "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==",
2132
+ "dev": true,
2133
+ "license": "MIT",
2134
+ "engines": {
2135
+ "node": ">=12"
2136
+ }
2137
+ },
2138
  "node_modules/balanced-match": {
2139
  "version": "4.0.4",
2140
  "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz",
 
2205
  "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
2206
  }
2207
  },
2208
+ "node_modules/cac": {
2209
+ "version": "6.7.14",
2210
+ "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz",
2211
+ "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==",
2212
+ "dev": true,
2213
+ "license": "MIT",
2214
+ "engines": {
2215
+ "node": ">=8"
2216
+ }
2217
+ },
2218
  "node_modules/caniuse-lite": {
2219
  "version": "1.0.30001793",
2220
  "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001793.tgz",
 
2236
  ],
2237
  "license": "CC-BY-4.0"
2238
  },
2239
+ "node_modules/chai": {
2240
+ "version": "5.3.3",
2241
+ "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz",
2242
+ "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==",
2243
+ "dev": true,
2244
+ "license": "MIT",
2245
+ "dependencies": {
2246
+ "assertion-error": "^2.0.1",
2247
+ "check-error": "^2.1.1",
2248
+ "deep-eql": "^5.0.1",
2249
+ "loupe": "^3.1.0",
2250
+ "pathval": "^2.0.0"
2251
+ },
2252
+ "engines": {
2253
+ "node": ">=18"
2254
+ }
2255
+ },
2256
+ "node_modules/check-error": {
2257
+ "version": "2.1.3",
2258
+ "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz",
2259
+ "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==",
2260
+ "dev": true,
2261
+ "license": "MIT",
2262
+ "engines": {
2263
+ "node": ">= 16"
2264
+ }
2265
+ },
2266
  "node_modules/convert-source-map": {
2267
  "version": "2.0.0",
2268
  "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
 
2323
  }
2324
  }
2325
  },
2326
+ "node_modules/deep-eql": {
2327
+ "version": "5.0.2",
2328
+ "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz",
2329
+ "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==",
2330
+ "dev": true,
2331
+ "license": "MIT",
2332
+ "engines": {
2333
+ "node": ">=6"
2334
+ }
2335
+ },
2336
  "node_modules/deep-is": {
2337
  "version": "0.1.4",
2338
  "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
 
2357
  "dev": true,
2358
  "license": "ISC"
2359
  },
2360
+ "node_modules/es-module-lexer": {
2361
+ "version": "1.7.0",
2362
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz",
2363
+ "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==",
2364
+ "dev": true,
2365
+ "license": "MIT"
2366
+ },
2367
+ "node_modules/esbuild": {
2368
+ "version": "0.27.7",
2369
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz",
2370
+ "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==",
2371
+ "dev": true,
2372
+ "hasInstallScript": true,
2373
+ "license": "MIT",
2374
+ "bin": {
2375
+ "esbuild": "bin/esbuild"
2376
+ },
2377
+ "engines": {
2378
+ "node": ">=18"
2379
+ },
2380
+ "optionalDependencies": {
2381
+ "@esbuild/aix-ppc64": "0.27.7",
2382
+ "@esbuild/android-arm": "0.27.7",
2383
+ "@esbuild/android-arm64": "0.27.7",
2384
+ "@esbuild/android-x64": "0.27.7",
2385
+ "@esbuild/darwin-arm64": "0.27.7",
2386
+ "@esbuild/darwin-x64": "0.27.7",
2387
+ "@esbuild/freebsd-arm64": "0.27.7",
2388
+ "@esbuild/freebsd-x64": "0.27.7",
2389
+ "@esbuild/linux-arm": "0.27.7",
2390
+ "@esbuild/linux-arm64": "0.27.7",
2391
+ "@esbuild/linux-ia32": "0.27.7",
2392
+ "@esbuild/linux-loong64": "0.27.7",
2393
+ "@esbuild/linux-mips64el": "0.27.7",
2394
+ "@esbuild/linux-ppc64": "0.27.7",
2395
+ "@esbuild/linux-riscv64": "0.27.7",
2396
+ "@esbuild/linux-s390x": "0.27.7",
2397
+ "@esbuild/linux-x64": "0.27.7",
2398
+ "@esbuild/netbsd-arm64": "0.27.7",
2399
+ "@esbuild/netbsd-x64": "0.27.7",
2400
+ "@esbuild/openbsd-arm64": "0.27.7",
2401
+ "@esbuild/openbsd-x64": "0.27.7",
2402
+ "@esbuild/openharmony-arm64": "0.27.7",
2403
+ "@esbuild/sunos-x64": "0.27.7",
2404
+ "@esbuild/win32-arm64": "0.27.7",
2405
+ "@esbuild/win32-ia32": "0.27.7",
2406
+ "@esbuild/win32-x64": "0.27.7"
2407
+ }
2408
+ },
2409
  "node_modules/escalade": {
2410
  "version": "3.2.0",
2411
  "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
 
2601
  "node": ">=4.0"
2602
  }
2603
  },
2604
+ "node_modules/estree-walker": {
2605
+ "version": "3.0.3",
2606
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz",
2607
+ "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==",
2608
+ "dev": true,
2609
+ "license": "MIT",
2610
+ "dependencies": {
2611
+ "@types/estree": "^1.0.0"
2612
+ }
2613
+ },
2614
  "node_modules/esutils": {
2615
  "version": "2.0.3",
2616
  "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
 
2621
  "node": ">=0.10.0"
2622
  }
2623
  },
2624
+ "node_modules/expect-type": {
2625
+ "version": "1.3.0",
2626
+ "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz",
2627
+ "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==",
2628
+ "dev": true,
2629
+ "license": "Apache-2.0",
2630
+ "engines": {
2631
+ "node": ">=12.0.0"
2632
+ }
2633
+ },
2634
  "node_modules/fast-deep-equal": {
2635
  "version": "3.1.3",
2636
  "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
 
3194
  "url": "https://github.com/sponsors/sindresorhus"
3195
  }
3196
  },
3197
+ "node_modules/loupe": {
3198
+ "version": "3.2.1",
3199
+ "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz",
3200
+ "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==",
3201
+ "dev": true,
3202
+ "license": "MIT"
3203
+ },
3204
  "node_modules/lru-cache": {
3205
  "version": "5.1.1",
3206
  "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
 
3211
  "yallist": "^3.0.2"
3212
  }
3213
  },
3214
+ "node_modules/magic-string": {
3215
+ "version": "0.30.21",
3216
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
3217
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
3218
+ "dev": true,
3219
+ "license": "MIT",
3220
+ "dependencies": {
3221
+ "@jridgewell/sourcemap-codec": "^1.5.5"
3222
+ }
3223
+ },
3224
  "node_modules/minimatch": {
3225
  "version": "10.2.5",
3226
  "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz",
 
3347
  "node": ">=8"
3348
  }
3349
  },
3350
+ "node_modules/pathe": {
3351
+ "version": "2.0.3",
3352
+ "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz",
3353
+ "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==",
3354
+ "dev": true,
3355
+ "license": "MIT"
3356
+ },
3357
+ "node_modules/pathval": {
3358
+ "version": "2.0.1",
3359
+ "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz",
3360
+ "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==",
3361
+ "dev": true,
3362
+ "license": "MIT",
3363
+ "engines": {
3364
+ "node": ">= 14.16"
3365
+ }
3366
+ },
3367
  "node_modules/picocolors": {
3368
  "version": "1.1.1",
3369
  "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
 
3378
  "dev": true,
3379
  "license": "MIT",
3380
  "engines": {
3381
+ "node": ">=12"
3382
+ },
3383
+ "funding": {
3384
+ "url": "https://github.com/sponsors/jonschlinkert"
3385
+ }
3386
+ },
3387
+ "node_modules/playwright": {
3388
+ "version": "1.60.0",
3389
+ "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz",
3390
+ "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==",
3391
+ "dev": true,
3392
+ "license": "Apache-2.0",
3393
+ "dependencies": {
3394
+ "playwright-core": "1.60.0"
3395
+ },
3396
+ "bin": {
3397
+ "playwright": "cli.js"
3398
+ },
3399
+ "engines": {
3400
+ "node": ">=18"
3401
+ },
3402
+ "optionalDependencies": {
3403
+ "fsevents": "2.3.2"
3404
+ }
3405
+ },
3406
+ "node_modules/playwright-core": {
3407
+ "version": "1.60.0",
3408
+ "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz",
3409
+ "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==",
3410
+ "dev": true,
3411
+ "license": "Apache-2.0",
3412
+ "bin": {
3413
+ "playwright-core": "cli.js"
3414
+ },
3415
+ "engines": {
3416
+ "node": ">=18"
3417
+ }
3418
+ },
3419
+ "node_modules/playwright/node_modules/fsevents": {
3420
+ "version": "2.3.2",
3421
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
3422
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
3423
+ "dev": true,
3424
+ "hasInstallScript": true,
3425
+ "license": "MIT",
3426
+ "optional": true,
3427
+ "os": [
3428
+ "darwin"
3429
+ ],
3430
+ "engines": {
3431
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
3432
  }
3433
  },
3434
  "node_modules/postcss": {
 
3573
  "@rolldown/binding-win32-x64-msvc": "1.0.1"
3574
  }
3575
  },
3576
+ "node_modules/rollup": {
3577
+ "version": "4.61.1",
3578
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.1.tgz",
3579
+ "integrity": "sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==",
3580
+ "dev": true,
3581
+ "license": "MIT",
3582
+ "dependencies": {
3583
+ "@types/estree": "1.0.9"
3584
+ },
3585
+ "bin": {
3586
+ "rollup": "dist/bin/rollup"
3587
+ },
3588
+ "engines": {
3589
+ "node": ">=18.0.0",
3590
+ "npm": ">=8.0.0"
3591
+ },
3592
+ "optionalDependencies": {
3593
+ "@rollup/rollup-android-arm-eabi": "4.61.1",
3594
+ "@rollup/rollup-android-arm64": "4.61.1",
3595
+ "@rollup/rollup-darwin-arm64": "4.61.1",
3596
+ "@rollup/rollup-darwin-x64": "4.61.1",
3597
+ "@rollup/rollup-freebsd-arm64": "4.61.1",
3598
+ "@rollup/rollup-freebsd-x64": "4.61.1",
3599
+ "@rollup/rollup-linux-arm-gnueabihf": "4.61.1",
3600
+ "@rollup/rollup-linux-arm-musleabihf": "4.61.1",
3601
+ "@rollup/rollup-linux-arm64-gnu": "4.61.1",
3602
+ "@rollup/rollup-linux-arm64-musl": "4.61.1",
3603
+ "@rollup/rollup-linux-loong64-gnu": "4.61.1",
3604
+ "@rollup/rollup-linux-loong64-musl": "4.61.1",
3605
+ "@rollup/rollup-linux-ppc64-gnu": "4.61.1",
3606
+ "@rollup/rollup-linux-ppc64-musl": "4.61.1",
3607
+ "@rollup/rollup-linux-riscv64-gnu": "4.61.1",
3608
+ "@rollup/rollup-linux-riscv64-musl": "4.61.1",
3609
+ "@rollup/rollup-linux-s390x-gnu": "4.61.1",
3610
+ "@rollup/rollup-linux-x64-gnu": "4.61.1",
3611
+ "@rollup/rollup-linux-x64-musl": "4.61.1",
3612
+ "@rollup/rollup-openbsd-x64": "4.61.1",
3613
+ "@rollup/rollup-openharmony-arm64": "4.61.1",
3614
+ "@rollup/rollup-win32-arm64-msvc": "4.61.1",
3615
+ "@rollup/rollup-win32-ia32-msvc": "4.61.1",
3616
+ "@rollup/rollup-win32-x64-gnu": "4.61.1",
3617
+ "@rollup/rollup-win32-x64-msvc": "4.61.1",
3618
+ "fsevents": "~2.3.2"
3619
+ }
3620
+ },
3621
  "node_modules/scheduler": {
3622
  "version": "0.27.0",
3623
  "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
 
3663
  "node": ">=8"
3664
  }
3665
  },
3666
+ "node_modules/siginfo": {
3667
+ "version": "2.0.0",
3668
+ "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz",
3669
+ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==",
3670
+ "dev": true,
3671
+ "license": "ISC"
3672
+ },
3673
  "node_modules/source-map-js": {
3674
  "version": "1.2.1",
3675
  "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
 
3680
  "node": ">=0.10.0"
3681
  }
3682
  },
3683
+ "node_modules/stackback": {
3684
+ "version": "0.0.2",
3685
+ "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz",
3686
+ "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==",
3687
+ "dev": true,
3688
+ "license": "MIT"
3689
+ },
3690
+ "node_modules/std-env": {
3691
+ "version": "3.10.0",
3692
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz",
3693
+ "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==",
3694
+ "dev": true,
3695
+ "license": "MIT"
3696
+ },
3697
+ "node_modules/strip-literal": {
3698
+ "version": "3.1.0",
3699
+ "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz",
3700
+ "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==",
3701
+ "dev": true,
3702
+ "license": "MIT",
3703
+ "dependencies": {
3704
+ "js-tokens": "^9.0.1"
3705
+ },
3706
+ "funding": {
3707
+ "url": "https://github.com/sponsors/antfu"
3708
+ }
3709
+ },
3710
+ "node_modules/strip-literal/node_modules/js-tokens": {
3711
+ "version": "9.0.1",
3712
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz",
3713
+ "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==",
3714
+ "dev": true,
3715
+ "license": "MIT"
3716
+ },
3717
+ "node_modules/tinybench": {
3718
+ "version": "2.9.0",
3719
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
3720
+ "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==",
3721
+ "dev": true,
3722
+ "license": "MIT"
3723
+ },
3724
+ "node_modules/tinyexec": {
3725
+ "version": "0.3.2",
3726
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
3727
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
3728
+ "dev": true,
3729
+ "license": "MIT"
3730
+ },
3731
  "node_modules/tinyglobby": {
3732
  "version": "0.2.16",
3733
  "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
 
3745
  "url": "https://github.com/sponsors/SuperchupuDev"
3746
  }
3747
  },
3748
+ "node_modules/tinypool": {
3749
+ "version": "1.1.1",
3750
+ "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz",
3751
+ "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==",
3752
+ "dev": true,
3753
+ "license": "MIT",
3754
+ "engines": {
3755
+ "node": "^18.0.0 || >=20.0.0"
3756
+ }
3757
+ },
3758
+ "node_modules/tinyrainbow": {
3759
+ "version": "2.0.0",
3760
+ "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz",
3761
+ "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==",
3762
+ "dev": true,
3763
+ "license": "MIT",
3764
+ "engines": {
3765
+ "node": ">=14.0.0"
3766
+ }
3767
+ },
3768
+ "node_modules/tinyspy": {
3769
+ "version": "4.0.4",
3770
+ "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz",
3771
+ "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==",
3772
+ "dev": true,
3773
+ "license": "MIT",
3774
+ "engines": {
3775
+ "node": ">=14.0.0"
3776
+ }
3777
+ },
3778
  "node_modules/ts-api-utils": {
3779
  "version": "2.5.0",
3780
  "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz",
 
3973
  }
3974
  }
3975
  },
3976
+ "node_modules/vite-node": {
3977
+ "version": "3.2.4",
3978
+ "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz",
3979
+ "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==",
3980
+ "dev": true,
3981
+ "license": "MIT",
3982
+ "dependencies": {
3983
+ "cac": "^6.7.14",
3984
+ "debug": "^4.4.1",
3985
+ "es-module-lexer": "^1.7.0",
3986
+ "pathe": "^2.0.3",
3987
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
3988
+ },
3989
+ "bin": {
3990
+ "vite-node": "vite-node.mjs"
3991
+ },
3992
+ "engines": {
3993
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
3994
+ },
3995
+ "funding": {
3996
+ "url": "https://opencollective.com/vitest"
3997
+ }
3998
+ },
3999
+ "node_modules/vite-node/node_modules/vite": {
4000
+ "version": "7.3.5",
4001
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz",
4002
+ "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==",
4003
+ "dev": true,
4004
+ "license": "MIT",
4005
+ "dependencies": {
4006
+ "esbuild": "^0.27.0",
4007
+ "fdir": "^6.5.0",
4008
+ "picomatch": "^4.0.3",
4009
+ "postcss": "^8.5.6",
4010
+ "rollup": "^4.43.0",
4011
+ "tinyglobby": "^0.2.15"
4012
+ },
4013
+ "bin": {
4014
+ "vite": "bin/vite.js"
4015
+ },
4016
+ "engines": {
4017
+ "node": "^20.19.0 || >=22.12.0"
4018
+ },
4019
+ "funding": {
4020
+ "url": "https://github.com/vitejs/vite?sponsor=1"
4021
+ },
4022
+ "optionalDependencies": {
4023
+ "fsevents": "~2.3.3"
4024
+ },
4025
+ "peerDependencies": {
4026
+ "@types/node": "^20.19.0 || >=22.12.0",
4027
+ "jiti": ">=1.21.0",
4028
+ "less": "^4.0.0",
4029
+ "lightningcss": "^1.21.0",
4030
+ "sass": "^1.70.0",
4031
+ "sass-embedded": "^1.70.0",
4032
+ "stylus": ">=0.54.8",
4033
+ "sugarss": "^5.0.0",
4034
+ "terser": "^5.16.0",
4035
+ "tsx": "^4.8.1",
4036
+ "yaml": "^2.4.2"
4037
+ },
4038
+ "peerDependenciesMeta": {
4039
+ "@types/node": {
4040
+ "optional": true
4041
+ },
4042
+ "jiti": {
4043
+ "optional": true
4044
+ },
4045
+ "less": {
4046
+ "optional": true
4047
+ },
4048
+ "lightningcss": {
4049
+ "optional": true
4050
+ },
4051
+ "sass": {
4052
+ "optional": true
4053
+ },
4054
+ "sass-embedded": {
4055
+ "optional": true
4056
+ },
4057
+ "stylus": {
4058
+ "optional": true
4059
+ },
4060
+ "sugarss": {
4061
+ "optional": true
4062
+ },
4063
+ "terser": {
4064
+ "optional": true
4065
+ },
4066
+ "tsx": {
4067
+ "optional": true
4068
+ },
4069
+ "yaml": {
4070
+ "optional": true
4071
+ }
4072
+ }
4073
+ },
4074
+ "node_modules/vitest": {
4075
+ "version": "3.2.6",
4076
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz",
4077
+ "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==",
4078
+ "dev": true,
4079
+ "license": "MIT",
4080
+ "dependencies": {
4081
+ "@types/chai": "^5.2.2",
4082
+ "@vitest/expect": "3.2.6",
4083
+ "@vitest/mocker": "3.2.6",
4084
+ "@vitest/pretty-format": "^3.2.6",
4085
+ "@vitest/runner": "3.2.6",
4086
+ "@vitest/snapshot": "3.2.6",
4087
+ "@vitest/spy": "3.2.6",
4088
+ "@vitest/utils": "3.2.6",
4089
+ "chai": "^5.2.0",
4090
+ "debug": "^4.4.1",
4091
+ "expect-type": "^1.2.1",
4092
+ "magic-string": "^0.30.17",
4093
+ "pathe": "^2.0.3",
4094
+ "picomatch": "^4.0.2",
4095
+ "std-env": "^3.9.0",
4096
+ "tinybench": "^2.9.0",
4097
+ "tinyexec": "^0.3.2",
4098
+ "tinyglobby": "^0.2.14",
4099
+ "tinypool": "^1.1.1",
4100
+ "tinyrainbow": "^2.0.0",
4101
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0",
4102
+ "vite-node": "3.2.4",
4103
+ "why-is-node-running": "^2.3.0"
4104
+ },
4105
+ "bin": {
4106
+ "vitest": "vitest.mjs"
4107
+ },
4108
+ "engines": {
4109
+ "node": "^18.0.0 || ^20.0.0 || >=22.0.0"
4110
+ },
4111
+ "funding": {
4112
+ "url": "https://opencollective.com/vitest"
4113
+ },
4114
+ "peerDependencies": {
4115
+ "@edge-runtime/vm": "*",
4116
+ "@types/debug": "^4.1.12",
4117
+ "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0",
4118
+ "@vitest/browser": "3.2.6",
4119
+ "@vitest/ui": "3.2.6",
4120
+ "happy-dom": "*",
4121
+ "jsdom": "*"
4122
+ },
4123
+ "peerDependenciesMeta": {
4124
+ "@edge-runtime/vm": {
4125
+ "optional": true
4126
+ },
4127
+ "@types/debug": {
4128
+ "optional": true
4129
+ },
4130
+ "@types/node": {
4131
+ "optional": true
4132
+ },
4133
+ "@vitest/browser": {
4134
+ "optional": true
4135
+ },
4136
+ "@vitest/ui": {
4137
+ "optional": true
4138
+ },
4139
+ "happy-dom": {
4140
+ "optional": true
4141
+ },
4142
+ "jsdom": {
4143
+ "optional": true
4144
+ }
4145
+ }
4146
+ },
4147
+ "node_modules/vitest/node_modules/@vitest/mocker": {
4148
+ "version": "3.2.6",
4149
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz",
4150
+ "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==",
4151
+ "dev": true,
4152
+ "license": "MIT",
4153
+ "dependencies": {
4154
+ "@vitest/spy": "3.2.6",
4155
+ "estree-walker": "^3.0.3",
4156
+ "magic-string": "^0.30.17"
4157
+ },
4158
+ "funding": {
4159
+ "url": "https://opencollective.com/vitest"
4160
+ },
4161
+ "peerDependencies": {
4162
+ "msw": "^2.4.9",
4163
+ "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0"
4164
+ },
4165
+ "peerDependenciesMeta": {
4166
+ "msw": {
4167
+ "optional": true
4168
+ },
4169
+ "vite": {
4170
+ "optional": true
4171
+ }
4172
+ }
4173
+ },
4174
+ "node_modules/vitest/node_modules/vite": {
4175
+ "version": "7.3.5",
4176
+ "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz",
4177
+ "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==",
4178
+ "dev": true,
4179
+ "license": "MIT",
4180
+ "dependencies": {
4181
+ "esbuild": "^0.27.0",
4182
+ "fdir": "^6.5.0",
4183
+ "picomatch": "^4.0.3",
4184
+ "postcss": "^8.5.6",
4185
+ "rollup": "^4.43.0",
4186
+ "tinyglobby": "^0.2.15"
4187
+ },
4188
+ "bin": {
4189
+ "vite": "bin/vite.js"
4190
+ },
4191
+ "engines": {
4192
+ "node": "^20.19.0 || >=22.12.0"
4193
+ },
4194
+ "funding": {
4195
+ "url": "https://github.com/vitejs/vite?sponsor=1"
4196
+ },
4197
+ "optionalDependencies": {
4198
+ "fsevents": "~2.3.3"
4199
+ },
4200
+ "peerDependencies": {
4201
+ "@types/node": "^20.19.0 || >=22.12.0",
4202
+ "jiti": ">=1.21.0",
4203
+ "less": "^4.0.0",
4204
+ "lightningcss": "^1.21.0",
4205
+ "sass": "^1.70.0",
4206
+ "sass-embedded": "^1.70.0",
4207
+ "stylus": ">=0.54.8",
4208
+ "sugarss": "^5.0.0",
4209
+ "terser": "^5.16.0",
4210
+ "tsx": "^4.8.1",
4211
+ "yaml": "^2.4.2"
4212
+ },
4213
+ "peerDependenciesMeta": {
4214
+ "@types/node": {
4215
+ "optional": true
4216
+ },
4217
+ "jiti": {
4218
+ "optional": true
4219
+ },
4220
+ "less": {
4221
+ "optional": true
4222
+ },
4223
+ "lightningcss": {
4224
+ "optional": true
4225
+ },
4226
+ "sass": {
4227
+ "optional": true
4228
+ },
4229
+ "sass-embedded": {
4230
+ "optional": true
4231
+ },
4232
+ "stylus": {
4233
+ "optional": true
4234
+ },
4235
+ "sugarss": {
4236
+ "optional": true
4237
+ },
4238
+ "terser": {
4239
+ "optional": true
4240
+ },
4241
+ "tsx": {
4242
+ "optional": true
4243
+ },
4244
+ "yaml": {
4245
+ "optional": true
4246
+ }
4247
+ }
4248
+ },
4249
  "node_modules/which": {
4250
  "version": "2.0.2",
4251
  "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
 
4262
  "node": ">= 8"
4263
  }
4264
  },
4265
+ "node_modules/why-is-node-running": {
4266
+ "version": "2.3.0",
4267
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz",
4268
+ "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==",
4269
+ "dev": true,
4270
+ "license": "MIT",
4271
+ "dependencies": {
4272
+ "siginfo": "^2.0.0",
4273
+ "stackback": "0.0.2"
4274
+ },
4275
+ "bin": {
4276
+ "why-is-node-running": "cli.js"
4277
+ },
4278
+ "engines": {
4279
+ "node": ">=8"
4280
+ }
4281
+ },
4282
  "node_modules/word-wrap": {
4283
  "version": "1.2.5",
4284
  "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
frontend/package.json CHANGED
@@ -7,7 +7,10 @@
7
  "dev": "vite",
8
  "build": "tsc -b && vite build",
9
  "lint": "eslint .",
10
- "preview": "vite preview"
 
 
 
11
  },
12
  "dependencies": {
13
  "react": "^19.2.6",
@@ -16,6 +19,7 @@
16
  },
17
  "devDependencies": {
18
  "@eslint/js": "^10.0.1",
 
19
  "@types/node": "^24.12.3",
20
  "@types/react": "^19.2.14",
21
  "@types/react-dom": "^19.2.3",
@@ -26,6 +30,7 @@
26
  "globals": "^17.6.0",
27
  "typescript": "~6.0.2",
28
  "typescript-eslint": "^8.59.2",
29
- "vite": "^8.0.12"
 
30
  }
31
  }
 
7
  "dev": "vite",
8
  "build": "tsc -b && vite build",
9
  "lint": "eslint .",
10
+ "preview": "vite preview",
11
+ "test": "vitest run",
12
+ "test:pipeline": "bash test/pipeline/run.sh",
13
+ "test:e2e": "npm run build && playwright test"
14
  },
15
  "dependencies": {
16
  "react": "^19.2.6",
 
19
  },
20
  "devDependencies": {
21
  "@eslint/js": "^10.0.1",
22
+ "@playwright/test": "^1.60.0",
23
  "@types/node": "^24.12.3",
24
  "@types/react": "^19.2.14",
25
  "@types/react-dom": "^19.2.3",
 
30
  "globals": "^17.6.0",
31
  "typescript": "~6.0.2",
32
  "typescript-eslint": "^8.59.2",
33
+ "vite": "^8.0.12",
34
+ "vitest": "^3.2.6"
35
  }
36
  }
frontend/playwright.config.ts ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { defineConfig } from "@playwright/test";
2
+
3
+ // E2E smoke test drives the REAL stack: one uvicorn process serves both the API
4
+ // and the built frontend (same-origin /api). The frontend must be built first
5
+ // (`npm run build`) so space_app can serve frontend/dist.
6
+ const PORT = 7860;
7
+
8
+ export default defineConfig({
9
+ testDir: "./e2e",
10
+ timeout: 60_000,
11
+ fullyParallel: false,
12
+ reporter: [["list"]],
13
+ use: {
14
+ baseURL: `http://127.0.0.1:${PORT}`,
15
+ headless: true,
16
+ },
17
+ webServer: {
18
+ command: `bash -c "cd .. && uvicorn space_app.main:app --host 127.0.0.1 --port ${PORT}"`,
19
+ url: `http://127.0.0.1:${PORT}/api/puzzles?puzzle_type=bridges&difficulty=medium`,
20
+ timeout: 180_000,
21
+ reuseExistingServer: true,
22
+ env: {
23
+ // Keep the e2e run off the real /data dir; reuse the existing HF dataset cache.
24
+ TOPOBENCH_DATA_DIR: "/tmp/topobench_e2e",
25
+ HF_HOME: `${process.env.HOME}/.cache/huggingface`,
26
+ SDL_AUDIODRIVER: "dummy",
27
+ SDL_VIDEODRIVER: "dummy",
28
+ PYTHONWARNINGS: "ignore",
29
+ },
30
+ },
31
+ });
frontend/src/components/PuzzleEditor.tsx CHANGED
@@ -150,18 +150,16 @@ function bridgesBoardFromStates(
150
  const grid = cloneGrid(parsed.lines);
151
  for (const opportunity of parsed.opportunities) {
152
  const level = states[opportunity.id] ?? 0;
 
 
 
 
 
 
 
 
153
  const symbol =
154
- opportunity.kind === "horizontal"
155
- ? level === 2
156
- ? "="
157
- : level === 1
158
- ? "-"
159
- : "."
160
- : level === 2
161
- ? '"'
162
- : level === 1
163
- ? "|"
164
- : ".";
165
  for (const [r, c] of opportunity.cells) {
166
  grid[r][c] = symbol;
167
  }
@@ -945,3 +943,26 @@ export function PuzzleEditor(props: Props) {
945
  }
946
  return null;
947
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
150
  const grid = cloneGrid(parsed.lines);
151
  for (const opportunity of parsed.opportunities) {
152
  const level = states[opportunity.id] ?? 0;
153
+ // The grid starts as a fresh copy of the problem (non-clue cells are "."),
154
+ // so a level-0 opportunity has nothing to add. Skip it: writing "." here
155
+ // would clobber the crossing cell of an *active* perpendicular bridge that
156
+ // shares this cell (e.g. a vertical bridge passing through a cell also owned
157
+ // by an unused horizontal opportunity), leaving a gap in the drawn bridge.
158
+ if (level === 0) {
159
+ continue;
160
+ }
161
  const symbol =
162
+ opportunity.kind === "horizontal" ? (level === 2 ? "=" : "-") : level === 2 ? '"' : "|";
 
 
 
 
 
 
 
 
 
 
163
  for (const [r, c] of opportunity.cells) {
164
  grid[r][c] = symbol;
165
  }
 
943
  }
944
  return null;
945
  }
946
+
947
+ // Test-only barrel: exposes the pure encode/decode helpers so the round-trip
948
+ // pipeline tests can exercise the *real* editor functions (not reimplementations).
949
+ // These mirror exactly what each <Family>Editor's onChange emits.
950
+ export const __testables = {
951
+ splitLines,
952
+ cloneGrid,
953
+ joinGrid,
954
+ parseBridges,
955
+ bridgesBoardFromStates,
956
+ bridgesStatesFromBoard,
957
+ parseLoopy,
958
+ loopyEdgeStates,
959
+ loopyBoardFromStates,
960
+ parseGalaxies,
961
+ galaxiesBoundaryStates,
962
+ galaxiesBoardFromStates,
963
+ parsePattern,
964
+ patternToAscii,
965
+ normalizePatternAscii,
966
+ parseUndead,
967
+ undeadToAscii,
968
+ };
frontend/test/pipeline/bridges_clickplan.json ADDED
@@ -0,0 +1,316 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "bridges_5x5de_6b8d9460.txt": [
3
+ 2,
4
+ 9,
5
+ 6,
6
+ 10,
7
+ 13,
8
+ 13,
9
+ 21,
10
+ 21
11
+ ],
12
+ "bridges_5x5de_3ab345b4.txt": [
13
+ 2,
14
+ 2,
15
+ 6,
16
+ 6,
17
+ 9,
18
+ 17,
19
+ 17,
20
+ 21,
21
+ 23,
22
+ 23
23
+ ],
24
+ "bridges_5x5de_750be39d.txt": [
25
+ 1,
26
+ 1,
27
+ 5,
28
+ 3,
29
+ 3,
30
+ 7,
31
+ 7,
32
+ 13,
33
+ 21
34
+ ],
35
+ "bridges_5x5de_d6a8fd57.txt": [
36
+ 1,
37
+ 5,
38
+ 8,
39
+ 14,
40
+ 14,
41
+ 12,
42
+ 21,
43
+ 21
44
+ ],
45
+ "bridges_5x5de_62b29e16.txt": [
46
+ 1,
47
+ 7,
48
+ 14,
49
+ 15,
50
+ 21,
51
+ 21,
52
+ 23
53
+ ],
54
+ "bridges_7x7dm_159f418e.txt": [
55
+ 3,
56
+ 3,
57
+ 5,
58
+ 13,
59
+ 8,
60
+ 8,
61
+ 14,
62
+ 16,
63
+ 22,
64
+ 22,
65
+ 19,
66
+ 27,
67
+ 27,
68
+ 30,
69
+ 41,
70
+ 41,
71
+ 43,
72
+ 43
73
+ ],
74
+ "bridges_7x7dm_98d15fca.txt": [
75
+ 1,
76
+ 7,
77
+ 7,
78
+ 5,
79
+ 11,
80
+ 13,
81
+ 13,
82
+ 29,
83
+ 33,
84
+ 33,
85
+ 39,
86
+ 39,
87
+ 44,
88
+ 44,
89
+ 47,
90
+ 47
91
+ ],
92
+ "bridges_7x7dm_c4439c2d.txt": [
93
+ 1,
94
+ 1,
95
+ 7,
96
+ 13,
97
+ 15,
98
+ 21,
99
+ 21,
100
+ 18,
101
+ 18,
102
+ 31,
103
+ 27,
104
+ 29,
105
+ 29,
106
+ 32,
107
+ 32,
108
+ 44,
109
+ 44,
110
+ 47,
111
+ 47
112
+ ],
113
+ "bridges_7x7dm_5d7e81df.txt": [
114
+ 2,
115
+ 2,
116
+ 13,
117
+ 14,
118
+ 16,
119
+ 18,
120
+ 24,
121
+ 24,
122
+ 27,
123
+ 29,
124
+ 32,
125
+ 43
126
+ ],
127
+ "bridges_7x7dm_24cecc91.txt": [
128
+ 1,
129
+ 7,
130
+ 7,
131
+ 5,
132
+ 11,
133
+ 13,
134
+ 9,
135
+ 22,
136
+ 22,
137
+ 17,
138
+ 21,
139
+ 37,
140
+ 37,
141
+ 40,
142
+ 43
143
+ ],
144
+ "bridges_10x10dh_e91c08d0.txt": [
145
+ 1,
146
+ 1,
147
+ 5,
148
+ 14,
149
+ 14,
150
+ 8,
151
+ 27,
152
+ 19,
153
+ 19,
154
+ 26,
155
+ 28,
156
+ 31,
157
+ 40,
158
+ 35,
159
+ 44,
160
+ 46,
161
+ 61,
162
+ 65,
163
+ 65,
164
+ 78,
165
+ 89,
166
+ 81,
167
+ 86,
168
+ 93
169
+ ],
170
+ "bridges_10x10dh_dbb54860.txt": [
171
+ 1,
172
+ 1,
173
+ 10,
174
+ 4,
175
+ 4,
176
+ 13,
177
+ 13,
178
+ 7,
179
+ 16,
180
+ 18,
181
+ 29,
182
+ 29,
183
+ 22,
184
+ 31,
185
+ 24,
186
+ 33,
187
+ 35,
188
+ 35,
189
+ 44,
190
+ 44,
191
+ 49,
192
+ 49,
193
+ 55,
194
+ 55,
195
+ 62,
196
+ 71,
197
+ 71,
198
+ 64,
199
+ 73,
200
+ 73,
201
+ 79,
202
+ 79,
203
+ 91,
204
+ 94,
205
+ 94
206
+ ],
207
+ "bridges_10x10dh_9a2eb1a6.txt": [
208
+ 2,
209
+ 4,
210
+ 13,
211
+ 13,
212
+ 6,
213
+ 6,
214
+ 15,
215
+ 18,
216
+ 18,
217
+ 21,
218
+ 30,
219
+ 30,
220
+ 32,
221
+ 41,
222
+ 41,
223
+ 45,
224
+ 45,
225
+ 48,
226
+ 53,
227
+ 53,
228
+ 62,
229
+ 62,
230
+ 64,
231
+ 73,
232
+ 66,
233
+ 75,
234
+ 79,
235
+ 71,
236
+ 71,
237
+ 80,
238
+ 80,
239
+ 84,
240
+ 86,
241
+ 82,
242
+ 91,
243
+ 91,
244
+ 95,
245
+ 97
246
+ ],
247
+ "bridges_10x10dh_1e764d30.txt": [
248
+ 2,
249
+ 2,
250
+ 19,
251
+ 11,
252
+ 11,
253
+ 20,
254
+ 13,
255
+ 13,
256
+ 22,
257
+ 43,
258
+ 43,
259
+ 52,
260
+ 52,
261
+ 59,
262
+ 63,
263
+ 63,
264
+ 67,
265
+ 76,
266
+ 71,
267
+ 80,
268
+ 80,
269
+ 82,
270
+ 84,
271
+ 87,
272
+ 91,
273
+ 91,
274
+ 95,
275
+ 95
276
+ ],
277
+ "bridges_10x10dh_714c4838.txt": [
278
+ 1,
279
+ 10,
280
+ 3,
281
+ 19,
282
+ 19,
283
+ 21,
284
+ 30,
285
+ 30,
286
+ 23,
287
+ 23,
288
+ 28,
289
+ 28,
290
+ 37,
291
+ 39,
292
+ 32,
293
+ 32,
294
+ 41,
295
+ 34,
296
+ 43,
297
+ 43,
298
+ 58,
299
+ 54,
300
+ 54,
301
+ 63,
302
+ 63,
303
+ 65,
304
+ 65,
305
+ 67,
306
+ 67,
307
+ 76,
308
+ 76,
309
+ 84,
310
+ 84,
311
+ 88,
312
+ 91,
313
+ 95,
314
+ 97
315
+ ]
316
+ }
frontend/test/pipeline/fixtures.json ADDED
@@ -0,0 +1,722 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [
2
+ {
3
+ "family": "bridges",
4
+ "difficulty": "easy",
5
+ "filename": "bridges_5x5de_6b8d9460.txt",
6
+ "args": "5x5de",
7
+ "problem": ".1..2\n2..3.\n.....\n...2.\n3...3",
8
+ "solution": ".1--2\n2--3|\n|..\"|\n|..2|\n3===3"
9
+ },
10
+ {
11
+ "family": "bridges",
12
+ "difficulty": "easy",
13
+ "filename": "bridges_5x5de_3ab345b4.txt",
14
+ "args": "5x5de",
15
+ "problem": ".4..3\n.....\n.....\n.4.2.\n1.3.3",
16
+ "solution": ".4==3\n.\"..|\n.\"..|\n.4=2|\n1-3=3"
17
+ },
18
+ {
19
+ "family": "bridges",
20
+ "difficulty": "easy",
21
+ "filename": "bridges_5x5de_750be39d.txt",
22
+ "args": "5x5de",
23
+ "problem": "3.4.2\n.2.3.\n.....\n.....\n2..2.",
24
+ "solution": "3=4=2\n|2=3.\n|..|.\n|..|.\n2--2."
25
+ },
26
+ {
27
+ "family": "bridges",
28
+ "difficulty": "easy",
29
+ "filename": "bridges_5x5de_d6a8fd57.txt",
30
+ "args": "5x5de",
31
+ "problem": "2..2.\n....2\n.1.2.\n.....\n3...4",
32
+ "solution": "2--2.\n|..|2\n|1-2\"\n|...\"\n3===4"
33
+ },
34
+ {
35
+ "family": "bridges",
36
+ "difficulty": "easy",
37
+ "filename": "bridges_5x5de_62b29e16.txt",
38
+ "args": "5x5de",
39
+ "problem": "1.2..\n....1\n1....\n.....\n3.4.2",
40
+ "solution": "1-2..\n..|.1\n1.|.|\n|.|.|\n3=4-2"
41
+ },
42
+ {
43
+ "family": "bridges",
44
+ "difficulty": "medium",
45
+ "filename": "bridges_7x7dm_159f418e.txt",
46
+ "args": "7x7dm",
47
+ "problem": "..2.3.2\n3....2.\n.3..2.4\n.......\n.3....5\n.......\n3.....4",
48
+ "solution": "..2=3-2\n3====2|\n|3--2-4\n|\"....\"\n|3----5\n|.....\"\n3=====4"
49
+ },
50
+ {
51
+ "family": "bridges",
52
+ "difficulty": "medium",
53
+ "filename": "bridges_7x7dm_98d15fca.txt",
54
+ "args": "7x7dm",
55
+ "problem": "3...3.3\n.......\n2.....2\n.......\n1...6.2\n.......\n.2..6.2",
56
+ "solution": "3---3-3\n\"...|.\"\n2...|.2\n....|..\n1---6=2\n....\"..\n.2==6=2"
57
+ },
58
+ {
59
+ "family": "bridges",
60
+ "difficulty": "medium",
61
+ "filename": "bridges_7x7dm_c4439c2d.txt",
62
+ "args": "7x7dm",
63
+ "problem": "3.....3\n.......\n4..4..4\n.2..2..\n2......\n...1...\n.4..6.3",
64
+ "solution": "3=====3\n|.....|\n4--4==4\n\"2.|2.|\n2\".|\".|\n.\".1\".|\n.4==6=3"
65
+ },
66
+ {
67
+ "family": "bridges",
68
+ "difficulty": "medium",
69
+ "filename": "bridges_7x7dm_5d7e81df.txt",
70
+ "args": "7x7dm",
71
+ "problem": ".2....3\n1......\n.1.4..3\n.......\n2..4.1.\n.......\n1.....2",
72
+ "solution": ".2====3\n1.....|\n|1-4--3\n|..\"..|\n2--4-1|\n......|\n1-----2"
73
+ },
74
+ {
75
+ "family": "bridges",
76
+ "difficulty": "medium",
77
+ "filename": "bridges_7x7dm_24cecc91.txt",
78
+ "args": "7x7dm",
79
+ "problem": "3...3.2\n.3.2...\n3.....1\n...1...\n.......\n.4..4.1\n2....1.",
80
+ "solution": "3---3-2\n\"3-2|.|\n3\".||.1\n|\".1|..\n|\"..|..\n|4==4-1\n2----1."
81
+ },
82
+ {
83
+ "family": "bridges",
84
+ "difficulty": "hard",
85
+ "filename": "bridges_10x10dh_e91c08d0.txt",
86
+ "args": "10x10dh",
87
+ "problem": "2...5..3.3\n......1.1.\n..........\n2...5.3...\n.......1..\n......1...\n2.1.3...4.\n.........3\n1....2..2.\n..1......2",
88
+ "solution": "2===5--3-3\n....\".1|1\"\n....\".|||\"\n2---5-3||\"\n|...|.|1|\"\n|...|.1.|\"\n2-1.3===4\"\n........|3\n1----2--2|\n..1------2"
89
+ },
90
+ {
91
+ "family": "bridges",
92
+ "difficulty": "hard",
93
+ "filename": "bridges_10x10dh_dbb54860.txt",
94
+ "args": "10x10dh",
95
+ "problem": "3..6..4.2.\n.........2\n.2.5.3....\n....2....4\n.1...2..1.\n....4.3...\n.3.5.....5\n..........\n.2........\n2..5.....4",
96
+ "solution": "3==6==4-2.\n|..\"..|.|2\n|2-5-3|.|\"\n||.|2\"|.|4\n|1.|\"2|.1\"\n|..|4=3..\"\n|3-5-----5\n|\".\".....\"\n|2.\".....\"\n2--5=====4"
97
+ },
98
+ {
99
+ "family": "bridges",
100
+ "difficulty": "hard",
101
+ "filename": "bridges_10x10dh_9a2eb1a6.txt",
102
+ "args": "10x10dh",
103
+ "problem": ".1.4.4..4.\n..........\n3..3......\n.3...4..3.\n...2......\n........1.\n.4.6.5...2\n6.2.1.1...\n.1.2.1....\n4...4.3..2",
104
+ "solution": ".1-4-4==4.\n...\".|..\".\n3--3.|..\".\n\"3---4..3.\n\"\".2.\"..|.\n\"\".\".\"..1.\n\"4=6-5---2\n6=2|1|1..|\n\"1-2|1|..|\n4===4-3--2"
105
+ },
106
+ {
107
+ "family": "bridges",
108
+ "difficulty": "hard",
109
+ "filename": "bridges_10x10dh_1e764d30.txt",
110
+ "args": "10x10dh",
111
+ "problem": ".2.......3\n3.5....2..\n..........\n..........\n..5......4\n..........\n..4...4.1.\n4....1....\n.1.2..3.1.\n4...4....3",
112
+ "solution": ".2=======3\n3=5====2.|\n|.|......|\n|.|......|\n|.5======4\n|.\"......|\n|.4===4-1|\n4----1|..|\n\"1-2--3-1|\n4===4====3"
113
+ },
114
+ {
115
+ "family": "bridges",
116
+ "difficulty": "hard",
117
+ "filename": "bridges_10x10dh_714c4838.txt",
118
+ "args": "10x10dh",
119
+ "problem": "2.2......3\n..........\n4.3....5.5\n.3.5.1....\n........1.\n...6...3..\n....2.6.3.\n.1........\n...4.2.1.2\n3...2.4.1.",
120
+ "solution": "2-2------3\n|........\"\n4-3====5=5\n\"3=5-1.|.|\n\"|.\"...|1|\n\"|.6===3||\n\"|.\"2=6=3|\n\"1.\"..\"..|\n\"..4=2\"1-2\n3---2-4-1."
121
+ },
122
+ {
123
+ "family": "flow_free",
124
+ "difficulty": "easy",
125
+ "filename": "5x5_3c_5_3b79ecca.txt",
126
+ "args": null,
127
+ "problem": ".....\nB..C.\n...A.\n.A.B.\n....C",
128
+ "solution": "BBBBB\nBCCCB\nCCAAB\nCAABB\nCCCCC"
129
+ },
130
+ {
131
+ "family": "flow_free",
132
+ "difficulty": "easy",
133
+ "filename": "6x6_6c_6_f86ee188.txt",
134
+ "args": null,
135
+ "problem": "BD...E\n.ED.C.\n....A.\n......\nBAC...\nF....F",
136
+ "solution": "BDDEEE\nBEDECC\nBEEEAC\nBAAAAC\nBACCCC\nFFFFFF"
137
+ },
138
+ {
139
+ "family": "flow_free",
140
+ "difficulty": "easy",
141
+ "filename": "5x5_3c_1_87fc29c5.txt",
142
+ "args": null,
143
+ "problem": "...A.\n.C.B.\n..B..\n..C..\n....A",
144
+ "solution": "BBBAA\nBCBBA\nBCBBA\nBCCBA\nBBBBA"
145
+ },
146
+ {
147
+ "family": "flow_free",
148
+ "difficulty": "easy",
149
+ "filename": "5x5_5c_10_a482332b.txt",
150
+ "args": null,
151
+ "problem": "E.DA.\nC..B.\n.....\n..D..\nC.EBA",
152
+ "solution": "EEDAA\nCEDBA\nCEDBA\nCEDBA\nCEEBA"
153
+ },
154
+ {
155
+ "family": "flow_free",
156
+ "difficulty": "easy",
157
+ "filename": "5x5_5c_3_22075c83.txt",
158
+ "args": null,
159
+ "problem": "C...C\n..EDA\n.....\n.DEBA\n....B",
160
+ "solution": "CCCCC\nEEEDA\nEDDDA\nEDEBA\nEEEBB"
161
+ },
162
+ {
163
+ "family": "flow_free",
164
+ "difficulty": "medium",
165
+ "filename": "8x8_7c_5_0118fd6b.txt",
166
+ "args": null,
167
+ "problem": "........\nB.......\n........\n....A.F.\nF.A.....\nE.G..D.C\n...GD...\n....EB.C",
168
+ "solution": "BBBBBBBB\nBFFFFFFB\nFFGGGGFB\nFGGAAGFB\nFGAAGGBB\nEGGGGDBC\nEGGGDDBC\nEEEEEBBC"
169
+ },
170
+ {
171
+ "family": "flow_free",
172
+ "difficulty": "medium",
173
+ "filename": "7x7_5c_10_d45b6049.txt",
174
+ "args": null,
175
+ "problem": "......D\n.A.....\nD....C.\n..A....\n.......\n.E...B.\n.CBE...",
176
+ "solution": "DDDDDDD\nDAAAAAA\nDCCCCCA\nCCAAAAA\nCEEEEEE\nCEBBBBE\nCCBEEEE"
177
+ },
178
+ {
179
+ "family": "flow_free",
180
+ "difficulty": "medium",
181
+ "filename": "8x8_8c_9_3b537bc3.txt",
182
+ "args": null,
183
+ "problem": ".F.....H\n.E....A.\n....D.GA\n.......C\n.E...G..\n.BH..B..\n........\nFD...C..",
184
+ "solution": "FFHHHHHH\nFEHGGGAA\nFEHGDGGA\nFEHGDDDC\nFEHGGGDC\nFBHBBBDC\nFBBBDDDC\nFDDDDCCC"
185
+ },
186
+ {
187
+ "family": "flow_free",
188
+ "difficulty": "medium",
189
+ "filename": "8x8_6c_3_cade0083.txt",
190
+ "args": null,
191
+ "problem": "A.BC....\n..E...E.\n........\n...C....\n...F..D.\n........\n.BA....F\n.......D",
192
+ "solution": "ABBCCCCC\nABEEEEEC\nABDDDDDC\nABDCCCDC\nABDFFCDC\nABDDFCCC\nABADFFFF\nAAADDDDD"
193
+ },
194
+ {
195
+ "family": "flow_free",
196
+ "difficulty": "medium",
197
+ "filename": "8x8_8c_3_671c264d.txt",
198
+ "args": null,
199
+ "problem": ".H......\n.CB...C.\n....F...\n.G...BA.\n..H...D.\nEG...DF.\n.A......\n..E.....",
200
+ "solution": "HHBBBBBB\nHCBCCCCB\nHCCCFBBB\nHGGGFBAA\nHHHGFDDA\nEGGGFDFA\nEAAAFFFA\nEEEAAAAA"
201
+ },
202
+ {
203
+ "family": "flow_free",
204
+ "difficulty": "hard",
205
+ "filename": "9x9_8c_8_43f37569.txt",
206
+ "args": null,
207
+ "problem": ".....DA..\n...H...B.\n.....A...\n.........\nD...E..CH\nG........\n....B.EGC\n........F\n.......F.",
208
+ "solution": "DDDDDDAAA\nDHHHBBBBA\nDHBBBAAAA\nDHBHHHHHH\nDHBHEEECH\nGHBHHHECC\nGHBBBHEGC\nGHHHHHGGF\nGGGGGGGFF"
209
+ },
210
+ {
211
+ "family": "flow_free",
212
+ "difficulty": "hard",
213
+ "filename": "9x9_7c_4_207aef04.txt",
214
+ "args": null,
215
+ "problem": "E......G.\nB........\n.F..A.D..\n...B.....\n.........\n...C..D..\n.........\n...E...C.\n.F..AG...",
216
+ "solution": "EEEEEEEGG\nBBBBBBEEG\nFFAAABDEG\nFAABBBDEG\nFAEEEEDEG\nFAECCEDEG\nFAEECEEEG\nFAAECCCCG\nFFAAAGGGG"
217
+ },
218
+ {
219
+ "family": "flow_free",
220
+ "difficulty": "hard",
221
+ "filename": "9x9_8c_5_2af3ded9.txt",
222
+ "args": null,
223
+ "problem": "....F....\n.B.F..E.A\n.....C...\n.....G...\n.D.GH..C.\n.....B...\n..E.H...D\n.........\n.A.......",
224
+ "solution": "AAAFFAAAA\nABAFAAEEA\nABAAACCEE\nABBGGGCCE\nADBGHHHCE\nADBBBBHEE\nADEEHHHED\nADDEEEEED\nAADDDDDDD"
225
+ },
226
+ {
227
+ "family": "flow_free",
228
+ "difficulty": "hard",
229
+ "filename": "9x9_8c_1_55c4888b.txt",
230
+ "args": null,
231
+ "problem": "C........\n.......G.\n.....H.C.\n..F..D.E.\n.......H.\n.FB......\n.......A.\n.B...D..A\n......G.E",
232
+ "solution": "CCCCCCCCC\nGGGGGGGGC\nGBBBBHHCC\nGBFFBDHEE\nGBBFBDHHE\nGFBFBDEEE\nGFFFBDEAA\nGBBBBDEEA\nGGGGGGGEE"
233
+ },
234
+ {
235
+ "family": "flow_free",
236
+ "difficulty": "hard",
237
+ "filename": "9x9_9c_6_a4b5019b.txt",
238
+ "args": null,
239
+ "problem": "...AB...C\n...H.....\n..I....EB\n....C....\n.......G.\n.........\n..GF.FI..\n.H......E\n.AD.....D",
240
+ "solution": "AAAABCCCC\nAHHHBCBBB\nAHIBBCBEB\nAHIBCCBEE\nAHIBBBBGE\nAHIIIIIGE\nAHGFFFIGE\nAHGGGGGGE\nAADDDDDDD"
241
+ },
242
+ {
243
+ "family": "galaxies",
244
+ "difficulty": "easy",
245
+ "filename": "galaxies_5x5de_4782ed21.txt",
246
+ "args": "5x5de",
247
+ "problem": "+-+-+-+-+-+\n|o o |\n+ + + + + +\n| |\n+ o + o +o+\n| |\n+ + + + + +\n| |\n+ + + + o +\n| o |\n+-+-+-+-+-+",
248
+ "solution": "+-+-+-+-+-+\n|o| |o| |\n+-+ +-+ +-+\n| | | |\n+ o + o +o+\n| | | |\n+ +-+ +-+-+\n| | | |\n+-+-+-+ o +\n| o | |\n+-+-+-+-+-+"
249
+ },
250
+ {
251
+ "family": "galaxies",
252
+ "difficulty": "easy",
253
+ "filename": "galaxies_5x5de_1c714a44.txt",
254
+ "args": "5x5de",
255
+ "problem": "+-+-+-+-+-+\n| o |\n+ + +o+ + +\n| |\n+ + + + + +\n| o |\n+ o + + + +\n| |\n+ + +o+ +o+\n| o o |\n+-+-+-+-+-+",
256
+ "solution": "+-+-+-+-+-+\n| |o| |\n+ +-+o+-+ +\n| | | |\n+-+-+-+ +-+\n| | o |\n+ o +-+ +-+\n| | | | |\n+-+-+o+-+o+\n| o | |o| |\n+-+-+-+-+-+"
257
+ },
258
+ {
259
+ "family": "galaxies",
260
+ "difficulty": "easy",
261
+ "filename": "galaxies_5x5de_5ef3fffb.txt",
262
+ "args": "5x5de",
263
+ "problem": "+-+-+-+-+-+\n| o o|\n+ + + + + +\n|o |\n+ + o + + +\n| |\n+ + + +o+ +\n| |\n+ + + + +o+\n| o |\n+-+-+-+-+-+",
264
+ "solution": "+-+-+-+-+-+\n| |o| |o|\n+ +-+ +-+-+\n|o| | |\n+ + o + + +\n| | | |\n+-+ +-+o+-+\n| | | |\n+-+-+ + +o+\n| o | | |\n+-+-+-+-+-+"
265
+ },
266
+ {
267
+ "family": "galaxies",
268
+ "difficulty": "easy",
269
+ "filename": "galaxies_5x5de_97c6c97e.txt",
270
+ "args": "5x5de",
271
+ "problem": "+-+-+-+-+-+\n|o o |\n+ + + + + +\n| o |\n+ + +o+ + +\n| o |\n+ + + + + +\n| o |\n+o+ + + +o+\n| o |\n+-+-+-+-+-+",
272
+ "solution": "+-+-+-+-+-+\n|o| | o |\n+-+ +-+-+-+\n| |o| |\n+ +-+o+-+ +\n| |o| |\n+-+-+-+ +-+\n| | o | | |\n+o+-+-+-+o+\n| | o | |\n+-+-+-+-+-+"
273
+ },
274
+ {
275
+ "family": "galaxies",
276
+ "difficulty": "easy",
277
+ "filename": "galaxies_5x5de_16dd3c71.txt",
278
+ "args": "5x5de",
279
+ "problem": "+-+-+-+-+-+\n| o o|\n+ + +o+ + +\n|o |\n+ + + + + +\n| o |\n+ + + + + +\n|o |\n+ + + + o +\n| o |\n+-+-+-+-+-+",
280
+ "solution": "+-+-+-+-+-+\n| o | |o|\n+-+-+o+-+-+\n|o| | |\n+-+-+-+ + +\n| | o |\n+ + + +-+-+\n|o| | |\n+ +-+-+ o +\n| | o | |\n+-+-+-+-+-+"
281
+ },
282
+ {
283
+ "family": "galaxies",
284
+ "difficulty": "medium",
285
+ "filename": "galaxies_7x7dm_82b6af84.txt",
286
+ "args": "7x7dm",
287
+ "problem": "+-+-+-+-+-+-+-+\n| o o o |\n+ + + + + + + +\n| o |\n+ + +o+ + + + +\n| |\n+ + + + + + + +\n| o |\n+ + + + o + + +\n| o |\n+o+ + + + + + +\n| o |\n+ + + + + o + +\n| o o|\n+-+-+-+-+-+-+-+",
288
+ "solution": "+-+-+-+-+-+-+-+\n| o |o| | o |\n+-+-+-+-+ +-+-+\n| | o |\n+ + +o+ + +-+-+\n| | |\n+ +-+-+-+-+-+ +\n| | |o| |\n+-+ +-+ o +-+ +\n| | |o| |\n+o+ +-+-+-+-+-+\n| | |o| |\n+-+-+-+-+ o +-+\n| o | |o|\n+-+-+-+-+-+-+-+"
289
+ },
290
+ {
291
+ "family": "galaxies",
292
+ "difficulty": "medium",
293
+ "filename": "galaxies_7x7dm_659074c8.txt",
294
+ "args": "7x7dm",
295
+ "problem": "+-+-+-+-+-+-+-+\n| |\n+o+ + + + + o +\n| |\n+ +o+ +o+ + + +\n| o |\n+ + + + + + + +\n| o o |\n+ + + + + + + +\n| |\n+ + + + + + + +\n|o o o o |\n+ + + + + + + +\n| |\n+-+-+-+-+-+-+-+",
296
+ "solution": "+-+-+-+-+-+-+-+\n| | | | |\n+o+ + + + + o +\n| | | | |\n+-+o+-+o+-+-+-+\n| | | o |\n+ + + + +-+-+-+\n| | |o| o |\n+-+-+-+-+-+-+-+\n| | |\n+ + +-+ + +-+ +\n|o| |o| o |o| |\n+ + +-+ + +-+ +\n| | |\n+-+-+-+-+-+-+-+"
297
+ },
298
+ {
299
+ "family": "galaxies",
300
+ "difficulty": "medium",
301
+ "filename": "galaxies_7x7dm_7b8cef48.txt",
302
+ "args": "7x7dm",
303
+ "problem": "+-+-+-+-+-+-+-+\n| o o |\n+ + + + + + + +\n|o o o |\n+ + + +o+ + + +\n| o o|\n+ + + + + + + +\n| |\n+ + + + + + + +\n| o o o |\n+ + + + + + + +\n| |\n+ +o+ + + + + +\n|o o o |\n+-+-+-+-+-+-+-+",
304
+ "solution": "+-+-+-+-+-+-+-+\n| | |o| o |\n+ + +-+-+-+-+-+\n|o|o| |o| | |\n+ + +-+o+-+ + +\n| | | | |o|o|\n+-+-+ +-+-+ + +\n| | | |\n+ + +-+ +-+-+-+\n| |o|o|o| |\n+-+-+-+ +-+ + +\n| | |\n+-+o+-+-+ +-+-+\n|o| |o| | o |\n+-+-+-+-+-+-+-+"
305
+ },
306
+ {
307
+ "family": "galaxies",
308
+ "difficulty": "medium",
309
+ "filename": "galaxies_7x7dm_99c8ddde.txt",
310
+ "args": "7x7dm",
311
+ "problem": "+-+-+-+-+-+-+-+\n| o o |\n+ + + + + + + +\n| o o|\n+ + + +o+ + + +\n|o |\n+ + + + + + + +\n| o |\n+ +o+ + + + + +\n| |\n+ + + o + + + +\n| o |\n+ + + + + + o +\n| |\n+-+-+-+-+-+-+-+",
312
+ "solution": "+-+-+-+-+-+-+-+\n| o | |o| |\n+-+-+-+-+ +-+ +\n| | | | o |o|\n+ + + +o+-+ + +\n|o| | | | | |\n+ + + +-+ +-+-+\n| | | | o |\n+-+o+-+ +-+-+ +\n| | | | |\n+ + + o + +-+-+\n| | |o| |\n+ + + +-+ + o +\n| | | | |\n+-+-+-+-+-+-+-+"
313
+ },
314
+ {
315
+ "family": "galaxies",
316
+ "difficulty": "medium",
317
+ "filename": "galaxies_7x7dm_f5ac64df.txt",
318
+ "args": "7x7dm",
319
+ "problem": "+-+-+-+-+-+-+-+\n| o |\n+ o + + + + + +\n| o |\n+ + + + +o+ + +\n|o o |\n+ + + + + + + +\n| o |\n+ +o+ + + + + +\n| |\n+ + + + + + + +\n| o o o|\n+ + + + + + + +\n| o |\n+-+-+-+-+-+-+-+",
320
+ "solution": "+-+-+-+-+-+-+-+\n| | | o |\n+ o + +-+ +-+-+\n| | |o| |\n+-+-+ +-+o+-+ +\n|o| | |o| |\n+-+ +-+-+ +-+ +\n| |o| |\n+ +o+ +-+-+-+-+\n| | | |\n+-+ +-+ +-+ + +\n| | | o |o| |o|\n+ +-+ +-+-+-+ +\n| | o | |\n+-+-+-+-+-+-+-+"
321
+ },
322
+ {
323
+ "family": "galaxies",
324
+ "difficulty": "hard",
325
+ "filename": "galaxies_10x10dh_be0cc135.txt",
326
+ "args": "10x10dh",
327
+ "problem": "+-+-+-+-+-+-+-+-+-+-+\n| o |\n+ + +o+ + + + + o +o+\n| |\n+o+ + + + + + + + + +\n| o o o |\n+ + + + + + + + + + +\n| o |\n+ o + + + + + + + + +\n| o |\n+ + +o+ + + + +o+ + +\n| o |\n+ + + + + + + + + + +\n|o o |\n+ + + o + +o+ o + + +\n| |\n+ + + + + + + + + + +\n| o o|\n+ + + +o+ + + + + + +\n| o o o |\n+-+-+-+-+-+-+-+-+-+-+",
328
+ "solution": "+-+-+-+-+-+-+-+-+-+-+\n| o | | | | |\n+-+-+o+-+ + + + o +o+\n| | | | | |\n+o+-+-+ +-+ +-+-+-+-+\n| | |o|o|o| |\n+-+-+-+-+-+ +-+ +-+-+\n| |o| | | |\n+ o +-+ + + + +-+ + +\n| | | | | o |\n+-+-+o+-+-+-+-+o+ + +\n| | | |o| | |\n+ + +-+ + +-+-+-+-+-+\n|o| | | | | o |\n+ +-+ o +-+o+ o +-+-+\n| | | | | | | |\n+-+ + +-+ +-+-+-+ + +\n| | | o |o|\n+-+-+-+o+ +-+-+-+ + +\n| o |o| | | o | | |\n+-+-+-+-+-+-+-+-+-+-+"
329
+ },
330
+ {
331
+ "family": "galaxies",
332
+ "difficulty": "hard",
333
+ "filename": "galaxies_10x10dh_2ddb4b86.txt",
334
+ "args": "10x10dh",
335
+ "problem": "+-+-+-+-+-+-+-+-+-+-+\n| o o o |\n+ + + + + + + + + + +\n| o o |\n+ + + + + + + + + +o+\n| |\n+ + + + + + + + +o+ +\n| o o|\n+ + + + + + + + + + +\n| |\n+ + + + + + + + + o +\n|o o |\n+ + + + o + + + + + +\n| o |\n+ + + + + + + o + + +\n| o |\n+ + + + + + + + + + +\n| o o o o|\n+ + + +o+ + + + + + +\n| o o |\n+-+-+-+-+-+-+-+-+-+-+",
336
+ "solution": "+-+-+-+-+-+-+-+-+-+-+\n| o | | o | | o |\n+-+-+ + + +-+-+ +-+-+\n| o | | o | |\n+ + + +-+-+ +-+ +-+o+\n| | | | | |\n+-+-+-+ + + + +-+o+-+\n| o | |o|\n+-+ + + + +-+-+-+-+-+\n| | | | |\n+ +-+ +-+-+ +-+ + o +\n|o| | | | |o| | |\n+ + +-+ o + +-+ +-+-+\n| | o | | |\n+-+-+ +-+-+ + o + +-+\n| | |o| | |\n+ + +-+-+-+-+ +-+ + +\n| o | | o | |o| |o|\n+ + +-+o+-+-+ +-+ + +\n| |o| |o| | |\n+-+-+-+-+-+-+-+-+-+-+"
337
+ },
338
+ {
339
+ "family": "galaxies",
340
+ "difficulty": "hard",
341
+ "filename": "galaxies_10x10dh_087062d9.txt",
342
+ "args": "10x10dh",
343
+ "problem": "+-+-+-+-+-+-+-+-+-+-+\n| o |\n+o+ + + + + + + + +o+\n| o o |\n+ + + + + + + + +o+ +\n| o o|\n+ + +o+ + + + o + + +\n| o |\n+ + + + + + + + + + +\n|o |\n+ +o+ + + + + + + + +\n| o |\n+ + + + + + + + + + +\n| |\n+ + + o +o+o+ + + + +\n| o o|\n+ o + + + + + + +o+ +\n| o |\n+ + + + + + + + + + +\n|o o |\n+-+-+-+-+-+-+-+-+-+-+",
344
+ "solution": "+-+-+-+-+-+-+-+-+-+-+\n| | | | o | | |\n+o+ +-+ +-+-+-+-+ +o+\n| |o| o | | | | |\n+-+ +-+ +-+ +-+ +o+-+\n| | | | o | | |o|\n+-+-+o+-+ +-+ o + +-+\n| | | | |o| | |\n+ + +-+-+-+-+ +-+-+-+\n|o| | | | |\n+ +o+-+ + + +-+ + +-+\n| | | | | o | |\n+-+ + +-+-+ +-+ + + +\n| | | | | | | |\n+ +-+ o +o+o+-+-+-+ +\n| | | | | o | |o|\n+ o +-+ +-+ +-+-+o+ +\n| |o| | | | |\n+-+ +-+-+-+ + + +-+ +\n|o| | o | | |\n+-+-+-+-+-+-+-+-+-+-+"
345
+ },
346
+ {
347
+ "family": "galaxies",
348
+ "difficulty": "hard",
349
+ "filename": "galaxies_10x10dh_005de3c6.txt",
350
+ "args": "10x10dh",
351
+ "problem": "+-+-+-+-+-+-+-+-+-+-+\n|o |\n+ + + + + +o+ + + + +\n| |\n+ + +o+ + + + + + + +\n| o |\n+o+ + + + + + + + + +\n| o |\n+ + + + + + + + + + +\n| o o |\n+ + + + + + + + + + +\n| o o o|\n+ + + + + + + + + + +\n|o |\n+ + + + o + + + o + +\n| o|\n+ + + + + + + + + + +\n| o |\n+ +o+ + + + +o+ + o +\n|o o |\n+-+-+-+-+-+-+-+-+-+-+",
352
+ "solution": "+-+-+-+-+-+-+-+-+-+-+\n|o| | | |\n+-+ + + + +o+ + + + +\n| | | |\n+-+ +o+ +-+-+-+ + + +\n| | | | o |\n+o+ + + +-+ + + + + +\n| | | o | |\n+-+-+-+-+ + +-+ + + +\n| o | | |o| |\n+-+-+-+ +-+-+-+-+-+-+\n| | o | | o | |o|\n+ + +-+-+ + +-+-+ +-+\n|o| | | |\n+ +-+ + o + +-+ o +-+\n| | | |o|\n+-+-+ + +-+-+-+ +-+-+\n| | |o| | | |\n+-+o+-+-+-+-+o+-+ o +\n|o| | o | | |\n+-+-+-+-+-+-+-+-+-+-+"
353
+ },
354
+ {
355
+ "family": "galaxies",
356
+ "difficulty": "hard",
357
+ "filename": "galaxies_10x10dh_bfdcd141.txt",
358
+ "args": "10x10dh",
359
+ "problem": "+-+-+-+-+-+-+-+-+-+-+\n| o o o|\n+ + + + + + +o+ + + +\n|o |\n+ + + + + + + + + o +\n| o |\n+ o + + + + + + + + +\n| o o |\n+ + + + + + + + + + +\n| o o o|\n+ + + + +o+ + + + + +\n|o |\n+ +o+ + + + + +o+ + +\n| o |\n+ + + + + + + + + + +\n| o |\n+ + + + + + + + + + +\n| o |\n+ + o + +o+ + + + + +\n| o |\n+-+-+-+-+-+-+-+-+-+-+",
360
+ "solution": "+-+-+-+-+-+-+-+-+-+-+\n| o | |o| |o|\n+-+-+-+ +-+ +o+ +-+-+\n|o| | | | |\n+-+ + + +-+-+-+-+ o +\n| | | o | | |\n+ o +-+-+ +-+-+ +-+-+\n| |o| | | o | |\n+ +-+-+ + +-+-+-+ + +\n| | |o| | |o| |o|\n+-+ + + +o+ + +-+-+ +\n|o| | | | | |\n+-+o+-+-+ +-+ +o+ +-+\n| | |o| |\n+ + +-+-+ +-+-+-+ + +\n| | o | | | |\n+-+-+-+-+-+ + + +-+-+\n| | | | o |\n+ + o + +o+ +-+-+-+ +\n| | | | o | |\n+-+-+-+-+-+-+-+-+-+-+"
361
+ },
362
+ {
363
+ "family": "loopy",
364
+ "difficulty": "easy",
365
+ "filename": "loopy_5x5de_c90e485f.txt",
366
+ "args": "5x5de",
367
+ "problem": "+++++++++++++\n+ +\n+ 1 2 3 +\n+ +\n+ 1 0 +\n+ +\n+ 3 0 1 3 +\n+ +\n+ 3 +\n+ +\n+ 3 2 +\n+ +\n+++++++++++++",
368
+ "solution": "+++++++++++++\n+ - - - x - +\n+| x1x2| |3|+\n+ - x x - x +\n+x |1x0x x |+\n+ - x x x - +\n+|3x0x1x |3x+\n+ - x - x - +\n+x | | | x3|+\n+ - x x x - +\n+|3x | | |2x+\n+ - - x - x +\n+++++++++++++"
369
+ },
370
+ {
371
+ "family": "loopy",
372
+ "difficulty": "easy",
373
+ "filename": "loopy_5x5de_6dd0e857.txt",
374
+ "args": "5x5de",
375
+ "problem": "+++++++++++++\n+ +\n+ 3 3 +\n+ +\n+ 3 1 +\n+ +\n+ 3 3 1 +\n+ +\n+ 2 0 2 +\n+ +\n+ 3 3 +\n+ +\n+++++++++++++",
376
+ "solution": "+++++++++++++\n+ x - x - x +\n+x |3| |3| x+\n+ - x - x x +\n+|3x x x |1x+\n+ - - x - x +\n+x x3| |3x1x+\n+ - - x - - +\n+|2x x0x x2|+\n+ x - x - x +\n+| | |3|3| |+\n+ - x - x - +\n+++++++++++++"
377
+ },
378
+ {
379
+ "family": "loopy",
380
+ "difficulty": "easy",
381
+ "filename": "loopy_5x5de_62a72b3f.txt",
382
+ "args": "5x5de",
383
+ "problem": "+++++++++++++\n+ +\n+ +\n+ +\n+ 3 1 2 3 2 +\n+ +\n+ 3 0 2 2 +\n+ +\n+ 3 +\n+ +\n+ 3 3 +\n+ +\n+++++++++++++",
384
+ "solution": "+++++++++++++\n+ - - x x - +\n+| x | x | |+\n+ - x - x x +\n+x3|1x2|3|2|+\n+ - x x - x +\n+|3x0x x2x2|+\n+ - x - - - +\n+x | |3x x x+\n+ - x - - - +\n+|3x x x x3|+\n+ - - - - - +\n+++++++++++++"
385
+ },
386
+ {
387
+ "family": "loopy",
388
+ "difficulty": "easy",
389
+ "filename": "loopy_5x5de_d2edcce9.txt",
390
+ "args": "5x5de",
391
+ "problem": "+++++++++++++\n+ +\n+ 3 3 +\n+ +\n+ 3 +\n+ +\n+ 2 0 3 +\n+ +\n+ 1 3 3 +\n+ +\n+ 3 1 2 +\n+ +\n+++++++++++++",
392
+ "solution": "+++++++++++++\n+ - - - - - +\n+|3x x x x3|+\n+ - - x x - +\n+x x3| x | x+\n+ - - x x - +\n+|2x x x0x3|+\n+ x x - x - +\n+|1x |3| |3x+\n+ x - x x - +\n+|3| x1|2x |+\n+ - x x - - +\n+++++++++++++"
393
+ },
394
+ {
395
+ "family": "loopy",
396
+ "difficulty": "easy",
397
+ "filename": "loopy_5x5de_dcab4893.txt",
398
+ "args": "5x5de",
399
+ "problem": "+++++++++++++\n+ +\n+ 3 3 +\n+ +\n+ 0 +\n+ +\n+ 2 +\n+ +\n+ 2 0 1 +\n+ +\n+ 1 3 3 +\n+ +\n+++++++++++++",
400
+ "solution": "+++++++++++++\n+ x - x x - +\n+x |3| x |3|+\n+ - x - x x +\n+| x0x | | |+\n+ - x - x x +\n+x |2| x | |+\n+ - x - - x +\n+|2x0x x x1|+\n+ x x x - x +\n+| x1x |3|3|+\n+ - - - x - +\n+++++++++++++"
401
+ },
402
+ {
403
+ "family": "loopy",
404
+ "difficulty": "medium",
405
+ "filename": "loopy_7x7dm_37050b65.txt",
406
+ "args": "7x7dm",
407
+ "problem": "+++++++++++++++++\n+ +\n+ 3 2 2 3 3 +\n+ +\n+ 2 3 +\n+ +\n+ 3 1 3 +\n+ +\n+ 2 2 2 +\n+ +\n+ 3 2 2 1 +\n+ +\n+ 2 2 1 2 +\n+ +\n+ 3 2 1 1 3 +\n+ +\n+++++++++++++++++",
408
+ "solution": "+++++++++++++++++\n+ - - - x - x - +\n+|3x x2|2|3|3| |+\n+ - - x x x - x +\n+x x |2|3| x x |+\n+ - - x - x - x +\n+|3x x x1x |3| |+\n+ - - - x x x x +\n+x2x x | x2|2| |+\n+ - - - x - x x +\n+|3x2x2x1| x | |+\n+ - - - x x x x +\n+x x2x |2| x1|2|+\n+ - - - x x x x +\n+|3x2x x |1x1|3|+\n+ - - - - x x - +\n+++++++++++++++++"
409
+ },
410
+ {
411
+ "family": "loopy",
412
+ "difficulty": "medium",
413
+ "filename": "loopy_7x7dm_6e7d3566.txt",
414
+ "args": "7x7dm",
415
+ "problem": "+++++++++++++++++\n+ +\n+ 3 2 3 +\n+ +\n+ 1 3 +\n+ +\n+ 2 1 1 3 +\n+ +\n+ 2 2 2 +\n+ +\n+ 3 1 3 +\n+ +\n+ 3 3 1 +\n+ +\n+ 3 3 3 3 +\n+ +\n+++++++++++++++++",
416
+ "solution": "+++++++++++++++++\n+ - x - x - - - +\n+| |3| |2| x x3|+\n+ x - x x x - - +\n+|1x x | | |3x x+\n+ x x x - x - - +\n+|2x x1x1x x x3|+\n+ - - - x - - - +\n+x2x x | | x2x2x+\n+ - - - x x - - +\n+|3x1x x |3| x |+\n+ - x - x - x - +\n+x3| |3| x x1| x+\n+ - x x x - x - +\n+|3x | |3|3| x3|+\n+ - - x - x - - +\n+++++++++++++++++"
417
+ },
418
+ {
419
+ "family": "loopy",
420
+ "difficulty": "medium",
421
+ "filename": "loopy_7x7dm_de5a9374.txt",
422
+ "args": "7x7dm",
423
+ "problem": "+++++++++++++++++\n+ +\n+ 3 1 3 +\n+ +\n+ 3 3 2 2 +\n+ +\n+ 3 1 +\n+ +\n+ 3 2 1 2 +\n+ +\n+ 2 2 +\n+ +\n+ 1 2 1 2 1 +\n+ +\n+ 1 3 1 2 +\n+ +\n+++++++++++++++++",
424
+ "solution": "+++++++++++++++++\n+ - - - x x x - +\n+|3x x | x1x |3|+\n+ - - x x - - x +\n+x x3| |3|2x x2|+\n+ - - x - x - - +\n+|3x x x1x | x x+\n+ - x - x x - - +\n+x3|2| |1x x2x |+\n+ - x x x - - x +\n+|2x |2| | x | |+\n+ x x x - x - x +\n+| x1|2x x1|2x1|+\n+ x x - x x x x +\n+| x1x3| x1|2x |+\n+ - - - x x - - +\n+++++++++++++++++"
425
+ },
426
+ {
427
+ "family": "loopy",
428
+ "difficulty": "medium",
429
+ "filename": "loopy_7x7dm_c635c6e9.txt",
430
+ "args": "7x7dm",
431
+ "problem": "+++++++++++++++++\n+ +\n+ 2 1 2 +\n+ +\n+ 2 2 3 1 +\n+ +\n+ 2 2 2 +\n+ +\n+ 3 1 1 +\n+ +\n+ 2 2 2 1 +\n+ +\n+ 2 3 3 2 +\n+ +\n+ 1 1 2 3 +\n+ +\n+++++++++++++++++",
432
+ "solution": "+++++++++++++++++\n+ - - - - - - - +\n+| x x2x1x x2x |+\n+ x x - x - - - +\n+|2x2|3| | x x1x+\n+ - - x x x - x +\n+x2x x |2| | |2x+\n+ - x - x - x - +\n+| | |3x1x1x x |+\n+ x x - - x - - +\n+|2| x2x2| | x1x+\n+ x x - x x x x +\n+|2| |3|3|2| x x+\n+ x - x - x - - +\n+| x x1x x1x2x3|+\n+ - - - - - - - +\n+++++++++++++++++"
433
+ },
434
+ {
435
+ "family": "loopy",
436
+ "difficulty": "medium",
437
+ "filename": "loopy_7x7dm_31ee9beb.txt",
438
+ "args": "7x7dm",
439
+ "problem": "+++++++++++++++++\n+ +\n+ 3 2 2 0 +\n+ +\n+ 3 1 2 +\n+ +\n+ 3 2 2 +\n+ +\n+ 2 0 +\n+ +\n+ 3 3 +\n+ +\n+ 3 2 1 2 +\n+ +\n+ 2 +\n+ +\n+++++++++++++++++",
440
+ "solution": "+++++++++++++++++\n+ - - - x x x x +\n+|3x x2|2x x x0x+\n+ - - x - - - x +\n+x x3| x1x x |2x+\n+ - - x x - x - +\n+|3x x x | |2x2|+\n+ - - x - x - x +\n+x x |2| x0x | |+\n+ - - x - x x x +\n+|3x x x | x |3|+\n+ - x - x x x - +\n+x3|2| | | x1x2x+\n+ - x x x - - - +\n+| x2| | x x x |+\n+ - - x - - - - +\n+++++++++++++++++"
441
+ },
442
+ {
443
+ "family": "loopy",
444
+ "difficulty": "hard",
445
+ "filename": "loopy_10x10dh_61183860.txt",
446
+ "args": "10x10dh",
447
+ "problem": "+++++++++++++++++++++++\n+ +\n+ 3 2 1 2 3 +\n+ +\n+ 2 1 3 1 1 +\n+ +\n+ 2 2 2 +\n+ +\n+ 1 2 1 2 3 1 +\n+ +\n+ 1 1 3 1 +\n+ +\n+ 2 1 3 +\n+ +\n+ 2 2 3 3 +\n+ +\n+ 1 2 2 1 2 +\n+ +\n+ 2 1 0 +\n+ +\n+ 2 2 2 3 2 +\n+ +\n+++++++++++++++++++++++",
448
+ "solution": "+++++++++++++++++++++++\n+ - x - x x - - - x - +\n+|3| | |2x1| x x |2|3|+\n+ x x x - x x - - x x +\n+| |2|1x | | |3x1x1| |+\n+ x x x - x x - x x x +\n+|2| | |2x | x | x |2|+\n+ x - x x x x - x - x +\n+| x1x |2x1|2|3x1| x |+\n+ - x x - x x - x - x +\n+x |1x1x | | x3|1x | |+\n+ - x - x - x - x - x +\n+|2x1|3| x x | x | x |+\n+ x x x x - x - - x - +\n+| x2| |2|3| x x x |3x+\n+ - - x x x - - - x - +\n+x1x2x | |2x1x x | x2|+\n+ x - - x - x x x - x +\n+x | x x x |2x1x0x | |+\n+ - x - - x - - x - x +\n+| x2|2x2| x x3| | x2|+\n+ - - x x - - - x - - +\n+++++++++++++++++++++++"
449
+ },
450
+ {
451
+ "family": "loopy",
452
+ "difficulty": "hard",
453
+ "filename": "loopy_10x10dh_5460cf15.txt",
454
+ "args": "10x10dh",
455
+ "problem": "+++++++++++++++++++++++\n+ +\n+ 2 3 3 +\n+ +\n+ 2 2 2 2 2 3 +\n+ +\n+ 1 2 3 1 +\n+ +\n+ 2 1 2 1 1 +\n+ +\n+ 2 3 2 +\n+ +\n+ 2 1 2 2 3 1 +\n+ +\n+ 2 2 2 2 2 +\n+ +\n+ 2 1 2 3 0 +\n+ +\n+ 2 1 2 +\n+ +\n+ 3 1 2 2 2 3 3 +\n+ +\n+++++++++++++++++++++++",
456
+ "solution": "+++++++++++++++++++++++\n+ - - - - x - x x - - +\n+| x x x2| |3| x | x3|+\n+ x - - x - x - x x - +\n+| |2x2| x2x x2| |2|3x+\n+ - x x - - - x - x - +\n+x x x1x x2x3|1x x x |+\n+ - - - - - - x - - - +\n+| x2x x1x x2x1| x x1x+\n+ x - - x - - x - - x +\n+| |2x | |3x | x x |2x+\n+ - x - x - x x - x - +\n+x x |2x1x2|2|3| |1x |+\n+ x - x - x x - x x - +\n+x2|2x | | |2x x2|2| x+\n+ - x - x x - x - x - +\n+| x |2x1| x2| |3x0x |+\n+ x - x x - x x - x - +\n+|2| x x1x |2| x | | x+\n+ x x x - - x x - x - +\n+|3| x1| x2x2|2|3x x3|+\n+ - x x - - - x - - - +\n+++++++++++++++++++++++"
457
+ },
458
+ {
459
+ "family": "loopy",
460
+ "difficulty": "hard",
461
+ "filename": "loopy_10x10dh_fe5cd01c.txt",
462
+ "args": "10x10dh",
463
+ "problem": "+++++++++++++++++++++++\n+ +\n+ 3 2 1 1 2 2 3 +\n+ +\n+ 1 1 2 1 2 +\n+ +\n+ 3 2 3 1 +\n+ +\n+ 1 1 3 2 +\n+ +\n+ 2 1 1 1 3 1 +\n+ +\n+ 2 0 3 +\n+ +\n+ 3 2 1 2 +\n+ +\n+ 2 1 0 2 +\n+ +\n+ 3 3 3 1 3 +\n+ +\n+ 2 3 2 3 +\n+ +\n+++++++++++++++++++++++",
464
+ "solution": "+++++++++++++++++++++++\n+ - x - x x x x - - - +\n+| |3| |2x1x1x2|2x x3|+\n+ x - x - - - - x - - +\n+| x1x1x x2x1x x2| x x+\n+ - x - - - x - - x - +\n+x |3| x x |2|3x x1| |+\n+ x - x - - x - - x x +\n+x x x1| x x1x x |3|2|+\n+ - x x - - - - x - x +\n+| |2x1x x1x1x3| x x1|+\n+ x - - x x x - x - x +\n+| x x2| x0x | x |3| |+\n+ x - x x x x x - x - +\n+| |3| |2x1x |2| x x x+\n+ - x x - - - x - - - +\n+x2x |1x x x x0x x x2|+\n+ - x x - x x x x - x +\n+|3|3| |3|1x x x |3| |+\n+ x - x x x - x x x x +\n+| x x2| | |3| x |2|3|+\n+ - - - x - x - - x - +\n+++++++++++++++++++++++"
465
+ },
466
+ {
467
+ "family": "loopy",
468
+ "difficulty": "hard",
469
+ "filename": "loopy_10x10dh_b015c646.txt",
470
+ "args": "10x10dh",
471
+ "problem": "+++++++++++++++++++++++\n+ +\n+ 3 2 2 2 3 +\n+ +\n+ 2 2 2 3 +\n+ +\n+ 2 2 3 1 0 2 +\n+ +\n+ 2 2 2 3 2 +\n+ +\n+ 3 2 1 1 3 +\n+ +\n+ 3 2 2 2 +\n+ +\n+ 1 2 3 1 1 3 +\n+ +\n+ 2 2 +\n+ +\n+ 2 1 1 3 +\n+ +\n+ 1 1 2 3 2 2 +\n+ +\n+++++++++++++++++++++++",
472
+ "solution": "+++++++++++++++++++++++\n+ - x - - x - x - x - +\n+|3|2|2x |2| | | | |3|+\n+ x x x - x x x x x x +\n+|2| | | x |2| |2|3| |+\n+ x - x x - x - x - x +\n+|2x x |2|3x1x x0x x2|+\n+ - - x x - - x x - - +\n+x2x |2|2x x3| x | x2x+\n+ - - x - x - x x - - +\n+|3x x x | |2x1x x1x3|+\n+ - x - x - x - - x - +\n+x |3| |2x x |2x |2| x+\n+ x - x - x - x x x x +\n+x x x1x2| |3x1x1|3| x+\n+ - - - x x - - x - x +\n+| x x2| | x x2| x x x+\n+ - - x - x - x - - - +\n+x2x |1x x1|3| x x x |+\n+ - - x x x x x - x x +\n+| x x1x1x2| |3| |2x2|+\n+ - - - - - x - x - - +\n+++++++++++++++++++++++"
473
+ },
474
+ {
475
+ "family": "loopy",
476
+ "difficulty": "hard",
477
+ "filename": "loopy_10x10dh_35065968.txt",
478
+ "args": "10x10dh",
479
+ "problem": "+++++++++++++++++++++++\n+ +\n+ 2 2 3 3 3 1 +\n+ +\n+ 2 3 1 3 +\n+ +\n+ 0 2 1 1 +\n+ +\n+ 1 2 3 2 +\n+ +\n+ 2 2 2 +\n+ +\n+ 3 2 2 2 1 3 2 +\n+ +\n+ 3 1 2 3 1 2 +\n+ +\n+ 2 2 2 +\n+ +\n+ 2 2 3 2 3 +\n+ +\n+ 3 2 2 2 2 2 3 +\n+ +\n+++++++++++++++++++++++",
480
+ "solution": "+++++++++++++++++++++++\n+ - - x - x - x - x x +\n+| x2|2|3|3| |3| | x1x+\n+ - x x x - x - x - - +\n+x |2|3| x x x1x x x3|+\n+ - x - x - - x - - - +\n+| x0x x |2x | | x1x1x+\n+ - x x x x - x x x x +\n+x | x1x |2|3x |2x x x+\n+ x x - - x - x - - - +\n+x2|2| x x x | x2x x |+\n+ - x x - - - x - - x +\n+|3x |2| x2x2x1|3x2| |+\n+ - x x - - - x - x - +\n+x3| |1x x2x3|1x2| x x+\n+ - x x - - - x x - x +\n+| x |2|2x2x x x x | x+\n+ - - x x - x - - x - +\n+x x2x2| | | |3x2| x3|+\n+ - - - x x x - x x - +\n+|3x2x2x2| |2x |2|3| x+\n+ - - - - x - - x - x +\n+++++++++++++++++++++++"
481
+ },
482
+ {
483
+ "family": "pattern",
484
+ "difficulty": "easy",
485
+ "filename": "pattern_5x5de_98df5b16.txt",
486
+ "args": "5x5de",
487
+ "problem": " 2 \n 4 2 2 1 1 \n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+\n3 1| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+\n 1| | | | | |\n +--+--+--+--+--+\n1 1| | | | | |\n +--+--+--+--+--+",
488
+ "solution": " 2 \n 4 2 2 1 1 \n +--+--+--+--+--+\n 3|..|..|##|##|##|\n +--+--+--+--+--+\n3 1|##|##|##|..|##|\n +--+--+--+--+--+\n 2|##|##|..|..|..|\n +--+--+--+--+--+\n 1|##|..|..|..|..|\n +--+--+--+--+--+\n1 1|##|..|..|..|##|\n +--+--+--+--+--+"
489
+ },
490
+ {
491
+ "family": "pattern",
492
+ "difficulty": "easy",
493
+ "filename": "pattern_5x5de_a028d637.txt",
494
+ "args": "5x5de",
495
+ "problem": " 1 \n 4 3 2 1 1 \n +--+--+--+--+--+\n1 2| | | | | |\n +--+--+--+--+--+\n 1| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+",
496
+ "solution": " 1 \n 4 3 2 1 1 \n +--+--+--+--+--+\n1 2|..|##|..|##|##|\n +--+--+--+--+--+\n 1|##|..|..|..|..|\n +--+--+--+--+--+\n 2|##|##|..|..|..|\n +--+--+--+--+--+\n 3|##|##|##|..|..|\n +--+--+--+--+--+\n 3|##|##|##|..|..|\n +--+--+--+--+--+"
497
+ },
498
+ {
499
+ "family": "pattern",
500
+ "difficulty": "easy",
501
+ "filename": "pattern_5x5de_15204aac.txt",
502
+ "args": "5x5de",
503
+ "problem": " 1 \n 4 3 1 1 3 \n +--+--+--+--+--+\n 4| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+\n2 1| | | | | |\n +--+--+--+--+--+\n1 1| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+",
504
+ "solution": " 1 \n 4 3 1 1 3 \n +--+--+--+--+--+\n 4|##|##|##|##|..|\n +--+--+--+--+--+\n 2|##|##|..|..|..|\n +--+--+--+--+--+\n2 1|##|##|..|..|##|\n +--+--+--+--+--+\n1 1|##|..|..|..|##|\n +--+--+--+--+--+\n 2|..|..|..|##|##|\n +--+--+--+--+--+"
505
+ },
506
+ {
507
+ "family": "pattern",
508
+ "difficulty": "easy",
509
+ "filename": "pattern_5x5de_da7af9b5.txt",
510
+ "args": "5x5de",
511
+ "problem": " 1 1 1 \n 3 1 2 1 2 \n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+\n 1| | | | | |\n +--+--+--+--+--+\n2 1| | | | | |\n +--+--+--+--+--+\n1 2| | | | | |\n +--+--+--+--+--+",
512
+ "solution": " 1 1 1 \n 3 1 2 1 2 \n +--+--+--+--+--+\n 3|..|..|##|##|##|\n +--+--+--+--+--+\n 2|..|##|##|..|..|\n +--+--+--+--+--+\n 1|##|..|..|..|..|\n +--+--+--+--+--+\n2 1|##|##|..|..|##|\n +--+--+--+--+--+\n1 2|##|..|..|##|##|\n +--+--+--+--+--+"
513
+ },
514
+ {
515
+ "family": "pattern",
516
+ "difficulty": "easy",
517
+ "filename": "pattern_5x5de_5f207763.txt",
518
+ "args": "5x5de",
519
+ "problem": " 1 1 \n 3 2 1 2 2 \n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+\n2 1| | | | | |\n +--+--+--+--+--+\n 1| | | | | |\n +--+--+--+--+--+\n 2| | | | | |\n +--+--+--+--+--+\n 3| | | | | |\n +--+--+--+--+--+",
520
+ "solution": " 1 1 \n 3 2 1 2 2 \n +--+--+--+--+--+\n 3|##|##|##|..|..|\n +--+--+--+--+--+\n2 1|##|##|..|..|##|\n +--+--+--+--+--+\n 1|##|..|..|..|..|\n +--+--+--+--+--+\n 2|..|..|..|##|##|\n +--+--+--+--+--+\n 3|..|..|##|##|##|\n +--+--+--+--+--+"
521
+ },
522
+ {
523
+ "family": "pattern",
524
+ "difficulty": "medium",
525
+ "filename": "pattern_7x7dm_b0646aba.txt",
526
+ "args": "7x7dm",
527
+ "problem": " 1 \n 5 5 5 3 2 2 1 \n +--+--+--+--+--+--+--+\n3| | | | | | | |\n +--+--+--+--+--+--+--+\n5| | | | | | | |\n +--+--+--+--+--+--+--+\n4| | | | | | | |\n +--+--+--+--+--+--+--+\n4| | | | | | | |\n +--+--+--+--+--+--+--+\n3| | | | | | | |\n +--+--+--+--+--+--+--+\n2| | | | | | | |\n +--+--+--+--+--+--+--+\n3| | | | | | | |\n +--+--+--+--+--+--+--+",
528
+ "solution": " 1 \n 5 5 5 3 2 2 1 \n +--+--+--+--+--+--+--+\n3|##|##|##|..|..|..|..|\n +--+--+--+--+--+--+--+\n5|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+\n4|##|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+\n4|##|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+\n3|##|##|##|..|..|..|..|\n +--+--+--+--+--+--+--+\n2|..|..|..|..|##|##|..|\n +--+--+--+--+--+--+--+\n3|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+"
529
+ },
530
+ {
531
+ "family": "pattern",
532
+ "difficulty": "medium",
533
+ "filename": "pattern_7x7dm_8ba4dcd7.txt",
534
+ "args": "7x7dm",
535
+ "problem": " 2 1 \n 2 2 4 2 4 3 4 \n +--+--+--+--+--+--+--+\n 2| | | | | | | |\n +--+--+--+--+--+--+--+\n 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 2| | | | | | | |\n +--+--+--+--+--+--+--+\n1 3| | | | | | | |\n +--+--+--+--+--+--+--+\n1 3| | | | | | | |\n +--+--+--+--+--+--+--+\n5 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 5| | | | | | | |\n +--+--+--+--+--+--+--+",
536
+ "solution": " 2 1 \n 2 2 4 2 4 3 4 \n +--+--+--+--+--+--+--+\n 2|##|##|..|..|..|..|..|\n +--+--+--+--+--+--+--+\n 1|##|..|..|..|..|..|..|\n +--+--+--+--+--+--+--+\n 2|..|..|..|..|..|##|##|\n +--+--+--+--+--+--+--+\n1 3|..|..|##|..|##|##|##|\n +--+--+--+--+--+--+--+\n1 3|..|..|##|..|##|##|##|\n +--+--+--+--+--+--+--+\n5 1|##|##|##|##|##|..|##|\n +--+--+--+--+--+--+--+\n 5|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+"
537
+ },
538
+ {
539
+ "family": "pattern",
540
+ "difficulty": "medium",
541
+ "filename": "pattern_7x7dm_0beb9c48.txt",
542
+ "args": "7x7dm",
543
+ "problem": " 3 2 1 \n 1 3 3 4 3 3 2 \n +--+--+--+--+--+--+--+\n3 1| | | | | | | |\n +--+--+--+--+--+--+--+\n2 2| | | | | | | |\n +--+--+--+--+--+--+--+\n1 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 3| | | | | | | |\n +--+--+--+--+--+--+--+\n 4| | | | | | | |\n +--+--+--+--+--+--+--+\n 4| | | | | | | |\n +--+--+--+--+--+--+--+\n 4| | | | | | | |\n +--+--+--+--+--+--+--+",
544
+ "solution": " 3 2 1 \n 1 3 3 4 3 3 2 \n +--+--+--+--+--+--+--+\n3 1|##|##|##|..|..|..|##|\n +--+--+--+--+--+--+--+\n2 2|##|##|..|..|..|##|##|\n +--+--+--+--+--+--+--+\n1 1|##|..|..|..|..|##|..|\n +--+--+--+--+--+--+--+\n 3|..|..|..|##|##|##|..|\n +--+--+--+--+--+--+--+\n 4|..|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+\n 4|..|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+\n 4|##|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+"
545
+ },
546
+ {
547
+ "family": "pattern",
548
+ "difficulty": "medium",
549
+ "filename": "pattern_7x7dm_b58a2865.txt",
550
+ "args": "7x7dm",
551
+ "problem": " 2 3 4 5 3 3 4 \n +--+--+--+--+--+--+--+\n1| | | | | | | |\n +--+--+--+--+--+--+--+\n3| | | | | | | |\n +--+--+--+--+--+--+--+\n4| | | | | | | |\n +--+--+--+--+--+--+--+\n5| | | | | | | |\n +--+--+--+--+--+--+--+\n3| | | | | | | |\n +--+--+--+--+--+--+--+\n4| | | | | | | |\n +--+--+--+--+--+--+--+\n4| | | | | | | |\n +--+--+--+--+--+--+--+",
552
+ "solution": " 2 3 4 5 3 3 4 \n +--+--+--+--+--+--+--+\n1|..|..|..|..|..|..|##|\n +--+--+--+--+--+--+--+\n3|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+\n4|..|..|..|##|##|##|##|\n +--+--+--+--+--+--+--+\n5|..|..|##|##|##|##|##|\n +--+--+--+--+--+--+--+\n3|..|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+\n4|##|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+\n4|##|##|##|##|..|..|..|\n +--+--+--+--+--+--+--+"
553
+ },
554
+ {
555
+ "family": "pattern",
556
+ "difficulty": "medium",
557
+ "filename": "pattern_7x7dm_be7de8ae.txt",
558
+ "args": "7x7dm",
559
+ "problem": " 1 \n 3 3 1 1 \n 2 1 3 1 1 1 6 \n +--+--+--+--+--+--+--+\n 2 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 2 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 4 2| | | | | | | |\n +--+--+--+--+--+--+--+\n 1| | | | | | | |\n +--+--+--+--+--+--+--+\n 2 1| | | | | | | |\n +--+--+--+--+--+--+--+\n1 1 1| | | | | | | |\n +--+--+--+--+--+--+--+\n3 1 1| | | | | | | |\n +--+--+--+--+--+--+--+",
560
+ "solution": " 1 \n 3 3 1 1 \n 2 1 3 1 1 1 6 \n +--+--+--+--+--+--+--+\n 2 1|##|##|..|##|..|..|..|\n +--+--+--+--+--+--+--+\n 2 1|##|##|..|..|..|..|##|\n +--+--+--+--+--+--+--+\n 4 2|##|##|##|##|..|##|##|\n +--+--+--+--+--+--+--+\n 1|..|..|..|..|..|..|##|\n +--+--+--+--+--+--+--+\n 2 1|..|..|##|##|..|..|##|\n +--+--+--+--+--+--+--+\n1 1 1|##|..|##|..|..|..|##|\n +--+--+--+--+--+--+--+\n3 1 1|##|##|##|..|##|..|##|\n +--+--+--+--+--+--+--+"
561
+ },
562
+ {
563
+ "family": "pattern",
564
+ "difficulty": "hard",
565
+ "filename": "pattern_10x10dh_9c7d7e1b.txt",
566
+ "args": "10x10dh",
567
+ "problem": " 4 \n 2 6 3 1 1 3 2 1 \n 3 1 1 1 2 4 1 5 4 5 \n +--+--+--+--+--+--+--+--+--+--+\n3 5| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n6 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 6| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+",
568
+ "solution": " 4 \n 2 6 3 1 1 3 2 1 \n 3 1 1 1 2 4 1 5 4 5 \n +--+--+--+--+--+--+--+--+--+--+\n3 5|##|##|##|..|..|##|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n3 3|##|##|##|..|..|..|##|##|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 2|..|##|##|..|..|..|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 2|##|##|..|..|..|##|##|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n6 1|##|##|##|##|##|##|..|..|..|##|\n +--+--+--+--+--+--+--+--+--+--+\n2 6|##|##|..|..|##|##|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n1 3|..|..|..|..|..|##|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 3|..|..|..|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 3|..|..|..|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n1 2|..|##|..|..|..|..|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+"
569
+ },
570
+ {
571
+ "family": "pattern",
572
+ "difficulty": "hard",
573
+ "filename": "pattern_10x10dh_a4952b90.txt",
574
+ "args": "10x10dh",
575
+ "problem": " 2 \n 1 3 \n 1 1 1 \n 3 3 5 3 7 1 1 7 5 6 \n +--+--+--+--+--+--+--+--+--+--+\n 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 6| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 4| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 8| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n4 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+",
576
+ "solution": " 2 \n 1 3 \n 1 1 1 \n 3 3 5 3 7 1 1 7 5 6 \n +--+--+--+--+--+--+--+--+--+--+\n 3|..|..|..|##|##|##|..|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 1|..|..|..|..|##|##|..|..|..|##|\n +--+--+--+--+--+--+--+--+--+--+\n1 2|..|..|..|..|##|..|..|..|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 6|..|..|..|..|##|##|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n1 4|..|..|..|..|##|..|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 8|..|..|##|##|##|##|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n3 3|..|..|##|##|##|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n4 3|##|##|##|##|..|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n3 1|##|##|##|..|..|..|..|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n3 2|##|##|##|..|..|..|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+"
577
+ },
578
+ {
579
+ "family": "pattern",
580
+ "difficulty": "hard",
581
+ "filename": "pattern_10x10dh_804c3344.txt",
582
+ "args": "10x10dh",
583
+ "problem": " 1 \n 2 \n 1 3 2 2 \n 7 7 1 4 4 6 1 3 3 3 \n +--+--+--+--+--+--+--+--+--+--+\n2 4| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n2 5| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 7| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n3 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+",
584
+ "solution": " 1 \n 2 \n 1 3 2 2 \n 7 7 1 4 4 6 1 3 3 3 \n +--+--+--+--+--+--+--+--+--+--+\n2 4|##|##|..|..|..|..|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n2 3|##|##|..|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n3 1|##|##|##|..|..|..|..|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 1|##|##|..|..|..|..|##|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 2|##|##|..|..|..|##|##|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 1|##|##|..|..|..|##|..|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n2 5|##|##|..|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n3 3|..|..|..|##|##|##|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 7|..|..|..|##|##|##|##|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n3 2|..|..|..|##|##|##|..|..|##|##|\n +--+--+--+--+--+--+--+--+--+--+"
585
+ },
586
+ {
587
+ "family": "pattern",
588
+ "difficulty": "hard",
589
+ "filename": "pattern_10x10dh_535b6abe.txt",
590
+ "args": "10x10dh",
591
+ "problem": " 4 \n 3 2 7 8 6 5 6 4 4 1 \n +--+--+--+--+--+--+--+--+--+--+\n3 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n4 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n5 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n6 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 6| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 6| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 7| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 5| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+",
592
+ "solution": " 4 \n 3 2 7 8 6 5 6 4 4 1 \n +--+--+--+--+--+--+--+--+--+--+\n3 1|..|##|##|##|..|..|..|..|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n4 1|##|##|##|##|..|..|..|..|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n5 2|##|##|##|##|##|..|..|..|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n6 1|##|##|##|##|##|##|..|..|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n 6|..|..|##|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n 6|..|..|##|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n 7|..|##|##|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n1 5|..|##|..|##|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n 1|..|..|..|..|..|..|##|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n 1|..|..|..|..|..|..|##|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+"
593
+ },
594
+ {
595
+ "family": "pattern",
596
+ "difficulty": "hard",
597
+ "filename": "pattern_10x10dh_cf8495dd.txt",
598
+ "args": "10x10dh",
599
+ "problem": " 1 3 2 3 3 5 3 \n 4 4 6 1 2 2 2 2 6 1 \n +--+--+--+--+--+--+--+--+--+--+\n 3 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 6| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 1 4| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 2 4| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 3 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 3 3| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 3 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 2| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n 1 4| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+\n1 4 1| | | | | | | | | | |\n +--+--+--+--+--+--+--+--+--+--+",
600
+ "solution": " 1 3 2 3 3 5 3 \n 4 4 6 1 2 2 2 2 6 1 \n +--+--+--+--+--+--+--+--+--+--+\n 3 1|..|..|##|##|##|..|..|..|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n 6|..|..|..|##|##|##|##|##|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n 1 4|..|..|..|##|..|##|##|##|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n 2 4|##|##|..|..|..|##|##|##|##|..|\n +--+--+--+--+--+--+--+--+--+--+\n 3 3|##|##|##|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 3 3|##|##|##|..|..|..|..|##|##|##|\n +--+--+--+--+--+--+--+--+--+--+\n 3 1|##|##|##|..|..|..|..|..|..|##|\n +--+--+--+--+--+--+--+--+--+--+\n 2|..|..|##|##|..|..|..|..|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n 1 4|..|..|##|..|##|##|##|##|..|..|\n +--+--+--+--+--+--+--+--+--+--+\n1 4 1|..|..|##|..|##|##|##|##|..|##|\n +--+--+--+--+--+--+--+--+--+--+"
601
+ },
602
+ {
603
+ "family": "undead",
604
+ "difficulty": "easy",
605
+ "filename": "undead_4x4de_c1f43ec6.txt",
606
+ "args": "4x4de",
607
+ "problem": "G: 2 V: 6 Z: 3\n\n 2 0 4 3 \n 2 . . . . 2\n 0 \\ / . . 2\n 0 / . . . 3\n 0 / / . . 2\n 0 2 4 3 ",
608
+ "solution": "G: 2 V: 6 Z: 3\n\n 2 0 4 3 \n 2 V G Z G 2\n 0 \\ / V V 2\n 0 / V V V 3\n 0 / / Z Z 2\n 0 2 4 3 "
609
+ },
610
+ {
611
+ "family": "undead",
612
+ "difficulty": "easy",
613
+ "filename": "undead_4x4de_0fd18e30.txt",
614
+ "args": "4x4de",
615
+ "problem": "G: 4 V: 3 Z: 4\n\n 2 2 3 0 \n 0 . \\ . \\ 0\n 2 . / . / 2\n 2 . . . . 2\n 2 / . . . 2\n 3 2 3 0 ",
616
+ "solution": "G: 4 V: 3 Z: 4\n\n 2 2 3 0 \n 0 G \\ V \\ 0\n 2 V / V / 2\n 2 Z Z G G 2\n 2 / Z Z G 2\n 3 2 3 0 "
617
+ },
618
+ {
619
+ "family": "undead",
620
+ "difficulty": "easy",
621
+ "filename": "undead_4x4de_6f20627a.txt",
622
+ "args": "4x4de",
623
+ "problem": "G: 4 V: 6 Z: 0\n\n 0 2 1 1 \n 0 \\ \\ . . 0\n 3 . . . . 3\n 0 / . / . 0\n 1 / \\ . . 2\n 0 0 2 1 ",
624
+ "solution": "G: 4 V: 6 Z: 0\n\n 0 2 1 1 \n 0 \\ \\ G G 0\n 3 V V V G 3\n 0 / V / G 0\n 1 / \\ V V 2\n 0 0 2 1 "
625
+ },
626
+ {
627
+ "family": "undead",
628
+ "difficulty": "easy",
629
+ "filename": "undead_4x4de_b9388a3d.txt",
630
+ "args": "4x4de",
631
+ "problem": "G: 4 V: 2 Z: 3\n\n 2 1 1 3 \n 1 . / \\ . 0\n 2 . \\ . / 0\n 2 / . . \\ 0\n 1 / . . . 0\n 3 2 4 0 ",
632
+ "solution": "G: 4 V: 2 Z: 3\n\n 2 1 1 3 \n 1 Z / \\ G 0\n 2 Z \\ Z / 0\n 2 / V V \\ 0\n 1 / G G G 0\n 3 2 4 0 "
633
+ },
634
+ {
635
+ "family": "undead",
636
+ "difficulty": "easy",
637
+ "filename": "undead_4x4de_bd4167ad.txt",
638
+ "args": "4x4de",
639
+ "problem": "G: 2 V: 3 Z: 4\n\n 1 3 2 0 \n 5 . . . \\ 0\n 1 / . \\ . 0\n 0 . / / / 3\n 3 . . . / 0\n 2 3 3 0 ",
640
+ "solution": "G: 2 V: 3 Z: 4\n\n 1 3 2 0 \n 5 Z V V \\ 0\n 1 / V \\ G 0\n 0 G / / / 3\n 3 Z Z Z / 0\n 2 3 3 0 "
641
+ },
642
+ {
643
+ "family": "undead",
644
+ "difficulty": "medium",
645
+ "filename": "undead_5x5dm_bd47fd3a.txt",
646
+ "args": "5x5dm",
647
+ "problem": "G: 7 V: 5 Z: 3\n\n 2 1 3 1 0 \n 0 . / . \\ . 0\n 2 \\ \\ \\ . . 0\n 2 . . \\ / \\ 2\n 4 . . . \\ / 1\n 2 . . . . . 2\n 2 3 2 2 1 ",
648
+ "solution": "G: 7 V: 5 Z: 3\n\n 2 1 3 1 0 \n 0 G / V \\ G 0\n 2 \\ \\ \\ G G 0\n 2 V V \\ / \\ 2\n 4 Z Z V \\ / 1\n 2 G G V G Z 2\n 2 3 2 2 1 "
649
+ },
650
+ {
651
+ "family": "undead",
652
+ "difficulty": "medium",
653
+ "filename": "undead_5x5dm_24c30c88.txt",
654
+ "args": "5x5dm",
655
+ "problem": "G: 10 V: 4 Z: 5\n\n 0 5 0 4 6 \n 0 / . . . / 0\n 3 . . . . . 3\n 3 . . . / . 2\n 0 . . . \\ \\ 0\n 1 . \\ . . . 4\n 4 1 0 4 0 ",
656
+ "solution": "G: 10 V: 4 Z: 5\n\n 0 5 0 4 6 \n 0 / V G Z / 0\n 3 Z Z G G V 3\n 3 G Z G / V 2\n 0 G G G \\ \\ 0\n 1 Z \\ G V G 4\n 4 1 0 4 0 "
657
+ },
658
+ {
659
+ "family": "undead",
660
+ "difficulty": "medium",
661
+ "filename": "undead_5x5dm_ce0a1642.txt",
662
+ "args": "5x5dm",
663
+ "problem": "G: 4 V: 8 Z: 5\n\n 0 2 5 2 3 \n 3 . . . . . 3\n 4 . . . \\ . 2\n 2 \\ \\ \\ . / 0\n 5 . . . . . 5\n 0 \\ / . . / 0\n 0 0 3 5 0 ",
664
+ "solution": "G: 4 V: 8 Z: 5\n\n 0 2 5 2 3 \n 3 G V V Z G 3\n 4 G Z Z \\ Z 2\n 2 \\ \\ \\ G / 0\n 5 V V V Z V 5\n 0 \\ / V V / 0\n 0 0 3 5 0 "
665
+ },
666
+ {
667
+ "family": "undead",
668
+ "difficulty": "medium",
669
+ "filename": "undead_5x5dm_4a5ebb99.txt",
670
+ "args": "5x5dm",
671
+ "problem": "G: 8 V: 4 Z: 2\n\n 0 4 0 2 0 \n 4 \\ . / / \\ 0\n 0 . . / . / 4\n 2 . \\ / . / 2\n 2 . . . . . 2\n 0 \\ . / . . 1\n 0 2 2 3 0 ",
672
+ "solution": "G: 8 V: 4 Z: 2\n\n 0 4 0 2 0 \n 4 \\ V / / \\ 0\n 0 G G / V / 4\n 2 G \\ / G / 2\n 2 V G V G G 2\n 0 \\ Z / Z G 1\n 0 2 2 3 0 "
673
+ },
674
+ {
675
+ "family": "undead",
676
+ "difficulty": "medium",
677
+ "filename": "undead_5x5dm_0770fdf4.txt",
678
+ "args": "5x5dm",
679
+ "problem": "G: 3 V: 9 Z: 6\n\n 2 0 4 3 3 \n 4 . \\ . . . 3\n 1 \\ . . . / 4\n 4 . . . \\ . 2\n 0 \\ \\ . . . 4\n 5 . . . . / 0\n 1 0 4 4 0 ",
680
+ "solution": "G: 3 V: 9 Z: 6\n\n 2 0 4 3 3 \n 4 Z \\ V V V 3\n 1 \\ V V Z / 4\n 4 V Z G \\ Z 2\n 0 \\ \\ V Z G 4\n 5 V G V Z / 0\n 1 0 4 4 0 "
681
+ },
682
+ {
683
+ "family": "undead",
684
+ "difficulty": "hard",
685
+ "filename": "undead_7x7dh_c659419d.txt",
686
+ "args": "7x7dh",
687
+ "problem": "G: 8 V: 15 Z: 12\n\n 4 3 0 6 2 0 1 \n 7 . . \\ . . \\ . 1\n 7 . . . . \\ . \\ 0\n 4 . \\ \\ . . \\ . 1\n 6 . . . . / . . 1\n 3 \\ . \\ . . . . 7\n 0 \\ . . . / . . 3\n 0 / . . \\ . . . 6\n 0 5 6 0 0 8 4 ",
688
+ "solution": "G: 8 V: 15 Z: 12\n\n 4 3 0 6 2 0 1 \n 7 Z G \\ V V \\ V 1\n 7 V G Z G \\ V \\ 0\n 4 Z \\ \\ Z Z \\ V 1\n 6 G Z Z G / G G 1\n 3 \\ Z \\ Z V Z V 7\n 0 \\ Z V V / V V 3\n 0 / V V \\ G Z V 6\n 0 5 6 0 0 8 4 "
689
+ },
690
+ {
691
+ "family": "undead",
692
+ "difficulty": "hard",
693
+ "filename": "undead_7x7dh_271c8105.txt",
694
+ "args": "7x7dh",
695
+ "problem": "G: 13 V: 9 Z: 2\n\n 0 2 3 3 1 2 0 \n 0 / . . / / / . 1\n 0 . / / / . . . 2\n 0 . . \\ / / / \\ 2\n 6 . \\ \\ / / . . 1\n 3 / . . . / / . 2\n 2 . \\ . . / . / 1\n 3 / . . . \\ \\ . 2\n 3 0 4 4 3 5 0 ",
696
+ "solution": "G: 13 V: 9 Z: 2\n\n 0 2 3 3 1 2 0 \n 0 / V Z / / / G 1\n 0 G / / / V V G 2\n 0 G G \\ / / / \\ 2\n 6 V \\ \\ / / G G 1\n 3 / G V V / / G 2\n 2 V \\ V V / G / 1\n 3 / G G Z \\ \\ G 2\n 3 0 4 4 3 5 0 "
697
+ },
698
+ {
699
+ "family": "undead",
700
+ "difficulty": "hard",
701
+ "filename": "undead_7x7dh_135444a8.txt",
702
+ "args": "7x7dh",
703
+ "problem": "G: 7 V: 18 Z: 5\n\n 5 4 0 0 6 5 2 \n 3 . . \\ / . . / 0\n 2 . . \\ . . . . 5\n 3 . \\ / . . . . 4\n 2 . . / \\ \\ . \\ 0\n 0 . . \\ / . \\ . 0\n 5 . . . / / . / 1\n 2 . . \\ \\ \\ . . 3\n 5 3 0 2 2 3 0 ",
704
+ "solution": "G: 7 V: 18 Z: 5\n\n 5 4 0 0 6 5 2 \n 3 Z V \\ / Z V / 0\n 2 G Z \\ V Z V V 5\n 3 V \\ / V V V V 4\n 2 V V / \\ \\ V \\ 0\n 0 G G \\ / G \\ G 0\n 5 V Z V / / V / 1\n 2 V V \\ \\ \\ G G 3\n 5 3 0 2 2 3 0 "
705
+ },
706
+ {
707
+ "family": "undead",
708
+ "difficulty": "hard",
709
+ "filename": "undead_7x7dh_62703468.txt",
710
+ "args": "7x7dh",
711
+ "problem": "G: 7 V: 16 Z: 5\n\n 0 2 5 1 2 4 0 \n 4 . . . . . . . 4\n 0 \\ / . . \\ . / 2\n 4 . . . / \\ / . 1\n 0 / . . / . / . 2\n 3 . . \\ \\ \\ \\ / 0\n 0 / / . . . \\ / 0\n 5 . . . . . / \\ 0\n 1 6 1 4 2 0 0 ",
712
+ "solution": "G: 7 V: 16 Z: 5\n\n 0 2 5 1 2 4 0 \n 4 G V Z G V V G 4\n 0 \\ / V G \\ V / 2\n 4 V V G / \\ / V 1\n 0 / V V / V / Z 2\n 3 V V \\ \\ \\ \\ / 0\n 0 / / V Z V \\ / 0\n 5 G Z G Z V / \\ 0\n 1 6 1 4 2 0 0 "
713
+ },
714
+ {
715
+ "family": "undead",
716
+ "difficulty": "hard",
717
+ "filename": "undead_7x7dh_2931ee4a.txt",
718
+ "args": "7x7dh",
719
+ "problem": "G: 11 V: 10 Z: 14\n\n 5 4 5 6 3 4 0 \n 5 . . . . . / \\ 0\n 5 . . . . . . . 5\n 6 . . . . . / \\ 5\n 0 . / . . \\ / \\ 3\n 4 . . . . . / . 2\n 6 . . . . / / . 0\n 6 / . . \\ . . \\ 5\n 0 8 5 0 0 2 4 ",
720
+ "solution": "G: 11 V: 10 Z: 14\n\n 5 4 5 6 3 4 0 \n 5 Z V Z Z Z / \\ 0\n 5 Z V Z V Z G G 5\n 6 Z V G V Z / \\ 5\n 0 G / Z Z \\ / \\ 3\n 4 Z G Z V G / V 2\n 6 Z G G G / / G 0\n 6 / V V \\ G V \\ 5\n 0 8 5 0 0 2 4 "
721
+ }
722
+ ]
frontend/test/pipeline/gen_fixtures.py ADDED
@@ -0,0 +1,66 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Pull reference solutions per (family, difficulty) from the topobench dataset.
3
+
4
+ Writes fixtures.json next to this script: a list of
5
+ {family, difficulty, filename, args, problem, solution}
6
+ used by the TS round-trip test and the Python verifier oracle.
7
+
8
+ Run with an env that has `datasets` installed (e.g. ~/base-venv).
9
+ """
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from collections import defaultdict
14
+ from pathlib import Path
15
+
16
+ from datasets import load_dataset
17
+
18
+ FAMILIES = ["bridges", "flow_free", "galaxies", "loopy", "pattern", "undead"]
19
+ DIFFICULTIES = ["easy", "medium", "hard"]
20
+ PER_COMBO = 5 # solutions per (family, difficulty)
21
+
22
+ OUT = Path(__file__).resolve().parent / "fixtures.json"
23
+
24
+
25
+ def main() -> None:
26
+ ds = load_dataset("topobench/topobench", split="test")
27
+ buckets: dict[tuple[str, str], list[dict]] = defaultdict(list)
28
+ for row in ds:
29
+ if "include" in row and not row["include"]:
30
+ continue
31
+ fam = row.get("puzzlename")
32
+ diff = row.get("difficulty")
33
+ if fam not in FAMILIES or diff not in DIFFICULTIES:
34
+ continue
35
+ if not row.get("solution") or not row.get("problem"):
36
+ continue
37
+ key = (fam, diff)
38
+ if len(buckets[key]) >= PER_COMBO:
39
+ continue
40
+ buckets[key].append(
41
+ {
42
+ "family": fam,
43
+ "difficulty": diff,
44
+ "filename": row.get("filename"),
45
+ "args": row.get("args"),
46
+ "problem": row["problem"],
47
+ "solution": row["solution"],
48
+ }
49
+ )
50
+
51
+ fixtures: list[dict] = []
52
+ for fam in FAMILIES:
53
+ for diff in DIFFICULTIES:
54
+ fixtures.extend(buckets[(fam, diff)])
55
+
56
+ OUT.write_text(json.dumps(fixtures, indent=1))
57
+ counts = {f"{fam}:{diff}": len(buckets[(fam, diff)]) for fam in FAMILIES for diff in DIFFICULTIES}
58
+ print(f"wrote {len(fixtures)} fixtures -> {OUT}")
59
+ for k, v in counts.items():
60
+ if v == 0:
61
+ print(f" WARNING: no puzzles for {k}")
62
+ print(json.dumps(counts, indent=1))
63
+
64
+
65
+ if __name__ == "__main__":
66
+ main()
frontend/test/pipeline/roundtrip.test.ts ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { readFileSync, writeFileSync } from "node:fs";
2
+ import { describe, it, expect } from "vitest";
3
+
4
+ import { __testables as T } from "../../src/components/PuzzleEditor";
5
+
6
+ type Fixture = {
7
+ family: string;
8
+ difficulty: string;
9
+ filename: string;
10
+ args: string;
11
+ problem: string;
12
+ solution: string;
13
+ };
14
+
15
+ const fixtures: Fixture[] = JSON.parse(
16
+ readFileSync(new URL("./fixtures.json", import.meta.url), "utf8"),
17
+ );
18
+
19
+ // Mirror exactly what each <Family>Editor.onChange emits: decode the board into
20
+ // editor state, then re-encode it. A correct editor round-trips a valid solution
21
+ // back to an equivalent valid board.
22
+ function reemit(family: string, problem: string, board: string): string {
23
+ switch (family) {
24
+ case "bridges":
25
+ return T.bridgesBoardFromStates(problem, T.bridgesStatesFromBoard(problem, board));
26
+ case "loopy":
27
+ return T.loopyBoardFromStates(problem, T.loopyEdgeStates(problem, board));
28
+ case "galaxies":
29
+ return T.galaxiesBoardFromStates(problem, T.galaxiesBoundaryStates(problem, board));
30
+ case "pattern":
31
+ return T.patternToAscii(T.parsePattern(board));
32
+ case "undead":
33
+ return T.undeadToAscii(T.parseUndead(board));
34
+ case "flow_free":
35
+ return T.joinGrid(T.cloneGrid(T.splitLines(board)));
36
+ default:
37
+ throw new Error(`unknown family ${family}`);
38
+ }
39
+ }
40
+
41
+ const rtrim = (s: string) =>
42
+ s
43
+ .replace(/\r/g, "")
44
+ .split("\n")
45
+ .map((l) => l.replace(/\s+$/, ""))
46
+ .join("\n")
47
+ .replace(/\n+$/, "");
48
+
49
+ // Compute round-trips once and persist them for the Python verifier-oracle step.
50
+ const results = fixtures.map((f) => ({
51
+ ...f,
52
+ roundtrip: reemit(f.family, f.problem, f.solution),
53
+ }));
54
+ writeFileSync(
55
+ new URL("./roundtrip_out.json", import.meta.url),
56
+ JSON.stringify(results, null, 1),
57
+ );
58
+
59
+ // Emit a click-plan for bridges so the Playwright e2e spec can replay the solution
60
+ // in the real UI without importing this React module into the e2e runner. Each entry
61
+ // is the ordered list of grid-button indices to click (repeated for double bridges).
62
+ const bridgesClickPlan: Record<string, number[]> = {};
63
+ for (const f of fixtures.filter((x) => x.family === "bridges")) {
64
+ const parsed = T.parseBridges(f.problem);
65
+ const target = T.bridgesStatesFromBoard(f.problem, f.solution);
66
+ const lineLens: number[] = parsed.lines.map((l: string) => l.length);
67
+ const indexOf = (r: number, c: number) =>
68
+ lineLens.slice(0, r).reduce((a: number, b: number) => a + b, 0) + c;
69
+ const clicks: number[] = [];
70
+ for (const opp of parsed.opportunities) {
71
+ const level = target[opp.id] ?? 0;
72
+ if (level === 0) continue;
73
+ const owned =
74
+ opp.cells.find(
75
+ ([r, c]: [number, number]) => parsed.cellToOpportunity.get(`${r}:${c}`)?.id === opp.id,
76
+ ) ?? opp.cells[0];
77
+ const idx = indexOf(owned[0], owned[1]);
78
+ for (let i = 0; i < level; i += 1) clicks.push(idx);
79
+ }
80
+ bridgesClickPlan[f.filename] = clicks;
81
+ }
82
+ writeFileSync(
83
+ new URL("./bridges_clickplan.json", import.meta.url),
84
+ JSON.stringify(bridgesClickPlan, null, 1),
85
+ );
86
+
87
+ const families = [...new Set(fixtures.map((f) => f.family))];
88
+
89
+ describe("editor round-trip preserves a valid solution (idempotency)", () => {
90
+ for (const family of families) {
91
+ it(`${family}: re-emitting the reference solution reproduces it`, () => {
92
+ const mismatches = results
93
+ .filter((r) => r.family === family)
94
+ .filter((r) => rtrim(r.roundtrip) !== rtrim(r.solution))
95
+ .map((r) => r.filename);
96
+ expect(mismatches, `mismatched puzzles: ${mismatches.join(", ")}`).toEqual([]);
97
+ });
98
+ }
99
+ });
frontend/test/pipeline/run.sh ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ # Full-pipeline puzzle test: dataset solutions -> editor encode/decode round-trip
3
+ # -> production verifier. Catches editor encode bugs (e.g. the bridges crossing-cell
4
+ # clobber) by proving every family's reference solution survives a round-trip through
5
+ # the real editor functions and still verifies SOLVED.
6
+ set -euo pipefail
7
+
8
+ HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ FRONTEND="$(cd "$HERE/../.." && pwd)"
10
+ PY="${PYTHON:-python3}"
11
+
12
+ echo "==> 1/3 generating dataset fixtures"
13
+ "$PY" "$HERE/gen_fixtures.py"
14
+
15
+ echo "==> 2/3 editor round-trip (vitest) + emit roundtrip_out.json"
16
+ ( cd "$FRONTEND" && npx vitest run test/pipeline/roundtrip.test.ts )
17
+
18
+ echo "==> 3/3 verifier oracle (production verifier on every round-tripped board)"
19
+ SDL_AUDIODRIVER=dummy SDL_VIDEODRIVER=dummy PYTHONWARNINGS=ignore "$PY" "$HERE/verify_oracle.py"
frontend/test/pipeline/verify_oracle.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Verifier-oracle step of the full-pipeline test.
3
+
4
+ Reads roundtrip_out.json (emitted by roundtrip.test.ts) and, using the REAL
5
+ production verification path (normalize_board_for_submission -> VerificationService.verify,
6
+ the exact pair the /submit handler calls), asserts for every fixture:
7
+
8
+ 1. the dataset reference SOLUTION verifies SOLVED (oracle sanity: verifier works per family)
9
+ 2. the editor ROUND-TRIPPED board verifies SOLVED (the real gate: editor didn't corrupt it)
10
+ 3. the empty PROBLEM board verifies NOT SOLVED (verifier isn't rubber-stamping)
11
+
12
+ Exit code 0 only if every assertion holds. Run with the same Python that can
13
+ import the rlp verifier (the Space image / a built rlp env).
14
+ """
15
+ from __future__ import annotations
16
+
17
+ import json
18
+ import sys
19
+ from collections import defaultdict
20
+ from pathlib import Path
21
+
22
+ REPO_ROOT = Path(__file__).resolve().parents[3]
23
+ sys.path.insert(0, str(REPO_ROOT))
24
+
25
+ from space_app.board_utils import normalize_board_for_submission # noqa: E402
26
+ from space_app.verification import VerificationService # noqa: E402
27
+
28
+ OUT = Path(__file__).resolve().parent / "roundtrip_out.json"
29
+
30
+
31
+ def verify(svc: VerificationService, family: str, problem: str, board: str, args: str) -> bool:
32
+ normalized = normalize_board_for_submission(
33
+ puzzle_type=family, problem_ascii=problem, board_ascii=board
34
+ )
35
+ result = svc.verify(
36
+ puzzle_type=family, problem_ascii=problem, board_ascii=normalized, args=args
37
+ )
38
+ return bool(result.get("correct"))
39
+
40
+
41
+ def main() -> int:
42
+ rows = json.loads(OUT.read_text())
43
+ svc = VerificationService()
44
+ fails: list[str] = []
45
+ neg_seen: set[str] = set()
46
+ neg_fail: list[str] = []
47
+ by_family: dict[str, dict[str, int]] = defaultdict(lambda: {"sol": 0, "rt": 0, "n": 0})
48
+
49
+ for r in rows:
50
+ fam, prob, args = r["family"], r["problem"], r["args"]
51
+ fn = r["filename"]
52
+ by_family[fam]["n"] += 1
53
+
54
+ if verify(svc, fam, prob, r["solution"], args):
55
+ by_family[fam]["sol"] += 1
56
+ else:
57
+ fails.append(f"[{fam}] reference SOLUTION did NOT verify: {fn}")
58
+
59
+ if verify(svc, fam, prob, r["roundtrip"], args):
60
+ by_family[fam]["rt"] += 1
61
+ else:
62
+ fails.append(f"[{fam}] ROUND-TRIP board did NOT verify: {fn}")
63
+
64
+ # one negative control per family: the empty problem must NOT verify solved
65
+ if fam not in neg_seen:
66
+ neg_seen.add(fam)
67
+ if verify(svc, fam, prob, prob, args):
68
+ neg_fail.append(f"[{fam}] empty PROBLEM wrongly verified SOLVED: {fn}")
69
+
70
+ print("family n sol_ok rt_ok")
71
+ for fam in sorted(by_family):
72
+ s = by_family[fam]
73
+ print(f"{fam:12s} {s['n']:2d} {s['sol']:3d} {s['rt']:3d}")
74
+
75
+ ok = True
76
+ if fails:
77
+ ok = False
78
+ print("\nFAILURES (solution/round-trip):")
79
+ for f in fails:
80
+ print(" " + f)
81
+ if neg_fail:
82
+ ok = False
83
+ print("\nFAILURES (negative control — verifier accepted an unsolved board):")
84
+ for f in neg_fail:
85
+ print(" " + f)
86
+ print("\n" + ("ALL VERIFIER-ORACLE CHECKS PASSED" if ok else "VERIFIER-ORACLE CHECKS FAILED"))
87
+ return 0 if ok else 1
88
+
89
+
90
+ if __name__ == "__main__":
91
+ raise SystemExit(main())