Skip to content

Include declared value and spelling classes in producer digests - #2945

Merged
trissim merged 8 commits into
refactor/id128-nominal-typefrom
fix/producer-digest-value-types
Oct 24, 2026
Merged

trissim merged 8 commits into
refactor/id128-nominal-typefrom
fix/producer-digest-value-types

Conversation

@trissim

@trissim trissim commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

MessageIdentitySource now declares its message_id as MessageId in production. Its digest therefore includes MessageId's minting code and MessageIdText's spelling: changing those implementations invalidates stored rows instead of silently retaining old identities.

Ready, based on #2943 (refactor/id128-nominal-type). Merged Reviewer head 0cf0835f782aaededa4f532163cdeeb9083516f9 into head d1bb4bccaac7b2a3510e23b76406b81aa2ddab81; both land as one batch. TextStorage remains in this PR. The merge was clean; none of the ten reserved send-back files was resolved or edited by Drafts.

Changes

  • message_reference.py:23: the actual inherited column is message_id: MessageId.
  • field_codec.py:1855: the existing classifier is now the public FieldCodec.representation classmethod. All internal callers and both typed_table callers use it; the old private method is deleted, with no alias.
  • typed_table.py:181–188: TextStorage asks that owner for the declared text representation. Nominal IDs retain plain TEXT storage; JSON storage does not receive this column.
  • typed_table.py:2092–2123: column value/representation owners come from declarations. The MRO walk includes only FieldRepresentation or NominalText descendants (WireValue already inherits FieldRepresentation), retaining each codec-family root and excluding unrelated Python/stdlib/C ancestors. No module-name filter or hand-written owners.
  • typed_table.py:2111: only dataclass declarations read physical columns. BusSchema, BusProjectionTables and ActivityMaximum all answer producer_owners without accessing nonexistent dataclass parameters (4, 3 and 4 owners respectively).
  • tests/test_bus.py:135: deleted the declaration rewrite. The test copies the real production source, changes only MessageIdText.digits, then separately an unrelated GitCommitText spelling.
  • tests/test_bus.py:149: the new test creates the real MessageIdentitySource table, inserts a MessageId, asserts SQLite typeof is text and the stored value is exactly its plain string, then reads an equal row with type(message_id) is MessageId.

Real-tree digest proof at 7c35a8c, before this parent sync

Fresh interpreters ran the canonical producer family on source copies of that pushed branch head. No declaration is rewritten in the test or proof.

Source change MessageIdentitySource digest
Actual branch declaration, unchanged codec cff8ffeee1974c7da4586bc483adb0950fe294c3ad61ddff8a0fc64b34997b1e
Only MessageIdText.digits 12 → 13 74c3297a00dce1198542c75f9ba02775f7b136cd2d17940f2503b37142c9b2ea
Restore digits; change only GitCommitText spelling cff8ffeee1974c7da4586bc483adb0950fe294c3ad61ddff8a0fc64b34997b1e

Owner-set changes versus the #2943 parent

The canonical producer_stamp import registers 11 concrete tables on both pinned trees, rather than the 13 from the earlier review inventory. These are every table returned by ProducedTable.members_with(ProducedTable) on those trees, not a selected subset.

Table Owner count Added owners Removed owners
answered_source 21 → 21 none none
awaiting_answer_source 73 → 73 none none
bus_activity_index 26 → 26 none none
bus_display_index 34 → 34 none none
bus_route_counts 32 → 32 none none
claim_operations 26 → 26 none none
held_resources 22 → 22 none none
message_identity_source 21 → 29 FieldRepresentation, MessageId, MessageIdText, NominalSpelling, NominalText, SpelledText, TextRepresentation, ValidatedScalar none
received_source 20 → 20 none none
sent_activity 44 → 44 none none
sent_source 18 → 18 none none

All eleven digest values change once because ProducedTable itself is an existing hashed ancestor and its producer_owners implementation changes. Only MessageIdentitySource gains value/codec owners. The whole-class source hash remains; no manual version or narrowed hashing.

Focused checks at 7c35a8c, before this parent sync

Only the following two nodes ran (nice 19, timeout 300, -p no:xdist):

