Skip to content

P924: separate automatic answers from turn wake permission - #3581

Merged
trissim merged 34 commits into
mainfrom
work/toad-render--P924
Oct 30, 2026
Merged

trissim merged 34 commits into
mainfrom
work/toad-render--P924

Conversation

@trissim

@trissim trissim commented Oct 29, 2026 •

Copy link
Copy Markdown
Contributor

P924: automatic replies use their original answer references once

31 commits ahead of main a8a71d7; 37 files, +1,318/-272, including carried #3594 head28b2249 exact-turn work. Current pushed head: 798669f.

Latest independent source correction, relative to3b406776: 3 files, +11/-5. NativeRecord selects final publications with a bool rather than returning unused nullable data; ClientId.external declares its real foreign encoder boundary. The reviewed3b reply policy, all controls, both moved RecordedEntry methods and generated native schema/manifest are unchanged. Main and ordered3594 head28b2249 are already ancestors; no new merge was needed.

Staged dependency, not whole-carrier delivery: root41000 assigns canonical recognition/member-relocation proof to claude-nra/P872, Core#3606 plus its existing audit PR. The exact reviewed Core3606 head and canonical audit pin have not been supplied. No arbitrary candidate, gate waiver, duplicate resolver or adapter edit is included here. Once root supplies that immutable head, merge it into this same PR and migrate AgentCommsProject.absence_boundaries to the two actual marker callables. Source/behavioral/gate/native/install acceptance remains open.

Prior correction, relative to7a3f: 3 files, +21/-23 in 9c116145f (delete answer recomputation/clamping) and 3b406776f (SourceTurn owns external acquisition).

computed the exact originals
asked the registry to compute them again
intersected the answer with the answer
deleted the second examination board

Current owner and consumer structure

MessageKind.allows_automatic_reply(message)
  default: bool(message.sender_role.human(message))
  NeedsAnswerKind override: True
    QuestionKind / HandoffKind / AlertKind inherit it

Message.automatic_reply_targets()
  declared kind capability + existing destination routing

ReplyingThreadOutput.end_turn(turn_id)
  resolve original bus messages from transcript.opening_for(turn_id)
  group their eligible original references by destination
  send(answers=tuple(references))
    existing send validation checks exact identities and recipient consumption

Messaging._answered_by(owner, target, source_turn)
  retain ordinary native lease inference
  add source_turn.external_answers(existing closed owner handles)

SourceTurn.external_answers(...) -> ()
NamedSourceTurn.external_answers(...)
  owns registry/bus acquisition and its existing exact-turn read

The output already holds each target's exact eligible references. It now passes them directly through the existing validated answers parameter. AutomaticReplyTurn, both answering_references methods, their import and clamp are deleted. No new answer store, class, boolean flag, kind roster, sender/body filter, compatibility path or extra inference policy.

Formal defect: IDEN-6, fact = which original messages the final answers; at = old messaging.py:116-126 and turn_item.py:58-66; derive = the original-reference grouping in end_turn; by = runtime_updates.py:284-289 and the existing validated send parameter. The rejected clamp preserved a second computation of that fact. It is gone, not renamed.

The source_turn parameter and actual Claude/Codex NamedSourceTurn producers remain. SourceTurn's empty default returns no external answers. NamedSourceTurn alone enters NativeCapture and the bus read, then resolves opening_for(self.id) and destination matching. Messaging no longer owns that walk. NativeCapture construction only stores its bus/measurement owner; registry/activity acquisition is in enter. ExternalTranscript is a frozen root/incarnation value; its transcript read occurs only in the named member. Thus the empty source opens neither external transcript nor registry for this inference. Type-only method annotations introduce no high-level runtime import into turn_item; actual read owners arrive as already constructed values.

Explicit answers= remain validated and valid, including intentional INFO acknowledgements. Ordinary native-lease inference is unchanged. Ordinary explicit NamedSourceTurn sends still infer their original references. No global prohibition on answering INFO.

Wake, answer obligation and context remain separate

The existing MessageKind capability defaults to the nominal human-role operation; existing NeedsAnswerKind owns the override. Message joins that semantic answer obligation to CommandTarget/ThreadTarget's unchanged destination algorithm. Human inputs remain InfoKind. Channels require explicit sends.

ReceivingMonitor still confirms every completely matched INFO/ACK/notice before returning opening references. INFO may open and complete a handled turn, retaining assistant text, without receiving another automatic DM. No context is filtered out; no unrelated request is cleared.

Preserved exact-turn integration

