swbt-python 0.5.0__tar.gz → 0.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. {swbt_python-0.5.0 → swbt_python-0.5.2}/PKG-INFO +11 -12
  2. {swbt_python-0.5.0 → swbt_python-0.5.2}/README.md +10 -11
  3. {swbt_python-0.5.0 → swbt_python-0.5.2}/pyproject.toml +1 -1
  4. {swbt_python-0.5.0/spec/wip → swbt_python-0.5.2/spec/complete}/unit_056/PAIRING_PROFILE_NAMING.md +10 -10
  5. {swbt_python-0.5.0/spec/wip → swbt_python-0.5.2/spec/complete}/unit_057/PAIRING_PROFILE_CONTROLLER_KIND.md +16 -16
  6. swbt_python-0.5.2/spec/complete/unit_068/DIRECT_PRE_CLOSE_INPUT_REFLECTION.md +143 -0
  7. swbt_python-0.5.2/spec/complete/unit_069/CONTROLLER_HANDSHAKE_READINESS.md +370 -0
  8. swbt_python-0.5.2/spec/complete/unit_070/DIAGNOSTICS_AND_UNUSED_PATHS_CLEANUP.md +174 -0
  9. swbt_python-0.5.2/spec/complete/unit_071/CONTROLLER_CONSTRUCTION_PATH.md +174 -0
  10. swbt_python-0.5.2/spec/complete/unit_072/CONNECTION_RUNTIME_INTEGRATION.md +152 -0
  11. swbt_python-0.5.2/spec/complete/unit_073/TEST_CONTRACT_BOUNDARY_CLEANUP.md +135 -0
  12. swbt_python-0.5.2/spec/complete/unit_074/PUBLIC_GAMEPAD_IMPLEMENTATION_OWNERSHIP.md +188 -0
  13. swbt_python-0.5.2/spec/complete/unit_075/CONCRETE_CONTROLLER_MODULE.md +169 -0
  14. swbt_python-0.5.2/spec/complete/unit_076/HARDWARE_HAPPY_CASE_VALIDATION.md +139 -0
  15. swbt_python-0.5.2/spec/complete/unit_077/RUNTIME_INPUT_UPDATE_DISPATCH.md +81 -0
  16. swbt_python-0.5.2/spec/complete/unit_078/TEST_RUNTIME_FIXTURES.md +80 -0
  17. swbt_python-0.5.2/spec/complete/unit_079/PAIRING_PROFILE_KEY_STORE.md +67 -0
  18. swbt_python-0.5.2/spec/complete/unit_080/TRANSPORT_PROTOCOL_CONTRACT.md +61 -0
  19. swbt_python-0.5.2/spec/complete/unit_081/PROTOCOL_HANDSHAKE.md +369 -0
  20. swbt_python-0.5.2/spec/complete/unit_082/REPLY_HOLDOFF_VALIDATION.md +133 -0
  21. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/hardware-test-log.md +72 -0
  22. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/api.md +9 -22
  23. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/architecture.md +15 -5
  24. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/lifecycle.md +32 -13
  25. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/protocol.md +21 -14
  26. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/roadmap.md +1 -1
  27. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/testing.md +15 -2
  28. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/transport-bumble.md +10 -14
  29. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/rearchitecture/01-design-change-overview.md +13 -5
  30. swbt_python-0.5.2/spec/rearchitecture/02-as-is-to-be.md +75 -0
  31. swbt_python-0.5.2/spec/rearchitecture/03-public-api-config-profile.md +39 -0
  32. swbt_python-0.5.2/spec/rearchitecture/04-runtime-profile-transport-details.md +23 -0
  33. swbt_python-0.5.2/spec/rearchitecture/05-milestones-implementation.md +38 -0
  34. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/rearchitecture/README.md +9 -3
  35. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/diagnostics.py +4 -27
  36. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/gamepad/__init__.py +1 -1
  37. swbt_python-0.5.2/src/swbt/gamepad/_config.py +53 -0
  38. swbt_python-0.5.2/src/swbt/gamepad/connection.py +24 -0
  39. swbt_python-0.5.2/src/swbt/gamepad/controllers.py +211 -0
  40. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/gamepad/interface.py +190 -31
  41. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/gamepad/output.py +32 -2
  42. swbt_python-0.5.2/src/swbt/gamepad/protocol_handshake.py +167 -0
  43. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/gamepad/runtime.py +392 -211
  44. swbt_python-0.5.2/src/swbt/gamepad/transport_factory.py +27 -0
  45. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/profiles/base.py +1 -0
  46. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/profiles/joycon.py +3 -0
  47. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/session.py +26 -0
  48. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/subcommand.py +36 -5
  49. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/report_loop.py +29 -32
  50. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/state_store.py +1 -31
  51. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_key_store.py +15 -67
  52. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/base.py +7 -33
  53. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/bumble.py +9 -17
  54. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/fake.py +12 -15
  55. swbt_python-0.5.2/tests/__init__.py +1 -0
  56. swbt_python-0.5.2/tests/gamepad_factory.py +202 -0
  57. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_controller_colors.py +2 -1
  58. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_pairing_profile.py +418 -3
  59. swbt_python-0.5.2/tests/hardware/test_reply_holdoff.py +199 -0
  60. swbt_python-0.5.2/tests/integration/__init__.py +1 -0
  61. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/integration/test_examples.py +5 -1
  62. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/integration/test_pairing_profile.py +10 -17
  63. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/integration/test_switch_gamepad_fake_transport.py +561 -133
  64. swbt_python-0.5.2/tests/unit/__init__.py +1 -0
  65. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/fixtures/source_audit/switch_protocol_values.toml +30 -1
  66. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_bumble_transport.py +53 -10
  67. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_diagnostics.py +25 -10
  68. swbt_python-0.5.2/tests/unit/test_gamepad_config.py +175 -0
  69. swbt_python-0.5.2/tests/unit/test_gamepad_connection_workflow.py +20 -0
  70. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_gamepad_transport_factory.py +1 -77
  71. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_package_import.py +8 -1
  72. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_pairing_profile_runtime.py +6 -6
  73. swbt_python-0.5.2/tests/unit/test_protocol_handshake.py +138 -0
  74. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_protocol_profile.py +1 -1
  75. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_protocol_session.py +64 -1
  76. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_public_api_boundary.py +44 -281
  77. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_report_loop.py +71 -5
  78. swbt_python-0.5.2/tests/unit/test_source_audit_fixtures.py +143 -0
  79. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_subcommand_responder.py +23 -1
  80. swbt_python-0.5.0/spec/rearchitecture/02-as-is-to-be.md +0 -212
  81. swbt_python-0.5.0/spec/rearchitecture/03-public-api-config-profile.md +0 -368
  82. swbt_python-0.5.0/spec/rearchitecture/04-runtime-profile-transport-details.md +0 -387
  83. swbt_python-0.5.0/spec/rearchitecture/05-milestones-implementation.md +0 -359
  84. swbt_python-0.5.0/src/swbt/_testing/__init__.py +0 -1
  85. swbt_python-0.5.0/src/swbt/_testing/gamepad.py +0 -145
  86. swbt_python-0.5.0/src/swbt/gamepad/_config.py +0 -101
  87. swbt_python-0.5.0/src/swbt/gamepad/connection.py +0 -228
  88. swbt_python-0.5.0/src/swbt/gamepad/core.py +0 -732
  89. swbt_python-0.5.0/src/swbt/gamepad/transport_factory.py +0 -104
  90. swbt_python-0.5.0/tests/unit/test_gamepad_connection_workflow.py +0 -62
  91. swbt_python-0.5.0/tests/unit/test_source_audit_fixtures.py +0 -506
  92. {swbt_python-0.5.0 → swbt_python-0.5.2}/AGENTS.md +0 -0
  93. {swbt_python-0.5.0 → swbt_python-0.5.2}/LICENSE +0 -0
  94. {swbt_python-0.5.0 → swbt_python-0.5.2}/examples/hardware_bringup.py +0 -0
  95. {swbt_python-0.5.0 → swbt_python-0.5.2}/examples/pairing_probe.py +0 -0
  96. {swbt_python-0.5.0 → swbt_python-0.5.2}/examples/tap_a.py +0 -0
  97. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_001/M0_PROTOCOL_CORE.md +0 -0
  98. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_002/M1_SWITCH_GAMEPAD_FAKE_TRANSPORT.md +0 -0
  99. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_003/M2_BUMBLE_HID_TRANSPORT.md +0 -0
  100. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_004/M3_PAIRING_L2CAP.md +0 -0
  101. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_005/M4_SUBCOMMAND_RESPONDER_HARDWARE.md +0 -0
  102. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_006/M5_INPUT_OPERATION_API.md +0 -0
  103. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_007/M6_RECONNECT_KEYSTORE_DIAGNOSTICS.md +0 -0
  104. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_008/M7_PACKAGING_EXAMPLES_CLI.md +0 -0
  105. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_009/PORTING_SOURCE_AUDIT.md +0 -0
  106. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_010/DIAGNOSTICS_TRACE_SCHEMA.md +0 -0
  107. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_011/HARDWARE_TEST_LOG_MATRIX.md +0 -0
  108. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_012/INITIAL_RELEASE_GATE.md +0 -0
  109. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_013/POST_M5_INPUT_SEMANTIC_CHARACTERIZATION.md +0 -0
  110. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_014/DEVICE_CLOSE_GRACEFUL_DISCONNECT.md +0 -0
  111. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_015/CONTEXT_MANAGER_RESOURCE_SCOPE.md +0 -0
  112. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_016/JSON_KEY_STORE_CURRENT_PREVIOUS.md +0 -0
  113. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_017/SWITCH_GAMEPAD_API_HARDENING.md +0 -0
  114. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_018/KEY_STORE_TRANSPORT_BOUNDARY.md +0 -0
  115. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_019/TRANSPORT_RECONNECT_CONTRACT.md +0 -0
  116. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_020/STRUCTURAL_REFACTOR_BOUNDARIES.md +0 -0
  117. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_021/SWITCH_GAMEPAD_INPUT_API_CONTRACT.md +0 -0
  118. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_022/PUBLIC_API_USAGE_HARDWARE_DOCS.md +0 -0
  119. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_023/MKDOCS_DOCUMENTATION_SITE.md +0 -0
  120. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_024/STICK_INPUT_SHORTHAND_API.md +0 -0
  121. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_025/IMU_INPUT_SHORTHAND_API.md +0 -0
  122. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_026/LINUX_MACOS_ADAPTER_EXPERIMENTAL.md +0 -0
  123. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_027/ADAPTER_DISCOVERY_API.md +0 -0
  124. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_028/CONTROLLER_PROFILE_CUSTOMIZATION.md +0 -0
  125. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_029/CONTROLLER_PROFILE_INJECTION.md +0 -0
  126. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_030/JOYCON_PROFILE_IDENTITY_SPI.md +0 -0
  127. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_031/JOYCON_INPUT_REPORT_MAPPING.md +0 -0
  128. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_032/PROFILE_AWARE_SUBCOMMAND_STATE.md +0 -0
  129. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_033/PROFILE_AWARE_BUMBLE_SDP.md +0 -0
  130. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_034/JOYCON_CONVENIENCE_API_DOCS.md +0 -0
  131. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_035/JOYCON_DEVICE_INFO_ADDRESS_WIRING.md +0 -0
  132. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_036/JOYCON_SDP_IDENTITY_POLICY.md +0 -0
  133. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_037/JOYCON_DEFAULT_CONTROLLER_COLORS.md +0 -0
  134. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_038/REARCHITECTURE_DECISION_BOUNDARY_TESTS.md +0 -0
  135. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_039/CONTROLLER_RUNTIME_EXTRACTION.md +0 -0
  136. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_040/PUBLIC_CONTROLLER_API_MODEL.md +0 -0
  137. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_041/CONTROLLER_CONFIG_PROFILE_OWNERSHIP.md +0 -0
  138. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_042/INTERNAL_TRANSPORT_FACTORY.md +0 -0
  139. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_043/PROTOCOL_PROFILE_MODULE_SPLIT.md +0 -0
  140. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_044/REARCHITECTURE_DOCS_RELEASE_MATRIX.md +0 -0
  141. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_045/INTERNAL_API_BOUNDARY_CLEANUP.md +0 -0
  142. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_046/HARDWARE_PROFILE_TEST_SCENARIOS.md +0 -0
  143. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_047/VIRTUAL_GYRO_CALIBRATION.md +0 -0
  144. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_048/VIRTUAL_ACCELEROMETER_CALIBRATION.md +0 -0
  145. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_049/IMU_SESSION_AND_ENCODING_REDESIGN.md +0 -0
  146. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_050/DIRECT_REPORTING_TYPES.md +0 -0
  147. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_051/CSR_BD_ADDR_REWRITE_EXPERIMENT.md +0 -0
  148. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_052/EXP_LOCAL_ADDRESS_PROFILE.md +0 -0
  149. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_053/EXP_LOCAL_ADDRESS_PROFILE_JOYCON.md +0 -0
  150. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_054/EXP_LOCAL_ADDRESS_PROFILE_DIRECT.md +0 -0
  151. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_055/REMOVE_NATIVE_KEY_STORE_API.md +0 -0
  152. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_058/MULTI_ADDRESS_RECONNECT.md +0 -0
  153. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_059/EXPERIMENTAL_DIRECT_SEND_TIMING_PROBE.md +0 -0
  154. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_060/HCI_ACL_COMPLETION_CORRELATION.md +0 -0
  155. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_061/EXPERIMENTAL_CLASSIC_LINK_POLICY_AB.md +0 -0
  156. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_062/PERIODIC_ACL_DRAIN_CHARACTERIZATION.md +0 -0
  157. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_063/PERIODIC_NO_DRAIN_CHARACTERIZATION.md +0 -0
  158. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md +0 -0
  159. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_065/PERIODIC_DEADLINE_SCHEDULER.md +0 -0
  160. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_066/PAIRING_PROFILE_DEFAULT_ADDRESS.md +0 -0
  161. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/complete/unit_067/DEFAULT_BATTERY_STATUS.md +0 -0
  162. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/dev-journal.md +0 -0
  163. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/README.md +0 -0
  164. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/naming.md +0 -0
  165. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/initial/risks.md +0 -0
  166. {swbt_python-0.5.0 → swbt_python-0.5.2}/spec/rearchitecture/mkdocs-nav-snippet.yml +0 -0
  167. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/__init__.py +0 -0
  168. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/adapter_discovery.py +0 -0
  169. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/errors.py +0 -0
  170. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/gamepad/constants.py +0 -0
  171. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/imu.py +0 -0
  172. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/input.py +0 -0
  173. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/probe.py +0 -0
  174. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/__init__.py +0 -0
  175. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/buttons.py +0 -0
  176. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/descriptors.py +0 -0
  177. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/imu_report.py +0 -0
  178. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/input_report.py +0 -0
  179. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/output_report.py +0 -0
  180. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/profiles/__init__.py +0 -0
  181. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/profiles/pro_controller.py +0 -0
  182. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/rumble.py +0 -0
  183. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/protocol/spi.py +0 -0
  184. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/py.typed +0 -0
  185. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/__init__.py +0 -0
  186. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_adapter_identity.py +0 -0
  187. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_acl.py +0 -0
  188. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_hidp.py +0 -0
  189. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_lifecycle.py +0 -0
  190. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_sdp.py +0 -0
  191. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_bumble_usb_devices.py +0 -0
  192. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_csr_bd_addr.py +0 -0
  193. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_csr_bd_addr_harness.py +0 -0
  194. {swbt_python-0.5.0 → swbt_python-0.5.2}/src/swbt/transport/_pairing_profile.py +0 -0
  195. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/conftest.py +0 -0
  196. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/README.md +0 -0
  197. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_battery_status.py +0 -0
  198. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_bumble_transport.py +0 -0
  199. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_close_disconnect.py +0 -0
  200. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_context_manager_resource_scope.py +0 -0
  201. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_multi_address_reconnect.py +0 -0
  202. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/hardware/test_pairing_l2cap.py +0 -0
  203. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_adapter_discovery.py +0 -0
  204. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_adapter_identity.py +0 -0
  205. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_bumble_acl.py +0 -0
  206. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_bumble_hidp.py +0 -0
  207. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_bumble_lifecycle.py +0 -0
  208. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_bumble_sdp.py +0 -0
  209. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_ci_workflow.py +0 -0
  210. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_csr_bd_addr_experiment.py +0 -0
  211. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_csr_bd_addr_harness.py +0 -0
  212. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_gamepad_output_dispatcher.py +0 -0
  213. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_imu_report.py +0 -0
  214. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_input_report.py +0 -0
  215. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_input_state.py +0 -0
  216. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_output_report.py +0 -0
  217. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_package_metadata.py +0 -0
  218. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_pairing_profile.py +0 -0
  219. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_probe_cli.py +0 -0
  220. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_protocol_boundary.py +0 -0
  221. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_publish_workflow.py +0 -0
  222. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_rumble_state.py +0 -0
  223. {swbt_python-0.5.0 → swbt_python-0.5.2}/tests/unit/test_virtual_spi_flash.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: swbt-python
