diff --git a/evidence/cold-recent-publication-20261008/SOURCE.md b/evidence/cold-recent-publication-20261008/SOURCE.md new file mode 100644 index 000000000..44a5356bd --- /dev/null +++ b/evidence/cold-recent-publication-20261008/SOURCE.md @@ -0,0 +1,60 @@ +# Cold recent-page preparation through existing renderer owners + +Baseline: published frontend 1ec/main625, installed default Core3e/native0f. +Candidate keeps those exact Core/native wheels, SDK0.12.1 and Python3.14.2. +No global package changes, owner restart, source/session fork or submitted input. +Original existing App observer and original ACP CLI were instrumented; their +normal attachment uses ExistingSessionLoadAdmission for original owner477574. +Raw clocks are retained in `.artifacts/cold-recent-publication-20261008`. + +## Source and decision + +AgentProcess acquires a connection with original command/env/cwd/route custody. +AgentSession.initialize keeps the response on that connection; initialization +builds capabilities through Core SessionLifecycle, without reading history. +Load attaches to the existing owner; ordered notification validation and the +independent response metadata decoder retain their distinct contracts. +SnapshotPublication validates captured source/native resources before and after +worker preparation, mounts provisional history, commits coverage, retires the +original captured cohort and calls painted. None of these decisions changed. +TranscriptHistory uses PreparedContentRange.initial_slice(newest=True), retaining +four recent fragments, or restores original reader admission. Its body preparation +uses SnapshotPublication's actual selected categories. Metadata/tool disclosures +retain their original lazy owners. No recent-first loader correction was needed. + +Actual two Markdown bodies were 24/241 characters. Their worker executes took +23ms each while first-use submission waited419/457ms. Removing unrelated editor +and patch imports alone did not reduce that delay. Import tracing then established +354/366ms importing render_tasks, principally required native Markdown/Textual. +Shared original worker initializer now acquires the rendering declarations beside +SDK ingress during bootstrap, before recent-page admission. Native editor and +patch implementation imports live in their original task execute/accept methods. +Both local and persistent renderers already use that same initializer. No dummy +job, task registry, decoder, adapter, cache or admission expansion was added. + +## Qualification + +Measured admitted-body preparation fell from395-462ms to39-40ms; publication +fell from492-590ms to97-116ms. Parent's earlier published run measured~800ms body +preparation. Total opening varied and has no demonstrated overall gain. Final +open had no App error, same147260275 frontier, four bodies and zero loaders. +Draft typing was accepted during attachment and restored before close; pilot.press +includes its own settling wait, so its301ms is not physical key-delivery latency. +App scheduling maximum64ms is not native wheel/layout acceptance. + +Final initialize1.255s: instrumented Core imports1.175s, Comms construction43ms, +CommsClient construction5ms, initialize handler0.3ms. Bootstrap is still the +remaining large wait. Core608d/84 remains source checkpoints, not default backend. +This change does not claim to solve the reported five-second cold opening. + +NRA SourceModule/module_syntax_index parsed862 production modules across Toad, +Core and native roots with zero omissions. Before/after import and consumer sites +are retained here; dynamic external imports are not an exhaustive behavioral proof. +Original Markdown, partition, patch and native document task execute/storage/result +acceptance passed in the candidate wheel. Persistent renderer execution remains +unverified here because optional ZMQRuntime is absent. Existing viewport, capture, +native layout, resource admission, notification order and currentness are untouched. + +Owned disposable settings/state were removed. Candidate runtime/wheel and compact +raw timings remain at the named artifact path for integration; no other scratch +or retained evidence was removed. diff --git a/evidence/cold-recent-publication-20261008/ast-after.json b/evidence/cold-recent-publication-20261008/ast-after.json new file mode 100644 index 000000000..196f83ee7 --- /dev/null +++ b/evidence/cold-recent-publication-20261008/ast-after.json @@ -0,0 +1,56 @@ +{ + "modules": 862, + "omissions": [], + "sites": [ + [ + "src/toad/tool_output.py", + 195, + "from toad.render_tasks import PatchRenderTask" + ], + [ + "src/toad/render_choices.py", + 24, + "from toad.render_processes import RenderProcessPool" + ], + [ + "src/toad/render_service.py", + 12, + "from toad.render_processes import _initialize_worker" + ], + [ + "src/toad/widgets/worker_static.py", + 26, + "from toad.render_tasks import RichRenderTask" + ], + [ + "src/toad/widgets/prepared_markdown.py", + 25, + "from toad.render_tasks import MarkdownRenderTask" + ], + [ + "src/toad/widgets/transcript_fragments.py", + 49, + "from toad.render_processes import RenderProcessPool" + ], + [ + "src/toad/widgets/transcript_fragments.py", + 275, + "from toad.render_tasks import MarkdownRenderTask" + ], + [ + "src/toad/widgets/tool_content.py", + 16, + "from toad.render_tasks import PatchRenderTask" + ], + [ + "src/toad/widgets/streaming_markdown.py", + 21, + "from toad.render_tasks import MarkdownPartsTask, MarkdownRenderTask" + ], + [ + "src/toad/widgets/context_explorer.py", + 223, + "from toad.render_tasks import ReadOnlyDocumentRenderTask" + ] + ] +} \ No newline at end of file diff --git a/evidence/cold-recent-publication-20261008/ast-before.json b/evidence/cold-recent-publication-20261008/ast-before.json new file mode 100644 index 000000000..bf2c0468a --- /dev/null +++ b/evidence/cold-recent-publication-20261008/ast-before.json @@ -0,0 +1,303 @@ +{ + "modules": 612, + "omissions": [], + "sites": [ + [ + "src/toad/render_tasks.py", + 8, + "ImportFrom", + [ + "PreparedTextArea" + ] + ], + [ + "src/toad/render_tasks.py", + 12, + "ImportFrom", + [ + "prepare_tokens" + ] + ], + [ + "src/toad/render_tasks.py", + 13, + "ImportFrom", + [ + "prepare_patch" + ] + ], + [ + "src/toad/render_tasks.py", + 22, + "ClassDef", + [ + "ReadOnlyDocumentRenderTask" + ] + ], + [ + "src/toad/render_tasks.py", + 38, + "ClassDef", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/render_tasks.py", + 53, + "ClassDef", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/render_tasks.py", + 72, + "ClassDef", + [ + "MarkdownPartsTask" + ] + ], + [ + "src/toad/render_tasks.py", + 92, + "ClassDef", + [ + "RichRenderTask" + ] + ], + [ + "src/toad/render_tasks.py", + 44, + "Name", + [ + "prepare_patch" + ] + ], + [ + "src/toad/render_tasks.py", + 63, + "Name", + [ + "prepare_tokens" + ] + ], + [ + "src/toad/render_tasks.py", + 29, + "Name", + [ + "PreparedTextArea" + ] + ], + [ + "src/toad/tool_output.py", + 195, + "ImportFrom", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/tool_output.py", + 200, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/markdown_preparation.py", + 56, + "FunctionDef", + [ + "prepare_tokens" + ] + ], + [ + "src/toad/widgets/worker_static.py", + 26, + "ImportFrom", + [ + "RichRenderTask" + ] + ], + [ + "src/toad/widgets/worker_static.py", + 35, + "Name", + [ + "RichRenderTask" + ] + ], + [ + "src/toad/widgets/worker_static.py", + 182, + "Name", + [ + "RichRenderTask" + ] + ], + [ + "src/toad/widgets/patch_diff.py", + 175, + "FunctionDef", + [ + "prepare_patch" + ] + ], + [ + "src/toad/widgets/prepared_markdown.py", + 25, + "ImportFrom", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/prepared_markdown.py", + 302, + "Name", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/transcript_fragments.py", + 275, + "ImportFrom", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/transcript_fragments.py", + 277, + "Name", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 16, + "ImportFrom", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 50, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 79, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 159, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 141, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 160, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 138, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/tool_content.py", + 201, + "Name", + [ + "PatchRenderTask" + ] + ], + [ + "src/toad/widgets/streaming_markdown.py", + 21, + "ImportFrom", + [ + "MarkdownPartsTask", + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/streaming_markdown.py", + 132, + "Name", + [ + "MarkdownPartsTask" + ] + ], + [ + "src/toad/widgets/streaming_markdown.py", + 62, + "Name", + [ + "MarkdownRenderTask" + ] + ], + [ + "src/toad/widgets/context_explorer.py", + 11, + "ImportFrom", + [ + "PreparedTextArea" + ] + ], + [ + "src/toad/widgets/context_explorer.py", + 219, + "Name", + [ + "PreparedTextArea" + ] + ], + [ + "src/toad/widgets/context_explorer.py", + 223, + "ImportFrom", + [ + "ReadOnlyDocumentRenderTask" + ] + ], + [ + "src/toad/widgets/context_explorer.py", + 226, + "Name", + [ + "ReadOnlyDocumentRenderTask" + ] + ] + ] +} \ No newline at end of file diff --git a/evidence/cold-recent-publication-20261008/runs.json b/evidence/cold-recent-publication-20261008/runs.json new file mode 100644 index 000000000..a7afdf92a --- /dev/null +++ b/evidence/cold-recent-publication-20261008/runs.json @@ -0,0 +1,118 @@ +[ + { + "run": "open", + "error": null, + "provider_inputs": 0, + "visible": { + "t": 6.3845499199815094, + "clock": 964735.799802173, + "name": "history.visible", + "cursor": 147260275, + "ready": true, + "loading": 0, + "bodies": 4 + }, + "AgentSession.initialize": 1.2663798689609393, + "AgentSession.load": 0.42861824901774526, + "TranscriptHistory.prepare_body": 0.4577785470755771, + "SnapshotPublication.publish_page": 0.5721763509791344, + "total_open": 3.86478916706983, + "draft": null, + "loop": null + }, + { + "run": "candidate", + "error": null, + "provider_inputs": 0, + "visible": { + "t": 7.342997727100737, + "clock": 964825.753449441, + "name": "history.visible", + "cursor": 147260275, + "ready": true, + "loading": 0, + "bodies": 4 + }, + "AgentSession.initialize": 1.5278954609530047, + "AgentSession.load": 0.488658839953132, + "TranscriptHistory.prepare_body": 0.4616966719040647, + "SnapshotPublication.publish_page": 0.5901343850418925, + "total_open": 4.246359543991275, + "draft": null, + "loop": null + }, + { + "run": "import-open", + "error": null, + "provider_inputs": 0, + "visible": { + "t": 4.979679779033177, + "clock": 964860.732974071, + "name": "history.visible", + "cursor": 147260275, + "ready": true, + "loading": 0, + "bodies": 4 + }, + "AgentSession.initialize": 1.2548370129661635, + "AgentSession.load": 0.5440245890058577, + "TranscriptHistory.prepare_body": 0.3945252359844744, + "SnapshotPublication.publish_page": 0.4920844399603084, + "total_open": 3.476080255000852, + "draft": null, + "loop": null + }, + { + "run": "completed", + "error": null, + "provider_inputs": 0, + "visible": { + "t": 5.402098145917989, + "clock": 964909.985796074, + "name": "history.visible", + "cursor": 147260275, + "ready": true, + "loading": 0, + "bodies": 4 + }, + "AgentSession.initialize": 1.2629758981056511, + "AgentSession.load": 0.9341113039990887, + "TranscriptHistory.prepare_body": 0.038554170983843505, + "SnapshotPublication.publish_page": 0.0974126560613513, + "total_open": 3.5720663799438626, + "draft": null, + "loop": null + }, + { + "run": "acceptance", + "error": null, + "provider_inputs": 0, + "visible": { + "t": 4.820359833072871, + "clock": 964982.313830981, + "name": "history.visible", + "cursor": 147260275, + "ready": true, + "loading": 0, + "bodies": 4 + }, + "AgentSession.initialize": 1.2548339229542762, + "AgentSession.load": 0.8665150220040232, + "TranscriptHistory.prepare_body": 0.04029429191723466, + "SnapshotPublication.publish_page": 0.11639040498994291, + "total_open": 3.3897179290652275, + "draft": { + "t": 2.27761263307184, + "clock": 964979.771083751, + "name": "draft.accepted", + "delay": 0.3012597889173776, + "accepted": true + }, + "loop": { + "t": 4.820398346055299, + "clock": 964982.313869213, + "name": "loop.delivery", + "max_delay": 0.06403053203597665 + } + } +] \ No newline at end of file diff --git a/src/toad/render_processes.py b/src/toad/render_processes.py index c258b85a0..cff4f063e 100644 --- a/src/toad/render_processes.py +++ b/src/toad/render_processes.py @@ -24,15 +24,18 @@ def _initialize_worker() -> None: - """Acquire typed ingress declarations without borrowing an agent identity. + """Acquire ingress and rendering declarations without an agent identity. These application workers serve both rendering and ACP validation. Finish - the required SDK imports during their own startup, before the first ordered - notification lends them a task. No notification or rendering job is made. + the required SDK and body rendering imports during their own startup, + before a notification or recent page lends them a task. Editor and patch + implementations remain owned by those tasks, rather than Markdown startup. + No notification or rendering job is made. """ os.environ.pop("PI_AGENT_ID", None) os.environ.pop("AGENT_COMMS_THREAD", None) from toad.acp import sdk_boundary # noqa: F401 -- declare worker ingress capabilities + from toad import render_tasks # noqa: F401 -- declare worker rendering capabilities class RenderProcessPool(Renderer): diff --git a/src/toad/render_tasks.py b/src/toad/render_tasks.py index 58ea1a200..15b4e5937 100644 --- a/src/toad/render_tasks.py +++ b/src/toad/render_tasks.py @@ -3,20 +3,22 @@ from __future__ import annotations from dataclasses import dataclass +from typing import TYPE_CHECKING from textual.document._document import DocumentBase from textual.document._wrapped_document import WrappedDocument -from textual.widgets import PreparedTextArea from toad.render_backend import ReusableRenderTask from toad.markdown_preparation import PreparedMarkdown, PreparedMarkdownPart, prepare_tokens -from toad.widgets.patch_diff import PreparedPatch, prepare_patch from toad.rich_preparation import ( PreparedRichContent, RichPresentation, RichSource, ) +if TYPE_CHECKING: + from toad.widgets.patch_diff import PreparedPatch + @dataclass(frozen=True) class ReadOnlyDocumentRenderTask(ReusableRenderTask[WrappedDocument]): @@ -26,6 +28,8 @@ class ReadOnlyDocumentRenderTask(ReusableRenderTask[WrappedDocument]): tab_width: int def execute(self) -> WrappedDocument: + from textual.widgets import PreparedTextArea + return PreparedTextArea.prepare_document(self.source, self.width, self.tab_width) def accept_result(self, result: object) -> WrappedDocument: @@ -35,15 +39,19 @@ def accept_result(self, result: object) -> WrappedDocument: @dataclass(frozen=True) -class PatchRenderTask(ReusableRenderTask[PreparedPatch]): +class PatchRenderTask(ReusableRenderTask["PreparedPatch"]): source: str ansi: bool dark: bool def execute(self) -> PreparedPatch: + from toad.widgets.patch_diff import prepare_patch + return prepare_patch(self.source, self.ansi, self.dark) def accept_result(self, result: object) -> PreparedPatch: + from toad.widgets.patch_diff import PreparedPatch + if not isinstance(result, PreparedPatch): raise TypeError("Patch renderer returned an invalid result") return result