From baeaf6fe1980d5353a5d85f1b653b09f3ff9d459 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 21:04:29 -0400 Subject: [PATCH 1/7] Repair what the ratchet counts with NRA plans; type imports by when they run tools/repairs.py: a Repair declares the located measure it removes and writes Nominal Refactor Advisor operations for each occurrence it can remove, tallying every one it keeps under the reason it stays. ImportHoist repairs FunctionLocalImport: it moves a local import to its module's top unless a module-level import cycle runs through it, judged with every accepted move already added to the load graph. tools/module_layers.py: Import is a family whose members say whether they run at module load: LoadTimeImport, CallTimeImport, CheckerImport (under TYPE_CHECKING). Only a function body is call-time; decorators, defaults and annotations run where the def runs. Package.load_graph gives the edges that load their target. docs/layout/MODULE_LAYERS.md regenerated; it had drifted 13 units. NRA joins the dev extra as a direct git reference. Co-Authored-By: Claude Opus 5.5 --- docs/layout/MODULE_LAYERS.md | 1574 +++++++++++++++-------------- pyproject.toml | 1 + tests/test_module_layers_loads.py | 46 + tests/test_repairs.py | 55 + tools/module_layers.py | 112 +- tools/repairs.py | 326 ++++++ uv.lock | 45 +- 7 files changed, 1398 insertions(+), 761 deletions(-) create mode 100644 tests/test_module_layers_loads.py create mode 100644 tests/test_repairs.py create mode 100644 tools/repairs.py diff --git a/docs/layout/MODULE_LAYERS.md b/docs/layout/MODULE_LAYERS.md index 76da6c1380..d5ea7c5635 100644 --- a/docs/layout/MODULE_LAYERS.md +++ b/docs/layout/MODULE_LAYERS.md @@ -4,9 +4,9 @@ Generated by `python tools/module_layers.py > docs/layout/MODULE_LAYERS.md`; do Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtime`, `ui_model`, `cli`, `commander`. Each layer imports only the layers before it; `ui_model`, `cli` and `commander` sit on top, and nothing outside a top layer imports it. The layer table in `tools/module_layers.py` declares the claiming prefixes; a module no prefix claims takes the highest layer it imports. -367 top-level units (8 of them subpackages); 1256 violating imports; 4 deletion candidates. +380 top-level units (8 of them subpackages); 1315 violating imports; 4 deletion candidates. -## wire (33) +## wire (34) - `bus_activity_index` - `bus_display_index` @@ -15,10 +15,12 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `bus_source_page` - `bus_tables` - `class_fact` +- `code_lines` - `core_stamp` - `delivery_failure` - `delivery_policy` - `delivery_presentation` +- `json_schema` - `lifecycle` - `lifecycle_capability` - `mentions` @@ -26,7 +28,6 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `message_page` - `message_reference` - `mro_dispatch` -- `participant_identity` - `pinned_audit` - `private_nk_entrypoint` - `private_path` @@ -42,7 +43,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `transcript_merge` - `wire_models` -## registry (41) +## registry (45) - `channel_coding_tools` - `channel_input_batch` @@ -54,8 +55,10 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `declared_verb` - `display_references` - `field_codec` +- `image_input` - `image_inputs` - `jsonl_stream` +- `owner_connection` - `owner_cutover` - `owner_fence` - `owner_launch` @@ -63,6 +66,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `owner_protocol` - `owner_requests` - `owner_restart` +- `participant_identity` - `peer_relevance` - `recorded_bus` - `recorded_time` @@ -71,6 +75,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `registry_document` - `registry_provenance` - `registry_store` +- `reported_turn` - `repository_name` - `reservation_rules` - `revision_views` @@ -86,7 +91,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `thread_status` - `thread_text` -## coordination (33) +## coordination (32) - `attempt_recovery` - `attempt_start` @@ -102,7 +107,6 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `coordination_session` - `coordination_snapshot` - `coordination_tables` -- `envelope_claim_transitions` - `goal_actions` - `goal_attempt_identity` - `goal_attempt_phase` @@ -133,13 +137,14 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `working_memory_requests` - `working_memory_worker` -## turns (44) +## turns (46) - `annotation_disclosure` - `input_attempt` - `input_disposition` - `input_drain` - `input_effects` +- `input_key` - `input_origin` - `selected_actions` - `selected_claim` @@ -154,6 +159,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `selected_write_authority` - `selected_write_plan` - `send_outcome` +- `session_config_options` - `session_effects` - `session_file` - `session_lifecycle` @@ -252,12 +258,12 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `tool_calls` - `tool_declaration` - `tool_denial` -- `tool_output` +- `tool_request` - `tool_result` - `tool_results` - `tools` -## commander (140) +## commander (147) - `acp` - `active_route` @@ -280,11 +286,15 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `cohort_schema` - `collaboration_ledger` - `commander` +- `commander_frame_file` - `commander_heartbeat` - `commander_hud` +- `commander_pings` +- `commander_service` - `comms` - `config_options` - `connector` +- `connector_caller` - `connector_store` - `context_store` - `coordinated_runtime` @@ -296,19 +306,20 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `display_order` - `drain_failures` - `durable_turn` +- `envelope_claim_transitions` - `errors` - `execution_states` - `execution_store` - `exporting` - `extension_ui` - `external_transcript` -- `fleet_replay` - `following_inputs` - `fresh_private_session` - `goals` - `harness_install` - `head_review` - `heartbeat_frame` +- `held_orders` - `historical_native_inputs` - `historical_views` - `history_result` @@ -332,6 +343,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `optional_awareness_projection` - `order_runs` - `order_story` +- `order_tools` - `order_work` - `ordinary_turn_rules` - `owned_send` @@ -342,6 +354,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim - `phase_tasks` - `plan_phases` - `presentation` +- `producer_stamp` - `progress_claims` - `prompt_state` - `proven_source_coverage` @@ -406,9 +419,9 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim |---|---|---|---| | `src/agent_comms/acp_extension.py:23` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/acp_extension.py:26` | `agent_comms.external_transcript` | runtime | commander | -| `src/agent_comms/acp_extension.py:43` | `agent_comms.routing` | runtime | commander | -| `src/agent_comms/acp_extension.py:45` | `agent_comms.tool_result` | runtime | cli | -| `src/agent_comms/acp_extension.py:46` | `agent_comms.transcripts` | runtime | commander | +| `src/agent_comms/acp_extension.py:48` | `agent_comms.routing` | runtime | commander | +| `src/agent_comms/acp_extension.py:50` | `agent_comms.tool_result` | runtime | cli | +| `src/agent_comms/acp_extension.py:51` | `agent_comms.transcripts` | runtime | commander | | `src/agent_comms/agent_activity.py:14` | `agent_comms.notification_progress` | runtime | commander | | `src/agent_comms/agent_activity.py:20` | `agent_comms.notification_progress` | runtime | commander | | `src/agent_comms/agent_activity.py:21` | `agent_comms.presentation` | runtime | commander | @@ -417,47 +430,45 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/agent_activity.py:33` | `agent_comms.audience_manifest` | runtime | commander | | `src/agent_comms/agent_activity.py:34` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/agent_activity.py:36` | `agent_comms.errors` | runtime | commander | -| `src/agent_comms/agent_activity.py:37` | `agent_comms.routing` | runtime | commander | -| `src/agent_comms/agent_activity.py:40` | `agent_comms.threads` | runtime | commander | -| `src/agent_comms/agent_activity.py:194` | `agent_comms.diagnostics` | runtime | commander | -| `src/agent_comms/agent_backend.py:31` | `agent_comms.tool_result` | runtime | cli | -| `src/agent_comms/agent_backend.py:37` | `agent_comms.launch_runtime` | runtime | commander | -| `src/agent_comms/agent_backend.py:41` | `agent_comms.threads` | runtime | commander | -| `src/agent_comms/agent_backend.py:42` | `agent_comms.transcript_sources` | runtime | commander | -| `src/agent_comms/agent_event_updates.py:28` | `agent_comms.coordinator` | runtime | commander | -| `src/agent_comms/agent_event_updates.py:30` | `agent_comms.tool_results` | runtime | cli | -| `src/agent_comms/agent_event_updates.py:31` | `agent_comms.transcript_updates` | runtime | commander | -| `src/agent_comms/agent_event_updates.py:35` | `agent_comms.routing` | runtime | commander | -| `src/agent_comms/agent_events.py:28` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/agent_events.py:43` | `agent_comms.tool_declaration` | runtime | cli | -| `src/agent_comms/agent_events.py:44` | `agent_comms.tool_results` | runtime | cli | -| `src/agent_comms/agent_events.py:48` | `agent_comms.comms` | runtime | commander | -| `src/agent_comms/agent_events.py:56` | `agent_comms.started_input` | runtime | commander | -| `src/agent_comms/agent_events.py:57` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/agent_events.py:371` | `agent_comms.coordinator` | runtime | commander | +| `src/agent_comms/agent_activity.py:38` | `agent_comms.routing` | runtime | commander | +| `src/agent_comms/agent_activity.py:41` | `agent_comms.threads` | runtime | commander | +| `src/agent_comms/agent_activity.py:195` | `agent_comms.diagnostics` | runtime | commander | +| `src/agent_comms/agent_backend.py:32` | `agent_comms.tool_result` | runtime | cli | +| `src/agent_comms/agent_backend.py:38` | `agent_comms.launch_runtime` | runtime | commander | +| `src/agent_comms/agent_backend.py:42` | `agent_comms.threads` | runtime | commander | +| `src/agent_comms/agent_backend.py:43` | `agent_comms.transcript_sources` | runtime | commander | +| `src/agent_comms/agent_event_updates.py:29` | `agent_comms.coordinator` | runtime | commander | +| `src/agent_comms/agent_event_updates.py:32` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/agent_event_updates.py:40` | `agent_comms.tool_results` | runtime | cli | +| `src/agent_comms/agent_event_updates.py:41` | `agent_comms.transcript_updates` | runtime | commander | +| `src/agent_comms/agent_event_updates.py:45` | `agent_comms.routing` | runtime | commander | +| `src/agent_comms/agent_events.py:23` | `agent_comms.child_process` | runtime | commander | +| `src/agent_comms/agent_events.py:38` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/agent_events.py:39` | `agent_comms.tool_results` | runtime | cli | +| `src/agent_comms/agent_events.py:46` | `agent_comms.comms` | runtime | commander | +| `src/agent_comms/agent_events.py:53` | `agent_comms.started_input` | runtime | commander | +| `src/agent_comms/agent_events.py:54` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/agent_events.py:368` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/agent_runtime.py:19` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/agent_runtime.py:20` | `agent_comms.messages` | runtime | commander | | `src/agent_comms/attempt_recovery.py:6` | `agent_comms.native_session_files` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:7` | `agent_comms.native_failures` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:38` | `agent_comms.coordinator` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:39` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:40` | `agent_comms.native_runtime_input` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:41` | `agent_comms.recovery_states` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:44` | `agent_comms.native_input_record` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:45` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:47` | `agent_comms.input_disposition` | coordination | turns | -| `src/agent_comms/attempt_recovery.py:48` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:49` | `agent_comms.registration` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:83` | `agent_comms.comms` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:84` | `agent_comms.native_runtime_input` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:289` | `agent_comms.comms` | coordination | commander | -| `src/agent_comms/attempt_recovery.py:319` | `agent_comms.native_entries` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:320` | `agent_comms.native_pi` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:321` | `agent_comms.native_prompt_binding` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:322` | `agent_comms.pi_vocabulary` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:436` | `agent_comms.native_entries` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:437` | `agent_comms.native_pi` | coordination | runtime | -| `src/agent_comms/attempt_recovery.py:438` | `agent_comms.native_prompt_binding` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:7` | `agent_comms.child_process` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:8` | `agent_comms.native_failures` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:39` | `agent_comms.coordinator` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:40` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:41` | `agent_comms.native_runtime_input` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:42` | `agent_comms.recovery_states` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:45` | `agent_comms.native_input_record` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:48` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:50` | `agent_comms.input_disposition` | coordination | turns | +| `src/agent_comms/attempt_recovery.py:51` | `agent_comms.locked_store` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:52` | `agent_comms.registration` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:53` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:75` | `agent_comms.comms` | coordination | commander | +| `src/agent_comms/attempt_recovery.py:450` | `agent_comms.native_entries` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:451` | `agent_comms.native_pi` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:452` | `agent_comms.native_prompt_binding` | coordination | runtime | +| `src/agent_comms/attempt_recovery.py:453` | `agent_comms.pi_vocabulary` | coordination | runtime | | `src/agent_comms/attempt_start.py:21` | `agent_comms.execution_states` | coordination | commander | | `src/agent_comms/attempt_states.py:19` | `agent_comms.coordinator_vocabulary` | coordination | commander | | `src/agent_comms/attempt_states.py:291` | `agent_comms.execution_states` | coordination | commander | @@ -467,31 +478,32 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/attempt_states.py:318` | `agent_comms.execution_states` | coordination | commander | | `src/agent_comms/attempt_states.py:319` | `agent_comms.obligation_states` | coordination | commander | | `src/agent_comms/attempt_store.py:8` | `agent_comms.assignment_states` | coordination | commander | -| `src/agent_comms/attempt_store.py:24` | `agent_comms.turn_failure` | coordination | turns | -| `src/agent_comms/attempt_store.py:25` | `agent_comms.recovery_reader` | coordination | commander | -| `src/agent_comms/attempt_store.py:26` | `agent_comms.recovery_states` | coordination | commander | +| `src/agent_comms/attempt_store.py:23` | `agent_comms.turn_failure` | coordination | turns | +| `src/agent_comms/attempt_store.py:24` | `agent_comms.recovery_reader` | coordination | commander | | `src/agent_comms/backend.py:65` | `agent_comms.tool_denial` | commander | cli | -| `src/agent_comms/bus_activity_index.py:8` | `agent_comms.activity_clocks` | wire | commander | -| `src/agent_comms/bus_activity_index.py:9` | `agent_comms.messages` | wire | commander | -| `src/agent_comms/bus_activity_index.py:10` | `agent_comms.typed_table` | wire | commander | +| `src/agent_comms/bus_activity_index.py:10` | `agent_comms.activity_clocks` | wire | commander | +| `src/agent_comms/bus_activity_index.py:11` | `agent_comms.messages` | wire | commander | +| `src/agent_comms/bus_activity_index.py:12` | `agent_comms.typed_table` | wire | commander | | `src/agent_comms/bus_display_index.py:4` | `agent_comms.activity_clocks` | wire | commander | | `src/agent_comms/bus_display_index.py:9` | `agent_comms.typed_table` | wire | commander | -| `src/agent_comms/bus_publication.py:11` | `agent_comms.audience_manifest` | wire | commander | -| `src/agent_comms/bus_publication.py:12` | `agent_comms.messages` | wire | commander | -| `src/agent_comms/bus_publication.py:13` | `agent_comms.errors` | wire | commander | -| `src/agent_comms/bus_publication.py:18` | `agent_comms.response_acknowledgement` | wire | commander | -| `src/agent_comms/bus_publication.py:21` | `agent_comms.typed_table` | wire | commander | -| `src/agent_comms/bus_publication.py:23` | `agent_comms.field_codec` | wire | registry | -| `src/agent_comms/bus_publication.py:24` | `agent_comms.read_basis` | wire | commander | -| `src/agent_comms/bus_publication.py:25` | `agent_comms.wake_policy` | wire | coordination | -| `src/agent_comms/bus_publication.py:28` | `agent_comms.bus` | wire | commander | -| `src/agent_comms/bus_publication.py:30` | `agent_comms.goal_management` | wire | coordination | -| `src/agent_comms/bus_publication.py:31` | `agent_comms.registry_document` | wire | registry | -| `src/agent_comms/bus_publication.py:32` | `agent_comms.threads` | wire | commander | -| `src/agent_comms/bus_route_counts.py:9` | `agent_comms.messages` | wire | commander | -| `src/agent_comms/bus_route_counts.py:10` | `agent_comms.read_basis` | wire | commander | -| `src/agent_comms/bus_route_counts.py:11` | `agent_comms.typed_table` | wire | commander | -| `src/agent_comms/bus_route_counts.py:14` | `agent_comms.page_traversal` | wire | commander | +| `src/agent_comms/bus_publication.py:13` | `agent_comms.audience_manifest` | wire | commander | +| `src/agent_comms/bus_publication.py:14` | `agent_comms.messages` | wire | commander | +| `src/agent_comms/bus_publication.py:15` | `agent_comms.errors` | wire | commander | +| `src/agent_comms/bus_publication.py:20` | `agent_comms.response_acknowledgement` | wire | commander | +| `src/agent_comms/bus_publication.py:23` | `agent_comms.typed_table` | wire | commander | +| `src/agent_comms/bus_publication.py:25` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/bus_publication.py:26` | `agent_comms.read_basis` | wire | commander | +| `src/agent_comms/bus_publication.py:27` | `agent_comms.wake_policy` | wire | coordination | +| `src/agent_comms/bus_publication.py:30` | `agent_comms.bus` | wire | commander | +| `src/agent_comms/bus_publication.py:32` | `agent_comms.goal_management` | wire | coordination | +| `src/agent_comms/bus_publication.py:33` | `agent_comms.registry_document` | wire | registry | +| `src/agent_comms/bus_publication.py:34` | `agent_comms.threads` | wire | commander | +| `src/agent_comms/bus_route_counts.py:10` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/bus_route_counts.py:11` | `agent_comms.messages` | wire | commander | +| `src/agent_comms/bus_route_counts.py:13` | `agent_comms.read_basis` | wire | commander | +| `src/agent_comms/bus_route_counts.py:14` | `agent_comms.typed_table` | wire | commander | +| `src/agent_comms/bus_route_counts.py:17` | `agent_comms.bus` | wire | commander | +| `src/agent_comms/bus_route_counts.py:19` | `agent_comms.page_traversal` | wire | commander | | `src/agent_comms/bus_source_page.py:8` | `agent_comms.coordination_errors` | wire | coordination | | `src/agent_comms/bus_source_page.py:9` | `agent_comms.field_codec` | wire | registry | | `src/agent_comms/bus_tables.py:9` | `agent_comms.messages` | wire | commander | @@ -501,165 +513,178 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/channel_coding_tools.py:16` | `agent_comms.coordinator` | registry | commander | | `src/agent_comms/channel_coding_tools.py:18` | `agent_comms.comms` | registry | commander | | `src/agent_comms/channel_coding_tools.py:19` | `agent_comms.coordination_database` | registry | coordination | -| `src/agent_comms/channel_coding_tools.py:20` | `agent_comms.envelope_claim_transitions` | registry | coordination | -| `src/agent_comms/channel_coding_tools.py:26` | `agent_comms.native_arguments` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:27` | `agent_comms.native_tool_call` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:28` | `agent_comms.native_tool_transport` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:29` | `agent_comms.native_tools` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:30` | `agent_comms.pi_payloads` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:31` | `agent_comms.selected_claim` | registry | turns | -| `src/agent_comms/channel_coding_tools.py:35` | `agent_comms.selected_tool_broker` | registry | turns | -| `src/agent_comms/channel_coding_tools.py:39` | `agent_comms.storage_room` | registry | commander | -| `src/agent_comms/channel_coding_tools.py:40` | `agent_comms.storage_rules` | registry | commander | -| `src/agent_comms/channel_coding_tools.py:41` | `agent_comms.tool_denial` | registry | cli | -| `src/agent_comms/channel_coding_tools.py:42` | `agent_comms.turn_goal_permission` | registry | turns | -| `src/agent_comms/channel_coding_tools.py:45` | `agent_comms.pi_payloads` | registry | runtime | -| `src/agent_comms/channel_coding_tools.py:111` | `agent_comms.native_runtime_input` | registry | runtime | -| `src/agent_comms/channel_input_batch.py:10` | `agent_comms.input_attempt` | registry | turns | -| `src/agent_comms/channel_input_batch.py:13` | `agent_comms.input_disposition` | registry | turns | -| `src/agent_comms/channel_input_batch.py:14` | `agent_comms.messages` | registry | commander | -| `src/agent_comms/channel_input_batch.py:15` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/channel_input_batch.py:48` | `agent_comms.input_disposition` | registry | turns | -| `src/agent_comms/channel_management.py:13` | `agent_comms.active_route` | registry | commander | -| `src/agent_comms/channel_management.py:16` | `agent_comms.channels` | registry | commander | -| `src/agent_comms/channel_management.py:17` | `agent_comms.cli_result` | registry | cli | -| `src/agent_comms/channel_management.py:19` | `agent_comms.display_order` | registry | commander | -| `src/agent_comms/channel_management.py:21` | `agent_comms.messages` | registry | commander | -| `src/agent_comms/channel_management.py:22` | `agent_comms.registration` | registry | commander | -| `src/agent_comms/channel_management.py:25` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/channel_targets.py:9` | `agent_comms.activity_clocks` | registry | commander | -| `src/agent_comms/channel_targets.py:11` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/channel_targets.py:13` | `agent_comms.history_result` | registry | commander | -| `src/agent_comms/channel_targets.py:15` | `agent_comms.response_policy` | registry | commander | -| `src/agent_comms/channel_targets.py:16` | `agent_comms.wake_policy` | registry | coordination | -| `src/agent_comms/channel_targets.py:19` | `agent_comms.audience_manifest` | registry | commander | -| `src/agent_comms/channel_targets.py:20` | `agent_comms.catalog_document` | registry | commander | -| `src/agent_comms/channel_targets.py:21` | `agent_comms.channels` | registry | commander | -| `src/agent_comms/channel_targets.py:22` | `agent_comms.cli_commands` | registry | cli | -| `src/agent_comms/channel_targets.py:23` | `agent_comms.cli_result` | registry | cli | -| `src/agent_comms/channel_targets.py:24` | `agent_comms.comms` | registry | commander | -| `src/agent_comms/channel_targets.py:25` | `agent_comms.goal_management` | registry | coordination | -| `src/agent_comms/channel_targets.py:26` | `agent_comms.historical_views` | registry | commander | -| `src/agent_comms/channel_targets.py:27` | `agent_comms.history_views` | registry | commander | -| `src/agent_comms/channel_targets.py:28` | `agent_comms.messages` | registry | commander | -| `src/agent_comms/channel_targets.py:29` | `agent_comms.read_basis` | registry | commander | -| `src/agent_comms/channel_targets.py:39` | `agent_comms.response_policy` | registry | commander | -| `src/agent_comms/channel_targets.py:42` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/channel_targets.py:43` | `agent_comms.wake_policy` | registry | coordination | -| `src/agent_comms/channel_targets.py:101` | `agent_comms.channels` | registry | commander | -| `src/agent_comms/channel_targets.py:484` | `agent_comms.channels` | registry | commander | -| `src/agent_comms/channel_targets.py:544` | `agent_comms.presentation` | registry | commander | -| `src/agent_comms/channel_targets.py:585` | `agent_comms.channels` | registry | commander | +| `src/agent_comms/channel_coding_tools.py:20` | `agent_comms.envelope_claim_transitions` | registry | commander | +| `src/agent_comms/channel_coding_tools.py:27` | `agent_comms.native_arguments` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:28` | `agent_comms.native_tool_call` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:29` | `agent_comms.native_tool_transport` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:30` | `agent_comms.native_tools` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:31` | `agent_comms.pi_payloads` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:32` | `agent_comms.selected_claim` | registry | turns | +| `src/agent_comms/channel_coding_tools.py:36` | `agent_comms.selected_tool_broker` | registry | turns | +| `src/agent_comms/channel_coding_tools.py:40` | `agent_comms.storage_room` | registry | commander | +| `src/agent_comms/channel_coding_tools.py:41` | `agent_comms.storage_rules` | registry | commander | +| `src/agent_comms/channel_coding_tools.py:42` | `agent_comms.tool_denial` | registry | cli | +| `src/agent_comms/channel_coding_tools.py:43` | `agent_comms.turn_goal_permission` | registry | turns | +| `src/agent_comms/channel_coding_tools.py:46` | `agent_comms.backend` | registry | commander | +| `src/agent_comms/channel_coding_tools.py:47` | `agent_comms.coordination_tables.assignments` | registry | coordination | +| `src/agent_comms/channel_coding_tools.py:48` | `agent_comms.pi_payloads` | registry | runtime | +| `src/agent_comms/channel_coding_tools.py:116` | `agent_comms.native_runtime_input` | registry | runtime | +| `src/agent_comms/channel_input_batch.py:9` | `agent_comms.input_key` | registry | turns | +| `src/agent_comms/channel_input_batch.py:12` | `agent_comms.input_attempt` | registry | turns | +| `src/agent_comms/channel_input_batch.py:15` | `agent_comms.input_disposition` | registry | turns | +| `src/agent_comms/channel_input_batch.py:16` | `agent_comms.messages` | registry | commander | +| `src/agent_comms/channel_input_batch.py:17` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/channel_input_batch.py:50` | `agent_comms.input_disposition` | registry | turns | +| `src/agent_comms/channel_management.py:15` | `agent_comms.channels` | registry | commander | +| `src/agent_comms/channel_management.py:16` | `agent_comms.cli_result` | registry | cli | +| `src/agent_comms/channel_management.py:18` | `agent_comms.display_order` | registry | commander | +| `src/agent_comms/channel_management.py:20` | `agent_comms.messages` | registry | commander | +| `src/agent_comms/channel_management.py:21` | `agent_comms.registration` | registry | commander | +| `src/agent_comms/channel_management.py:24` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/channel_targets.py:10` | `agent_comms.activity_clocks` | registry | commander | +| `src/agent_comms/channel_targets.py:12` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/channel_targets.py:14` | `agent_comms.history_result` | registry | commander | +| `src/agent_comms/channel_targets.py:16` | `agent_comms.response_policy` | registry | commander | +| `src/agent_comms/channel_targets.py:17` | `agent_comms.wake_policy` | registry | coordination | +| `src/agent_comms/channel_targets.py:20` | `agent_comms.audience_manifest` | registry | commander | +| `src/agent_comms/channel_targets.py:21` | `agent_comms.catalog_document` | registry | commander | +| `src/agent_comms/channel_targets.py:22` | `agent_comms.channels` | registry | commander | +| `src/agent_comms/channel_targets.py:23` | `agent_comms.cli_commands` | registry | cli | +| `src/agent_comms/channel_targets.py:24` | `agent_comms.cli_result` | registry | cli | +| `src/agent_comms/channel_targets.py:25` | `agent_comms.comms` | registry | commander | +| `src/agent_comms/channel_targets.py:26` | `agent_comms.goal_management` | registry | coordination | +| `src/agent_comms/channel_targets.py:27` | `agent_comms.historical_views` | registry | commander | +| `src/agent_comms/channel_targets.py:28` | `agent_comms.history_views` | registry | commander | +| `src/agent_comms/channel_targets.py:29` | `agent_comms.messages` | registry | commander | +| `src/agent_comms/channel_targets.py:30` | `agent_comms.read_basis` | registry | commander | +| `src/agent_comms/channel_targets.py:40` | `agent_comms.response_policy` | registry | commander | +| `src/agent_comms/channel_targets.py:43` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/channel_targets.py:44` | `agent_comms.wake_policy` | registry | coordination | +| `src/agent_comms/channel_targets.py:102` | `agent_comms.channels` | registry | commander | +| `src/agent_comms/channel_targets.py:491` | `agent_comms.channels` | registry | commander | +| `src/agent_comms/channel_targets.py:553` | `agent_comms.presentation` | registry | commander | +| `src/agent_comms/channel_targets.py:594` | `agent_comms.channels` | registry | commander | | `src/agent_comms/channels.py:15` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/channels.py:23` | `agent_comms.tool_result` | commander | cli | | `src/agent_comms/check_root.py:18` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/cli.py:17` | `agent_comms.active_route` | cli | commander | -| `src/agent_comms/cli.py:21` | `agent_comms.launch_root` | cli | commander | +| `src/agent_comms/cli.py:20` | `agent_comms.launch_root` | cli | commander | | `src/agent_comms/cli_bridges/claude.py:12` | `agent_comms.bus` | runtime | commander | | `src/agent_comms/cli_bridges/claude.py:16` | `agent_comms.watched` | runtime | commander | | `src/agent_comms/cli_bridges/claude_protocol.py:18` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/claude_protocol.py:38` | `agent_comms.tool_calls` | runtime | cli | -| `src/agent_comms/cli_bridges/claude_protocol.py:39` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/cli_bridges/codex.py:16` | `agent_comms.messages` | runtime | commander | -| `src/agent_comms/cli_bridges/codex.py:17` | `agent_comms.send_result` | runtime | commander | -| `src/agent_comms/cli_bridges/codex.py:18` | `agent_comms.cli_protocol` | runtime | cli | +| `src/agent_comms/cli_bridges/claude_protocol.py:39` | `agent_comms.tool_calls` | runtime | cli | +| `src/agent_comms/cli_bridges/claude_protocol.py:40` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/cli_bridges/codex.py:17` | `agent_comms.child_process` | runtime | commander | +| `src/agent_comms/cli_bridges/codex.py:18` | `agent_comms.messages` | runtime | commander | +| `src/agent_comms/cli_bridges/codex.py:19` | `agent_comms.send_result` | runtime | commander | +| `src/agent_comms/cli_bridges/codex.py:20` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/cli_bridges/codex_protocol.py:18` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/cli_bridges/codex_protocol.py:20` | `agent_comms.external_transcript` | runtime | commander | -| `src/agent_comms/cli_bridges/codex_protocol.py:40` | `agent_comms.tool_calls` | runtime | cli | -| `src/agent_comms/cli_bridges/codex_protocol.py:41` | `agent_comms.tool_declaration` | runtime | cli | -| `src/agent_comms/cli_bridges/codex_protocol.py:42` | `agent_comms.tool_results` | runtime | cli | -| `src/agent_comms/cli_bridges/codex_protocol.py:43` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/cli_bridges/codex_rollout.py:17` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/codex_rollout.py:25` | `agent_comms.tool_declaration` | runtime | cli | -| `src/agent_comms/cli_bridges/codex_rollout.py:26` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/cli_bridges/codex_protocol.py:41` | `agent_comms.tool_calls` | runtime | cli | +| `src/agent_comms/cli_bridges/codex_protocol.py:42` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/cli_bridges/codex_protocol.py:43` | `agent_comms.tool_results` | runtime | cli | +| `src/agent_comms/cli_bridges/codex_protocol.py:44` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/cli_bridges/codex_rollout.py:24` | `agent_comms.cli_protocol` | runtime | cli | +| `src/agent_comms/cli_bridges/codex_rollout.py:32` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/cli_bridges/codex_rollout.py:33` | `agent_comms.transcript_events` | runtime | commander | | `src/agent_comms/cli_bridges/history.py:25` | `agent_comms.harness_install` | runtime | commander | | `src/agent_comms/cli_bridges/monitor.py:19` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/cli_bridges/monitor.py:20` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/cli_bridges/monitor.py:23` | `agent_comms.launch_runtime` | runtime | commander | | `src/agent_comms/cli_bridges/monitor.py:24` | `agent_comms.messages` | runtime | commander | | `src/agent_comms/cli_bridges/opencode.py:15` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/cli_bridges/opencode.py:16` | `agent_comms.messages` | runtime | commander | -| `src/agent_comms/cli_bridges/opencode.py:17` | `agent_comms.send_result` | runtime | commander | -| `src/agent_comms/cli_bridges/opencode.py:18` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/opencode.py:72` | `agent_comms.comms` | runtime | commander | -| `src/agent_comms/cli_bridges/opencode.py:82` | `agent_comms.comms` | runtime | commander | -| `src/agent_comms/cli_bridges/opencode.py:83` | `agent_comms.cli_commands` | runtime | cli | +| `src/agent_comms/cli_bridges/opencode.py:16` | `agent_comms.comms` | runtime | commander | +| `src/agent_comms/cli_bridges/opencode.py:17` | `agent_comms.messages` | runtime | commander | +| `src/agent_comms/cli_bridges/opencode.py:18` | `agent_comms.send_result` | runtime | commander | +| `src/agent_comms/cli_bridges/opencode.py:19` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/cli_bridges/opencode_parts.py:10` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/opencode_parts.py:22` | `agent_comms.tool_calls` | runtime | cli | -| `src/agent_comms/cli_bridges/opencode_parts.py:23` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/cli_bridges/opencode_parts.py:23` | `agent_comms.tool_calls` | runtime | cli | +| `src/agent_comms/cli_bridges/opencode_parts.py:24` | `agent_comms.transcript_events` | runtime | commander | | `src/agent_comms/cli_bridges/opencode_protocol.py:11` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/cli_bridges/opencode_store.py:15` | `agent_comms.locked_store` | runtime | commander | | `src/agent_comms/cli_bridges/opencode_store.py:17` | `agent_comms.typed_table` | runtime | commander | | `src/agent_comms/cli_bridges/shared.py:28` | `agent_comms.messages` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:30` | `agent_comms.change_report` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:31` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:38` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/shared.py:49` | `agent_comms.comms` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:50` | `agent_comms.config_options` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:55` | `agent_comms.launch_runtime` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:57` | `agent_comms.read_basis` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:59` | `agent_comms.send_result` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:60` | `agent_comms.typed_table` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:70` | `agent_comms.locked_store` | runtime | commander | -| `src/agent_comms/cli_bridges/shared.py:820` | `agent_comms.registration` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:30` | `agent_comms.bus` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:32` | `agent_comms.change_report` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:33` | `agent_comms.child_process` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:40` | `agent_comms.cli_protocol` | runtime | cli | +| `src/agent_comms/cli_bridges/shared.py:51` | `agent_comms.comms` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:52` | `agent_comms.config_options` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:62` | `agent_comms.installer.refusals` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:63` | `agent_comms.launch_runtime` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:71` | `agent_comms.read_basis` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:73` | `agent_comms.send_result` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:77` | `agent_comms.threads` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:78` | `agent_comms.typed_table` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:89` | `agent_comms.locked_store` | runtime | commander | +| `src/agent_comms/cli_bridges/shared.py:634` | `agent_comms.registration` | runtime | commander | | `src/agent_comms/cli_commands.py:31` | `agent_comms.errors` | cli | commander | -| `src/agent_comms/cli_commands.py:32` | `agent_comms.launch_root` | cli | commander | -| `src/agent_comms/cli_commands.py:36` | `agent_comms.active_route` | cli | commander | -| `src/agent_comms/cli_commands.py:43` | `agent_comms.activity` | cli | commander | -| `src/agent_comms/cli_commands.py:44` | `agent_comms.bus` | cli | commander | -| `src/agent_comms/cli_commands.py:45` | `agent_comms.catalog_document` | cli | commander | -| `src/agent_comms/cli_commands.py:56` | `agent_comms.channels` | cli | commander | -| `src/agent_comms/cli_commands.py:57` | `agent_comms.check_root` | cli | commander | -| `src/agent_comms/cli_commands.py:58` | `agent_comms.child_process` | cli | commander | -| `src/agent_comms/cli_commands.py:73` | `agent_comms.commander.config` | cli | commander | -| `src/agent_comms/cli_commands.py:79` | `agent_comms.comms` | cli | commander | -| `src/agent_comms/cli_commands.py:80` | `agent_comms.config_options` | cli | commander | -| `src/agent_comms/cli_commands.py:85` | `agent_comms.context_store` | cli | commander | -| `src/agent_comms/cli_commands.py:89` | `agent_comms.exporting` | cli | commander | -| `src/agent_comms/cli_commands.py:118` | `agent_comms.harness_install` | cli | commander | -| `src/agent_comms/cli_commands.py:119` | `agent_comms.installer.probes.harnesses` | cli | commander | -| `src/agent_comms/cli_commands.py:120` | `agent_comms.history_result` | cli | commander | -| `src/agent_comms/cli_commands.py:121` | `agent_comms.history_views` | cli | commander | -| `src/agent_comms/cli_commands.py:122` | `agent_comms.importing` | cli | commander | -| `src/agent_comms/cli_commands.py:124` | `agent_comms.install_choices` | cli | commander | -| `src/agent_comms/cli_commands.py:125` | `agent_comms.maintenance_barrier` | cli | commander | -| `src/agent_comms/cli_commands.py:128` | `agent_comms.messages` | cli | commander | -| `src/agent_comms/cli_commands.py:135` | `agent_comms.page_traversal` | cli | commander | -| `src/agent_comms/cli_commands.py:137` | `agent_comms.presentation` | cli | commander | -| `src/agent_comms/cli_commands.py:138` | `agent_comms.read_basis` | cli | commander | -| `src/agent_comms/cli_commands.py:147` | `agent_comms.repo` | cli | commander | -| `src/agent_comms/cli_commands.py:148` | `agent_comms.restart_scope` | cli | commander | -| `src/agent_comms/cli_commands.py:150` | `agent_comms.schema_report` | cli | commander | -| `src/agent_comms/cli_commands.py:151` | `agent_comms.send_result` | cli | commander | -| `src/agent_comms/cli_commands.py:152` | `agent_comms.shared_ledger` | cli | commander | -| `src/agent_comms/cli_commands.py:175` | `agent_comms.threads` | cli | commander | -| `src/agent_comms/cli_commands.py:187` | `agent_comms.typed_table` | cli | commander | -| `src/agent_comms/cli_commands.py:1275` | `agent_comms.coordinator` | cli | commander | -| `src/agent_comms/cli_commands.py:1335` | `agent_comms.task_sources` | cli | commander | -| `src/agent_comms/cli_commands.py:1353` | `agent_comms.task_sources` | cli | commander | -| `src/agent_comms/cli_commands.py:1726` | `agent_comms.installer.launch` | cli | commander | +| `src/agent_comms/cli_commands.py:32` | `agent_comms.installer.interpreter_operation` | cli | commander | +| `src/agent_comms/cli_commands.py:33` | `agent_comms.installer.owner_starts` | cli | commander | +| `src/agent_comms/cli_commands.py:34` | `agent_comms.launch_root` | cli | commander | +| `src/agent_comms/cli_commands.py:38` | `agent_comms.active_route` | cli | commander | +| `src/agent_comms/cli_commands.py:45` | `agent_comms.activity` | cli | commander | +| `src/agent_comms/cli_commands.py:46` | `agent_comms.bus` | cli | commander | +| `src/agent_comms/cli_commands.py:47` | `agent_comms.catalog_document` | cli | commander | +| `src/agent_comms/cli_commands.py:58` | `agent_comms.channels` | cli | commander | +| `src/agent_comms/cli_commands.py:59` | `agent_comms.check_root` | cli | commander | +| `src/agent_comms/cli_commands.py:60` | `agent_comms.child_process` | cli | commander | +| `src/agent_comms/cli_commands.py:75` | `agent_comms.commander.config` | cli | commander | +| `src/agent_comms/cli_commands.py:81` | `agent_comms.comms` | cli | commander | +| `src/agent_comms/cli_commands.py:82` | `agent_comms.config_options` | cli | commander | +| `src/agent_comms/cli_commands.py:87` | `agent_comms.context_store` | cli | commander | +| `src/agent_comms/cli_commands.py:91` | `agent_comms.exporting` | cli | commander | +| `src/agent_comms/cli_commands.py:122` | `agent_comms.harness_install` | cli | commander | +| `src/agent_comms/cli_commands.py:123` | `agent_comms.installer.probes.harnesses` | cli | commander | +| `src/agent_comms/cli_commands.py:124` | `agent_comms.history_result` | cli | commander | +| `src/agent_comms/cli_commands.py:125` | `agent_comms.history_views` | cli | commander | +| `src/agent_comms/cli_commands.py:126` | `agent_comms.importing` | cli | commander | +| `src/agent_comms/cli_commands.py:129` | `agent_comms.install_choices` | cli | commander | +| `src/agent_comms/cli_commands.py:130` | `agent_comms.launch_runtime` | cli | commander | +| `src/agent_comms/cli_commands.py:131` | `agent_comms.maintenance_barrier` | cli | commander | +| `src/agent_comms/cli_commands.py:134` | `agent_comms.messages` | cli | commander | +| `src/agent_comms/cli_commands.py:141` | `agent_comms.page_traversal` | cli | commander | +| `src/agent_comms/cli_commands.py:143` | `agent_comms.presentation` | cli | commander | +| `src/agent_comms/cli_commands.py:144` | `agent_comms.read_basis` | cli | commander | +| `src/agent_comms/cli_commands.py:153` | `agent_comms.repo` | cli | commander | +| `src/agent_comms/cli_commands.py:155` | `agent_comms.storage_rules` | cli | commander | +| `src/agent_comms/cli_commands.py:159` | `agent_comms.restart_queue` | cli | commander | +| `src/agent_comms/cli_commands.py:160` | `agent_comms.restart_scope` | cli | commander | +| `src/agent_comms/cli_commands.py:162` | `agent_comms.schema_report` | cli | commander | +| `src/agent_comms/cli_commands.py:163` | `agent_comms.send_result` | cli | commander | +| `src/agent_comms/cli_commands.py:164` | `agent_comms.shared_ledger` | cli | commander | +| `src/agent_comms/cli_commands.py:187` | `agent_comms.threads` | cli | commander | +| `src/agent_comms/cli_commands.py:188` | `agent_comms.todos` | cli | commander | +| `src/agent_comms/cli_commands.py:200` | `agent_comms.typed_table` | cli | commander | +| `src/agent_comms/cli_commands.py:1367` | `agent_comms.coordinator` | cli | commander | +| `src/agent_comms/cli_commands.py:1427` | `agent_comms.task_sources` | cli | commander | +| `src/agent_comms/cli_commands.py:1445` | `agent_comms.task_sources` | cli | commander | +| `src/agent_comms/cli_commands.py:1824` | `agent_comms.installer.launch` | cli | commander | | `src/agent_comms/cli_native_package.py:25` | `agent_comms.storage_rules` | cli | commander | | `src/agent_comms/cli_native_package.py:26` | `agent_comms.unit_instructions` | cli | commander | -| `src/agent_comms/cli_protocol.py:27` | `agent_comms.external_transcript` | cli | commander | -| `src/agent_comms/cli_protocol.py:29` | `agent_comms.maintenance_barrier` | cli | commander | -| `src/agent_comms/cli_protocol.py:30` | `agent_comms.messages` | cli | commander | -| `src/agent_comms/cli_protocol.py:36` | `agent_comms.child_process` | cli | commander | -| `src/agent_comms/commander/judge.py:47` | `agent_comms.tools` | commander | cli | -| `src/agent_comms/commander/judge.py:48` | `agent_comms.tool_caller` | commander | cli | -| `src/agent_comms/commander/judge.py:49` | `agent_comms.tool_declaration` | commander | cli | -| `src/agent_comms/commander/order.py:56` | `agent_comms.tool_denial` | commander | cli | -| `src/agent_comms/commander/order.py:97` | `agent_comms.tool_caller` | commander | cli | -| `src/agent_comms/commander/order.py:98` | `agent_comms.tools` | commander | cli | -| `src/agent_comms/commander/standing.py:40` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/cli_protocol.py:30` | `agent_comms.external_transcript` | cli | commander | +| `src/agent_comms/cli_protocol.py:32` | `agent_comms.maintenance_barrier` | cli | commander | +| `src/agent_comms/cli_protocol.py:33` | `agent_comms.messages` | cli | commander | +| `src/agent_comms/cli_protocol.py:35` | `agent_comms.repo` | cli | commander | +| `src/agent_comms/cli_protocol.py:40` | `agent_comms.child_process` | cli | commander | +| `src/agent_comms/commander/judge.py:61` | `agent_comms.tool_caller` | commander | cli | +| `src/agent_comms/commander/judge.py:62` | `agent_comms.tool_declaration` | commander | cli | +| `src/agent_comms/commander/order.py:100` | `agent_comms.tool_caller` | commander | cli | +| `src/agent_comms/commander/standing.py:15` | `agent_comms.cli_commands` | commander | cli | +| `src/agent_comms/commander/standing.py:50` | `agent_comms.ui_model.unit_state` | commander | ui_model | | `src/agent_comms/commander/tool_watch.py:8` | `agent_comms.tool_declaration` | commander | cli | -| `src/agent_comms/commander/vibe_check.py:45` | `agent_comms.tool_result` | commander | cli | -| `src/agent_comms/commander/vibe_check.py:46` | `agent_comms.ui_model.unit_state` | commander | ui_model | -| `src/agent_comms/commander_heartbeat.py:16` | `agent_comms.ui_model.unit_state` | commander | ui_model | -| `src/agent_comms/commander_hud.py:16` | `agent_comms.tool_result` | commander | cli | -| `src/agent_comms/connector.py:46` | `agent_comms.cli_protocol` | commander | cli | -| `src/agent_comms/connector.py:73` | `agent_comms.tool_result` | commander | cli | -| `src/agent_comms/connector.py:75` | `agent_comms.tool_caller` | commander | cli | +| `src/agent_comms/commander/vibe_check.py:46` | `agent_comms.tool_result` | commander | cli | +| `src/agent_comms/commander/vibe_check.py:47` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/commander_heartbeat.py:17` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/commander_hud.py:20` | `agent_comms.tool_result` | commander | cli | +| `src/agent_comms/commander_hud.py:22` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/commander_pings.py:24` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/connector.py:48` | `agent_comms.cli_protocol` | commander | cli | +| `src/agent_comms/connector.py:74` | `agent_comms.tool_result` | commander | cli | | `src/agent_comms/connector.py:76` | `agent_comms.tools` | commander | cli | +| `src/agent_comms/connector.py:78` | `agent_comms.tool_request` | commander | cli | +| `src/agent_comms/connector_caller.py:16` | `agent_comms.tool_caller` | commander | cli | +| `src/agent_comms/connector_caller.py:17` | `agent_comms.tool_request` | commander | cli | | `src/agent_comms/context_segments/awareness.py:7` | `agent_comms.turn_context` | context | turns | | `src/agent_comms/context_segments/doctrine.py:7` | `agent_comms.turn_context` | context | turns | | `src/agent_comms/context_segments/optional_awareness.py:22` | `agent_comms.cohort_schema` | context | commander | @@ -694,11 +719,11 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/coordination_response.py:44` | `agent_comms.obligation_states` | coordination | commander | | `src/agent_comms/coordination_response.py:49` | `agent_comms.publisher` | coordination | commander | | `src/agent_comms/coordination_response.py:51` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/coordination_response.py:60` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/coordination_response.py:289` | `agent_comms.comms` | coordination | commander | -| `src/agent_comms/coordination_response.py:381` | `agent_comms.input_disposition` | coordination | turns | -| `src/agent_comms/coordination_response.py:382` | `agent_comms.response_conversation` | coordination | commander | -| `src/agent_comms/coordination_response.py:554` | `agent_comms.response_conversation` | coordination | commander | +| `src/agent_comms/coordination_response.py:61` | `agent_comms.locked_store` | coordination | commander | +| `src/agent_comms/coordination_response.py:290` | `agent_comms.comms` | coordination | commander | +| `src/agent_comms/coordination_response.py:382` | `agent_comms.input_disposition` | coordination | turns | +| `src/agent_comms/coordination_response.py:383` | `agent_comms.response_conversation` | coordination | commander | +| `src/agent_comms/coordination_response.py:555` | `agent_comms.response_conversation` | coordination | commander | | `src/agent_comms/coordination_schema.py:10` | `agent_comms.coordinator_vocabulary` | coordination | commander | | `src/agent_comms/coordination_schema.py:11` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/coordination_session.py:17` | `agent_comms.locked_store` | coordination | commander | @@ -707,20 +732,21 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/coordination_session.py:92` | `agent_comms.store_files` | coordination | commander | | `src/agent_comms/coordination_session.py:115` | `agent_comms.publisher` | coordination | commander | | `src/agent_comms/coordination_session.py:115` | `agent_comms.registration` | coordination | commander | -| `src/agent_comms/coordination_snapshot.py:306` | `agent_comms.execution_states` | coordination | commander | +| `src/agent_comms/coordination_snapshot.py:314` | `agent_comms.execution_states` | coordination | commander | | `src/agent_comms/coordination_tables/annotations.py:9` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/coordination_tables/annotations.py:17` | `agent_comms.working_memory_labels` | coordination | context | | `src/agent_comms/coordination_tables/annotations.py:18` | `agent_comms.working_memory_questions` | coordination | context | | `src/agent_comms/coordination_tables/annotations.py:19` | `agent_comms.working_memory_requests` | coordination | context | | `src/agent_comms/coordination_tables/assignments.py:8` | `agent_comms.assignment_states` | coordination | commander | +| `src/agent_comms/coordination_tables/assignments.py:19` | `agent_comms.envelope_claim_transitions` | coordination | commander | | `src/agent_comms/coordination_tables/assignments.py:22` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/coordination_tables/assignments.py:66` | `agent_comms.audience_manifest` | coordination | commander | | `src/agent_comms/coordination_tables/assignments.py:71` | `agent_comms.audience_manifest` | coordination | commander | | `src/agent_comms/coordination_tables/attempts.py:23` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/coordination_tables/executions.py:24` | `agent_comms.execution_states` | coordination | commander | -| `src/agent_comms/coordination_tables/executions.py:35` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/coordination_tables/executions.py:61` | `agent_comms.selected_source_batch` | coordination | turns | -| `src/agent_comms/coordination_tables/participants.py:11` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/coordination_tables/executions.py:36` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/coordination_tables/executions.py:62` | `agent_comms.selected_source_batch` | coordination | turns | +| `src/agent_comms/coordination_tables/participants.py:12` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/coordination_tables/publications.py:17` | `agent_comms.errors` | coordination | commander | | `src/agent_comms/coordination_tables/publications.py:20` | `agent_comms.messages` | coordination | commander | | `src/agent_comms/coordination_tables/publications.py:21` | `agent_comms.response_acknowledgement` | coordination | commander | @@ -728,46 +754,46 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/coordination_tables/publications.py:33` | `agent_comms.bus` | coordination | commander | | `src/agent_comms/coordination_tables/recovery.py:17` | `agent_comms.recovery_states` | coordination | commander | | `src/agent_comms/coordination_tables/recovery.py:18` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:11` | `agent_comms.active_route` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:15` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:16` | `agent_comms.maintenance_barrier` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:17` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:19` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/coordination_tables/refusals.py:22` | `agent_comms.coordinator` | coordination | commander | +| `src/agent_comms/coordination_tables/refusals.py:14` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/coordination_tables/refusals.py:15` | `agent_comms.maintenance_barrier` | coordination | commander | +| `src/agent_comms/coordination_tables/refusals.py:16` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/coordination_tables/refusals.py:18` | `agent_comms.locked_store` | coordination | commander | +| `src/agent_comms/coordination_tables/refusals.py:21` | `agent_comms.coordinator` | coordination | commander | | `src/agent_comms/coordination_tables/responses.py:17` | `agent_comms.obligation_states` | coordination | commander | | `src/agent_comms/coordination_tables/responses.py:19` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/delivery_failure.py:3` | `agent_comms.acp_extension` | wire | runtime | | `src/agent_comms/delivery_failure.py:4` | `agent_comms.errors` | wire | commander | -| `src/agent_comms/delivery_policy.py:9` | `agent_comms.audience_manifest` | wire | commander | -| `src/agent_comms/delivery_policy.py:10` | `agent_comms.declared_family` | wire | registry | -| `src/agent_comms/delivery_policy.py:11` | `agent_comms.field_codec` | wire | registry | -| `src/agent_comms/delivery_policy.py:12` | `agent_comms.response_acknowledgement` | wire | commander | -| `src/agent_comms/delivery_policy.py:15` | `agent_comms.wake` | wire | commander | -| `src/agent_comms/delivery_policy.py:16` | `agent_comms.wake_policy` | wire | coordination | +| `src/agent_comms/delivery_policy.py:5` | `agent_comms.audience_manifest` | wire | commander | +| `src/agent_comms/delivery_policy.py:6` | `agent_comms.declared_family` | wire | registry | +| `src/agent_comms/delivery_policy.py:7` | `agent_comms.wake` | wire | commander | +| `src/agent_comms/delivery_policy.py:8` | `agent_comms.wake_policy` | wire | coordination | | `src/agent_comms/exporting.py:17` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/external_transcript.py:27` | `agent_comms.tool_declaration` | commander | cli | -| `src/agent_comms/external_transcript.py:247` | `agent_comms.tool_declaration` | commander | cli | -| `src/agent_comms/goal_actions.py:13` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_actions.py:25` | `agent_comms.input_disposition` | coordination | turns | -| `src/agent_comms/goal_actions.py:26` | `agent_comms.todos` | coordination | commander | -| `src/agent_comms/goal_actions.py:28` | `agent_comms.change_report` | coordination | commander | -| `src/agent_comms/goal_actions.py:29` | `agent_comms.child_process` | coordination | commander | -| `src/agent_comms/goal_actions.py:32` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_actions.py:47` | `agent_comms.progress_claims` | coordination | commander | -| `src/agent_comms/goal_actions.py:51` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_actions.py:145` | `agent_comms.runtime_requests` | coordination | runtime | -| `src/agent_comms/goal_actions.py:487` | `agent_comms.runtime_requests` | coordination | runtime | -| `src/agent_comms/goal_actions.py:673` | `agent_comms.runtime_requests` | coordination | runtime | +| `src/agent_comms/external_transcript.py:248` | `agent_comms.tool_declaration` | commander | cli | +| `src/agent_comms/goal_actions.py:14` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_actions.py:25` | `agent_comms.input_key` | coordination | turns | +| `src/agent_comms/goal_actions.py:26` | `agent_comms.input_disposition` | coordination | turns | +| `src/agent_comms/goal_actions.py:27` | `agent_comms.todos` | coordination | commander | +| `src/agent_comms/goal_actions.py:31` | `agent_comms.change_report` | coordination | commander | +| `src/agent_comms/goal_actions.py:32` | `agent_comms.child_process` | coordination | commander | +| `src/agent_comms/goal_actions.py:35` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/goal_actions.py:50` | `agent_comms.progress_claims` | coordination | commander | +| `src/agent_comms/goal_actions.py:54` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_actions.py:149` | `agent_comms.runtime_requests` | coordination | runtime | +| `src/agent_comms/goal_actions.py:505` | `agent_comms.runtime_requests` | coordination | runtime | +| `src/agent_comms/goal_actions.py:570` | `agent_comms.standing_rules` | coordination | commander | +| `src/agent_comms/goal_actions.py:702` | `agent_comms.runtime_requests` | coordination | runtime | | `src/agent_comms/goal_attempt_phase.py:10` | `agent_comms.errors` | coordination | commander | | `src/agent_comms/goal_attempts.py:14` | `agent_comms.errors` | coordination | commander | | `src/agent_comms/goal_attempts.py:33` | `agent_comms.child_process` | coordination | commander | | `src/agent_comms/goal_attempts.py:63` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/goal_attempts.py:64` | `agent_comms.pi_counts` | coordination | runtime | -| `src/agent_comms/goal_attempts.py:65` | `agent_comms.pi_payloads` | coordination | runtime | -| `src/agent_comms/goal_attempts.py:66` | `agent_comms.store_files` | coordination | commander | -| `src/agent_comms/goal_attempts.py:67` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/goal_attempts.py:71` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_attempts.py:72` | `agent_comms.turn_context` | coordination | turns | +| `src/agent_comms/goal_attempts.py:64` | `agent_comms.maintenance_barrier` | coordination | commander | +| `src/agent_comms/goal_attempts.py:65` | `agent_comms.pi_counts` | coordination | runtime | +| `src/agent_comms/goal_attempts.py:66` | `agent_comms.pi_payloads` | coordination | runtime | +| `src/agent_comms/goal_attempts.py:67` | `agent_comms.store_files` | coordination | commander | +| `src/agent_comms/goal_attempts.py:68` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/goal_attempts.py:79` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_attempts.py:80` | `agent_comms.turn_context` | coordination | turns | | `src/agent_comms/goal_failure_observation.py:15` | `agent_comms.turn_failure` | coordination | turns | | `src/agent_comms/goal_failure_observation.py:25` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/goal_failure_observation.py:30` | `agent_comms.goals` | coordination | commander | @@ -776,150 +802,153 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/goal_generation.py:11` | `agent_comms.errors` | coordination | commander | | `src/agent_comms/goal_generation.py:31` | `agent_comms.goals` | coordination | commander | | `src/agent_comms/goal_generation.py:32` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_history.py:25` | `agent_comms.child_process` | coordination | commander | -| `src/agent_comms/goal_history.py:27` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_history.py:28` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/goal_history.py:30` | `agent_comms.store_files` | coordination | commander | +| `src/agent_comms/goal_history.py:23` | `agent_comms.child_process` | coordination | commander | +| `src/agent_comms/goal_history.py:26` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_history.py:27` | `agent_comms.locked_store` | coordination | commander | +| `src/agent_comms/goal_history.py:29` | `agent_comms.store_files` | coordination | commander | | `src/agent_comms/goal_history.py:31` | `agent_comms.typed_table` | coordination | commander | | `src/agent_comms/goal_management.py:5` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_management.py:14` | `agent_comms.agent_activity` | coordination | runtime | -| `src/agent_comms/goal_management.py:16` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_management.py:25` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_management.py:35` | `agent_comms.native_input_owner` | coordination | runtime | -| `src/agent_comms/goal_management.py:37` | `agent_comms.registration` | coordination | commander | -| `src/agent_comms/goal_management.py:38` | `agent_comms.store_files` | coordination | commander | -| `src/agent_comms/goal_management.py:41` | `agent_comms.agent_events` | coordination | runtime | -| `src/agent_comms/goal_management.py:43` | `agent_comms.messages` | coordination | commander | -| `src/agent_comms/goal_management.py:44` | `agent_comms.native_input_owner` | coordination | runtime | -| `src/agent_comms/goal_management.py:55` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_management.py:56` | `agent_comms.input_attempt` | coordination | turns | -| `src/agent_comms/goal_management.py:62` | `agent_comms.input_disposition` | coordination | turns | -| `src/agent_comms/goal_management.py:64` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_management.py:65` | `agent_comms.todos` | coordination | commander | -| `src/agent_comms/goal_management.py:66` | `agent_comms.turn_lease` | coordination | turns | -| `src/agent_comms/goal_management.py:363` | `agent_comms.agent_events` | coordination | runtime | -| `src/agent_comms/goal_mentions.py:12` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_mentions.py:24` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_management.py:15` | `agent_comms.agent_activity` | coordination | runtime | +| `src/agent_comms/goal_management.py:17` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/goal_management.py:27` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/goal_management.py:37` | `agent_comms.native_input_owner` | coordination | runtime | +| `src/agent_comms/goal_management.py:39` | `agent_comms.registration` | coordination | commander | +| `src/agent_comms/goal_management.py:40` | `agent_comms.store_files` | coordination | commander | +| `src/agent_comms/goal_management.py:43` | `agent_comms.agent_events` | coordination | runtime | +| `src/agent_comms/goal_management.py:45` | `agent_comms.messages` | coordination | commander | +| `src/agent_comms/goal_management.py:46` | `agent_comms.native_input_owner` | coordination | runtime | +| `src/agent_comms/goal_management.py:57` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_management.py:58` | `agent_comms.input_attempt` | coordination | turns | +| `src/agent_comms/goal_management.py:64` | `agent_comms.input_disposition` | coordination | turns | +| `src/agent_comms/goal_management.py:66` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_management.py:67` | `agent_comms.todos` | coordination | commander | +| `src/agent_comms/goal_management.py:68` | `agent_comms.turn_lease` | coordination | turns | +| `src/agent_comms/goal_management.py:382` | `agent_comms.agent_events` | coordination | runtime | +| `src/agent_comms/goal_mentions.py:13` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_mentions.py:25` | `agent_comms.threads` | coordination | commander | | `src/agent_comms/goal_presentation.py:14` | `agent_comms.goals` | coordination | commander | | `src/agent_comms/goal_presentation.py:20` | `agent_comms.agent_activity` | coordination | runtime | | `src/agent_comms/goal_presentation.py:27` | `agent_comms.threads` | coordination | commander | | `src/agent_comms/goal_presentation.py:28` | `agent_comms.turn_lease` | coordination | turns | | `src/agent_comms/goal_scheduler.py:9` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:16` | `agent_comms.agent_event_updates` | coordination | runtime | -| `src/agent_comms/goal_scheduler.py:17` | `agent_comms.child_process` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:18` | `agent_comms.coordinator` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:19` | `agent_comms.errors` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:30` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:32` | `agent_comms.routing` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:33` | `agent_comms.schedule_rules` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:37` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:38` | `agent_comms.comms` | coordination | commander | -| `src/agent_comms/goal_scheduler.py:39` | `agent_comms.input_drain` | coordination | turns | -| `src/agent_comms/goal_scheduler.py:40` | `agent_comms.session_lifecycle` | coordination | turns | -| `src/agent_comms/goal_scheduler.py:41` | `agent_comms.turn_effects` | coordination | turns | +| `src/agent_comms/goal_scheduler.py:17` | `agent_comms.agent_event_updates` | coordination | runtime | +| `src/agent_comms/goal_scheduler.py:18` | `agent_comms.child_process` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:19` | `agent_comms.coordinator` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:20` | `agent_comms.errors` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:31` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:33` | `agent_comms.routing` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:34` | `agent_comms.schedule_rules` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:38` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:39` | `agent_comms.comms` | coordination | commander | +| `src/agent_comms/goal_scheduler.py:40` | `agent_comms.input_drain` | coordination | turns | +| `src/agent_comms/goal_scheduler.py:41` | `agent_comms.session_lifecycle` | coordination | turns | +| `src/agent_comms/goal_scheduler.py:42` | `agent_comms.turn_effects` | coordination | turns | | `src/agent_comms/goal_states.py:16` | `agent_comms.goals` | coordination | commander | | `src/agent_comms/goal_states.py:33` | `agent_comms.turn_context` | coordination | turns | | `src/agent_comms/goal_turn_permit.py:9` | `agent_comms.ordinary_turn_rules` | coordination | commander | -| `src/agent_comms/goal_turn_permit.py:14` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_turn_permit.py:15` | `agent_comms.pi_payloads` | coordination | runtime | -| `src/agent_comms/goal_turn_permit.py:17` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goal_turn_permit.py:18` | `agent_comms.turn_context` | coordination | turns | -| `src/agent_comms/goal_turn_permit.py:19` | `agent_comms.turn_goal_account` | coordination | turns | -| `src/agent_comms/goal_turn_permit.py:20` | `agent_comms.turn_terminal` | coordination | turns | +| `src/agent_comms/goal_turn_permit.py:16` | `agent_comms.goals` | coordination | commander | +| `src/agent_comms/goal_turn_permit.py:17` | `agent_comms.pi_payloads` | coordination | runtime | +| `src/agent_comms/goal_turn_permit.py:18` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goal_turn_permit.py:19` | `agent_comms.turn_context` | coordination | turns | +| `src/agent_comms/goal_turn_permit.py:20` | `agent_comms.turn_goal_account` | coordination | turns | +| `src/agent_comms/goal_turn_permit.py:21` | `agent_comms.turn_terminal` | coordination | turns | | `src/agent_comms/goal_waits.py:12` | `agent_comms.bus` | coordination | commander | | `src/agent_comms/goal_waits.py:15` | `agent_comms.errors` | coordination | commander | | `src/agent_comms/goal_waits.py:18` | `agent_comms.goals` | coordination | commander | -| `src/agent_comms/goal_waits.py:19` | `agent_comms.input_attempt` | coordination | turns | -| `src/agent_comms/goal_waits.py:20` | `agent_comms.locked_store` | coordination | commander | -| `src/agent_comms/goal_waits.py:21` | `agent_comms.store_files` | coordination | commander | -| `src/agent_comms/goal_waits.py:24` | `agent_comms.turn_lease` | coordination | turns | -| `src/agent_comms/goal_waits.py:25` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/goal_waits.py:28` | `agent_comms.agent_activity` | coordination | runtime | -| `src/agent_comms/goal_waits.py:31` | `agent_comms.threads` | coordination | commander | -| `src/agent_comms/goals.py:34` | `agent_comms.ui_model.goal` | commander | ui_model | +| `src/agent_comms/goal_waits.py:19` | `agent_comms.input_key` | coordination | turns | +| `src/agent_comms/goal_waits.py:20` | `agent_comms.input_attempt` | coordination | turns | +| `src/agent_comms/goal_waits.py:21` | `agent_comms.locked_store` | coordination | commander | +| `src/agent_comms/goal_waits.py:22` | `agent_comms.store_files` | coordination | commander | +| `src/agent_comms/goal_waits.py:25` | `agent_comms.turn_lease` | coordination | turns | +| `src/agent_comms/goal_waits.py:26` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/goal_waits.py:29` | `agent_comms.agent_activity` | coordination | runtime | +| `src/agent_comms/goal_waits.py:32` | `agent_comms.threads` | coordination | commander | +| `src/agent_comms/goals.py:41` | `agent_comms.ui_model.goal` | commander | ui_model | | `src/agent_comms/history_result.py:7` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/history_result.py:9` | `agent_comms.tool_result` | commander | cli | | `src/agent_comms/history_views.py:15` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/host_services/connector.py:24` | `agent_comms.tools` | commander | cli | +| `src/agent_comms/host_services/connector.py:28` | `agent_comms.tools` | commander | cli | | `src/agent_comms/importing.py:16` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/input_attempt.py:12` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/input_attempt.py:10` | `agent_comms.errors` | turns | commander | | `src/agent_comms/input_disposition.py:15` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/input_disposition.py:30` | `agent_comms.locked_store` | turns | commander | -| `src/agent_comms/input_disposition.py:32` | `agent_comms.messages` | turns | commander | -| `src/agent_comms/input_disposition.py:33` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/input_disposition.py:34` | `agent_comms.tool_result` | turns | cli | -| `src/agent_comms/input_disposition.py:35` | `agent_comms.typed_table` | turns | commander | -| `src/agent_comms/input_disposition.py:38` | `agent_comms.bus` | turns | commander | -| `src/agent_comms/input_drain.py:14` | `agent_comms.acp_extension` | turns | runtime | -| `src/agent_comms/input_drain.py:23` | `agent_comms.activity` | turns | commander | -| `src/agent_comms/input_drain.py:24` | `agent_comms.agent_backend` | turns | runtime | -| `src/agent_comms/input_drain.py:25` | `agent_comms.bus` | turns | commander | -| `src/agent_comms/input_drain.py:26` | `agent_comms.child_process` | turns | commander | -| `src/agent_comms/input_drain.py:27` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/input_drain.py:30` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/input_disposition.py:32` | `agent_comms.locked_store` | turns | commander | +| `src/agent_comms/input_disposition.py:34` | `agent_comms.messages` | turns | commander | +| `src/agent_comms/input_disposition.py:36` | `agent_comms.tool_result` | turns | cli | +| `src/agent_comms/input_disposition.py:37` | `agent_comms.typed_table` | turns | commander | +| `src/agent_comms/input_disposition.py:42` | `agent_comms.bus` | turns | commander | +| `src/agent_comms/input_disposition.py:46` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/input_drain.py:16` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/input_drain.py:25` | `agent_comms.activity` | turns | commander | +| `src/agent_comms/input_drain.py:26` | `agent_comms.agent_backend` | turns | runtime | +| `src/agent_comms/input_drain.py:27` | `agent_comms.bus` | turns | commander | +| `src/agent_comms/input_drain.py:28` | `agent_comms.child_process` | turns | commander | +| `src/agent_comms/input_drain.py:29` | `agent_comms.cohort_schema` | turns | commander | +| `src/agent_comms/input_drain.py:30` | `agent_comms.comms` | turns | commander | | `src/agent_comms/input_drain.py:31` | `agent_comms.controller` | turns | runtime | -| `src/agent_comms/input_drain.py:32` | `agent_comms.cursor_owner` | turns | commander | -| `src/agent_comms/input_drain.py:33` | `agent_comms.drain_failures` | turns | commander | -| `src/agent_comms/input_drain.py:39` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/input_drain.py:50` | `agent_comms.maintenance_barrier` | turns | commander | -| `src/agent_comms/input_drain.py:51` | `agent_comms.native_input_owner` | turns | runtime | -| `src/agent_comms/input_drain.py:52` | `agent_comms.proven_source_coverage` | turns | commander | -| `src/agent_comms/input_drain.py:53` | `agent_comms.queued_input` | turns | commander | -| `src/agent_comms/input_drain.py:56` | `agent_comms.routing` | turns | commander | -| `src/agent_comms/input_drain.py:57` | `agent_comms.runtime` | turns | runtime | -| `src/agent_comms/input_drain.py:58` | `agent_comms.schedule_rules` | turns | commander | -| `src/agent_comms/input_drain.py:61` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/input_drain.py:64` | `agent_comms.watched` | turns | commander | -| `src/agent_comms/input_drain.py:67` | `agent_comms.following_inputs` | turns | commander | -| `src/agent_comms/input_effects.py:9` | `agent_comms.cursor_publication` | turns | commander | -| `src/agent_comms/input_origin.py:11` | `agent_comms.controller` | turns | runtime | -| `src/agent_comms/input_origin.py:13` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/input_origin.py:15` | `agent_comms.goals` | turns | commander | +| `src/agent_comms/input_drain.py:34` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/input_drain.py:35` | `agent_comms.cursor_owner` | turns | commander | +| `src/agent_comms/input_drain.py:36` | `agent_comms.drain_failures` | turns | commander | +| `src/agent_comms/input_drain.py:42` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/input_drain.py:53` | `agent_comms.maintenance_barrier` | turns | commander | +| `src/agent_comms/input_drain.py:54` | `agent_comms.native_input_owner` | turns | runtime | +| `src/agent_comms/input_drain.py:55` | `agent_comms.proven_source_coverage` | turns | commander | +| `src/agent_comms/input_drain.py:56` | `agent_comms.queued_input` | turns | commander | +| `src/agent_comms/input_drain.py:59` | `agent_comms.routing` | turns | commander | +| `src/agent_comms/input_drain.py:60` | `agent_comms.runtime` | turns | runtime | +| `src/agent_comms/input_drain.py:61` | `agent_comms.schedule_rules` | turns | commander | +| `src/agent_comms/input_drain.py:64` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/input_drain.py:67` | `agent_comms.watched` | turns | commander | +| `src/agent_comms/input_drain.py:70` | `agent_comms.following_inputs` | turns | commander | +| `src/agent_comms/input_effects.py:11` | `agent_comms.cursor_publication` | turns | commander | +| `src/agent_comms/input_key.py:16` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/input_origin.py:12` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/input_origin.py:14` | `agent_comms.goals` | turns | commander | | `src/agent_comms/input_origin.py:21` | `agent_comms.comms` | turns | commander | | `src/agent_comms/input_origin.py:24` | `agent_comms.threads` | turns | commander | | `src/agent_comms/input_origin.py:55` | `agent_comms.retained_task_facts` | turns | commander | -| `src/agent_comms/input_origin.py:129` | `agent_comms.active_route` | turns | commander | -| `src/agent_comms/input_origin.py:151` | `agent_comms.store_files` | turns | commander | -| `src/agent_comms/input_origin.py:165` | `agent_comms.retained_task_facts` | turns | commander | -| `src/agent_comms/installer/launch.py:25` | `agent_comms.cli_commands` | commander | cli | -| `src/agent_comms/installer/probes/commands.py:23` | `agent_comms.cli` | commander | cli | +| `src/agent_comms/input_origin.py:148` | `agent_comms.store_files` | turns | commander | +| `src/agent_comms/input_origin.py:162` | `agent_comms.retained_task_facts` | turns | commander | +| `src/agent_comms/installer/launch.py:27` | `agent_comms.cli_commands` | commander | cli | | `src/agent_comms/installer/probes/harnesses.py:10` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/installer/upgrade.py:45` | `agent_comms.cli_commands` | commander | cli | -| `src/agent_comms/installer/upgrade.py:56` | `agent_comms.cli_protocol` | commander | cli | -| `src/agent_comms/installer/upgrade.py:57` | `agent_comms.cli_result` | commander | cli | +| `src/agent_comms/installer/upgrade.py:48` | `agent_comms.cli_commands` | commander | cli | +| `src/agent_comms/installer/upgrade.py:59` | `agent_comms.cli_protocol` | commander | cli | +| `src/agent_comms/installer/upgrade.py:60` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/message_bus.py:5` | `agent_comms.activity_clocks` | wire | commander | -| `src/agent_comms/message_bus.py:23` | `agent_comms.bus` | wire | commander | -| `src/agent_comms/message_bus.py:24` | `agent_comms.channel_targets` | wire | registry | -| `src/agent_comms/message_bus.py:25` | `agent_comms.channels` | wire | commander | +| `src/agent_comms/message_bus.py:22` | `agent_comms.bus` | wire | commander | +| `src/agent_comms/message_bus.py:23` | `agent_comms.channel_targets` | wire | registry | +| `src/agent_comms/message_bus.py:24` | `agent_comms.channels` | wire | commander | +| `src/agent_comms/message_bus.py:25` | `agent_comms.coordination_database` | wire | coordination | | `src/agent_comms/message_bus.py:26` | `agent_comms.coordinator` | wire | commander | -| `src/agent_comms/message_bus.py:27` | `agent_comms.errors` | wire | commander | -| `src/agent_comms/message_bus.py:28` | `agent_comms.historical_views` | wire | commander | -| `src/agent_comms/message_bus.py:29` | `agent_comms.maintenance_barrier` | wire | commander | -| `src/agent_comms/message_bus.py:38` | `agent_comms.messages` | wire | commander | -| `src/agent_comms/message_bus.py:39` | `agent_comms.page_traversal` | wire | commander | -| `src/agent_comms/message_bus.py:40` | `agent_comms.publisher` | wire | commander | -| `src/agent_comms/message_bus.py:41` | `agent_comms.read_basis` | wire | commander | -| `src/agent_comms/message_bus.py:50` | `agent_comms.routing` | wire | commander | -| `src/agent_comms/message_bus.py:51` | `agent_comms.store_files` | wire | commander | -| `src/agent_comms/message_bus.py:54` | `agent_comms.comms` | wire | commander | -| `src/agent_comms/message_bus.py:55` | `agent_comms.registration` | wire | commander | -| `src/agent_comms/message_bus.py:56` | `agent_comms.registry_document` | wire | registry | -| `src/agent_comms/message_bus.py:57` | `agent_comms.relationships` | wire | commander | -| `src/agent_comms/message_bus.py:58` | `agent_comms.threads` | wire | commander | -| `src/agent_comms/message_bus.py:88` | `agent_comms.catalog_store` | wire | commander | -| `src/agent_comms/message_bus.py:89` | `agent_comms.read_ledger` | wire | commander | -| `src/agent_comms/message_bus.py:158` | `agent_comms.watched` | wire | commander | -| `src/agent_comms/message_bus.py:192` | `agent_comms.watched` | wire | commander | -| `src/agent_comms/message_bus.py:272` | `agent_comms.context_segments.awareness` | wire | context | -| `src/agent_comms/message_bus.py:273` | `agent_comms.peer_relevance` | wire | registry | +| `src/agent_comms/message_bus.py:27` | `agent_comms.historical_views` | wire | commander | +| `src/agent_comms/message_bus.py:28` | `agent_comms.maintenance_barrier` | wire | commander | +| `src/agent_comms/message_bus.py:36` | `agent_comms.messages` | wire | commander | +| `src/agent_comms/message_bus.py:37` | `agent_comms.page_traversal` | wire | commander | +| `src/agent_comms/message_bus.py:38` | `agent_comms.publisher` | wire | commander | +| `src/agent_comms/message_bus.py:39` | `agent_comms.read_basis` | wire | commander | +| `src/agent_comms/message_bus.py:47` | `agent_comms.routing` | wire | commander | +| `src/agent_comms/message_bus.py:48` | `agent_comms.store_files` | wire | commander | +| `src/agent_comms/message_bus.py:51` | `agent_comms.assignment_states` | wire | commander | +| `src/agent_comms/message_bus.py:52` | `agent_comms.comms` | wire | commander | +| `src/agent_comms/message_bus.py:53` | `agent_comms.registration` | wire | commander | +| `src/agent_comms/message_bus.py:54` | `agent_comms.registry_document` | wire | registry | +| `src/agent_comms/message_bus.py:55` | `agent_comms.relationships` | wire | commander | +| `src/agent_comms/message_bus.py:56` | `agent_comms.threads` | wire | commander | +| `src/agent_comms/message_bus.py:86` | `agent_comms.catalog_store` | wire | commander | +| `src/agent_comms/message_bus.py:87` | `agent_comms.read_ledger` | wire | commander | +| `src/agent_comms/message_bus.py:166` | `agent_comms.watched` | wire | commander | +| `src/agent_comms/message_bus.py:259` | `agent_comms.context_segments.awareness` | wire | context | +| `src/agent_comms/message_bus.py:260` | `agent_comms.peer_relevance` | wire | registry | | `src/agent_comms/message_page.py:10` | `agent_comms.messages` | wire | commander | | `src/agent_comms/message_page.py:11` | `agent_comms.page_traversal` | wire | commander | | `src/agent_comms/message_page.py:12` | `agent_comms.read_basis` | wire | commander | | `src/agent_comms/message_page.py:15` | `agent_comms.bus` | wire | commander | -| `src/agent_comms/message_reference.py:8` | `agent_comms.field_codec` | wire | registry | -| `src/agent_comms/message_reference.py:9` | `agent_comms.page_traversal` | wire | commander | -| `src/agent_comms/messages.py:58` | `agent_comms.ui_model.message_category` | commander | ui_model | -| `src/agent_comms/native_arguments.py:17` | `agent_comms.launch_runtime` | runtime | commander | +| `src/agent_comms/message_reference.py:11` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/message_reference.py:12` | `agent_comms.page_traversal` | wire | commander | +| `src/agent_comms/message_reference.py:15` | `agent_comms.read_basis` | wire | commander | +| `src/agent_comms/message_reference.py:16` | `agent_comms.read_ledger` | wire | commander | +| `src/agent_comms/message_reference.py:17` | `agent_comms.registry_document` | wire | registry | +| `src/agent_comms/messages.py:60` | `agent_comms.ui_model.message_category` | commander | ui_model | +| `src/agent_comms/native_arguments.py:18` | `agent_comms.launch_runtime` | runtime | commander | | `src/agent_comms/native_attestation.py:22` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/native_child.py:13` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/native_child.py:15` | `agent_comms.launch_runtime` | runtime | commander | @@ -927,17 +956,17 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/native_child.py:34` | `agent_comms.threads` | runtime | commander | | `src/agent_comms/native_claim_epoch.py:17` | `agent_comms.errors` | runtime | commander | | `src/agent_comms/native_entries.py:17` | `agent_comms.locked_store` | runtime | commander | -| `src/agent_comms/native_entries.py:33` | `agent_comms.importing` | runtime | commander | -| `src/agent_comms/native_entries.py:38` | `agent_comms.routing` | runtime | commander | -| `src/agent_comms/native_entries.py:39` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/native_entries.py:40` | `agent_comms.transcript_routes` | runtime | commander | +| `src/agent_comms/native_entries.py:34` | `agent_comms.importing` | runtime | commander | +| `src/agent_comms/native_entries.py:39` | `agent_comms.routing` | runtime | commander | +| `src/agent_comms/native_entries.py:40` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/native_entries.py:41` | `agent_comms.transcript_routes` | runtime | commander | | `src/agent_comms/native_failures.py:10` | `agent_comms.send_result` | runtime | commander | | `src/agent_comms/native_fork.py:14` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/native_fork.py:15` | `agent_comms.launch_runtime` | runtime | commander | -| `src/agent_comms/native_input_owner.py:13` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/native_input_owner.py:16` | `agent_comms.coordinator` | runtime | commander | -| `src/agent_comms/native_input_owner.py:17` | `agent_comms.errors` | runtime | commander | -| `src/agent_comms/native_input_owner.py:25` | `agent_comms.threads` | runtime | commander | +| `src/agent_comms/native_input_owner.py:14` | `agent_comms.child_process` | runtime | commander | +| `src/agent_comms/native_input_owner.py:17` | `agent_comms.coordinator` | runtime | commander | +| `src/agent_comms/native_input_owner.py:18` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/native_input_owner.py:26` | `agent_comms.threads` | runtime | commander | | `src/agent_comms/native_input_owner.py:30` | `agent_comms.goals` | runtime | commander | | `src/agent_comms/native_input_owner.py:31` | `agent_comms.registration` | runtime | commander | | `src/agent_comms/native_input_record.py:27` | `agent_comms.typed_table` | runtime | commander | @@ -945,16 +974,16 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/native_input_record.py:36` | `agent_comms.cursor_owner` | runtime | commander | | `src/agent_comms/native_input_record.py:37` | `agent_comms.historical_native_inputs` | runtime | commander | | `src/agent_comms/native_input_record.py:41` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/native_input_record.py:181` | `agent_comms.transcript_routes` | runtime | commander | -| `src/agent_comms/native_input_record.py:254` | `agent_comms.triage_native_sources` | runtime | commander | -| `src/agent_comms/native_input_record.py:260` | `agent_comms.triage_native_sources` | runtime | commander | -| `src/agent_comms/native_input_record.py:355` | `agent_comms.historical_native_inputs` | runtime | commander | +| `src/agent_comms/native_input_record.py:182` | `agent_comms.transcript_routes` | runtime | commander | +| `src/agent_comms/native_input_record.py:257` | `agent_comms.triage_native_sources` | runtime | commander | +| `src/agent_comms/native_input_record.py:265` | `agent_comms.triage_native_sources` | runtime | commander | +| `src/agent_comms/native_input_record.py:362` | `agent_comms.historical_native_inputs` | runtime | commander | | `src/agent_comms/native_package.py:26` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/native_package.py:32` | `agent_comms.store_files` | runtime | commander | -| `src/agent_comms/native_pi.py:24` | `agent_comms.locked_store` | runtime | commander | -| `src/agent_comms/native_pi.py:25` | `agent_comms.errors` | runtime | commander | -| `src/agent_comms/native_pi.py:34` | `agent_comms.launch_root` | runtime | commander | -| `src/agent_comms/native_pi.py:35` | `agent_comms.launch_runtime` | runtime | commander | +| `src/agent_comms/native_pi.py:24` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/native_pi.py:33` | `agent_comms.launch_root` | runtime | commander | +| `src/agent_comms/native_pi.py:34` | `agent_comms.launch_runtime` | runtime | commander | +| `src/agent_comms/native_pi.py:35` | `agent_comms.locked_store` | runtime | commander | | `src/agent_comms/native_pi.py:49` | `agent_comms.typed_table` | runtime | commander | | `src/agent_comms/native_pi.py:144` | `agent_comms.active_route` | runtime | commander | | `src/agent_comms/native_pi.py:463` | `agent_comms.active_route` | runtime | commander | @@ -966,74 +995,84 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/native_prompt_send.py:21` | `agent_comms.diagnostics` | runtime | commander | | `src/agent_comms/native_prompt_send.py:23` | `agent_comms.errors` | runtime | commander | | `src/agent_comms/native_prompt_send.py:26` | `agent_comms.tracked_turn` | runtime | commander | -| `src/agent_comms/native_runtime_input.py:22` | `agent_comms.tool_denial` | runtime | cli | -| `src/agent_comms/native_runtime_input.py:43` | `agent_comms.typed_table` | runtime | commander | -| `src/agent_comms/native_runtime_input.py:221` | `agent_comms.transcripts` | runtime | commander | +| `src/agent_comms/native_runtime_input.py:25` | `agent_comms.tool_denial` | runtime | cli | +| `src/agent_comms/native_runtime_input.py:46` | `agent_comms.typed_table` | runtime | commander | +| `src/agent_comms/native_runtime_input.py:224` | `agent_comms.transcripts` | runtime | commander | | `src/agent_comms/native_session_files.py:16` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/native_session_files.py:18` | `agent_comms.locked_store` | runtime | commander | -| `src/agent_comms/native_session_files.py:23` | `agent_comms.errors` | runtime | commander | -| `src/agent_comms/native_session_files.py:25` | `agent_comms.typed_table` | runtime | commander | +| `src/agent_comms/native_session_files.py:17` | `agent_comms.locked_store` | runtime | commander | +| `src/agent_comms/native_session_files.py:22` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/native_session_files.py:24` | `agent_comms.typed_table` | runtime | commander | | `src/agent_comms/native_session_prepare.py:14` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/native_session_prepare.py:18` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/native_session_prepare.py:20` | `agent_comms.prompt_state` | runtime | commander | | `src/agent_comms/native_settings.py:6` | `agent_comms.cli_options` | runtime | cli | | `src/agent_comms/native_startup.py:10` | `agent_comms.diagnostics` | runtime | commander | -| `src/agent_comms/native_tool_call.py:19` | `agent_comms.storage_rules` | runtime | commander | -| `src/agent_comms/native_tool_call.py:20` | `agent_comms.tool_denial` | runtime | cli | +| `src/agent_comms/native_tool_call.py:21` | `agent_comms.storage_rules` | runtime | commander | +| `src/agent_comms/native_tool_call.py:22` | `agent_comms.tool_denial` | runtime | cli | +| `src/agent_comms/native_tool_call.py:26` | `agent_comms.envelope_claim_transitions` | runtime | commander | | `src/agent_comms/native_tool_call.py:27` | `agent_comms.storage_room` | runtime | commander | | `src/agent_comms/native_tool_call.py:28` | `agent_comms.threads` | runtime | commander | | `src/agent_comms/native_tool_call.py:29` | `agent_comms.storage_rules` | runtime | commander | -| `src/agent_comms/native_tool_call.py:178` | `agent_comms.storage_room` | runtime | commander | -| `src/agent_comms/native_tool_call.py:182` | `agent_comms.storage_room` | runtime | commander | +| `src/agent_comms/native_tool_call.py:188` | `agent_comms.storage_room` | runtime | commander | +| `src/agent_comms/native_tool_call.py:192` | `agent_comms.storage_room` | runtime | commander | | `src/agent_comms/native_tool_transport.py:19` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/native_tool_transport.py:22` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/native_tool_transport.py:21` | `agent_comms.errors` | runtime | commander | | `src/agent_comms/native_tool_transport.py:32` | `agent_comms.tool_denial` | runtime | cli | | `src/agent_comms/native_tool_transport.py:35` | `agent_comms.backend` | runtime | commander | -| `src/agent_comms/native_tools.py:15` | `agent_comms.tool_denial` | runtime | cli | -| `src/agent_comms/native_tools.py:17` | `agent_comms.storage_rules` | runtime | commander | -| `src/agent_comms/native_tools.py:18` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/native_tools.py:11` | `agent_comms.envelope_claim_transitions` | runtime | commander | +| `src/agent_comms/native_tools.py:15` | `agent_comms.storage_rules` | runtime | commander | +| `src/agent_comms/native_tools.py:16` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/native_tools.py:26` | `agent_comms.tool_denial` | runtime | cli | | `src/agent_comms/native_transcript.py:16` | `agent_comms.read_ledger` | runtime | commander | | `src/agent_comms/native_transcript.py:34` | `agent_comms.transcript_sources` | runtime | commander | -| `src/agent_comms/native_transcript.py:386` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/native_transcript.py:382` | `agent_comms.errors` | runtime | commander | | `src/agent_comms/native_turn_context.py:11` | `agent_comms.tool_result` | runtime | cli | | `src/agent_comms/native_turn_context.py:26` | `agent_comms.context_store` | runtime | commander | | `src/agent_comms/native_turn_context.py:49` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/order_story.py:11` | `agent_comms.tool_result` | commander | cli | +| `src/agent_comms/order_tools.py:52` | `agent_comms.tool_caller` | commander | cli | +| `src/agent_comms/order_tools.py:53` | `agent_comms.tool_request` | commander | cli | +| `src/agent_comms/order_tools.py:61` | `agent_comms.tool_result` | commander | cli | +| `src/agent_comms/order_tools.py:71` | `agent_comms.ui_model.unit_state` | commander | ui_model | | `src/agent_comms/order_work.py:8` | `agent_comms.tool_result` | commander | cli | -| `src/agent_comms/owned_send.py:176` | `agent_comms.tool_denial` | commander | cli | -| `src/agent_comms/owner_cutover.py:11` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/owner_cutover.py:12` | `agent_comms.launch_runtime` | registry | commander | -| `src/agent_comms/owner_cutover.py:15` | `agent_comms.maintenance_barrier` | registry | commander | -| `src/agent_comms/owner_cutover.py:19` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/owner_cutover.py:51` | `agent_comms.restart_refusals` | registry | commander | +| `src/agent_comms/owned_send.py:125` | `agent_comms.tool_denial` | commander | cli | +| `src/agent_comms/owner_connection.py:12` | `agent_comms.coordinator` | registry | commander | +| `src/agent_comms/owner_connection.py:13` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/owner_connection.py:20` | `agent_comms.child_process` | registry | commander | +| `src/agent_comms/owner_cutover.py:10` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/owner_cutover.py:11` | `agent_comms.launch_runtime` | registry | commander | +| `src/agent_comms/owner_cutover.py:14` | `agent_comms.maintenance_barrier` | registry | commander | +| `src/agent_comms/owner_cutover.py:18` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/owner_cutover.py:50` | `agent_comms.restart_refusals` | registry | commander | | `src/agent_comms/owner_fence.py:9` | `agent_comms.coordination_contracts` | registry | coordination | -| `src/agent_comms/owner_launch.py:10` | `agent_comms.child_process` | registry | commander | -| `src/agent_comms/owner_launch.py:11` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/owner_launch.py:12` | `agent_comms.launch_runtime` | registry | commander | -| `src/agent_comms/owner_launch.py:13` | `agent_comms.native_arguments` | registry | runtime | -| `src/agent_comms/owner_lifecycle.py:17` | `agent_comms.active_route` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:18` | `agent_comms.attempt_recovery` | registry | coordination | -| `src/agent_comms/owner_lifecycle.py:19` | `agent_comms.child_process` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:28` | `agent_comms.cli_result` | registry | cli | -| `src/agent_comms/owner_lifecycle.py:29` | `agent_comms.commander_heartbeat` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:30` | `agent_comms.diagnostics` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:31` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:32` | `agent_comms.launch_root` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:33` | `agent_comms.input_disposition` | registry | turns | -| `src/agent_comms/owner_lifecycle.py:34` | `agent_comms.launch_runtime` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:35` | `agent_comms.maintenance_barrier` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:37` | `agent_comms.native_arguments` | registry | runtime | -| `src/agent_comms/owner_lifecycle.py:45` | `agent_comms.registration` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:47` | `agent_comms.restart_refusals` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:51` | `agent_comms.restart_scope` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:55` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:56` | `agent_comms.tool_result` | registry | cli | -| `src/agent_comms/owner_lifecycle.py:57` | `agent_comms.typed_table` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:60` | `agent_comms.goal_management` | registry | coordination | -| `src/agent_comms/owner_lifecycle.py:61` | `agent_comms.messaging` | registry | commander | -| `src/agent_comms/owner_lifecycle.py:270` | `agent_comms.restart_refusals` | registry | commander | -| `src/agent_comms/owner_protocol.py:22` | `agent_comms.package_stamp` | registry | commander | -| `src/agent_comms/owner_protocol.py:25` | `agent_comms.runtime` | registry | runtime | +| `src/agent_comms/owner_launch.py:8` | `agent_comms.child_process` | registry | commander | +| `src/agent_comms/owner_launch.py:9` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/owner_launch.py:10` | `agent_comms.launch_runtime` | registry | commander | +| `src/agent_comms/owner_launch.py:11` | `agent_comms.native_arguments` | registry | runtime | +| `src/agent_comms/owner_lifecycle.py:16` | `agent_comms.active_route` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:17` | `agent_comms.attempt_recovery` | registry | coordination | +| `src/agent_comms/owner_lifecycle.py:18` | `agent_comms.child_process` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:27` | `agent_comms.cli_result` | registry | cli | +| `src/agent_comms/owner_lifecycle.py:28` | `agent_comms.commander_service` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:29` | `agent_comms.diagnostics` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:30` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:31` | `agent_comms.launch_root` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:32` | `agent_comms.input_key` | registry | turns | +| `src/agent_comms/owner_lifecycle.py:34` | `agent_comms.input_disposition` | registry | turns | +| `src/agent_comms/owner_lifecycle.py:35` | `agent_comms.launch_runtime` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:36` | `agent_comms.maintenance_barrier` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:38` | `agent_comms.native_arguments` | registry | runtime | +| `src/agent_comms/owner_lifecycle.py:46` | `agent_comms.registration` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:48` | `agent_comms.restart_refusals` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:52` | `agent_comms.restart_scope` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:56` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:57` | `agent_comms.tool_result` | registry | cli | +| `src/agent_comms/owner_lifecycle.py:58` | `agent_comms.typed_table` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:61` | `agent_comms.goal_management` | registry | coordination | +| `src/agent_comms/owner_lifecycle.py:62` | `agent_comms.messaging` | registry | commander | +| `src/agent_comms/owner_lifecycle.py:295` | `agent_comms.restart_refusals` | registry | commander | +| `src/agent_comms/owner_protocol.py:21` | `agent_comms.package_stamp` | registry | commander | +| `src/agent_comms/owner_protocol.py:24` | `agent_comms.runtime` | registry | runtime | | `src/agent_comms/owner_requests.py:13` | `agent_comms.errors` | registry | commander | | `src/agent_comms/owner_requests.py:24` | `agent_comms.messages` | registry | commander | | `src/agent_comms/owner_requests.py:25` | `agent_comms.registration` | registry | commander | @@ -1046,9 +1085,9 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/owner_restart.py:26` | `agent_comms.restart_refusals` | registry | commander | | `src/agent_comms/owner_restart.py:27` | `agent_comms.restart_scope` | registry | commander | | `src/agent_comms/owner_restart.py:34` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/owner_restart.py:241` | `agent_comms.attempt_recovery` | registry | coordination | -| `src/agent_comms/pi_commands.py:51` | `agent_comms.backend` | runtime | commander | -| `src/agent_comms/pi_commands.py:261` | `agent_comms.child_process` | runtime | commander | +| `src/agent_comms/owner_restart.py:238` | `agent_comms.attempt_recovery` | registry | coordination | +| `src/agent_comms/pi_commands.py:52` | `agent_comms.backend` | runtime | commander | +| `src/agent_comms/pi_commands.py:262` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/pi_counts.py:22` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/pi_durable_backend.py:24` | `agent_comms.locked_store` | runtime | commander | | `src/agent_comms/pi_durable_backend.py:25` | `agent_comms.external_transcript` | runtime | commander | @@ -1064,43 +1103,44 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/pi_native_backend.py:52` | `agent_comms.threads` | runtime | commander | | `src/agent_comms/pi_native_backend.py:226` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/pi_native_backend.py:259` | `agent_comms.backend` | runtime | commander | -| `src/agent_comms/pi_native_backend.py:290` | `agent_comms.backend` | runtime | commander | -| `src/agent_comms/pi_native_backend.py:318` | `agent_comms.coordinator` | runtime | commander | -| `src/agent_comms/pi_payloads.py:51` | `agent_comms.goals` | runtime | commander | -| `src/agent_comms/pi_payloads.py:64` | `agent_comms.send_result` | runtime | commander | -| `src/agent_comms/pi_payloads.py:66` | `agent_comms.tool_declaration` | runtime | cli | -| `src/agent_comms/pi_payloads.py:67` | `agent_comms.tool_results` | runtime | cli | -| `src/agent_comms/pi_payloads.py:68` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:73` | `agent_comms.backend` | runtime | commander | -| `src/agent_comms/pi_payloads.py:499` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:504` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:522` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:543` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:559` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:928` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:953` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:996` | `agent_comms.tool_declaration` | runtime | cli | -| `src/agent_comms/pi_payloads.py:997` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/pi_payloads.py:1301` | `agent_comms.backend` | runtime | commander | +| `src/agent_comms/pi_native_backend.py:289` | `agent_comms.backend` | runtime | commander | +| `src/agent_comms/pi_native_backend.py:317` | `agent_comms.coordinator` | runtime | commander | +| `src/agent_comms/pi_payloads.py:50` | `agent_comms.goals` | runtime | commander | +| `src/agent_comms/pi_payloads.py:63` | `agent_comms.send_result` | runtime | commander | +| `src/agent_comms/pi_payloads.py:65` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/pi_payloads.py:66` | `agent_comms.tool_results` | runtime | cli | +| `src/agent_comms/pi_payloads.py:67` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:72` | `agent_comms.backend` | runtime | commander | +| `src/agent_comms/pi_payloads.py:484` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:489` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:507` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:528` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:544` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:905` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:930` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:973` | `agent_comms.tool_declaration` | runtime | cli | +| `src/agent_comms/pi_payloads.py:974` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/pi_payloads.py:1274` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/pi_vocabulary.py:22` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/plan_phases.py:19` | `agent_comms.tool_calls` | commander | cli | | `src/agent_comms/presentation.py:20` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/presentation.py:83` | `agent_comms.tool_result` | commander | cli | -| `src/agent_comms/presentation.py:84` | `agent_comms.ui_model.unread` | commander | ui_model | -| `src/agent_comms/presentation.py:104` | `agent_comms.ui_model.observation` | commander | ui_model | -| `src/agent_comms/private_nk_entrypoint.py:16` | `agent_comms.coordination_errors` | wire | coordination | -| `src/agent_comms/private_nk_entrypoint.py:18` | `agent_comms.native_arguments` | wire | runtime | -| `src/agent_comms/private_nk_entrypoint.py:19` | `agent_comms.native_package` | wire | runtime | -| `src/agent_comms/private_nk_entrypoint.py:24` | `agent_comms.native_session_files` | wire | runtime | -| `src/agent_comms/private_nk_entrypoint.py:25` | `agent_comms.store_files` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:28` | `agent_comms.active_route` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:29` | `agent_comms.launch_runtime` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:30` | `agent_comms.threads` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:70` | `agent_comms.locked_store` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:71` | `agent_comms.registration` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:146` | `agent_comms.bus` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:147` | `agent_comms.locked_store` | wire | commander | -| `src/agent_comms/private_nk_entrypoint.py:148` | `agent_comms.registry_store` | wire | registry | +| `src/agent_comms/presentation.py:86` | `agent_comms.tool_result` | commander | cli | +| `src/agent_comms/presentation.py:87` | `agent_comms.ui_model.unread` | commander | ui_model | +| `src/agent_comms/presentation.py:107` | `agent_comms.ui_model.observation` | commander | ui_model | +| `src/agent_comms/private_nk_entrypoint.py:10` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/private_nk_entrypoint.py:18` | `agent_comms.coordination_errors` | wire | coordination | +| `src/agent_comms/private_nk_entrypoint.py:20` | `agent_comms.native_arguments` | wire | runtime | +| `src/agent_comms/private_nk_entrypoint.py:21` | `agent_comms.native_package` | wire | runtime | +| `src/agent_comms/private_nk_entrypoint.py:26` | `agent_comms.native_session_files` | wire | runtime | +| `src/agent_comms/private_nk_entrypoint.py:27` | `agent_comms.store_files` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:30` | `agent_comms.active_route` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:31` | `agent_comms.launch_runtime` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:32` | `agent_comms.threads` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:72` | `agent_comms.locked_store` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:73` | `agent_comms.registration` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:148` | `agent_comms.bus` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:149` | `agent_comms.locked_store` | wire | commander | +| `src/agent_comms/private_nk_entrypoint.py:150` | `agent_comms.registry_store` | wire | registry | | `src/agent_comms/private_path.py:18` | `agent_comms.child_process` | wire | commander | | `src/agent_comms/private_path.py:19` | `agent_comms.declared_family` | wire | registry | | `src/agent_comms/private_path.py:20` | `agent_comms.errors` | wire | commander | @@ -1108,26 +1148,28 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/private_registry_guard.py:29` | `agent_comms.child_process` | wire | commander | | `src/agent_comms/private_registry_guard.py:30` | `agent_comms.store_files` | wire | commander | | `src/agent_comms/private_registry_guard.py:31` | `agent_comms.coordination_database` | wire | coordination | -| `src/agent_comms/private_registry_guard.py:32` | `agent_comms.coordinator` | wire | commander | -| `src/agent_comms/private_registry_guard.py:33` | `agent_comms.errors` | wire | commander | -| `src/agent_comms/private_registry_guard.py:34` | `agent_comms.field_codec` | wire | registry | -| `src/agent_comms/private_registry_guard.py:35` | `agent_comms.locked_store` | wire | commander | -| `src/agent_comms/private_registry_guard.py:36` | `agent_comms.native_runtime_input` | wire | runtime | -| `src/agent_comms/private_registry_guard.py:41` | `agent_comms.acp_extension` | wire | runtime | -| `src/agent_comms/private_registry_guard.py:43` | `agent_comms.cursor_publication` | wire | commander | -| `src/agent_comms/private_registry_guard.py:44` | `agent_comms.notification_assignment` | wire | commander | -| `src/agent_comms/private_registry_guard.py:46` | `agent_comms.registry_document` | wire | registry | -| `src/agent_comms/private_registry_guard.py:47` | `agent_comms.typed_table` | wire | commander | -| `src/agent_comms/private_registry_guard.py:120` | `agent_comms.registry_store` | wire | registry | -| `src/agent_comms/private_registry_guard.py:121` | `agent_comms.store_files` | wire | commander | -| `src/agent_comms/private_registry_guard.py:179` | `agent_comms.coordination_schema` | wire | coordination | -| `src/agent_comms/private_registry_guard.py:193` | `agent_comms.notification_assignment` | wire | commander | -| `src/agent_comms/private_registry_guard.py:200` | `agent_comms.acp_extension` | wire | runtime | -| `src/agent_comms/private_registry_guard.py:242` | `agent_comms.coordination_response` | wire | coordination | -| `src/agent_comms/private_registry_guard.py:264` | `agent_comms.coordination_errors` | wire | coordination | -| `src/agent_comms/private_registry_guard.py:302` | `agent_comms.acp_extension` | wire | runtime | -| `src/agent_comms/private_registry_guard.py:303` | `agent_comms.native_input_owner` | wire | runtime | -| `src/agent_comms/private_registry_guard.py:304` | `agent_comms.thread_identity` | wire | registry | +| `src/agent_comms/private_registry_guard.py:32` | `agent_comms.cohort_schema` | wire | commander | +| `src/agent_comms/private_registry_guard.py:33` | `agent_comms.coordination_tables.participants` | wire | coordination | +| `src/agent_comms/private_registry_guard.py:34` | `agent_comms.coordinator` | wire | commander | +| `src/agent_comms/private_registry_guard.py:35` | `agent_comms.errors` | wire | commander | +| `src/agent_comms/private_registry_guard.py:36` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/private_registry_guard.py:37` | `agent_comms.locked_store` | wire | commander | +| `src/agent_comms/private_registry_guard.py:38` | `agent_comms.native_runtime_input` | wire | runtime | +| `src/agent_comms/private_registry_guard.py:43` | `agent_comms.acp_extension` | wire | runtime | +| `src/agent_comms/private_registry_guard.py:45` | `agent_comms.cursor_publication` | wire | commander | +| `src/agent_comms/private_registry_guard.py:46` | `agent_comms.notification_assignment` | wire | commander | +| `src/agent_comms/private_registry_guard.py:48` | `agent_comms.registry_document` | wire | registry | +| `src/agent_comms/private_registry_guard.py:49` | `agent_comms.typed_table` | wire | commander | +| `src/agent_comms/private_registry_guard.py:122` | `agent_comms.registry_store` | wire | registry | +| `src/agent_comms/private_registry_guard.py:123` | `agent_comms.store_files` | wire | commander | +| `src/agent_comms/private_registry_guard.py:188` | `agent_comms.coordination_schema` | wire | coordination | +| `src/agent_comms/private_registry_guard.py:202` | `agent_comms.notification_assignment` | wire | commander | +| `src/agent_comms/private_registry_guard.py:209` | `agent_comms.acp_extension` | wire | runtime | +| `src/agent_comms/private_registry_guard.py:261` | `agent_comms.coordination_response` | wire | coordination | +| `src/agent_comms/private_registry_guard.py:283` | `agent_comms.coordination_errors` | wire | coordination | +| `src/agent_comms/private_registry_guard.py:317` | `agent_comms.acp_extension` | wire | runtime | +| `src/agent_comms/private_registry_guard.py:318` | `agent_comms.native_input_owner` | wire | runtime | +| `src/agent_comms/private_registry_guard.py:319` | `agent_comms.thread_identity` | wire | registry | | `src/agent_comms/private_runtime_schema.py:7` | `agent_comms.coordination_errors` | wire | coordination | | `src/agent_comms/private_runtime_schema.py:8` | `agent_comms.coordination_schema` | wire | coordination | | `src/agent_comms/private_runtime_schema.py:9` | `agent_comms.typed_table` | wire | commander | @@ -1138,37 +1180,39 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/private_runtime_schema.py:28` | `agent_comms.triage_native_sources` | wire | commander | | `src/agent_comms/private_runtime_schema.py:45` | `agent_comms.cohort_schema` | wire | commander | | `src/agent_comms/private_send_claim.py:18` | `agent_comms.native_runtime_input` | wire | runtime | -| `src/agent_comms/private_send_claim.py:19` | `agent_comms.coordination_errors` | wire | coordination | -| `src/agent_comms/private_send_claim.py:20` | `agent_comms.coordinator` | wire | commander | -| `src/agent_comms/private_send_claim.py:21` | `agent_comms.diagnostics` | wire | commander | -| `src/agent_comms/private_send_claim.py:25` | `agent_comms.following_inputs` | wire | commander | -| `src/agent_comms/private_send_claim.py:26` | `agent_comms.maintenance_barrier` | wire | commander | -| `src/agent_comms/private_send_claim.py:28` | `agent_comms.native_arguments` | wire | runtime | -| `src/agent_comms/private_send_claim.py:29` | `agent_comms.native_input_owner` | wire | runtime | -| `src/agent_comms/private_send_claim.py:30` | `agent_comms.native_entries` | wire | runtime | -| `src/agent_comms/private_send_claim.py:31` | `agent_comms.native_pi` | wire | runtime | -| `src/agent_comms/private_send_claim.py:32` | `agent_comms.native_prompt_binding` | wire | runtime | -| `src/agent_comms/private_send_claim.py:33` | `agent_comms.native_prompt_send` | wire | runtime | -| `src/agent_comms/private_send_claim.py:34` | `agent_comms.native_session_reopen` | wire | runtime | -| `src/agent_comms/private_send_claim.py:35` | `agent_comms.native_startup` | wire | runtime | -| `src/agent_comms/private_send_claim.py:36` | `agent_comms.native_tool_call` | wire | runtime | -| `src/agent_comms/private_send_claim.py:37` | `agent_comms.text_digest` | wire | registry | -| `src/agent_comms/private_send_claim.py:38` | `agent_comms.tracked_turn` | wire | commander | -| `src/agent_comms/private_send_claim.py:44` | `agent_comms.turn_context` | wire | turns | -| `src/agent_comms/private_send_claim.py:45` | `agent_comms.turn_input_source` | wire | turns | -| `src/agent_comms/private_send_claim.py:48` | `agent_comms.coordinated_runtime` | wire | commander | -| `src/agent_comms/private_send_claim.py:49` | `agent_comms.selected_participant` | wire | turns | -| `src/agent_comms/private_send_claim.py:50` | `agent_comms.selected_session` | wire | turns | -| `src/agent_comms/private_send_rules.py:8` | `agent_comms.child_process` | wire | commander | -| `src/agent_comms/private_send_rules.py:9` | `agent_comms.coordination_tables.assignments` | wire | coordination | -| `src/agent_comms/private_send_rules.py:10` | `agent_comms.coordination_tables.participants` | wire | coordination | -| `src/agent_comms/private_send_rules.py:11` | `agent_comms.reservation_rules` | wire | registry | -| `src/agent_comms/private_send_rules.py:12` | `agent_comms.text_digest` | wire | registry | -| `src/agent_comms/private_send_rules.py:13` | `agent_comms.threads` | wire | commander | -| `src/agent_comms/private_send_rules.py:14` | `agent_comms.turn_goal_permission` | wire | turns | -| `src/agent_comms/private_send_rules.py:17` | `agent_comms.native_input_record` | wire | runtime | -| `src/agent_comms/private_send_rules.py:18` | `agent_comms.native_prompt_binding` | wire | runtime | -| `src/agent_comms/private_send_rules.py:19` | `agent_comms.native_runtime_input` | wire | runtime | +| `src/agent_comms/private_send_claim.py:19` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/private_send_claim.py:20` | `agent_comms.coordination_errors` | wire | coordination | +| `src/agent_comms/private_send_claim.py:21` | `agent_comms.coordinator` | wire | commander | +| `src/agent_comms/private_send_claim.py:22` | `agent_comms.diagnostics` | wire | commander | +| `src/agent_comms/private_send_claim.py:26` | `agent_comms.following_inputs` | wire | commander | +| `src/agent_comms/private_send_claim.py:27` | `agent_comms.maintenance_barrier` | wire | commander | +| `src/agent_comms/private_send_claim.py:29` | `agent_comms.native_arguments` | wire | runtime | +| `src/agent_comms/private_send_claim.py:30` | `agent_comms.native_input_owner` | wire | runtime | +| `src/agent_comms/private_send_claim.py:31` | `agent_comms.native_entries` | wire | runtime | +| `src/agent_comms/private_send_claim.py:32` | `agent_comms.native_pi` | wire | runtime | +| `src/agent_comms/private_send_claim.py:33` | `agent_comms.native_prompt_binding` | wire | runtime | +| `src/agent_comms/private_send_claim.py:34` | `agent_comms.native_prompt_send` | wire | runtime | +| `src/agent_comms/private_send_claim.py:35` | `agent_comms.native_session_reopen` | wire | runtime | +| `src/agent_comms/private_send_claim.py:36` | `agent_comms.native_startup` | wire | runtime | +| `src/agent_comms/private_send_claim.py:37` | `agent_comms.native_tool_call` | wire | runtime | +| `src/agent_comms/private_send_claim.py:38` | `agent_comms.text_digest` | wire | registry | +| `src/agent_comms/private_send_claim.py:39` | `agent_comms.tracked_turn` | wire | commander | +| `src/agent_comms/private_send_claim.py:45` | `agent_comms.turn_context` | wire | turns | +| `src/agent_comms/private_send_claim.py:46` | `agent_comms.turn_input_source` | wire | turns | +| `src/agent_comms/private_send_claim.py:49` | `agent_comms.coordinated_runtime` | wire | commander | +| `src/agent_comms/private_send_claim.py:50` | `agent_comms.selected_participant` | wire | turns | +| `src/agent_comms/private_send_claim.py:51` | `agent_comms.selected_session` | wire | turns | +| `src/agent_comms/private_send_rules.py:8` | `agent_comms.field_codec` | wire | registry | +| `src/agent_comms/private_send_rules.py:10` | `agent_comms.child_process` | wire | commander | +| `src/agent_comms/private_send_rules.py:11` | `agent_comms.coordination_tables.assignments` | wire | coordination | +| `src/agent_comms/private_send_rules.py:12` | `agent_comms.coordination_tables.participants` | wire | coordination | +| `src/agent_comms/private_send_rules.py:13` | `agent_comms.reservation_rules` | wire | registry | +| `src/agent_comms/private_send_rules.py:14` | `agent_comms.text_digest` | wire | registry | +| `src/agent_comms/private_send_rules.py:15` | `agent_comms.threads` | wire | commander | +| `src/agent_comms/private_send_rules.py:16` | `agent_comms.turn_goal_permission` | wire | turns | +| `src/agent_comms/private_send_rules.py:19` | `agent_comms.native_input_record` | wire | runtime | +| `src/agent_comms/private_send_rules.py:20` | `agent_comms.native_prompt_binding` | wire | runtime | +| `src/agent_comms/private_send_rules.py:21` | `agent_comms.native_runtime_input` | wire | runtime | | `src/agent_comms/private_send_stage.py:7` | `agent_comms.native_session_files` | wire | runtime | | `src/agent_comms/private_send_stage.py:8` | `agent_comms.native_session_reopen` | wire | runtime | | `src/agent_comms/private_send_stage.py:17` | `agent_comms.assignment_states` | wire | commander | @@ -1192,30 +1236,30 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/private_sidecar.py:29` | `agent_comms.locked_store` | wire | commander | | `src/agent_comms/private_sidecar.py:30` | `agent_comms.coordination_errors` | wire | coordination | | `src/agent_comms/private_sidecar.py:32` | `agent_comms.field_codec` | wire | registry | -| `src/agent_comms/private_sidecar.py:33` | `agent_comms.child_process` | wire | commander | -| `src/agent_comms/private_sidecar.py:36` | `agent_comms.agent_backend` | wire | runtime | -| `src/agent_comms/private_sidecar.py:39` | `agent_comms.store_files` | wire | commander | -| `src/agent_comms/private_sidecar.py:40` | `agent_comms.typed_table` | wire | commander | +| `src/agent_comms/private_sidecar.py:35` | `agent_comms.agent_backend` | wire | runtime | +| `src/agent_comms/private_sidecar.py:38` | `agent_comms.store_files` | wire | commander | +| `src/agent_comms/private_sidecar.py:39` | `agent_comms.typed_table` | wire | commander | | `src/agent_comms/registration_change.py:16` | `agent_comms.errors` | registry | commander | | `src/agent_comms/registration_change.py:17` | `agent_comms.coordination_session` | registry | coordination | | `src/agent_comms/registration_change.py:18` | `agent_comms.goals` | registry | commander | | `src/agent_comms/registration_change.py:19` | `agent_comms.participant_store` | registry | coordination | -| `src/agent_comms/registration_change.py:21` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/registry_document.py:13` | `agent_comms.child_process` | registry | commander | -| `src/agent_comms/registry_document.py:15` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/registry_document.py:29` | `agent_comms.repo` | registry | commander | -| `src/agent_comms/registry_document.py:37` | `agent_comms.restart_refusals` | registry | commander | -| `src/agent_comms/registry_document.py:60` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/registry_document.py:61` | `agent_comms.turn_lease` | registry | turns | -| `src/agent_comms/registry_document.py:64` | `agent_comms.activity` | registry | commander | -| `src/agent_comms/registry_document.py:65` | `agent_comms.agent_activity` | registry | runtime | -| `src/agent_comms/registry_document.py:66` | `agent_comms.audience_manifest` | registry | commander | -| `src/agent_comms/registry_provenance.py:15` | `agent_comms.agent_activity` | registry | runtime | -| `src/agent_comms/registry_provenance.py:16` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/registry_provenance.py:17` | `agent_comms.routing` | registry | commander | -| `src/agent_comms/registry_provenance.py:19` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/registry_provenance.py:22` | `agent_comms.audience_manifest` | registry | commander | -| `src/agent_comms/registry_provenance.py:23` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/registration_change.py:22` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/registry_document.py:17` | `agent_comms.child_process` | registry | commander | +| `src/agent_comms/registry_document.py:19` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/registry_document.py:35` | `agent_comms.repo` | registry | commander | +| `src/agent_comms/registry_document.py:44` | `agent_comms.restart_refusals` | registry | commander | +| `src/agent_comms/registry_document.py:67` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/registry_document.py:68` | `agent_comms.turn_lease` | registry | turns | +| `src/agent_comms/registry_document.py:74` | `agent_comms.activity` | registry | commander | +| `src/agent_comms/registry_document.py:75` | `agent_comms.agent_activity` | registry | runtime | +| `src/agent_comms/registry_document.py:76` | `agent_comms.audience_manifest` | registry | commander | +| `src/agent_comms/registry_provenance.py:17` | `agent_comms.agent_activity` | registry | runtime | +| `src/agent_comms/registry_provenance.py:18` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/registry_provenance.py:19` | `agent_comms.messages` | registry | commander | +| `src/agent_comms/registry_provenance.py:20` | `agent_comms.routing` | registry | commander | +| `src/agent_comms/registry_provenance.py:22` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/registry_provenance.py:25` | `agent_comms.audience_manifest` | registry | commander | +| `src/agent_comms/registry_provenance.py:26` | `agent_comms.threads` | registry | commander | | `src/agent_comms/registry_store.py:17` | `agent_comms.coordination_database` | registry | coordination | | `src/agent_comms/registry_store.py:18` | `agent_comms.errors` | registry | commander | | `src/agent_comms/registry_store.py:20` | `agent_comms.locked_store` | registry | commander | @@ -1226,10 +1270,11 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/registry_store.py:34` | `agent_comms.store_files` | registry | commander | | `src/agent_comms/registry_store.py:36` | `agent_comms.threads` | registry | commander | | `src/agent_comms/registry_store.py:37` | `agent_comms.turn_lease` | registry | turns | +| `src/agent_comms/restart_queue.py:23` | `agent_comms.cli_result` | commander | cli | +| `src/agent_comms/restart_queue.py:44` | `agent_comms.tool_result` | commander | cli | | `src/agent_comms/runtime.py:10` | `agent_comms.coordinator` | runtime | commander | -| `src/agent_comms/runtime.py:53` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/runtime.py:55` | `agent_comms.errors` | runtime | commander | -| `src/agent_comms/runtime.py:61` | `agent_comms.acp` | runtime | commander | +| `src/agent_comms/runtime.py:52` | `agent_comms.errors` | runtime | commander | +| `src/agent_comms/runtime.py:58` | `agent_comms.acp` | runtime | commander | | `src/agent_comms/runtime_children.py:14` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/runtime_children.py:25` | `agent_comms.launch_runtime` | runtime | commander | | `src/agent_comms/runtime_children.py:26` | `agent_comms.locked_store` | runtime | commander | @@ -1246,7 +1291,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/runtime_requests.py:26` | `agent_comms.coordinator` | runtime | commander | | `src/agent_comms/runtime_requests.py:28` | `agent_comms.errors` | runtime | commander | | `src/agent_comms/runtime_requests.py:32` | `agent_comms.goals` | runtime | commander | -| `src/agent_comms/runtime_requests.py:36` | `agent_comms.tool_result` | runtime | cli | +| `src/agent_comms/runtime_requests.py:37` | `agent_comms.tool_result` | runtime | cli | | `src/agent_comms/runtime_requests.py:326` | `agent_comms.manual_compaction_bridge` | runtime | commander | | `src/agent_comms/runtime_requests.py:564` | `agent_comms.cli_commands` | runtime | cli | | `src/agent_comms/runtime_updates.py:15` | `agent_comms.activity` | runtime | commander | @@ -1254,7 +1299,10 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/runtime_updates.py:18` | `agent_comms.external_transcript` | runtime | commander | | `src/agent_comms/runtime_updates.py:20` | `agent_comms.transcript_events` | runtime | commander | | `src/agent_comms/runtime_updates.py:32` | `agent_comms.importing` | runtime | commander | +| `src/agent_comms/runtime_updates.py:33` | `agent_comms.comms` | runtime | commander | +| `src/agent_comms/runtime_updates.py:34` | `agent_comms.messaging` | runtime | commander | | `src/agent_comms/schema_report.py:9` | `agent_comms.cli_result` | commander | cli | +| `src/agent_comms/selected_actions.py:11` | `agent_comms.envelope_claim_transitions` | turns | commander | | `src/agent_comms/selected_actions.py:13` | `agent_comms.native_tool_call` | turns | runtime | | `src/agent_comms/selected_actions.py:14` | `agent_comms.native_tool_transport` | turns | runtime | | `src/agent_comms/selected_actions.py:22` | `agent_comms.threads` | turns | commander | @@ -1262,19 +1310,19 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/selected_claim.py:18` | `agent_comms.cohort_schema` | turns | commander | | `src/agent_comms/selected_claim.py:19` | `agent_comms.bus` | turns | commander | | `src/agent_comms/selected_claim.py:21` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/selected_claim.py:26` | `agent_comms.envelope_claim_transitions` | turns | commander | | `src/agent_comms/selected_claim.py:32` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/selected_claim.py:33` | `agent_comms.child_process` | turns | commander | -| `src/agent_comms/selected_claim.py:34` | `agent_comms.native_input_owner` | turns | runtime | -| `src/agent_comms/selected_claim.py:37` | `agent_comms.store_files` | turns | commander | -| `src/agent_comms/selected_claim.py:38` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/selected_participant.py:12` | `agent_comms.agent_events` | turns | runtime | -| `src/agent_comms/selected_participant.py:14` | `agent_comms.cohort_schema` | turns | commander | -| `src/agent_comms/selected_participant.py:15` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/selected_participant.py:16` | `agent_comms.native_runtime_input` | turns | runtime | -| `src/agent_comms/selected_participant.py:17` | `agent_comms.context_store` | turns | commander | -| `src/agent_comms/selected_participant.py:24` | `agent_comms.coordinator` | turns | commander | -| `src/agent_comms/selected_participant.py:25` | `agent_comms.cursor_publication` | turns | commander | -| `src/agent_comms/selected_participant.py:26` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/selected_claim.py:33` | `agent_comms.native_input_owner` | turns | runtime | +| `src/agent_comms/selected_claim.py:36` | `agent_comms.store_files` | turns | commander | +| `src/agent_comms/selected_claim.py:37` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/selected_participant.py:11` | `agent_comms.agent_events` | turns | runtime | +| `src/agent_comms/selected_participant.py:13` | `agent_comms.cohort_schema` | turns | commander | +| `src/agent_comms/selected_participant.py:14` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/selected_participant.py:15` | `agent_comms.native_runtime_input` | turns | runtime | +| `src/agent_comms/selected_participant.py:16` | `agent_comms.context_store` | turns | commander | +| `src/agent_comms/selected_participant.py:23` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/selected_participant.py:24` | `agent_comms.cursor_publication` | turns | commander | +| `src/agent_comms/selected_participant.py:25` | `agent_comms.errors` | turns | commander | | `src/agent_comms/selected_participant.py:30` | `agent_comms.native_arguments` | turns | runtime | | `src/agent_comms/selected_participant.py:31` | `agent_comms.native_attestation` | turns | runtime | | `src/agent_comms/selected_participant.py:32` | `agent_comms.native_input_owner` | turns | runtime | @@ -1290,8 +1338,8 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/selected_request.py:14` | `agent_comms.native_failures` | turns | runtime | | `src/agent_comms/selected_result.py:10` | `agent_comms.assignment_states` | turns | commander | | `src/agent_comms/selected_result.py:12` | `agent_comms.diagnostics` | turns | commander | -| `src/agent_comms/selected_result.py:13` | `agent_comms.messages` | turns | commander | -| `src/agent_comms/selected_result.py:14` | `agent_comms.send_result` | turns | commander | +| `src/agent_comms/selected_result.py:14` | `agent_comms.messages` | turns | commander | +| `src/agent_comms/selected_result.py:15` | `agent_comms.send_result` | turns | commander | | `src/agent_comms/selected_session.py:11` | `agent_comms.coordinator` | turns | commander | | `src/agent_comms/selected_session.py:12` | `agent_comms.native_arguments` | turns | runtime | | `src/agent_comms/selected_session.py:13` | `agent_comms.native_session_files` | turns | runtime | @@ -1307,30 +1355,32 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/selected_source_batch.py:11` | `agent_comms.messages` | turns | commander | | `src/agent_comms/selected_source_batch.py:12` | `agent_comms.native_failures` | turns | runtime | | `src/agent_comms/selected_source_batch.py:16` | `agent_comms.assignment_store` | turns | commander | -| `src/agent_comms/selected_tool_broker.py:21` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/selected_tool_broker.py:25` | `agent_comms.coordinator` | turns | commander | -| `src/agent_comms/selected_tool_broker.py:28` | `agent_comms.native_input_record` | turns | runtime | -| `src/agent_comms/selected_tool_broker.py:29` | `agent_comms.native_runtime_input` | turns | runtime | -| `src/agent_comms/selected_tool_broker.py:30` | `agent_comms.native_tool_call` | turns | runtime | +| `src/agent_comms/selected_tool_broker.py:20` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/selected_tool_broker.py:24` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/selected_tool_broker.py:25` | `agent_comms.envelope_claim_transitions` | turns | commander | +| `src/agent_comms/selected_tool_broker.py:27` | `agent_comms.native_input_record` | turns | runtime | +| `src/agent_comms/selected_tool_broker.py:28` | `agent_comms.native_runtime_input` | turns | runtime | +| `src/agent_comms/selected_tool_broker.py:29` | `agent_comms.native_tool_call` | turns | runtime | | `src/agent_comms/selected_tool_broker.py:35` | `agent_comms.native_tool_transport` | turns | runtime | | `src/agent_comms/selected_tool_broker.py:43` | `agent_comms.tool_denial` | turns | cli | | `src/agent_comms/selected_triage.py:11` | `agent_comms.assignment_states` | turns | commander | | `src/agent_comms/selected_triage.py:13` | `agent_comms.coordinator` | turns | commander | -| `src/agent_comms/selected_triage.py:22` | `agent_comms.typed_table` | turns | commander | -| `src/agent_comms/selected_triage.py:27` | `agent_comms.assignment_states` | turns | commander | -| `src/agent_comms/selected_triage.py:28` | `agent_comms.coordinated_runtime` | turns | commander | -| `src/agent_comms/selected_triage.py:29` | `agent_comms.historical_native_inputs` | turns | commander | -| `src/agent_comms/selected_triage.py:30` | `agent_comms.native_input_record` | turns | runtime | -| `src/agent_comms/selected_triage.py:31` | `agent_comms.native_pi` | turns | runtime | -| `src/agent_comms/selected_triage.py:32` | `agent_comms.native_runtime_input` | turns | runtime | -| `src/agent_comms/selected_triage.py:221` | `agent_comms.historical_native_inputs` | turns | commander | +| `src/agent_comms/selected_triage.py:23` | `agent_comms.typed_table` | turns | commander | +| `src/agent_comms/selected_triage.py:28` | `agent_comms.assignment_states` | turns | commander | +| `src/agent_comms/selected_triage.py:29` | `agent_comms.coordinated_runtime` | turns | commander | +| `src/agent_comms/selected_triage.py:30` | `agent_comms.historical_native_inputs` | turns | commander | +| `src/agent_comms/selected_triage.py:31` | `agent_comms.native_input_record` | turns | runtime | +| `src/agent_comms/selected_triage.py:32` | `agent_comms.native_pi` | turns | runtime | +| `src/agent_comms/selected_triage.py:33` | `agent_comms.native_runtime_input` | turns | runtime | +| `src/agent_comms/selected_triage.py:240` | `agent_comms.historical_native_inputs` | turns | commander | | `src/agent_comms/selected_turn.py:10` | `agent_comms.assignment_states` | turns | commander | | `src/agent_comms/selected_turn.py:13` | `agent_comms.coordinator` | turns | commander | | `src/agent_comms/selected_turn.py:17` | `agent_comms.durable_turn` | turns | commander | +| `src/agent_comms/selected_turn.py:18` | `agent_comms.envelope_claim_transitions` | turns | commander | | `src/agent_comms/selected_turn.py:19` | `agent_comms.optional_awareness_projection` | turns | commander | | `src/agent_comms/selected_turn.py:20` | `agent_comms.native_failures` | turns | runtime | -| `src/agent_comms/selected_write_authority.py:13` | `agent_comms.acp` | turns | commander | -| `src/agent_comms/selected_write_authority.py:16` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/selected_write_authority.py:14` | `agent_comms.acp` | turns | commander | +| `src/agent_comms/selected_write_authority.py:17` | `agent_comms.threads` | turns | commander | | `src/agent_comms/selected_write_plan.py:20` | `agent_comms.locked_store` | turns | commander | | `src/agent_comms/selected_write_plan.py:21` | `agent_comms.store_files` | turns | commander | | `src/agent_comms/selected_write_plan.py:24` | `agent_comms.acp_extension` | turns | runtime | @@ -1338,7 +1388,23 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/selected_write_plan.py:27` | `agent_comms.threads` | turns | commander | | `src/agent_comms/selected_write_plan.py:30` | `agent_comms.coordinator` | turns | commander | | `src/agent_comms/selected_write_plan.py:32` | `agent_comms.child_process` | turns | commander | -| `src/agent_comms/selected_write_plan.py:236` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/selected_write_plan.py:35` | `agent_comms.envelope_claim_transitions` | turns | commander | +| `src/agent_comms/selected_write_plan.py:228` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/session_config_options.py:17` | `agent_comms.agent_backend` | turns | runtime | +| `src/agent_comms/session_config_options.py:18` | `agent_comms.bus` | turns | commander | +| `src/agent_comms/session_config_options.py:19` | `agent_comms.child_process` | turns | commander | +| `src/agent_comms/session_config_options.py:20` | `agent_comms.config_options` | turns | commander | +| `src/agent_comms/session_config_options.py:22` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/session_config_options.py:24` | `agent_comms.launch_runtime` | turns | commander | +| `src/agent_comms/session_config_options.py:25` | `agent_comms.native_failures` | turns | runtime | +| `src/agent_comms/session_config_options.py:26` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/session_config_options.py:27` | `agent_comms.watched` | turns | commander | +| `src/agent_comms/session_config_options.py:31` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/session_config_options.py:32` | `agent_comms.controller` | turns | runtime | +| `src/agent_comms/session_config_options.py:33` | `agent_comms.native_arguments` | turns | runtime | +| `src/agent_comms/session_config_options.py:34` | `agent_comms.pi_commands` | turns | runtime | +| `src/agent_comms/session_config_options.py:35` | `agent_comms.runtime` | turns | runtime | +| `src/agent_comms/session_config_options.py:38` | `agent_comms.threads` | turns | commander | | `src/agent_comms/session_effects.py:8` | `agent_comms.runtime` | turns | runtime | | `src/agent_comms/session_effects.py:9` | `agent_comms.threads` | turns | commander | | `src/agent_comms/session_effects.py:12` | `agent_comms.cursor_publication` | turns | commander | @@ -1349,7 +1415,6 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/session_lifecycle.py:31` | `agent_comms.acp_extension` | turns | runtime | | `src/agent_comms/session_lifecycle.py:36` | `agent_comms.child_process` | turns | commander | | `src/agent_comms/session_lifecycle.py:37` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/session_lifecycle.py:38` | `agent_comms.config_options` | turns | commander | | `src/agent_comms/session_lifecycle.py:39` | `agent_comms.coordinator` | turns | commander | | `src/agent_comms/session_lifecycle.py:40` | `agent_comms.errors` | turns | commander | | `src/agent_comms/session_lifecycle.py:42` | `agent_comms.native_arguments` | turns | runtime | @@ -1364,7 +1429,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/session_load.py:16` | `agent_comms.threads` | turns | commander | | `src/agent_comms/session_revision.py:9` | `agent_comms.native_session_files` | turns | runtime | | `src/agent_comms/shared_ledger.py:9` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/standing_rules.py:37` | `agent_comms.ui_model.unit_state` | commander | ui_model | +| `src/agent_comms/standing_rules.py:43` | `agent_comms.ui_model.unit_state` | commander | ui_model | | `src/agent_comms/storage_rules.py:40` | `agent_comms.tool_denial` | commander | cli | | `src/agent_comms/storage_rules.py:51` | `agent_comms.ui_model.unit_state` | commander | ui_model | | `src/agent_comms/thread_configuration.py:8` | `agent_comms.acp_extension` | registry | runtime | @@ -1375,43 +1440,46 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/thread_execution.py:9` | `agent_comms.child_process` | registry | commander | | `src/agent_comms/thread_execution.py:11` | `agent_comms.errors` | registry | commander | | `src/agent_comms/thread_execution.py:17` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/thread_execution.py:109` | `agent_comms.agent_activity` | registry | runtime | -| `src/agent_comms/thread_execution.py:174` | `agent_comms.agent_activity` | registry | runtime | -| `src/agent_comms/thread_identity.py:19` | `agent_comms.cli_options` | registry | cli | -| `src/agent_comms/thread_identity.py:26` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/thread_identity.py:34` | `agent_comms.response_policy` | registry | commander | -| `src/agent_comms/thread_identity.py:37` | `agent_comms.child_process` | registry | commander | -| `src/agent_comms/thread_identity.py:38` | `agent_comms.messages` | registry | commander | -| `src/agent_comms/thread_identity.py:39` | `agent_comms.read_ledger` | registry | commander | -| `src/agent_comms/thread_identity.py:41` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/thread_identity.py:42` | `agent_comms.todos` | registry | commander | +| `src/agent_comms/thread_execution.py:120` | `agent_comms.agent_activity` | registry | runtime | +| `src/agent_comms/thread_execution.py:185` | `agent_comms.agent_activity` | registry | runtime | +| `src/agent_comms/thread_identity.py:20` | `agent_comms.cli_options` | registry | cli | +| `src/agent_comms/thread_identity.py:27` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/thread_identity.py:37` | `agent_comms.response_policy` | registry | commander | +| `src/agent_comms/thread_identity.py:38` | `agent_comms.wake_policy` | registry | coordination | +| `src/agent_comms/thread_identity.py:41` | `agent_comms.child_process` | registry | commander | +| `src/agent_comms/thread_identity.py:42` | `agent_comms.messages` | registry | commander | +| `src/agent_comms/thread_identity.py:43` | `agent_comms.read_ledger` | registry | commander | +| `src/agent_comms/thread_identity.py:45` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/thread_identity.py:46` | `agent_comms.todos` | registry | commander | | `src/agent_comms/thread_management.py:17` | `agent_comms.coordination_errors` | registry | coordination | | `src/agent_comms/thread_management.py:19` | `agent_comms.child_process` | registry | commander | | `src/agent_comms/thread_management.py:20` | `agent_comms.cli_result` | registry | cli | | `src/agent_comms/thread_management.py:21` | `agent_comms.native_entries` | registry | runtime | | `src/agent_comms/thread_management.py:22` | `agent_comms.registration` | registry | commander | -| `src/agent_comms/thread_management.py:26` | `agent_comms.cli_bridges.history` | registry | runtime | -| `src/agent_comms/thread_management.py:27` | `agent_comms.tool_caller` | registry | cli | -| `src/agent_comms/thread_management.py:28` | `agent_comms.agent_activity` | registry | runtime | -| `src/agent_comms/thread_management.py:29` | `agent_comms.agent_backend` | registry | runtime | -| `src/agent_comms/thread_management.py:30` | `agent_comms.catalog_store` | registry | commander | -| `src/agent_comms/thread_management.py:31` | `agent_comms.collaboration_ledger` | registry | commander | -| `src/agent_comms/thread_management.py:32` | `agent_comms.errors` | registry | commander | -| `src/agent_comms/thread_management.py:34` | `agent_comms.importing` | registry | commander | -| `src/agent_comms/thread_management.py:35` | `agent_comms.launch_runtime` | registry | commander | -| `src/agent_comms/thread_management.py:37` | `agent_comms.native_arguments` | registry | runtime | -| `src/agent_comms/thread_management.py:38` | `agent_comms.native_settings` | registry | runtime | -| `src/agent_comms/thread_management.py:40` | `agent_comms.pi_vocabulary` | registry | runtime | -| `src/agent_comms/thread_management.py:43` | `agent_comms.session_file` | registry | turns | -| `src/agent_comms/thread_management.py:44` | `agent_comms.store_files` | registry | commander | -| `src/agent_comms/thread_management.py:49` | `agent_comms.tool_result` | registry | cli | -| `src/agent_comms/thread_management.py:50` | `agent_comms.threads` | registry | commander | -| `src/agent_comms/thread_management.py:456` | `agent_comms.goal_waits` | registry | coordination | -| `src/agent_comms/thread_management.py:457` | `agent_comms.relationships` | registry | commander | -| `src/agent_comms/thread_management.py:458` | `agent_comms.view_unread` | registry | commander | +| `src/agent_comms/thread_management.py:27` | `agent_comms.cli_bridges.history` | registry | runtime | +| `src/agent_comms/thread_management.py:28` | `agent_comms.tool_caller` | registry | cli | +| `src/agent_comms/thread_management.py:29` | `agent_comms.agent_activity` | registry | runtime | +| `src/agent_comms/thread_management.py:30` | `agent_comms.agent_backend` | registry | runtime | +| `src/agent_comms/thread_management.py:31` | `agent_comms.catalog_store` | registry | commander | +| `src/agent_comms/thread_management.py:32` | `agent_comms.collaboration_ledger` | registry | commander | +| `src/agent_comms/thread_management.py:33` | `agent_comms.config_options` | registry | commander | +| `src/agent_comms/thread_management.py:34` | `agent_comms.errors` | registry | commander | +| `src/agent_comms/thread_management.py:36` | `agent_comms.importing` | registry | commander | +| `src/agent_comms/thread_management.py:37` | `agent_comms.launch_runtime` | registry | commander | +| `src/agent_comms/thread_management.py:39` | `agent_comms.native_arguments` | registry | runtime | +| `src/agent_comms/thread_management.py:40` | `agent_comms.native_settings` | registry | runtime | +| `src/agent_comms/thread_management.py:42` | `agent_comms.pi_vocabulary` | registry | runtime | +| `src/agent_comms/thread_management.py:44` | `agent_comms.session_file` | registry | turns | +| `src/agent_comms/thread_management.py:45` | `agent_comms.store_files` | registry | commander | +| `src/agent_comms/thread_management.py:50` | `agent_comms.tool_result` | registry | cli | +| `src/agent_comms/thread_management.py:51` | `agent_comms.threads` | registry | commander | +| `src/agent_comms/thread_management.py:485` | `agent_comms.goal_waits` | registry | coordination | +| `src/agent_comms/thread_management.py:486` | `agent_comms.relationships` | registry | commander | +| `src/agent_comms/thread_management.py:487` | `agent_comms.view_unread` | registry | commander | | `src/agent_comms/thread_model.py:10` | `agent_comms.native_arguments` | registry | runtime | | `src/agent_comms/thread_model.py:11` | `agent_comms.native_failures` | registry | runtime | -| `src/agent_comms/thread_model.py:15` | `agent_comms.pi_commands` | registry | runtime | +| `src/agent_comms/thread_model.py:15` | `agent_comms.native_arguments` | registry | runtime | +| `src/agent_comms/thread_model.py:16` | `agent_comms.pi_commands` | registry | runtime | | `src/agent_comms/thread_owned_state.py:9` | `agent_comms.store_files` | registry | commander | | `src/agent_comms/thread_owned_state.py:10` | `agent_comms.errors` | registry | commander | | `src/agent_comms/thread_owned_state.py:13` | `agent_comms.threads` | registry | commander | @@ -1432,125 +1500,129 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/thread_status.py:30` | `agent_comms.threads` | registry | commander | | `src/agent_comms/thread_status.py:31` | `agent_comms.tool_caller` | registry | cli | | `src/agent_comms/thread_status.py:32` | `agent_comms.turn_lease` | registry | turns | -| `src/agent_comms/thread_status.py:123` | `agent_comms.turn_lease` | registry | turns | -| `src/agent_comms/thread_status.py:210` | `agent_comms.turn_lease` | registry | turns | +| `src/agent_comms/thread_status.py:130` | `agent_comms.turn_lease` | registry | turns | +| `src/agent_comms/thread_status.py:218` | `agent_comms.turn_lease` | registry | turns | | `src/agent_comms/threads.py:15` | `agent_comms.cli_result` | commander | cli | -| `src/agent_comms/todos.py:75` | `agent_comms.tool_denial` | commander | cli | +| `src/agent_comms/todos.py:79` | `agent_comms.tool_denial` | commander | cli | | `src/agent_comms/tool_caller.py:10` | `agent_comms.errors` | cli | commander | | `src/agent_comms/tool_caller.py:12` | `agent_comms.launch_root` | cli | commander | | `src/agent_comms/tool_caller.py:13` | `agent_comms.launch_runtime` | cli | commander | | `src/agent_comms/tool_caller.py:14` | `agent_comms.presentation` | cli | commander | | `src/agent_comms/tool_caller.py:19` | `agent_comms.comms` | cli | commander | | `src/agent_comms/tool_caller.py:20` | `agent_comms.registration` | cli | commander | -| `src/agent_comms/tool_caller.py:21` | `agent_comms.threads` | cli | commander | -| `src/agent_comms/tool_calls.py:23` | `agent_comms.transcript_events` | cli | commander | +| `src/agent_comms/tool_caller.py:21` | `agent_comms.head_review` | cli | commander | +| `src/agent_comms/tool_caller.py:22` | `agent_comms.todos` | cli | commander | +| `src/agent_comms/tool_caller.py:23` | `agent_comms.threads` | cli | commander | +| `src/agent_comms/tool_calls.py:24` | `agent_comms.transcript_events` | cli | commander | +| `src/agent_comms/tool_request.py:13` | `agent_comms.comms` | cli | commander | +| `src/agent_comms/tool_request.py:15` | `agent_comms.errors` | cli | commander | | `src/agent_comms/tool_results.py:15` | `agent_comms.transcript_events` | cli | commander | | `src/agent_comms/tool_results.py:96` | `agent_comms.transcript_events` | cli | commander | -| `src/agent_comms/tools.py:19` | `agent_comms.todos` | cli | commander | -| `src/agent_comms/tools.py:39` | `agent_comms.change_report` | cli | commander | -| `src/agent_comms/tools.py:42` | `agent_comms.channels` | cli | commander | -| `src/agent_comms/tools.py:59` | `agent_comms.commander.vibe_check` | cli | commander | -| `src/agent_comms/tools.py:60` | `agent_comms.commander_hud` | cli | commander | -| `src/agent_comms/tools.py:63` | `agent_comms.display_order` | cli | commander | -| `src/agent_comms/tools.py:64` | `agent_comms.errors` | cli | commander | -| `src/agent_comms/tools.py:83` | `agent_comms.heartbeat_frame` | cli | commander | -| `src/agent_comms/tools.py:98` | `agent_comms.goals` | cli | commander | -| `src/agent_comms/tools.py:99` | `agent_comms.history_result` | cli | commander | -| `src/agent_comms/tools.py:101` | `agent_comms.launch_runtime` | cli | commander | -| `src/agent_comms/tools.py:105` | `agent_comms.messages` | cli | commander | -| `src/agent_comms/tools.py:107` | `agent_comms.order_story` | cli | commander | -| `src/agent_comms/tools.py:108` | `agent_comms.order_work` | cli | commander | -| `src/agent_comms/tools.py:110` | `agent_comms.page_traversal` | cli | commander | -| `src/agent_comms/tools.py:113` | `agent_comms.plan_phases` | cli | commander | -| `src/agent_comms/tools.py:114` | `agent_comms.presentation` | cli | commander | -| `src/agent_comms/tools.py:115` | `agent_comms.progress_claims` | cli | commander | -| `src/agent_comms/tools.py:116` | `agent_comms.read_basis` | cli | commander | -| `src/agent_comms/tools.py:117` | `agent_comms.relationships` | cli | commander | -| `src/agent_comms/tools.py:123` | `agent_comms.restart_queue` | cli | commander | -| `src/agent_comms/tools.py:126` | `agent_comms.restart_queue` | cli | commander | -| `src/agent_comms/tools.py:129` | `agent_comms.restart_queue` | cli | commander | -| `src/agent_comms/tools.py:132` | `agent_comms.restart_queue` | cli | commander | -| `src/agent_comms/tools.py:135` | `agent_comms.send_result` | cli | commander | -| `src/agent_comms/tools.py:136` | `agent_comms.standing_rules` | cli | commander | -| `src/agent_comms/tools.py:137` | `agent_comms.task_sources` | cli | commander | -| `src/agent_comms/tools.py:148` | `agent_comms.order_story` | cli | commander | -| `src/agent_comms/tools.py:149` | `agent_comms.order_work` | cli | commander | -| `src/agent_comms/tools.py:151` | `agent_comms.progress_claims` | cli | commander | -| `src/agent_comms/tools.py:152` | `agent_comms.relationships` | cli | commander | -| `src/agent_comms/tools.py:163` | `agent_comms.threads` | cli | commander | -| `src/agent_comms/tools.py:167` | `agent_comms.transcript_events` | cli | commander | -| `src/agent_comms/tools.py:176` | `agent_comms.ui_model.unit_state` | cli | ui_model | -| `src/agent_comms/tools.py:177` | `agent_comms.work_branches` | cli | commander | -| `src/agent_comms/tools.py:180` | `agent_comms.comms` | cli | commander | -| `src/agent_comms/tracked_turn.py:42` | `agent_comms.tool_denial` | commander | cli | -| `src/agent_comms/transcript_events.py:15` | `agent_comms.tool_declaration` | commander | cli | -| `src/agent_comms/transcript_events.py:22` | `agent_comms.tool_results` | commander | cli | +| `src/agent_comms/tools.py:8` | `agent_comms.order_tools` | cli | commander | +| `src/agent_comms/tools.py:25` | `agent_comms.change_report` | cli | commander | +| `src/agent_comms/tools.py:28` | `agent_comms.channels` | cli | commander | +| `src/agent_comms/tools.py:47` | `agent_comms.display_order` | cli | commander | +| `src/agent_comms/tools.py:48` | `agent_comms.errors` | cli | commander | +| `src/agent_comms/tools.py:66` | `agent_comms.goals` | cli | commander | +| `src/agent_comms/tools.py:67` | `agent_comms.history_result` | cli | commander | +| `src/agent_comms/tools.py:71` | `agent_comms.messages` | cli | commander | +| `src/agent_comms/tools.py:74` | `agent_comms.page_traversal` | cli | commander | +| `src/agent_comms/tools.py:77` | `agent_comms.presentation` | cli | commander | +| `src/agent_comms/tools.py:78` | `agent_comms.progress_claims` | cli | commander | +| `src/agent_comms/tools.py:79` | `agent_comms.read_basis` | cli | commander | +| `src/agent_comms/tools.py:80` | `agent_comms.relationships` | cli | commander | +| `src/agent_comms/tools.py:86` | `agent_comms.restart_queue` | cli | commander | +| `src/agent_comms/tools.py:89` | `agent_comms.restart_queue` | cli | commander | +| `src/agent_comms/tools.py:92` | `agent_comms.restart_queue` | cli | commander | +| `src/agent_comms/tools.py:95` | `agent_comms.restart_queue` | cli | commander | +| `src/agent_comms/tools.py:98` | `agent_comms.send_result` | cli | commander | +| `src/agent_comms/tools.py:99` | `agent_comms.task_sources` | cli | commander | +| `src/agent_comms/tools.py:111` | `agent_comms.progress_claims` | cli | commander | +| `src/agent_comms/tools.py:112` | `agent_comms.relationships` | cli | commander | +| `src/agent_comms/tools.py:116` | `agent_comms.threads` | cli | commander | +| `src/agent_comms/tools.py:119` | `agent_comms.work_branches` | cli | commander | +| `src/agent_comms/tools.py:122` | `agent_comms.comms` | cli | commander | +| `src/agent_comms/tracked_turn.py:46` | `agent_comms.tool_denial` | commander | cli | +| `src/agent_comms/transcript_events.py:14` | `agent_comms.tool_declaration` | commander | cli | +| `src/agent_comms/transcript_events.py:21` | `agent_comms.tool_results` | commander | cli | | `src/agent_comms/transcript_events.py:24` | `agent_comms.ui_model.message_category` | commander | ui_model | | `src/agent_comms/transcript_updates.py:21` | `agent_comms.ui_model.observation` | commander | ui_model | | `src/agent_comms/turn_context.py:19` | `agent_comms.cli_result` | turns | cli | -| `src/agent_comms/turn_context.py:30` | `agent_comms.goals` | turns | commander | -| `src/agent_comms/turn_context.py:32` | `agent_comms.native_session_reopen` | turns | runtime | -| `src/agent_comms/turn_context.py:35` | `agent_comms.tool_result` | turns | cli | -| `src/agent_comms/turn_context.py:38` | `agent_comms.context_store` | turns | commander | -| `src/agent_comms/turn_context.py:40` | `agent_comms.presentation` | turns | commander | -| `src/agent_comms/turn_context.py:41` | `agent_comms.relationships` | turns | commander | -| `src/agent_comms/turn_context.py:42` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/turn_context.py:80` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_context.py:116` | `agent_comms.cli_bridges.codex_rollout` | turns | runtime | -| `src/agent_comms/turn_context.py:938` | `agent_comms.pi_payloads` | turns | runtime | -| `src/agent_comms/turn_context.py:943` | `agent_comms.pi_payloads` | turns | runtime | -| `src/agent_comms/turn_context.py:963` | `agent_comms.pi_payloads` | turns | runtime | -| `src/agent_comms/turn_digests.py:12` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_digests.py:13` | `agent_comms.external_transcript` | turns | commander | -| `src/agent_comms/turn_digests.py:14` | `agent_comms.order_work` | turns | commander | -| `src/agent_comms/turn_digests.py:17` | `agent_comms.tool_declaration` | turns | cli | -| `src/agent_comms/turn_digests.py:18` | `agent_comms.tool_result` | turns | cli | -| `src/agent_comms/turn_digests.py:19` | `agent_comms.bus` | turns | commander | -| `src/agent_comms/turn_digests.py:20` | `agent_comms.context_store` | turns | commander | -| `src/agent_comms/turn_digests.py:21` | `agent_comms.transcript_events` | turns | commander | -| `src/agent_comms/turn_digests.py:24` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/turn_digests.py:26` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/turn_digests.py:27` | `agent_comms.transcript_sources` | turns | commander | -| `src/agent_comms/turn_digests.py:28` | `agent_comms.todos` | turns | commander | +| `src/agent_comms/turn_context.py:31` | `agent_comms.goals` | turns | commander | +| `src/agent_comms/turn_context.py:33` | `agent_comms.native_session_reopen` | turns | runtime | +| `src/agent_comms/turn_context.py:36` | `agent_comms.tool_result` | turns | cli | +| `src/agent_comms/turn_context.py:39` | `agent_comms.context_store` | turns | commander | +| `src/agent_comms/turn_context.py:41` | `agent_comms.presentation` | turns | commander | +| `src/agent_comms/turn_context.py:42` | `agent_comms.relationships` | turns | commander | +| `src/agent_comms/turn_context.py:43` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_context.py:81` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_context.py:117` | `agent_comms.cli_bridges.codex_rollout` | turns | runtime | +| `src/agent_comms/turn_context.py:939` | `agent_comms.pi_payloads` | turns | runtime | +| `src/agent_comms/turn_context.py:944` | `agent_comms.pi_payloads` | turns | runtime | +| `src/agent_comms/turn_context.py:964` | `agent_comms.pi_payloads` | turns | runtime | +| `src/agent_comms/turn_digests.py:13` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_digests.py:14` | `agent_comms.external_transcript` | turns | commander | +| `src/agent_comms/turn_digests.py:15` | `agent_comms.held_orders` | turns | commander | +| `src/agent_comms/turn_digests.py:16` | `agent_comms.order_work` | turns | commander | +| `src/agent_comms/turn_digests.py:19` | `agent_comms.tool_declaration` | turns | cli | +| `src/agent_comms/turn_digests.py:20` | `agent_comms.tool_result` | turns | cli | +| `src/agent_comms/turn_digests.py:21` | `agent_comms.bus` | turns | commander | +| `src/agent_comms/turn_digests.py:22` | `agent_comms.context_store` | turns | commander | +| `src/agent_comms/turn_digests.py:23` | `agent_comms.transcript_events` | turns | commander | +| `src/agent_comms/turn_digests.py:26` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/turn_digests.py:27` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_digests.py:28` | `agent_comms.transcript_sources` | turns | commander | +| `src/agent_comms/turn_digests.py:29` | `agent_comms.todos` | turns | commander | +| `src/agent_comms/turn_digests.py:198` | `agent_comms.todos` | turns | commander | | `src/agent_comms/turn_effects.py:11` | `agent_comms.runtime` | turns | runtime | -| `src/agent_comms/turn_failure.py:10` | `agent_comms.native_arguments` | turns | runtime | -| `src/agent_comms/turn_failure.py:13` | `agent_comms.backend` | turns | commander | -| `src/agent_comms/turn_failure.py:43` | `agent_comms.native_failures` | turns | runtime | -| `src/agent_comms/turn_failure.py:114` | `agent_comms.native_pi` | turns | runtime | -| `src/agent_comms/turn_goal_account.py:9` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_goal_account.py:22` | `agent_comms.agent_events` | turns | runtime | -| `src/agent_comms/turn_goal_account.py:24` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/turn_goal_account.py:25` | `agent_comms.goals` | turns | commander | -| `src/agent_comms/turn_goal_account.py:26` | `agent_comms.pi_payloads` | turns | runtime | -| `src/agent_comms/turn_goal_account.py:28` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/turn_goal_permission.py:9` | `agent_comms.ordinary_turn_rules` | turns | commander | -| `src/agent_comms/turn_goal_permission.py:11` | `agent_comms.tool_denial` | turns | cli | -| `src/agent_comms/turn_goal_permission.py:15` | `agent_comms.goals` | turns | commander | -| `src/agent_comms/turn_input_source.py:10` | `agent_comms.agent_backend` | turns | runtime | -| `src/agent_comms/turn_input_source.py:12` | `agent_comms.messages` | turns | commander | -| `src/agent_comms/turn_input_source.py:13` | `agent_comms.started_input` | turns | commander | -| `src/agent_comms/turn_input_source.py:17` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/turn_input_source.py:19` | `agent_comms.goals` | turns | commander | -| `src/agent_comms/turn_input_source.py:22` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_failure.py:12` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_failure.py:13` | `agent_comms.native_arguments` | turns | runtime | +| `src/agent_comms/turn_failure.py:16` | `agent_comms.backend` | turns | commander | +| `src/agent_comms/turn_failure.py:48` | `agent_comms.native_failures` | turns | runtime | +| `src/agent_comms/turn_failure.py:130` | `agent_comms.native_pi` | turns | runtime | +| `src/agent_comms/turn_goal_account.py:11` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_goal_account.py:25` | `agent_comms.agent_events` | turns | runtime | +| `src/agent_comms/turn_goal_account.py:27` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/turn_goal_account.py:28` | `agent_comms.goals` | turns | commander | +| `src/agent_comms/turn_goal_account.py:29` | `agent_comms.pi_payloads` | turns | runtime | +| `src/agent_comms/turn_goal_account.py:30` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_goal_permission.py:10` | `agent_comms.ordinary_turn_rules` | turns | commander | +| `src/agent_comms/turn_goal_permission.py:12` | `agent_comms.tool_denial` | turns | cli | +| `src/agent_comms/turn_goal_permission.py:16` | `agent_comms.goals` | turns | commander | +| `src/agent_comms/turn_input_source.py:14` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/turn_input_source.py:15` | `agent_comms.agent_backend` | turns | runtime | +| `src/agent_comms/turn_input_source.py:20` | `agent_comms.messages` | turns | commander | +| `src/agent_comms/turn_input_source.py:21` | `agent_comms.ordinary_turn_rules` | turns | commander | +| `src/agent_comms/turn_input_source.py:28` | `agent_comms.routing` | turns | commander | +| `src/agent_comms/turn_input_source.py:30` | `agent_comms.started_input` | turns | commander | +| `src/agent_comms/turn_input_source.py:33` | `agent_comms.acp_extension` | turns | runtime | +| `src/agent_comms/turn_input_source.py:34` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/turn_input_source.py:35` | `agent_comms.controller` | turns | runtime | +| `src/agent_comms/turn_input_source.py:37` | `agent_comms.goals` | turns | commander | +| `src/agent_comms/turn_input_source.py:40` | `agent_comms.owned_send` | turns | commander | +| `src/agent_comms/turn_input_source.py:41` | `agent_comms.runtime` | turns | runtime | +| `src/agent_comms/turn_input_source.py:43` | `agent_comms.threads` | turns | commander | | `src/agent_comms/turn_inputs.py:13` | `agent_comms.pi_payloads` | turns | runtime | | `src/agent_comms/turn_inputs.py:15` | `agent_comms.agent_events` | turns | runtime | | `src/agent_comms/turn_inputs.py:16` | `agent_comms.pi_commands` | turns | runtime | | `src/agent_comms/turn_inputs.py:17` | `agent_comms.agent_backend` | turns | runtime | -| `src/agent_comms/turn_inputs.py:27` | `agent_comms.locked_store` | turns | commander | -| `src/agent_comms/turn_inputs.py:28` | `agent_comms.maintenance_barrier` | turns | commander | -| `src/agent_comms/turn_inputs.py:30` | `agent_comms.native_failures` | turns | runtime | -| `src/agent_comms/turn_inputs.py:31` | `agent_comms.prompt_state` | turns | commander | -| `src/agent_comms/turn_inputs.py:34` | `agent_comms.backend` | turns | commander | -| `src/agent_comms/turn_inputs.py:35` | `agent_comms.pi_events` | turns | runtime | +| `src/agent_comms/turn_inputs.py:19` | `agent_comms.locked_store` | turns | commander | +| `src/agent_comms/turn_inputs.py:20` | `agent_comms.maintenance_barrier` | turns | commander | +| `src/agent_comms/turn_inputs.py:22` | `agent_comms.native_failures` | turns | runtime | +| `src/agent_comms/turn_inputs.py:23` | `agent_comms.prompt_state` | turns | commander | +| `src/agent_comms/turn_inputs.py:26` | `agent_comms.backend` | turns | commander | +| `src/agent_comms/turn_inputs.py:27` | `agent_comms.pi_events` | turns | runtime | | `src/agent_comms/turn_lease.py:12` | `agent_comms.activity` | turns | commander | -| `src/agent_comms/turn_lease.py:13` | `agent_comms.child_process` | turns | commander | -| `src/agent_comms/turn_lease.py:14` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_lease.py:26` | `agent_comms.locked_store` | turns | commander | -| `src/agent_comms/turn_lease.py:27` | `agent_comms.routing` | turns | commander | -| `src/agent_comms/turn_lease.py:28` | `agent_comms.store_files` | turns | commander | -| `src/agent_comms/turn_lease.py:35` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/turn_origin.py:9` | `agent_comms.messages` | turns | commander | -| `src/agent_comms/turn_origin.py:10` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_lease.py:14` | `agent_comms.child_process` | turns | commander | +| `src/agent_comms/turn_lease.py:16` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_lease.py:29` | `agent_comms.locked_store` | turns | commander | +| `src/agent_comms/turn_lease.py:31` | `agent_comms.read_basis` | turns | commander | +| `src/agent_comms/turn_lease.py:33` | `agent_comms.routing` | turns | commander | +| `src/agent_comms/turn_lease.py:34` | `agent_comms.store_files` | turns | commander | +| `src/agent_comms/turn_lease.py:46` | `agent_comms.messaging` | turns | commander | +| `src/agent_comms/turn_lease.py:48` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_origin.py:11` | `agent_comms.messages` | turns | commander | +| `src/agent_comms/turn_origin.py:12` | `agent_comms.threads` | turns | commander | | `src/agent_comms/turn_output.py:9` | `agent_comms.agent_events` | turns | runtime | | `src/agent_comms/turn_output.py:11` | `agent_comms.acp_failure` | turns | runtime | | `src/agent_comms/turn_output.py:17` | `agent_comms.native_arguments` | turns | runtime | @@ -1571,37 +1643,37 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/turn_progress.py:26` | `agent_comms.send_result` | turns | commander | | `src/agent_comms/turn_progress.py:28` | `agent_comms.transcript_updates` | turns | commander | | `src/agent_comms/turn_progress.py:33` | `agent_comms.owned_turn` | turns | commander | -| `src/agent_comms/turn_runner.py:17` | `agent_comms.agent_events` | turns | runtime | -| `src/agent_comms/turn_runner.py:18` | `agent_comms.agent_backend` | turns | runtime | -| `src/agent_comms/turn_runner.py:19` | `agent_comms.agent_event_updates` | turns | runtime | -| `src/agent_comms/turn_runner.py:21` | `agent_comms.channels` | turns | commander | -| `src/agent_comms/turn_runner.py:22` | `agent_comms.controller` | turns | runtime | -| `src/agent_comms/turn_runner.py:23` | `agent_comms.coordinator` | turns | commander | -| `src/agent_comms/turn_runner.py:24` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_runner.py:25` | `agent_comms.following_inputs` | turns | commander | -| `src/agent_comms/turn_runner.py:34` | `agent_comms.messages` | turns | commander | -| `src/agent_comms/turn_runner.py:36` | `agent_comms.native_arguments` | turns | runtime | -| `src/agent_comms/turn_runner.py:37` | `agent_comms.native_input_owner` | turns | runtime | -| `src/agent_comms/turn_runner.py:38` | `agent_comms.pi_payloads` | turns | runtime | -| `src/agent_comms/turn_runner.py:39` | `agent_comms.queued_input` | turns | commander | -| `src/agent_comms/turn_runner.py:40` | `agent_comms.routing` | turns | commander | -| `src/agent_comms/turn_runner.py:41` | `agent_comms.runtime` | turns | runtime | -| `src/agent_comms/turn_runner.py:45` | `agent_comms.threads` | turns | commander | -| `src/agent_comms/turn_runner.py:46` | `agent_comms.transcript_updates` | turns | commander | -| `src/agent_comms/turn_runner.py:54` | `agent_comms.pi_events` | turns | runtime | -| `src/agent_comms/turn_runner.py:55` | `agent_comms.comms` | turns | commander | -| `src/agent_comms/turn_runner.py:56` | `agent_comms.coordinated_runtime` | turns | commander | -| `src/agent_comms/turn_runner.py:165` | `agent_comms.pi_commands` | turns | runtime | -| `src/agent_comms/turn_runner.py:170` | `agent_comms.pi_commands` | turns | runtime | -| `src/agent_comms/turn_runner.py:281` | `agent_comms.pi_events` | turns | runtime | -| `src/agent_comms/turn_runner.py:445` | `agent_comms.owned_turn` | turns | commander | +| `src/agent_comms/turn_runner.py:19` | `agent_comms.agent_events` | turns | runtime | +| `src/agent_comms/turn_runner.py:20` | `agent_comms.agent_backend` | turns | runtime | +| `src/agent_comms/turn_runner.py:21` | `agent_comms.agent_event_updates` | turns | runtime | +| `src/agent_comms/turn_runner.py:23` | `agent_comms.channels` | turns | commander | +| `src/agent_comms/turn_runner.py:24` | `agent_comms.controller` | turns | runtime | +| `src/agent_comms/turn_runner.py:25` | `agent_comms.coordinator` | turns | commander | +| `src/agent_comms/turn_runner.py:27` | `agent_comms.errors` | turns | commander | +| `src/agent_comms/turn_runner.py:28` | `agent_comms.following_inputs` | turns | commander | +| `src/agent_comms/turn_runner.py:37` | `agent_comms.messages` | turns | commander | +| `src/agent_comms/turn_runner.py:39` | `agent_comms.native_arguments` | turns | runtime | +| `src/agent_comms/turn_runner.py:40` | `agent_comms.native_input_owner` | turns | runtime | +| `src/agent_comms/turn_runner.py:41` | `agent_comms.pi_payloads` | turns | runtime | +| `src/agent_comms/turn_runner.py:42` | `agent_comms.queued_input` | turns | commander | +| `src/agent_comms/turn_runner.py:43` | `agent_comms.routing` | turns | commander | +| `src/agent_comms/turn_runner.py:44` | `agent_comms.runtime` | turns | runtime | +| `src/agent_comms/turn_runner.py:48` | `agent_comms.threads` | turns | commander | +| `src/agent_comms/turn_runner.py:49` | `agent_comms.transcript_updates` | turns | commander | +| `src/agent_comms/turn_runner.py:58` | `agent_comms.pi_events` | turns | runtime | +| `src/agent_comms/turn_runner.py:59` | `agent_comms.comms` | turns | commander | +| `src/agent_comms/turn_runner.py:60` | `agent_comms.coordinated_runtime` | turns | commander | +| `src/agent_comms/turn_runner.py:169` | `agent_comms.pi_commands` | turns | runtime | +| `src/agent_comms/turn_runner.py:174` | `agent_comms.pi_commands` | turns | runtime | +| `src/agent_comms/turn_runner.py:285` | `agent_comms.pi_events` | turns | runtime | +| `src/agent_comms/turn_runner.py:449` | `agent_comms.owned_turn` | turns | commander | | `src/agent_comms/turn_stats.py:11` | `agent_comms.pi_payloads` | turns | runtime | | `src/agent_comms/turn_stats.py:13` | `agent_comms.agent_events` | turns | runtime | | `src/agent_comms/turn_stats.py:14` | `agent_comms.pi_commands` | turns | runtime | | `src/agent_comms/turn_stats.py:18` | `agent_comms.backend` | turns | commander | | `src/agent_comms/turn_stats.py:19` | `agent_comms.pi_events` | turns | runtime | -| `src/agent_comms/turn_terminal.py:5` | `agent_comms.errors` | turns | commander | -| `src/agent_comms/turn_terminal.py:15` | `agent_comms.agent_events` | turns | runtime | +| `src/agent_comms/turn_terminal.py:13` | `agent_comms.agent_events` | turns | runtime | +| `src/agent_comms/turn_terminal.py:15` | `agent_comms.maintenance_barrier` | turns | commander | | `src/agent_comms/turn_usage.py:7` | `agent_comms.agent_events` | turns | runtime | | `src/agent_comms/turn_usage.py:8` | `agent_comms.pi_counts` | turns | runtime | | `src/agent_comms/turn_usage.py:9` | `agent_comms.pi_payloads` | turns | runtime | @@ -1613,20 +1685,20 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/ui_model/goal.py:11` | `agent_comms.goals` | ui_model | commander | | `src/agent_comms/ui_model/observation.py:36` | `agent_comms.active_route` | ui_model | commander | | `src/agent_comms/ui_model/observation.py:37` | `agent_comms.activity` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:45` | `agent_comms.errors` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:47` | `agent_comms.presentation` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:59` | `agent_comms.view_unread` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:66` | `agent_comms.comms` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:67` | `agent_comms.history_views` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:69` | `agent_comms.presentation` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:73` | `agent_comms.transcripts` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:557` | `agent_comms.historical_views` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:1215` | `agent_comms.watched` | ui_model | commander | -| `src/agent_comms/ui_model/observation.py:1296` | `agent_comms.comms` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:38` | `agent_comms.commander_hud` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:46` | `agent_comms.errors` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:48` | `agent_comms.presentation` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:66` | `agent_comms.view_unread` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:73` | `agent_comms.comms` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:74` | `agent_comms.history_views` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:76` | `agent_comms.presentation` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:80` | `agent_comms.transcripts` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:584` | `agent_comms.historical_views` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:1277` | `agent_comms.watched` | ui_model | commander | +| `src/agent_comms/ui_model/observation.py:1358` | `agent_comms.comms` | ui_model | commander | | `src/agent_comms/ui_model/sidebar.py:14` | `agent_comms.read_ledger` | ui_model | commander | | `src/agent_comms/ui_model/sidebar.py:17` | `agent_comms.display_order` | ui_model | commander | | `src/agent_comms/ui_model/sidebar.py:18` | `agent_comms.presentation` | ui_model | commander | -| `src/agent_comms/ui_model/unit_state.py:18` | `agent_comms.commander.questions` | ui_model | commander | | `src/agent_comms/ui_model/unit_state.py:21` | `agent_comms.messages` | ui_model | commander | | `src/agent_comms/ui_model/unit_state.py:23` | `agent_comms.repo` | ui_model | commander | | `src/agent_comms/ui_model/unit_state.py:24` | `agent_comms.standing_rules` | ui_model | commander | @@ -1639,13 +1711,13 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/ui_model/unread.py:10` | `agent_comms.presentation` | ui_model | commander | | `src/agent_comms/view_unread.py:35` | `agent_comms.ui_model.unread` | commander | ui_model | | `src/agent_comms/wake_candidate_index.py:9` | `agent_comms.bus` | coordination | commander | -| `src/agent_comms/wake_policy.py:11` | `agent_comms.coordinator_vocabulary` | coordination | commander | -| `src/agent_comms/wake_policy.py:14` | `agent_comms.source_proof_requirement` | coordination | commander | -| `src/agent_comms/wake_policy.py:20` | `agent_comms.typed_table` | coordination | commander | -| `src/agent_comms/wake_policy.py:177` | `agent_comms.turn_context` | coordination | turns | -| `src/agent_comms/wake_policy.py:195` | `agent_comms.assignment_states` | coordination | commander | -| `src/agent_comms/wake_policy.py:223` | `agent_comms.assignment_states` | coordination | commander | -| `src/agent_comms/wake_policy.py:235` | `agent_comms.assignment_states` | coordination | commander | +| `src/agent_comms/wake_policy.py:13` | `agent_comms.coordinator_vocabulary` | coordination | commander | +| `src/agent_comms/wake_policy.py:16` | `agent_comms.source_proof_requirement` | coordination | commander | +| `src/agent_comms/wake_policy.py:22` | `agent_comms.typed_table` | coordination | commander | +| `src/agent_comms/wake_policy.py:182` | `agent_comms.turn_context` | coordination | turns | +| `src/agent_comms/wake_policy.py:200` | `agent_comms.assignment_states` | coordination | commander | +| `src/agent_comms/wake_policy.py:228` | `agent_comms.assignment_states` | coordination | commander | +| `src/agent_comms/wake_policy.py:240` | `agent_comms.assignment_states` | coordination | commander | | `src/agent_comms/wire_models.py:11` | `agent_comms.declared_family` | wire | registry | | `src/agent_comms/working_memory_annotations.py:8` | `agent_comms.errors` | context | commander | | `src/agent_comms/working_memory_disclosure.py:9` | `agent_comms.turn_context` | context | turns | @@ -1682,12 +1754,16 @@ Units the git sources in `stack/pyproject.toml` import directly, read at each br | `child_process` | batrachian-toad | | `cli_bridges` | batrachian-toad | | `cli_commands` | batrachian-toad | +| `cli_protocol` | batrachian-toad | | `cli_result` | batrachian-toad | | `command` | batrachian-toad | +| `commander` | batrachian-toad | +| `commander_hud` | batrachian-toad | | `comms` | batrachian-toad, textual | | `config_options` | batrachian-toad | | `context_reading` | batrachian-toad | | `context_store` | batrachian-toad | +| `controller` | batrachian-toad | | `coordination_errors` | batrachian-toad | | `coordinator` | batrachian-toad | | `declared_family` | batrachian-toad | @@ -1700,6 +1776,7 @@ Units the git sources in `stack/pyproject.toml` import directly, read at each br | `field_codec` | batrachian-toad | | `fresh_private_session` | batrachian-toad | | `goal_actions` | batrachian-toad | +| `goal_history` | batrachian-toad | | `goal_mentions` | batrachian-toad | | `goal_presentation` | batrachian-toad | | `goal_states` | batrachian-toad | @@ -1707,6 +1784,7 @@ Units the git sources in `stack/pyproject.toml` import directly, read at each br | `harness_install` | batrachian-toad | | `historical_views` | batrachian-toad | | `history_views` | batrachian-toad | +| `image_input` | batrachian-toad | | `image_inputs` | batrachian-toad | | `importing` | batrachian-toad | | `input_attempt` | batrachian-toad | @@ -1744,16 +1822,21 @@ Units the git sources in `stack/pyproject.toml` import directly, read at each br | `registry_document` | batrachian-toad | | `registry_store` | batrachian-toad | | `relationships` | batrachian-toad | +| `reported_turn` | batrachian-toad | +| `restart_refusals` | batrachian-toad | | `retained_task_facts` | batrachian-toad | | `revision_views` | batrachian-toad | +| `root_runtime` | batrachian-toad | | `route_selection` | batrachian-toad | | `routing` | batrachian-toad | | `runtime` | batrachian-toad | +| `runtime_requests` | batrachian-toad | | `selected_triage` | batrachian-toad | | `sent_message` | batrachian-toad | | `session_file` | batrachian-toad | | `session_load` | batrachian-toad | | `session_revision` | batrachian-toad | +| `thread_creation` | batrachian-toad | | `thread_execution` | batrachian-toad | | `thread_identity` | batrachian-toad | | `thread_model` | batrachian-toad | @@ -1761,6 +1844,7 @@ Units the git sources in `stack/pyproject.toml` import directly, read at each br | `thread_status` | batrachian-toad | | `thread_text` | batrachian-toad | | `threads` | batrachian-toad, textual | +| `tool_caller` | batrachian-toad | | `tool_results` | batrachian-toad | | `tools` | batrachian-toad | | `transcript_events` | batrachian-toad | @@ -1781,5 +1865,5 @@ No console script in `pyproject.toml` and no stack client reaches these through - `behaviour_patterns` - `cli_native_package` -- `fleet_replay` +- `producer_stamp` - `skills` diff --git a/pyproject.toml b/pyproject.toml index cb47fae20d..006161c66b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -42,6 +42,7 @@ dev = [ "ruff==0.16.0", "mypy==2.3.0", "uv==0.13.1", + "nominal-refactor-advisor @ git+https://github.com/OpenHCSDev/NominalRefactorAdvisor@main", ] [project.urls] diff --git a/tests/test_module_layers_loads.py b/tests/test_module_layers_loads.py new file mode 100644 index 0000000000..3d85fb2058 --- /dev/null +++ b/tests/test_module_layers_loads.py @@ -0,0 +1,46 @@ +"""An import loads its target when its module loads, unless a function call or a type +checker is the only thing that runs it.""" + +from pathlib import Path + +from module_layers import Package + +SOURCES = { + "__init__.py": "", + "top.py": "", + "body.py": "", + "decorator.py": "", + "default.py": "", + "checked.py": "", + "user.py": ( + "from typing import TYPE_CHECKING\n" + "import importlib\n" + "from . import top\n" + "if TYPE_CHECKING:\n" + " from . import checked\n" + "@importlib.import_module('agent_comms.decorator').wrap\n" + "def f(\n" + " x=importlib.import_module('agent_comms.default'),\n" + " y=lambda: importlib.import_module('agent_comms.body'),\n" + "):\n" + " from . import body\n" + ), +} + + +def test_only_imports_that_run_while_the_module_loads_load_their_target(tmp_path: Path) -> None: + for name, source in SOURCES.items(): + path = tmp_path / "src" / "agent_comms" / name + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(source) + package = Package(tmp_path) + loads = { + edge.target: edge.loads for edge in package.imports if edge.source == "agent_comms.user" + } + assert loads == { + "agent_comms.top": True, + "agent_comms.decorator": True, + "agent_comms.default": True, + "agent_comms.checked": False, + "agent_comms.body": False, + } diff --git a/tests/test_repairs.py b/tests/test_repairs.py new file mode 100644 index 0000000000..b82e600503 --- /dev/null +++ b/tests/test_repairs.py @@ -0,0 +1,55 @@ +import subprocess +import sys +from pathlib import Path + +from repairs import ImportHoist + +PACKAGE = { + "__init__.py": "", + "leaf.py": "VALUE = 1\n", + "loop.py": "from .user import used\n\nLOOPED = used\n", + "user.py": ( + "def used():\n" + " from .leaf import VALUE\n" + "\n" + " return VALUE\n" + "\n" + "\n" + "def looped():\n" + " from .loop import LOOPED\n" + "\n" + " return LOOPED\n" + ), +} + + +def tree(root: Path) -> Path: + for name, source in PACKAGE.items(): + path = root / "src" / "agent_comms" / name + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(source) + return root + + +def test_a_local_import_moves_up_unless_a_load_time_import_leads_back(tmp_path: Path) -> None: + repo = tree(tmp_path) + hoist = ImportHoist(repo, ["src/agent_comms/user.py"]) + diff, changed = hoist.simulation() + assert changed == 1 + assert "+from .leaf import VALUE" in diff + assert "- from .leaf import VALUE" in diff + assert "- from .loop import LOOPED" not in diff + assert hoist.left == {"a module-level import cycle runs through it": 1} + + assert ImportHoist(repo, ["src/agent_comms/user.py"]).apply() == ("src/agent_comms/user.py",) + source = (repo / "src/agent_comms/user.py").read_text() + assert source.startswith("from .leaf import VALUE\n") + assert " from .loop import LOOPED\n" in source + loaded = subprocess.run( + [sys.executable, "-c", "import agent_comms.loop, agent_comms.user"], + cwd=repo, + env={"PYTHONPATH": str(repo / "src")}, + capture_output=True, + text=True, + ) + assert loaded.returncode == 0, loaded.stderr diff --git a/tools/module_layers.py b/tools/module_layers.py index dc723b6471..10f4b6addd 100644 --- a/tools/module_layers.py +++ b/tools/module_layers.py @@ -23,7 +23,9 @@ import sys import tempfile import tomllib +import typing from abc import ABC, abstractmethod +from collections.abc import Iterable from dataclasses import dataclass from functools import cached_property from pathlib import Path @@ -61,13 +63,44 @@ def claims(self, module: str) -> bool: @dataclass(frozen=True) -class Import: - """One import statement inside agent_comms naming another agent_comms module.""" +class Import(ABC): + """One import statement inside agent_comms naming another agent_comms module. Its + class says when the statement runs.""" source: str target: str line: int + loads: typing.ClassVar[bool] + """Whether loading ``source`` runs it, so loading ``source`` loads ``target``.""" + + @classmethod + def in_function(cls) -> type[Import]: + """The class of an import written one function deeper.""" + return CallTimeImport + + +class LoadTimeImport(Import): + """At module level: it runs when its module loads.""" + + loads = True + + +class CallTimeImport(Import): + """Inside a function body: it runs when the function is called.""" + + loads = False + + +class CheckerImport(Import): + """Under ``if TYPE_CHECKING:``: only a type checker reads it.""" + + loads = False + + @classmethod + def in_function(cls) -> type[Import]: + return cls + class ModuleReferences(ast.NodeVisitor, ABC): """Reads a literal import_module call as an import of the module it names.""" @@ -92,11 +125,41 @@ def __init__(self, package: Package, module: str, path: Path, found: list[Import self.package, self.module, self.found = package, module, found # relative imports start at the file's own directory, a package's __init__ included self.parent = ".".join(path.parent.relative_to(package.src).parts) + self.runs: type[Import] = LoadTimeImport def record(self, node: ast.stmt | ast.expr, *names: str) -> None: for name in names: if (target := self.package.resolve(name)) is not None: - self.found.append(Import(self.module, target, node.lineno)) + self.found.append(self.runs(self.module, target, node.lineno)) + + def visit_within(self, runs: type[Import], nodes: list[ast.stmt] | list[ast.AST]) -> None: + outer, self.runs = self.runs, runs + for node in nodes: + self.visit(node) + self.runs = outer + + def visit_FunctionDef(self, node: ast.FunctionDef | ast.AsyncFunctionDef | ast.Lambda) -> None: + """Decorators, defaults and annotations run where the ``def`` runs; only the body + runs when the function is called. Wrapping the body in an Expression lets + iter_child_nodes yield a lambda's one expression and a def's statements alike.""" + called = list(ast.iter_child_nodes(ast.Expression(body=node.body))) + self.visit_within( + self.runs, + [child for child in ast.iter_child_nodes(node) if all(child is not c for c in called)], + ) + self.visit_within(self.runs.in_function(), called) + + # NodeVisitor dispatches on these names; one method serves all three scopes. + visit_AsyncFunctionDef = visit_Lambda = visit_FunctionDef # noqa: N815 + + def visit_If(self, node: ast.If) -> None: + match node.test: + case ast.Name(id="TYPE_CHECKING") | ast.Attribute(attr="TYPE_CHECKING"): + self.visit(node.test) + self.visit_within(CheckerImport, node.body) + self.visit_within(self.runs, node.orelse) + case _: + self.generic_visit(node) def visit_Import(self, node: ast.Import) -> None: self.record(node, *(alias.name for alias in node.names)) @@ -235,6 +298,32 @@ def imports(self) -> tuple[ClientImport, ...]: return tuple(found) +class ImportGraph: + """The modules reached from some modules through a set of import edges. Importing a + module imports every package above it first, so those are reached too.""" + + def __init__(self, edges: Iterable[Import]) -> None: + self.targets: dict[str, set[str]] = {} + for edge in edges: + self.add(edge.source, (edge.target,)) + + def add(self, source: str, targets: Iterable[str]) -> None: + self.targets.setdefault(source, set()).update(targets) + + def reached(self, starts: Iterable[str]) -> set[str]: + seen: set[str] = set() + todo = list(starts) + while todo: + module = todo.pop() + if module in seen: + continue + seen.add(module) + parts = module.split(".") + todo.extend(".".join(parts[:end]) for end in range(1, len(parts))) + todo.extend(self.targets.get(module, ())) + return seen + + class Package: """The agent_comms source tree: its modules, their imports and their layers.""" @@ -393,21 +482,14 @@ def client_surface(self) -> dict[str, set[str]]: def unreached(self) -> tuple[str, ...]: """Units no console script or stack client reaches through static imports, package __init__s included.""" - edges: dict[str, set[str]] = {} - for edge in self.imports: - edges.setdefault(edge.source, set()).add(edge.target) clients = (target for entry in self.client_imports for target in self.client_targets(entry)) - seen, todo = set(), [PACKAGE, *self.entry_points, *clients] - while todo: - module = todo.pop() - if module in seen: - continue - seen.add(module) - parts = module.split(".") - todo.extend(".".join(parts[:end]) for end in range(1, len(parts))) - todo.extend(edges.get(module, ())) + seen = ImportGraph(self.imports).reached([PACKAGE, *self.entry_points, *clients]) return tuple(unit for unit in self.top_level if not any(self.unit(m) == unit for m in seen)) + def load_graph(self) -> ImportGraph: + """The imports that run while modules load: a cycle through them deadlocks an import.""" + return ImportGraph(edge for edge in self.imports if edge.loads) + def markdown(self) -> str: lines = [ "# Module layers", diff --git a/tools/repairs.py b/tools/repairs.py new file mode 100644 index 0000000000..00e4b6f1d3 --- /dev/null +++ b/tools/repairs.py @@ -0,0 +1,326 @@ +"""Repairs for what the debt ratchet counts, built as Nominal Refactor Advisor plans. + +A repair declares the located measure whose occurrences it removes. It reads the files +of the working tree, writes one NRA operation per occurrence it can remove and keeps +every other occurrence with the reason it stays. NRA simulates the plan, so the diff +shows before any file changes; applying it goes through NRA's source-revision guards, +then the repository's import sorter over the touched files and Black over those Black +already accepted. + + python tools/repairs.py --root src --base origin/main --head HEAD + python tools/repairs.py --root src --all --apply +""" + +from __future__ import annotations + +import argparse +import ast +import subprocess +import sys +from abc import ABC, abstractmethod +from collections import Counter +from collections.abc import Iterable +from pathlib import Path +from typing import ClassVar + +from debt_ratchet import FunctionLocalImport, LocatedSource, compare, production_paths +from module_layers import Package, TopLevelNames +from nominal_refactor_advisor.codemod import ( + CodemodPlanSequence, + CodemodSourceSnapshot, + EnsureImportOperation, + PatchTargetOperation, + SourceRewriteTarget, + SourceTextReplacement, +) + +from agent_comms.declared_family import DeclaredFamily + +FUNCTIONS = (ast.FunctionDef, ast.AsyncFunctionDef) + + +class Repair(DeclaredFamily, ABC): + """One measure's repair over some files of the working tree.""" + + repairs: ClassVar[type[LocatedSource]] + + def __init__(self, repo: Path, paths: Iterable[str]) -> None: + self.repo, self.paths = repo, sorted(paths) + self.left: Counter[str] = Counter() + + @abstractmethod + def file_operations( + self, path: str, source: str + ) -> list[EnsureImportOperation | PatchTargetOperation]: + """The operations removing this file's occurrences; each one left is tallied in + ``left`` under the reason it stays.""" + + def sequence(self) -> CodemodPlanSequence: + return CodemodPlanSequence.from_operations( + tuple( + operation + for path in self.paths + for operation in self.file_operations(path, (self.repo / path).read_text()) + ) + ) + + def target(self, path: str, qualname: str | None = None) -> SourceRewriteTarget: + """A file of this repair's tree, named absolutely: NRA resolves a relative path + against the process directory, which need not be the tree.""" + return SourceRewriteTarget(file_path=str(self.repo / path), qualname=qualname) + + @staticmethod + def sources(sequence: CodemodPlanSequence) -> dict[str, str]: + return {path: Path(path).read_text() for path in sequence.explicit_source_paths()} + + def simulation(self) -> tuple[str, int]: + """NRA's diff of the plan and how many files it changes.""" + sequence = self.sequence() + if not sequence.explicit_source_paths(): + return "", 0 + sources = self.sources(sequence) + simulated = sequence.simulate(CodemodSourceSnapshot.from_source_mapping(sources)) + return simulated.unified_diff(sources), len(sources) + + def apply(self) -> tuple[str, ...]: + """Apply the plan; the touched files then take the repository's import order, and + those Black accepted before stay formatted.""" + sequence = self.sequence() + if not sequence.explicit_source_paths(): + return () + sources = self.sources(sequence) + touched = tuple(str(Path(path).relative_to(self.repo)) for path in sources) + formatted = [ + path for path in touched if self.tool("black", "--check", "-q", path).returncode == 0 + ] + sequence.simulate(CodemodSourceSnapshot.from_source_mapping(sources)).apply() + self.tool("ruff", "check", "--quiet", "--select", "I001", "--fix", *touched) + if formatted: + self.tool("black", "-q", *formatted) + return touched + + def tool(self, *arguments: str) -> subprocess.CompletedProcess[str]: + return subprocess.run( + [sys.executable, "-m", *arguments], cwd=self.repo, capture_output=True, text=True + ) + + +class ImportHoist(Repair): + """Moves a function-local import to its module top when no import that runs at module + load leads back to the module, judged with every move already accepted: two local + imports naming each other each pass alone and deadlock together.""" + + repairs = FunctionLocalImport + + def __init__(self, repo: Path, paths: Iterable[str]) -> None: + super().__init__(repo, paths) + self.package = Package(repo) + self.graph = self.package.load_graph() + self.modules = { + str(path.relative_to(repo)): module for module, path in self.package.files.items() + } + self.targets: dict[tuple[str, int], set[str]] = {} + for edge in self.package.imports: + self.targets.setdefault((edge.source, edge.line), set()).add(edge.target) + + def file_operations( + self, path: str, source: str + ) -> list[EnsureImportOperation | PatchTargetOperation]: + if path not in self.modules: + self.left["outside the agent_comms package"] += FunctionLocalImport.count( + source.encode(), path + ) + return [] + module, tree, lines = ( + self.modules[path], + ast.parse(source), + source.splitlines(keepends=True), + ) + bound = TopLevelNames.of(tree) + imported = { + name: ast.unparse(statement) + for statement in tree.body + if isinstance(statement, (ast.Import, ast.ImportFrom)) + for name in self.bound(statement) + } + hoisted: dict[str, str] = {} + moved: dict[str, tuple[ast.FunctionDef | ast.AsyncFunctionDef, list[ast.stmt]]] = {} + for qualname, function, statement in self.local_imports(tree, []): + text, names = ast.unparse(statement), set(self.bound(statement)) + inside = self.targets.get((module, statement.lineno), set()) + reason = self.stays( + statement, function, text, names, inside, lines, bound, imported, hoisted, module + ) + if reason: + self.left[reason] += 1 + continue + self.graph.add(module, inside) + hoisted.update(dict.fromkeys(names, text)) + moved.setdefault(qualname, (function, []))[1].append(statement) + operations: list[EnsureImportOperation | PatchTargetOperation] = [ + EnsureImportOperation(target=self.target(path), import_source=text) + for text in dict.fromkeys(hoisted.values()) + ] + operations += [ + PatchTargetOperation( + target=self.target(path, qualname), + replacements=tuple( + SourceTextReplacement(old_source=removed, new_source="") + for removed in dict.fromkeys(self.removals(lines, function, statements)) + ), + ) + for qualname, (function, statements) in moved.items() + ] + return operations + + def stays( + self, + statement: ast.Import | ast.ImportFrom, + function: ast.FunctionDef | ast.AsyncFunctionDef, + text: str, + names: set[str], + inside: set[str], + lines: list[str], + bound: frozenset[str], + imported: dict[str, str], + hoisted: dict[str, str], + module: str, + ) -> str: + """Why this import stays local, or the empty string when it moves.""" + root = self.imported_module(statement) + if not inside and root not in sys.stdlib_module_names: + return "third-party" + if statement.lineno != statement.end_lineno or lines[statement.lineno - 1].strip() != text: + return "not one plain line" + if any(name in bound and imported.get(name) != text for name in names): + return "the module binds the name another way" + if any(hoisted.get(name, text) != text for name in names): + return "another moved import binds the name" + if self.rebinds(function, statement, names): + return "the function rebinds the name" + if len(function.body) == 1: + return "the import is the whole body" + if module in self.graph.reached(inside): + return "a module-level import cycle runs through it" + return "" + + @staticmethod + def imported_module(statement: ast.Import | ast.ImportFrom) -> str: + match statement: + case ast.ImportFrom(level=0, module=str(name)): + return name.split(".")[0] + case ast.Import(names=[ast.alias(name=name), *_]): + return name.split(".")[0] + return "" + + @staticmethod + def bound(statement: ast.Import | ast.ImportFrom) -> list[str]: + return [alias.asname or alias.name.split(".")[0] for alias in statement.names] + + def local_imports(self, node: ast.AST, scope: list[str]): + """Each import that is a direct body statement of a function, with the function's + qualified name, at any nesting of classes and functions.""" + for child in ast.iter_child_nodes(node): + if isinstance(child, (*FUNCTIONS, ast.ClassDef)): + inner = [*scope, child.name] + if isinstance(child, FUNCTIONS): + for statement in child.body: + if isinstance(statement, (ast.Import, ast.ImportFrom)): + yield ".".join(inner), child, statement + yield from self.local_imports(child, inner) + + def rebinds(self, function: ast.AST, statement: ast.stmt, names: set[str]) -> bool: + for node in ast.walk(function): + match node: + case ast.Name(id=name, ctx=ast.Store()) if name in names: + return True + case ast.Import() | ast.ImportFrom() if ( + node is not statement and set(self.bound(node)) & names + ): + return True + return False + + @staticmethod + def removals( + lines: list[str], function: ast.FunctionDef | ast.AsyncFunctionDef, removed: list[ast.stmt] + ) -> list[str]: + """Each moved import's line; when the function's whole leading import block moves, + the blank line that separated it from the code goes with the block's last line.""" + body = function.body + match body[0]: + case ast.Expr(value=ast.Constant(value=str())): + start = 1 + case _: + start = 0 + block: list[ast.stmt] = [] + for statement in body[start:]: + if not isinstance(statement, (ast.Import, ast.ImportFrom)): + break + block.append(statement) + texts = [lines[statement.lineno - 1] for statement in removed] + if ( + block + and all(statement in removed for statement in block) + and not lines[block[-1].lineno].strip() + ): + texts[removed.index(block[-1])] += lines[block[-1].lineno] + return texts + + +def main() -> int: + parser = argparse.ArgumentParser( + description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter + ) + parser.add_argument( + "--root", required=True, help="Repository-relative production source directory" + ) + scope = parser.add_mutually_exclusive_group(required=True) + scope.add_argument("--all", action="store_true", help="Repair every file under the root") + scope.add_argument( + "--base", help="Repair the files whose repaired measures grew since this revision" + ) + parser.add_argument("--head", default="HEAD") + parser.add_argument( + "--apply", action="store_true", help="Apply the plan instead of showing its diff" + ) + args = parser.parse_args() + repo = Path.cwd() + root = args.root.rstrip("/") + "/" + if args.all: + files = { + measure: sorted( + path for path in production_paths(repo, "HEAD") if path.startswith(root) + ) + for measure in (repair.repairs for repair in Repair.members_with(Repair)) + } + else: + found = compare( + repo, + args.base, + args.head, + args.root, + 1, + tuple(repair.repairs for repair in Repair.members_with(Repair)), + ).found + files = { + measure: sorted( + {site.path for key, sites in found.items() if measure.owns(key) for site in sites} + ) + for measure in (repair.repairs for repair in Repair.members_with(Repair)) + } + for repair in Repair.members_with(Repair): + fixer = repair(repo, files[repair.repairs]) + if args.apply: + touched = fixer.apply() + print(f"{repair.__name__}: applied to {len(touched)} files", file=sys.stderr) + else: + diff, changed = fixer.simulation() + print(diff, end="") + print(f"{repair.__name__}: {changed} files would change", file=sys.stderr) + for reason, count in fixer.left.most_common(): + print(f"{repair.__name__}: {count} left, {reason}", file=sys.stderr) + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/uv.lock b/uv.lock index 998328253a..9c2cf68dfc 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 5 +revision = 3 requires-python = "==3.14.*" [[package]] @@ -29,6 +29,7 @@ dependencies = [ dev = [ { name = "black" }, { name = "mypy" }, + { name = "nominal-refactor-advisor" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -45,6 +46,7 @@ requires-dist = [ { name = "black", marker = "extra == 'dev'", specifier = "==26.5.1" }, { name = "metaclass-registry", git = "https://github.com/OpenHCSDev/metaclass-registry?branch=main" }, { name = "mypy", marker = "extra == 'dev'", specifier = "==2.3.0" }, + { name = "nominal-refactor-advisor", marker = "extra == 'dev'", git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main" }, { name = "packaging", specifier = ">=24" }, { name = "pydantic", specifier = ">=2.13" }, { name = "pytest", marker = "extra == 'dev'", specifier = ">=7.0" }, @@ -505,6 +507,16 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "nominal-refactor-advisor" +version = "0.1.0" +source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#9194ceaaddb9e74a744fc49810d8ff018c5b911d" } +dependencies = [ + { name = "metaclass-registry" }, + { name = "tree-sitter" }, + { name = "tree-sitter-python" }, +] + [[package]] name = "packaging" version = "26.3" @@ -761,6 +773,37 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cb/9a/8415f2657cbe200f41a4531ccededf135505a92d4a012229121f885b26f9/ruff-0.16.0-py3-none-win_arm64.whl", hash = "sha256:14296fedcd2705c77ab8235439278bbb38f285cf7da5528b00b3e330c3d4872d", size = 11273407, upload-time = "2026-07-23T19:11:28.705Z" }, ] +[[package]] +name = "tree-sitter" +version = "0.25.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/66/7c/0350cfc47faadc0d3cf7d8237a4e34032b3014ddf4a12ded9933e1648b55/tree-sitter-0.25.2.tar.gz", hash = "sha256:fe43c158555da46723b28b52e058ad444195afd1db3ca7720c59a254544e9c20", size = 177961, upload-time = "2025-09-25T17:37:59.751Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/07/e3/d9526ba71dfbbe4eba5e51d89432b4b333a49a1e70712aa5590cd22fc74f/tree_sitter-0.25.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:65d3c931013ea798b502782acab986bbf47ba2c452610ab0776cf4a8ef150fc0", size = 146776, upload-time = "2025-09-25T17:37:50.898Z" }, + { url = "https://files.pythonhosted.org/packages/42/97/4bd4ad97f85a23011dd8a535534bb1035c4e0bac1234d58f438e15cff51f/tree_sitter-0.25.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:bda059af9d621918efb813b22fb06b3fe00c3e94079c6143fcb2c565eb44cb87", size = 137732, upload-time = "2025-09-25T17:37:51.877Z" }, + { url = "https://files.pythonhosted.org/packages/b6/19/1e968aa0b1b567988ed522f836498a6a9529a74aab15f09dd9ac1e41f505/tree_sitter-0.25.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:eac4e8e4c7060c75f395feec46421eb61212cb73998dbe004b7384724f3682ab", size = 609456, upload-time = "2025-09-25T17:37:52.925Z" }, + { url = "https://files.pythonhosted.org/packages/48/b6/cf08f4f20f4c9094006ef8828555484e842fc468827ad6e56011ab668dbd/tree_sitter-0.25.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:260586381b23be33b6191a07cea3d44ecbd6c01aa4c6b027a0439145fcbc3358", size = 636772, upload-time = "2025-09-25T17:37:54.647Z" }, + { url = "https://files.pythonhosted.org/packages/57/e2/d42d55bf56360987c32bc7b16adb06744e425670b823fb8a5786a1cea991/tree_sitter-0.25.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7d2ee1acbacebe50ba0f85fff1bc05e65d877958f00880f49f9b2af38dce1af0", size = 631522, upload-time = "2025-09-25T17:37:55.833Z" }, + { url = "https://files.pythonhosted.org/packages/03/87/af9604ebe275a9345d88c3ace0cf2a1341aa3f8ef49dd9fc11662132df8a/tree_sitter-0.25.2-cp314-cp314-win_amd64.whl", hash = "sha256:4973b718fcadfb04e59e746abfbb0288694159c6aeecd2add59320c03368c721", size = 130864, upload-time = "2025-09-25T17:37:57.453Z" }, + { url = "https://files.pythonhosted.org/packages/a6/6e/e64621037357acb83d912276ffd30a859ef117f9c680f2e3cb955f47c680/tree_sitter-0.25.2-cp314-cp314-win_arm64.whl", hash = "sha256:b8d4429954a3beb3e844e2872610d2a4800ba4eb42bb1990c6a4b1949b18459f", size = 117470, upload-time = "2025-09-25T17:37:58.431Z" }, +] + +[[package]] +name = "tree-sitter-python" +version = "0.25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b8/8b/c992ff0e768cb6768d5c96234579bf8842b3a633db641455d86dd30d5dac/tree_sitter_python-0.25.0.tar.gz", hash = "sha256:b13e090f725f5b9c86aa455a268553c65cadf325471ad5b65cd29cac8a1a68ac", size = 159845, upload-time = "2025-09-11T06:47:58.159Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/64/a4e503c78a4eb3ac46d8e72a29c1b1237fa85238d8e972b063e0751f5a94/tree_sitter_python-0.25.0-cp310-abi3-macosx_10_9_x86_64.whl", hash = "sha256:14a79a47ddef72f987d5a2c122d148a812169d7484ff5c75a3db9609d419f361", size = 73790, upload-time = "2025-09-11T06:47:47.652Z" }, + { url = "https://files.pythonhosted.org/packages/e6/1d/60d8c2a0cc63d6ec4ba4e99ce61b802d2e39ef9db799bdf2a8f932a6cd4b/tree_sitter_python-0.25.0-cp310-abi3-macosx_11_0_arm64.whl", hash = "sha256:480c21dbd995b7fe44813e741d71fed10ba695e7caab627fb034e3828469d762", size = 76691, upload-time = "2025-09-11T06:47:49.038Z" }, + { url = "https://files.pythonhosted.org/packages/aa/cb/d9b0b67d037922d60cbe0359e0c86457c2da721bc714381a63e2c8e35eba/tree_sitter_python-0.25.0-cp310-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:86f118e5eecad616ecdb81d171a36dde9bef5a0b21ed71ea9c3e390813c3baf5", size = 108133, upload-time = "2025-09-11T06:47:50.499Z" }, + { url = "https://files.pythonhosted.org/packages/40/bd/bf4787f57e6b2860f3f1c8c62f045b39fb32d6bac4b53d7a9e66de968440/tree_sitter_python-0.25.0-cp310-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be71650ca2b93b6e9649e5d65c6811aad87a7614c8c1003246b303f6b150f61b", size = 110603, upload-time = "2025-09-11T06:47:51.985Z" }, + { url = "https://files.pythonhosted.org/packages/5d/25/feff09f5c2f32484fbce15db8b49455c7572346ce61a699a41972dea7318/tree_sitter_python-0.25.0-cp310-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6d5b5799628cc0f24691ab2a172a8e676f668fe90dc60468bee14084a35c16d", size = 108998, upload-time = "2025-09-11T06:47:53.046Z" }, + { url = "https://files.pythonhosted.org/packages/75/69/4946da3d6c0df316ccb938316ce007fb565d08f89d02d854f2d308f0309f/tree_sitter_python-0.25.0-cp310-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:71959832fc5d9642e52c11f2f7d79ae520b461e63334927e93ca46cd61cd9683", size = 107268, upload-time = "2025-09-11T06:47:54.388Z" }, + { url = "https://files.pythonhosted.org/packages/ed/a2/996fc2dfa1076dc460d3e2f3c75974ea4b8f02f6bc925383aaae519920e8/tree_sitter_python-0.25.0-cp310-abi3-win_amd64.whl", hash = "sha256:9bcde33f18792de54ee579b00e1b4fe186b7926825444766f849bf7181793a76", size = 76073, upload-time = "2025-09-11T06:47:55.773Z" }, + { url = "https://files.pythonhosted.org/packages/07/19/4b5569d9b1ebebb5907d11554a96ef3fa09364a30fcfabeff587495b512f/tree_sitter_python-0.25.0-cp310-abi3-win_arm64.whl", hash = "sha256:0fbf6a3774ad7e89ee891851204c2e2c47e12b63a5edbe2e9156997731c128bb", size = 74169, upload-time = "2025-09-11T06:47:56.747Z" }, +] + [[package]] name = "typing-extensions" version = "4.16.0" From 275e2787780d667995ca266d4262c1222d059d00 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 21:04:48 -0400 Subject: [PATCH 2/7] Regenerate MODULE_LAYERS.md on current main Co-Authored-By: Claude Opus 5.5 --- docs/layout/MODULE_LAYERS.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/layout/MODULE_LAYERS.md b/docs/layout/MODULE_LAYERS.md index d5ea7c5635..54be1f49c6 100644 --- a/docs/layout/MODULE_LAYERS.md +++ b/docs/layout/MODULE_LAYERS.md @@ -571,9 +571,9 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/cli.py:20` | `agent_comms.launch_root` | cli | commander | | `src/agent_comms/cli_bridges/claude.py:12` | `agent_comms.bus` | runtime | commander | | `src/agent_comms/cli_bridges/claude.py:16` | `agent_comms.watched` | runtime | commander | -| `src/agent_comms/cli_bridges/claude_protocol.py:18` | `agent_comms.cli_protocol` | runtime | cli | -| `src/agent_comms/cli_bridges/claude_protocol.py:39` | `agent_comms.tool_calls` | runtime | cli | -| `src/agent_comms/cli_bridges/claude_protocol.py:40` | `agent_comms.transcript_events` | runtime | commander | +| `src/agent_comms/cli_bridges/claude_protocol.py:19` | `agent_comms.cli_protocol` | runtime | cli | +| `src/agent_comms/cli_bridges/claude_protocol.py:43` | `agent_comms.tool_calls` | runtime | cli | +| `src/agent_comms/cli_bridges/claude_protocol.py:44` | `agent_comms.transcript_events` | runtime | commander | | `src/agent_comms/cli_bridges/codex.py:17` | `agent_comms.child_process` | runtime | commander | | `src/agent_comms/cli_bridges/codex.py:18` | `agent_comms.messages` | runtime | commander | | `src/agent_comms/cli_bridges/codex.py:19` | `agent_comms.send_result` | runtime | commander | @@ -1088,7 +1088,7 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/owner_restart.py:238` | `agent_comms.attempt_recovery` | registry | coordination | | `src/agent_comms/pi_commands.py:52` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/pi_commands.py:262` | `agent_comms.child_process` | runtime | commander | -| `src/agent_comms/pi_counts.py:22` | `agent_comms.backend` | runtime | commander | +| `src/agent_comms/pi_counts.py:24` | `agent_comms.backend` | runtime | commander | | `src/agent_comms/pi_durable_backend.py:24` | `agent_comms.locked_store` | runtime | commander | | `src/agent_comms/pi_durable_backend.py:25` | `agent_comms.external_transcript` | runtime | commander | | `src/agent_comms/pi_durable_backend.py:39` | `agent_comms.transcript_sources` | runtime | commander | @@ -1298,9 +1298,9 @@ Layers in order: `wire`, `registry`, `coordination`, `context`, `turns`, `runtim | `src/agent_comms/runtime_updates.py:17` | `agent_comms.cli_protocol` | runtime | cli | | `src/agent_comms/runtime_updates.py:18` | `agent_comms.external_transcript` | runtime | commander | | `src/agent_comms/runtime_updates.py:20` | `agent_comms.transcript_events` | runtime | commander | -| `src/agent_comms/runtime_updates.py:32` | `agent_comms.importing` | runtime | commander | -| `src/agent_comms/runtime_updates.py:33` | `agent_comms.comms` | runtime | commander | -| `src/agent_comms/runtime_updates.py:34` | `agent_comms.messaging` | runtime | commander | +| `src/agent_comms/runtime_updates.py:33` | `agent_comms.importing` | runtime | commander | +| `src/agent_comms/runtime_updates.py:34` | `agent_comms.comms` | runtime | commander | +| `src/agent_comms/runtime_updates.py:35` | `agent_comms.messaging` | runtime | commander | | `src/agent_comms/schema_report.py:9` | `agent_comms.cli_result` | commander | cli | | `src/agent_comms/selected_actions.py:11` | `agent_comms.envelope_claim_transitions` | turns | commander | | `src/agent_comms/selected_actions.py:13` | `agent_comms.native_tool_call` | turns | runtime | From 3198108d34faadd649f7d8cb07f46f73fc13bf12 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 21:39:22 -0400 Subject: [PATCH 3/7] Repair's reasons are a declared family; typing names have their own owner The debt-src and debt-tools growth on this branch, at its owners: - ImportHoist.stays was a seven-arm if-chain returning sentences that left counted by string (StringSubscript at repairs.py:130). The reasons are now a HoistVerdict family in declaration order: each KeptImport member owns its holds() and why, Moves is the last member, and left is Counter[type[Kept]]. Its locals become HoistedFile and LocalImport. - target(path, qualname=None) named two targets with None as the switch: file_target and function_target. - rebinds' match over node types (TypeSwitch, three arms) is a Rebinding NodeVisitor. - module_layers wrapped a def's statements in ast.Expression to iterate them (a type error); visit_scope takes each scope's own body. Its TYPE_CHECKING test matched the spelling (StringIdentity +2) and any local name spelled so; it asks TypingReference.is_type_checking. - TypingImports and TypingReference move from debt_ratchet to typing_names, so module_layers stays at 0.04 s to import instead of debt_ratchet's 0.95 s. Their Python 3.11 type_param guard is deleted: the package requires 3.14. The full src simulation and its tallies are byte-identical before and after; the generated MODULE_LAYERS.md is unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q8rVa3cPyXzpCKyR8XvM8W --- tests/test_repairs.py | 4 +- tools/debt_ratchet.py | 120 +------------ tools/module_layers.py | 43 +++-- tools/repairs.py | 370 ++++++++++++++++++++++++++++------------- tools/typing_names.py | 137 +++++++++++++++ 5 files changed, 418 insertions(+), 256 deletions(-) create mode 100644 tools/typing_names.py diff --git a/tests/test_repairs.py b/tests/test_repairs.py index b82e600503..20e4b245ae 100644 --- a/tests/test_repairs.py +++ b/tests/test_repairs.py @@ -2,7 +2,7 @@ import sys from pathlib import Path -from repairs import ImportHoist +from repairs import ImportCycle, ImportHoist PACKAGE = { "__init__.py": "", @@ -39,7 +39,7 @@ def test_a_local_import_moves_up_unless_a_load_time_import_leads_back(tmp_path: assert "+from .leaf import VALUE" in diff assert "- from .leaf import VALUE" in diff assert "- from .loop import LOOPED" not in diff - assert hoist.left == {"a module-level import cycle runs through it": 1} + assert hoist.left == {ImportCycle: 1} assert ImportHoist(repo, ["src/agent_comms/user.py"]).apply() == ("src/agent_comms/user.py",) source = (repo / "src/agent_comms/user.py").read_text() diff --git a/tools/debt_ratchet.py b/tools/debt_ratchet.py index 4237a9809e..b7dd914b33 100644 --- a/tools/debt_ratchet.py +++ b/tools/debt_ratchet.py @@ -51,6 +51,7 @@ from agent_comms.declared_family import DeclaredFamily from agent_comms.installer.carry import STEPS from stored_formats import StoredForm +from typing_names import TypingImports, TypingReference from agent_comms.field_codec import FieldCodec, boundary_decoder, projected from agent_comms.mro_dispatch import MroDispatch, handles @@ -2070,125 +2071,6 @@ def occurrences(node: ast.AST) -> int: return 0 -class TypingImports(MroDispatch): - """Resolve unshadowed module imports from the actual stdlib declarations. - - This bounded syntactic measure never executes inspected source. Nested - bindings conservatively disqualify a name rather than inferring its flow. - """ - - typing_modules: typing.ClassVar[dict[str, types.ModuleType]] = { - module.__name__: module for module in (typing, typing_extensions) - } - - def __init__(self, declarations: set[ast.AST]) -> None: - self.declarations = declarations - self.values: dict[str, object] = {} - self.shadowed: set[str] = set() - - def bind(self, node: ast.AST, name: str, value: object) -> None: - if node not in self.declarations or name in self.values: - self.shadowed.add(name) - self.values[name] = value - - @handles(ast.Import) - def modules(self, node: ast.Import) -> None: - for item in node.names: - self.bind(node, item.asname or item.name.split(".")[0], - self.typing_modules.get(item.name)) - - @handles(ast.ImportFrom) - def members(self, node: ast.ImportFrom) -> None: - for item in node.names: - declaration = None - module = self.typing_modules.get(node.module) if node.level == 0 else None - if module is not None: - declaration = vars(module).get(item.name) - self.bind(node, item.asname or item.name, declaration) - - @handles(ast.Name) - def assignment(self, node: ast.Name) -> None: - if isinstance(node.ctx, (ast.Store, ast.Del)): - self.shadowed.add(node.id) - - @handles(ast.Attribute) - def mutation(self, node: ast.Attribute) -> None: - if isinstance(node.ctx, (ast.Store, ast.Del)): - for descendant in ast.walk(node.value): - if isinstance(descendant, ast.Name): - self.shadowed.add(descendant.id) - - @handles(ast.arg) - def parameter(self, node: ast.arg) -> None: - self.shadowed.add(node.arg) - - @handles(ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef) - def named_binding(self, node) -> None: - self.shadowed.add(node.name) - - @handles(ast.ExceptHandler) - def exception_binding(self, node: ast.ExceptHandler) -> None: - name = node.name - if name is not None: - self.shadowed.add(name) - - # Honor the package's Python 3.11 contract without inventing parser nodes. - if hasattr(ast, "type_param"): - @handles(ast.type_param) - def type_parameter(self, node) -> None: - self.shadowed.add(node.name) - - @classmethod - def of(cls, tree: ast.Module) -> dict[str, object]: - imports = cls(set(tree.body)) - for node in ast.walk(tree): - imports.dispatch_sync(node) - if "*" in imports.values: - return {} # A star import can replace any otherwise known binding. - return {name: value for name, value in imports.values.items() - if name not in imports.shadowed} - - @classmethod - def at_any_depth(cls, tree: ast.Module) -> dict[str, object]: - """Every name an import binds to ``typing``, wherever the import is written. - - For a measure that counts uses of a typing name: skipping an import inside - ``if TYPE_CHECKING:`` or a function body would hide the uses it enables. - """ - imports = cls(set(ast.walk(tree))) - for node in ast.walk(tree): - imports.dispatch_sync(node) - return {name: value for name, value in imports.values.items() if value is not None} - - -class TypingReference(MroDispatch): - """One AST expression's resolved imported declaration, never evaluated code.""" - - def __init__(self, imports: dict[str, object]) -> None: - self.imports = imports - self.value: object = None - - @property - def is_any(self) -> bool: - return self.value is typing.Any - - @handles(ast.Name) - def name(self, node: ast.Name) -> None: - self.value = self.imports.get(node.id) - - @handles(ast.Attribute) - def member(self, node: ast.Attribute) -> None: - parent = TypingReference(self.imports) - parent.dispatch_sync(node.value) - for module in TypingImports.typing_modules.values(): - if parent.value is module: - self.value = vars(module).get(node.attr) - - def raw_access_count(self) -> int: - """Typing declarations contribute no raw-record operation; unknowns do.""" - return int(getattr(self.value, "__module__", None) != typing.__name__) - - class StringSubscript(OccurrenceMeasure): @classmethod def lines(cls, source: bytes, filename: str) -> list[int]: diff --git a/tools/module_layers.py b/tools/module_layers.py index 10f4b6addd..8baff7f33e 100644 --- a/tools/module_layers.py +++ b/tools/module_layers.py @@ -25,11 +25,13 @@ import tomllib import typing from abc import ABC, abstractmethod -from collections.abc import Iterable +from collections.abc import Iterable, Sequence from dataclasses import dataclass from functools import cached_property from pathlib import Path +from typing_names import TypingImports, TypingReference + ROOT = Path(__file__).resolve().parent.parent PACKAGE = "agent_comms" @@ -132,34 +134,43 @@ def record(self, node: ast.stmt | ast.expr, *names: str) -> None: if (target := self.package.resolve(name)) is not None: self.found.append(self.runs(self.module, target, node.lineno)) - def visit_within(self, runs: type[Import], nodes: list[ast.stmt] | list[ast.AST]) -> None: + def visit_within(self, runs: type[Import], nodes: Sequence[ast.AST]) -> None: outer, self.runs = self.runs, runs for node in nodes: self.visit(node) self.runs = outer - def visit_FunctionDef(self, node: ast.FunctionDef | ast.AsyncFunctionDef | ast.Lambda) -> None: - """Decorators, defaults and annotations run where the ``def`` runs; only the body - runs when the function is called. Wrapping the body in an Expression lets - iter_child_nodes yield a lambda's one expression and a def's statements alike.""" - called = list(ast.iter_child_nodes(ast.Expression(body=node.body))) + def visit_scope(self, node: ast.AST, called: Sequence[ast.AST]) -> None: + """Decorators, defaults and annotations run where the definition runs; only the + body runs when the function is called.""" self.visit_within( self.runs, [child for child in ast.iter_child_nodes(node) if all(child is not c for c in called)], ) self.visit_within(self.runs.in_function(), called) - # NodeVisitor dispatches on these names; one method serves all three scopes. - visit_AsyncFunctionDef = visit_Lambda = visit_FunctionDef # noqa: N815 + def visit_FunctionDef(self, node: ast.FunctionDef | ast.AsyncFunctionDef) -> None: + self.visit_scope(node, node.body) + + # NodeVisitor dispatches on the node's class name; a coroutine's scopes are a function's. + visit_AsyncFunctionDef = visit_FunctionDef # noqa: N815 + + def visit_Lambda(self, node: ast.Lambda) -> None: + self.visit_scope(node, [node.body]) + + def visit_Module(self, node: ast.Module) -> None: + self.typing = TypingImports.of(node) + self.generic_visit(node) def visit_If(self, node: ast.If) -> None: - match node.test: - case ast.Name(id="TYPE_CHECKING") | ast.Attribute(attr="TYPE_CHECKING"): - self.visit(node.test) - self.visit_within(CheckerImport, node.body) - self.visit_within(self.runs, node.orelse) - case _: - self.generic_visit(node) + test = TypingReference(self.typing) + test.dispatch_sync(node.test) + if test.is_type_checking: + self.visit(node.test) + self.visit_within(CheckerImport, node.body) + self.visit_within(self.runs, node.orelse) + else: + self.generic_visit(node) def visit_Import(self, node: ast.Import) -> None: self.record(node, *(alias.name for alias in node.names)) diff --git a/tools/repairs.py b/tools/repairs.py index 00e4b6f1d3..16f1fd9a71 100644 --- a/tools/repairs.py +++ b/tools/repairs.py @@ -19,7 +19,9 @@ import sys from abc import ABC, abstractmethod from collections import Counter -from collections.abc import Iterable +from collections.abc import Iterable, Iterator +from dataclasses import dataclass, field, replace +from functools import cached_property from pathlib import Path from typing import ClassVar @@ -36,7 +38,24 @@ from agent_comms.declared_family import DeclaredFamily -FUNCTIONS = (ast.FunctionDef, ast.AsyncFunctionDef) +type FunctionNode = ast.FunctionDef | ast.AsyncFunctionDef +type ImportNode = ast.Import | ast.ImportFrom +type Operation = EnsureImportOperation | PatchTargetOperation + + +def bound_names(statement: ImportNode) -> list[str]: + """The names one import statement binds in its scope.""" + return [alias.asname or alias.name.split(".")[0] for alias in statement.names] + + +class Kept(ABC): + """Why a repair leaves an occurrence of its measure in place; ``why`` reports it.""" + + why: ClassVar[str] + + +class OutsidePackage(Kept): + why = "outside the agent_comms package" class Repair(DeclaredFamily, ABC): @@ -46,12 +65,10 @@ class Repair(DeclaredFamily, ABC): def __init__(self, repo: Path, paths: Iterable[str]) -> None: self.repo, self.paths = repo, sorted(paths) - self.left: Counter[str] = Counter() + self.left: Counter[type[Kept]] = Counter() @abstractmethod - def file_operations( - self, path: str, source: str - ) -> list[EnsureImportOperation | PatchTargetOperation]: + def file_operations(self, path: str, source: str) -> list[Operation]: """The operations removing this file's occurrences; each one left is tallied in ``left`` under the reason it stays.""" @@ -64,10 +81,13 @@ def sequence(self) -> CodemodPlanSequence: ) ) - def target(self, path: str, qualname: str | None = None) -> SourceRewriteTarget: + def file_target(self, path: str) -> SourceRewriteTarget: """A file of this repair's tree, named absolutely: NRA resolves a relative path against the process directory, which need not be the tree.""" - return SourceRewriteTarget(file_path=str(self.repo / path), qualname=qualname) + return SourceRewriteTarget(file_path=str(self.repo / path)) + + def function_target(self, path: str, qualname: str) -> SourceRewriteTarget: + return replace(self.file_target(path), qualname=qualname) @staticmethod def sources(sequence: CodemodPlanSequence) -> dict[str, str]: @@ -123,127 +143,81 @@ def __init__(self, repo: Path, paths: Iterable[str]) -> None: for edge in self.package.imports: self.targets.setdefault((edge.source, edge.line), set()).add(edge.target) - def file_operations( - self, path: str, source: str - ) -> list[EnsureImportOperation | PatchTargetOperation]: + def file_operations(self, path: str, source: str) -> list[Operation]: if path not in self.modules: - self.left["outside the agent_comms package"] += FunctionLocalImport.count( - source.encode(), path - ) + self.left[OutsidePackage] += FunctionLocalImport.count(source.encode(), path) return [] - module, tree, lines = ( - self.modules[path], - ast.parse(source), - source.splitlines(keepends=True), - ) - bound = TopLevelNames.of(tree) - imported = { + hoisted = HoistedFile(self, path, self.modules[path], source) + for local in hoisted.local_imports(hoisted.tree, []): + HoistVerdict.of(local).take(local) + return hoisted.operations() + + +@dataclass +class HoistedFile: + """One file under the hoist: what its top level binds, and the imports moved so far.""" + + hoist: ImportHoist + path: str + module: str + source: str + hoisted: dict[str, str] = field(default_factory=dict) + """Each moved name, by the one import text that binds it at the top.""" + moved: dict[str, tuple[FunctionNode, list[ImportNode]]] = field(default_factory=dict) + """Each function losing imports, by qualified name, with the imports it loses.""" + + @cached_property + def tree(self) -> ast.Module: + return ast.parse(self.source) + + @cached_property + def lines(self) -> list[str]: + return self.source.splitlines(keepends=True) + + @cached_property + def bound(self) -> frozenset[str]: + return TopLevelNames.of(self.tree) + + @cached_property + def imported(self) -> dict[str, str]: + """Each name a top-level import binds, by that import's text.""" + return { name: ast.unparse(statement) - for statement in tree.body + for statement in self.tree.body if isinstance(statement, (ast.Import, ast.ImportFrom)) - for name in self.bound(statement) + for name in bound_names(statement) } - hoisted: dict[str, str] = {} - moved: dict[str, tuple[ast.FunctionDef | ast.AsyncFunctionDef, list[ast.stmt]]] = {} - for qualname, function, statement in self.local_imports(tree, []): - text, names = ast.unparse(statement), set(self.bound(statement)) - inside = self.targets.get((module, statement.lineno), set()) - reason = self.stays( - statement, function, text, names, inside, lines, bound, imported, hoisted, module - ) - if reason: - self.left[reason] += 1 - continue - self.graph.add(module, inside) - hoisted.update(dict.fromkeys(names, text)) - moved.setdefault(qualname, (function, []))[1].append(statement) - operations: list[EnsureImportOperation | PatchTargetOperation] = [ - EnsureImportOperation(target=self.target(path), import_source=text) - for text in dict.fromkeys(hoisted.values()) + + def local_imports(self, node: ast.AST, scope: list[str]) -> Iterator[LocalImport]: + """Each import that is a direct body statement of a function, at any nesting of + classes and functions.""" + for child in ast.iter_child_nodes(node): + if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef)): + inner = [*scope, child.name] + if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef)): + for statement in child.body: + if isinstance(statement, (ast.Import, ast.ImportFrom)): + yield LocalImport(self, ".".join(inner), child, statement) + yield from self.local_imports(child, inner) + + def operations(self) -> list[Operation]: + operations: list[Operation] = [ + EnsureImportOperation(target=self.hoist.file_target(self.path), import_source=text) + for text in dict.fromkeys(self.hoisted.values()) ] operations += [ PatchTargetOperation( - target=self.target(path, qualname), + target=self.hoist.function_target(self.path, qualname), replacements=tuple( SourceTextReplacement(old_source=removed, new_source="") - for removed in dict.fromkeys(self.removals(lines, function, statements)) + for removed in dict.fromkeys(self.removals(function, statements)) ), ) - for qualname, (function, statements) in moved.items() + for qualname, (function, statements) in self.moved.items() ] return operations - def stays( - self, - statement: ast.Import | ast.ImportFrom, - function: ast.FunctionDef | ast.AsyncFunctionDef, - text: str, - names: set[str], - inside: set[str], - lines: list[str], - bound: frozenset[str], - imported: dict[str, str], - hoisted: dict[str, str], - module: str, - ) -> str: - """Why this import stays local, or the empty string when it moves.""" - root = self.imported_module(statement) - if not inside and root not in sys.stdlib_module_names: - return "third-party" - if statement.lineno != statement.end_lineno or lines[statement.lineno - 1].strip() != text: - return "not one plain line" - if any(name in bound and imported.get(name) != text for name in names): - return "the module binds the name another way" - if any(hoisted.get(name, text) != text for name in names): - return "another moved import binds the name" - if self.rebinds(function, statement, names): - return "the function rebinds the name" - if len(function.body) == 1: - return "the import is the whole body" - if module in self.graph.reached(inside): - return "a module-level import cycle runs through it" - return "" - - @staticmethod - def imported_module(statement: ast.Import | ast.ImportFrom) -> str: - match statement: - case ast.ImportFrom(level=0, module=str(name)): - return name.split(".")[0] - case ast.Import(names=[ast.alias(name=name), *_]): - return name.split(".")[0] - return "" - - @staticmethod - def bound(statement: ast.Import | ast.ImportFrom) -> list[str]: - return [alias.asname or alias.name.split(".")[0] for alias in statement.names] - - def local_imports(self, node: ast.AST, scope: list[str]): - """Each import that is a direct body statement of a function, with the function's - qualified name, at any nesting of classes and functions.""" - for child in ast.iter_child_nodes(node): - if isinstance(child, (*FUNCTIONS, ast.ClassDef)): - inner = [*scope, child.name] - if isinstance(child, FUNCTIONS): - for statement in child.body: - if isinstance(statement, (ast.Import, ast.ImportFrom)): - yield ".".join(inner), child, statement - yield from self.local_imports(child, inner) - - def rebinds(self, function: ast.AST, statement: ast.stmt, names: set[str]) -> bool: - for node in ast.walk(function): - match node: - case ast.Name(id=name, ctx=ast.Store()) if name in names: - return True - case ast.Import() | ast.ImportFrom() if ( - node is not statement and set(self.bound(node)) & names - ): - return True - return False - - @staticmethod - def removals( - lines: list[str], function: ast.FunctionDef | ast.AsyncFunctionDef, removed: list[ast.stmt] - ) -> list[str]: + def removals(self, function: FunctionNode, removed: list[ImportNode]) -> list[str]: """Each moved import's line; when the function's whole leading import block moves, the blank line that separated it from the code goes with the block's last line.""" body = function.body @@ -252,21 +226,179 @@ def removals( start = 1 case _: start = 0 - block: list[ast.stmt] = [] + block: list[ImportNode] = [] for statement in body[start:]: if not isinstance(statement, (ast.Import, ast.ImportFrom)): break block.append(statement) - texts = [lines[statement.lineno - 1] for statement in removed] + texts = [self.lines[statement.lineno - 1] for statement in removed] if ( block and all(statement in removed for statement in block) - and not lines[block[-1].lineno].strip() + and not self.lines[block[-1].lineno].strip() ): - texts[removed.index(block[-1])] += lines[block[-1].lineno] + texts[removed.index(block[-1])] += self.lines[block[-1].lineno] return texts +@dataclass(frozen=True) +class LocalImport: + """One import written as a direct body statement of a function in a hoisted file.""" + + file: HoistedFile + qualname: str + function: FunctionNode + statement: ImportNode + + @cached_property + def text(self) -> str: + return ast.unparse(self.statement) + + @cached_property + def names(self) -> set[str]: + return set(bound_names(self.statement)) + + @cached_property + def inside(self) -> set[str]: + """The agent_comms modules the statement imports.""" + return self.file.hoist.targets.get((self.file.module, self.statement.lineno), set()) + + @cached_property + def root(self) -> str: + """The top-level package an absolute import names; empty for a relative one.""" + match self.statement: + case ast.ImportFrom(level=0, module=str(name)) | ast.Import( + names=[ast.alias(name=name), *_] + ): + return name.split(".")[0] + return "" + + +class HoistVerdict(DeclaredFamily, ABC): + """What the hoist does with one local import: the first member, in declaration order, + that holds for it decides.""" + + @classmethod + @abstractmethod + def holds(cls, local: LocalImport) -> bool: ... + + @classmethod + @abstractmethod + def take(cls, local: LocalImport) -> None: ... + + @classmethod + def of(cls, local: LocalImport) -> type[HoistVerdict]: + return next(verdict for verdict in cls.members_with(cls) if verdict.holds(local)) + + +class KeptImport(Kept, HoistVerdict, ABC): + """The import stays in its function, and the hoist tallies why.""" + + @classmethod + def take(cls, local: LocalImport) -> None: + local.file.hoist.left[cls] += 1 + + +class ThirdParty(KeptImport): + why = "third-party" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return not local.inside and local.root not in sys.stdlib_module_names + + +class NotOnePlainLine(KeptImport): + why = "not one plain line" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + statement = local.statement + return ( + statement.lineno != statement.end_lineno + or local.file.lines[statement.lineno - 1].strip() != local.text + ) + + +class BoundOtherwise(KeptImport): + why = "the module binds the name another way" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return any( + name in local.file.bound and local.file.imported.get(name) != local.text + for name in local.names + ) + + +class BoundByAnotherMove(KeptImport): + why = "another moved import binds the name" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return any(local.file.hoisted.get(name, local.text) != local.text for name in local.names) + + +class Rebound(KeptImport): + why = "the function rebinds the name" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + rebinding = Rebinding(local) + rebinding.visit(local.function) + return rebinding.found + + +class WholeBody(KeptImport): + why = "the import is the whole body" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return len(local.function.body) == 1 + + +class ImportCycle(KeptImport): + why = "a module-level import cycle runs through it" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return local.file.module in local.file.hoist.graph.reached(local.inside) + + +class Moves(HoistVerdict): + """Nothing keeps the import: it moves to the module top, and later imports are + judged with the move accepted.""" + + @classmethod + def holds(cls, local: LocalImport) -> bool: + return True + + @classmethod + def take(cls, local: LocalImport) -> None: + local.file.hoist.graph.add(local.file.module, local.inside) + local.file.hoisted.update(dict.fromkeys(local.names, local.text)) + local.file.moved.setdefault(local.qualname, (local.function, []))[1].append(local.statement) + + +class Rebinding(ast.NodeVisitor): + """Whether a function binds one of a local import's names again, by assignment or by + another import.""" + + def __init__(self, local: LocalImport) -> None: + self.local, self.found = local, False + + def visit_Name(self, node: ast.Name) -> None: + match node: + case ast.Name(id=name, ctx=ast.Store()) if name in self.local.names: + self.found = True + + def visit_Import(self, node: ImportNode) -> None: + if node is not self.local.statement and set(bound_names(node)) & self.local.names: + self.found = True + + # NodeVisitor dispatches on the node's class name; both import forms bind alike. + visit_ImportFrom = visit_Import # noqa: N815 + + def main() -> int: parser = argparse.ArgumentParser( description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter @@ -318,7 +450,7 @@ def main() -> int: print(diff, end="") print(f"{repair.__name__}: {changed} files would change", file=sys.stderr) for reason, count in fixer.left.most_common(): - print(f"{repair.__name__}: {count} left, {reason}", file=sys.stderr) + print(f"{repair.__name__}: {count} left, {reason.why}", file=sys.stderr) return 0 diff --git a/tools/typing_names.py b/tools/typing_names.py new file mode 100644 index 0000000000..aa357b0c3d --- /dev/null +++ b/tools/typing_names.py @@ -0,0 +1,137 @@ +"""Which typing declaration a name or attribute in a module stands for, read from the +module's imports and the stdlib's own typing modules, never by running the module.""" + +from __future__ import annotations + +import ast +import types +import typing + +import typing_extensions + +from agent_comms.mro_dispatch import MroDispatch, handles + + +class TypingImports(MroDispatch): + """Resolve unshadowed module imports from the actual stdlib declarations. + + This bounded syntactic measure never executes inspected source. Nested + bindings conservatively disqualify a name rather than inferring its flow. + """ + + typing_modules: typing.ClassVar[dict[str, types.ModuleType]] = { + module.__name__: module for module in (typing, typing_extensions) + } + + def __init__(self, declarations: set[ast.AST]) -> None: + self.declarations = declarations + self.values: dict[str, object] = {} + self.shadowed: set[str] = set() + + def bind(self, node: ast.AST, name: str, value: object) -> None: + if node not in self.declarations or name in self.values: + self.shadowed.add(name) + self.values[name] = value + + @handles(ast.Import) + def modules(self, node: ast.Import) -> None: + for item in node.names: + self.bind( + node, item.asname or item.name.split(".")[0], self.typing_modules.get(item.name) + ) + + @handles(ast.ImportFrom) + def members(self, node: ast.ImportFrom) -> None: + match node: + case ast.ImportFrom(level=0, module=str(name)) if name in self.typing_modules: + namespace = vars(self.typing_modules[name]) + case _: + namespace = {} + for item in node.names: + self.bind(node, item.asname or item.name, namespace.get(item.name)) + + @handles(ast.Name) + def assignment(self, node: ast.Name) -> None: + if isinstance(node.ctx, (ast.Store, ast.Del)): + self.shadowed.add(node.id) + + @handles(ast.Attribute) + def mutation(self, node: ast.Attribute) -> None: + if isinstance(node.ctx, (ast.Store, ast.Del)): + for descendant in ast.walk(node.value): + if isinstance(descendant, ast.Name): + self.shadowed.add(descendant.id) + + @handles(ast.arg) + def parameter(self, node: ast.arg) -> None: + self.shadowed.add(node.arg) + + @handles(ast.FunctionDef, ast.AsyncFunctionDef, ast.ClassDef) + def named_binding(self, node: ast.FunctionDef | ast.AsyncFunctionDef | ast.ClassDef) -> None: + self.shadowed.add(node.name) + + @handles(ast.ExceptHandler) + def exception_binding(self, node: ast.ExceptHandler) -> None: + match node: + case ast.ExceptHandler(name=str(name)): + self.shadowed.add(name) + + @handles(ast.TypeVar, ast.ParamSpec, ast.TypeVarTuple) + def type_parameter(self, node: ast.TypeVar | ast.ParamSpec | ast.TypeVarTuple) -> None: + self.shadowed.add(node.name) + + @classmethod + def of(cls, tree: ast.Module) -> dict[str, object]: + imports = cls(set(tree.body)) + for node in ast.walk(tree): + imports.dispatch_sync(node) + if "*" in imports.values: + return {} # A star import can replace any otherwise known binding. + return { + name: value for name, value in imports.values.items() if name not in imports.shadowed + } + + @classmethod + def at_any_depth(cls, tree: ast.Module) -> dict[str, object]: + """Every name an import binds to ``typing``, wherever the import is written. + + For a measure that counts uses of a typing name: skipping an import inside + ``if TYPE_CHECKING:`` or a function body would hide the uses it enables. + """ + imports = cls(set(ast.walk(tree))) + for node in ast.walk(tree): + imports.dispatch_sync(node) + return {name: value for name, value in imports.values.items() if value is not None} + + +class TypingReference(MroDispatch): + """One AST expression's resolved imported declaration, never evaluated code.""" + + def __init__(self, imports: dict[str, object]) -> None: + self.imports = imports + self.value: object = None + + @property + def is_any(self) -> bool: + return self.value is typing.Any + + @property + def is_type_checking(self) -> bool: + """``typing.TYPE_CHECKING`` is the one typing declaration whose value is False.""" + return self.value is typing.TYPE_CHECKING + + @handles(ast.Name) + def name(self, node: ast.Name) -> None: + self.value = self.imports.get(node.id) + + @handles(ast.Attribute) + def member(self, node: ast.Attribute) -> None: + parent = TypingReference(self.imports) + parent.dispatch_sync(node.value) + for module in TypingImports.typing_modules.values(): + if parent.value is module: + self.value = vars(module).get(node.attr) + + def raw_access_count(self) -> int: + """Typing declarations contribute no raw-record operation; unknowns do.""" + return int(getattr(self.value, "__module__", None) != typing.__name__) From dc242bbcbcf3c1e8a68b9bdf25bf2ee85f7989b1 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 21:52:27 -0400 Subject: [PATCH 4/7] Declare Untyped and keep the Any question beside AnyName Moving TypingImports into typing_names brought three sites into a new file the ratchet counts from zero: None meaning "no typing declaration" from dict.get, a getattr of "__module__" by literal name, and is_any's typing.Any. Untyped is now the declared null value, raw_access_count asks for it by identity, and AnyReference holds is_any in debt_ratchet next to the measure that asks it. The unused typing_extensions import goes. StringSubscript and AnyName lines are identical on every tracked file except the moved Any site; MODULE_LAYERS.md is unchanged. uv.lock takes NRA 3fc2f084, which ships py.typed. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q8rVa3cPyXzpCKyR8XvM8W --- tools/debt_ratchet.py | 13 ++++++++++--- tools/typing_names.py | 24 +++++++++++++----------- uv.lock | 4 ++-- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/tools/debt_ratchet.py b/tools/debt_ratchet.py index fcd2d87530..179f3ccf6d 100644 --- a/tools/debt_ratchet.py +++ b/tools/debt_ratchet.py @@ -27,7 +27,6 @@ import tomllib import types import typing -import typing_extensions from typing import Annotated from abc import abstractmethod from collections import Counter @@ -2112,6 +2111,14 @@ def occurrences(node: ast.AST) -> int: ) +class AnyReference(TypingReference): + """A reference AnyName asks one question of: does it resolve to ``typing.Any``.""" + + @property + def is_any(self) -> bool: + return self.value is typing.Any + + class AnyInTypeExpression(MroDispatch): """Count ``typing.Any`` in one type expression without evaluating it. @@ -2136,7 +2143,7 @@ def resolved(self, node: ast.AST) -> object: @handles(ast.Name, ast.Attribute) def reference(self, node: ast.expr) -> None: - reference = TypingReference(self.imports) + reference = AnyReference(self.imports) reference.dispatch_sync(node) if reference.is_any: self.references.append(node) @@ -2213,7 +2220,7 @@ def declare(self, site: str, expression: ast.AST | None, scope: tuple[ast.AST, . def reference(self, node: ast.Name | ast.Attribute, scope: tuple[ast.AST, ...]) -> None: if not isinstance(node.ctx, ast.Load) or node in self.counted: return - reference = TypingReference(self.imports) + reference = AnyReference(self.imports) reference.dispatch_sync(node) if reference.is_any: self.counted.add(node) diff --git a/tools/typing_names.py b/tools/typing_names.py index aa357b0c3d..837a5f851c 100644 --- a/tools/typing_names.py +++ b/tools/typing_names.py @@ -12,6 +12,10 @@ from agent_comms.mro_dispatch import MroDispatch, handles +class Untyped: + """What a name stands for when it is bound to no typing declaration.""" + + class TypingImports(MroDispatch): """Resolve unshadowed module imports from the actual stdlib declarations. @@ -37,7 +41,9 @@ def bind(self, node: ast.AST, name: str, value: object) -> None: def modules(self, node: ast.Import) -> None: for item in node.names: self.bind( - node, item.asname or item.name.split(".")[0], self.typing_modules.get(item.name) + node, + item.asname or item.name.split(".")[0], + self.typing_modules.get(item.name, Untyped), ) @handles(ast.ImportFrom) @@ -48,7 +54,7 @@ def members(self, node: ast.ImportFrom) -> None: case _: namespace = {} for item in node.names: - self.bind(node, item.asname or item.name, namespace.get(item.name)) + self.bind(node, item.asname or item.name, namespace.get(item.name, Untyped)) @handles(ast.Name) def assignment(self, node: ast.Name) -> None: @@ -101,7 +107,7 @@ def at_any_depth(cls, tree: ast.Module) -> dict[str, object]: imports = cls(set(ast.walk(tree))) for node in ast.walk(tree): imports.dispatch_sync(node) - return {name: value for name, value in imports.values.items() if value is not None} + return {name: value for name, value in imports.values.items() if value is not Untyped} class TypingReference(MroDispatch): @@ -109,11 +115,7 @@ class TypingReference(MroDispatch): def __init__(self, imports: dict[str, object]) -> None: self.imports = imports - self.value: object = None - - @property - def is_any(self) -> bool: - return self.value is typing.Any + self.value: object = Untyped @property def is_type_checking(self) -> bool: @@ -122,7 +124,7 @@ def is_type_checking(self) -> bool: @handles(ast.Name) def name(self, node: ast.Name) -> None: - self.value = self.imports.get(node.id) + self.value = self.imports.get(node.id, Untyped) @handles(ast.Attribute) def member(self, node: ast.Attribute) -> None: @@ -130,8 +132,8 @@ def member(self, node: ast.Attribute) -> None: parent.dispatch_sync(node.value) for module in TypingImports.typing_modules.values(): if parent.value is module: - self.value = vars(module).get(node.attr) + self.value = vars(module).get(node.attr, Untyped) def raw_access_count(self) -> int: """Typing declarations contribute no raw-record operation; unknowns do.""" - return int(getattr(self.value, "__module__", None) != typing.__name__) + return int(self.value is Untyped) diff --git a/uv.lock b/uv.lock index 9c2cf68dfc..9a009c8431 100644 --- a/uv.lock +++ b/uv.lock @@ -1,5 +1,5 @@ version = 1 -revision = 3 +revision = 5 requires-python = "==3.14.*" [[package]] @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "nominal-refactor-advisor" version = "0.1.0" -source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#9194ceaaddb9e74a744fc49810d8ff018c5b911d" } +source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#3fc2f0848bb91981bd8e2a015cf381cd2c51e1dc" } dependencies = [ { name = "metaclass-registry" }, { name = "tree-sitter" }, From 54bfd69f0f76a4a113d984747a2503da4ccf5e6f Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 23:27:13 -0400 Subject: [PATCH 5/7] Track NRA a25f0a77: mypy can cache its surrogate probe Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q8rVa3cPyXzpCKyR8XvM8W --- uv.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uv.lock b/uv.lock index 9a009c8431..63ff7773fd 100644 --- a/uv.lock +++ b/uv.lock @@ -510,7 +510,7 @@ wheels = [ [[package]] name = "nominal-refactor-advisor" version = "0.1.0" -source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#3fc2f0848bb91981bd8e2a015cf381cd2c51e1dc" } +source = { git = "https://github.com/OpenHCSDev/NominalRefactorAdvisor?rev=main#a25f0a77e5ec59dc7ce7537928f7a547057eef51" } dependencies = [ { name = "metaclass-registry" }, { name = "tree-sitter" }, From 4b5e52e0a6709da6ce501140788a296ccb5b0ccd Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sat, 24 Oct 2026 23:37:25 -0400 Subject: [PATCH 6/7] Import the ratchet by one name in its tests repairs.py imports debt_ratchet by its tools-directory name, as every tool imports its siblings; the two tests spelling tools.debt_ratchet loaded the same file as a second module, and the second registration of each measure family member failed collection (DuplicateRegistryKeyError on ReportExclude). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q8rVa3cPyXzpCKyR8XvM8W --- tests/guards/test_debt_ratchet.py | 2 +- tests/test_carry.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/guards/test_debt_ratchet.py b/tests/guards/test_debt_ratchet.py index c0e570438f..e8fa107e5a 100644 --- a/tests/guards/test_debt_ratchet.py +++ b/tests/guards/test_debt_ratchet.py @@ -17,7 +17,7 @@ from fixture_git import IDENTITY from process_tree_fixture import TREE, identities -from tools.debt_ratchet import ( +from debt_ratchet import ( AUDIT_SCRIPTS, BannedVocabulary, BroadExceptDefault, diff --git a/tests/test_carry.py b/tests/test_carry.py index ca0afe2567..f0b7df3df1 100644 --- a/tests/test_carry.py +++ b/tests/test_carry.py @@ -9,7 +9,7 @@ from pathlib import Path import pytest -from tools.debt_ratchet import UncarriedRecordFormat, git +from debt_ratchet import UncarriedRecordFormat, git from agent_comms.cli_commands import StopCliCommand, TargetBatchResult from agent_comms.goal_attempts import GoalAttemptStore From bf1d2548683a7a72cfb9c5c41801aa27724ba3e7 Mon Sep 17 00:00:00 2001 From: Tristan Simas Date: Sun, 25 Oct 2026 00:12:17 -0400 Subject: [PATCH 7/7] Ask TypingImports whether a value is a typing declaration, not Untyped's identity dc242bbcb traded main's getattr(value, "__module__") probe for `self.value is Untyped`: a None check in a class costume, counted by OwnTypeTest as a test of our own class (debt-tools: grew OwnTypeTest:tools/typing_names.py +1). at_any_depth held the same probe as `is not Untyped`. Both now ask TypingImports.declares, derived from the typing_modules the class already declares; nothing tests Untyped any more. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01Q8rVa3cPyXzpCKyR8XvM8W --- tools/typing_names.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/typing_names.py b/tools/typing_names.py index 837a5f851c..f59a492509 100644 --- a/tools/typing_names.py +++ b/tools/typing_names.py @@ -13,7 +13,8 @@ class Untyped: - """What a name stands for when it is bound to no typing declaration.""" + """What a name stands for when it is bound to no typing declaration; TypingImports.declares + answers no for it, as for every other value the typing modules do not declare.""" class TypingImports(MroDispatch): @@ -86,6 +87,14 @@ def exception_binding(self, node: ast.ExceptHandler) -> None: def type_parameter(self, node: ast.TypeVar | ast.ParamSpec | ast.TypeVarTuple) -> None: self.shadowed.add(node.name) + @classmethod + def declares(cls, value: object) -> bool: + """Whether a bound value is one of the typing modules or a member they declare.""" + return any( + value is module or any(value is member for member in vars(module).values()) + for module in cls.typing_modules.values() + ) + @classmethod def of(cls, tree: ast.Module) -> dict[str, object]: imports = cls(set(tree.body)) @@ -107,7 +116,7 @@ def at_any_depth(cls, tree: ast.Module) -> dict[str, object]: imports = cls(set(ast.walk(tree))) for node in ast.walk(tree): imports.dispatch_sync(node) - return {name: value for name, value in imports.values.items() if value is not Untyped} + return {name: value for name, value in imports.values.items() if cls.declares(value)} class TypingReference(MroDispatch): @@ -136,4 +145,4 @@ def member(self, node: ast.Attribute) -> None: def raw_access_count(self) -> int: """Typing declarations contribute no raw-record operation; unknowns do.""" - return int(self.value is Untyped) + return int(not TypingImports.declares(self.value))