From 29e58430b21d132d242ac2c11c7a56b136da7c1d Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 11:43:33 +0000 Subject: [PATCH 1/4] =?UTF-8?q?=EC=8B=9C=EC=9E=91=20=E2=80=94=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC=EB=A5=BC=20=EC=8B=9C=EC=9E=91=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EC=A0=84=20=EB=A0=88=ED=8F=AC=EC=9D=98=20=EC=B6=9C=EB=B0=9C?= =?UTF-8?q?=EC=A0=90(=EC=8B=9C=ED=97=98=20=EA=B2=B0=EA=B3=BC=C2=B7?= =?UTF-8?q?=EB=AC=B8=EC=84=9C=20=EC=A7=80=EB=8F=84)=EC=9D=84=20=EA=B8=B0?= =?UTF-8?q?=EB=A1=9D=ED=95=B4=20=EB=91=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014L3ZRG6hS4BH2Q8YQjhzS5 From 9c82f1c234a909ded8b08ad644cf0032f10f955a Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 11:53:56 +0000 Subject: [PATCH 2/4] web: add doc-map, every link into the repository and whether it lands A file move breaks links that no build checks; the cleanup maps them first. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014L3ZRG6hS4BH2Q8YQjhzS5 --- docs/investigations/2026-10-doc-map.csv | 1001 +++++++++++++++++++++++ web/package.json | 3 +- web/scripts/doc-map.ts | 216 +++++ 3 files changed, 1219 insertions(+), 1 deletion(-) create mode 100644 docs/investigations/2026-10-doc-map.csv create mode 100644 web/scripts/doc-map.ts diff --git a/docs/investigations/2026-10-doc-map.csv b/docs/investigations/2026-10-doc-map.csv new file mode 100644 index 000000000..4e5b43cd4 --- /dev/null +++ b/docs/investigations/2026-10-doc-map.csv @@ -0,0 +1,1001 @@ +from,to,kind,anchor,resolves +.github/PULL_REQUEST_TEMPLATE.md,CONTRIBUTING.md,absolute-blob,where-your-contribution-goes,yes +AGENTS.md,docs/EDITIONS.md,relative,,yes +AUDIO_GUIDE.md,/editions,site,,yes +AUDIO_GUIDE.md,/guide/audio,site,,yes +AUDIO_GUIDE.md,AGENTS.md,relative,hard-rules-do-not-violate,yes +AUDIO_GUIDE.md,BUILD_GUIDE.md,relative,8-firmware,yes +AUDIO_GUIDE.md,CONTRIBUTING.md,relative,,yes +AUDIO_GUIDE.md,FEATURE_GUIDE.md,relative,,yes +AUDIO_GUIDE.md,docs/audio-ws-spec.md,relative,,yes +AUDIO_GUIDE.md,docs/director-midi.md,relative,,yes +AUDIO_GUIDE.md,docs/images/audio-guide/pdm-mic-wiring.jpg,relative,,yes +AUDIO_GUIDE.md,docs/midi-ableton.md,relative,,yes +AUDIO_GUIDE.md,docs/midi-spec.md,relative,,yes +AUDIO_GUIDE.md,docs/osc-spec.md,relative,,yes +AUDIO_GUIDE.md,docs/rest-api.md,relative,,yes +AUDIO_GUIDE.md,docs/rest-api.md,relative,microphone-audio-edition,yes +AUDIO_GUIDE.md,firmware/patternflow/console/README.md,relative,the-page-that-is-assembled-audio-in,yes +AUDIO_GUIDE.md,firmware/patternflow/features/audio,relative,,yes +AUDIO_GUIDE.md,firmware/patternflow/features/audio_in,relative,,yes +AUDIO_GUIDE.md,firmware/patternflow/features/midi,relative,,yes +AUDIO_GUIDE.md,integrations/ableton,relative,,yes +AUDIO_GUIDE.md,tools/patternflow-audio-android,relative,,yes +AUDIO_GUIDE.md,tools/patternflow-audio-android/README.md,relative,,yes +AUDIO_GUIDE.md,tools/patternflow-audio-extension,relative,,yes +AUDIO_GUIDE.md,tools/patternflow-audio-extension/README.md,relative,,yes +BUILD_GUIDE.md,/,site,,yes +BUILD_GUIDE.md,/editions,site,,yes +BUILD_GUIDE.md,/guide/build,site,,yes +BUILD_GUIDE.md,/guide/play,site,,yes +BUILD_GUIDE.md,/guide/play,site,flash,yes +BUILD_GUIDE.md,/guide/play,site,patterns,yes +BUILD_GUIDE.md,BUILD_GUIDE_v2.md,relative,,yes +BUILD_GUIDE.md,PATTERN_GUIDE.md,relative,,yes +BUILD_GUIDE.md,docs/EDITIONS.md,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/esp32_insert.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/01_printing.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/02_printed_parts.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/03_glue_mount.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/04_seam_gap.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/06_usbc_bad.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/07_usbc_good.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/16_power_path_compare.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/v3/17_screw_terminal_wiring.jpg,relative,,yes +BUILD_GUIDE.md,docs/build-guide/images/web_flash.jpg,relative,,yes +BUILD_GUIDE.md,docs/midi-ableton.md,relative,,yes +BUILD_GUIDE.md,docs/panel-compatibility.md,relative,,yes +BUILD_GUIDE.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +BUILD_GUIDE.md,firmware/README.md,relative,,yes +BUILD_GUIDE.md,hardware/bom/README.md,relative,,yes +BUILD_GUIDE.md,hardware/bom/bom_v3.0.csv,relative,,yes +BUILD_GUIDE.md,hardware/bom/bom_v3.9.csv,relative,,yes +BUILD_GUIDE.md,hardware/case,relative,,yes +BUILD_GUIDE.md,hardware/case/bed_256mm/patternflow_v3.3mf,relative,,yes +BUILD_GUIDE.md,hardware/case/remixes/besoiobiy-printed/README.md,relative,,yes +BUILD_GUIDE.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +BUILD_GUIDE.md,integrations/ableton,relative,,yes +BUILD_GUIDE_v2.md,/,site,,yes +BUILD_GUIDE_v2.md,/build/breadboard,site,,yes +BUILD_GUIDE_v2.md,BUILD_GUIDE.md,relative,,yes +BUILD_GUIDE_v2.md,BUILD_GUIDE.md,relative,6-case-assembly,yes +BUILD_GUIDE_v2.md,docs/assembly/README.md,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/all_parts.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/back_cover.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/case_bond.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/divider_bond.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/encoder_back_correct.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/encoder_front_wrong.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/encoder_nut.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/esp32_insert.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/first_boot.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/knobs.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/matrix_bump_cut1.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/matrix_bump_cut2.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/matrix_screw.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/parts_layout.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/pcb_assembly_setup.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/pcb_insert.webm,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/pcb_inserted.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/pcb_left_screw.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/pcb_slider.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/power_wire_measure.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/usb_wire_cut.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/build-guide/images/web_flash.jpg,relative,,yes +BUILD_GUIDE_v2.md,docs/panel-compatibility.md,relative,,yes +BUILD_GUIDE_v2.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +BUILD_GUIDE_v2.md,firmware/README.md,relative,required-board-package,yes +BUILD_GUIDE_v2.md,firmware/patternflow/config.h,relative,,yes +BUILD_GUIDE_v2.md,hardware/case/legacy_v2/encloser_v2.1.stl,relative,,yes +BUILD_GUIDE_v2.md,hardware/pcb/gerber,relative,,yes +BUILD_GUIDE_v2.md,v2.1.0:hardware/case,absolute-blob,,yes +CHANGELOG.md,/guide,site,,yes +CHANGELOG.md,/guide/build,site,,yes +CHANGELOG.md,/guide/make,site,,yes +CHANGELOG.md,/guide/play,site,,yes +CHANGELOG.md,/panel-tuner.html,site,,yes +CHANGELOG.md,/roadmap,site,,yes +CHANGELOG.md,/update,site,,yes +CHANGELOG.md,/variants,site,,yes +CHANGELOG.md,BUILD_GUIDE.md,relative,,yes +CHANGELOG.md,docs/investigations/2026-08-core2-heap-and-the-5s-stall.md,relative,,yes +CHANGELOG.md,docs/investigations/2026-08-the-panel-clock-and-the-wifi-radio.md,relative,,yes +CHANGELOG.md,docs/investigations/2026-09-firmware-runtime.md,relative,,yes +CHANGELOG.md,docs/panel-compatibility.md,relative,,yes +CHANGELOG.md,docs/pfst-v2-spec.md,relative,,yes +CODE_OF_CONDUCT.md,SECURITY.md,relative,,yes +CODE_OF_CONDUCT.md,docs/manifesto.md,relative,6-how-we-treat-each-other,yes +CONTRIBUTING.md,/guide,site,,yes +CONTRIBUTING.md,/inside,site,,yes +CONTRIBUTING.md,/pattern-lab,site,,yes +CONTRIBUTING.md,AGENTS.md,relative,hard-rules-do-not-violate,yes +CONTRIBUTING.md,CODE_OF_CONDUCT.md,relative,,yes +CONTRIBUTING.md,FEATURE_GUIDE.md,relative,,yes +CONTRIBUTING.md,LICENSE-CC-BY-SA,relative,,yes +CONTRIBUTING.md,LICENSE-MIT,relative,,yes +CONTRIBUTING.md,PATTERN_GUIDE.md,relative,,yes +CONTRIBUTING.md,SUPPORT.md,relative,,yes +CONTRIBUTING.md,docs/EDITIONS.md,relative,,yes +CONTRIBUTING.md,docs/LICENSE-SUMMARY.md,relative,,yes +CONTRIBUTING.md,docs/RELEASING.md,relative,,yes +CONTRIBUTING.md,docs/REPOSITORY.md,relative,,yes +CONTRIBUTING.md,docs/audio-ws-spec.md,relative,,yes +CONTRIBUTING.md,docs/midi-spec.md,relative,,yes +CONTRIBUTING.md,docs/mqtt-spec.md,relative,,yes +CONTRIBUTING.md,docs/osc-spec.md,relative,,yes +CONTRIBUTING.md,docs/pfst-v2-spec.md,relative,,yes +CONTRIBUTING.md,docs/rest-api.md,relative,,yes +CONTRIBUTING.md,firmware/bundles/README.md,relative,,yes +CONTRIBUTING.md,firmware/patternflow/features/README.md,relative,,yes +CONTRIBUTING.md,web/ARCHITECTURE.md,relative,,yes +CONTRIBUTING.md,web/README.md,relative,,yes +CONTRIBUTING.md,web/src/components/sections/InsideGlobe/builds.ts,relative,,yes +FEATURE_GUIDE.md,.github/workflows/console-sync.yml,relative,,yes +FEATURE_GUIDE.md,.github/workflows/firmware-build.yml,relative,,yes +FEATURE_GUIDE.md,.github/workflows/firmware-checks.yml,relative,,yes +FEATURE_GUIDE.md,AGENTS.md,relative,hard-rules-do-not-violate,yes +FEATURE_GUIDE.md,CONTRIBUTING.md,relative,,yes +FEATURE_GUIDE.md,docs/EDITIONS.md,relative,,yes +FEATURE_GUIDE.md,docs/audio-ws-spec.md,relative,,yes +FEATURE_GUIDE.md,docs/midi-spec.md,relative,,yes +FEATURE_GUIDE.md,firmware/bundles/README.md,relative,,yes +FEATURE_GUIDE.md,firmware/bundles/audio,relative,,yes +FEATURE_GUIDE.md,firmware/patternflow/features/README.md,relative,,yes +FEATURE_GUIDE.md,firmware/patternflow/features/audio_in,relative,,yes +FEATURE_GUIDE.md,firmware/patternflow/features/osc,relative,,yes +FEATURE_GUIDE.md,firmware/patternflow/features/show,relative,,yes +PATTERN_GUIDE.md,/community,site,,yes +PATTERN_GUIDE.md,/guide/make,site,,yes +PATTERN_GUIDE.md,/guide/play,site,flash,yes +PATTERN_GUIDE.md,/pattern,site,,yes +PATTERN_GUIDE.md,/update,site,,yes +PATTERN_GUIDE.md,BUILD_GUIDE.md,relative,,yes +PATTERN_GUIDE.md,BUILD_GUIDE.md,relative,8-firmware,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/01-landing-to-community.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/02-community-home.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/03-the-wall.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/04-card-hover-knobs.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/05-deck.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/06-send-to-my-board.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/07-modules-built.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/08-device-patterns-page.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/09-delete-modules.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/10-pattern-detail.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/11-pattern-lab.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/12-resolution.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/13-color-ramp.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/14-share-to-hardware.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/15-convert-header.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/16-on-to-hardware.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/17-send-over-wifi.png,relative,,yes +PATTERN_GUIDE.md,docs/images/pattern-guide/18-publish.png,relative,,yes +README.md,/,site,,yes +README.md,/build/breadboard,site,,yes +README.md,/contact,site,,yes +README.md,/editions,site,,yes +README.md,/features,site,,yes +README.md,/guide,site,,yes +README.md,/guide/audio,site,,yes +README.md,/guide/build,site,,yes +README.md,/guide/make,site,,yes +README.md,/guide/play,site,,yes +README.md,/guide/play,site,flash,yes +README.md,/guide/play,site,flash-5,yes +README.md,/guide/play,site,patterns,yes +README.md,/inside,site,,yes +README.md,/journal,site,,yes +README.md,/pattern,site,,yes +README.md,/pattern-lab,site,,yes +README.md,AUDIO_GUIDE.md,relative,,yes +README.md,BUILD_GUIDE.md,relative,,yes +README.md,BUILD_GUIDE.md,relative,1-bill-of-materials-bom,yes +README.md,BUILD_GUIDE.md,relative,10-known-issues--design-notes,yes +README.md,BUILD_GUIDE.md,relative,8-firmware,yes +README.md,BUILD_GUIDE.md,relative,9-final-checks,yes +README.md,BUILD_GUIDE.md,relative,off-the-board,yes +README.md,BUILD_GUIDE_v2.md,relative,,yes +README.md,CHANGELOG.md,relative,,yes +README.md,CONTRIBUTING.md,relative,,yes +README.md,FEATURE_GUIDE.md,relative,,yes +README.md,LICENSE-CC-BY-SA,relative,,yes +README.md,LICENSE-MIT,relative,,yes +README.md,PATTERN_GUIDE.md,relative,,yes +README.md,SUPPORT.md,relative,,yes +README.md,docs/EDITIONS.md,relative,,yes +README.md,docs/LICENSE-SUMMARY.md,relative,,yes +README.md,docs/README.md,relative,,yes +README.md,docs/REPOSITORY.md,relative,,yes +README.md,docs/assembly/README.md,relative,,yes +README.md,docs/director-midi.md,relative,,yes +README.md,docs/manifesto.md,relative,,yes +README.md,docs/media/community-builds.jpg,relative,,yes +README.md,docs/media/community-library.png,relative,,yes +README.md,docs/media/daw-ableton.jpg,relative,,yes +README.md,docs/media/device-card.png,relative,,yes +README.md,docs/media/hero-loop.webp,relative,,yes +README.md,docs/media/pcbway-3d-print.jpg,relative,,yes +README.md,docs/media/pcbway-logo.png,relative,,yes +README.md,docs/media/web-build-map.png,relative,,yes +README.md,docs/media/web-live-editor.png,relative,,yes +README.md,docs/midi-ableton.md,relative,,yes +README.md,docs/midi-spec.md,relative,,yes +README.md,docs/mqtt-spec.md,relative,,yes +README.md,docs/osc-spec.md,relative,,yes +README.md,docs/panel-compatibility.md,relative,,yes +README.md,docs/rest-api.md,relative,,yes +README.md,docs/rest-api.md,relative,get-apidisplay,yes +README.md,docs/rest-api.md,relative,get-apiknobs-and-post-apiknobs,yes +README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +README.md,firmware/README.md,relative,,yes +README.md,firmware/README.md,relative,refresh-rate-anti-flicker-for-video,yes +README.md,firmware/toolchain/make_pack.py,relative,,yes +README.md,hardware/README.md,relative,,yes +README.md,hardware/case/remixes/README.md,relative,,yes +README.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +README.md,integrations/README.md,relative,,yes +README.md,integrations/ableton,relative,,yes +README.md,tools/patternflow-audio-extension,relative,,yes +README.md,web/ARCHITECTURE.md,relative,,yes +README.md,web/public/journal/v1-30-days/first-pcb.jpg,relative,,yes +SECURITY.md,/editions,site,,yes +SECURITY.md,/pattern,site,,yes +SECURITY.md,/update,site,,yes +SECURITY.md,docs/rest-api.md,relative,transport,yes +SUPPORT.md,/guide,site,,yes +SUPPORT.md,/guide/play,site,flash,yes +SUPPORT.md,/inside,site,,yes +SUPPORT.md,/pattern,site,,yes +SUPPORT.md,/pattern-lab,site,,yes +SUPPORT.md,BUILD_GUIDE.md,relative,8-firmware,yes +SUPPORT.md,CONTRIBUTING.md,relative,,yes +SUPPORT.md,SECURITY.md,relative,,yes +docs/EDITIONS.md,/editions,site,,yes +docs/EDITIONS.md,PATTERN_GUIDE.md,relative,,yes +docs/EDITIONS.md,docs/RELEASING.md,relative,,yes +docs/EDITIONS.md,docs/audio-ws-spec.md,relative,,yes +docs/EDITIONS.md,docs/investigations/2026-08-the-wifi-portal-a-samsung-never-drew.md,relative,,yes +docs/EDITIONS.md,docs/osc-spec.md,relative,,yes +docs/EDITIONS.md,docs/rest-api.md,relative,,yes +docs/EDITIONS.md,docs/rfc-core-and-variants.md,relative,,yes +docs/EDITIONS.md,docs/rfc-core-and-variants.md,relative,213-what-changed-and-why-step-5-is-withdrawn,yes +docs/EDITIONS.md,docs/rfc-core-and-variants.md,relative,214-the-formats-are-frozen,yes +docs/EDITIONS.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +docs/EDITIONS.md,firmware/bundles/README.md,relative,,yes +docs/EDITIONS.md,firmware/patternflow/features/README.md,relative,,yes +docs/LICENSE-SUMMARY.md,/community,site,,yes +docs/LICENSE-SUMMARY.md,/terms,site,,yes +docs/LICENSE-SUMMARY.md,CONTRIBUTING.md,relative,,yes +docs/README.md,/guide,site,,yes +docs/README.md,/guide/audio,site,,yes +docs/README.md,/guide/build,site,,yes +docs/README.md,/guide/make,site,,yes +docs/README.md,/guide/play,site,,yes +docs/README.md,/guide/play,site,flash,yes +docs/README.md,BUILD_GUIDE.md,relative,,yes +docs/README.md,BUILD_GUIDE.md,relative,8-firmware,yes +docs/README.md,CONTRIBUTING.md,relative,,yes +docs/README.md,PATTERN_GUIDE.md,relative,,yes +docs/README.md,SUPPORT.md,relative,,yes +docs/README.md,docs/EDITIONS.md,relative,,yes +docs/README.md,docs/LICENSE-SUMMARY.md,relative,,yes +docs/README.md,docs/RELEASING.md,relative,,yes +docs/README.md,docs/REPOSITORY.md,relative,,yes +docs/README.md,docs/SERVICES.md,relative,,yes +docs/README.md,docs/assembly/README.md,relative,,yes +docs/README.md,docs/audio-ws-spec.md,relative,,yes +docs/README.md,docs/build-guide/images,relative,,yes +docs/README.md,docs/director-midi.md,relative,,yes +docs/README.md,docs/images,relative,,yes +docs/README.md,docs/investigations,relative,,yes +docs/README.md,docs/manifesto.md,relative,,yes +docs/README.md,docs/media,relative,,yes +docs/README.md,docs/midi-ableton.md,relative,,yes +docs/README.md,docs/midi-spec.md,relative,,yes +docs/README.md,docs/mqtt-spec.md,relative,,yes +docs/README.md,docs/osc-spec.md,relative,,yes +docs/README.md,docs/panel-compatibility.md,relative,,yes +docs/README.md,docs/pfst-v2-spec.md,relative,,yes +docs/README.md,docs/pfst-v2-vectors,relative,,yes +docs/README.md,docs/releases,relative,,yes +docs/README.md,docs/rest-api.md,relative,,yes +docs/README.md,docs/rfc-core-and-variants-progress.md,relative,,yes +docs/README.md,docs/rfc-core-and-variants.md,relative,,yes +docs/README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +docs/README.md,firmware/patternflow/console/README.md,relative,,yes +docs/README.md,hardware/README.md,relative,,yes +docs/README.md,hardware/case/remixes/README.md,relative,,yes +docs/REPOSITORY.md,/guide/audio,site,,yes +docs/REPOSITORY.md,/guide/build,site,,yes +docs/REPOSITORY.md,/guide/make,site,,yes +docs/REPOSITORY.md,/guide/play,site,,yes +docs/REPOSITORY.md,/guide/play,site,flash,yes +docs/REPOSITORY.md,AGENTS.md,relative,,yes +docs/REPOSITORY.md,AUDIO_GUIDE.md,relative,,yes +docs/REPOSITORY.md,BUILD_GUIDE.md,relative,,yes +docs/REPOSITORY.md,BUILD_GUIDE.md,relative,8-firmware,yes +docs/REPOSITORY.md,CONTRIBUTING.md,relative,,yes +docs/REPOSITORY.md,FEATURE_GUIDE.md,relative,,yes +docs/REPOSITORY.md,PATTERN_GUIDE.md,relative,,yes +docs/REPOSITORY.md,README.md,relative,,yes +docs/REPOSITORY.md,docs/EDITIONS.md,relative,,yes +docs/REPOSITORY.md,docs/README.md,relative,,yes +docs/REPOSITORY.md,docs/RELEASING.md,relative,,yes +docs/REPOSITORY.md,docs/SERVICES.md,relative,,yes +docs/REPOSITORY.md,docs/assembly/README.md,relative,,yes +docs/REPOSITORY.md,docs/rest-api.md,relative,,yes +docs/REPOSITORY.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +docs/REPOSITORY.md,firmware/README.md,relative,,yes +docs/REPOSITORY.md,firmware/bundles/README.md,relative,,yes +docs/REPOSITORY.md,firmware/patternflow/features/README.md,relative,,yes +docs/REPOSITORY.md,hardware/README.md,relative,,yes +docs/REPOSITORY.md,integrations/README.md,relative,,yes +docs/REPOSITORY.md,tools/README.md,relative,,yes +docs/REPOSITORY.md,web/ARCHITECTURE.md,relative,,yes +docs/REPOSITORY.md,web/README.md,relative,,yes +docs/assembly/README.md,/build/breadboard,site,,yes +docs/assembly/README.md,/guide/build,site,,yes +docs/assembly/README.md,/guide/play,site,flash,yes +docs/assembly/README.md,BUILD_GUIDE.md,relative,,yes +docs/assembly/README.md,BUILD_GUIDE.md,relative,8-firmware,yes +docs/assembly/README.md,BUILD_GUIDE_v2.md,relative,,yes +docs/assembly/README.md,PATTERN_GUIDE.md,relative,,yes +docs/assembly/README.md,docs/panel-compatibility.md,relative,,yes +docs/assembly/README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +docs/assembly/README.md,hardware/README.md,relative,,yes +docs/assembly/README.md,hardware/case/README.md,relative,,yes +docs/assembly/README.md,hardware/case/legacy_lasercut/README.md,relative,,yes +docs/assembly/README.md,hardware/case/remixes/README.md,relative,,yes +docs/assembly/README.md,hardware/case/remixes/besoiobiy-printed/README.md,relative,,yes +docs/assembly/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,relative,,yes +docs/assembly/README.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +docs/assembly/README.md,hardware/pcb/README.md,relative,,yes +docs/audio-ws-spec.md,docs/osc-spec.md,relative,,yes +docs/audio-ws-spec.md,docs/rest-api.md,relative,,yes +docs/audio-ws-spec.md,docs/rest-api.md,relative,audio-react-audio-edition,yes +docs/director-midi.md,docs/audio-ws-spec.md,relative,,yes +docs/director-midi.md,docs/osc-spec.md,relative,,yes +docs/director-midi.md,integrations/ableton/README.md,relative,,yes +docs/director-midi.md,integrations/ableton/docs/recording-sync.md,relative,,yes +docs/investigations/2026-09-firmware-runtime.md,docs/investigations/2026-09-runtime-improvements.json,relative,,yes +docs/investigations/2026-09-firmware-runtime.md,docs/investigations/2026-09-runtime-research/README.md,relative,,yes +docs/investigations/2026-09-runtime-research/README.md,docs/investigations/2026-09-firmware-runtime.md,relative,,yes +docs/manifesto.md,/inside,site,,yes +docs/midi-ableton.md,docs/director-midi.md,relative,,yes +docs/midi-ableton.md,docs/images/midi/ableton-5-remote.png,relative,,yes +docs/midi-ableton.md,docs/images/midi/rtpmidi-1-new-session.png,relative,,yes +docs/midi-ableton.md,docs/images/midi/rtpmidi-2-enable.png,relative,,yes +docs/midi-ableton.md,docs/images/midi/rtpmidi-3-connect.png,relative,,yes +docs/midi-ableton.md,docs/images/midi/rtpmidi-4-connected.png,relative,,yes +docs/midi-ableton.md,docs/midi-spec.md,relative,,yes +docs/midi-spec.md,docs/EDITIONS.md,relative,,yes +docs/midi-spec.md,docs/director-midi.md,relative,,yes +docs/midi-spec.md,docs/osc-spec.md,relative,,yes +docs/midi-spec.md,docs/rest-api.md,relative,,yes +docs/mqtt-spec.md,docs/EDITIONS.md,relative,,yes +docs/mqtt-spec.md,docs/midi-spec.md,relative,,yes +docs/mqtt-spec.md,docs/osc-spec.md,relative,,yes +docs/mqtt-spec.md,docs/rest-api.md,relative,,yes +docs/mqtt-spec.md,docs/rest-api.md,relative,choosing-a-transport,yes +docs/mqtt-spec.md,docs/rest-api.md,relative,knob-ordering,yes +docs/panel-compatibility.md,docs/media/panels/dp5125d_sm5166p.jpg,relative,,yes +docs/panel-compatibility.md,docs/media/panels/fm6124ej.jpg,relative,,yes +docs/panel-compatibility.md,docs/media/panels/icn2037bp.jpg,relative,,yes +docs/panel-compatibility.md,firmware/README.md,relative,,yes +docs/panel-compatibility.md,firmware/patternflow/config.h,relative,,yes +docs/panel-compatibility.md,firmware/patternflow/src/core_display.h,relative,,yes +docs/panel-compatibility.md,hardware/bom/README.md,relative,,yes +docs/pfst-v2-spec.md,docs/pfst-v2-vectors,relative,,yes +docs/releases/v3.0.0-launch.md,docs/RELEASING.md,relative,,yes +docs/releases/v3.0.0.md,/,site,,yes +docs/releases/v3.0.0.md,BUILD_GUIDE.md,absolute-blob,2-power-input--use-the-screw-terminal,yes +docs/releases/v3.0.0.md,v3.0.0:BUILD_GUIDE.md,absolute-blob,,yes +docs/releases/v3.0.0.md,v3.0.0:BUILD_GUIDE_v2.md,absolute-blob,,yes +docs/releases/v3.0.0.md,v3.0.0:CHANGELOG.md,absolute-blob,,yes +docs/releases/v3.0.0.md,v3.0.0:hardware/bom/bom_v3.0.csv,absolute-blob,,yes +docs/releases/v3.1.0.md,/roadmap,site,,yes +docs/releases/v3.1.0.md,v3.1.0:BUILD_GUIDE.md,absolute-blob,,yes +docs/releases/v3.1.0.md,v3.1.0:BUILD_GUIDE.md,absolute-blob,2-power-input--use-the-screw-terminal,yes +docs/releases/v3.1.0.md,v3.1.0:CHANGELOG.md,absolute-blob,,yes +docs/rest-api.md,docs/EDITIONS.md,relative,,yes +docs/rest-api.md,docs/audio-ws-spec.md,relative,,yes +docs/rest-api.md,docs/audio-ws-spec.md,relative,the-switch-on-the-panel,yes +docs/rest-api.md,docs/midi-spec.md,relative,,yes +docs/rest-api.md,docs/mqtt-spec.md,relative,,yes +docs/rfc-cleanup-progress.md,docs/rfc-cleanup.md,relative,,yes +docs/rfc-core-and-variants-progress.md,docs/EDITIONS.md,relative,,yes +docs/rfc-core-and-variants-progress.md,docs/pfst-v2-vectors,relative,,yes +docs/rfc-core-and-variants-progress.md,docs/rest-api.md,relative,,yes +docs/rfc-core-and-variants-progress.md,docs/rfc-core-and-variants.md,relative,,yes +docs/rfc-core-and-variants-progress.md,firmware/patternflow/features/README.md,relative,,yes +docs/rfc-core-and-variants.md,/variants,site,,yes +docs/rfc-core-and-variants.md,docs/EDITIONS.md,relative,,yes +docs/rfc-core-and-variants.md,docs/pfst-v2-spec.md,relative,,yes +docs/rfc-core-and-variants.md,docs/rfc-core-and-variants-progress.md,relative,,yes +docs/rfc-core-and-variants.md,docs/rfc-core-and-variants-progress.md,relative,what-the-slim-core-measures,yes +firmware/CUSTOM_PATTERNS.md,/,site,,yes +firmware/CUSTOM_PATTERNS.md,/update,site,,yes +firmware/CUSTOM_PATTERNS.md,firmware/README.md,relative,loadable-pattern-modules-pfm,yes +firmware/CUSTOM_PATTERNS.md,firmware/README.md,relative,required-board-package,yes +firmware/README.md,/editions,site,,yes +firmware/README.md,/guide/play,site,flash,yes +firmware/README.md,/update,site,,yes +firmware/README.md,AUDIO_GUIDE.md,relative,,yes +firmware/README.md,BUILD_GUIDE.md,relative,8-firmware,yes +firmware/README.md,PATTERN_GUIDE.md,relative,,yes +firmware/README.md,docs/EDITIONS.md,relative,,yes +firmware/README.md,docs/README.md,relative,,yes +firmware/README.md,docs/audio-ws-spec.md,relative,,yes +firmware/README.md,docs/investigations/2026-08-the-panel-clock-and-the-wifi-radio.md,relative,,yes +firmware/README.md,docs/investigations/2026-09-firmware-runtime.md,relative,,yes +firmware/README.md,docs/midi-ableton.md,relative,,yes +firmware/README.md,docs/midi-spec.md,relative,,yes +firmware/README.md,docs/mqtt-spec.md,relative,,yes +firmware/README.md,docs/osc-spec.md,relative,,yes +firmware/README.md,docs/panel-compatibility.md,relative,,yes +firmware/README.md,docs/rest-api.md,relative,,yes +firmware/README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +firmware/README.md,firmware/bundles/README.md,relative,,yes +firmware/README.md,firmware/patternflow/console,relative,,yes +firmware/README.md,firmware/patternflow/console/README.md,relative,,yes +firmware/README.md,integrations/ableton,relative,,yes +firmware/README.md,tools/README.md,relative,,yes +firmware/bundles/README.md,/editions,site,,yes +firmware/bundles/README.md,docs/EDITIONS.md,relative,,yes +firmware/bundles/README.md,firmware/patternflow/features/README.md,relative,,yes +firmware/modules/README.md,/pattern-lab,site,,yes +firmware/modules/README.md,PATTERN_GUIDE.md,relative,,yes +firmware/patternflow/README.md,CONTRIBUTING.md,relative,,yes +firmware/patternflow/README.md,PATTERN_GUIDE.md,relative,,yes +firmware/patternflow/README.md,docs/LICENSE-SUMMARY.md,relative,,yes +firmware/patternflow/README.md,docs/panel-compatibility.md,relative,,yes +firmware/patternflow/README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +firmware/patternflow/README.md,firmware/README.md,relative,,yes +firmware/patternflow/README.md,firmware/patternflow/_TEMPLATE.h,relative,,yes +firmware/patternflow/README.md,firmware/patternflow/config.h,relative,,yes +firmware/patternflow/README.md,firmware/patternflow/pattern_registry.h,relative,,yes +firmware/patternflow/README.md,firmware/patternflow/presets,relative,,yes +firmware/patternflow/console/_audio_in_bar.html,/,console,,yes +firmware/patternflow/console/_audio_in_bar.html,/status,console,,yes +firmware/patternflow/console/_audio_in_bar.html,tools/patternflow-audio-extension,absolute-blob,readme,yes +firmware/patternflow/console/audio-in.html,/,console,,yes +firmware/patternflow/console/audio-in.html,/pf-console.js,console,,yes +firmware/patternflow/console/audio-in.html,/status,console,,yes +firmware/patternflow/console/audio-in.html,tools/patternflow-audio-extension,absolute-blob,readme,yes +firmware/patternflow/console/clock.html,/pf-console.js,console,,yes +firmware/patternflow/console/home.html,/,site,,yes +firmware/patternflow/console/home.html,/editions,site,,yes +firmware/patternflow/console/home.html,/flash/manifest.json,site,,yes +firmware/patternflow/console/home.html,/knobs,console,,yes +firmware/patternflow/console/home.html,/patterns,console,,yes +firmware/patternflow/console/home.html,/pf-console.js,console,,yes +firmware/patternflow/console/home.html,/status,console,,yes +firmware/patternflow/console/home.html,/update,console,,yes +firmware/patternflow/console/home.html,/update,site,,yes +firmware/patternflow/console/home.html,/wifi,console,,yes +firmware/patternflow/console/knobs.html,/,console,,yes +firmware/patternflow/console/knobs.html,/pf-console.js,console,,yes +firmware/patternflow/console/knobs.html,/status,console,,yes +firmware/patternflow/console/midi.html,/pf-console.js,console,,yes +firmware/patternflow/console/midi.html,docs/midi-ableton.md,absolute-blob,,yes +firmware/patternflow/console/midi.html,docs/midi-spec.md,absolute-blob,,yes +firmware/patternflow/console/mqtt.html,/pf-console.js,console,,yes +firmware/patternflow/console/patterns.html,/,console,,yes +firmware/patternflow/console/patterns.html,/,site,,yes +firmware/patternflow/console/patterns.html,/patterns/fflate.js,console,,yes +firmware/patternflow/console/patterns.html,/pf-console.js,console,,yes +firmware/patternflow/console/show.html,/patterns/fflate.js,console,,yes +firmware/patternflow/console/show.html,/pf-console.js,console,,yes +firmware/patternflow/console/show.html,/weather,console,,yes +firmware/patternflow/console/status.html,/,console,,yes +firmware/patternflow/console/status.html,/patterns,console,,yes +firmware/patternflow/console/status.html,/pf-console.js,console,,yes +firmware/patternflow/console/update.html,/,console,,yes +firmware/patternflow/console/update.html,/,site,,yes +firmware/patternflow/console/update.html,/editions,site,,yes +firmware/patternflow/console/update.html,/pf-console.js,console,,yes +firmware/patternflow/console/update.html,/update,site,,yes +firmware/patternflow/console/weather.html,/pf-console.js,console,,yes +firmware/patternflow/console/wifi.html,/,console,,yes +firmware/patternflow/console/wifi.html,/pf-console.js,console,,yes +firmware/patternflow/console/wifi.html,/status,console,,yes +firmware/patternflow/features/README.md,docs/EDITIONS.md,relative,,yes +firmware/patternflow/features/README.md,docs/rfc-core-and-variants.md,relative,,yes +firmware/patternflow/features/README.md,firmware/bundles/README.md,relative,,yes +firmware/patternflow/presets/README.md,/pattern-lab,site,,yes +firmware/patternflow/presets/README.md,docs/LICENSE-SUMMARY.md,relative,,yes +firmware/patternflow/presets/README.md,firmware/CUSTOM_PATTERNS.md,relative,,yes +firmware/patternflow/presets/README.md,firmware/patternflow/README.md,relative,,yes +firmware/patternflow/presets/README.md,firmware/patternflow/pattern_registry.h,relative,,yes +firmware/patternflow/presets/preset_0628.h,/,site,,yes +firmware/patternflow/presets/preset_0629.h,/,site,,yes +firmware/patternflow/presets/preset_0629_2.h,/,site,,yes +firmware/patternflow/presets/preset_0701.h,/,site,,yes +firmware/patternflow/presets/preset_0707.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0710.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0712.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0712_2.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0713.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0715.h,/pattern,site,,yes +firmware/patternflow/presets/preset_0716.h,/pattern,site,,yes +firmware/patternflow/presets/preset_0718.h,/pattern-lab,site,,yes +firmware/patternflow/presets/preset_0719.h,/pattern-lab,site,,yes +firmware/toolchain/README.md,docs/EDITIONS.md,relative,,yes +firmware/toolchain/README.md,docs/RELEASING.md,relative,,yes +firmware/toolchain/README.md,firmware/patternflow/console/README.md,relative,,yes +hardware/README.md,/build,site,,yes +hardware/README.md,/guide/build,site,,yes +hardware/README.md,BUILD_GUIDE.md,relative,,yes +hardware/README.md,BUILD_GUIDE_v2.md,relative,,yes +hardware/README.md,LICENSE-CC-BY-SA,relative,,yes +hardware/README.md,docs/assembly/README.md,relative,,yes +hardware/README.md,hardware/bom/README.md,relative,,yes +hardware/README.md,hardware/bom/bom_v3.0.csv,relative,,yes +hardware/README.md,hardware/bom/bom_v3.9.csv,relative,,yes +hardware/README.md,hardware/case/README.md,relative,,yes +hardware/README.md,hardware/case/legacy_lasercut/README.md,relative,,yes +hardware/README.md,hardware/case/remixes/README.md,relative,,yes +hardware/README.md,hardware/pcb/README.md,relative,,yes +hardware/README.md,hardware/pcb/gerber,relative,,yes +hardware/README.md,v2.1.0:BUILD_GUIDE.md,absolute-blob,1-bill-of-materials-bom,yes +hardware/bom/README.md,docs/panel-compatibility.md,relative,,yes +hardware/bom/README.md,firmware/patternflow/config.h,relative,,yes +hardware/bom/README.md,v2.1.0:BUILD_GUIDE.md,absolute-blob,1-bill-of-materials-bom,yes +hardware/case/README.md,BUILD_GUIDE.md,relative,,yes +hardware/case/README.md,BUILD_GUIDE.md,relative,2-power-input--use-the-screw-terminal,yes +hardware/case/README.md,BUILD_GUIDE.md,relative,6-case-assembly,yes +hardware/case/README.md,BUILD_GUIDE_v2.md,relative,,yes +hardware/case/README.md,hardware/bom,relative,,yes +hardware/case/README.md,hardware/case/bed_256mm,relative,,yes +hardware/case/README.md,hardware/case/bed_256mm/patternflow_v3.3mf,relative,,yes +hardware/case/README.md,hardware/case/bed_330mm,relative,,yes +hardware/case/README.md,hardware/case/knobs,relative,,yes +hardware/case/README.md,hardware/case/legacy_lasercut/README.md,relative,,yes +hardware/case/README.md,hardware/case/legacy_v2,relative,,yes +hardware/case/README.md,hardware/case/remixes/README.md,relative,,yes +hardware/case/README.md,hardware/case/remixes/besoiobiy-printed/README.md,relative,,yes +hardware/case/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,relative,,yes +hardware/case/README.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +hardware/case/README.md,v2.1.0:hardware/case,absolute-blob,,yes +hardware/case/legacy_lasercut/README.md,hardware/case/remixes/README.md,relative,,yes +hardware/case/legacy_lasercut/README.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +hardware/case/remixes/README.md,/build,site,,yes +hardware/case/remixes/README.md,/inside,site,,yes +hardware/case/remixes/README.md,CONTRIBUTING.md,relative,your-build,yes +hardware/case/remixes/README.md,hardware/case/remixes/besoiobiy-printed/README.md,relative,,yes +hardware/case/remixes/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,relative,,yes +hardware/case/remixes/README.md,hardware/case/remixes/simonepda-lasercut/README.md,relative,,yes +hardware/case/remixes/README.md,tools/case-models/README.md,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,BUILD_GUIDE.md,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,BUILD_GUIDE.md,relative,2-power-input--use-the-screw-terminal,yes +hardware/case/remixes/besoiobiy-printed/README.md,BUILD_GUIDE.md,relative,6-case-assembly,yes +hardware/case/remixes/besoiobiy-printed/README.md,docs/panel-compatibility.md,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig1_corner_bulge.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig2_panel_gap.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig3_variants.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig4_grooves.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig5_glue_order.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig6_inserts_and_screws.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig7_panel_bolts.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/fig8_ribbon_connector.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/photo_built.jpg,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/render_exploded_back.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/render_exploded_front.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/images/render_parts.png,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/print_layout.3mf,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/source/patternbox.blend,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/source/patternbox.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_bottom.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_bottom_no_bridge.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_bottom_plain.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_top.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_top_no_bridge.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/box_top_plain.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/cover_box_bottom.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/cover_box_top.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/cover_frame_bottom.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/cover_frame_top.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/frame_bottom.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/frame_top.stl,relative,,yes +hardware/case/remixes/besoiobiy-printed/README.md,hardware/case/remixes/besoiobiy-printed/stl/knob_cap.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,BUILD_GUIDE.md,relative,2-power-input--use-the-screw-terminal,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,LICENSE-CC-BY-SA,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/bom.md,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/photo_front.jpg,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/photo_front_angle.jpg,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/print_layout.3mf,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/alignment_pin_2mm.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/control_section.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/joint_bar.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/knob.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/rear_control_cover.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/rear_display_cover.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/stand.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/usb_retainer.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/white_inner_frame.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/stl/white_outer_frame.stl,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,BUILD_GUIDE.md,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/bom.md,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/01_frame_connections.png,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/02_joint_section.png,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/03_optional_pins.png,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/04_usb_installation.png,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/05_connections.png,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/photo_rear_assembly.jpg,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/images/photo_socket_detail.jpg,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/bom.md,hardware/bom/bom_v3.0.csv,relative,,yes +hardware/case/remixes/mbchars-horizontal-desktop-printed/bom.md,hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,relative,print-files,yes +hardware/case/remixes/simonepda-lasercut/README.md,BUILD_GUIDE.md,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/knobs,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/lasercut_layout.cdr,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/lasercut_layout.pdf,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/photos/acrylic_front.jpg,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/photos/board_in_box.jpg,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/photos/mdf_back.jpg,relative,,yes +hardware/case/remixes/simonepda-lasercut/README.md,hardware/case/remixes/simonepda-lasercut/photos/mdf_front.jpg,relative,,yes +hardware/pcb/README.md,LICENSE-CC-BY-SA,relative,,yes +hardware/pcb/README.md,hardware/bom,relative,,yes +hardware/pcb/README.md,hardware/pcb/gerber,relative,,yes +hardware/pcb/README.md,hardware/pcb/images/board_render_bottom.png,relative,,yes +hardware/pcb/README.md,hardware/pcb/images/board_render_top.png,relative,,yes +hardware/pcb/README.md,hardware/pcb/images/schematic.svg,relative,,yes +hardware/pcb/README.md,hardware/pcb/schematic.pdf,relative,,yes +hardware/pcb/gerber/experiment/README.md,hardware/pcb/gerber,relative,,yes +integrations/README.md,/editions,site,,yes +integrations/README.md,docs/midi-spec.md,relative,,yes +integrations/README.md,docs/mqtt-spec.md,relative,,yes +integrations/README.md,docs/osc-spec.md,relative,,yes +integrations/README.md,docs/rest-api.md,relative,,yes +integrations/README.md,integrations/ableton/README.md,relative,,yes +integrations/README.md,tools/README.md,relative,,yes +integrations/ableton/README.md,/editions,site,,yes +integrations/ableton/README.md,docs/EDITIONS.md,relative,,yes +integrations/ableton/README.md,docs/director-midi.md,relative,,yes +integrations/ableton/README.md,docs/osc-spec.md,relative,,yes +integrations/ableton/README.md,integrations/ableton/docs/m4l-osc-guide.md,relative,,yes +integrations/ableton/README.md,integrations/ableton/docs/recording-sync.md,relative,,yes +integrations/ableton/docs/recording-sync.md,docs/osc-spec.md,relative,,yes +tools/README.md,LICENSE-MIT,relative,,yes +tools/README.md,docs/README.md,relative,contracts--other-software-is-built-against-these-not-against-the-firmware-source,yes +tools/README.md,docs/audio-ws-spec.md,relative,,yes +tools/README.md,docs/midi-spec.md,relative,,yes +tools/README.md,docs/rest-api.md,relative,microphone-audio-edition,yes +tools/README.md,integrations/README.md,relative,,yes +tools/README.md,tools/case-models/README.md,relative,,yes +tools/README.md,tools/patternflow-audio-android/README.md,relative,,yes +tools/README.md,tools/patternflow-audio-extension/README.md,relative,,yes +tools/README.md,tools/rtpmidi-probe/README.md,relative,,yes +tools/case-models/README.md,/build,site,,yes +tools/patternflow-audio-android/README.md,/editions,site,,yes +tools/patternflow-audio-extension/README.md,/editions,site,,yes +tools/patternflow-audio-extension/README.md,AUDIO_GUIDE.md,relative,,yes +tools/patternflow-audio-extension/README.md,docs/audio-ws-spec.md,relative,,yes +tools/patternflow-audio-extension/README.md,firmware/patternflow/console/README.md,relative,the-page-that-is-assembled-audio-in,yes +tools/rtpmidi-probe/README.md,docs/midi-spec.md,relative,,yes +web/ARCHITECTURE.md,/,site,,yes +web/ARCHITECTURE.md,docs/SERVICES.md,relative,,yes +web/README.md,/,site,,yes +web/README.md,CONTRIBUTING.md,relative,,yes +web/README.md,LICENSE-MIT,relative,,yes +web/README.md,tools/case-models/README.md,relative,,yes +web/README.md,web/ARCHITECTURE.md,relative,,yes +web/README.md,web/ARCHITECTURE.md,relative,environment-variables,yes +web/content/inside.md,CONTRIBUTING.md,absolute-blob,,yes +web/content/journal/a-strange-dream.en.mdx,/journal/a-strange-dream/certificate.jpg,site,,yes +web/content/journal/a-strange-dream.mdx,/journal/a-strange-dream/certificate.jpg,site,,yes +web/content/journal/a-strange-feeling.en.mdx,/journal/a-strange-feeling/build-guide.jpg,site,,yes +web/content/journal/a-strange-feeling.mdx,/journal/a-strange-feeling/build-guide.jpg,site,,yes +web/content/journal/all-jumbled-up.en.mdx,/journal/all-jumbled-up/turntable.jpg,site,,yes +web/content/journal/all-jumbled-up.mdx,/journal/all-jumbled-up/turntable.jpg,site,,yes +web/content/journal/all-over-the-place.en.mdx,/journal/all-over-the-place/funding-spreadsheet.png,site,,yes +web/content/journal/all-over-the-place.mdx,/journal/all-over-the-place/funding-spreadsheet.png,site,,yes +web/content/journal/community.en.mdx,/roadmap,site,,yes +web/content/journal/community.mdx,/roadmap,site,,yes +web/content/journal/experiment-after-experiment.en.mdx,/pattern-lab,site,,yes +web/content/journal/experiment-after-experiment.mdx,/pattern-lab,site,,yes +web/content/journal/faster-faster.en.mdx,/community,site,,yes +web/content/journal/faster-faster.en.mdx,/journal/faster-faster/crowd-supply-subscribers.png,site,,yes +web/content/journal/faster-faster.mdx,/community,site,,yes +web/content/journal/faster-faster.mdx,/journal/faster-faster/crowd-supply-subscribers.png,site,,yes +web/content/journal/good-but.en.mdx,/journal/good-but/astra-patterns.png,site,,yes +web/content/journal/good-but.en.mdx,/journal/good-but/funding-success.png,site,,yes +web/content/journal/good-but.mdx,/journal/good-but/astra-patterns.png,site,,yes +web/content/journal/good-but.mdx,/journal/good-but/funding-success.png,site,,yes +web/content/journal/how-to-use-patternflow.en.mdx,/journal/how-to-use-patternflow/gwangju-biennale.jpg,site,,yes +web/content/journal/how-to-use-patternflow.mdx,/journal/how-to-use-patternflow/gwangju-biennale.jpg,site,,yes +web/content/journal/i-hope-it-works-out.en.mdx,/journal/i-hope-it-works-out/crowd-supply-subscribers.png,site,,yes +web/content/journal/i-hope-it-works-out.mdx,/journal/i-hope-it-works-out/crowd-supply-subscribers.png,site,,yes +web/content/journal/ill-just-do-it.en.mdx,/journal/ill-just-do-it/at-a-glance.png,site,,yes +web/content/journal/ill-just-do-it.en.mdx,/journal/ill-just-do-it/the-lab.png,site,,yes +web/content/journal/ill-just-do-it.mdx,/journal/ill-just-do-it/at-a-glance.png,site,,yes +web/content/journal/ill-just-do-it.mdx,/journal/ill-just-do-it/the-lab.png,site,,yes +web/content/journal/its-a-failure.en.mdx,/journal/its-a-failure/pdm-mic.jpg,site,,yes +web/content/journal/its-a-failure.en.mdx,/journal/its-a-failure/petg-enclosure.jpg,site,,yes +web/content/journal/its-a-failure.mdx,/journal/its-a-failure/pdm-mic.jpg,site,,yes +web/content/journal/its-a-failure.mdx,/journal/its-a-failure/petg-enclosure.jpg,site,,yes +web/content/journal/maybe-this-will-work.en.mdx,/journal/maybe-this-will-work/filming-setup.jpg,site,,yes +web/content/journal/maybe-this-will-work.mdx,/journal/maybe-this-will-work/filming-setup.jpg,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/instagram-grid.png,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/pattern-lab.png,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/posthog-session-replay.png,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/price-comment.png,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/robot-k456.jpg,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/me-and-patternflow/tally-dashboard.png,site,,yes +web/content/journal/me-and-patternflow.en.mdx,/journal/wins-and-losses-next-step/en,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/instagram-grid.png,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/pattern-lab.png,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/posthog-session-replay.png,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/price-comment.png,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/robot-k456.jpg,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/me-and-patternflow/tally-dashboard.png,site,,yes +web/content/journal/me-and-patternflow.mdx,/journal/wins-and-losses-next-step,site,,yes +web/content/journal/nam-june-paik-me-patternflow.en.mdx,/journal/nam-june-paik-me-patternflow/pattern-30.png,site,,yes +web/content/journal/nam-june-paik-me-patternflow.mdx,/journal/nam-june-paik-me-patternflow/pattern-30.png,site,,yes +web/content/journal/negative.en.mdx,/journal/negative/emc-test-scan.jpg,site,,yes +web/content/journal/negative.en.mdx,/journal/negative/funding-dashboard.png,site,,yes +web/content/journal/negative.mdx,/journal/negative/emc-test-scan.jpg,site,,yes +web/content/journal/negative.mdx,/journal/negative/funding-dashboard.png,site,,yes +web/content/journal/new-possibilities.en.mdx,/journal/new-possibilities/kkuji-tree.jpg,site,,yes +web/content/journal/new-possibilities.en.mdx,/journal/new-possibilities/pattern-map.png,site,,yes +web/content/journal/new-possibilities.mdx,/journal/new-possibilities/kkuji-tree.jpg,site,,yes +web/content/journal/new-possibilities.mdx,/journal/new-possibilities/pattern-map.png,site,,yes +web/content/journal/refocus.en.mdx,/journal/refocus/blender-3d-modeling.png,site,,yes +web/content/journal/refocus.en.mdx,/journal/refocus/exhibition-process.jpg,site,,yes +web/content/journal/refocus.en.mdx,/journal/refocus/pcb-discord-feedback.png,site,,yes +web/content/journal/refocus.en.mdx,/journal/refocus/pcbway-delivery-1.jpg,site,,yes +web/content/journal/refocus.en.mdx,/journal/refocus/pcbway-delivery-2.jpg,site,,yes +web/content/journal/refocus.mdx,/journal/refocus/blender-3d-modeling.png,site,,yes +web/content/journal/refocus.mdx,/journal/refocus/exhibition-process.jpg,site,,yes +web/content/journal/refocus.mdx,/journal/refocus/pcb-discord-feedback.png,site,,yes +web/content/journal/refocus.mdx,/journal/refocus/pcbway-delivery-1.jpg,site,,yes +web/content/journal/refocus.mdx,/journal/refocus/pcbway-delivery-2.jpg,site,,yes +web/content/journal/right-before-launch.en.mdx,/journal/right-before-launch/business-cards.png,site,,yes +web/content/journal/right-before-launch.mdx,/journal/right-before-launch/business-cards.png,site,,yes +web/content/journal/shaking-it-off.en.mdx,/journal/shaking-it-off/flooded-lawn.jpg,site,,yes +web/content/journal/shaking-it-off.mdx,/journal/shaking-it-off/flooded-lawn.jpg,site,,yes +web/content/journal/the-messy-desk.en.mdx,/journal/the-messy-desk/flowlocal.jpg,site,,yes +web/content/journal/the-messy-desk.en.mdx,/journal/the-messy-desk/messy-desk.jpg,site,,yes +web/content/journal/the-messy-desk.en.mdx,/journal/the-messy-desk/park-ice-cream.jpg,site,,yes +web/content/journal/the-messy-desk.mdx,/journal/the-messy-desk/flowlocal.jpg,site,,yes +web/content/journal/the-messy-desk.mdx,/journal/the-messy-desk/messy-desk.jpg,site,,yes +web/content/journal/the-messy-desk.mdx,/journal/the-messy-desk/park-ice-cream.jpg,site,,yes +web/content/journal/this-is-the-worst.en.mdx,/journal/this-is-the-worst/studio-product-shoot.jpg,site,,yes +web/content/journal/this-is-the-worst.mdx,/journal/this-is-the-worst/studio-product-shoot.jpg,site,,yes +web/content/journal/today-is-my-birthday.en.mdx,/journal/today-is-my-birthday/crowd-supply-contract-signed.png,site,,yes +web/content/journal/today-is-my-birthday.en.mdx,/journal/today-is-my-birthday/crowd-supply-contract-top.png,site,,yes +web/content/journal/today-is-my-birthday.en.mdx,/journal/today-is-my-birthday/diffuser-discord.png,site,,yes +web/content/journal/today-is-my-birthday.mdx,/journal/today-is-my-birthday/crowd-supply-contract-signed.png,site,,yes +web/content/journal/today-is-my-birthday.mdx,/journal/today-is-my-birthday/crowd-supply-contract-top.png,site,,yes +web/content/journal/today-is-my-birthday.mdx,/journal/today-is-my-birthday/diffuser-discord.png,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/assembled-pcb-back.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/debugging-wires-esp32-potentiometer.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/first-pcb.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/kicad-schematic-screenshot.png,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/led-panel-in-nature-1.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/led-panel-in-nature-2.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/participation-tv-experience.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/patternflow-origin-interaction.png,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/patternflow-v1-complete.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/reddit-comment-1.png,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/reddit-comment-2.png,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/robot-k456.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/tangled-wires-led-panel.jpg,site,,yes +web/content/journal/v1-30-days.en.mdx,/journal/v1-30-days/warped-3d-print.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/assembled-pcb-back.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/debugging-wires-esp32-potentiometer.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/first-pcb.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/kicad-schematic-screenshot.png,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/led-panel-in-nature-1.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/led-panel-in-nature-2.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/participation-tv-experience.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/patternflow-origin-interaction.png,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/patternflow-v1-complete.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/reddit-comment-1.png,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/reddit-comment-2.png,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/robot-k456.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/tangled-wires-led-panel.jpg,site,,yes +web/content/journal/v1-30-days.mdx,/journal/v1-30-days/warped-3d-print.jpg,site,,yes +web/content/journal/what-is-patternflow.en.mdx,/journal/what-is-patternflow/viral-x-post.png,site,,yes +web/content/journal/what-is-patternflow.mdx,/journal/what-is-patternflow/viral-x-post.png,site,,yes +web/content/journal/wins-and-losses-next-step.en.mdx,/journal/wins-and-losses-next-step/io0-pullup-resistor.jpg,site,,yes +web/content/journal/wins-and-losses-next-step.en.mdx,/journal/wins-and-losses-next-step/remote-rendering-failure.webm,site,,yes +web/content/journal/wins-and-losses-next-step.mdx,/journal/wins-and-losses-next-step/io0-pullup-resistor.jpg,site,,yes +web/content/journal/wins-and-losses-next-step.mdx,/journal/wins-and-losses-next-step/remote-rendering-failure.webm,site,,yes +web/content/journal/worn-out.en.mdx,/journal/worn-out/c-type-patternflow.jpg,site,,yes +web/content/journal/worn-out.en.mdx,/journal/worn-out/studying-sound.jpg,site,,yes +web/content/journal/worn-out.mdx,/journal/worn-out/c-type-patternflow.jpg,site,,yes +web/content/journal/worn-out.mdx,/journal/worn-out/studying-sound.jpg,site,,yes +web/next.config.ts,/editions,site,,yes +web/next.config.ts,/guide/play,site,flash,yes +web/next.config.ts,/journal/:slug/en,site,,yes +web/next.config.ts,/journal/en,site,,yes +web/scripts/deck-pack-smoke.ts,/community/p/p123,site,,yes +web/scripts/license-smoke.ts,/community/p/abc123,site,,yes +web/scripts/license-smoke.ts,/pattern-lab,site,,yes +web/scripts/module-cache-smoke.ts,/community/p/p-author,site,,yes +web/src/app/build/breadboard/page.tsx,BUILD_GUIDE.md,absolute-blob,,yes +web/src/app/build/breadboard/page.tsx,BUILD_GUIDE.md,absolute-blob,4-3d-printing,yes +web/src/app/build/breadboard/page.tsx,BUILD_GUIDE.md,absolute-blob,82-arduino-ide-custom-builds,yes +web/src/app/build/breadboard/page.tsx,docs/panel-compatibility.md,absolute-blob,,yes +web/src/app/build/page.tsx,/build,site,,yes +web/src/app/compliance/page.tsx,/compliance,site,,yes +web/src/app/editions/editions-data.ts,/flash/bin/audio-v0.7.0/patternflow.ino.bin,site,,yes +web/src/app/editions/editions-data.ts,/flash/bin/core-v3.11.0/patternflow.ino.bin,site,,yes +web/src/app/editions/editions-data.ts,/flash/bin/performance-v0.4.0/patternflow.ino.bin,site,,yes +web/src/app/editions/editions-data.ts,firmware/bundles/audio,absolute-blob,,yes +web/src/app/editions/editions-data.ts,firmware/bundles/performance,absolute-blob,,yes +web/src/app/editions/page.tsx,docs/EDITIONS.md,absolute-blob,,yes +web/src/app/editions/page.tsx,docs/EDITIONS.md,absolute-blob,getting-an-edition-listed,yes +web/src/app/features/TryInstall.tsx,/,site,,yes +web/src/app/features/features-data.ts,AUDIO_GUIDE.md,absolute-blob,,yes +web/src/app/features/features-data.ts,PATTERN_GUIDE.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/audio-ws-spec.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/director-midi.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/midi-spec.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/mqtt-spec.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/osc-spec.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/pfst-v2-spec.md,absolute-blob,,yes +web/src/app/features/features-data.ts,docs/rest-api.md,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/bundles/midi,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/audio,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/audio_in,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/ble,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/clock,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/midi,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/mqtt,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/osc,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/show,absolute-blob,,yes +web/src/app/features/features-data.ts,firmware/patternflow/features/weather,absolute-blob,,yes +web/src/app/features/features-data.ts,integrations/ableton,absolute-blob,,yes +web/src/app/features/features-data.ts,tools/patternflow-audio-android,absolute-blob,,yes +web/src/app/features/features-data.ts,tools/patternflow-audio-extension,absolute-blob,,yes +web/src/app/features/page.tsx,FEATURE_GUIDE.md,absolute-blob,,yes +web/src/app/features/page.tsx,docs/EDITIONS.md,absolute-blob,building-an-edition,yes +web/src/app/features/page.tsx,firmware/patternflow/features,absolute-blob,,yes +web/src/app/feed.xml/route.ts,/,site,,yes +web/src/app/feed.xml/route.ts,/feed.xml,site,,yes +web/src/app/feed.xml/route.ts,/journal,site,,yes +web/src/app/inside/[build]/page.tsx,/,site,,yes +web/src/app/inside/page.tsx,/inside,site,,yes +web/src/app/layout.tsx,/,site,,yes +web/src/app/layout.tsx,/,site,organization,yes +web/src/app/layout.tsx,/,site,person,yes +web/src/app/layout.tsx,/,site,website,yes +web/src/app/layout.tsx,/,site,work,yes +web/src/app/layout.tsx,/apple-touch-icon.png,site,,yes +web/src/app/layout.tsx,/og-image.png,site,,yes +web/src/app/pattern/page.tsx,/pattern,site,,yes +web/src/app/roadmap/roadmap-data.ts,/,site,,yes +web/src/app/roadmap/roadmap-data.ts,/build/breadboard,site,,yes +web/src/app/roadmap/roadmap-data.ts,/community,site,,yes +web/src/app/roadmap/roadmap-data.ts,/inside/nath-uk,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/community,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/faster-faster,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/i-hope-it-works-out,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/nam-june-paik-me-patternflow,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/refocus,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/right-before-launch,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/stopped,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/v1-30-days,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/v3-and-beyond,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/what-is-patternflow,site,,yes +web/src/app/roadmap/roadmap-data.ts,/journal/wins-and-losses-next-step,site,,yes +web/src/app/roadmap/roadmap-data.ts,/panel-tuner.html,site,,yes +web/src/app/roadmap/roadmap-data.ts,/pattern,site,,yes +web/src/app/roadmap/roadmap-data.ts,/pattern-lab,site,,yes +web/src/app/roadmap/roadmap-data.ts,BUILD_GUIDE.md,absolute-blob,2-power-input--use-the-screw-terminal,yes +web/src/app/roadmap/roadmap-data.ts,CHANGELOG.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,docs/EDITIONS.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,docs/osc-spec.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,docs/panel-compatibility.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,firmware/CUSTOM_PATTERNS.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,integrations/ableton,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v1.0.0:docs/BUILD.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v1.0.0:firmware/patternflow_v1,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v1.0.0:hardware/case,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v1.0.0:hardware/pcb,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v2.0.0:docs/BUILD.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v2.1.0:BUILD_GUIDE.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v2.1.0:firmware/patternflow,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v2.1.0:hardware/case/source,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v2.1.0:hardware/pcb,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v3.0.0:BUILD_GUIDE.md,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v3.0.0:hardware/bom/bom_v3.0.csv,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v3.0.0:hardware/case,absolute-blob,,yes +web/src/app/roadmap/roadmap-data.ts,v3.0.0:hardware/pcb,absolute-blob,,yes +web/src/app/robots.ts,/,site,,yes +web/src/app/robots.ts,/sitemap.xml,site,,yes +web/src/app/sitemap.ts,/,site,,yes +web/src/app/sitemap.ts,/build,site,,yes +web/src/app/sitemap.ts,/compliance,site,,yes +web/src/app/sitemap.ts,/contact,site,,yes +web/src/app/sitemap.ts,/editions,site,,yes +web/src/app/sitemap.ts,/features,site,,yes +web/src/app/sitemap.ts,/guide,site,,yes +web/src/app/sitemap.ts,/guide/audio,site,,yes +web/src/app/sitemap.ts,/guide/audio/ko,site,,yes +web/src/app/sitemap.ts,/guide/build,site,,yes +web/src/app/sitemap.ts,/guide/build/ko,site,,yes +web/src/app/sitemap.ts,/guide/ko,site,,yes +web/src/app/sitemap.ts,/guide/make,site,,yes +web/src/app/sitemap.ts,/guide/make/ko,site,,yes +web/src/app/sitemap.ts,/guide/play,site,,yes +web/src/app/sitemap.ts,/guide/play/ko,site,,yes +web/src/app/sitemap.ts,/inside,site,,yes +web/src/app/sitemap.ts,/journal,site,,yes +web/src/app/sitemap.ts,/journal/en,site,,yes +web/src/app/sitemap.ts,/pattern,site,,yes +web/src/app/sitemap.ts,/roadmap,site,,yes +web/src/app/sitemap.ts,/terms,site,,yes +web/src/app/terms/page.tsx,docs/LICENSE-SUMMARY.md,absolute-blob,,yes +web/src/components/guide/build/build.test.ts,BUILD_GUIDE.md,absolute-blob,1-bill-of-materials-bom,yes +web/src/components/guide/build/build.test.ts,BUILD_GUIDE.md,absolute-blob,10-known-issues--design-notes,yes +web/src/components/guide/build/build.test.ts,docs/panel-compatibility.md,absolute-blob,,yes +web/src/components/guide/copy/audio.ts,AUDIO_GUIDE.md,absolute-blob,,yes +web/src/components/guide/copy/audio.ts,docs/director-midi.md,absolute-blob,,yes +web/src/components/guide/copy/audio.ts,docs/midi-spec.md,absolute-blob,,yes +web/src/components/guide/copy/audio.ts,docs/osc-spec.md,absolute-blob,,yes +web/src/components/guide/copy/audio.ts,tools/patternflow-audio-android/README.md,absolute-blob,,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,1-bill-of-materials-bom,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,10-known-issues--design-notes,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,4-3d-printing,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,6-case-assembly,yes +web/src/components/guide/copy/build.ts,BUILD_GUIDE.md,absolute-blob,what-you-also-need-not-in-bom,yes +web/src/components/guide/copy/build.ts,docs/panel-compatibility.md,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/case,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/case/bed_256mm/encloser.stl,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/case/bed_256mm/for_other_panels,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/case/bed_256mm/patternflow_v3.3mf,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/case/bed_330mm/encloser.stl,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/pcb/gerber/patternflow_v3.9_gerber.zip,absolute-blob,,yes +web/src/components/guide/copy/build.ts,hardware/pcb/kicad,absolute-blob,,yes +web/src/components/guide/desk/ai/headers.ts,/pattern-lab,site,,yes +web/src/components/sections/BuildPanel.test.tsx,BUILD_GUIDE_v2.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,docs/panel-compatibility.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/README.md,absolute-blob,for_other_panels--using-a-different-led-panel,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/besoiobiy-printed,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/besoiobiy-printed/README.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/besoiobiy-printed/README.md,absolute-blob,check-your-panel-first,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/besoiobiy-printed/print_layout.3mf,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/mbchars-horizontal-desktop-printed,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/mbchars-horizontal-desktop-printed/README.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/mbchars-horizontal-desktop-printed/assembly.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/simonepda-lasercut,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/simonepda-lasercut/README.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.test.tsx,hardware/case/remixes/simonepda-lasercut/lasercut_layout.pdf,absolute-blob,,yes +web/src/components/sections/BuildPanel.tsx,BUILD_GUIDE.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.tsx,BUILD_GUIDE_v2.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.tsx,docs/assembly/README.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.tsx,docs/panel-compatibility.md,absolute-blob,,yes +web/src/components/sections/BuildPanel.tsx,hardware/README.md,absolute-blob,,yes +web/src/components/sections/PatternPanel.tsx,BUILD_GUIDE.md,absolute-blob,8-firmware,yes +web/src/components/sections/PatternPanel.tsx,firmware/README.md,absolute-blob,,yes +web/src/lib/ai/gemini.ts,/pattern-lab,site,,yes +web/src/lib/pattern/packs.ts,/,site,,yes +web/src/lib/pattern/share.ts,/community,site,,yes +web/src/lib/pattern/share.ts,/pattern,site,,yes +web/src/lib/pattern/share.ts,/pattern-lab,site,,yes +web/src/lib/presets/README.md,/pattern-lab,site,,yes +web/src/lib/presets/README.md,firmware/modules/README.md,relative,,yes +web/src/lib/presets/README.md,firmware/patternflow/presets/README.md,relative,,yes +web/src/lib/presets/README.md,web/ARCHITECTURE.md,relative,pattern-system,yes +web/src/lib/presets/pattern-0624.ts,/,site,,yes +web/src/lib/presets/pattern-0624.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0628.ts,/,site,,yes +web/src/lib/presets/pattern-0628.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0629-2.ts,/,site,,yes +web/src/lib/presets/pattern-0629.ts,/,site,,yes +web/src/lib/presets/pattern-0701.ts,/,site,,yes +web/src/lib/presets/pattern-0707.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0710.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0712-2.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0712.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0713.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0715.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0716.ts,/pattern,site,,yes +web/src/lib/presets/pattern-0718.ts,/pattern-lab,site,,yes +web/src/lib/presets/pattern-0719.ts,/pattern-lab,site,,yes diff --git a/web/package.json b/web/package.json index d05a1187d..a462f844d 100644 --- a/web/package.json +++ b/web/package.json @@ -41,7 +41,8 @@ "check:panels": "vitest run", "check:ci": "npm run check:license && npm run check:moderation && npm run check:headermod && npm run check:hidemod && npm run check:retention && npm run check:deck && npm run check:pack && npm run check:sharing && npm run check:publish && npm run check:notify && npm run check:ports && npm run check:workshop && npm run check:sandbox && npm run check:capture && npm run check:thumbs && npm run check:flatten && npm run check:labedit && npm run check:performance && npm run check:pixelcode && npm run check:director && npm run check:pfstvectors && npm run check:ramp && npm run check:panels && npm run check:sandbox-sync && npm run check:modcache", "build:sandbox": "tsx scripts/build-sandbox.ts", - "check:sandbox-sync": "tsx scripts/build-sandbox.ts --check" + "check:sandbox-sync": "tsx scripts/build-sandbox.ts --check", + "doc-map": "tsx scripts/doc-map.ts" }, "dependencies": { "@google/genai": "^2.9.0", diff --git a/web/scripts/doc-map.ts b/web/scripts/doc-map.ts new file mode 100644 index 000000000..5c02ba1b0 --- /dev/null +++ b/web/scripts/doc-map.ts @@ -0,0 +1,216 @@ +/** + * The doc map: every link into this repository, and whether it lands. + * `npm run doc-map` in web/ writes docs/investigations/2026-10-doc-map.csv. + * + * Moving a file breaks the links that point at it, and only one kind of link + * is watched: the relative ones in Markdown (.github/scripts/check_links.py). + * The site points at the guides by absolute GitHub URL. The console pages the + * device serves point at docs and at the site. The redirect table sends old + * URLs to new ones. None of those fail a build when the file they name moves, + * so the cleanup (docs/rfc-cleanup.md §2.2) maps them before it moves anything. + * + * Sources are the tracked .md, .mdx, .ts, .tsx and .h files, the console + * pages, and the redirect table in next.config.ts. Vendored upstream code is + * skipped, as check_links.py skips it, and so are the *_index.h headers, + * which are the console pages again. Kinds: + * + * relative a path in Markdown, resolved against the file it is in + * absolute-blob github.com//Patternflow/blob|tree// + * absolute-raw raw.githubusercontent.com/..., or .../raw// + * site patternflow.work/, a root-relative Markdown link, or + * a redirect destination; checked against web/src/app, + * web/public and the redirect and rewrite sources + * console a root-relative link in a console page; checked against + * the paths the firmware registers with .on("/path") + * + * An anchor into a Markdown file has to match one of its headings, slugged + * the way GitHub slugs them. A ref other than main is read with git, and a + * shallow clone has no tags: run `git fetch --tags` first or those rows say no. + */ +import { execFileSync } from "node:child_process"; +import fs from "node:fs"; +import path from "node:path"; + +const ROOT = execFileSync("git", ["rev-parse", "--show-toplevel"], { encoding: "utf8" }).trim(); +const OUT = "docs/investigations/2026-10-doc-map.csv"; +const CONSOLE = "firmware/patternflow/console/"; +const REDIRECTS = "web/next.config.ts"; +const SKIP = /(^|\/)(hub75|webserver|pubsubclient)\//; + +const git = (args: string[]) => + execFileSync("git", args, { cwd: ROOT, encoding: "utf8", maxBuffer: 1 << 28, stdio: ["ignore", "pipe", "ignore"] }); +const tracked = git(["ls-files", "-z"]).split("\0").filter(Boolean); +const files = new Set(tracked); +const dirs = new Set([""]); +for (const f of tracked) for (let d = path.posix.dirname(f); d !== "."; d = path.posix.dirname(d)) dirs.add(d); + +// ── What a link can land on ── + +const read = (f: string) => fs.readFileSync(path.join(ROOT, f), "utf8"); + +const atRef = new Map(); +function contentAt(ref: string, p: string): string | null { + if (ref === "main" || ref === "HEAD") return files.has(p) ? read(p) : dirs.has(p) ? "" : null; + const key = `${ref}:${p}`; + if (!atRef.has(key)) { + try { + atRef.set(key, git(["cat-file", "-p", key])); + } catch { + atRef.set(key, null); + } + } + return atRef.get(key) ?? null; +} + +// GitHub's heading ids: rendered text, lower-cased, punctuation dropped, +// spaces to hyphens, a repeat numbered -1, -2. Plus any explicit id= or name=. +function anchorsOf(md: string): Set { + const out = new Set(); + const seen = new Map(); + for (const line of md.replace(/```[\s\S]*?```/g, "").split("\n")) { + const h = /^ {0,3}#{1,6}\s+(.*?)\s*#*\s*$/.exec(line); + if (!h) continue; + const text = h[1].replace(/!?\[([^\]]*)\]\([^)]*\)/g, "$1").replace(/<[^>]+>/g, "").replace(/[*`~]/g, ""); + const base = text.toLowerCase().replace(/[^\p{L}\p{M}\p{N}\p{Pc} -]/gu, "").replace(/ /g, "-"); + const n = seen.get(base) ?? 0; + seen.set(base, n + 1); + out.add(n ? `${base}-${n}` : base); + } + for (const m of md.matchAll(/\b(?:id|name)=["']([^"']+)["']/g)) out.add(m[1].toLowerCase()); + return out; +} + +const pattern = (route: string) => + new RegExp( + "^" + + route + .replace(/\[\[\.\.\.\w+\]\]/g, "\u0001") + .replace(/\[\.\.\.\w+\]/g, "\u0002") + .replace(/\[\w+\]|:\w+\*?/g, "\u0003") + .replace(/[.*+?^${}()|[\]\\]/g, "\\$&") + .replace(/\/?\u0001/g, "(?:/.*)?") + .replace(/\u0002/g, ".+") + .replace(/\u0003/g, "[^/]+") + + "$", + ); + +const publicFiles = new Set(tracked.filter((f) => f.startsWith("web/public/")).map((f) => f.slice("web/public".length))); +const siteRoutes = [pattern("/sitemap.xml"), pattern("/robots.txt")]; +for (const f of tracked) { + const app = /^web\/src\/app(\/.*)?\/(?:page|route)\.(?:tsx?|jsx?|mdx?)$/.exec(f); + if (app) siteRoutes.push(pattern((app[1] ?? "").replace(/\/\([^/]+\)/g, "") || "/")); +} +// Redirect sources only: the headers() block has sources too, and they are not pages. +const redirects = read(REDIRECTS).split("async redirects()")[1]?.split("async rewrites()")[0] ?? ""; +for (const m of redirects.matchAll(/\bsource: "(\/[^"]*)"/g)) siteRoutes.push(pattern(m[1])); +for (const m of read("web/src/lib/campaignRoutes.ts").matchAll(/\bpath: "(\/[^"]*)"/g)) siteRoutes.push(pattern(m[1])); + +const deviceRoutes = new Set(); +for (const f of tracked.filter((f) => /^firmware\/patternflow\/.*\.(h|ino|cpp)$/.test(f))) + for (const m of read(f).matchAll(/\.on\(\s*"(\/[^"]*)"/g)) deviceRoutes.add(m[1]); + +// ── Reading links out of a file ── + +type Row = { from: string; to: string; kind: string; anchor: string; resolves: "yes" | "no" }; + +const REPO_URL = + /^https?:\/\/(?:www\.)?(?:github\.com\/(?:engmung|patternflow-lab)\/patternflow\/(blob|tree|raw|edit)|raw\.githubusercontent\.com\/(?:engmung|patternflow-lab)\/patternflow)\/([^/?#]+)\/?([^?#]*)/i; +const SITE_URL = /^https?:\/\/(?:www\.)?patternflow\.work(\/[^?#]*)?/i; +const URL_IN_TEXT = /https?:\/\/(?:www\.)?(?:github\.com|raw\.githubusercontent\.com|patternflow\.work)[^\s"'`<>)\]]*/gi; + +function decode(p: string): string { + try { + return decodeURIComponent(p); + } catch { + return p; + } +} + +function classify(from: string, raw: string, markdown: boolean): Row | null { + const target = raw.replace(/^<|>$/g, "").replace(/[.,;:]+$/, ""); + if (target.includes("${")) return null; // a template the constants did not fill + const anchor = target.includes("#") ? decode(target.slice(target.indexOf("#") + 1)) : ""; + const row = (to: string, kind: string, ok: boolean): Row => ({ from, to, kind, anchor, resolves: ok ? "yes" : "no" }); + const fileRow = (ref: string, p: string, kind: string) => { + const body = contentAt(ref, p); + const ok = body !== null && (!anchor || !/\.mdx?$/.test(p) || /^L\d+/.test(anchor) || anchorsOf(body).has(anchor.toLowerCase())); + return row(ref === "main" ? p : `${ref}:${p}`, kind, ok); + }; + const site = (p: string) => { + const route = p.length > 1 ? p.replace(/\/+$/, "") : p; + return row(route, "site", publicFiles.has(route) || siteRoutes.some((r) => r.test(route))); + }; + + const repo = REPO_URL.exec(target); + if (repo) { + const kind = repo[1] && repo[1].toLowerCase() !== "raw" ? "absolute-blob" : "absolute-raw"; + const p = decode(repo[3]).replace(/\/$/, ""); + return p ? fileRow(repo[2], p, kind) : null; // the repository's front page, which no move breaks + } + const web = SITE_URL.exec(target); + if (web) return site(decode(web[1] ?? "/")); + if (/^[a-z][a-z0-9+.-]*:|^\/\/|^#/i.test(target)) return null; + const p = decode(target.split("#")[0].split("?")[0]); + if (from.startsWith(CONSOLE)) { + if (!p.startsWith("/")) return null; + const route = p.length > 1 ? p.replace(/\/+$/, "") : p; + return row(route, "console", deviceRoutes.has(route)); + } + if (!markdown || !p) return null; + if (p.startsWith("/")) return site(p); + if (p.startsWith("../../") && path.posix.normalize(path.posix.join(path.posix.dirname(from), p)).startsWith("../")) + return null; // GitHub's own pages (../../releases), not files + return fileRow("main", path.posix.normalize(path.posix.join(path.posix.dirname(from), p)).replace(/\/$/, ""), "relative"); +} + +// `const REPO = "https://github.com/…"`, `${REPO}/blob/main/x` and one-line +// helpers like `blob("x")` are how the site writes its GitHub links. +function expandConstants(text: string): string { + const consts = new Map(); + for (let pass = 0; pass < 3; pass++) { + for (const m of text.matchAll(/\bconst (\w+) = (["'`])(https?:\/\/[^"'`$]*)\2/g)) consts.set(m[1], m[3]); + text = text.replace(/\$\{(\w+)\}/g, (s, n: string) => consts.get(n) ?? s); + } + for (const m of text.matchAll(/\bconst (\w+) = \((\w+)(?:: string)?\) =>\s*`(https?:\/\/[^`$]*)\$\{\2\}`/g)) + text = text.replace(new RegExp(`\\b${m[1]}\\((["'])([^"']*)\\1\\)`, "g"), (_s, _q, arg: string) => m[3] + arg); + return text; +} + +function linksIn(f: string): Row[] { + const markdown = /\.mdx?$/.test(f); + let text = read(f); + const found: [string, boolean][] = []; + if (markdown) text = text.replace(/```[\s\S]*?```/g, "").replace(/`[^`\n]*`/g, ""); + if (/\.tsx?$/.test(f)) text = expandConstants(text); + // In code, `a[i](x)` looks like a Markdown link; only a path that starts like one counts. + for (const m of text.matchAll(/\]\(\s*(<[^>]+>|[^)\s]+)/g)) found.push([m[1], markdown || /^\.{0,2}\//.test(m[1])]); + if (markdown) for (const m of text.matchAll(/^\s*\[(?!\^)[^\]]+\]:\s*(\S+)/gm)) found.push([m[1], true]); + for (const m of text.matchAll(/\b(?:href|src)=["']([^"']+)["']/g)) found.push([m[1], markdown]); + for (const m of text.matchAll(URL_IN_TEXT)) found.push([m[0], false]); + if (f === REDIRECTS) for (const m of text.matchAll(/\bdestination: "(\/[^"]*)"/g)) found.push([m[1], true]); + return found.map(([raw, md]) => classify(f, raw, md)).filter((r): r is Row => r !== null); +} + +// ── The map ── + +const sources = tracked.filter( + (f) => + !SKIP.test(f) && + (/\.(mdx?|tsx?)$/.test(f) || + (f.endsWith(".h") && !f.endsWith("_index.h")) || + (f.startsWith(CONSOLE) && f.endsWith(".html"))), +); +const key = (r: Row) => [r.from, r.to, r.anchor, r.kind].join("\0"); +const rows = new Map(); +for (const f of sources) for (const r of linksIn(f)) rows.set(key(r), r); + +const cell = (v: string) => (/[",\n]/.test(v) ? `"${v.replace(/"/g, '""')}"` : v); +// Code-point order, not the locale's, so the file is the same on every machine. +const sorted = [...rows.values()].sort((a, b) => (key(a) < key(b) ? -1 : key(a) > key(b) ? 1 : 0)); +const csv = ["from,to,kind,anchor,resolves", ...sorted.map((r) => [r.from, r.to, r.kind, r.anchor, r.resolves].map(cell).join(","))]; +fs.writeFileSync(path.join(ROOT, OUT), csv.join("\n") + "\n"); + +const broken = sorted.filter((r) => r.resolves === "no"); +console.log(`${sorted.length} links from ${new Set(sorted.map((r) => r.from)).size} files → ${OUT}`); +console.log(`${broken.length} do not resolve`); +for (const r of broken) console.log(` ${r.from} → ${r.to}${r.anchor ? "#" + r.anchor : ""} (${r.kind})`); From 6646ab69f9bcc8d3edb0d1a0f0b5876582b494e4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 11:57:03 +0000 Subject: [PATCH 3/4] docs: record the cleanup baseline at 8226f7e Step 0 of rfc-cleanup.md: the five commands, the doc map, and the cleanup-window rule. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014L3ZRG6hS4BH2Q8YQjhzS5 --- AGENTS.md | 1 + .../2026-10-cleanup-baseline.md | 82 +++++++++++++++++++ docs/investigations/2026-10-doc-map.csv | 7 ++ docs/rfc-cleanup-progress.md | 20 ++++- web/scripts/doc-map.ts | 69 +++++----------- 5 files changed, 129 insertions(+), 50 deletions(-) create mode 100644 docs/investigations/2026-10-cleanup-baseline.md diff --git a/AGENTS.md b/AGENTS.md index 9a3f68dd6..306e68560 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ It is standalone (not Eurorack), powered from a 5 V power bank through a screw t 5. Known issues of the current board are documented in `BUILD_GUIDE.md` section 10; the v2.0 fixes and leftovers are in `BUILD_GUIDE_v2.md` section 10. Reference those sections instead of restating the issues. 6. **The board has exactly one power input: `J4`, the screw terminal. Never describe USB-C as a power option.** v3.9 removed the `USB1` footprint and its `R1`/`R2` CC pull-downs outright, after a USB-C-powered v3.0 board ran for 20–30 minutes and then smoked at a connector pin ([#221](https://github.com/engmung/Patternflow/issues/221)) — the failure is delayed, so "it seems to work" is not evidence. On v3.9 the footprint does not exist; on a v3.0 board already in someone's hands, `USB1`/`R1`/`R2` stay unpopulated. Release notes and changelog entries that record the hold as it stood are history — update current-state docs, leave the record alone. 7. **The firmware core is not the place to put a feature.** `firmware/patternflow/patternflow.ino` and `firmware/patternflow/src/` are the device itself — panel, encoders, pattern loader, Wi-Fi, sleep, console — and every published firmware compiles them **unchanged**. They change for a bug or a real improvement to the device, and nothing else; a feature bends to fit the core, never the reverse. Features attach through the hooks in `firmware/patternflow/features/pf_feature.h`, and the core names none of them — no `#include`, no `#if PF__ENABLED`, not even a feature's name in a string on the screen or in a console page. Before editing the core, ask whether the edit would still be correct on a build that does not contain the feature you are working on; if not, it belongs in `features/`. The full reasoning is [`docs/EDITIONS.md`](docs/EDITIONS.md), and the header comment of `patternflow.ino` lists the regressions this rule exists because of. +8. During a cleanup window (see [`docs/rfc-cleanup.md`](docs/rfc-cleanup.md)) no PR changes behaviour; moves and renames carry a redirect or an updated link map. ## Common commands - Web dev server: `npm run dev` (inside the `web/` directory) diff --git a/docs/investigations/2026-10-cleanup-baseline.md b/docs/investigations/2026-10-cleanup-baseline.md new file mode 100644 index 000000000..01899d731 --- /dev/null +++ b/docs/investigations/2026-10-cleanup-baseline.md @@ -0,0 +1,82 @@ +# Cleanup baseline + +*Step 0 of [rfc-cleanup.md](../rfc-cleanup.md), §2.2. Run on 14 October 2026.* + +The cleanup starts from `8226f7ea5da15b0e0e55b15fa9ec7af136eef080` on `dev`, +the commit that added [rfc-cleanup-progress.md](../rfc-cleanup-progress.md). +Project v3.11.0, Audio v0.7.0, Performance v0.4.0. The last commit to touch +`firmware/` or `web/` before it is `caaf2c1`, on 12 October. + +The commands ran in a cloud container on that tree with nothing added: Linux, +Node 22.22.0 and npm 10.9.4, Python 3.13, `npm ci` from `web/package-lock.json`. +CI runs Node 20. + +## The five commands + +| command | result | output | +| --- | --- | --- | +| `firmware/bundles/build.sh all` | not run | see below | +| `npm run check:ci` | pass | 25 suites, last line `All module cache checks passed.`, 50 s | +| `npm run check:panels` | pass | 35 test files, 478 tests, 19 s | +| `npm run typecheck` | pass | `tsc --noEmit` prints nothing, 27 s | +| `npm run lint` | pass | 0 errors, 12 warnings, 50 s | + +None of the four that ran is red, so there is no fix PR to land before Step 1. + +`build.sh all` never reached the compiler. PlatformIO fetches the espressif32 +7.0.1 platform and the Xtensa toolchain from `api.registry.platformio.org`, and +the container's network policy refuses that host (403 on CONNECT). The run stopped +after 68 seconds at `Platform Manager: Installing espressif32 @ 7.0.1` with +`HTTPClientError`. No CI result can stand in for it: GitHub Actions has no runs +on the Patternflow-lab fork, where `dev` lives. The firmware line stays open +until somebody runs `./firmware/bundles/build.sh all` at this SHA on a machine +that reaches the registry and pastes the last lines here. + +What runs without the Xtensa compiler did run, and passed. Those are the 17 +host-side checks in `firmware-checks.yml`, `check_boundaries.py` through +`check_versions.py` with the sanitizer builds, the two checks in +`console-sync.yml`, and `.github/scripts/check_links.py` (624 relative links). +They say the boundary, the ABI freeze, the presets and the console headers +hold. They do not say the five compositions compile. + +The lint warnings, for Step 3: + +| file | line | rule | +| --- | --- | --- | +| `web/scripts/performance-smoke.ts` | 16 | `@typescript-eslint/no-unused-vars` | +| `web/src/app/build/breadboard/page.tsx` | 394, 435, 476, 514, 556 | `@next/next/no-img-element` | +| `web/src/app/editions/EditionCard.tsx` | 35 | `@typescript-eslint/no-unused-vars` | +| `web/src/app/roadmap/RoadmapMap.tsx` | 272 | `@typescript-eslint/no-unused-vars` | +| `web/src/app/roadmap/RoadmapMap.tsx` | 315 | `react-hooks/exhaustive-deps` | +| `web/src/components/community/PatternCard.tsx` | 8 | `@typescript-eslint/no-unused-vars` | +| `web/src/components/journal/JournalLightbox.tsx` | 86 | `@next/next/no-img-element` | +| `web/src/components/sections/Hero.tsx` | 55 | `@next/next/no-img-element` | + +## The doc map + +`npm run doc-map` in `web/` ([doc-map.ts](../../web/scripts/doc-map.ts)) +wrote [2026-10-doc-map.csv](2026-10-doc-map.csv): 1007 links out of 193 +files, 7 of them from this file, `AGENTS.md` and the progress log as Step 0 +leaves them. 532 are relative, 329 site, 114 absolute-blob and 32 console. +None is absolute-raw; nothing links through `raw.githubusercontent.com`. + +24 of the absolute-blob rows name a release tag, `v1.0.0` to `v3.1.0`, from the +roadmap, the release notes and the hardware READMEs. A shallow clone has no +tags and reports those 24 as `no`, so fetch the tags before running the script. + +The map leaves out links that a file move cannot break: a bare `#anchor` +inside one file, the repository's front page, issues, pull requests and +releases. It also leaves out the site's own route links (`href="/guide"` in a +component), the vendored upstream docs under `hub75/`, `webserver/` and +`pubsubclient/`, and the `*_index.h` headers, which are the console pages again. + +§2.3 expects the site to link `BUILD_GUIDE_v2.md` at §1, §2, §4, §8 and §10. +At this SHA it links it once, from `BuildPanel.tsx`, with no anchor. The +anchored links go to `BUILD_GUIDE.md`. Moving the v2 guide touches that one +site link, the test beside it, and five Markdown files: `README.md`, +`BUILD_GUIDE.md`, `docs/assembly/README.md`, `hardware/README.md` and +`hardware/case/README.md`. + +## Known broken + +None. Every row in the map resolves. diff --git a/docs/investigations/2026-10-doc-map.csv b/docs/investigations/2026-10-doc-map.csv index 4e5b43cd4..bb3c9aa69 100644 --- a/docs/investigations/2026-10-doc-map.csv +++ b/docs/investigations/2026-10-doc-map.csv @@ -1,6 +1,7 @@ from,to,kind,anchor,resolves .github/PULL_REQUEST_TEMPLATE.md,CONTRIBUTING.md,absolute-blob,where-your-contribution-goes,yes AGENTS.md,docs/EDITIONS.md,relative,,yes +AGENTS.md,docs/rfc-cleanup.md,relative,,yes AUDIO_GUIDE.md,/editions,site,,yes AUDIO_GUIDE.md,/guide/audio,site,,yes AUDIO_GUIDE.md,AGENTS.md,relative,hard-rules-do-not-violate,yes @@ -359,6 +360,10 @@ docs/director-midi.md,integrations/ableton/docs/recording-sync.md,relative,,yes docs/investigations/2026-09-firmware-runtime.md,docs/investigations/2026-09-runtime-improvements.json,relative,,yes docs/investigations/2026-09-firmware-runtime.md,docs/investigations/2026-09-runtime-research/README.md,relative,,yes docs/investigations/2026-09-runtime-research/README.md,docs/investigations/2026-09-firmware-runtime.md,relative,,yes +docs/investigations/2026-10-cleanup-baseline.md,docs/investigations/2026-10-doc-map.csv,relative,,yes +docs/investigations/2026-10-cleanup-baseline.md,docs/rfc-cleanup-progress.md,relative,,yes +docs/investigations/2026-10-cleanup-baseline.md,docs/rfc-cleanup.md,relative,,yes +docs/investigations/2026-10-cleanup-baseline.md,web/scripts/doc-map.ts,relative,,yes docs/manifesto.md,/inside,site,,yes docs/midi-ableton.md,docs/director-midi.md,relative,,yes docs/midi-ableton.md,docs/images/midi/ableton-5-remote.png,relative,,yes @@ -401,6 +406,8 @@ docs/rest-api.md,docs/audio-ws-spec.md,relative,,yes docs/rest-api.md,docs/audio-ws-spec.md,relative,the-switch-on-the-panel,yes docs/rest-api.md,docs/midi-spec.md,relative,,yes docs/rest-api.md,docs/mqtt-spec.md,relative,,yes +docs/rfc-cleanup-progress.md,docs/investigations/2026-10-cleanup-baseline.md,relative,,yes +docs/rfc-cleanup-progress.md,docs/investigations/2026-10-doc-map.csv,relative,,yes docs/rfc-cleanup-progress.md,docs/rfc-cleanup.md,relative,,yes docs/rfc-core-and-variants-progress.md,docs/EDITIONS.md,relative,,yes docs/rfc-core-and-variants-progress.md,docs/pfst-v2-vectors,relative,,yes diff --git a/docs/rfc-cleanup-progress.md b/docs/rfc-cleanup-progress.md index 0af498365..ec9a45560 100644 --- a/docs/rfc-cleanup-progress.md +++ b/docs/rfc-cleanup-progress.md @@ -5,11 +5,11 @@ against the step order in §2.12. Updated as PRs land. Entries are added by whoever merges; the table is the summary, the sections below are the record. -**Where it stands: not started.** Baseline SHA to be recorded in step 0. +**Where it stands: step 0, firmware line open.** Baseline SHA `8226f7e`. | step | what | state | | --- | --- | --- | -| 0 | Baseline: CI record, doc map, cleanup-window rule in `AGENTS.md` | — | +| 0 | Baseline: CI record, doc map, cleanup-window rule in `AGENTS.md` | web, doc map and rule in ([#11](https://github.com/Patternflow-lab/Patternflow/pull/11)); `build.sh all` not run yet | | 1 | Document structure: root, legacy guide, CHANGELOG split, ko/en parity list | — | | 2 | Drift checks: links, BOM triad, features, editions, presets, roadmap | — | | 3 | Code hygiene: lint/typecheck zero, legacy named or gone, HUB75 upstream patch, shared constants | — | @@ -22,4 +22,18 @@ Gate for any-resolution (§2.12): not met. ## Step 0 — baseline -*(empty)* +[#11](https://github.com/Patternflow-lab/Patternflow/pull/11), 14 October +2026. The cleanup starts from `8226f7ea5da15b0e0e55b15fa9ec7af136eef080` on +`dev`. The record is +[investigations/2026-10-cleanup-baseline.md](investigations/2026-10-cleanup-baseline.md). + +At that SHA `check:ci` passes its 25 suites, `check:panels` its 478 tests, +and `typecheck` is clean. `lint` has no errors and 12 warnings, listed in the +record for Step 3. `build.sh all` did not run: the container that ran the rest +cannot reach the PlatformIO registry, and the fork has no Actions runs to read +instead. Step 0 is not done until somebody runs it at that SHA. + +`npm run doc-map` in `web/` writes +[investigations/2026-10-doc-map.csv](investigations/2026-10-doc-map.csv). +1007 links out of 193 files, every one resolving, so the known-broken list is +empty. `AGENTS.md` carries the cleanup-window rule as hard rule 8. diff --git a/web/scripts/doc-map.ts b/web/scripts/doc-map.ts index 5c02ba1b0..b2cee3bdd 100644 --- a/web/scripts/doc-map.ts +++ b/web/scripts/doc-map.ts @@ -47,18 +47,21 @@ for (const f of tracked) for (let d = path.posix.dirname(f); d !== "."; d = path // ── What a link can land on ── const read = (f: string) => fs.readFileSync(path.join(ROOT, f), "utf8"); +const attempt = (f: () => T, fallback: T): T => { + try { + return f(); + } catch { + return fallback; + } +}; +const decode = (p: string) => attempt(() => decodeURIComponent(p), p); +const trim = (p: string) => (p.length > 1 ? p.replace(/\/+$/, "") : p); const atRef = new Map(); function contentAt(ref: string, p: string): string | null { if (ref === "main" || ref === "HEAD") return files.has(p) ? read(p) : dirs.has(p) ? "" : null; const key = `${ref}:${p}`; - if (!atRef.has(key)) { - try { - atRef.set(key, git(["cat-file", "-p", key])); - } catch { - atRef.set(key, null); - } - } + if (!atRef.has(key)) atRef.set(key, attempt(() => git(["cat-file", "-p", key]), null)); return atRef.get(key) ?? null; } @@ -80,19 +83,12 @@ function anchorsOf(md: string): Set { return out; } -const pattern = (route: string) => - new RegExp( - "^" + - route - .replace(/\[\[\.\.\.\w+\]\]/g, "\u0001") - .replace(/\[\.\.\.\w+\]/g, "\u0002") - .replace(/\[\w+\]|:\w+\*?/g, "\u0003") - .replace(/[.*+?^${}()|[\]\\]/g, "\\$&") - .replace(/\/?\u0001/g, "(?:/.*)?") - .replace(/\u0002/g, ".+") - .replace(/\u0003/g, "[^/]+") + - "$", - ); +// A route or redirect source as a regex; [[...x]], [...x], [x] and :x are its parameters. +const pattern = (route: string) => { + const marked = route.replace(/\[\[\.\.\.\w+\]\]/g, "\u0001").replace(/\[\.\.\.\w+\]/g, "\u0002").replace(/\[\w+\]|:\w+\*?/g, "\u0003"); + const escaped = marked.replace(/[.*+?^${}()|[\]\\]/g, "\\$&").replace(/\/?\u0001/g, "(?:/.*)?"); + return new RegExp(`^${escaped.replace(/\u0002/g, ".+").replace(/\u0003/g, "[^/]+")}$`); +}; const publicFiles = new Set(tracked.filter((f) => f.startsWith("web/public/")).map((f) => f.slice("web/public".length))); const siteRoutes = [pattern("/sitemap.xml"), pattern("/robots.txt")]; @@ -118,14 +114,6 @@ const REPO_URL = const SITE_URL = /^https?:\/\/(?:www\.)?patternflow\.work(\/[^?#]*)?/i; const URL_IN_TEXT = /https?:\/\/(?:www\.)?(?:github\.com|raw\.githubusercontent\.com|patternflow\.work)[^\s"'`<>)\]]*/gi; -function decode(p: string): string { - try { - return decodeURIComponent(p); - } catch { - return p; - } -} - function classify(from: string, raw: string, markdown: boolean): Row | null { const target = raw.replace(/^<|>$/g, "").replace(/[.,;:]+$/, ""); if (target.includes("${")) return null; // a template the constants did not fill @@ -136,10 +124,7 @@ function classify(from: string, raw: string, markdown: boolean): Row | null { const ok = body !== null && (!anchor || !/\.mdx?$/.test(p) || /^L\d+/.test(anchor) || anchorsOf(body).has(anchor.toLowerCase())); return row(ref === "main" ? p : `${ref}:${p}`, kind, ok); }; - const site = (p: string) => { - const route = p.length > 1 ? p.replace(/\/+$/, "") : p; - return row(route, "site", publicFiles.has(route) || siteRoutes.some((r) => r.test(route))); - }; + const site = (p: string) => row(trim(p), "site", publicFiles.has(trim(p)) || siteRoutes.some((r) => r.test(trim(p)))); const repo = REPO_URL.exec(target); if (repo) { @@ -151,16 +136,11 @@ function classify(from: string, raw: string, markdown: boolean): Row | null { if (web) return site(decode(web[1] ?? "/")); if (/^[a-z][a-z0-9+.-]*:|^\/\/|^#/i.test(target)) return null; const p = decode(target.split("#")[0].split("?")[0]); - if (from.startsWith(CONSOLE)) { - if (!p.startsWith("/")) return null; - const route = p.length > 1 ? p.replace(/\/+$/, "") : p; - return row(route, "console", deviceRoutes.has(route)); - } + if (from.startsWith(CONSOLE)) return p.startsWith("/") ? row(trim(p), "console", deviceRoutes.has(trim(p))) : null; if (!markdown || !p) return null; if (p.startsWith("/")) return site(p); - if (p.startsWith("../../") && path.posix.normalize(path.posix.join(path.posix.dirname(from), p)).startsWith("../")) - return null; // GitHub's own pages (../../releases), not files - return fileRow("main", path.posix.normalize(path.posix.join(path.posix.dirname(from), p)).replace(/\/$/, ""), "relative"); + const local = path.posix.normalize(path.posix.join(path.posix.dirname(from), p)).replace(/\/$/, ""); + return local.startsWith("../") ? null : fileRow("main", local, "relative"); // ../../releases is GitHub's page, not a file } // `const REPO = "https://github.com/…"`, `${REPO}/blob/main/x` and one-line @@ -193,13 +173,8 @@ function linksIn(f: string): Row[] { // ── The map ── -const sources = tracked.filter( - (f) => - !SKIP.test(f) && - (/\.(mdx?|tsx?)$/.test(f) || - (f.endsWith(".h") && !f.endsWith("_index.h")) || - (f.startsWith(CONSOLE) && f.endsWith(".html"))), -); +const sources = tracked.filter((f) => !SKIP.test(f) && (/\.(mdx?|tsx?)$/.test(f) || + (f.endsWith(".h") && !f.endsWith("_index.h")) || (f.startsWith(CONSOLE) && f.endsWith(".html")))); const key = (r: Row) => [r.from, r.to, r.anchor, r.kind].join("\0"); const rows = new Map(); for (const f of sources) for (const r of linksIn(f)) rows.set(key(r), r); From ad1083f80417b06f09f7a49291247e32df2e6783 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 14 Oct 2026 12:04:38 +0000 Subject: [PATCH 4/4] docs: record the firmware baseline from CI The container cannot reach the PlatformIO registry; firmware-build.yml ran on dev at 8226f7e instead. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_014L3ZRG6hS4BH2Q8YQjhzS5 --- .../2026-10-cleanup-baseline.md | 43 ++++++++++--------- docs/rfc-cleanup-progress.md | 9 ++-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/docs/investigations/2026-10-cleanup-baseline.md b/docs/investigations/2026-10-cleanup-baseline.md index 01899d731..92c1ec5a3 100644 --- a/docs/investigations/2026-10-cleanup-baseline.md +++ b/docs/investigations/2026-10-cleanup-baseline.md @@ -7,37 +7,38 @@ the commit that added [rfc-cleanup-progress.md](../rfc-cleanup-progress.md). Project v3.11.0, Audio v0.7.0, Performance v0.4.0. The last commit to touch `firmware/` or `web/` before it is `caaf2c1`, on 12 October. -The commands ran in a cloud container on that tree with nothing added: Linux, -Node 22.22.0 and npm 10.9.4, Python 3.13, `npm ci` from `web/package-lock.json`. -CI runs Node 20. +The web commands ran in a cloud container on that tree with nothing added: +Node 22.22.0, npm 10.9.4, `npm ci` from `web/package-lock.json`. CI runs Node 20. ## The five commands | command | result | output | | --- | --- | --- | -| `firmware/bundles/build.sh all` | not run | see below | +| `firmware/bundles/build.sh all` | pass, on CI | five compositions built and scanned, see below | | `npm run check:ci` | pass | 25 suites, last line `All module cache checks passed.`, 50 s | | `npm run check:panels` | pass | 35 test files, 478 tests, 19 s | | `npm run typecheck` | pass | `tsc --noEmit` prints nothing, 27 s | | `npm run lint` | pass | 0 errors, 12 warnings, 50 s | -None of the four that ran is red, so there is no fix PR to land before Step 1. - -`build.sh all` never reached the compiler. PlatformIO fetches the espressif32 -7.0.1 platform and the Xtensa toolchain from `api.registry.platformio.org`, and -the container's network policy refuses that host (403 on CONNECT). The run stopped -after 68 seconds at `Platform Manager: Installing espressif32 @ 7.0.1` with -`HTTPClientError`. No CI result can stand in for it: GitHub Actions has no runs -on the Patternflow-lab fork, where `dev` lives. The firmware line stays open -until somebody runs `./firmware/bundles/build.sh all` at this SHA on a machine -that reaches the registry and pastes the last lines here. - -What runs without the Xtensa compiler did run, and passed. Those are the 17 -host-side checks in `firmware-checks.yml`, `check_boundaries.py` through -`check_versions.py` with the sanitizer builds, the two checks in -`console-sync.yml`, and `.github/scripts/check_links.py` (624 relative links). -They say the boundary, the ABI freeze, the presets and the console headers -hold. They do not say the five compositions compile. +None of the five is red, so there is no fix PR to land before Step 1. + +The container cannot build firmware. PlatformIO fetches the espressif32 platform +and the Xtensa toolchain from `api.registry.platformio.org`, and the container's +network policy refuses that host (403 on CONNECT). So `build.sh all` ran the way +CI runs it, `build.sh one ` per job, in `firmware-build.yml` +dispatched on `dev` at this SHA ([run 38560727407](https://github.com/Patternflow-lab/Patternflow/actions/runs/38560727407)). +Each job scans its image for the feature markers: + +``` +default 1102672 bytes ok +audio 1208656 bytes ok +performance 1526624 bytes ok +clock 1187088 bytes ok +midi 1163440 bytes ok +``` + +`check_footprint.py` says `every edition within tolerance` in all five. The 17 +host-side checks in `firmware-checks.yml` and the two in `console-sync.yml` pass. The lint warnings, for Step 3: diff --git a/docs/rfc-cleanup-progress.md b/docs/rfc-cleanup-progress.md index ec9a45560..d70dee051 100644 --- a/docs/rfc-cleanup-progress.md +++ b/docs/rfc-cleanup-progress.md @@ -5,11 +5,11 @@ against the step order in §2.12. Updated as PRs land. Entries are added by whoever merges; the table is the summary, the sections below are the record. -**Where it stands: step 0, firmware line open.** Baseline SHA `8226f7e`. +**Where it stands: step 0 done, step 1 next.** Baseline SHA `8226f7e`. | step | what | state | | --- | --- | --- | -| 0 | Baseline: CI record, doc map, cleanup-window rule in `AGENTS.md` | web, doc map and rule in ([#11](https://github.com/Patternflow-lab/Patternflow/pull/11)); `build.sh all` not run yet | +| 0 | Baseline: CI record, doc map, cleanup-window rule in `AGENTS.md` | done ([#11](https://github.com/Patternflow-lab/Patternflow/pull/11)) | | 1 | Document structure: root, legacy guide, CHANGELOG split, ko/en parity list | — | | 2 | Drift checks: links, BOM triad, features, editions, presets, roadmap | — | | 3 | Code hygiene: lint/typecheck zero, legacy named or gone, HUB75 upstream patch, shared constants | — | @@ -29,9 +29,8 @@ Gate for any-resolution (§2.12): not met. At that SHA `check:ci` passes its 25 suites, `check:panels` its 478 tests, and `typecheck` is clean. `lint` has no errors and 12 warnings, listed in the -record for Step 3. `build.sh all` did not run: the container that ran the rest -cannot reach the PlatformIO registry, and the fork has no Actions runs to read -instead. Step 0 is not done until somebody runs it at that SHA. +record for Step 3. `build.sh all` ran on GitHub Actions, because the container +cannot reach the PlatformIO registry, and all five compositions built. `npm run doc-map` in `web/` writes [investigations/2026-10-doc-map.csv](investigations/2026-10-doc-map.csv).