Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions evidence/dm-initial-publication-20261008/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -647,3 +647,64 @@ incoming messages; its route ended at Window. That source observation also
included the merged prepared-style rule and preceded the final single-dispatch
correction, so its aggregate timings are not a causal measurement of this patch.
Neither this viewport change nor the native mount candidate is published live.


## Published document wheel / native mount integration

Textual120 and Toad571 merged. Matched published frontend: Toad fbb8e395d,
Textual c330608250, unchanged Core client09a0131ab. Full954assets /69packages /
2857RECORD entries and retained native Pi matched.

Actual installed private-driver observation preserved160 ordered wheel packets,
three reversals and20 incoming messages /16recipients, provider0. Wheel median
3.88ms/p95 78.80/max219.98; backlog after final post3.86ms. Frame p95 109.87ms/
max337.05; loop max105.21. Overall pacing still FAIL, not a statistical speedup
claim. Timer update reached61.32ms UI CPU; layout48.81ms UI CPU.

Installed real-click disclosure passed: no closed body, opened body current, live
error, closed update deferred, reopen current, original pre-mount explicit read.
Reviewed frontend publisher changed NEW launches only; backend defaults, active
route and native package preserved. Existing windows keep imported modules.
Receipt: `.artifacts/document-wheel-routing-delivery-20261008/live-publication.json`.
Raw build/App/disclosure/publication files remain in
`/home/ts/.cache/agent-scratch/prepared-style-measurement-20261008/`.

Removed55,187,908bytes of superseded never-published native-mount candidate
runtime after fresh privileged census226processes/no gaps/no refs and separate
default/publication checks. Wheels/source/proofs/raw and actual published/rollback
runtimes retained. The first evidence append met absent sparse-checkout path;
no evidence was changed then. Materialized original HEAD bytes and appended here.

Next work is original synchronous geometry/layout and paint publication; native
capture/FIFO is preserved rather than bypassed to mask its costs.


## Wire row resources owned by composition

WireMarkdownMessage and IRCMessage now retain the actual body and notification
widgets created by their original compose methods. Recomposition acquires fresh
resources; unmounted resources cannot supply read/extent evidence. Compact and
full Markdown remain distinct rendering contracts. CommsChatView uses the row's
notification resource, revalidating attachment after the asynchronous read.
Three body queries and the per-row notification descendant query are deleted.
No message, read ledger, status or preparation result is copied.

AST:288 production/417 authored modules parsed, zero omissions. All changed row
family body/feedback selector calls are gone. The separate incoming/outgoing
transcript WireMessageHandling queries belong to another declared resource
family; this change does not claim to replace them.

Existing real private wire partial-paint control passed: only painted bodies
acknowledged, scrolling admits the remaining original page and compact/Markdown
style replacement preserves identities/read results. Actual private Toad App
resource control passed: both styles own their mounted children, recomposition
replaces retired instances and removed bodies cannot authorize reads. First
resource fixture used a bare Screen without the real history viewport and failed
its Markdown admission; preserved, then corrected to the real wire/window.
No production fallback or timeout changed.

Raw/source control files are under
`/home/ts/.cache/agent-scratch/dm-owned-resources-20261008/`. Speed improvement is
unmeasured. The next required installed observation also retains Layout.widget
identity and original node/layout source epochs in the existing recorder so
native work can distinguish real changed extents from repeated late requests.
5 changes: 2 additions & 3 deletions src/toad/widgets/comms_chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@
)
from toad.widgets.flash import Flash
from toad.widgets.prompt import Prompt
from toad.widgets.message_notifications import MessageNotifications
from toad.owner_preparation import read_thread_presentation
from toad.screens.session_view import SessionView
from toad.command_catalog import CommandCatalog
Expand Down Expand Up @@ -318,8 +317,8 @@ async def _read_notifications(self, rows: tuple[tuple[WireMessage, Widget], ...]
visible = {widget for _, widget in self._visible_notification_rows()}
for message, widget in rows:
if widget in visible:
feedback = next(iter(widget.query(MessageNotifications)), None)
if feedback is None:
feedback = widget.notifications
if feedback is None or not feedback.is_attached:
continue # Style replacement has unmounted this row's children.
if error is not None:
feedback.show_error(error)
Expand Down
25 changes: 15 additions & 10 deletions src/toad/widgets/irc_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ class WireMarkdownMessage(CoreEventReceiver, ConversationBlock, VerticalGroup):
def __init__(self, message: Message, *, direction: str = "Inbound"):
super().__init__()
self.message = message
# Composition acquires these native resources. Recomposition replaces
# them; the row never borrows a retired body from a selector cache.
self.body = None
self.notifications = None
self.direction = (
f"History · {message.source.original_root} · @{message.sender} incarnation {message.sender_created_at}"
if isinstance(message, HistoricalMessage) else direction
Expand All @@ -104,7 +108,8 @@ def __init__(self, message: Message, *, direction: str = "Inbound"):
def compose(self) -> ComposeResult:
yield MessageDivider(self.direction, clock=MessageClock.recorded(self.message.timestamp))
yield from self.compose_body()
yield MessageNotifications()
self.notifications = MessageNotifications()
yield self.notifications

def compose_body(self) -> ComposeResult:
from toad.widgets.agent_response import AgentResponse
Expand All @@ -114,7 +119,8 @@ def compose_body(self) -> ComposeResult:
yield ThreadLink(self.message.sender, source)
yield Static(" → ", markup=False, expand=False)
yield ThreadLink(self.message.target, source)
yield AgentResponse(self.message.body, show_divider=False)
self.body = AgentResponse(self.message.body, show_divider=False)
yield self.body
if self.message.mentions:
with HorizontalGroup():
yield Static("Mentioned: ", expand=False)
Expand All @@ -123,14 +129,12 @@ def compose_body(self) -> ComposeResult:

def read_ack_widget(self) -> Widget | None:
"""Only the rendered message body can authorize a read."""
from toad.widgets.agent_response import AgentResponse

return self.query_one(AgentResponse)
return self.body if self.body is not None and self.body.is_attached else None

@property
def native_extent_ready(self) -> bool:
"""Paging borrows the body's real extent, not its loading placeholder."""
return self.read_ack_widget().body_ready
return self.body is not None and self.body.is_attached and self.body.body_ready

def action_open_target(self, target: str):
if isinstance(self.message, HistoricalMessage) and not target.startswith("#"):
Expand Down Expand Up @@ -160,16 +164,17 @@ class IRCMessage(WireMarkdownMessage, can_focus=True):
"""

def compose_body(self) -> ComposeResult:
yield IRCMessageText(IRCMessageSource(self.message))
self.body = IRCMessageText(IRCMessageSource(self.message))
yield self.body

def read_ack_widget(self) -> Widget | None:
"""Only the text block can authorize a read, never its divider."""
body = self.query_one(IRCMessageText)
return body if body.paint_ready else None
body = self.body
return body if body is not None and body.is_attached and body.paint_ready else None

@property
def native_extent_ready(self) -> bool:
return self.query_one(IRCMessageText).preparation_complete
return self.body is not None and self.body.is_attached and self.body.preparation_complete

def get_clipboard_text(self) -> str:
return f"{self.message.sender} → {self.message.target}: {self.message.body}"
Loading