Repository navigation
Fix/matter - #28
Closed
khlam wants to merge 68 commits into
Closed
Fix/matter#28khlam wants to merge 68 commits into
khlam wants to merge 68 commits into
Conversation
khlam
force-pushed
the
fix/matter
branch
2 times, most recently
from
September 21, 2026 20:28
b3b774d to
13daced
Compare
Each skill has one copy under skills/. link-skills.sh links it into .claude/skills and .agents/skills, because an agent cannot see a skill missing from its own tree. The PR template now lives in the tidy-pr skill.
Microdot comes from PyPI, not firmware-packages/, so the new firmware-dependencies stage in Dockerfile.host installs it from uv.lock with hash checks and keeps only its sources and license. Every firmware build stage copies that stage in, and manifest.py fails the build when firmware imports Microdot but the sources are missing.
Compilation now yields one image with an empty factory partition, so a single build can flash many boards. esp32-flash derives each board's credentials from a PASSCODE key (random when unset), writes the factory partition into the image, validates it, flashes it, and only then publishes that board's QR code and setup file.
The modem now sleeps between commissioning events, and routine INFO lines are no longer formatted and written over USB. WARN, with CHIP at ERROR, still reports commissioning failures.
reports.py holds the dead zone, hold timer, and telemetry pacing as pure functions of each report's time, and status.py owns commissioning state and pixel priority, so tests reach both without booting the application. Behavior is unchanged.
An unchanged scene, empty or not, is no longer serialized every 500 ms. Every report that falls due restarts the interval, sent or not, so the last timestamp stays within ticks_diff's range while the scene is idle.
webserver.py bounds connections, request sizes, deadlines, socket writes, and heap use, and shuts the dashboard down when memory runs low, so network traffic cannot starve the radar or Matter tasks. The page draws its charts in inline SVG instead of loading Plotly from a CDN, so the viewing device needs no internet access. A second browser gets a Take connection button rather than a second slot.
…ver the untested error paths.
…partition check for Matter images.
…re pairing module.
… firmware for flashing.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Overview
Matter boards now get their pairing credentials when they are flashed, not when the firmware compiles, so one build can flash many boards and a saved key reproduces a board's codes. The radar sensor's dashboard moves from the in-repo
httpdpackage to Microdot, with hard limits on connections and memory, and the page now works without internet access. The PR also adds agent skills with a CI link check, and updates two locked dependencies to clear the vulnerability scan.What’s New
matter.generate_pairing(passcode)infirmware-packages/matter/matter/pairing.pyderives the Matter setup passcode, discriminator, and manual pairing code from one secret key. A key needs at least 24 characters and 12 distinct ones. With no key, it draws a random 256-bit key and returns it, so the codes can be rebuilt later.tools/matter-build/pairing_code.pyrebuilds a board's QR image and manual code from its key, with no hardware attached.firmware-dependenciesstage inDockerfile.hostinstalls it fromuv.lockwith hash checks. Every firmware build stage copies it in.manifest.pyfreezes it into firmware that imports it, and fails the build if it is missing.projects/matter-radar-sensor/firmware/webserver.pyserves the dashboard page and WebSocket through Microdot. Its own socket layer caps every resource a browser can grow; the limits are listed in the radar README.reports.py(dead zone, occupancy hold, telemetry pacing) andstatus.py(commissioning state, pixel colors) are split out of the radarmain.py.skills/:new-skill,talking-to-a-user, andtidy-pr.skills/link-skills.shlinks every skill into.claude/skillsand.agents/skills, and caps eachSKILL.mdandAGENTS.mdat 600 words.make skillsruns it; the CI "Repo guards" job runs it with--check.What Has Changed
build.py:flowchart LR compile["esp32-compile"] --> image["app.esp32-s3.bin<br/>empty factory partition"] key["PASSCODE key<br/>(random if unset)"] --> flash["esp32-flash"] image --> flash flash --> provision["insert factory partition,<br/>validate, flash"] provision --> publish["publish image, QR,<br/>setup.txt"]esp32-compilepublishes onlyoutputs/app.esp32-s3.binand deletes any old QR and setup files.esp32-flashnow runsbuild.py --flash. It takesPASSCODE,MANUFACTURER, andSERIAL_NUMBER(moved from the compile service), writes the factory partition into the image, validates it, flashes, and then publishes that board's image, QR, andsetup.txt. A failed flash leaves the previous files in place. Add--no-depsto flash another board without recompiling.setup.txtnow also holds the board'spasscodekey. Keep it secret: the key alone gives away the pairing code of every board flashed with it.viz/static/index.html) draws its four charts as inline SVG instead of loading Plotly fromcdn.plot.ly. One browser connects at a time (was three); a second one sees a Take connection button that replaces the current viewer. Hiding the tab closes the socket, and the page reconnects only when that button is clicked (it used to retry every 250 ms).sdkconfig.board) turns on BLE modem sleep on the main crystal, and lowers logging fromINFOtoWARN, with CHIP atERROR.firmware-packages/matter/ARCHITECTURE.mdis folded into a shorter package README with a new Pairing section. The radar README is rewritten for the new server, build flow, and wiring. The routing tables inAGENTS.md,projects/AGENTS.md, andtools/AGENTS.mdare gone.firmware-packages/httpdpackage, which nothing imports anymore, and.github/pull_request_template.md. The template now lives in thetidy-prskill, so GitHub no longer prefills new PRs.matter0.2.0 → 0.2.2,matter-example0.2.0 → 0.2.3,matter-radar-sensor0.3.0 → 0.5.5, and a patch bump for every other project, whose compose file gained thefirmware-dependenciesbuild context.What’s Fixed
uv.lockmovesanyio4.13.0 → 4.15.1 andtyping-extensions4.15.0 → 4.16.0, which clears thevuln-checkjob.node.factory_reset(), but the firmware has no globalnode. It now sendsimport _matter; _matter.factory_reset().Testing
New:
test_pairing.py: key rules, random keys, fixed vectors, forbidden passcodes, and the published CHIP manual-code vector.test_pairing_pipeline.py: board-free compiles, repeatable and random flashes, esptool reset flags, a wrong-size image refused, and a failed flash leaving outputs intact.test_reports.py,test_status.py,test_webserver.py,test_webserver_connections.py(bounds, deadlines, takeover, and heap recovery through real Microdot routing), andtest_webserver_protocol.py.Updated: the radar
conftest.py,test_boot_status.py,test_occupancy.py,test_radar.py, andtest_matter_poll.py; the build-tool teststest_artifact_checks.py,test_factory_data.py,test_toolchain_commands.py,test_board_config.py, andtest_onboarding.py. Removed: the radartest_dashboard.py(replaced bytest_webserver.py) and thehttpdpackage tests.Full suite: 707 passed, 94.64% coverage (gate: 90%).
Additional Information
SKILL.mdorAGENTS.md, now fails the Repo guards job, which every other job depends on. Fix it withmake skillsand commit the result. The script never removes a real file or folder where a link belongs; it reports it for manual removal.