),\n \"screen uses the manufacturer-dimensioned GLB assembly rather than a generic slab\")\nassert.ok(nearly(screenCad.position.x, 40.8) \u0026\u0026 nearly(screenCad.position.y, 15),\n \"screen 3D model is anchored to J_LCD\")\nassert.ok(nearly(screenCad.rotation.z, 90),\n \"screen 3D model extends left from the right-side J_LCD cable-entry axis\")\n\nfor (const traceName of [\"SPK_POS_OUT\", \"SPK_NEG_OUT\"])\n assert.ok(of(\"source_trace\").some((trace) =\u003e trace.name === traceName),\n `J_SPK carries ${traceName} from the PAM8403 bridge output`)\n\nconst traces = of(\"pcb_trace\")\nassert.ok(traces.length \u003e= 250, \"dense routed design contains its expected copper traces\")\nassert.ok(!circuit.some((record) =\u003e /unrouted|trace_missing/i.test(record.type)), \"no unrouted/missing-trace records\")\n\nconst traceEndingWith = (suffix) =\u003e {\n const matches = traces.filter((trace) =\u003e trace.pcb_trace_id.endsWith(suffix))\n assert.equal(matches.length, 1, `one PCB trace ends with ${suffix}`)\n return matches[0]\n}\nconst assertMinimumWireWidth = (trace, width, label) =\u003e {\n const wireWidths = trace.route.filter((point) =\u003e point.route_type === \"wire\").map((point) =\u003e point.width)\n assert.ok(wireWidths.length \u003e 0 \u0026\u0026 wireWidths.every((actual) =\u003e actual \u003e= width - 1e-6),\n `${label} is physically routed at least ${width.toFixed(2)} mm wide`)\n}\nassertMinimumWireWidth(traceEndingWith(\"source_net_6_mst14_0\"), 0.5, \"buck output capacitor A link\")\nassertMinimumWireWidth(traceEndingWith(\"source_net_6_mst23_0\"), 0.5, \"buck output capacitor B link\")\nfor (const id of [\"source_trace_361_0\", \"source_trace_363_0\", \"source_trace_364_0\", \"source_trace_365_0\", \"source_trace_367_0\"])\n assertMinimumWireWidth(traces.find((trace) =\u003e trace.pcb_trace_id === id), 0.5, `${id} backlight power link`)\n\nconst batteryRangeText = of(\"pcb_silkscreen_text\").find((text) =\u003e text.text === \"4xAAA 4.8-6.4V\")\nassert.ok(batteryRangeText, \"battery silkscreen states the corrected 4.8-6.4 V input range\")\n\nconst report = {\n circuitPath,\n generatedAt: new Date().toISOString(),\n board: {\n title: \"F1C100S Linux Game Boy Advance\",\n widthMm: board.width,\n heightMm: board.height,\n copperLayers: board.num_layers,\n },\n routing: {\n pcbTraces: traces.length,\n pcbVias: vias.length,\n viaHoleDiameterMm: 0.3,\n viaPadDiameterMm: 0.45,\n minimumFinishedHoleGapMm: Number(minimumFinishedHoleGap.toFixed(6)),\n closestViaPair,\n reviewedViaHoleToCopperGapMm: Number(reviewedViaCopperGap.toFixed(3)),\n reviewedViaNearestTrace,\n buckOutputCapLinksMm: 0.5,\n backlightPowerLinksMm: 0.5,\n },\n mechanical: {\n batteryCableEdgeCut: {\n widthMm: Number((cutoutBounds.maxX - cutoutBounds.minX).toFixed(3)),\n overallLengthMm: Number((cutoutBounds.maxY - cutoutBounds.minY).toFixed(3)),\n depthIntoBoardMm: Number((cutoutBounds.maxY - boardBottomY).toFixed(3)),\n closedEnd: \"rounded\",\n },\n shoulderSwitches: \"TS66135ZJ 022 low-profile right-angle housing, 13.5 mm switch height, 9.6 mm board-edge stem protrusion\",\n bootHeader: {\n center: { x: -55, y: 23 },\n outsideLandscapeLcdEnvelope: true,\n },\n startSelectYmm: -19,\n microSdEdge: \"right recessed access bay\",\n microSdEdgeClearanceMm: Number(microSdEdgeClearanceMm.toFixed(3)),\n batteryConnectorFacesCutout: true,\n batteryCableBendCorridorMm: Number(batteryCableBendCorridorMm.toFixed(3)),\n powerSwitch: {\n center: { x: -61.5, y: -32.5 },\n side: \"lower-left, matching AGB-001 bottom control strip\",\n edgeRecessMm: Number(powerSwitchEdgeRecessMm.toFixed(3)),\n enclosureActuation: \"guarded slider\",\n },\n rearServiceConnectors: {\n uart: { center: { x: -18, y: 37 }, layer: \"bottom\", pinout: [\"RX\", \"GND\", \"TX\"] },\n i2c: { center: { x: -28, y: 37 }, layer: \"bottom\", pinout: [\"GND\", \"3V3\", \"SDA\", \"SCL\"] },\n spi: { center: { x: 22, y: 37 }, layer: \"bottom\", pinout: [\"GND\", \"3V3\", \"SCLK\", \"MOSI\", \"MISO\", \"CS\"] },\n },\n },\n display: {\n part: \"ER-TFT035IPS-6\",\n widthMm: 84.96,\n heightMm: 55.5,\n orientation: \"landscape\",\n fpcConnectorSide: \"right\",\n connectorRotationDeg: 270,\n assemblyModel: screenModelFile,\n backlightDriver: \"AP3031KTR-G1\",\n regulatedBacklightCurrentMa: lcdBacklightCurrentMa,\n },\n power: {\n labeledBatteryRangeV: [4.8, 6.4],\n },\n models: {\n f1c100s: \"C1511928\",\n spiFlash: \"C97521\",\n shoulderSwitch: \"C33543626\",\n screen: screenModelFile,\n fittedPartsWithRenderableModels: fitted.length - missingCadModels.length,\n missingRenderableModels: missingCadModels,\n },\n audio: {\n speakerConnector: \"J_SPK\",\n output: \"PAM8403 mono bridge SPK+/SPK- for an internal 4-8 ohm speaker\",\n },\n assembly: {\n fittedComponents: fitted.length,\n uniqueJlcpcbPartNumbers: uniqueJlcpcbParts.size,\n missingJlcpcbPartNumbers: missingJlcpcb,\n },\n controls: expectedButtons.length,\n errorsByType: {},\n emittedErrors: 0,\n}\n\nfs.writeFileSync(\"verification.json\", `${JSON.stringify(report, null, 2)}\\n`)\nconsole.log(JSON.stringify(report, null, 2))\n","content_mimetype":"text/javascript","created_at":"2026-10-02T20:01:10.165Z"}; window.SSR_PACKAGE_RELEASES = [{"package_release_id":"e6ac90a9-3da9-425f-8e8c-b3f0264e6a54","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.17","github_commit_sha":null,"is_locked":false,"is_latest":true,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-02T19:58:05.381Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-16753a3ae52a5c4043b237d776477bea","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"0ebf4f0e-702b-4de6-9b36-9914c21efc07","user_code_job_started_at":"2026-10-02T20:07:44.376Z","user_code_job_completed_at":"2026-10-02T20:37:45.660Z","user_code_job_error":{"message":"Build timed out before user code job was created after 30 minutes","error_code":"user_code_job_missing_timeout"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"86cece99-7ad0-4f19-9c25-9ff405152717","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.16","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-10-02T19:50:32.876Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-217f3485c1a5147f742a007926ded3da","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"eedbf6b4-b0fc-47f0-882c-8efb8c41a8e3","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.15","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-02T18:28:08.523Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-723d7a2a17d28773dbf27837cd619104","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eedbf6b4-b0fc-47f0-882c-8efb8c41a8e3\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eedbf6b4-b0fc-47f0-882c-8efb8c41a8e3\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=eedbf6b4-b0fc-47f0-882c-8efb8c41a8e3\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"1dedb5be-2b5c-4621-b3eb-525189c2a7f9","user_code_job_started_at":"2026-10-02T18:34:39.002Z","user_code_job_completed_at":"2026-10-02T18:48:03.404Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=5d1a3af44b756f3c5148173e86992895f814e7f62bbaccaff5ae3e947aeff95a","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"fe53dbb6-c20b-4002-a864-7d5ab00c970e","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.14","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-02T18:02:44.259Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-da0f9aa989edb179960972b3ad89072d","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"3b3faf20-0e99-4180-816f-3dd584081dfc","user_code_job_started_at":"2026-10-02T18:09:09.985Z","user_code_job_completed_at":"2026-10-02T18:24:34.006Z","user_code_job_error":{"message":"Your code failed to build (exit code 1), see build logs for the error details","error_code":"user_code_build_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=698ceadf4a86ce9892bae64ef38f8673ce88d1c3d1c684f5b18c2bd145e55941","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"7c801a2b-8d14-4926-9010-0260244d5f59","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.13","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-02T17:34:12.037Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-f83ca8b02febab32b5cb097bb01efcc8","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"f2f621e4-67c7-4689-9ee8-37c1a15d045d","user_code_job_started_at":"2026-10-02T17:42:16.301Z","user_code_job_completed_at":"2026-10-02T17:55:43.184Z","user_code_job_error":{"message":"Your code failed to build (exit code 1), see build logs for the error details","error_code":"user_code_build_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=9434143c0c90b6140561f347467928da829ac916c6a93cac5cfa9e2ec556bb72","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"d1878735-dbc7-4743-9c81-2e65b33d62ff","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.11","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T18:36:15.014Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-433342c1c8cf28bfdea0ec820aab1318","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d1878735-dbc7-4743-9c81-2e65b33d62ff\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d1878735-dbc7-4743-9c81-2e65b33d62ff\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=d1878735-dbc7-4743-9c81-2e65b33d62ff\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"4ebf010b-1cb3-4c67-a481-c679479e9e22","user_code_job_started_at":"2026-10-01T18:42:12.581Z","user_code_job_completed_at":"2026-10-01T18:50:36.908Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=7d998484307cfcd6c23d8fd4e44a80926ea957504fb7a6db5e9073943f12289b","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"8897ae51-2827-4dd6-b60a-1e3e165b5f42","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.10","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T17:23:14.912Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-c4ccbf59caae6a616c43d96e1e15e6ef","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8897ae51-2827-4dd6-b60a-1e3e165b5f42\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8897ae51-2827-4dd6-b60a-1e3e165b5f42\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8897ae51-2827-4dd6-b60a-1e3e165b5f42\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"a6ed638e-bf10-42e3-b89e-fd28ce309346","user_code_job_started_at":"2026-10-01T17:31:20.384Z","user_code_job_completed_at":"2026-10-01T17:44:37.474Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=2c02094c35e5a7a308b95f678789cc775646bf433d6ce8dbd2af4af428fcd3e5","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"8899c9c3-5374-4f95-864b-7a4b3499bd25","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.9","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T16:12:02.680Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-3567d66fdba9a5dfff22244ea3cd7133","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8899c9c3-5374-4f95-864b-7a4b3499bd25\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8899c9c3-5374-4f95-864b-7a4b3499bd25\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=8899c9c3-5374-4f95-864b-7a4b3499bd25\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"afd61352-3d4b-4014-a7ae-a405b8f55868","user_code_job_started_at":"2026-10-01T16:23:03.633Z","user_code_job_completed_at":"2026-10-01T16:31:04.811Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=2e680a8297c55a96f04e6d0bdfe61196d744613bd804ed4f00767d4f172cfc97","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"7373da57-b74f-4fd8-a919-7bba7737dfb5","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.8","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-10-01T16:04:32.170Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-32aac27e06230aa255923001453434b2","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"3279672d-3a8b-4317-b0cd-a5cccf903c40","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.7","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T15:58:18.076Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-a00f45b388955e32d6cb70564e3839f9","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=3279672d-3a8b-4317-b0cd-a5cccf903c40\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=3279672d-3a8b-4317-b0cd-a5cccf903c40\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=3279672d-3a8b-4317-b0cd-a5cccf903c40\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"08d6f3c5-af95-42bd-96ed-4b218073b00c","user_code_job_started_at":"2026-10-01T16:17:48.247Z","user_code_job_completed_at":"2026-10-01T16:27:53.246Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=fe38cf55776fc8863bf5adb7bbebde83786aa418b198d7c138031a28e0d26eec","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"b808114b-bc19-45f3-9e6a-24e97746eba9","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.6","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T12:56:42.250Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-5e3042a150f264ee035d0123d591dd5b","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b808114b-bc19-45f3-9e6a-24e97746eba9\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b808114b-bc19-45f3-9e6a-24e97746eba9\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=b808114b-bc19-45f3-9e6a-24e97746eba9\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"142b2528-472e-4539-9335-387046f4e220","user_code_job_started_at":"2026-10-01T12:58:26.879Z","user_code_job_completed_at":"2026-10-01T13:13:31.340Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=6260310164cf88f72941f587ccf2f6e307428a27f14905b472b893816af86636","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"e0e7c82a-fa30-4b22-9509-571e837fa3da","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.5","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T12:44:41.574Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-5bb9f279de90941350ce3ce6cdc86137","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"6a3ea5fe-6b20-49c4-b076-5ce4259e5cf9","user_code_job_started_at":"2026-10-01T12:46:26.747Z","user_code_job_completed_at":"2026-10-01T12:53:11.686Z","user_code_job_error":{"message":"There was an error running the job on our infrastructure, this is probably not your code, see build logs","error_code":"user_code_job_infrastructure_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=a728e33192916cd26ebfe7b502c9f0f9169a8385fa013dacf0ce32bbaaba99b0","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"067b260a-5ead-4ec1-bf8b-01d32d8a2cd0","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.4","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-10-01T05:33:08.319Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-c9120b413caa56972a3e5a3c269ebd3e","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"55b2a169-7ec7-4234-b348-fd3c9b3d2e11","user_code_job_started_at":"2026-10-01T12:00:11.697Z","user_code_job_completed_at":"2026-10-01T12:15:45.951Z","user_code_job_error":{"message":"There was an error running the job on our infrastructure, this is probably not your code, see build logs","error_code":"user_code_job_infrastructure_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=f748b78e6c3c6b868243fffc546187d2bd8852ff6593a75b3eb14b8d753e93a3","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"f307972c-5d9d-4a9b-b863-6350d0fa6068","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.3","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-30T23:12:37.573Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-725e3307ff585e7707fbb49e0f47e11a","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f307972c-5d9d-4a9b-b863-6350d0fa6068\u0026file_path=dist%2Findex%2Fpcb.svg","sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f307972c-5d9d-4a9b-b863-6350d0fa6068\u0026file_path=dist%2Findex%2Fschematic.svg","cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=f307972c-5d9d-4a9b-b863-6350d0fa6068\u0026file_path=dist%2Findex%2F3d.png","package_release_website_url":null,"display_status":"pending","latest_package_build_id":"8a2a2fe5-0831-4696-8e6b-b575a9718699","user_code_job_started_at":"2026-09-30T23:16:28.551Z","user_code_job_completed_at":"2026-09-30T23:26:42.816Z","user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=a05b23425ccf2f5b25f52f657529d001ec13f7e544edb0737616ddb7758f8bd0","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"6bf18fb2-52fc-48fc-b29a-3fab93bad7f7","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.2","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":true,"is_pr_preview":false,"created_at":"2026-09-30T23:09:28.400Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":true,"transpilation_display_status":"pending","fs_sha":"md5-9591b99390b49f037552f3da683fda5a","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":true,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":true,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":"7ffdbc40-dbba-47ef-b513-5bfdaf591439","user_code_job_started_at":"2026-09-30T23:12:47.396Z","user_code_job_completed_at":"2026-09-30T23:24:22.417Z","user_code_job_error":{"message":"Your code failed to build (exit code 1), see build logs for the error details","error_code":"user_code_build_error"},"user_code_job_completed_logs":null,"user_code_job_log_stream_url":"https://usercode.tscircuit.com/user_code_jobs/view_log_stream?user_code_job_id=46b62a4f5c64a5292fbb3b54efb077fa1eec5b488c878c6983adf014942460ad","ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"bee88c24-a984-4313-9d1a-19c787c59e3c","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.1","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-09-30T22:57:12.122Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-d7fd24fb40171142ac55779401985aaf","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null},{"package_release_id":"12fca4e0-38e0-4884-9108-c26c28368399","package_id":"8d33bdc3-aed3-402c-a597-4096ab10fff3","version":"1.0.0","github_commit_sha":null,"is_locked":false,"is_latest":false,"ready_to_build":false,"is_pr_preview":false,"created_at":"2026-09-30T22:56:15.338Z","circuit_json_build_error":null,"circuit_json_build_error_last_updated_at":null,"has_transpiled":false,"transpilation_error":null,"transpilation_logs":null,"transpilation_in_progress":false,"transpilation_started_at":null,"transpilation_completed_at":null,"transpilation_is_stale":false,"transpilation_display_status":"pending","fs_sha":"md5-3ff194afef1be5e147c4ced30c88a417","circuit_json_build_logs":null,"circuit_json_build_in_progress":false,"circuit_json_build_started_at":null,"circuit_json_build_completed_at":null,"circuit_json_build_is_stale":false,"circuit_json_build_display_status":"pending","image_generation_error":null,"image_generation_error_last_updated_at":null,"image_generation_logs":null,"image_generation_in_progress":false,"image_generation_started_at":null,"image_generation_completed_at":null,"image_generation_is_stale":false,"image_generation_display_status":"pending","pcb_preview_image_url":null,"sch_preview_image_url":null,"cad_preview_image_url":null,"package_release_website_url":null,"display_status":"pending","latest_package_build_id":null,"user_code_job_started_at":null,"user_code_job_completed_at":null,"user_code_job_error":null,"user_code_job_completed_logs":null,"user_code_job_log_stream_url":null,"ai_review_requested":false,"github_pr_number":null,"github_pr_title":null,"github_branch_name":null}]; window.SSR_PACKAGE_BUILDS = []; window.SSR_RELATED_PACKAGES = [{"package_id":"c2dbfdad-2a76-4754-bb78-450a1e66ccfd","creator_account_id":"63586009-ac32-446c-b5aa-a60ea81a44bf","latest_package_release_id":"2ec669f5-eeb3-4c19-8cbe-feee3641937e","last_built_release_id":"2ec669f5-eeb3-4c19-8cbe-feee3641937e","latest_package_release_fs_sha":"md5-ecf40c53611da146479dfffe616cf055","latest_pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2ec669f5-eeb3-4c19-8cbe-feee3641937e\u0026file_path=dist%2Findex%2Fpcb.svg","latest_sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2ec669f5-eeb3-4c19-8cbe-feee3641937e\u0026file_path=dist%2Findex%2Fschematic.svg","latest_cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=2ec669f5-eeb3-4c19-8cbe-feee3641937e\u0026file_path=dist%2Findex%2F3d.png","latest_version":"1.0.2","license":"unset","owner_org_id":"e4b51b30-273d-4e29-92ed-981078150dff","org_owner_tscircuit_handle":"ShiboSoftwareDev","owner_github_username":"ShiboSoftwareDev","github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"ShiboSoftwareDev/msp-exp430g2et","unscoped_name":"msp-exp430g2et","star_count":0,"created_at":"2026-08-14T18:11:52.880Z","updated_at":"2026-08-14T18:19:02.037Z","ai_description":"This circuit integrates a 4MHz crystal resonator, various resistors and capacitors for power management and filtering, a microcontroller (MSP430F5528), and multiple connectors and test points to enable USB communication, programming, and system monitoring with shielding and grounding.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"files","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"same_author","thumbnail_url":"https://api.tscircuit.com/package_files/view?package_release_id=2ec669f5-eeb3-4c19-8cbe-feee3641937e\u0026file_path=dist%2Findex%2Fpcb.svg"},{"package_id":"a3391bc2-7eab-4764-b0b7-4dfa274b65bf","creator_account_id":"1f745cb8-1b99-4215-905f-f8e3dc29bc28","latest_package_release_id":"1efa0e27-9630-45db-88d5-6a40c5019895","last_built_release_id":"1efa0e27-9630-45db-88d5-6a40c5019895","latest_package_release_fs_sha":"md5-622f9c9e7b3f16cbb007fdab81c8c5bb","latest_pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=1efa0e27-9630-45db-88d5-6a40c5019895\u0026file_path=dist%2Fevidence%2Ffirst-route%2Fraw%2Fpcb.svg","latest_sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=1efa0e27-9630-45db-88d5-6a40c5019895\u0026file_path=dist%2Fevidence%2Ffirst-route%2Fraw%2Fschematic.svg","latest_cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=1efa0e27-9630-45db-88d5-6a40c5019895\u0026file_path=dist%2Findex%2F3d.png","latest_version":"1.0.0","license":"unset","owner_org_id":"60917f07-d371-4c51-854f-e2bd7dab9e5a","org_owner_tscircuit_handle":"hrithik18k","owner_github_username":null,"github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"hrithik18k/metal-touch-panel","unscoped_name":"metal-touch-panel","star_count":0,"created_at":"2026-10-01T08:20:18.280Z","updated_at":"2026-10-01T08:26:23.796Z","ai_description":"A PCB autorouting wrapper that corrects footprint-trace obstacle dimensions, solves routes with a preloaded trace-graph solver, and reports completed traces or routing errors.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"files","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"similar_ai_description","thumbnail_url":"https://api.tscircuit.com/package_files/view?package_release_id=1efa0e27-9630-45db-88d5-6a40c5019895\u0026file_path=dist%2Fevidence%2Ffirst-route%2Fraw%2Fpcb.svg"},{"package_id":"ddf74268-ab6e-406e-b9a4-7c298f2c7cb5","creator_account_id":"013dcc15-6192-4e44-8812-fb27d760567f","latest_package_release_id":"adcc1289-d401-4200-91c3-905ed5de71fa","last_built_release_id":"adcc1289-d401-4200-91c3-905ed5de71fa","latest_package_release_fs_sha":"md5-dd220c8c53d20854351bb694a8fd9d0f","latest_pcb_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=adcc1289-d401-4200-91c3-905ed5de71fa\u0026file_path=dist%2Findex%2Fpcb.svg","latest_sch_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=adcc1289-d401-4200-91c3-905ed5de71fa\u0026file_path=dist%2Findex%2Fschematic.svg","latest_cad_preview_image_url":"https://api.tscircuit.com/package_files/view?package_release_id=adcc1289-d401-4200-91c3-905ed5de71fa\u0026file_path=dist%2Findex%2F3d.png","latest_version":"0.0.1","license":"unset","owner_org_id":"6b3a48f6-6cb3-49cf-b787-a976b7534f06","org_owner_tscircuit_handle":"pixalynx","owner_github_username":null,"github_repo_full_name":null,"is_source_from_github":false,"description":null,"name":"pixalynx/usb3-hub-10g","unscoped_name":"usb3-hub-10g","star_count":0,"created_at":"2026-09-30T02:28:17.771Z","updated_at":"2026-09-30T02:35:27.766Z","ai_description":"A USB 3.2 Gen 2 six-port hub board with USB-C PD power input, regulated 5 V/3.3 V/1.15 V rails, one upstream and four protected downstream USB-A/USB-C ports, SuperSpeed muxes, ESD protection, and controlled port power.","ai_usage_instructions":null,"is_private":false,"is_unlisted":false,"is_public":true,"public_dist_enabled":false,"has_public_dist":true,"starred_at":null,"default_view":"files","website":null,"github_installation_id":null,"allow_pr_previews":false,"related_type":"random","thumbnail_url":"https://api.tscircuit.com/package_files/view?package_release_id=adcc1289-d401-4200-91c3-905ed5de71fa\u0026file_path=dist%2Findex%2Fpcb.svg"}]; window.SSR_PACKAGE_ROUTE = {"author":"ShiboSoftwareDev","packageName":"linux-gameboy-advance","packageNameWithScope":"ShiboSoftwareDev/linux-gameboy-advance","version":null,"isLegacyRoute":false,"kind":"file","filePath":"scripts/verify.mjs"};
ShiboSoftwareDev/linux-gameboy-advance
Restores PCB assembly metadata by assigning part numbers and 3D CAD models, removing test-point bodies, and validating top-side SMT solder-paste features without altering copper or pads.
Version
1.0.17
License
unset
Stars
0
scripts/verify.mjs
import assert from "node:assert/strict"
import fs from "node:fs"
const circuitPath = "dist/index/circuit.json"
const circuit = JSON.parse(fs.readFileSync(circuitPath, "utf8"))
const of = (type) => circuit.filter((record) => record.type === type)
const nearly = (actual, expected, tolerance = 1e-6) =>
Math.abs(actual - expected) <= tolerance
const pointToSegmentDistance = (point, start, end) => {
const dx = end.x - start.x
const dy = end.y - start.y
const lengthSquared = dx * dx + dy * dy
const position = lengthSquared === 0 ? 0 : Math.max(0, Math.min(1,
((point.x - start.x) * dx + (point.y - start.y) * dy) / lengthSquared))
return Math.hypot(point.x - (start.x + position * dx), point.y - (start.y + position * dy))
}
const errors = circuit.filter((record) => record.type.endsWith("_error"))
assert.equal(errors.length, 0, `expected zero emitted DRC/electrical errors; got ${errors.length}`)
const board = of("pcb_board")[0]
assert.ok(board, "PCB board exists")
assert.equal(board.num_layers, 4, "four copper layers")
assert.ok(board.outline?.length >= 4, "custom board outline is present")
assert.ok(nearly(board.width, 144.5) && nearly(board.height, 82), "144.5 x 82 mm envelope")
assert.ok(nearly(board.min_via_hole_diameter, 0.3), "board via drill rule is 0.30 mm")
assert.ok(nearly(board.min_via_pad_diameter, 0.45), "board via pad rule is 0.45 mm")
assert.ok(nearly(board.min_via_hole_edge_to_via_hole_edge_clearance, 0.2), "finished-hole spacing rule is 0.20 mm")
const cutouts = of("pcb_cutout")
assert.equal(cutouts.length, 1, "one battery-cable edge cutout exists")
const batteryCableCutout = cutouts[0]
assert.equal(batteryCableCutout.shape, "polygon", "battery-cable cutout uses fabrication-safe outline geometry")
assert.ok(batteryCableCutout.points.length >= 15, "battery-cable cutout has a rounded closed end")
const cutoutXs = batteryCableCutout.points.map(({ x }) => x)
const cutoutYs = batteryCableCutout.points.map(({ y }) => y)
const cutoutBounds = {
minX: Math.min(...cutoutXs), maxX: Math.max(...cutoutXs),
minY: Math.min(...cutoutYs), maxY: Math.max(...cutoutYs),
}
assert.ok(nearly(cutoutBounds.maxX - cutoutBounds.minX, 5), "battery-cable cutout is 5 mm wide")
assert.ok(nearly(cutoutBounds.maxY - cutoutBounds.minY, 11), "battery-cable cutout is 11 mm long")
const boardBottomY = Math.min(...board.outline.map(({ y }) => y))
assert.ok(cutoutBounds.minY < boardBottomY && nearly(cutoutBounds.maxY - boardBottomY, 9.5),
"battery-cable cutout opens through the bottom edge and extends 9.5 mm into the PCB")
const vias = of("pcb_via")
assert.ok(vias.length > 0, "routed board contains vias")
for (const via of vias) {
assert.ok(nearly(via.hole_diameter, 0.3), `${via.pcb_via_id}: drill is exactly 0.30 mm`)
assert.ok(nearly(via.outer_diameter, 0.45), `${via.pcb_via_id}: pad is exactly 0.45 mm`)
}
let minimumFinishedHoleGap = Infinity
let closestViaPair = []
for (let index = 0; index < vias.length; index++) {
for (let other = index + 1; other < vias.length; other++) {
const a = vias[index]
const b = vias[other]
const centerDistance = Math.hypot(a.x - b.x, a.y - b.y)
const gap = centerDistance - a.hole_diameter / 2 - b.hole_diameter / 2
if (gap < minimumFinishedHoleGap) {
minimumFinishedHoleGap = gap
closestViaPair = [a.pcb_via_id, b.pcb_via_id]
}
}
}
assert.ok(minimumFinishedHoleGap >= 0.2 - 1e-6,
`minimum via finished-hole gap ${minimumFinishedHoleGap.toFixed(6)} mm is at least 0.20 mm`)
// Regression for the fabrication review's exact failure: the former via at
// (8.399, 11.013) had only 0.177 mm from its finished-hole edge to an inner2
// module trace. Its repaired position must retain JLCPCB's 0.20 mm minimum.
const reviewedVia = vias.find((via) => via.pcb_via_id === "pcb_via_385")
assert.ok(reviewedVia, "reviewed V3V3 transition via exists")
let reviewedViaCopperGap = Infinity
let reviewedViaNearestTrace = null
for (const trace of of("pcb_trace")) {
if (trace.pcb_trace_id === reviewedVia.pcb_trace_id ||
trace.subcircuit_connectivity_map_key === reviewedVia.subcircuit_connectivity_map_key) continue
for (let index = 1; index < (trace.route?.length ?? 0); index++) {
const start = trace.route[index - 1]
const end = trace.route[index]
if (start.route_type !== "wire" || end.route_type !== "wire") continue
const gap = pointToSegmentDistance(reviewedVia, start, end) -
reviewedVia.hole_diameter / 2 - Math.max(start.width, end.width) / 2
if (gap < reviewedViaCopperGap) {
reviewedViaCopperGap = gap
reviewedViaNearestTrace = trace.pcb_trace_id
}
}
}
assert.ok(reviewedViaCopperGap >= 0.2 - 1e-6,
`reviewed via finished-hole-to-copper gap ${reviewedViaCopperGap.toFixed(3)} mm is at least 0.20 mm`)
const sourceComponents = of("source_component")
const sourceById = new Map(sourceComponents.map((component) => [component.source_component_id, component]))
const pcbComponents = of("pcb_component")
const fitted = pcbComponents
.map((pcb) => ({ pcb, source: sourceById.get(pcb.source_component_id) }))
.filter(({ pcb, source }) => source && !pcb.do_not_place && source.ftype !== "simple_test_point")
const missingJlcpcb = fitted
.filter(({ source }) => !source.supplier_part_numbers?.jlcpcb?.some((id) => /^C\d+$/.test(id)))
.map(({ source }) => source.name)
assert.deepEqual(missingJlcpcb, [], `all fitted parts have explicit JLCPCB/LCSC IDs: ${missingJlcpcb.join(", ")}`)
const uniqueJlcpcbParts = new Set(fitted.flatMap(({ source }) => source.supplier_part_numbers.jlcpcb))
const componentByName = new Map(sourceComponents.map((component) => [component.name, component]))
const pcbByName = new Map(pcbComponents.map((pcb) => [sourceById.get(pcb.source_component_id)?.name, pcb]))
const cadByName = new Map(of("cad_component").map((cad) => [sourceById.get(cad.source_component_id)?.name, cad]))
for (const name of [
"U1", "J_LCD", "J_SD", "U_FLASH", "U_IO", "J_USB", "J_BAT",
"U_BUCK_3V3", "U_2V5", "U_1V2", "U_2V8", "U_SPK_AMP", "J_SPK",
"J_UART", "J_I2C", "J_SPI",
"U_LCD_BL", "L_LCD_BL", "D_LCD_BL", "C_LCD_BL_IN", "C_LCD_BL_OUT",
"R_LCD_BL_SET_A", "R_LCD_BL_SET_B",
]) assert.ok(componentByName.has(name), `critical component ${name} exists`)
const hasRenderableCad = (cad) => Boolean(cad && (
cad.model_step_url || cad.model_obj_url || cad.jscad || cad.footprinter_string
)) && !cad.show_as_bounding_box
const missingCadModels = fitted
.filter(({ source }) => !hasRenderableCad(cadByName.get(source.name)))
.map(({ source }) => source.name)
assert.deepEqual(missingCadModels, [],
`every fitted PCB part has a renderable non-placeholder 3D model: ${missingCadModels.join(", ")}`)
assert.equal(componentByName.get("U_LCD_BL").manufacturer_part_number, "AP3031KTR-G1",
"LCD uses a regulated AP3031 boost/current driver")
assert.deepEqual(componentByName.get("U_LCD_BL").supplier_part_numbers.jlcpcb, ["C82636"],
"LCD current driver has an explicit JLCPCB part")
assert.deepEqual(componentByName.get("L_LCD_BL").supplier_part_numbers.jlcpcb, ["C2997603"],
"LCD boost inductor has an explicit JLCPCB part")
assert.deepEqual(componentByName.get("D_LCD_BL").supplier_part_numbers.jlcpcb, ["C5444012"],
"LCD boost diode has an explicit JLCPCB part")
for (const name of ["R_LCD_BL_SET_A", "R_LCD_BL_SET_B"]) {
assert.ok(nearly(componentByName.get(name).resistance, 1), `${name} is 1 ohm`)
assert.deepEqual(componentByName.get(name).supplier_part_numbers.jlcpcb, ["C17928"],
`${name} has an explicit JLCPCB part`)
assert.equal(pcbByName.get(name).layer, "bottom", `${name} is on the bottom side`)
}
const lcdBacklightCurrentMa = 0.2 / (1 + 1) * 1000
assert.ok(nearly(lcdBacklightCurrentMa, 100), "AP3031 sense network regulates the LCD backlight to 100 mA")
const expectedButtons = ["UP", "DOWN", "LEFT", "RIGHT", "A", "B", "X", "Y", "SELECT", "START", "L", "R"]
for (const label of expectedButtons)
assert.ok(componentByName.has(`SW_${label}`), `${label} control exists`)
assert.equal(sourceComponents.filter((component) => component.name?.startsWith("SW_")).length, 13,
"twelve game controls plus reset switch")
const placement = (name, x, y, rotation) => {
const pcb = pcbByName.get(name)
assert.ok(pcb, `${name} has a PCB placement`)
assert.ok(nearly(pcb.center.x, x) && nearly(pcb.center.y, y), `${name} placement is ${x}, ${y}`)
assert.ok(nearly(pcb.rotation, rotation), `${name} rotation is ${rotation} degrees`)
}
placement("SW_SELECT", -52, -19, 0)
placement("SW_START", 52, -19, 0)
for (const name of ["SW_SELECT", "SW_START"])
assert.deepEqual(componentByName.get(name).supplier_part_numbers.jlcpcb, ["C18186519"],
`${name} uses the same long-plunger JLC button as the reference Game Boy`)
placement("SW_L", -45, 36.65593325, 0)
placement("SW_R", 45, 36.65593325, 0)
for (const name of ["SW_L", "SW_R"]) {
assert.deepEqual(componentByName.get(name).supplier_part_numbers.jlcpcb, ["C33543626"],
`${name} is the long-stem variant of the original low-profile shoulder-switch family`)
assert.match(cadByName.get(name)?.model_step_url ?? "", /C33543626\.step/,
`${name} has the real JLC 3D model`)
}
const shoulderBoardEdgeY = 41
const shoulderBodyEdgeY = 36.65593325 + 4.34406675
const shoulderActuatorTipY = 36.65593325 + 13.95999875
assert.ok(Math.abs(shoulderBodyEdgeY - shoulderBoardEdgeY) < 0.01,
"shoulder switch housings finish flush with the top board edge")
assert.ok(shoulderActuatorTipY - shoulderBoardEdgeY >= 9.6 - 1e-6,
"shoulder actuators extend at least 9.6 mm beyond the top board edge")
placement("J_LCD", 40.8, 15, 270)
placement("J_SD", 58.5, 22, 90)
placement("JP_BOOT", -55, 23, 0)
placement("J_BAT", -40, -37.4, 270)
placement("J_PWR_SW", -61.5, -32.5, 270)
placement("J_UART", -18, 37, 180)
placement("J_I2C", -28, 37, 180)
placement("J_SPI", 22, 37, 180)
for (const name of ["J_UART", "J_I2C", "J_SPI"])
assert.equal(pcbByName.get(name).layer, "bottom", `${name} is on the bottom-side rear service edge`)
const microSdBayEdgeX = board.outline
.filter(({ x, y }) => x > 0 && y >= 12 && y <= 30)
.reduce((nearest, { x }) => Math.min(nearest, x), Infinity)
const microSdFootprintRightX = pcbByName.get("J_SD").center.x + pcbByName.get("J_SD").width / 2
const microSdEdgeClearanceMm = microSdBayEdgeX - microSdFootprintRightX
assert.ok(nearly(microSdBayEdgeX, 65), "microSD access bay pulls the right PCB edge in to x=65 mm")
assert.ok(microSdEdgeClearanceMm >= 0.3 && microSdEdgeClearanceMm <= 0.5,
"microSD socket is within 0.3-0.5 mm of its recessed board edge")
const powerFootprintBottomY = pcbByName.get("J_PWR_SW").center.y - pcbByName.get("J_PWR_SW").height / 2
const powerSwitchEdgeRecessMm = powerFootprintBottomY - boardBottomY
assert.ok(powerSwitchEdgeRecessMm >= 7,
"power switch is recessed behind the lower-left enclosure wall instead of being directly exposed")
assert.ok(Math.abs(pcbByName.get("J_BAT").center.y - boardBottomY) < 5,
"battery connector is beside the bottom cable cutout")
const landscapePanelHalfWidthMm = 84.96 / 2
const bootHeaderRightEdge = pcbByName.get("JP_BOOT").center.x + pcbByName.get("JP_BOOT").width / 2
assert.ok(bootHeaderRightEdge < -landscapePanelHalfWidthMm,
"boot header is fully outside the landscape LCD module envelope")
const batteryConnectorCourtyardRightX = pcbByName.get("J_BAT").center.x + 6.5492
const batteryCableBendCorridorMm = cutoutBounds.minX - batteryConnectorCourtyardRightX
assert.ok(batteryCableBendCorridorMm >= 5.9,
"battery connector leaves at least 5.9 mm for the cable to bend before the cutout")
assert.match(cadByName.get("U1")?.model_step_url ?? "", /C1511928\.step/,
"F1C100S uses the real JLC 3D model")
assert.match(cadByName.get("U_FLASH")?.model_step_url ?? "", /C97521\.step/,
"SPI flash uses the real JLC 3D model")
assert.equal(cadByName.get("U1")?.show_as_bounding_box, undefined, "F1C100S is not a placeholder box")
assert.equal(cadByName.get("U_FLASH")?.show_as_bounding_box, undefined, "SPI flash is not a placeholder box")
const screenComponent = componentByName.get("ER_TFT035IPS_6")
const screenCad = cadByName.get("ER_TFT035IPS_6")
const screenModelFile = "er-tft035ips-6-realistic.glb"
assert.ok(screenComponent, "ER-TFT035IPS-6 assembly screen exists")
assert.ok(screenCad, "ER-TFT035IPS-6 has a 3D assembly model")
assert.match(screenCad.model_glb_url ?? "", new RegExp(`${screenModelFile}$`),
"screen uses the manufacturer-dimensioned GLB assembly rather than a generic slab")
assert.ok(nearly(screenCad.position.x, 40.8) && nearly(screenCad.position.y, 15),
"screen 3D model is anchored to J_LCD")
assert.ok(nearly(screenCad.rotation.z, 90),
"screen 3D model extends left from the right-side J_LCD cable-entry axis")
for (const traceName of ["SPK_POS_OUT", "SPK_NEG_OUT"])
assert.ok(of("source_trace").some((trace) => trace.name === traceName),
`J_SPK carries ${traceName} from the PAM8403 bridge output`)
const traces = of("pcb_trace")
assert.ok(traces.length >= 250, "dense routed design contains its expected copper traces")
assert.ok(!circuit.some((record) => /unrouted|trace_missing/i.test(record.type)), "no unrouted/missing-trace records")
const traceEndingWith = (suffix) => {
const matches = traces.filter((trace) => trace.pcb_trace_id.endsWith(suffix))
assert.equal(matches.length, 1, `one PCB trace ends with ${suffix}`)
return matches[0]
}
const assertMinimumWireWidth = (trace, width, label) => {
const wireWidths = trace.route.filter((point) => point.route_type === "wire").map((point) => point.width)
assert.ok(wireWidths.length > 0 && wireWidths.every((actual) => actual >= width - 1e-6),
`${label} is physically routed at least ${width.toFixed(2)} mm wide`)
}
assertMinimumWireWidth(traceEndingWith("source_net_6_mst14_0"), 0.5, "buck output capacitor A link")
assertMinimumWireWidth(traceEndingWith("source_net_6_mst23_0"), 0.5, "buck output capacitor B link")
for (const id of ["source_trace_361_0", "source_trace_363_0", "source_trace_364_0", "source_trace_365_0", "source_trace_367_0"])
assertMinimumWireWidth(traces.find((trace) => trace.pcb_trace_id === id), 0.5, `${id} backlight power link`)
const batteryRangeText = of("pcb_silkscreen_text").find((text) => text.text === "4xAAA 4.8-6.4V")
assert.ok(batteryRangeText, "battery silkscreen states the corrected 4.8-6.4 V input range")
const report = {
circuitPath,
generatedAt: new Date().toISOString(),
board: {
title: "F1C100S Linux Game Boy Advance",
widthMm: board.width,
heightMm: board.height,
copperLayers: board.num_layers,
},
routing: {
pcbTraces: traces.length,
pcbVias: vias.length,
viaHoleDiameterMm: 0.3,
viaPadDiameterMm: 0.45,
minimumFinishedHoleGapMm: Number(minimumFinishedHoleGap.toFixed(6)),
closestViaPair,
reviewedViaHoleToCopperGapMm: Number(reviewedViaCopperGap.toFixed(3)),
reviewedViaNearestTrace,
buckOutputCapLinksMm: 0.5,
backlightPowerLinksMm: 0.5,
},
mechanical: {
batteryCableEdgeCut: {
widthMm: Number((cutoutBounds.maxX - cutoutBounds.minX).toFixed(3)),
overallLengthMm: Number((cutoutBounds.maxY - cutoutBounds.minY).toFixed(3)),
depthIntoBoardMm: Number((cutoutBounds.maxY - boardBottomY).toFixed(3)),
closedEnd: "rounded",
},
shoulderSwitches: "TS66135ZJ 022 low-profile right-angle housing, 13.5 mm switch height, 9.6 mm board-edge stem protrusion",
bootHeader: {
center: { x: -55, y: 23 },
outsideLandscapeLcdEnvelope: true,
},
startSelectYmm: -19,
microSdEdge: "right recessed access bay",
microSdEdgeClearanceMm: Number(microSdEdgeClearanceMm.toFixed(3)),
batteryConnectorFacesCutout: true,
batteryCableBendCorridorMm: Number(batteryCableBendCorridorMm.toFixed(3)),
powerSwitch: {
center: { x: -61.5, y: -32.5 },
side: "lower-left, matching AGB-001 bottom control strip",
edgeRecessMm: Number(powerSwitchEdgeRecessMm.toFixed(3)),
enclosureActuation: "guarded slider",
},
rearServiceConnectors: {
uart: { center: { x: -18, y: 37 }, layer: "bottom", pinout: ["RX", "GND", "TX"] },
i2c: { center: { x: -28, y: 37 }, layer: "bottom", pinout: ["GND", "3V3", "SDA", "SCL"] },
spi: { center: { x: 22, y: 37 }, layer: "bottom", pinout: ["GND", "3V3", "SCLK", "MOSI", "MISO", "CS"] },
},
},
display: {
part: "ER-TFT035IPS-6",
widthMm: 84.96,
heightMm: 55.5,
orientation: "landscape",
fpcConnectorSide: "right",
connectorRotationDeg: 270,
assemblyModel: screenModelFile,
backlightDriver: "AP3031KTR-G1",
regulatedBacklightCurrentMa: lcdBacklightCurrentMa,
},
power: {
labeledBatteryRangeV: [4.8, 6.4],
},
models: {
f1c100s: "C1511928",
spiFlash: "C97521",
shoulderSwitch: "C33543626",
screen: screenModelFile,
fittedPartsWithRenderableModels: fitted.length - missingCadModels.length,
missingRenderableModels: missingCadModels,
},
audio: {
speakerConnector: "J_SPK",
output: "PAM8403 mono bridge SPK+/SPK- for an internal 4-8 ohm speaker",
},
assembly: {
fittedComponents: fitted.length,
uniqueJlcpcbPartNumbers: uniqueJlcpcbParts.size,
missingJlcpcbPartNumbers: missingJlcpcb,
},
controls: expectedButtons.length,
errorsByType: {},
emittedErrors: 0,
}
fs.writeFileSync("verification.json", `${JSON.stringify(report, null, 2)}\n`)
console.log(JSON.stringify(report, null, 2))