Published #3594 head28b2249 was merged once into this same PR, retaining original #3581 and #3594 history. Current main a8a71d7 is included by normal merge, without reset, force push or copying foreign trees.

Carried mechanisms: immutable original opening references; ordered input evidence; prompt/turn identity through Monitor/Read/Codex observations; source-specific explicit send inference; turn/item publication attachments; pending final completion; deduplication; cancellation/retirement; repeated completion/catchup idempotence; twelve independent directives and exact native input/ancestry bounds. Root integrates overlapping published heads once.

Controls: authored and preserved, not author-executed

tests/test_claude_automatic_reply.py retains:

  • INFO and ACK originals: confirmed opening, retained Holding, zero automatic DM.
  • Question/Handoff/Alert: one final to the original direct sender.
  • Actual human send operation: InfoKind retains its direct answer.
  • NoticeRole Question: confirmed, no opening/reply, final transcript retained.
  • Explicit-only channel sends; mixed channel/DM final stays private.
  • Same-sender and different-sender INFO+Question variants: both original references remain ordered openings; generated final.answers is exactly (question.reference,).
  • Explicit INFO answer and ordinary NamedSourceTurn control: both retain intended INFO answer linkage; unrelated automatic text still sends nothing.
  • Finite two-existing-ClaudeBridge journey: Question -> one Info final with exact original link -> confirmed Info -> retained Holding -> no third DM, including repeated completion/confirmation.
  • Opening versus mid-output/tool/human prefixes, following-turn routes, exact commander/Codex attribution, interrupted/thinking-only/still-open/empty-final directive variants, all-active-window retirement and reused-prompt refusal.

Ordinary agent request fixtures explicitly use QuestionKind rather than accidental defaultInfo. The existing monitor direct/channel family now declares that kind; channel information remains InfoKind. Existing diagnostic NoticeRole and human-direct monitor controls, including both terminal-update variants, remain.

The latest correction does not change any of these controls. Root owns execution. No author tests, collection, ratchets, App, provider, installation, service operation or replay were run for these source corrections. Source-only parsing/in-memory compilation and diff checks passed. Deleted-name search covers Core src/tests/tools and Toad src/tools after proving the Toad path finds known MessageReference consumers; no AutomaticReplyTurn/answering_references callers remain.

Actual native contract and normal builder result

The carried NativeInputCommit.session_entry_id changes str -> FreshNativeId. Its declaration-generated native_context_journal schema gains a TEXT type CHECK. The old manifest did not match that contract.

On1973, ran the explicitly requested normal builder once under low priority and a 180-second timeout:

TMPDIR=/home/ts/.cache/agent-scratch/toad-render/p924-native-repin \
  timeout -s INT 180 nice -n 19 ionice -c3 \
  ./stack/native/prepare-pi-native \
  --python /home/ts/code/projects/agent-comms/.venv/bin/python --update-pins

It completed NATIVE_REPIN_OK, rendering the declaration-owned schema and regenerating its manifest entry, tree digest and source-input stamp. Built tree 724dbf68818d1932e6981b737b8e1a8cf4280e592f4d63013306e41e9d15feb8 exactly matches the earlier hosted failure's built tree; stock stays Pi0.85.1. No generated schema/hash was hand-edited. These schema/manifest bytes are unchanged by the latest source correction; there is no claim of another builder run or installed acceptance.

Log: /home/ts/.cache/agent-scratch/toad-render/p924-native-repin.log. Builder temporary trees cleaned; own TMPDIR removed. Resource helper path was absent; direct readings showed515GiB disk free/2.4GiB available RAM before the single bounded builder.

Optional findings: exact source disposition, no waiver

Evidence: p924-back-optional-evidence.json and p924-back-optional-before.diff in own scratch.

  • NativeEntry -> RecordedEntry tracked_user and require_tracked_user: complete method AST-identical moves, including the existing Optional spelling.
  • NativeRecord.publication_producer is deleted. is_final_publication() -> bool at native_transcript.py:205 retains require_entry first, returns False for a valid nonfinal entry, and requires entry ID before True. Its sole consumer publication_input at:445 uses that predicate; reverse bounds and exact tracked input ancestry are unchanged. The discarded producer local and None branch are gone, with no wrapper or internal codec marker.
  • ClientId.external at codex_protocol.py:208 is the real foreign string/null serializer contract, not a moved method. It now uses the canonical typed no-op boundary_encoder declared at field_codec.py:88; property/abstractmethod behavior and NoClientId/ForeignClientId/BusClientId are unchanged. The actual UserItem PlainSerializer at codex_protocol.py:483 still consumes identity.external. boundary_decoder remains decoder-only.