3
- Version: 0.5.0
3
+ Version: 0.5.2
4
4
  Summary: Python library for presenting an NX-compatible virtual Bluetooth HID input device.
5
5
  Keywords: bluetooth,bluetooth-hid,controller,gamepad,hid,nx
6
6
  Author: niart120
@@ -55,12 +55,14 @@ uv sync --dev
55
55
  - [API リファレンス](https://niart120.github.io/swbt-python/api/)
56
56
  - [利用例](https://niart120.github.io/swbt-python/usage/)
57
57
  - [実機準備手順](https://niart120.github.io/swbt-python/hardware/)
58
- - [Agent Brief](https://niart120.github.io/swbt-python/agent-brief/)
58
+ - [AI エージェント向け要約](https://niart120.github.io/swbt-python/agent-brief/)
59
59
 
60
60
  同じ内容は `docs/` 配下でも確認できます。
61
61
 
62
62
  ## 利用例
63
+
63
64
  ### Pro Controller
65
+
64
66
  ```python
65
67
  import asyncio
66
68
  from swbt import Button, ProController
@@ -79,7 +81,9 @@ async def main() -> None:
79
81
  asyncio.run(main())
80
82
  ```
81
83
 
82
- Pro Controller 相当の一時的な仮想デバイスを作成し、ペアリング後に A ボタン入力を送信するコードの例です。接続情報を永続化する場合は `ProController.create_profile()` を使います。`local_address` を省略するとアダプタが現在報告する Bluetooth アドレスを維持し、揮発領域へ書き込みません。利用者管理のローカルアドレスへ切り替える手順は[利用例](docs/usage.md)、対応する専用 USB Bluetooth ドングルと復旧手順は[実機準備手順](docs/hardware.md)を参照してください。
84
+ Pro Controller 相当の仮想デバイスを作成し、ペアリング後に A ボタン入力を送信する例です。
85
+
86
+ 接続情報を保存して再利用する場合は、先に `ProController.create_profile()` で `profile_path` を作成します。アドレスの選択方法と復旧手順は[利用例](docs/usage.md)、専用 USB Bluetooth ドングルの準備は[実機準備手順](docs/hardware.md)を参照してください。
83
87
 
84
88
  ### Joy-Con L/R
85
89
 
@@ -96,7 +100,6 @@ async def main() -> None:
96
100
  profile_path="switch-left-joycon-profile.json",
97
101
  ) as left:
98
102
  await left.connect(timeout=30.0, allow_pairing=True)
99
- await left.tap(Button.SR, Button.SL)
100
103
  await left.tap(Button.L)
101
104
  await left.lstick(Stick.left())
102
105
  await left.neutral()
@@ -105,9 +108,9 @@ async def main() -> None:
105
108
  asyncio.run(main())
106
109
  ```
107
110
 
108
- 「持ちかた/順番を変える」画面で Joy-Con としてペアリングする場合は、接続後に `await left.tap(Button.SR, Button.SL)` のように SR+SL を送信する必要があります。
111
+ 「持ちかた/順番を変える」画面でペアリングするときも、登録用の SR+SL 入力を追加送信する必要はありません。`connect()` Joy-Con 用の初期化とプレイヤーライトの設定が完了してから戻ります。
109
112
 
110
- Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetooth アドレスの選択方法とペアリングキーをまとめる `profile_path` を使います。新規プロファイルは各具象クラスの `create_profile()` で作成し、コントローラー形状と対象機器ごとに保存先を分けてください。v0.4.0 の `key_store_path` で使用していた JSON 形式のペアリング情報との互換経路はありません。Joy-Con L で右スティックや A/B/X/Y、Joy-Con R で左スティックや十字キーを入力すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
113
+ `profile_path` はコントローラー形状と対象機器ごとに分けます。Joy-Con L では右スティックと A/B/X/Y、Joy-Con R では左スティックと十字キーを使えません。これらを指定すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
111
114
 
112
115
  ## 接続方法
113
116
 
@@ -117,15 +120,11 @@ Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetoo
117
120
 
118
121
  ### 確認済み構成
119
122
 
120
- 2026-07-07 時点では、Windows 11 / CSR8510 A10 / WinUSB / `usb:0` / Switch 2 ファームウェア 22.1.0 で、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、主要なボタン / スティック入力、ニュートラル復帰を確認済みです。
121
-
122
- 同じ Windows 構成で、Joy-Con L/R も部分的に動作確認済みです。確認済み範囲と未確認範囲の詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
123
-
124
- macOS 15.7.7 / CSR8510 A10 では、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、ボタン入力、ニュートラル復帰を記録しています。
123
+ Windows 11 / CSR8510 A10 / WinUSB では、Pro Controller、Joy-Con L、Joy-Con R のペアリング、再接続、対応する入力操作を確認しています。macOS 15.7.7 / CSR8510 A10 では Pro Controller の限定的な動作を確認しています。条件と未確認範囲は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)を参照してください。
125
124
 
126
125
  ### 実験的構成
127
126
 
128
- Linux は experimental です。手順は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)に整備されていますが、専用 USB Bluetooth ドングルにアクセスできるか、ペアリングできるか、入力が反映されるかは未確認です。macOS Pro Controller の一部挙動のみ検証済みです。Joy-Con、別ドングル、別ファームウェアでの互換性は未確認です。
127
+ Linux は experimental です。専用 USB Bluetooth ドングルへのアクセス、ペアリング、入力反映は未確認です。macOS Joy-Con、別ドングル、別ファームウェアでの互換性も未確認です。
129
128
 
130
129
  ## 開発
131
130
 
@@ -29,12 +29,14 @@ uv sync --dev
29
29
  - [API リファレンス](https://niart120.github.io/swbt-python/api/)
30
30
  - [利用例](https://niart120.github.io/swbt-python/usage/)
31
31
  - [実機準備手順](https://niart120.github.io/swbt-python/hardware/)
32
- - [Agent Brief](https://niart120.github.io/swbt-python/agent-brief/)
32
+ - [AI エージェント向け要約](https://niart120.github.io/swbt-python/agent-brief/)
33
33
 
34
34
  同じ内容は `docs/` 配下でも確認できます。
35
35
 
36
36
  ## 利用例
37
+
37
38
  ### Pro Controller
39
+
38
40
  ```python
39
41
  import asyncio
40
42
  from swbt import Button, ProController
@@ -53,7 +55,9 @@ async def main() -> None:
53
55
  asyncio.run(main())
54
56
  ```
55
57
 
56
- Pro Controller 相当の一時的な仮想デバイスを作成し、ペアリング後に A ボタン入力を送信するコードの例です。接続情報を永続化する場合は `ProController.create_profile()` を使います。`local_address` を省略するとアダプタが現在報告する Bluetooth アドレスを維持し、揮発領域へ書き込みません。利用者管理のローカルアドレスへ切り替える手順は[利用例](docs/usage.md)、対応する専用 USB Bluetooth ドングルと復旧手順は[実機準備手順](docs/hardware.md)を参照してください。
58
+ Pro Controller 相当の仮想デバイスを作成し、ペアリング後に A ボタン入力を送信する例です。
59
+
60
+ 接続情報を保存して再利用する場合は、先に `ProController.create_profile()` で `profile_path` を作成します。アドレスの選択方法と復旧手順は[利用例](docs/usage.md)、専用 USB Bluetooth ドングルの準備は[実機準備手順](docs/hardware.md)を参照してください。
57
61
 
58
62
  ### Joy-Con L/R
59
63
 
@@ -70,7 +74,6 @@ async def main() -> None:
70
74
  profile_path="switch-left-joycon-profile.json",
71
75
  ) as left:
72
76
  await left.connect(timeout=30.0, allow_pairing=True)
73
- await left.tap(Button.SR, Button.SL)
74
77
  await left.tap(Button.L)
75
78
  await left.lstick(Stick.left())
76
79
  await left.neutral()
@@ -79,9 +82,9 @@ async def main() -> None:
79
82
  asyncio.run(main())
80
83
  ```
81
84
 
82
- 「持ちかた/順番を変える」画面で Joy-Con としてペアリングする場合は、接続後に `await left.tap(Button.SR, Button.SL)` のように SR+SL を送信する必要があります。
85
+ 「持ちかた/順番を変える」画面でペアリングするときも、登録用の SR+SL 入力を追加送信する必要はありません。`connect()` Joy-Con 用の初期化とプレイヤーライトの設定が完了してから戻ります。
83
86
 
84
- Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetooth アドレスの選択方法とペアリングキーをまとめる `profile_path` を使います。新規プロファイルは各具象クラスの `create_profile()` で作成し、コントローラー形状と対象機器ごとに保存先を分けてください。v0.4.0 の `key_store_path` で使用していた JSON 形式のペアリング情報との互換経路はありません。Joy-Con L で右スティックや A/B/X/Y、Joy-Con R で左スティックや十字キーを入力すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
87
+ `profile_path` はコントローラー形状と対象機器ごとに分けます。Joy-Con L では右スティックと A/B/X/Y、Joy-Con R では左スティックと十字キーを使えません。これらを指定すると `UnsupportedInputError` が送出されます。`JoyConPair` は未実装です。
85
88
 
86
89
  ## 接続方法
87
90
 
@@ -91,15 +94,11 @@ Pro Controller、周期送信型 Joy-Con、直接送信型はすべて、Bluetoo
91
94
 
92
95
  ### 確認済み構成
93
96
 
94
- 2026-07-07 時点では、Windows 11 / CSR8510 A10 / WinUSB / `usb:0` / Switch 2 ファームウェア 22.1.0 で、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、主要なボタン / スティック入力、ニュートラル復帰を確認済みです。
95
-
96
- 同じ Windows 構成で、Joy-Con L/R も部分的に動作確認済みです。確認済み範囲と未確認範囲の詳細は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)にあります。
97
-
98
- macOS 15.7.7 / CSR8510 A10 では、Pro Controller のペアリング、保存済みペアリング情報を使う再接続、ボタン入力、ニュートラル復帰を記録しています。
97
+ Windows 11 / CSR8510 A10 / WinUSB では、Pro Controller、Joy-Con L、Joy-Con R のペアリング、再接続、対応する入力操作を確認しています。macOS 15.7.7 / CSR8510 A10 では Pro Controller の限定的な動作を確認しています。条件と未確認範囲は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)を参照してください。
99
98
 
100
99
  ### 実験的構成
101
100
 
102
- Linux は experimental です。手順は[実機準備手順](https://niart120.github.io/swbt-python/hardware/)に整備されていますが、専用 USB Bluetooth ドングルにアクセスできるか、ペアリングできるか、入力が反映されるかは未確認です。macOS Pro Controller の一部挙動のみ検証済みです。Joy-Con、別ドングル、別ファームウェアでの互換性は未確認です。
101
+ Linux は experimental です。専用 USB Bluetooth ドングルへのアクセス、ペアリング、入力反映は未確認です。macOS Joy-Con、別ドングル、別ファームウェアでの互換性も未確認です。
103
102
 
104
103
  ## 開発
105
104
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "swbt-python"
3
- version = "0.5.0"
3
+ version = "0.5.2"
4
4
  description = "Python library for presenting an NX-compatible virtual Bluetooth HID input device."
5
5
  readme = "README.md"
6
6
  authors = [
@@ -61,16 +61,16 @@
61
61
 
62
62
  | status | item | type | layer | hardware | notes |
63
63
  |---|---|---|---|---|---|
64
- | implemented / smoke passed | `local_address` で作成した profile が従来の JSON payload を保存・読み込みできる | regression | unit | no | system Python smoke test で確認。pytest は環境遮断 |
65
- | implemented / blocked | adapter identity 準備失敗が新しい例外型で復旧を要求する | regression | unit | no | adapter は開かない fake session。pytest は環境遮断 |
66
- | implemented / blocked | concrete controller が `local_address` で profile を作成して再利用できる | regression | integration | no | fake transport。pytest は環境遮断 |
64
+ | green | `local_address` で作成した profile が従来の JSON payload を保存・読み込みできる | regression | unit | no | 現行 unit test CI で確認 |
65
+ | green | adapter identity 準備失敗が新しい例外型で復旧を要求する | regression | unit | no | adapterを開かない fake sessionで確認 |
66
+ | green | concrete controller が `local_address` で profile を作成して再利用できる | regression | integration | no | fake transport integrationで確認 |
67
67
 
68
68
  ## 8. 文書検証計画
69
69
 
70
70
  | document | audience / task | source of truth | mechanical check | review result | unresolved |
71
71
  |---|---|---|---|---|---|
72
- | API / usage / hardware docs | profile の作成と再利用 | 本仕様 §6、実装 | `uv run mkdocs build --strict` | manual pass / build blocked | `uv` cache が read-only |
73
- | release notes / agent brief | 例外名と用語 | 本仕様 §6、実装 | link / build | manual pass / build blocked | `uv` cache が read-only |
72
+ | API / usage / hardware docs | profile の作成と再利用 | 本仕様 §6、実装 | `uv run --group docs mkdocs build --strict` | done | none |
73
+ | release notes / agent brief | 例外名と用語 | 本仕様 §6、実装 | link / diff review | done | none |
74
74
 
75
75
  ## 9. 設計メモ
76
76
 
@@ -97,10 +97,10 @@
97
97
  | GitHub Actions CI #142 | passed | 新規 shape-only 値の保存と `direct_*` の未対応扱いを含む unit / integration test |
98
98
  | `ruff 0.15.20 format --check .` | passed | CI と同じ Ruff version を一時領域で実行 |
99
99
  | `ruff 0.15.20 check .` | passed | CI と同じ Ruff version を一時領域で実行 |
100
- | `uv run ty check --no-progress` | blocked | 同上 |
101
- | `uv run pytest tests/unit` | blocked | 同上。Bumble を含む依存が未導入 |
102
- | `uv run pytest tests/integration` | blocked | 同上 |
103
- | `uv run mkdocs build --strict` | blocked | 同上 |
100
+ | `uv run ty check --no-progress` | pass | current mainでAll checks passed |
101
+ | `uv run pytest tests/unit` | pass | current mainで439 passed |
102
+ | `uv run pytest tests/integration` | pass | current mainで154 passed |
103
+ | `uv run --group docs mkdocs build --strict` | pass | current mainでstrict build成功 |
104
104
 
105
105
  ## 12. 実機実行条件
106
106
 
@@ -115,7 +115,7 @@
115
115
 
116
116
  ## 13. 先送り事項
117
117
 
118
- - ReportingMode 分類の削除は unit_057 で扱う。
118
+ - none(ReportingMode 分類の削除は unit_057 で完了)
119
119
 
120
120
  ## 14. チェックリスト
121
121
 
@@ -64,17 +64,17 @@ pairing profile の `controller_kind` から、入力レポートの送信方式
64
64
 
65
65
  | status | item | type | layer | hardware | notes |
66
66
  |---|---|---|---|---|---|
67
- | implemented / CI passed | 新規 profile が ReportingMode を含まない controller shape を保存する | regression | unit | no | 新規保存は `pro` / `joycon_l` / `joycon_r`。GitHub Actions CI #142 で確認 |
68
- | implemented / CI passed | 旧 direct kind を持つ JSON が未対応値として adapter open 前に失敗する | regression | unit | no | `direct_*` を特別扱いせず、既存の `controller_kind` 検証で拒否。GitHub Actions CI #142 で確認 |
69
- | implemented / local passed | 同じ controller shape の periodic / direct が profile を相互利用できる | regression | unit | no | Direct controller の `open()` が profile path と local address を fake transport factory へ渡すことを確認 |
70
- | implemented / CI passed | controller shape が異なる profile は adapter open 前に拒否される | regression | unit | no | `ControllerKind` 比較の guard を GitHub Actions CI #142 で確認 |
67
+ | green | 新規 profile が ReportingMode を含まない controller shape を保存する | regression | unit | no | 新規保存は `pro` / `joycon_l` / `joycon_r`。CIと現行unitで確認 |
68
+ | green | 旧 direct kind を持つ JSON が未対応値として adapter open 前に失敗する | regression | unit | no | `direct_*` を特別扱いせず、既存の `controller_kind` 検証で拒否 |
69
+ | green | 同じ controller shape の periodic / direct が profile を相互利用できる | regression | unit | no | fake transport regression 3 passed |
70
+ | green | controller shape が異なる profile は adapter open 前に拒否される | regression | unit | no | `ControllerKind`比較のguardを確認 |
71
71
  | deferred | Direct / Periodic 間 profile 再利用の実機 pairing / reconnect | characterization | hardware | yes | 明示承認と専用 adapter が必要 |
72
72
 
73
73
  ## 8. 文書検証計画
74
74
 
75
75
  | document | audience / task | source of truth | mechanical check | review result | unresolved |
76
76
  |---|---|---|---|---|---|
77
- | API / usage / hardware docs | プロファイルの再利用範囲 | 本仕様 §6、実装、対象 test | `uv run --with mkdocs mkdocs build --strict` | 2026-07-21 docs-quality-review strict build が pass | 実機共有は未検証 |
77
+ | API / usage / hardware docs | プロファイルの再利用範囲 | 本仕様 §6、実装、対象 test | `uv run --group docs mkdocs build --strict` | done | Direct / Periodicの実機共有はdeferred |
78
78
 
79
79
  ## 9. 設計メモ
80
80
 
@@ -88,7 +88,7 @@ pairing profile の `controller_kind` から、入力レポートの送信方式
88
88
  |---|---|---|
89
89
  | `src/swbt/transport/_pairing_profile.py` | modify | `ControllerKind` 化と shape-only の値だけの受理 |
90
90
  | `src/swbt/gamepad/_config.py` | modify | profile kind config の削除 |
91
- | `src/swbt/gamepad/core.py` | modify | direct / periodic 共通の shape 利用 |
91
+ | `src/swbt/gamepad/controllers.py` | modify | direct / periodic 共通の shape 利用 |
92
92
  | `src/swbt/gamepad/runtime.py` | modify | protocol profile の kind による guard |
93
93
  | `tests/` | modify | legacy / cross-mode / mismatch 回帰 |
94
94
  | `docs/`, `spec/initial/` | modify | profile 共有範囲の説明 |
@@ -102,10 +102,10 @@ pairing profile の `controller_kind` から、入力レポートの送信方式
102
102
  | GitHub Actions CI #142 | passed | 新規 shape-only 値の保存と `direct_*` の未対応扱いを含む unit / integration test |
103
103
  | `ruff 0.15.20 format --check .` | passed | CI と同じ Ruff version を一時領域で実行 |
104
104
  | `ruff 0.15.20 check .` | passed | CI と同じ Ruff version を一時領域で実行 |
105
- | `uv run ty check --no-progress` | blocked | 同上 |
106
- | `uv run pytest tests/unit` | blocked | 同上。Bumble を含む依存が未導入 |
107
- | `uv run pytest tests/integration` | blocked | 同上 |
108
- | `uv run mkdocs build --strict` | blocked | 同上 |
105
+ | `uv run ty check --no-progress` | pass | current mainでAll checks passed |
106
+ | `uv run pytest tests/unit` | pass | current mainで439 passed |
107
+ | `uv run pytest tests/integration` | pass | current mainで154 passed |
108
+ | `uv run --group docs mkdocs build --strict` | pass | current mainでstrict build成功 |
109
109
  | `uv run pytest tests/unit/test_pairing_profile_runtime.py::test_direct_controller_reuses_profile_for_the_same_controller_shape -q` | passed | 3 passed。P2 review finding の fake transport regression |
110
110
  | `uv run --with mkdocs mkdocs build --strict` | passed | 2026-07-21。公開 docs の strict build |
111
111
 
@@ -113,16 +113,16 @@ pairing profile の `controller_kind` から、入力レポートの送信方式
113
113
 
114
114
  | 項目 | 内容 |
115
115
  |---|---|
116
- | 実機要否 | required for deferred characterization |
117
- | 承認範囲 | dedicated adapter open、target Switch pairing、active reconnect、normal close |
118
- | adapter | 実行直前に確認する専用 adapter |
116
+ | 実機要否 | not required for this unit(deferred characterization only) |
117
+ | 承認範囲 | この完了ではなし。将来実行する場合は明示承認を取得する |
118
+ | adapter | この完了では該当なし |
119
119
  | 実行遮断 | 環境変数による実行遮断は採用しない。明示承認、対象 adapter、command、cleanup plan で管理する |
120
- | log / artifact | `spec/hardware-test-log.md` に環境、command、result、cleanup を記録する |
121
- | cleanup | normal close 後に dedicated adapter を切り離す |
120
+ | log / artifact | この完了では新規記録なし。将来実行時は `spec/hardware-test-log.md` に記録する |
121
+ | cleanup | この完了では該当なし |
122
122
 
123
123
  ## 13. 先送り事項
124
124
 
125
- - Direct / Periodic 間での実機 pairing / reconnect hardware characterization として別途実行する。
125
+ - Direct / Periodic 間での実機 pairing / reconnect は、今回のprofile shape分離の完了条件に含めない。fake transportで公開契約を確認済みであり、実機再検証の追加価値は低いため、release gateで必要になった場合だけ専用hardware runとして扱う。
126
126
 
127
127
  ## 14. チェックリスト
128
128
 
@@ -0,0 +1,143 @@
1
+ # Direct close 前入力反映観測 仕様書
2
+
3
+ ## 1. 概要
4
+
5
+ ### 1.1 目的
6
+
7
+ Direct controller の実機テストで、入力送信後に `close()` へ進む前の観測窓を設ける。通常送信中は入力が Switch へ届かず、切断前の ACL queue drain で初めて送られる退行を、従来の local state assertion だけで成功扱いしない。
8
+
9
+ ### 1.2 起点 / source
10
+
11
+ | source | 内容 | path |
12
+ |---|---|---|
13
+ | external review / user request | Direct pairing 実機テストは `send()` 後に local state だけを確認して直ちに `close()` するため、close 前の Switch 入力反映を確認できない | `tests/hardware/test_pairing_profile.py` |
14
+ | current transport contract | Direct の成功と `report_tx` は Bumble enqueue 受理を表し、Switch 反映を表さない。切断時は pending ACL queue を drain する | `spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md` |
15
+
16
+ ### 1.3 use case
17
+
18
+ | actor / boundary | 入力または状態 | 期待する観測結果 | 制約 |
19
+ |---|---|---|---|
20
+ | hardware test operator | Switch の入力確認画面を開き、Direct controller の sentinel button を送信する | `close()` 開始前の観測窓で対象 button が表示される | 画面反映は pytest だけでは判定せず、利用者確認を hardware log に記録する |
21
+ | transport regression | 通常 send の queue が close まで進行しない | pytest の trace 順序は通っても、close 前の Switch 画面確認が失敗する | close 時 drain による遅延送信を成功根拠にしない |
22
+
23
+ ## 2. 対象範囲
24
+
25
+ - Direct Pro Controller / Joy-Con L / Joy-Con R の fresh pairing 実機テスト。
26
+ - 実機 gate は Direct Pro / Button A の代表ケースを先に実行する。
27
+ - Direct input の enqueue 後、neutral と `close()` の前に設ける手動観測窓。
28
+ - operator の準備条件、期待 button、観測窓完了、close 開始、cleanup を trace に記録する。
29
+ - pytest pass と Switch UI の目視結果を別の証拠として扱う。
30
+
31
+ ## 3. 対象外
32
+
33
+ - `send()` を controller completion や Switch 反映まで待つ API への変更。
34
+ - Bumble `DataPacketQueue` の内部計測や production diagnostics の追加。
35
+ - CI での実機入力反映検証。
36
+ - report bytes、button bit、controller profile の変更。
37
+ - active reconnect の入力反映。今回の起点は fresh pairing test の acceptance gap であり、reconnect は別検証とする。
38
+
39
+ ## 4. 関連 docs
40
+
41
+ - `spec/initial/api.md`
42
+ - `spec/initial/lifecycle.md`
43
+ - `spec/initial/testing.md`
44
+ - `spec/complete/unit_050/DIRECT_REPORTING_TYPES.md`
45
+ - `spec/complete/unit_054/EXP_LOCAL_ADDRESS_PROFILE_DIRECT.md`
46
+ - `spec/complete/unit_064/BUMBLE_ENQUEUE_COMPLETION_CONTRACT.md`
47
+ - `tests/hardware/README.md`
48
+
49
+ ## 5. 根拠監査
50
+
51
+ | 項目 | 要否 | 状態 | 根拠 / 理由 |
52
+ |---|---|---|---|
53
+ | Switch HID / report bytes | not applicable | not applicable | 既存の sentinel `InputState` と report builder を変更しない |
54
+ | Bumble / transport | required | done | unit_064 の enqueue 受理と disconnect 前 drain 契約を利用する。新しい transport 仮定は追加しない |
55
+ | OS / driver / adapter | required | done | Windows 11、専用 `usb:0`、CSR8510 A10、WinUSB、Bumble 0.0.230、Python 3.13.5 で代表ケースを実行し、`spec/hardware-test-log.md` に記録した |
56
+
57
+ ## 6. 振る舞い仕様
58
+
59
+ | 振る舞い | 入力・状態 | 期待結果 | 備考 |
60
+ |---|---|---|---|
61
+ | operator preparation | Direct fresh pairing を開始する | Switch の controller search / change grip order 画面、controller、button、観測秒数を trace と stderr に出す | 画面準備なしの run は input reflection の根拠にしない |
62
+ | pre-close observation | `send(sentinel_state)` が正常終了する | local state と direct `report_tx` を確認し、neutral / close を呼ばず観測窓を維持する | `report_tx` 自体は enqueue 受理だけを表す |
63
+ | cleanup ordering | 観測窓が完了する | 観測窓完了後に初めて `close(neutral=True)` を開始する | button pressed を残さない |
64
+ | evidence classification | pytest が pass する | enqueue、trace 順序、profile、cleanup の成功として扱う | Switch UI は利用者確認が記録された場合だけ observed-pass |
65
+
66
+ ## 7. TDD Test List
67
+
68
+ | status | item | type | layer | hardware | notes |
69
+ |---|---|---|---|---|---|
70
+ | green | fresh pairing の Direct input は close 前の観測窓を完了してから neutral close する | regression | hardware | yes | Pro / Button A の代表ケースが `1 passed in 33.27s`。Joy-Con L / R は collection のみ |
71
+ | green | trace は direct enqueue、観測窓完了、close 開始、transport close の順序を保持する | regression | hardware | yes | direct `0x30` index 23、観測窓完了 71、close 開始 72、transport close 103、cleanup 104 |
72
+ | green | Switch UI に対象 button が close 前に表示される | characterization | hardware | yes | 利用者が観測窓中の画面反応とコントローラー認識を目視確認した |
73
+
74
+ ## 8. 文書検証計画
75
+
76
+ 公開文書は変更しない。作業仕様、hardware test docstring、`tests/hardware/README.md` を照合し、pytest pass と人間の目視結果を混同していないことをレビューする。
77
+
78
+ ## 9. 設計メモ
79
+
80
+ ### Test Desiderata Review
81
+
82
+ | test | value | trade-off | decision |
83
+ |---|---|---|---|
84
+ | fake transport Direct send | isolated、deterministic、fast、precise | Switch-facing queue progression を表さない | 既存 integration test を維持する |
85
+ | Direct pre-close hardware observation | representative。close drain に隠れる退行を観測できる | 手動、低速、adapter と Switch 状態に依存する | CI 外の承認制 hardware test として追加する |
86
+ | Bumble private queue assertion | queue 内部には precise | Bumble 内部構造へ密結合し、Switch 反映を証明しない | 追加しない |
87
+
88
+ ### Gaps
89
+
90
+ - 自動化された Switch UI assertion はない。利用者確認と hardware log が必要。
91
+ - 観測窓は queue completion の時刻を測定しない。close 前に入力反映を確認するための時間境界である。
92
+
93
+ ## 10. 対象ファイル
94
+
95
+ | path | change | 内容 |
96
+ |---|---|---|
97
+ | `tests/hardware/test_pairing_profile.py` | modify | Direct fresh pairing に operator checkpoint と close 前観測窓を追加 |
98
+ | `spec/complete/unit_068/DIRECT_PRE_CLOSE_INPUT_REFLECTION.md` | new | 対象範囲、検証境界、実機条件を記録 |
99
+ | `spec/hardware-test-log.md` | modify | 実機 rerun、cleanup、利用者確認を記録 |
100
+
101
+ ## 11. 検証
102
+
103
+ | command | result | notes |
104
+ |---|---|---|
105
+ | `uv sync --dev` | pass | 53 packages resolved |
106
+ | `uv run ruff format --check .` | pass | 100 files already formatted |
107
+ | `uv run ruff check .` | pass | All checks passed |
108
+ | `uv run ty check --no-progress` | pass | All checks passed |
109
+ | `uv run pytest tests/unit` | pass | 468 passed |
110
+ | `uv run pytest tests/integration` | pass | 137 passed |
111
+ | `uv run pytest tests/hardware/test_pairing_profile.py --collect-only -q` | pass | adapter を開かず14件を収集。Direct fresh / reconnect は各3 controller |
112
+ | `uv run pytest tests/hardware/test_pairing_profile.py -q` | skipped | adapter option を指定せず14件すべて skip。実機経路は未実行 |
113
+ | `uv sync --dev --group docs` | pass | docs dependencies を同期 |
114
+ | `uv run mkdocs build --strict` | pass | strict build 成功 |
115
+ | read-only adapter identity preflight / postflight | pass | HCI / CSR はともに `0E:08:71:C0:B4:5C`、postflight は `adapter_closed` |
116
+ | Direct Pro fresh pairing / Button A | pass | `1 passed in 33.27s`。30秒の close 前観測窓と trace 順序 assertion が成功 |
117
+ | Switch UI 目視 | observed-pass | 利用者が close 前に画面反応とコントローラー認識を確認 |
118
+ | 先行 reconnect 2件 | failed before send | HCI authentication failure reason 5。Button A 送信と観測窓より前の失敗であり、input reflection の判定には使用しない |
119
+
120
+ ## 12. 実機実行条件
121
+
122
+ | 項目 | 内容 |
123
+ |---|---|
124
+ | 実機要否 | required for input reflection completion |
125
+ | 承認範囲 | 専用 adapter open、profile identity preparation、Direct HID fresh pairing、sentinel button 1件、close 前観測窓、neutral close |
126
+ | adapter | dedicated `usb:0`、CSR8510 A10、VID:PID `0A12:0001`、WinUSB |
127
+ | 実行遮断 | 環境変数による遮断は採用しない。明示承認、対象 adapter、command、cleanup plan で管理する |
128
+ | log / artifact | `build/hardware/unit_068/direct-pro-fresh-pre-close-20260724-115129/` と利用者目視結果を `spec/hardware-test-log.md` に記録 |
129
+ | cleanup | `close(neutral=True)`、disconnect、transport close、adapter release を実行。postflight で identity 一致と `adapter_closed` を確認 |
130
+
131
+ ## 13. 先送り事項
132
+
133
+ - Joy-Con L / Joy-Con R の同一観測は未実行。今回の完了 gate は仕様どおり Direct Pro / Button A の代表ケースとし、両 variant は必要になった時点で同じ parameterized test を実行する。
134
+
135
+ ## 14. チェックリスト
136
+
137
+ - [x] 対象範囲と対象外を確認した
138
+ - [x] TDD Test List または文書検証計画を更新した
139
+ - [x] 必要な根拠監査を記録した
140
+ - [x] 実機実行条件を記録した
141
+ - [x] close 前観測窓を実装した
142
+ - [x] 非実機 gate の結果を記録した
143
+ - [x] 実機 rerun と利用者確認を記録した