docs: de-identify reporter usernames repo-wide, add PII rule to skill

Extended the earlier de-identification (jhkwon19) to the other issue #177
reporter (HJcom), who was named in ~20 spots across coordinator.py,
diagnostics.py, subdevices.py, identity.py, capabilities/airconditioner.py,
a fixture's seeds_note, and several test docstrings/function names. Swapped
all of it for "the reporter"/"the Pattern A reporter", matching the
convention already established for the other reporter.

Added a rule to the adding-device-support skill (end of "Lock it in"):
don't put a reporter's name or GitHub username in code comments,
docstrings, seeds_note, or test/function names -- that prose ships and
sits in git history indefinitely, unlike an issue thread or a
release-notes thank-you. Use "the reporter" / "issue #NNN's reporter" /
a pattern label instead.
This commit is contained in:
Marc Billow committed 2026-07-30 03:06:06 +00:00
1 parent ce92d71a92
commit ca27bf7f6e
11 files changed
+121 -97

No files matched your search

@@ -2029,5 +2029,5 @@
"x.com.samsung.da.numofsubdevice": "2"
}
},
"seeds_note": "ALL REAL CAPTURED DATA -- issue #177, HJcom's ARTIK051_DONGLE_FAC_18K (Samsung 2-in-1: floor-standing master + wall-mounted second indoor subdevice). device0, oic_res and both /device/<n> seeds come verbatim from their v0.16.0 diagnostics download, which is the first release that probes /device/1 and /device/2. Nothing here is reconstructed. The reporter masked a handful of values in their own dump before posting (serialNum, and the airflow `direction` / vendor `humidity` readings); those are normalized onto this repo's usual **REDACTED** marker. /device/1 is the real second subdevice -- populated power/mode/temperature and its own /information/vs/1 reporting ARTIK051_DONGLE_FAC_RAC_18K (RAC = the wall-mounted subdevice) against the master's ARTIK051_DONGLE_FAC_18K. /device/2 answers with the same 14-href shape but every state rep is empty {} -- it is the unused third slot SmartThings shows disabled, and it is why subdevice materialization gates on populated climate state rather than on a seed merely answering. `probes` is not part of any batch response: /multidevice/vs/0 is listed in oic_res but absent from /device/0's batch, and the reporter read it by hand through the debug panel (a write attempt returned CoAP 4.00, i.e. read-only). Its numofsubdevice=2 independently corroborates 2 real subdevices, not 3."
"seeds_note": "ALL REAL CAPTURED DATA -- issue #177, the reporter's ARTIK051_DONGLE_FAC_18K (Samsung 2-in-1: floor-standing master + wall-mounted second indoor subdevice). device0, oic_res and both /device/<n> seeds come verbatim from their v0.16.0 diagnostics download, which is the first release that probes /device/1 and /device/2. Nothing here is reconstructed. The reporter masked a handful of values in their own dump before posting (serialNum, and the airflow `direction` / vendor `humidity` readings); those are normalized onto this repo's usual **REDACTED** marker. /device/1 is the real second subdevice -- populated power/mode/temperature and its own /information/vs/1 reporting ARTIK051_DONGLE_FAC_RAC_18K (RAC = the wall-mounted subdevice) against the master's ARTIK051_DONGLE_FAC_18K. /device/2 answers with the same 14-href shape but every state rep is empty {} -- it is the unused third slot SmartThings shows disabled, and it is why subdevice materialization gates on populated climate state rather than on a seed merely answering. `probes` is not part of any batch response: /multidevice/vs/0 is listed in oic_res but absent from /device/0's batch, and the reporter read it by hand through the debug panel (a write attempt returned CoAP 4.00, i.e. read-only). Its numofsubdevice=2 independently corroborates 2 real subdevices, not 3."
}
+15 -13
View File
@@ -3,10 +3,11 @@
two -- and that the legacy-board test (is_legacy_board/_legacy_airflow) is
evaluated per subdevice rather than once globally.
Uses HJcom's ARTIK051_DONGLE_FAC_18K fixture deliberately: it's a legacy
`/airflow/vs/<n>` board (no `/wind/*` at all) on *both* the master and its
materialized sibling, which is exactly the shape climate.py's own comments
warn is easy to get wrong if the canonical view leaks between subdevices.
Uses the issue #177 reporter's ARTIK051_DONGLE_FAC_18K fixture deliberately:
it's a legacy `/airflow/vs/<n>` board (no `/wind/*` at all) on *both* the
master and its materialized sibling, which is exactly the shape climate.py's
own comments warn is easy to get wrong if the canonical view leaks between
subdevices.
"""
from __future__ import annotations
@@ -71,15 +72,16 @@ async def test_subdevice_climate_reads_its_own_power_state(climates):
async def test_legacy_board_test_is_evaluated_per_subdevice(climates):
"""HJcom's board has no /wind/* resources at all on *either* subdevice --
is_legacy_board(self._resources) must independently evaluate True for
the master's own canonical view and for the subdevice's own canonical
view. If is_legacy_board were fed the raw, unpartitioned snapshot (or
if canonical_view leaked one subdevice's hrefs into the other's), this
wouldn't distinguish "this subdevice is legacy" from "some subdevice on
this connection is legacy" -- and a future board with one legacy + one
modern subdevice sharing a connection would silently read the wrong
fan/swing channel on one side."""
"""The reporter's board has no /wind/* resources at all on *either*
subdevice -- is_legacy_board(self._resources) must independently
evaluate True for the master's own canonical view and for the
subdevice's own canonical view. If is_legacy_board were fed the raw,
unpartitioned snapshot (or if canonical_view leaked one subdevice's
hrefs into the other's), this wouldn't distinguish "this subdevice is
legacy" from "some subdevice on this connection is legacy" -- and a
future board with one legacy + one modern subdevice sharing a
connection would silently read the wrong fan/swing channel on one
side."""
main, sub1 = climates[None], climates['1']
assert main._legacy_airflow() != {}
assert sub1._legacy_airflow() != {}
+1 -1
View File
@@ -903,7 +903,7 @@ def _new_subdevice_aware_state_keys(name):
def test_registry_reproduces_golden_state_keys_for_airconditioner_artik051_dongle_fac_18k():
"""HJcom's ARTIK051_DONGLE_FAC_18K (issue #177, Pattern A -- indexed
"""The reporter's ARTIK051_DONGLE_FAC_18K (issue #177, Pattern A -- indexed
siblings): a real v0.16.0 dump with a genuine second indoor subdevice at
`/device/1` (subdevice1_-prefixed keys below) and an unused SmartThings
slot at `/device/2` that answers its seed but never produces a
+7 -7
View File
@@ -87,10 +87,10 @@ def _climate_bound(coordinator, subdevice_key: str):
# ---------------------------------------------------------------------------
# HJcom -- ARTIK051_DONGLE_FAC_18K, Pattern A (indexed siblings)
# Pattern A reporter -- ARTIK051_DONGLE_FAC_18K, indexed siblings
# ---------------------------------------------------------------------------
async def test_hjcom_materializes_master_and_bedroom_subdevice(hass: HomeAssistant):
async def test_pattern_a_materializes_master_and_bedroom_subdevice(hass: HomeAssistant):
coordinator = _coordinator(hass)
await _discover(coordinator, 'airconditioner_artik051_dongle_fac_18k')
@@ -104,11 +104,11 @@ async def test_hjcom_materializes_master_and_bedroom_subdevice(hass: HomeAssista
assert sub1_climate.href == '/mode/vs/1'
async def test_hjcom_device_2_produces_no_entities_at_all(hass: HomeAssistant):
"""HJcom's /device/2 is the unused SmartThings slot (DESIGN-177.md
section 4): it answers its seed with a full-shaped batch, but every
climate-state rep on it is empty. It must be recorded as skipped, not
materialized, and must contribute zero bound entities."""
async def test_pattern_a_device_2_produces_no_entities_at_all(hass: HomeAssistant):
"""The reporter's /device/2 is the unused SmartThings slot
(DESIGN-177.md section 4): it answers its seed with a full-shaped
batch, but every climate-state rep on it is empty. It must be recorded
as skipped, not materialized, and must contribute zero bound entities."""
coordinator = _coordinator(hass)
await _discover(coordinator, 'airconditioner_artik051_dongle_fac_18k')
+9 -8
View File
@@ -383,10 +383,10 @@ def test_enumerate_no_subdevices_resource_at_all():
def test_enumerate_indexed_materializes_candidate_regardless_of_content():
"""enumerate_subdevices itself has no way to tell a real sibling from an
unused slot that merely answers the same shape (HJcom's /device/2) --
that's discover_partitioned's job (see its own tests below). A
same-shaped batch of otherwise-empty reps is still returned as a
candidate here."""
unused slot that merely answers the same shape (the reporter's
/device/2) -- that's discover_partitioned's job (see its own tests
below). A same-shaped batch of otherwise-empty reps is still returned
as a candidate here."""
oic_res = [{'di': 'a', 'links': [{'href': '/device/2'}]}]
sess = _FakeSession({
('device', '2'): [_DEVCOL_REP, {'href': '/power/vs/2', 'rep': {}},
@@ -598,13 +598,14 @@ def test_discover_partitioned_no_subdevices_matches_plain_discover():
# ---------------------------------------------------------------------------
# discover_partitioned's materialization gate: a candidate is only kept if
# it produced at least one *primary* (no entity_category) bound entity whose
# flattened value isn't None. This is what tells HJcom's real /device/1
# sibling apart from the unused /device/2 slot that answers the same shape.
# flattened value isn't None. This is what tells the reporter's real
# /device/1 sibling apart from the unused /device/2 slot that answers the
# same shape.
# ---------------------------------------------------------------------------
def test_discover_partitioned_skips_candidate_with_no_live_primary_entity():
"""A candidate whose only populated entity is diagnostic-category
doesn't count -- exactly HJcom's /device/2 shape (an alarm_code
doesn't count -- exactly the reporter's /device/2 shape (an alarm_code
sensor reading something even though the subdevice itself is empty)."""
diag_cap = Capability(
href='/alarms/vs/0',
@@ -632,7 +633,7 @@ def test_discover_partitioned_skips_candidate_with_no_live_primary_entity():
def test_discover_partitioned_materializes_candidate_with_live_primary_entity():
"""A candidate with a populated *primary* (no entity_category) entity
is materialized, even alongside an all-empty diagnostic sibling href --
exactly HJcom's /device/1 shape."""
exactly the reporter's /device/1 shape."""
climate_cap = Capability(
href='/mode/vs/0',
entities=(BinarySensorDesc(key='mode', field='m'),), # no entity_category -> primary