safety, no data imported into sqlite yet
This commit is contained in:
parent
f47cc42d10
commit
41a5c86a8e
8 changed files with 940 additions and 0 deletions
1
migration/.gitignore
vendored
Normal file
1
migration/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
*.sqlite
|
||||
47
migration/Codex_prompt_20250616_1449.md
Normal file
47
migration/Codex_prompt_20250616_1449.md
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
I am trying to extract the protocol-only portion of this BLE Reticulum implementation into a future C++ library callable from Python.
|
||||
|
||||
Use /usr/local/src/ble-reticulum/src/ble_symbols_20260516_1429.txt as the master inventory. For every symbol listed in that file, inspect the corresponding source code and classify it as:
|
||||
|
||||
[CORE]
|
||||
Protocol logic that may belong in a future C++/Rust library.
|
||||
|
||||
[GLUE]
|
||||
Python Reticulum integration that should probably stay Python initially.
|
||||
|
||||
[PLATFORM]
|
||||
Linux/BLE/BlueZ/Bleak/bluezero/DBus/GATT/scanning/advertising code.
|
||||
|
||||
[TEST]
|
||||
Examples, proof scripts, diagnostics, command-line tools, or test harnesses.
|
||||
|
||||
[UNKNOWN]
|
||||
Not enough information to classify safely.
|
||||
|
||||
For each symbol, produce a Markdown table with:
|
||||
|
||||
- file path
|
||||
- symbol name
|
||||
- line number
|
||||
- tag
|
||||
- phase-1 C++ candidate: yes/no
|
||||
- rationale
|
||||
- important callers, if easily found
|
||||
- important callees, if easily found
|
||||
|
||||
Do not modify files.
|
||||
|
||||
At the end, produce:
|
||||
|
||||
1. A "Phase 1 C++ extraction candidates" list.
|
||||
2. A "Do not port yet" list.
|
||||
3. A short explanation of where the Python/C++ boundary should probably be.
|
||||
4. Any symbols whose classification depends on Reticulum internals.
|
||||
|
||||
For information about where reticulum is installed, see /usr/local/src/ble-reticulum/reticulum_info.txt
|
||||
|
||||
The main tree is /usr/local/src/ble-reticulum which is pulled from my Forgejo instance. I have created a branch "c++migration" which is the current branch.
|
||||
|
||||
Treat ble_dual_node_echo.py as an acceptance test/harness, not as the source of the protocol-core design.
|
||||
|
||||
Prefer conservative classification. If a symbol touches RNS.Transport, RNS.Interface, RNS.Link, BleakClient, bluezero, DBus, sockets, threads, or OS-specific objects, do not mark it as phase-1 C++ unless the protocol logic can be cleanly separated from those dependencies.
|
||||
|
||||
154
migration/Codex_response_20260616_1514.md
Normal file
154
migration/Codex_response_20260616_1514.md
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
Read-only inspection completed. Note: the prompt’s Reticulum info path was not present as named; I used `/usr/local/src/ble-reticulum/reticulum_info_20260516_1444.txt`. Installed RNS is `rns 1.1.3` at `/home/jlpoole/rnsenv/lib/python3.13/site-packages/RNS`.
|
||||
|
||||
**BLEFragmentation.py**
|
||||
|
||||
| file path | symbol | line | tag | phase-1 C++ candidate | rationale | important callers | important callees |
|
||||
|---|---:|---:|---|---|---|---|---|
|
||||
| `src/ble_reticulum/BLEFragmentation.py` | `BLEFragmenter` | 52 | [CORE] | yes | Pure BLE packet fragmentation format; RNS only logging. | `BLEInterface._mtu_negotiated_callback`, `_handle_identity_handshake`, `BLEPeerInterface.process_outgoing` | `struct.pack` |
|
||||
| same | `BLEFragmenter.__init__` | 68 | [CORE] | yes | MTU/header sizing logic. | fragmenter construction | none |
|
||||
| same | `BLEFragmenter.fragment_packet` | 82 | [CORE] | yes | Core packet-to-fragments encoding. | `BLEPeerInterface.process_outgoing` | `struct.pack` |
|
||||
| same | `BLEFragmenter.get_fragment_overhead` | 158 | [CORE] | yes | Pure sizing/overhead calculation. | tests/diagnostics likely | none |
|
||||
| same | `BLEReassembler` | 176 | [CORE] | yes | Core fragment state machine; RNS only logging. | `BLEInterface` receive paths | `_reassemble`, `cleanup_stale_buffers` |
|
||||
| same | `BLEReassembler.__init__` | 187 | [CORE] | yes | Protocol reassembly state. | reassembler construction | none |
|
||||
| same | `BLEReassembler.receive_fragment` | 205 | [CORE] | yes | Core fragment validation/dedup/reassembly trigger. | `_handle_ble_data`, `handle_peripheral_data` | `struct.unpack`, `_reassemble` |
|
||||
| same | `BLEReassembler._reassemble` | 380 | [CORE] | yes | Pure ordered fragment join. | `receive_fragment` | none |
|
||||
| same | `BLEReassembler.cleanup_stale_buffers` | 402 | [CORE] | yes | Timeout policy for incomplete protocol frames. | cleanup timer, receive paths | `time.time` |
|
||||
| same | `BLEReassembler.get_statistics` | 429 | [CORE] | yes | Protocol stats. | receive/logging paths | none |
|
||||
| same | `BLEReassembler.reset_statistics` | 443 | [CORE] | yes | Protocol stats reset. | tests likely | none |
|
||||
| same | `HDLCFramer` | 450 | [CORE] | yes | Pure byte-stuffing frame format. | not obviously used | static methods |
|
||||
| same | `HDLCFramer.frame_packet` | 464 | [CORE] | yes | Pure HDLC-style escaping. | tests/possible future use | none |
|
||||
| same | `HDLCFramer.deframe_packet` | 491 | [CORE] | yes | Pure HDLC-style unescaping/validation. | tests/possible future use | none |
|
||||
|
||||
**BLEInterface.py**
|
||||
|
||||
| file path | symbol | line | tag | phase-1 C++ candidate | rationale | important callers | important callees |
|
||||
|---|---:|---:|---|---|---|---|---|
|
||||
| `src/ble_reticulum/BLEInterface.py` | `DiscoveredPeer` | 118 | [PLATFORM] | no | BLE discovery/connection scoring state. | `_device_discovered_callback`, `_select_peers_to_connect` | `time.time` |
|
||||
| same | `DiscoveredPeer.__init__` | 146 | [PLATFORM] | no | Stores BLE address/RSSI/timing. | discovery callback | `time.time` |
|
||||
| same | `update_rssi` | 167 | [PLATFORM] | no | Discovery cache update. | discovery callback | `time.time` |
|
||||
| same | `record_connection_attempt` | 172 | [PLATFORM] | no | BLE connection policy state. | discovery callback | `time.time` |
|
||||
| same | `record_connection_success` | 177 | [PLATFORM] | no | BLE connection policy state. | `_record_connection_success` | none |
|
||||
| same | `record_connection_failure` | 181 | [PLATFORM] | no | BLE connection policy state. | `_record_connection_failure` | none |
|
||||
| same | `get_success_rate` | 185 | [PLATFORM] | no | BLE peer scoring helper. | `_score_peer`, `__repr__` | none |
|
||||
| same | `__repr__` | 196 | [TEST] | no | Diagnostic formatting only. | logging/debug | `get_success_rate` |
|
||||
| same | `BLEInterface` | 202 | [GLUE] | no | Reticulum `Interface` implementation binding BLE driver to RNS Transport. | Reticulum external interface loader | many |
|
||||
| same | `BLEInterface.__init__` | 267 | [GLUE] | no | Heavy RNS config, driver, locks, timers, callbacks. | Reticulum loader | `Interface.get_config_obj`, driver ctor |
|
||||
| same | `start` | 479 | [GLUE] | no | Starts driver/scanning and touches Transport path workaround. | `__init__` | `driver.start`, `driver.start_scanning`, `_clear_stale_ble_paths` |
|
||||
| same | `final_init` | 516 | [GLUE] | no | Reticulum lifecycle hook. | Reticulum | `_start_advertising_when_identity_ready` |
|
||||
| same | `_setup_logging_redirect` | 529 | [GLUE] | no | RNS logging integration. | `__init__` | `logging`, `RNS.log` |
|
||||
| same | `_start_advertising_when_identity_ready` | 583 | [GLUE] | no | Polls `RNS.Transport.identity`; starts platform advertising. | `final_init` thread | `driver.set_identity`, `driver.start_advertising` |
|
||||
| same | `_clear_stale_ble_paths` | 630 | [GLUE] | no | Depends on `RNS.Transport.path_table` internals. | `start` | `Transport.path_table` |
|
||||
| same | `_start_cleanup_timer` | 686 | [GLUE] | no | Thread timer around Python state. | `__init__`, cleanup task | `threading.Timer` |
|
||||
| same | `_periodic_cleanup_task` | 701 | [GLUE] | no | Coordinates reassembly cleanup plus interface lifecycle. | timer | `cleanup_stale_buffers`, `_validate_spawned_interfaces` |
|
||||
| same | `_cleanup_pending_identity_connections` | 741 | [GLUE] | no | Driver disconnect policy around identity handshake. | cleanup task | `driver.disconnect` |
|
||||
| same | `_process_pending_detaches` | 771 | [GLUE] | no | Reticulum peer interface lifecycle. | cleanup task | `peer_if.detach`, `_get_fragmenter_key` |
|
||||
| same | `_validate_spawned_interfaces` | 829 | [GLUE] | no | Compares RNS spawned interfaces to driver connections. | cleanup task | `driver.connected_peers`, `peer_if.detach` |
|
||||
| same | `_device_discovered_callback` | 912 | [PLATFORM] | no | BLE scan callback and connection initiation. | driver callback | `DiscoveredPeer`, `_select_peers_to_connect`, `driver.connect` |
|
||||
| same | `_device_connected_callback` | 964 | [GLUE] | no | Driver callback; maps identity to Reticulum peer interface. | driver callback | `_compute_identity_hash`, `_mtu_negotiated_callback` |
|
||||
| same | `_check_duplicate_identity` | 1023 | [GLUE] | no | Identity dedup policy tied to driver state and MAC rotation. | driver callback | `_cleanup_stale_address`, `driver.disconnect` |
|
||||
| same | `_mtu_negotiated_callback` | 1112 | [GLUE] | no | Creates protocol fragmenters but tied to driver/RNS interface spawn. | driver callback | `BLEFragmenter`, `BLEReassembler`, `_spawn_peer_interface` |
|
||||
| same | `_handle_identity_handshake` | 1174 | [GLUE] | no | 16-byte identity handshake is protocol-ish, but intertwined with driver/RNS state. | `_data_received_callback` | `_check_duplicate_identity`, `_spawn_peer_interface` |
|
||||
| same | `_data_received_callback` | 1281 | [GLUE] | no | Driver callback dispatch. | driver callback | `_handle_identity_handshake`, `_handle_ble_data` |
|
||||
| same | `_device_disconnected_callback` | 1295 | [GLUE] | no | Reticulum/driver cleanup. | driver callback | `_compute_identity_hash`, detach scheduling |
|
||||
| same | `_cleanup_stale_address` | 1380 | [GLUE] | no | MAC rotation mapping cleanup. | duplicate/address-change paths | dict cleanup |
|
||||
| same | `_address_changed_callback` | 1411 | [GLUE] | no | Driver MAC rotation callback. | driver callback | `_get_fragmenter_key`, `_compute_identity_hash` |
|
||||
| same | `_error_callback` | 1479 | [GLUE] | no | Driver error logging/blacklisting. | driver callback | `_record_connection_failure` |
|
||||
| same | `_score_peer` | 1534 | [PLATFORM] | no | BLE RSSI/recency scoring policy. | `_select_peers_to_connect` | `peer.get_success_rate` |
|
||||
| same | `_select_peers_to_connect` | 1620 | [PLATFORM] | no | BLE connection selection and MAC sorting. | discovery callback | `_score_peer`, `_is_blacklisted` |
|
||||
| same | `_is_blacklisted` | 1761 | [PLATFORM] | no | BLE retry/backoff policy. | `_select_peers_to_connect` | `time.time` |
|
||||
| same | `_record_connection_success` | 1785 | [PLATFORM] | no | BLE discovery/backoff state. | connection callback | `DiscoveredPeer.record_connection_success` |
|
||||
| same | `_record_connection_failure` | 1800 | [PLATFORM] | no | BLE retry/backoff plus BlueZ cleanup hook. | error callback | `driver._remove_bluez_device` |
|
||||
| same | `_get_fragmenter_key` | 1858 | [CORE] | yes | Pure identity-to-fragment-state key; cleanly separable. | many send/receive paths | `bytes.hex` |
|
||||
| same | `_compute_identity_hash` | 1871 | [CORE] | yes | Pure identity truncation rule; cleanly separable. | identity mapping paths | `bytes.hex` |
|
||||
| same | `_spawn_peer_interface` | 1892 | [GLUE] | no | Creates Reticulum `Interface`, mutates `RNS.Transport.interfaces`. | MTU/handshake paths | `BLEPeerInterface`, `RNS.Transport.interfaces.append` |
|
||||
| same | `_handle_ble_data` | 1957 | [GLUE] | no | Uses core reassembly, but routes into Reticulum peer interfaces. | data callback | `BLEReassembler.receive_fragment`, `peer_if.process_incoming` |
|
||||
| same | `handle_peripheral_data` | 2085 | [GLUE] | no | Older peripheral data path; handshake/reassembly/RNS routing mixed. | `BLEGATTServer` callback | `BLEFragmenter`, `BLEReassembler`, `_spawn_peer_interface` |
|
||||
| same | `handle_central_connected` | 2188 | [GLUE] | no | GATT server to RNS interface lifecycle. | `BLEGATTServer` callback | `_spawn_peer_interface` |
|
||||
| same | `handle_central_disconnected` | 2222 | [GLUE] | no | GATT server cleanup of Reticulum peer mapping. | `BLEGATTServer` callback | `_compute_identity_hash` |
|
||||
| same | `process_incoming` | 2291 | [GLUE] | no | Calls Reticulum owner inbound. | peer interfaces | `owner.inbound` |
|
||||
| same | `process_outgoing` | 2305 | [GLUE] | no | Broadcasts Reticulum packet to peer interfaces. | Reticulum Transport | `peer_if.process_outgoing` |
|
||||
| same | `detach` | 2335 | [GLUE] | no | Reticulum/driver shutdown. | Reticulum | `driver.stop`, `peer_if.detach` |
|
||||
| same | `should_ingress_limit` | 2365 | [GLUE] | no | Reticulum Interface policy. | Reticulum | none |
|
||||
| same | `__str__` | 2376 | [TEST] | no | Diagnostic formatting. | logging | none |
|
||||
| same | `BLEPeerInterface` | 2380 | [GLUE] | no | Reticulum per-peer interface wrapper. | `_spawn_peer_interface` | `Interface` |
|
||||
| same | `BLEPeerInterface.__init__` | 2388 | [GLUE] | no | Reticulum interface fields/statistics. | `_spawn_peer_interface` | `Interface.__init__` |
|
||||
| same | `BLEPeerInterface.process_incoming` | 2420 | [GLUE] | no | Hands data to `owner.inbound`. | `_handle_ble_data` | `owner.inbound` |
|
||||
| same | `BLEPeerInterface.process_outgoing` | 2437 | [GLUE] | no | Calls core fragmenter, then platform driver send. | parent `process_outgoing`, Reticulum | `fragment_packet`, `driver.send` |
|
||||
| same | `BLEPeerInterface.detach` | 2483 | [GLUE] | no | Removes interface from `RNS.Transport.interfaces`. | cleanup paths | `RNS.Transport.interfaces.remove` |
|
||||
| same | `BLEPeerInterface.should_ingress_limit` | 2493 | [GLUE] | no | Delegates Reticulum policy. | Reticulum | parent method |
|
||||
| same | `BLEPeerInterface.connection_id` | 2498 | [GLUE] | no | Reticulum/RNS identity display helper. | Reticulum/status | `RNS.Identity.full_hash` |
|
||||
| same | `BLEPeerInterface.__str__` | 2510 | [TEST] | no | Diagnostic formatting. | logging | none |
|
||||
|
||||
**BLEAgent.py, BLEGATTServer.py, bluetooth_driver.py**
|
||||
|
||||
| file path | symbol | line | tag | phase-1 C++ candidate | rationale | important callers | important callees |
|
||||
|---|---:|---:|---|---|---|---|---|
|
||||
| `src/ble_reticulum/BLEAgent.py` | `BLEAgent` + all methods | 55 | [PLATFORM] | no | BlueZ DBus pairing agent. | `register_agent`, GATT servers | `dbus.service`, `RNS.log` |
|
||||
| same | `register_agent` | 202 | [PLATFORM] | no | Registers BlueZ agent on system DBus. | GATT server startup | `DBusGMainLoop`, `dbus.SystemBus` |
|
||||
| same | `unregister_agent` | 262 | [PLATFORM] | no | Unregisters BlueZ agent. | GATT server shutdown | `dbus.SystemBus` |
|
||||
| `src/ble_reticulum/BLEGATTServer.py` | `BLEGATTServer` + all methods | 51 | [PLATFORM] | no | bluezero GATT server, threads, callbacks, notifications. | older/alternate peripheral path | `bluezero.peripheral`, `register_agent` |
|
||||
| same | `set_transport_identity` | 484 | [GLUE] | no | Validates Reticulum identity bytes but serves them over GATT. | startup | none |
|
||||
| `src/ble_reticulum/bluetooth_driver.py` | `BLEDevice` | 10 | [PLATFORM] | no | BLE discovery DTO. | Linux driver scan | dataclass |
|
||||
| same | `DriverState` | 18 | [PLATFORM] | no | Driver state enum. | driver state property | enum |
|
||||
| same | `BLEDriverInterface` + all abstract methods | 29 | [PLATFORM] | no | Platform BLE backend contract, not protocol core. | `BLEInterface` | abstract methods |
|
||||
|
||||
**linux_bluetooth_driver.py**
|
||||
|
||||
| file path | symbol | line | tag | phase-1 C++ candidate | rationale | important callers | important callees |
|
||||
|---|---:|---:|---|---|---|---|---|
|
||||
| `src/ble_reticulum/linux_bluetooth_driver.py` | `_rns_showwarning` | 142 | [GLUE] | no | Routes Python warnings to RNS logging. | `warnings.showwarning` | `RNS.log` |
|
||||
| same | `apply_bluez_services_resolved_patch` | 220 | [PLATFORM] | no | Monkey-patches Bleak BlueZ manager. | `LinuxBluetoothDriver.__init__` | `BlueZManager._wait_for_services_discovery` |
|
||||
| same | `PeerConnection` | 287 | [PLATFORM] | no | BLE connection runtime DTO with `BleakClient`. | driver connection state | dataclass |
|
||||
| same | `LinuxBluetoothDriver` + lifecycle/scanning/connection/GATT methods | 297 | [PLATFORM] | no | Linux BLE backend using Bleak, bluezero, DBus, asyncio, threads. | `BLEInterface` | `BleakScanner`, `BleakClient`, DBus, `BluezeroGATTServer` |
|
||||
| same | `_connect_to_peer` | 988 | [PLATFORM] | no | Central connection flow, service discovery, GATT reads/writes. | `connect` | `BleakClient`, `_negotiate_mtu`, callbacks |
|
||||
| same | `_connect_via_dbus_le` | 1253 | [PLATFORM] | no | BlueZ DBus LE-only workaround. | `_connect_to_peer` | `MessageBus`, `Adapter1.ConnectDevice` |
|
||||
| same | `_negotiate_mtu` | 1291 | [PLATFORM] | no | Bleak/BlueZ MTU probing. | `_connect_to_peer` | `client._backend`, `client.mtu_size` |
|
||||
| same | `_handle_notification` | 1332 | [PLATFORM] | no | Bleak notification callback adapter. | `start_notify` callback | `on_data_received` |
|
||||
| same | `BluezeroGATTServer` + all methods | 1578 | [PLATFORM] | no | bluezero peripheral server, DBus monitoring, stale polling. | `LinuxBluetoothDriver.start_advertising` | `bluezero`, DBus, threads |
|
||||
| same | `_handle_write_rx` | 2328 | [PLATFORM] | no | GATT write callback; forwards bytes upward. | bluezero | driver callbacks |
|
||||
| same | `_handle_read_identity` | 2374 | [PLATFORM] | no | GATT identity characteristic read. | bluezero | none |
|
||||
| same | `_handle_central_connected` | 2388 | [PLATFORM] | no | Peripheral connection state plus callbacks. | `_handle_write_rx` | `PeerConnection`, driver callbacks |
|
||||
| same | `_handle_central_disconnected` | 2430 | [PLATFORM] | no | DBus/poll disconnect cleanup. | DBus monitor, stale poll | driver callback |
|
||||
| same | `send_notification` | 2479 | [PLATFORM] | no | bluezero notification send. | `LinuxBluetoothDriver.send` | `tx_characteristic.set_value` |
|
||||
|
||||
For `linux_bluetooth_driver.py`, the inventory includes many individual platform methods under `LinuxBluetoothDriver` and `BluezeroGATTServer`; all are [PLATFORM]/no for the same reason: they directly touch Bleak, bluezero, DBus, BlueZ, sockets/processes, asyncio event loops, or threads.
|
||||
|
||||
**Phase 1 C++ Extraction Candidates**
|
||||
- `BLEFragmenter`
|
||||
- `BLEFragmenter.fragment_packet`
|
||||
- `BLEFragmenter.get_fragment_overhead`
|
||||
- `BLEReassembler`
|
||||
- `BLEReassembler.receive_fragment`
|
||||
- `BLEReassembler.cleanup_stale_buffers`
|
||||
- `BLEReassembler.get_statistics`
|
||||
- `BLEReassembler.reset_statistics`
|
||||
- `HDLCFramer.frame_packet`
|
||||
- `HDLCFramer.deframe_packet`
|
||||
- Extracted pure equivalents of `BLEInterface._get_fragmenter_key`
|
||||
- Extracted pure equivalents of `BLEInterface._compute_identity_hash`
|
||||
|
||||
**Do Not Port Yet**
|
||||
- `BLEInterface` and `BLEPeerInterface` as classes.
|
||||
- All BlueZ/Bleak/bluezero/DBus code: `BLEAgent`, `BLEGATTServer`, `LinuxBluetoothDriver`, `BluezeroGATTServer`.
|
||||
- `bluetooth_driver.py` driver abstraction unless designing a cross-language platform backend API later.
|
||||
- Peer discovery/scoring/backoff/MAC-rotation orchestration in `BLEInterface`; it is BLE transport policy and Reticulum glue, not a clean protocol core.
|
||||
- `ble_dual_node_echo.py`: treat as acceptance harness, as requested.
|
||||
|
||||
**Likely Python/C++ Boundary**
|
||||
The clean first boundary is a small protocol library that accepts/returns bytes and simple metadata only: fragment packet, parse fragment, reassemble by sender/session key, timeout stale buffers, and compute identity-derived keys. Python should continue owning Reticulum `Interface` integration, `RNS.Transport` mutation, driver callbacks, scanning, advertising, GATT characteristics, DBus pairing, threading, timers, and logging.
|
||||
|
||||
**Classification Depends On Reticulum Internals**
|
||||
- `BLEInterface.__init__`, `start`, `final_init`
|
||||
- `_start_advertising_when_identity_ready`
|
||||
- `_clear_stale_ble_paths`
|
||||
- `_spawn_peer_interface`
|
||||
- `_handle_ble_data`
|
||||
- `handle_peripheral_data`
|
||||
- `process_incoming`
|
||||
- `process_outgoing`
|
||||
- `detach`
|
||||
- `BLEPeerInterface.process_incoming`
|
||||
- `BLEPeerInterface.detach`
|
||||
- `BLEPeerInterface.connection_id`
|
||||
|
||||
The strongest dependency is `_clear_stale_ble_paths`, which assumes `RNS.Transport.path_table` tuple indexes and BLE interface type names.
|
||||
1
migration/README.md
Normal file
1
migration/README.md
Normal file
|
|
@ -0,0 +1 @@
|
|||
This directory concerns the migration to C++ the ble-reticulum project.
|
||||
182
migration/ble_symbols_20260516_1429.txt
Normal file
182
migration/ble_symbols_20260516_1429.txt
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
BLEAgent.py
|
||||
class BLEAgent line 55
|
||||
def __init__(self, bus, capability) line 68
|
||||
def _log(self, message, level) line 82
|
||||
def Release(self) line 101
|
||||
def AuthorizeService(self, device, uuid) line 111
|
||||
def RequestAuthorization(self, device) line 127
|
||||
def RequestConfirmation(self, device, passkey) line 139
|
||||
def RequestPasskey(self, device) line 155
|
||||
def Cancel(self) line 172
|
||||
def _format_device_path(self, device_path) line 182
|
||||
def register_agent(capability) line 202
|
||||
def unregister_agent(agent) line 262
|
||||
BLEFragmentation.py
|
||||
class BLEFragmenter line 52
|
||||
def __init__(self, mtu) line 68
|
||||
def fragment_packet(self, packet) line 82
|
||||
def get_fragment_overhead(self, packet_size) line 158
|
||||
class BLEReassembler line 176
|
||||
def __init__(self, timeout) line 187
|
||||
def receive_fragment(self, fragment, sender_id) line 205
|
||||
def _reassemble(self, buffer) line 380
|
||||
def cleanup_stale_buffers(self) line 402
|
||||
def get_statistics(self) line 429
|
||||
def reset_statistics(self) line 443
|
||||
class HDLCFramer line 450
|
||||
def frame_packet(packet) line 464
|
||||
def deframe_packet(frame) line 491
|
||||
BLEGATTServer.py
|
||||
class BLEGATTServer line 51
|
||||
def __init__(self, interface, device_name, agent_capability) line 77
|
||||
def _log(self, message, level) line 127
|
||||
def _handle_write_rx(self, value, options) line 148
|
||||
def _handle_read_identity(self, options) line 215
|
||||
def _handle_central_connected(self, central_address, mtu) line 242
|
||||
def _handle_central_disconnected(self, central_address) line 279
|
||||
def _run_server_thread(self) line 306
|
||||
async def start(self) line 441
|
||||
def set_transport_identity(self, identity_hash) line 484
|
||||
async def stop(self) line 503
|
||||
async def send_notification(self, data, central_address) line 543
|
||||
def is_connected(self, central_address) line 607
|
||||
def get_connected_centrals(self) line 620
|
||||
def get_connection_info(self, central_address) line 630
|
||||
def get_central_mtu(self, central_address) line 643
|
||||
def get_statistics(self) line 658
|
||||
def __str__(self) line 678
|
||||
def __repr__(self) line 684
|
||||
BLEInterface.py
|
||||
class DiscoveredPeer line 118
|
||||
def __init__(self, address, name, rssi) line 146
|
||||
def update_rssi(self, rssi) line 167
|
||||
def record_connection_attempt(self) line 172
|
||||
def record_connection_success(self) line 177
|
||||
def record_connection_failure(self) line 181
|
||||
def get_success_rate(self) line 185
|
||||
def __repr__(self) line 196
|
||||
class BLEInterface line 202
|
||||
def __init__(self, owner, configuration) line 267
|
||||
def start(self) line 479
|
||||
def final_init(self) line 516
|
||||
def _setup_logging_redirect(self) line 529
|
||||
def _start_advertising_when_identity_ready(self) line 583
|
||||
def _clear_stale_ble_paths(self) line 630
|
||||
def _start_cleanup_timer(self) line 686
|
||||
def _periodic_cleanup_task(self) line 701
|
||||
def _cleanup_pending_identity_connections(self) line 741
|
||||
def _process_pending_detaches(self) line 771
|
||||
def _validate_spawned_interfaces(self) line 829
|
||||
def _device_discovered_callback(self, device) line 912
|
||||
def _device_connected_callback(self, address, peer_identity) line 964
|
||||
def _check_duplicate_identity(self, address, peer_identity) line 1023
|
||||
def _mtu_negotiated_callback(self, address, mtu) line 1112
|
||||
def _handle_identity_handshake(self, address, data) line 1174
|
||||
def _data_received_callback(self, address, data) line 1281
|
||||
def _device_disconnected_callback(self, address) line 1295
|
||||
def _cleanup_stale_address(self, identity_hash, old_address) line 1380
|
||||
def _address_changed_callback(self, old_address, new_address, identity_hash) line 1411
|
||||
def _error_callback(self, severity, message, exc) line 1479
|
||||
def _score_peer(self, peer) line 1534
|
||||
def _select_peers_to_connect(self) line 1620
|
||||
def _is_blacklisted(self, address) line 1761
|
||||
def _record_connection_success(self, address) line 1785
|
||||
def _record_connection_failure(self, address) line 1800
|
||||
def _get_fragmenter_key(self, peer_identity, peer_address) line 1858
|
||||
def _compute_identity_hash(self, peer_identity) line 1871
|
||||
def _spawn_peer_interface(self, address, name, peer_identity, client, mtu, connection_type) line 1892
|
||||
def _handle_ble_data(self, peer_address, data) line 1957
|
||||
def handle_peripheral_data(self, data, sender_address) line 2085
|
||||
def handle_central_connected(self, address) line 2188
|
||||
def handle_central_disconnected(self, address) line 2222
|
||||
def process_incoming(self, data) line 2291
|
||||
def process_outgoing(self, data) line 2305
|
||||
def detach(self) line 2335
|
||||
def should_ingress_limit(self) line 2365
|
||||
def __str__(self) line 2376
|
||||
class BLEPeerInterface line 2380
|
||||
def __init__(self, parent, peer_address, peer_name, peer_identity) line 2388
|
||||
def process_incoming(self, data) line 2420
|
||||
def process_outgoing(self, data) line 2437
|
||||
def detach(self) line 2483
|
||||
def should_ingress_limit(self) line 2493
|
||||
def connection_id(self) line 2498
|
||||
def __str__(self) line 2510
|
||||
__init__.py
|
||||
bluetooth_driver.py
|
||||
class BLEDevice line 10
|
||||
class DriverState line 18
|
||||
class BLEDriverInterface line 29
|
||||
def start(self, service_uuid, rx_char_uuid, tx_char_uuid, identity_char_uuid) line 57
|
||||
def stop(self) line 66
|
||||
def set_identity(self, identity_bytes) line 74
|
||||
def state(self) line 85
|
||||
def connected_peers(self) line 91
|
||||
def start_scanning(self) line 98
|
||||
def stop_scanning(self) line 106
|
||||
def start_advertising(self, device_name, identity) line 111
|
||||
def stop_advertising(self) line 124
|
||||
def connect(self, address) line 129
|
||||
def disconnect(self, address) line 137
|
||||
def send(self, address, data) line 142
|
||||
def read_characteristic(self, address, char_uuid) line 157
|
||||
def write_characteristic(self, address, char_uuid, data) line 165
|
||||
def start_notify(self, address, char_uuid, callback) line 173
|
||||
def get_local_address(self) line 183
|
||||
def get_peer_role(self, address) line 191
|
||||
def set_service_discovery_delay(self, seconds) line 204
|
||||
def set_power_mode(self, mode) line 212
|
||||
linux_bluetooth_driver.py
|
||||
def _rns_showwarning(message, category, filename, lineno, file, line) line 142
|
||||
def apply_bluez_services_resolved_patch() line 220
|
||||
class PeerConnection line 287
|
||||
class LinuxBluetoothDriver line 297
|
||||
def __init__(self, discovery_interval, connection_timeout, min_rssi, service_discovery_delay, max_peers, adapter_index, agent_capability) line 314
|
||||
def _log(self, message, level) line 403
|
||||
def start(self, service_uuid, rx_char_uuid, tx_char_uuid, identity_char_uuid) line 426
|
||||
def stop(self) line 489
|
||||
def set_identity(self, identity_bytes) line 531
|
||||
def state(self) line 551
|
||||
def connected_peers(self) line 556
|
||||
def start_scanning(self) line 565
|
||||
def stop_scanning(self) line 582
|
||||
def _should_pause_scanning(self) line 593
|
||||
async def _scan_loop(self) line 607
|
||||
async def _perform_scan(self) line 636
|
||||
def start_advertising(self, device_name, identity) line 749
|
||||
def stop_advertising(self) line 784
|
||||
def connect(self, address) line 806
|
||||
def disconnect(self, address) line 876
|
||||
def _handle_peripheral_disconnected(self, address) line 909
|
||||
async def _remove_bluez_device(self, address) line 942
|
||||
async def _connect_to_peer(self, address) line 988
|
||||
async def _connect_via_dbus_le(self, peer_address) line 1253
|
||||
async def _negotiate_mtu(self, client) line 1291
|
||||
def _handle_notification(self, address, data) line 1332
|
||||
def send(self, address, data) line 1344
|
||||
def read_characteristic(self, address, char_uuid) line 1386
|
||||
def write_characteristic(self, address, char_uuid, data) line 1409
|
||||
def start_notify(self, address, char_uuid, callback) line 1431
|
||||
def get_local_address(self) line 1464
|
||||
def get_peer_role(self, address) line 1468
|
||||
def get_peer_mtu(self, address) line 1475
|
||||
def set_service_discovery_delay(self, seconds) line 1494
|
||||
def set_power_mode(self, mode) line 1499
|
||||
def _run_event_loop(self) line 1511
|
||||
async def _get_local_adapter_address(self) line 1523
|
||||
def _detect_bluez_version(self) line 1556
|
||||
class BluezeroGATTServer line 1578
|
||||
def __init__(self, driver, service_uuid, rx_char_uuid, tx_char_uuid, identity_char_uuid, adapter_index, agent_capability) line 1589
|
||||
def _log(self, message, level) line 1646
|
||||
def set_identity(self, identity_bytes) line 1650
|
||||
def _verify_services_on_dbus(self, timeout) line 1662
|
||||
def _monitor_device_disconnections(self) line 1730
|
||||
def _poll_stale_connections(self) line 1965
|
||||
def start(self, device_name) line 2072
|
||||
def stop(self) line 2160
|
||||
def _run_server_thread(self, device_name) line 2206
|
||||
def _handle_write_rx(self, value, options) line 2328
|
||||
def _handle_read_identity(self, options) line 2374
|
||||
def _handle_central_connected(self, central_address, mtu) line 2388
|
||||
def _handle_central_disconnected(self, central_address) line 2430
|
||||
def send_notification(self, central_address, data) line 2479
|
||||
41
migration/reticulum_info_20260516_1444.txt
Normal file
41
migration/reticulum_info_20260516_1444.txt
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ date
|
||||
Sat May 16 14:41:10 PDT 2026
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ python3 -c 'import RNS; print(RNS.__file__)'
|
||||
/home/jlpoole/rnsenv/lib/python3.13/site-packages/RNS/__init__.py
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ which rnsd
|
||||
/home/jlpoole/rnsenv/bin/rnsd
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ which rnstatus
|
||||
/home/jlpoole/rnsenv/bin/rnstatus
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ which rnpath
|
||||
/home/jlpoole/rnsenv/bin/rnpath
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ equery belongs "$(which rnsd)"
|
||||
* Searching for /home/jlpoole/rnsenv/bin/rnsd ...
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ python3 -m pip show rns
|
||||
python3 -m pip show reticulum
|
||||
Name: rns
|
||||
Version: 1.1.3
|
||||
Summary: Self-configuring, encrypted and resilient mesh networking stack for LoRa, packet radio, WiFi and everything in between
|
||||
Home-page: https://reticulum.network/
|
||||
Author: Mark Qvist
|
||||
Author-email: mark@unsigned.io
|
||||
License: Reticulum License
|
||||
Location: /home/jlpoole/rnsenv/lib/python3.13/site-packages
|
||||
Requires: cryptography, pyserial
|
||||
Required-by: lxmf, lxst, nomadnet, sbapp
|
||||
WARNING: Package(s) not found: reticulum
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $ date
|
||||
hostname
|
||||
which python3
|
||||
python3 -V
|
||||
python3 -c 'import RNS, os; print("RNS file:", RNS.__file__); print("RNS dir :", os.path.dirname(RNS.__file__))'
|
||||
which rnsd
|
||||
rnsd --version 2>/dev/null || true
|
||||
Sat May 16 14:43:28 PDT 2026
|
||||
jp
|
||||
/home/jlpoole/rnsenv/bin/python3
|
||||
Python 3.13.12
|
||||
RNS file: /home/jlpoole/rnsenv/lib/python3.13/site-packages/RNS/__init__.py
|
||||
RNS dir : /home/jlpoole/rnsenv/lib/python3.13/site-packages/RNS
|
||||
/home/jlpoole/rnsenv/bin/rnsd
|
||||
rnsd 1.1.3
|
||||
(rnsenv) jlpoole@jp /usr/local/src/ble-reticulum $
|
||||
456
migration/scripts/import_codex_review.pl
Normal file
456
migration/scripts/import_codex_review.pl
Normal file
|
|
@ -0,0 +1,456 @@
|
|||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
use Getopt::Long qw(GetOptions);
|
||||
use File::Basename qw(dirname);
|
||||
use Cwd qw(abs_path);
|
||||
|
||||
my $script_dir = dirname(abs_path($0));
|
||||
my $default_db = "$script_dir/ble_migration.sqlite";
|
||||
my $default_md = "$script_dir/Codex_response_20260616_1514.md";
|
||||
my $default_inventory = "$script_dir/ble_symbols_20260516_1429.txt";
|
||||
|
||||
my $db_path = $default_db;
|
||||
my $markdown_path = $default_md;
|
||||
my $inventory_path = $default_inventory;
|
||||
my $reviewer = 'codex';
|
||||
my $dry_run = 0;
|
||||
my $help = 0;
|
||||
|
||||
GetOptions(
|
||||
'db=s' => \$db_path,
|
||||
'markdown=s' => \$markdown_path,
|
||||
'inventory=s' => \$inventory_path,
|
||||
'reviewer=s' => \$reviewer,
|
||||
'dry-run' => \$dry_run,
|
||||
'help' => \$help,
|
||||
) or usage(2);
|
||||
|
||||
usage(0) if $help;
|
||||
|
||||
die "Markdown file not found: $markdown_path\n" unless -f $markdown_path;
|
||||
die "SQLite database not found: $db_path\n" unless -f $db_path;
|
||||
die "Inventory file not found: $inventory_path\n" unless -f $inventory_path;
|
||||
|
||||
my $inventory = load_inventory($inventory_path);
|
||||
my @rows = parse_markdown_tables($markdown_path, $inventory);
|
||||
die "No symbol rows found in $markdown_path\n" unless @rows;
|
||||
|
||||
my $sql = build_sql(\@rows, $reviewer);
|
||||
|
||||
if ($dry_run) {
|
||||
print $sql;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
open(my $sqlite, '|-', 'sqlite3', $db_path)
|
||||
or die "Unable to start sqlite3 for $db_path: $!\n";
|
||||
print {$sqlite} $sql;
|
||||
close($sqlite) or die "sqlite3 import failed for $db_path\n";
|
||||
|
||||
print "Imported " . scalar(@rows) . " symbol review rows into $db_path\n";
|
||||
|
||||
sub usage {
|
||||
my ($exit_code) = @_;
|
||||
print <<"USAGE";
|
||||
Usage:
|
||||
perl migration/import_codex_review.pl [options]
|
||||
|
||||
Options:
|
||||
--db PATH SQLite database path
|
||||
default: migration/ble_migration.sqlite
|
||||
--markdown PATH Codex Markdown review path
|
||||
default: migration/Codex_response_20260616_1514.md
|
||||
--inventory PATH symbol inventory used to infer class_name for unqualified
|
||||
method rows
|
||||
default: migration/ble_symbols_20260516_1429.txt
|
||||
--reviewer NAME reviewer value for reviews table
|
||||
default: codex
|
||||
--dry-run print SQL instead of applying it
|
||||
--help show this help
|
||||
|
||||
The importer is idempotent for symbols: it upserts by the schema's unique key
|
||||
(source_file, class_name, symbol_name, line_number). It appends one review row
|
||||
per imported Markdown table row each time it is run.
|
||||
USAGE
|
||||
exit $exit_code;
|
||||
}
|
||||
|
||||
sub load_inventory {
|
||||
my ($path) = @_;
|
||||
open(my $fh, '<', $path) or die "Unable to read $path: $!\n";
|
||||
|
||||
my %inventory;
|
||||
my $current_file;
|
||||
my $current_class = '';
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
|
||||
if ($line =~ /^(\S+\.py)\s*$/) {
|
||||
$current_file = $1;
|
||||
$current_class = '';
|
||||
next;
|
||||
}
|
||||
|
||||
next unless defined $current_file;
|
||||
|
||||
if ($line =~ /^\s{4}class\s+([A-Za-z_][A-Za-z0-9_]*)\s+line\s+(\d+)/) {
|
||||
my ($class, $line_number) = ($1, $2);
|
||||
$current_class = $class;
|
||||
my $key = inventory_key($current_file, $class, $line_number);
|
||||
$inventory{$key} = {
|
||||
symbol_type => 'class',
|
||||
class_name => '',
|
||||
symbol_name => $class,
|
||||
};
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~ /^\s{8}(?:async\s+)?def\s+([A-Za-z_][A-Za-z0-9_]*)\([^)]*\)\s+line\s+(\d+)/) {
|
||||
my ($method, $line_number) = ($1, $2);
|
||||
my $key = inventory_key($current_file, $method, $line_number);
|
||||
$inventory{$key} = {
|
||||
symbol_type => 'method',
|
||||
class_name => $current_class,
|
||||
symbol_name => $method,
|
||||
};
|
||||
next;
|
||||
}
|
||||
|
||||
if ($line =~ /^\s{4}def\s+([A-Za-z_][A-Za-z0-9_]*)\([^)]*\)\s+line\s+(\d+)/) {
|
||||
my ($function, $line_number) = ($1, $2);
|
||||
my $key = inventory_key($current_file, $function, $line_number);
|
||||
$inventory{$key} = {
|
||||
symbol_type => 'function',
|
||||
class_name => '',
|
||||
symbol_name => $function,
|
||||
};
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
close($fh);
|
||||
return \%inventory;
|
||||
}
|
||||
|
||||
sub inventory_key {
|
||||
my ($file, $symbol, $line_number) = @_;
|
||||
return join('|', basename_only($file), $symbol, defined($line_number) ? $line_number : '');
|
||||
}
|
||||
|
||||
sub parse_markdown_tables {
|
||||
my ($path, $inventory) = @_;
|
||||
open(my $fh, '<', $path) or die "Unable to read $path: $!\n";
|
||||
|
||||
my @rows;
|
||||
my $current_file;
|
||||
my $in_expected_table = 0;
|
||||
|
||||
while (my $line = <$fh>) {
|
||||
chomp $line;
|
||||
|
||||
if ($line =~ /^\|\s*file path\s*\|\s*symbol\s*\|\s*line\s*\|\s*tag\s*\|\s*phase-1 C\+\+ candidate\s*\|/i) {
|
||||
$in_expected_table = 1;
|
||||
next;
|
||||
}
|
||||
|
||||
if ($in_expected_table && $line =~ /^\|\s*-+/) {
|
||||
next;
|
||||
}
|
||||
|
||||
if ($in_expected_table && $line !~ /^\|/) {
|
||||
$in_expected_table = 0;
|
||||
next;
|
||||
}
|
||||
|
||||
next unless $in_expected_table;
|
||||
|
||||
my @cells = split_markdown_row($line);
|
||||
next unless @cells == 8;
|
||||
|
||||
my ($file, $symbol, $line_number, $tag, $candidate, $rationale, $callers, $callees) = @cells;
|
||||
next if lc($file) eq 'file path';
|
||||
|
||||
$file = clean_cell($file);
|
||||
if ($file eq 'same') {
|
||||
die "Encountered 'same' file before an explicit file path\n" unless defined $current_file;
|
||||
$file = $current_file;
|
||||
} else {
|
||||
$current_file = $file;
|
||||
}
|
||||
|
||||
$symbol = clean_cell($symbol);
|
||||
$tag = clean_tag(clean_cell($tag));
|
||||
$candidate = lc(clean_cell($candidate)) eq 'yes' ? 1 : 0;
|
||||
$line_number = clean_cell($line_number);
|
||||
$line_number = $line_number =~ /(\d+)/ ? $1 : undef;
|
||||
|
||||
$rationale = clean_cell($rationale);
|
||||
$callers = clean_cell($callers);
|
||||
$callees = clean_cell($callees);
|
||||
|
||||
my ($symbol_type, $class_name, $symbol_name);
|
||||
my $inventory_key = inventory_key($file, symbol_lookup_name($symbol), $line_number);
|
||||
if (exists $inventory->{$inventory_key}) {
|
||||
$symbol_type = $inventory->{$inventory_key}->{symbol_type};
|
||||
$class_name = $inventory->{$inventory_key}->{class_name};
|
||||
$symbol_name = $inventory->{$inventory_key}->{symbol_name};
|
||||
} else {
|
||||
($symbol_type, $class_name, $symbol_name) = infer_symbol_shape($symbol);
|
||||
$class_name = '' unless defined $class_name;
|
||||
}
|
||||
my $phase = $candidate ? '1_candidate' : '0_inventory';
|
||||
my $confidence = $symbol =~ /\+\s*all\s+methods/i ? 'medium' : 'high';
|
||||
my $notes = "Imported from " . basename_only($path) . "; original symbol cell: $symbol";
|
||||
|
||||
push @rows, {
|
||||
source_file => $file,
|
||||
symbol_name => $symbol_name,
|
||||
symbol_type => $symbol_type,
|
||||
class_name => $class_name,
|
||||
line_number => $line_number,
|
||||
tag => $tag,
|
||||
phase => $phase,
|
||||
status => 'REVIEWED',
|
||||
cpp_candidate => $candidate,
|
||||
confidence => $confidence,
|
||||
rationale => $rationale,
|
||||
callers => $callers,
|
||||
callees => $callees,
|
||||
notes => $notes,
|
||||
};
|
||||
}
|
||||
|
||||
close($fh);
|
||||
return @rows;
|
||||
}
|
||||
|
||||
sub split_markdown_row {
|
||||
my ($line) = @_;
|
||||
$line =~ s/^\|//;
|
||||
$line =~ s/\|$//;
|
||||
my @cells = split /\|/, $line, -1;
|
||||
for my $cell (@cells) {
|
||||
$cell =~ s/^\s+//;
|
||||
$cell =~ s/\s+$//;
|
||||
}
|
||||
return @cells;
|
||||
}
|
||||
|
||||
sub clean_cell {
|
||||
my ($value) = @_;
|
||||
$value = '' unless defined $value;
|
||||
$value =~ s/<br\s*\/?>/\n/gi;
|
||||
$value =~ s/`([^`]*)`/$1/g;
|
||||
$value =~ s/^\s+//;
|
||||
$value =~ s/\s+$//;
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub clean_tag {
|
||||
my ($tag) = @_;
|
||||
$tag =~ s/^\[//;
|
||||
$tag =~ s/\]$//;
|
||||
$tag = uc($tag || 'UNKNOWN');
|
||||
return $tag =~ /^(CORE|GLUE|PLATFORM|TEST|UNKNOWN)$/ ? $tag : 'UNKNOWN';
|
||||
}
|
||||
|
||||
sub infer_symbol_shape {
|
||||
my ($symbol) = @_;
|
||||
|
||||
if ($symbol =~ /^([A-Za-z_][A-Za-z0-9_]*)\s*\+\s*all\s+methods\b/i) {
|
||||
return ('class_group', undef, $symbol);
|
||||
}
|
||||
|
||||
if ($symbol =~ /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/) {
|
||||
return ('method', $1, $2);
|
||||
}
|
||||
|
||||
if ($symbol =~ /^_[A-Za-z_][A-Za-z0-9_]*$/ || $symbol =~ /^[a-z_][A-Za-z0-9_]*$/) {
|
||||
return ('function', undef, $symbol);
|
||||
}
|
||||
|
||||
if ($symbol =~ /^[A-Z][A-Za-z0-9_]*$/) {
|
||||
return ('class', undef, $symbol);
|
||||
}
|
||||
|
||||
return ('symbol', undef, $symbol);
|
||||
}
|
||||
|
||||
sub symbol_lookup_name {
|
||||
my ($symbol) = @_;
|
||||
if ($symbol =~ /^([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)$/) {
|
||||
return $2;
|
||||
}
|
||||
if ($symbol =~ /^([A-Za-z_][A-Za-z0-9_]*)\s*\+\s*all\s+methods\b/i) {
|
||||
return $1;
|
||||
}
|
||||
return $symbol;
|
||||
}
|
||||
|
||||
sub build_sql {
|
||||
my ($rows, $reviewer_name) = @_;
|
||||
|
||||
my $sql = <<"SQL";
|
||||
.bail on
|
||||
PRAGMA foreign_keys = ON;
|
||||
BEGIN;
|
||||
|
||||
CREATE TEMP TABLE import_symbols (
|
||||
import_order INTEGER PRIMARY KEY,
|
||||
source_file TEXT NOT NULL,
|
||||
symbol_name TEXT NOT NULL,
|
||||
symbol_type TEXT,
|
||||
class_name TEXT,
|
||||
line_number INTEGER,
|
||||
tag TEXT NOT NULL,
|
||||
phase TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
cpp_candidate INTEGER NOT NULL,
|
||||
confidence TEXT,
|
||||
rationale TEXT,
|
||||
callers TEXT,
|
||||
callees TEXT,
|
||||
notes TEXT
|
||||
);
|
||||
|
||||
SQL
|
||||
|
||||
my $i = 0;
|
||||
for my $row (@{$rows}) {
|
||||
$i++;
|
||||
$sql .= "INSERT INTO import_symbols VALUES ("
|
||||
. join(', ',
|
||||
$i,
|
||||
sql_quote($row->{source_file}),
|
||||
sql_quote($row->{symbol_name}),
|
||||
sql_quote($row->{symbol_type}),
|
||||
sql_quote($row->{class_name}),
|
||||
sql_integer($row->{line_number}),
|
||||
sql_quote($row->{tag}),
|
||||
sql_quote($row->{phase}),
|
||||
sql_quote($row->{status}),
|
||||
$row->{cpp_candidate} ? 1 : 0,
|
||||
sql_quote($row->{confidence}),
|
||||
sql_quote($row->{rationale}),
|
||||
sql_quote($row->{callers}),
|
||||
sql_quote($row->{callees}),
|
||||
sql_quote($row->{notes}),
|
||||
)
|
||||
. ");\n";
|
||||
}
|
||||
|
||||
$sql .= <<"SQL";
|
||||
|
||||
CREATE TEMP TABLE import_existing AS
|
||||
SELECT
|
||||
i.import_order,
|
||||
s.symbol_id,
|
||||
s.tag AS old_tag,
|
||||
s.status AS old_status
|
||||
FROM import_symbols i
|
||||
JOIN symbols s
|
||||
ON s.source_file = i.source_file
|
||||
AND COALESCE(s.class_name, '') = COALESCE(i.class_name, '')
|
||||
AND s.symbol_name = i.symbol_name
|
||||
AND COALESCE(s.line_number, -1) = COALESCE(i.line_number, -1);
|
||||
|
||||
INSERT INTO symbols (
|
||||
source_file,
|
||||
symbol_name,
|
||||
symbol_type,
|
||||
class_name,
|
||||
line_number,
|
||||
tag,
|
||||
phase,
|
||||
status,
|
||||
cpp_candidate,
|
||||
confidence,
|
||||
rationale,
|
||||
callers,
|
||||
callees,
|
||||
notes,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
source_file,
|
||||
symbol_name,
|
||||
symbol_type,
|
||||
class_name,
|
||||
line_number,
|
||||
tag,
|
||||
phase,
|
||||
status,
|
||||
cpp_candidate,
|
||||
confidence,
|
||||
rationale,
|
||||
callers,
|
||||
callees,
|
||||
notes,
|
||||
CURRENT_TIMESTAMP
|
||||
FROM import_symbols
|
||||
WHERE 1
|
||||
ON CONFLICT(source_file, class_name, symbol_name, line_number) DO UPDATE SET
|
||||
symbol_type = excluded.symbol_type,
|
||||
tag = excluded.tag,
|
||||
phase = excluded.phase,
|
||||
status = excluded.status,
|
||||
cpp_candidate = excluded.cpp_candidate,
|
||||
confidence = excluded.confidence,
|
||||
rationale = excluded.rationale,
|
||||
callers = excluded.callers,
|
||||
callees = excluded.callees,
|
||||
notes = excluded.notes,
|
||||
updated_at = CURRENT_TIMESTAMP;
|
||||
|
||||
INSERT INTO reviews (
|
||||
symbol_id,
|
||||
reviewer,
|
||||
old_tag,
|
||||
new_tag,
|
||||
old_status,
|
||||
new_status,
|
||||
note
|
||||
)
|
||||
SELECT
|
||||
s.symbol_id,
|
||||
@{[sql_quote($reviewer_name)]},
|
||||
e.old_tag,
|
||||
i.tag,
|
||||
e.old_status,
|
||||
i.status,
|
||||
'Imported from Codex Markdown review. Rationale: ' || COALESCE(i.rationale, '')
|
||||
FROM import_symbols i
|
||||
JOIN symbols s
|
||||
ON s.source_file = i.source_file
|
||||
AND COALESCE(s.class_name, '') = COALESCE(i.class_name, '')
|
||||
AND s.symbol_name = i.symbol_name
|
||||
AND COALESCE(s.line_number, -1) = COALESCE(i.line_number, -1)
|
||||
LEFT JOIN import_existing e
|
||||
ON e.import_order = i.import_order;
|
||||
|
||||
COMMIT;
|
||||
SQL
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
sub sql_quote {
|
||||
my ($value) = @_;
|
||||
return 'NULL' unless defined $value;
|
||||
$value =~ s/'/''/g;
|
||||
return "'$value'";
|
||||
}
|
||||
|
||||
sub sql_integer {
|
||||
my ($value) = @_;
|
||||
return 'NULL' unless defined $value && $value =~ /^\d+$/;
|
||||
return $value;
|
||||
}
|
||||
|
||||
sub basename_only {
|
||||
my ($path) = @_;
|
||||
$path =~ s{.*/}{};
|
||||
return $path;
|
||||
}
|
||||
58
migration/sql/ble_migration_schema.sql
Normal file
58
migration/sql/ble_migration_schema.sql
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
-- 20260516 ChatGPT
|
||||
-- $Header$
|
||||
--
|
||||
-- Example:
|
||||
-- cd /usr/local/src/ble-reticulum/migration
|
||||
-- sqlite3 ble_migration.sqlite ".read sql/ble_migration_schema.sql"
|
||||
-- Verify
|
||||
-- sqlite3 ble_migration.sqlite ".tables"
|
||||
-- sqlite3 ble_migration.sqlite ".schema symbols"
|
||||
--
|
||||
-- Purpose:
|
||||
-- Track symbol-by-symbol migration status for BLE Reticulum protocol extraction.
|
||||
|
||||
CREATE TABLE IF NOT EXISTS symbols (
|
||||
symbol_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
source_file TEXT NOT NULL,
|
||||
symbol_name TEXT NOT NULL,
|
||||
symbol_type TEXT,
|
||||
class_name TEXT,
|
||||
line_number INTEGER,
|
||||
tag TEXT DEFAULT 'UNKNOWN',
|
||||
phase TEXT DEFAULT '0_inventory',
|
||||
status TEXT DEFAULT 'DISCOVERED',
|
||||
cpp_candidate INTEGER DEFAULT 0,
|
||||
confidence TEXT DEFAULT 'unknown',
|
||||
rationale TEXT,
|
||||
callers TEXT,
|
||||
callees TEXT,
|
||||
notes TEXT,
|
||||
first_seen_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
UNIQUE(source_file, class_name, symbol_name, line_number)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS reviews (
|
||||
review_id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
symbol_id INTEGER NOT NULL REFERENCES symbols(symbol_id),
|
||||
reviewed_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
reviewer TEXT,
|
||||
old_tag TEXT,
|
||||
new_tag TEXT,
|
||||
old_status TEXT,
|
||||
new_status TEXT,
|
||||
note TEXT
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS symbols_tag_idx
|
||||
ON symbols(tag);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS symbols_status_idx
|
||||
ON symbols(status);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS symbols_phase_idx
|
||||
ON symbols(phase);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS symbols_cpp_candidate_idx
|
||||
ON symbols(cpp_candidate);
|
||||
Loading…
Add table
Add a link
Reference in a new issue