docs(export): E8 — user documentation for the Matter export bridge [no-release] - #130
Conversation
INSTALL.md gains an "Exporting Indigo devices" section: prerequisites (Node >=22.13, the second npm package and the fact it is not yet published), first-export walkthrough, the pairing window and its security caveat, the expected "uncertified accessory" prompt with the Homebridge/matterbridge precedent per ADR-0006, removal/unpairing/stopping, and the two destructive recovery actions in the same words their dialogs use. Backups now cover the bridge storage dir (and no longer claim the backup menu is a stub — it has not been one since fabric_backup landed). Troubleshooting is split into controller and export-bridge tables, the latter sourced from the log strings the code actually emits. MATTER.md gains the outbound architecture section at the depth of the inbound one: the two processes, why the bridge node exists, the opt-in allow-list and why, fabrics (Apple takes two slots), endpoint identity and why it must never move, the v1 role table and the excluded set with reasons — both checked against export_catalog.py — and the honest ecosystem statement per ADR-0007. README.md's lede now shows both roles, with export's status stated as built-but-not-yet-live-validated. Three drifts fixed rather than papered over: * PRD 5.2's sensor rows implied a fixed unit->type mapping; the code offers the roles as a user choice with the unit heuristic picking only the default. * PRD 5.2's excluded set was missing the "reports neither an on/off state nor a value" sensor exclusion, which has always been in the code. * PRD 5.3 called indigo-matter-bridge a "published" npm package while 9's E7 row says it is not on the registry. PRD 9's E7/E8 rows are updated for what shipped; bridge-node/README.md no longer claims Alexa/Google/SmartThings. Nothing is claimed that the code does not do. Stated as unfinished: the unpublished npm package, XAC3/XAC5's pending live validation, the pairing page's dependence on Indigo Web Server auth, the no-declared-units limitation, and per-ecosystem export sets being v2. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
The build agent, checking HANDOVER rather than trusting the brief, wrote that no live Apple Home pairing had happened. HANDOVER was stale: the E0 gate paired an uncertified bridge into Apple Home with the prompt accepted, E3 controlled a light and a dimmer both directions, and the E5 upgrade kept three accessories' identity with no duplicates — all on the reference server, all in this session's logs. The caution was right in kind and wrong in fact, so both docs now list what was actually done and what genuinely is not: pairing through the plugin's own menu (the E0 pairing was driven from the node's console), a second admin alongside Apple, the reboot leg, and the LaunchAgent end to end. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
Two whole-doc reviews — an accuracy pass falsifying every claim against the code, and a reader-experience pass following the guide cold. Accuracy (each verified on this branch): * The drift troubleshooting row prescribed a hand-copy out of a backup zip for a non-fault: node.ts:868-880 says drift after a factory reset is EXPECTED and is what the preserved map exists to report, and factoryReset() runs on both "Reset Matter Export Pairings…" and unpairing the last ecosystem — both of which this same doc walks users through. Expected-cause first, no action; storage loss second. * MATTER.md documented an exclusion the code cannot produce: a device this plugin created hits REASON_LOOP_GUARD before any type reasoning (export_catalog.py:232) and is then absent from the picker (plugin.py:1843), so it can never reach REASON_NO_ROLE. Energy meters moved to the loop-guard row; the no-role row now says what actually triggers it. * kPa was listed among the units taken on trust. Pressure is the one unit that IS converted (export_handlers.py:895-918 divides by HPA_PER_KPA), so as written a barometer owner would "fix" their sensor into the 10x error the code exists to prevent. * Apple Home finds "Indigo Matter Bridge" (node.ts:71 PRODUCT_NAME), not "Indigo" — that is what the user scans a phone screen for. * The picker is capped at EXPORT_PICKER_LIMIT = 300 with a truncation row, not "every Indigo device". * Export needs Node (Step 1) and a storage path (Step 3), not a healthy matter-server — "everything in Steps 1-4 working" contradicted MATTER.md's own "one can be broken while the other works". * Smaller: PROTOCOL not plugin version; the offered-role order for a full-colour dimmer per _dimmer/_default_first; the port-reload note is in the Matter port's Description only; Restore fabric backup's stated precondition; bridge_agent's docstring still called the package "published". Reader experience: * The npm blocker now leads the export section instead of arriving 250 lines in, and is echoed in the overview bullet and MATTER.md. * "You only pair the bridge once per ecosystem" added to Step E2 — guessing wrong means opening an unnecessary pairing window, which the security section says exposes the house. * Destructive actions ordered by recoverability, Rebuild (unrecoverable) first; the unpair row carries the last-ecosystem factory-reset consequence. * INSTALL retitled for both runtimes, with a contents list routing to the three export subsections that do not sit under the export heading. * "fabric" defined on first use; the two-node-processes fact stated up front. * Troubleshooting reordered to put observable symptoms before log strings, with rows for the two most likely first failures (exported but never paired; Add Accessory cannot find the bridge). EADDRINUSE now covers both its ports; the pressure/flow and room-change rows give a verdict rather than a hedge. * MATTER.md leads with the can/cannot-export tables; the identity subsection leads with its instruction; the status inventory lives in README only. * matter-server is Beta everywhere (upstream's own word). Status corrections, with dates, so HANDOVER and the PRD stop contradicting the README they are cited from: E0's pairing gate PASSED 2026-08-04, E3's live two-way E2E PASSED 2026-08-05, E5 deployed to jarvis 2026-08-05 with the upgrade migration observed (endpoints 3/5/4 kept, no duplicates). Pairing through the plugin's own menu, the second-admin proof, XAC5's reboot leg and E6/E7 end-to-end stay marked outstanding. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
|
Warning Review limit reached
Next review available in: 14 minutes You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThe PR documents bidirectional Matter support, including the optional Indigo-to-Matter export bridge. It adds export architecture, device mappings, installation and recovery guidance, ecosystem scope, certification notes, package availability, and deployment status. ChangesMatter export documentation
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (2)
docs/INSTALL.md (2)
417-417: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winKeep the pairing warning in one blockquote.
markdownlintreports MD028 because Line 417 is a blank line inside the blockquote. Prefix the blank line with>or remove it.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/INSTALL.md` at line 417, Update the pairing warning block in INSTALL.md so it contains no unquoted blank line: prefix the blank line with “>” or remove it, keeping the entire warning as one continuous blockquote.Source: Linters/SAST tools
362-365: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd language identifiers to fenced blocks.
markdownlintreports MD040 at Lines 362, 401, 599, and 684. Usetextfor log and path examples, andbashfor shell commands.Also applies to: 401-404, 599-601, 684-687
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/INSTALL.md` around lines 362 - 365, Add language identifiers to the fenced code blocks in docs/INSTALL.md at the referenced sections: use text for log or path examples and bash for shell command examples, resolving the markdownlint MD040 warnings without changing their contents.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/INSTALL.md`:
- Line 702: Update the ifconfig troubleshooting command in the installation
documentation to use an unescaped pipe before grep, so the shell executes the
pipeline and filters for active interfaces.
In `@docs/MATTER.md`:
- Around line 490-497: Update the Matter ecosystem support note near the Alexa,
Google Home, and SmartThings statement to remove the claim that a real CSA
vendor ID is the only remedy. State that the bridge provides neither a
production CSA vendor ID nor ecosystem-specific developer-console registration,
while preserving the existing untested and unclaimed status.
In `@docs/PRD-indigo-matter-export.md`:
- Around line 217-218: Update the “Dimmer (colour)” row in the export
role-mapping table to document Full-colour light as the default and include the
Dimmable, Colour-temperature, and Window covering roles, matching the role names
and ordering defined in docs/MATTER.md.
- Line 222: The numeric-sensor role policy is inconsistent across the two
documents. Update docs/PRD-indigo-matter-export.md:222 to state whether sensors
without matching unit hints remain selectable, and update docs/MATTER.md:323-332
to use the identical rule and default-selection behavior, preserving the
implementation and user-declared-role policy.
In `@README.md`:
- Around line 220-225: Scope the uncertified-warning documentation to tested
ecosystems: in README.md lines 220-225, limit the claim to Apple Home; in
docs/MATTER.md lines 508-523, rename the universal heading and state that other
ecosystems may differ; and in docs/INSTALL.md lines 325-332, remove the promise
that every ecosystem displays the warning.
- Around line 68-70: Distinguish registry-backed installation from local
development installation: in README.md lines 68-70, state that the menu cannot
resolve the pinned indigo-matter-bridge package until publication while
preserving local validation; in docs/MATTER.md lines 298-303, document the same
install-menu limitation; in docs/INSTALL.md lines 10-13, qualify the
introduction as the supported registry path; in lines 90-96, separate
unavailable registry installation from local validation; and in lines 284-290,
document or link to the local workaround in docs/HANDOVER.md.
---
Nitpick comments:
In `@docs/INSTALL.md`:
- Line 417: Update the pairing warning block in INSTALL.md so it contains no
unquoted blank line: prefix the blank line with “>” or remove it, keeping the
entire warning as one continuous blockquote.
- Around line 362-365: Add language identifiers to the fenced code blocks in
docs/INSTALL.md at the referenced sections: use text for log or path examples
and bash for shell command examples, resolving the markdownlint MD040 warnings
without changing their contents.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 9ea9dbd3-7454-4eef-9327-72cac3a426ef
📒 Files selected for processing (7)
README.mdbridge-node/README.mddocs/HANDOVER.mddocs/INSTALL.mddocs/MATTER.mddocs/PRD-indigo-matter-export.mdindigo-matter.indigoPlugin/Contents/Server Plugin/bridge_agent.py
| | Symptom | Cause | Fix | | ||
| |---|---|---| | ||
| | You exported a device and **nothing appeared** in Apple Home | The bridge has never been paired. Exporting publishes a device *on* the bridge; an ecosystem sees nothing at all until the bridge itself has been added to it. | Do Step E3 then Step E4. You do this **once per ecosystem** — after that, later exports appear by themselves with no further pairing. | | ||
| | Apple Home's **Add Accessory** cannot find the bridge | One of three: nothing is exported (the bridge only runs while the export list is non-empty), or no pairing window is open, or **Primary network interface** in Configure… names an interface this Mac is not actually using. That field is shared with matter-server and the bridge pins its mDNS advertising to it, so a wrong value advertises where nobody is listening. Matter discovery is also mDNS + link-local IPv6, so the phone must be on the same subnet as the Mac. | Export at least one device; open a window with **Pair Matter Bridge…**; check the interface with `ifconfig \| grep "status: active"` and **reload the plugin** after changing it; put the phone on the same subnet/VLAN as the Indigo Mac. | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the escape before the pipe.
The command currently renders as ifconfig \| grep "status: active". The shell treats \| as a literal argument, so it does not pipe output to grep.
Corrected command
- `ifconfig \| grep "status: active"`
+ `ifconfig | grep "status: active"`🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/INSTALL.md` at line 702, Update the ifconfig troubleshooting command in
the installation documentation to use an unescaped pipe before grep, so the
shell executes the pipeline and filters for active interfaces.
| - **Alexa, Google Home and SmartThings are untested and unclaimed.** Not | ||
| supported, not unsupported: nobody here has the hardware, no decision hangs on | ||
| the answer, and the only remedy for a refusal — a real CSA vendor ID — is out | ||
| of scope for a free plugin. The bridge is an ordinary multi-admin Matter | ||
| bridge and there is no reason in principle they should refuse it, but a reason | ||
| in principle is not a test. Google Home is the most likely to be awkward: it | ||
| has historically been strictest about test-range vendor IDs. If you pair any of | ||
| them, please report it. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Do not describe a CSA vendor ID as the only remedy.
docs/HANDOVER.md also records ecosystem-specific developer-console registration as a possible remedy. State that this bridge provides neither a production CSA vendor ID nor ecosystem-specific registration.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/MATTER.md` around lines 490 - 497, Update the Matter ecosystem support
note near the Alexa, Google Home, and SmartThings statement to remove the claim
that a real CSA vendor ID is the only remedy. State that the bridge provides
neither a production CSA vendor ID nor ecosystem-specific developer-console
registration, while preserving the existing untested and unclaimed status.
| | Dimmer (colour) | Light | Extended Color Light | Colour-temp-only devices → Color Temperature Light. A colour-capable dimmer is *also* offered the colour-temp-only role, so a user can downgrade a bulb an ecosystem renders badly | | ||
| | Dimmer | Window covering | Window Covering | Polarity declared per export (100% = open, inbound convention). Must implement `handleMovement()` — matter.js's default snaps to target instantly | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Complete the colour-dimmer role mapping.
The Dimmer (colour) row lists only Light, while docs/MATTER.md defines Full-colour light as the default and also offers Dimmable, Colour-temperature, and Window covering roles. Document the complete role set and default here.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/PRD-indigo-matter-export.md` around lines 217 - 218, Update the “Dimmer
(colour)” row in the export role-mapping table to document Full-colour light as
the default and include the Dimmable, Colour-temperature, and Window covering
roles, matching the role names and ordering defined in docs/MATTER.md.
| | Sensor (numeric, flow) | — | Flow Sensor | Apple Home ignores this type (Google supports it); exported anyway, documented | | ||
| | Sensor (binary) | Occupancy *(default)* | Occupancy Sensor | Indigo does not distinguish motion from contact any more than it distinguishes a plug from a lamp, so this is declared too. Corrected 2026-08-05 (E8): the row used to read "—" in both directions, implying a mapping the code does not make | | ||
| | Sensor (binary) | Contact | Contact Sensor | | | ||
| | Sensor (numeric) | Temperature / Humidity / Light / Pressure / Flow | the matching Matter sensor type | **All five are offered for any numeric sensor**; the unit heuristic (pluginProps, then the formatted UI value, then the device name) picks only the *default*, and a sensor no hint matches is the "units outside the table" exclusion below. Corrected 2026-08-05 (E8): the rows used to read as one unit → one type | |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Use one numeric-sensor role rule.
The PRD says that a numeric sensor with no matching hint is excluded, while docs/MATTER.md says all five roles stay selectable. Align both documents with the implementation and the user-declared-role policy.
docs/PRD-indigo-matter-export.md#L222-L222: clarify whether unknown-unit sensors remain selectable.docs/MATTER.md#L323-L332: use the same rule and default-selection behavior.
📍 Affects 2 files
docs/PRD-indigo-matter-export.md#L222-L222(this comment)docs/MATTER.md#L323-L332
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/PRD-indigo-matter-export.md` at line 222, The numeric-sensor role policy
is inconsistent across the two documents. Update
docs/PRD-indigo-matter-export.md:222 to state whether sensors without matching
unit hints remain selectable, and update docs/MATTER.md:323-332 to use the
identical rule and default-selection behavior, preserving the implementation and
user-declared-role policy.
| - **A second npm package** (`indigo-matter-bridge`), installed from its own menu item. | ||
| Note it is **not on the npm registry yet**, so export cannot be brought up until it is. | ||
|
|
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Distinguish registry installation from local installation.
The affected text treats npm publication as a prerequisite for any bridge run, but docs/HANDOVER.md documents a local package install that can run E7 before publication. State that the registry-backed menu cannot resolve the exact pin until publication. Keep the local package path available for development and validation.
README.md#L68-L70: replace the absolute “cannot be brought up” statement with a registry/menu limitation.docs/MATTER.md#L298-L303: state that the install menu cannot resolve the package until publication.docs/INSTALL.md#L10-L13: qualify the introduction as the supported registry install path.docs/INSTALL.md#L90-L96: distinguish unavailable package installation from local validation.docs/INSTALL.md#L284-L290: document the local workaround or link todocs/HANDOVER.md.
📍 Affects 3 files
README.md#L68-L70(this comment)docs/MATTER.md#L298-L303docs/INSTALL.md#L10-L13docs/INSTALL.md#L90-L96docs/INSTALL.md#L284-L290
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` around lines 68 - 70, Distinguish registry-backed installation
from local development installation: in README.md lines 68-70, state that the
menu cannot resolve the pinned indigo-matter-bridge package until publication
while preserving local validation; in docs/MATTER.md lines 298-303, document the
same install-menu limitation; in docs/INSTALL.md lines 10-13, qualify the
introduction as the supported registry path; in lines 90-96, separate
unavailable registry installation from local validation; and in lines 284-290,
document or link to the local workaround in docs/HANDOVER.md.
| - **The export bridge is uncertified in the other direction, and visibly so.** It | ||
| advertises with the specification's test vendor ID, so every ecosystem shows an | ||
| "uncertified accessory" warning when you add it and you choose *Add Anyway*. That is the | ||
| normal state for this class of software — Homebridge, matterbridge and Home Assistant's | ||
| bridge all ship the same way — and it is not something the plugin can change: outbound, | ||
| the trust policy belongs to the ecosystem doing the commissioning. |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Scope uncertified-warning behavior to tested ecosystems.
The documents mark non-Apple ecosystems as untested and unclaimed, so the universal “every ecosystem” warning claim is not established. Guarantee the Apple Home behavior and describe other ecosystem behavior as untested.
README.md#L220-L225: limit the warning claim to Apple Home.docs/MATTER.md#L508-L523: rename the universal heading and state that other ecosystems may differ.docs/INSTALL.md#L325-L332: remove the promise that every ecosystem displays the warning.
📍 Affects 3 files
README.md#L220-L225(this comment)docs/MATTER.md#L508-L523docs/INSTALL.md#L325-L332
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@README.md` around lines 220 - 225, Scope the uncertified-warning
documentation to tested ecosystems: in README.md lines 220-225, limit the claim
to Apple Home; in docs/MATTER.md lines 508-523, rename the universal heading and
state that other ecosystems may differ; and in docs/INSTALL.md lines 325-332,
remove the promise that every ecosystem displays the warning.
Step E4 offered '(or scan the QR from the page)'. There is no QR on the page — the same section says so two paragraphs earlier. Typing the manual code is the whole path. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
…sues Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
Replaces #129, which GitHub auto-closed when its base branch (
feat/e6-e7-pairing-and-agent) was deleted on merge. Same three commits, rebased ontomain.Summary
The final milestone of the Matter export build — user-facing documentation, plus corrections to internal docs that had drifted from the code.
Reviewed by two agents
An accuracy pass falsified every claim against the code; a reader-experience pass walked the guide as a first-time user. Both sets of findings applied, including two Criticals: a troubleshooting row that would have sent users to restore a backup after an expected post-reset drift report, and a status contradiction between the user docs and HANDOVER.
🤖 Generated with Claude Code
https://claude.ai/code/session_01JxqGhP3DcENf68AZK21U4S
Summary by CodeRabbit