Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
c82bd3a
Use one observed private lifetime for physical Toad runs
trissim Nov 1, 2026
6afd1a5
Freeze run operations and retain exact child retirement evidence
trissim Nov 1, 2026
7d776bb
Give physical runs an explicit framebuffer and reject clipped windows
trissim Nov 1, 2026
f1e689b
Record the debugger context repair and private functional journey
trissim Nov 1, 2026
b0e83fe
Detach pager retirement joins from the cancelled worker context
trissim Nov 1, 2026
c08b219
Record the qualified pager retirement app controls
trissim Nov 1, 2026
06f307a
Compare recorded runtime inputs before physical UI input
trissim Nov 1, 2026
e13d1fe
Keep narrow message headers and receipts readable through shared rows
trissim Oct 31, 2026
d5dabdb
Derive four-edge sidebar geometry and controls from crossing capabili…
trissim Oct 31, 2026
16a6086
Migrate the tool header to the shared variable-height line block
trissim Oct 31, 2026
9672035
Inherit the cursor grouping and direction contract once
trissim Oct 31, 2026
a834afa
Own sidebar content clearance once and preserve resize minimums
trissim Oct 31, 2026
971a101
Resize from native parent geometry without percentage round trips
trissim Oct 31, 2026
f0cd49a
Own session sidebars before native composition and through retirement
trissim Nov 1, 2026
3de4ec3
Derive sidebar presentation from current native attachment
trissim Nov 1, 2026
620955b
Verify physical runtime builds at the frontend resource lifetime
trissim Nov 1, 2026
0264972
Ask the storage rule to verify physical-run isolation
trissim Nov 1, 2026
a12c5b9
Merge commit '3de4ec3cae302cb63e1b73116e5a1f3202efe827' into qualific…
trissim Nov 1, 2026
a79769e
Merge commit '0264972385fb663cd37e7a9f70caf762aa7ae0e9' into qualific…
trissim Nov 1, 2026
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
122 changes: 122 additions & 0 deletions docs/performance/cpython-debugger-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
# Remote debugger context: functional candidate, not an installed fix

The accompanying `cpython-debugger-context.patch` belongs to CPython's
`Python/ceval_gil.c`, not Toad's renderer or its runner. It is retained here so
this runner's platform dependency, exact proposed repair and demonstrated scope
are reviewable. It is **not** an alternate launcher, import preload, retry or
permission bypass. No live Python binary/library was replaced.

## Failure and owner

On CPython3.14.8, retained physical run11 and independently read mobile06 fail
before opening the helper:

```
Can't open debugger script .../operation.py
File "<string>", line 1, in <lambda>
KeyError: '__import__'
```

`run_remote_debugger_script` audits/opens/reads/closes source under the
interrupted frame. Only afterward does `run_remote_debugger_source` create its
fresh namespace. The default `PyFile_OpenCodeObject` imports `_io.open`;
`PyImport_Import` consults the interrupted frame's builtins. A legitimate empty
builtin mapping therefore breaks the debugger itself. The interrupted constructor
is unidentified; run14's separate timeout remains unexplained.

Exact source: v3.14.8, commit
`8e6e75d9102e39bed2a2b279203a396741180f12`. The debugger owner file is identical
on the checked compatible3.14.9/3.14.10 tags;3.14.10's file-open/import owners are
also unchanged. NRA's Python AST does not parse these C files; the C call chain
was read manually and checked against installed disassembly.

## Repair and audit difference

The original remote-debugger audit refusal remains first. The existing loader
body becomes one private C callable, invoked through a real Python frame with
interpreter-owned builtins. The original application frame stays in the normal
frame/GC chain. The embedder's open-code hook is still called; global import
behavior, source reading/closing and payload execution are not replaced.

**The complete audit trace is not equivalent.** Successful execution now emits:

1. `cpython.remote_debugger_script(path)`;
2. `compile` / `exec` for the context lambda, filename `<string>`;
3. the existing `compile` / `exec` for payload source, filename `<string>`.

The initial proposal incorrectly put context preparation ahead of the original
audit. Review caught this; the published patch restores that audit gate first.
The extra context events remain explicit. A policy refusing them prevents source
opening and reports a context-entry error. A close error still reports the error
then executes already-read source, matching the original loader body.

## Functional build and native controls

A separately owned3.14.8 build used existing GCC16.1.1/make, no new toolchain,
PGO/LTO/BOLT/JIT/tail-call chase, and at most two make/compileall jobs. Configure,
make and private altinstall completed0 in18.4s/109.6s/13.0s. Built patch SHA256:
`5a679cd8875271a4c7eace7ce088b5f93f261076b929987e1276b6161ef9857d`;
functional binary SHA256:
`e18b6c81a63f9683beca2d20c9e56225da3207b68530bae2eaa26b6bf351e4fe`.
These identify measured artifacts, not a runtime publication. Existing `BoundedRun`
owned process retirement and deadlines; no output for180s failed the stage.
This nonmatching compiler build is **not release-performance evidence**.

One native batch completed0:

- one fresh unpatched empty-builtins child reproduced the source-open failure;
- 18 patched controls: nine cases under full and empty interrupted builtins;
- normal execution; refusing request/compile/exec audit hooks; real embedder-hook
acceptance/refusal; read/close failure; payload failure;
- executing cases retained the original frame and cyclic guard through
`gc.collect`; every case preserved its active exception and builtin mapping;
- all19 typed target identities independently absent after retirement.

These are exercised counterexamples/controls, not a proof over every CPython state.
The guard has other strong references; this is not a sole-root liveness proof.
The fresh control target deliberately runs a busy select loop, not a production
workload. The separate actual Toad run below exercises the unchanged application.
The disposable control extension/script targets never loaded into a user app.

## Actual private Toad

The unchanged shared runner then completed one real default-launcher journey0:
saved history, held PageUp/PageDown, reversal, End, wheel scrolling and normal
retirement. It obtained31 observed callbacks,17 explicit startup-pending results
and one exec result. The screenshot shows saved message bodies and STANDARD
mode; no physical timeout or source-open failure occurred in this run.

Admission checked1013 module locations; HOME/XDG/database/palette, selected and
opened root, and saved-source identities were private. There were **zero ACP
bindings**: this does not qualify bound-ACP behavior, mobile1391 or errors1389.
The controller used the installed source owner to copy history. The target used
the functional interpreter with a byte-compared copy of5295 regular installed
package files, declaration-derived console scripts and an existing Neovim payload
verified through its archive owner. No native download or fabricated build.json.
A setup assertion initially confused Core's package root with site-packages;
that failure is retained, and only script generation was completed afterward.

st/Xvfb/encoder retired0, all four frontend/resource identities were independently
absent, and the copied root was stopped. Original sessions, input dispositions,
phone/editor processes, desktop/pointer and scientific data were untouched.
The separately approved metadata/profile capture remains unused.

## Receipts and remaining work

Owned retained evidence under `/home/ts/.cache/agent-scratch/pi-ui-performance/`:

- `cpython-functional-build.log`, `cpython-functional-startup.log`;
- `cpython-native-controls.log`, `cpython-native-control-absence.log`;
- `cpython-functional-toad-{prepare,finish}.log` and native-payload log;
- `cpython-functional-toad-01/{admitted.json,frontend/end-return.png}`,
typed retirement/copy-stop records and `cpython-functional-toad-absence.log`.

Native case inputs/results and the functional source/prefix are retained under
the allocated Core checkout's `platform-source/` pending review. One-shot build
code was retired after its successful result. Input hashes are observations,
not a new runtime stamp. Integration still needs a qualified interpreter/build
selection: `RuntimeStack.build` currently keys reuse by Core commit and lock
hash only. The runner's repository-identity work must use the existing
`RecordedBuildIdentity`/`RuntimeResolution`/`RuntimePackage` owners; a mutable
prefix/module location is not a repository commit. Installed acceptance and
measured production source-lifetime/performance repair remain open.
79 changes: 79 additions & 0 deletions docs/performance/cpython-debugger-context.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
--- a/Python/ceval_gil.c
+++ b/Python/ceval_gil.c
@@ -1216,22 +1216,16 @@
return 0;
}

-// Note that this function is inline to avoid creating a PLT entry
-// that would be an easy target for a ROP gadget.
-static inline void run_remote_debugger_script(PyObject *path)
+// This private callback is invoked only inside the debugger's Python frame.
+// It remains static: there is no new exported or PLT entry point.
+static PyObject *
+run_remote_debugger_script_body(PyObject *Py_UNUSED(self), PyObject *path)
{
- if (0 != PySys_Audit("cpython.remote_debugger_script", "O", path)) {
- PyErr_FormatUnraisable(
- "Audit hook failed for remote debugger script %U", path);
- return;
- }
-
- // Open the debugger script with the open code hook, and reopen the
- // resulting file object to get a C FILE* object.
+ // Preserve the existing open-code hook, read/close ordering and errors.
PyObject* fileobj = PyFile_OpenCodeObject(path);
if (!fileobj) {
PyErr_FormatUnraisable("Can't open debugger script %U", path);
- return;
+ Py_RETURN_NONE;
}

PyObject* source = PyObject_CallMethodNoArgs(fileobj, &_Py_ID(read));
@@ -1253,6 +1247,47 @@
}
Py_DECREF(source);
}
+ Py_RETURN_NONE;
+}
+
+// Note that this function is inline to avoid creating a PLT entry
+// that would be an easy target for a ROP gadget.
+static inline void run_remote_debugger_script(PyObject *path)
+{
+ // Keep the existing debugger refusal before context compilation/execution.
+ if (0 != PySys_Audit("cpython.remote_debugger_script", "O", path)) {
+ PyErr_FormatUnraisable(
+ "Audit hook failed for remote debugger script %U", path);
+ return;
+ }
+ static PyMethodDef body_definition = {
+ "_run_remote_debugger_script_body",
+ run_remote_debugger_script_body,
+ METH_O,
+ NULL
+ };
+ PyObject *ns = PyDict_New();
+ if (!ns) {
+ PyErr_FormatUnraisable("Can't prepare debugger namespace for %U", path);
+ return;
+ }
+ // PyRun_String initializes this namespace from the interpreter's builtins.
+ // A real Python call frame then owns audit/open/read/close as well as exec;
+ // it neither borrows the interrupted frame's builtins nor detaches its GC roots.
+ PyObject *entry = PyRun_String("lambda load, path: load(path)", Py_eval_input, ns, ns);
+ if (entry) {
+ PyObject *body = PyCFunction_New(&body_definition, NULL);
+ if (body) {
+ PyObject *result = PyObject_CallFunctionObjArgs(entry, body, path, NULL);
+ Py_XDECREF(result);
+ Py_DECREF(body);
+ }
+ Py_DECREF(entry);
+ }
+ Py_DECREF(ns);
+ if (PyErr_Occurred()) {
+ PyErr_FormatUnraisable("Can't enter debugger execution context for %U", path);
+ }
}

int _PyRunRemoteDebugger(PyThreadState *tstate)
Loading
Loading