tests/test_bus.py::test_projection_digest_tracks_declared_column_spelling
tests/test_bus.py::test_nominal_message_id_column_stores_plain_text
2 passed, 1 warning in 2.88s

An earlier attempt on the prior #2943 head failed before collection at acp_extension.py's removed Id128Text.mint call. Syncing the parent's 6cef37d update supplied its InputId.mint migration; no ACP edit belongs to this PR.

Direct SQLite proof: stored ('9f72589d55b5', 'text'); decoded type MessageId; restored row equals inserted row. Abstract-base owner reads passed. AST parsing of all three changed production modules had zero omissions; the public query has eleven internal calls and two typed_table calls. Search of src/tests/tools finds no old private _representation reference. No suite ran.

Assumed:

  • Preserve nominal ID kinds through input, turn and storage owners #2943 supplies the nominal MessageId/MessageIdText declarations; it and this dependent storage/digest change land as one batch. This PR adopts its one assigned production column.
  • Column annotations own declared value/representation dependencies. Undeclared helper dependencies elsewhere are not discovered by this change.
  • Codec-family implementations have inspectable Python source. Python/stdlib/C classes outside those families are excluded.
  • Source is immutable during a build; mutation proofs use new interpreter processes to avoid the existing digest cache.
  • Nominal message IDs keep their existing plain-text SQLite/wire spelling; no data conversion is needed for that column.

Fixture send-back fixed at d1bb4bc

The production type remains MessageId. Twelve free-text-ID call sites across the seven assigned test files now use MessageId.mint. This includes the additional single-quoted 'not-input' constructor at test_current_input_origin.py:275 which the requested double-quote grep missed. The three durable-reply references share one reply_id binding. Existing refusal/equality assertions remain; the absent-ID lookup still requires RowNotFoundError. No production file changed in this correction.

Requested grep:

tests/test_current_input_origin.py:171:        origin.root_id, MessageReference(1, MessageId.mint("original-id"))))
tests/test_holder_standing_rules.py:386:                answers=(MessageReference(question.seq, MessageId.mint("wrong-original")),))
tests/test_input_disposition.py:181:REFERENCE = MessageReference(7, MessageId.mint("original-id"))
tests/test_observer_death.py:67:                str(comms.root), (MessageReference(1, MessageId.mint("not-the-original")),)

AST traversal of all tests also checked single-quoted/keyword MessageReference message_id arguments and direct string lookup_message arguments: zero direct string arguments remain, hence zero malformed literals. AST parsed all seven edited test modules. This verifies the source migration, not the runtime results. No tests ran for this correction; commander review runs the two named nodes.

Ruff check ran on all 129 Python files returned by git diff --name-only origin/main -- '*.py'. It reports 1,118 findings overall and zero on Drafts changed lines. Only the changed long lines were wrapped; no whole-file formatting or inherited debt cleanup.

Assumed for this correction: deterministic minted values remain distinct from the actual stored messages in these fixtures; the three historical notifications intentionally share one reply identity; the single-quoted not-input site has the same migration requirement; runtime test results come from review, not from the AST/grep checks.

git diff --stat origin/refactor/id128-nominal-type...HEAD:

 src/agent_comms/field_codec.py         | 27 ++++++++++++------------
 src/agent_comms/message_reference.py   |  4 ++--
 src/agent_comms/typed_table.py         | 23 +++++++++++++++++---
 tests/test_bus.py                      | 38 +++++++++++++++++++++++++++++++++-
 tests/test_bus_history_seq.py          |  4 ++--
 tests/test_current_input_origin.py     | 13 +++++++-----
 tests/test_historical_notifications.py |  9 ++++----
 tests/test_holder_standing_rules.py    |  7 ++++---
 tests/test_input_disposition.py        |  4 ++--
 tests/test_observer_death.py           |  3 ++-
 10 files changed, 96 insertions(+), 36 deletions(-)