The four previously reported gate findings are not claimed green. P872 owns recognizing the two unique identical ancestor-member moves and the genuine boundary markers in the canonical audit. The project adapter migration is staged behind root's accepted Core3606 head/pin. No inline tools/debt_ratchet.py edit, per-function exception, decoder misdeclaration, object/Any widening or author checker run.

Source evidence and history

Retained root census originally covered625 modules; the existing retained corpus covers614 production modules. This correction uses only four owner modules on that existing map, via NRA ModuleSyntaxIndex; no new corpus scan. Targeted source parsing/in-memory compilation and diff checks passed. Exact blob comparison preserves the3b policy, both control files, moved-member module and native generated bytes. Old producer search across Core src/tests/tools has no remaining callers; the earlier full related-root search found no Toad caller. Dynamic binding and runtime behavior remain outside this syntax evidence. Map: /home/ts/.cache/agent-scratch/toad-render/p924-automatic-reply-owner-census.json. No permanent scanner or executable authority added.

#3594 disposition is separate: its current ad6a752 head is not an ancestor of this branch. Legal Claude promptId reuse still lacks occurrence identity/carry, and its refusal-asserting control remains at test_claude_automatic_reply.py:316–327. slot-activity41079 explicitly retains that source work after P958; root retains trusted tools/call _meta and combined twelve-directive/carry/live proof. #3594 is not fully carried or closed.

History is explicit: old six-plus-four passes belong to earlier reply semantics. e86 missed the same-sender case.1973 added a clamp and was rejected for recomputation;7a3f merely merged main and did not repair that defect.9c116145f deletes the clamp;3b406776f moves named acquisition into SourceTurn. Earlier tests are not claimed to qualify this head.

Assumed: root retains combined control execution, exact-head review/merge and actual installed INFO/asked-DM/human-DM proof. No merged, installed, loop-termination, answer-link behavioral pass or frontend speedup claim from source authoring.

@trissim
trissim marked this pull request as ready for review October 29, 2026 04:27
Copilot AI balanced review requested due to automatic review settings October 29, 2026 04:27
@trissim
trissim enabled auto-merge October 29, 2026 04:27

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 disabled auto-merge October 29, 2026 04:30
trissim and others added 19 commits October 29, 2026 03:26
main's 1492f6b already routes confirmed monitor replies through
CommandTarget.automatic_reply_targets, which keeps a session's final text off
shared channels; this branch's exact_reply_target hunk is superseded by it.
The routing test's channel-mention case now expects no automatic reply, the
owner's policy: shared destinations need an explicit send.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RnH6dR85kyFKcc2tQAJLhK
@trissim trissim changed the title Derive CLI monitor reply routes from the existing response policy P924: separate automatic answers from turn wake permission Oct 29, 2026
@github-actions

github-actions Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

debt-src at 25bc3f6, every finding:

grew ClientTypeErrors:batrachian-toad/src/toad/widgets/sidebar_tree.py +1: this change removes or changes an agent_comms name that client file uses; run mypy on it to see which
::warning file=src/agent_comms/cli_bridges/claude_protocol.py::LintFindings +4 (warns, never blocks)
::warning file=src/agent_comms/cli_bridges/codex_protocol.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/cli_bridges/shared.py::LintFindings +5 (warns, never blocks)
::warning file=src/agent_comms/external_transcript.py::LintFindings +5 (warns, never blocks)
::warning file=src/agent_comms/harness_delivery_states.py::LintFindings +2 (warns, never blocks)
::warning file=src/agent_comms/historical_native_inputs.py::LintFindings +5 (warns, never blocks)
::warning file=src/agent_comms/messaging.py::LintFindings +2 (warns, never blocks)
::warning file=src/agent_comms/native_input_record.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/native_runtime_input.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/native_transcript.py::LintFindings +3 (warns, never blocks)
::warning file=src/agent_comms/private_send_rules.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/runtime_updates.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/tools.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/turn_digests.py::LintFindings +3 (warns, never blocks)
::warning file=src/agent_comms/turn_item.py::LintFindings +3 (warns, never blocks)
::warning file=src/agent_comms/turn_lease.py::LintFindings +1 (warns, never blocks)
::warning file=src/agent_comms/turn_item.py::Unformatted +1 (warns, never blocks)

@trissim
trissim added this pull request to the merge queue Oct 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 30, 2026
@trissim
trissim added this pull request to the merge queue Oct 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Oct 30, 2026
@trissim
trissim merged commit 799855d into main Oct 30, 2026
9 checks passed
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