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:
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."
|
||||
}
|
||||
@@ -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() != {}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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')
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user