git diff --stat origin/main...HEAD (includes #2943):

 plans/ID128-NOMINAL-PLAN.md                   |  34 +-
 src/agent_comms/acp_extension.py              |  13 +-
 src/agent_comms/agent_activity.py             |   3 +-
 src/agent_comms/agent_backend.py              |  12 +-
 src/agent_comms/backend.py                    |   4 +-
 src/agent_comms/commander/order.py            |   3 +-
 src/agent_comms/cursor_owner.py               |   2 +-
 src/agent_comms/cursor_publication.py         |   6 +-
 src/agent_comms/envelope_claim_transitions.py |   8 +-
 src/agent_comms/field_codec.py                | 664 +++++++++++++++-----------
 src/agent_comms/following_inputs.py           |  11 +-
 src/agent_comms/goal_turn_permit.py           |   4 +-
 src/agent_comms/goals.py                      |   8 +-
 src/agent_comms/historical_native_inputs.py   |   4 +-
 src/agent_comms/input_attempt.py              |   6 +-
 src/agent_comms/input_disposition.py          |   5 +-
 src/agent_comms/input_drain.py                |  17 +-
 src/agent_comms/installer/launch.py           |   4 +-
 src/agent_comms/maintenance_barrier.py        |   9 +-
 src/agent_comms/manual_compaction_bridge.py   |   4 +-
 src/agent_comms/message_reference.py          |   4 +-
 src/agent_comms/messages.py                   |   6 +-
 src/agent_comms/native_input_record.py        |  21 +-
 src/agent_comms/native_prompt_binding.py      |  14 +-
 src/agent_comms/native_runtime_input.py       |   4 +-
 src/agent_comms/native_turn_context.py        |   4 +-
 src/agent_comms/nk_foreground.py              |   6 +-
 src/agent_comms/ordinary_turn_rules.py        |   4 +-
 src/agent_comms/owned_send.py                 |  15 +-
 src/agent_comms/owned_turn.py                 |  16 +-
 src/agent_comms/plan_phases.py                |  90 +++-
 src/agent_comms/private_registry_guard.py     |   4 +-
 src/agent_comms/private_send_claim.py         |   3 +-
 src/agent_comms/private_send_stage.py         |  20 +-
 src/agent_comms/proven_source_coverage.py     |   3 +-
 src/agent_comms/publisher.py                  |   4 +-
 src/agent_comms/queued_input.py               |  19 +-
 src/agent_comms/registration.py               |  17 +-
 src/agent_comms/registry_store.py             |   4 +-
 src/agent_comms/selected_actions.py           |   4 +-
 src/agent_comms/selected_participant.py       |   4 +-
 src/agent_comms/selected_turn.py              |   4 +-
 src/agent_comms/selected_write_plan.py        |   4 +-
 src/agent_comms/task_sources.py               |   6 +-
 src/agent_comms/thread_identity.py            |  18 +-
 src/agent_comms/threads.py                    |  15 +-
 src/agent_comms/todos.py                      |  10 +-
 src/agent_comms/turn_context.py               |   4 +-
 src/agent_comms/turn_goal_account.py          |   6 +-
 src/agent_comms/turn_input_source.py          |   8 +-
 src/agent_comms/turn_inputs.py                |  20 +-
 src/agent_comms/turn_lease.py                 | 124 ++---
 src/agent_comms/turn_runner.py                |   7 +-
 src/agent_comms/typed_table.py                |  23 +-
 tests/goal_stop_journey.py                    |  19 +-
 tests/native_backend_fixture.py               |   5 +-
 tests/test_absence_owners.py                  |   7 +-
 tests/test_acp.py                             |   5 +-
 tests/test_acp_extension.py                   |  35 +-
 tests/test_acp_queue_contract.py              |  15 +-
 tests/test_active_turn.py                     |  12 +-
 tests/test_activity_text.py                   |  14 +-
 tests/test_agent_backend.py                   |  10 +-
 tests/test_atomic_turn_source_owner.py        |   9 +-
 tests/test_backend.py                         |   8 +-
 tests/test_bus.py                             |  38 +-
 tests/test_bus_files.py                       |   8 +-
 tests/test_bus_history_seq.py                 |   4 +-
 tests/test_carry_wake_claim_turn_ids.py       |  85 ++++
 tests/test_channels.py                        |   4 +-
 tests/test_claim_admission_verifier.py        |   7 +-
 tests/test_claim_bus_read.py                  |  23 +-
 tests/test_cli.py                             |  10 +-
 tests/test_context_manifest_deltas.py         |  35 +-
 tests/test_context_source_inspection.py       |   8 +-
 tests/test_coordination_response.py           |   3 +-
 tests/test_current_input_origin.py            |  29 +-
 tests/test_declarations.py                    |  32 +-
 tests/test_envelope_claim_transitions.py      |  19 +-
 tests/test_field_codec.py                     |  63 ++-
 tests/test_goal_answers.py                    |   6 +-
 tests/test_goal_failure_observation.py        |   5 +-
 tests/test_goal_input_review.py               |   6 +-
 tests/test_goal_reply_lock_scope.py           |  17 +-
 tests/test_goal_resume.py                     |   6 +-
 tests/test_goal_standby.py                    |  23 +-
 tests/test_goal_standby_liveness.py           |  41 +-
 tests/test_goal_wait_certified_reply.py       |   5 +-
 tests/test_historical_notifications.py        |  10 +-
 tests/test_history_view_declaration.py        |   3 +-
 tests/test_holder_standing_rules.py           |  18 +-
 tests/test_input_delivery_history.py          |  17 +-
 tests/test_input_disposition.py               |  73 ++-
 tests/test_input_documents.py                 | 197 ++++++--
 tests/test_install.py                         |   3 +-
 tests/test_interrupted_delivery_recovery.py   |   3 +-
 tests/test_l0_goal_input_closure.py           |  17 +-
 tests/test_live_drain_failure.py              |   7 +-
 tests/test_maintenance_barrier.py             |  18 +-
 tests/test_mcp_acceptance.py                  |  28 +-
 tests/test_message_notifications.py           |   7 +-
 tests/test_native_channel_reply_roundtrip.py  |   8 +-
 tests/test_native_context_reference.py        |   2 +-
 tests/test_native_unknown_recovery.py         |   5 +-
 tests/test_observer_death.py                  |   3 +-
 tests/test_optional_awareness_projection.py   |   4 +-
 tests/test_owned_turn_goal_replacement.py     |   4 +-
 tests/test_preflight_feedback.py              |  10 +-
 tests/test_project_resume.py                  |   8 +-
 tests/test_read_ledger.py                     |   4 +-
 tests/test_registration_authority.py          |  23 +-
 tests/test_registration_inheritance.py        |   5 +-
 tests/test_registration_process_identity.py   |   9 +-
 tests/test_registration_transitions.py        |  11 +-
 tests/test_reservation_rules.py               |  19 +-
 tests/test_roster_restoration.py              |   3 +-
 tests/test_selected_tool_broker.py            |   3 +-
 tests/test_task_decisions.py                  |  12 +-
 tests/test_thread_identity.py                 |  20 +-
 tests/test_tool_output.py                     |  24 +-
 tests/test_turn_context_wire.py               |  14 +-
 tests/test_turn_declaration.py                |  26 +-
 tests/test_turn_goal_account.py               |   5 +-
 tests/test_turn_identity_equality.py          |  11 +-
 tests/test_turn_inbox.py                      |   5 +-
 tests/test_turn_lease_release.py              |  16 +-
 tests/test_turn_record.py                     |   7 +-
 tests/test_unscoped_claim_history.py          |  18 +-
 tests/verify_connector_tools.py               |   6 +-
 tools/cutover/carry_wake_claim_turn_ids.py    |  69 +++
 130 files changed, 1775 insertions(+), 932 deletions(-)

@trissim
trissim marked this pull request as ready for review October 23, 2026 22:46
Copilot AI balanced review requested due to automatic review settings October 23, 2026 22:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@trissim
trissim marked this pull request as draft October 23, 2026 22:48
@trissim
trissim marked this pull request as ready for review October 23, 2026 22:50
@github-actions

Copy link
Copy Markdown

debt-src at 76b6605, every finding:

grew NoneAbsence:src/agent_comms/typed_table.py +1
introduced NoneAbsence:src/agent_comms/typed_table.py at lines [188]

@trissim
trissim marked this pull request as draft October 23, 2026 22:54
@trissim
trissim changed the base branch from main to refactor/id128-nominal-type October 23, 2026 22:56
@trissim
trissim marked this pull request as ready for review October 24, 2026 00:31
@trissim
trissim merged commit 3fbe446 into refactor/id128-nominal-type Oct 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants