Skip to content

Notebooks 1/4: notebook service, Jupyter Server transport and contracts #210

Closed

Description

@tannerpolley

Part of #208. The owner approved the design on 2026-10-28. Design doc: ~/.local/share/t3-fork-notes/notebook-execution-design.md, sections 1, 2 and 7 (PR 1). The summary is on #208.

Add NotebookService and JupyterTransport (Jupyter Server REST plus kernel WebSocket, JSON frames) and the notebook contracts. Cover lossless .ipynb round-trips, the execute/output reducer (it must match parent_header.msg_id and wait for both execute_reply and idle, in either order), interrupt/restart/shutdown, the bounded stream and snapshot, and permissions.

Tests use a fake transport, plus a short runtime transcript against a local Jupyter server on 127.0.0.1, stopped by its captured PID.

Activity

  1. tannerpolley commented on Oct 28, 2026

    @tannerpolley
    OwnerAuthor

    T3 Code status: Unavailable

    Issue: #210 Notebooks 1/4: notebook service, Jupyter Server transport and contracts

    Thread: thread:delegated-task:command%3Amcp%3A3431d214-908d-4cc4-995e-02bcea9a397c%3Adelegate-task%3Anotebooks-208-210-implement-20261028

    Model: gpt-6.1-sol

    Branch: issue-210-notebooks-1-4-notebook-service-jupyter

    Updated: 2026-11-13T05:08:05.827Z

  2. tannerpolley commented on Oct 28, 2026

    @tannerpolley
    OwnerAuthor

    T3 Code closeout: done

    Issue: #210 Notebooks 1/4: notebook service, Jupyter Server transport and contracts
    Thread: thread:delegated-task:command%3Amcp%3A3431d214-908d-4cc4-995e-02bcea9a397c%3Adelegate-task%3Anotebooks-208-210-implement-20261028
    Model: gpt-6.1-sol
    Branch: issue-210-notebooks-1-4-notebook-service-jupyter
    Completed: 2026-10-28T20:07:03.287Z

    Implemented #210 and committed locally as d5f67adcce34c64ed2e308b2a44cc36fd490fb10. Working tree is clean.

    Branch: issue-210-notebooks-1-4-notebook-service-jupyter
    Worktree: /home/tnnrpolley21/Workspaces/Applications/t3code/.worktrees/issue-210-notebooks-1-4-notebook-service-jupyter

    The change adds:

    • NotebookService, REST/WebSocket JSON JupyterTransport, and typed fork RPC contracts.
    • Lossless notebook JSON retention, stable cell IDs, source hashes, and execution provenance.
    • Parent-message correlation requiring both execute_reply and idle, in either order.
    • Late output, display updates across cells, deferred clears, bounded output/deltas, truncation markers, and slow-subscriber resynchronization.
    • Request deduplication, uncertain disconnect outcomes without automatic replay, interrupt, restart, shutdown, scoped cleanup, permission checks, and canonical path containment.

    Validation:

    Check Result
    vp run typecheck from packages/contracts Passed
    vp run typecheck from apps/server Failed on two unresolved MCP SDK imports in unchanged OrchestratorMcpToolkit.integration.fork.test.ts; no notebook diagnostics
    Focused notebook and authorization tests 31 passed, 3 files
    vp lint for all changed files Passed
    vp run check:changed Format, lint, GraphQL, and 44 tests passed; overall failure from unused-code findings and mobile type errors outside this change
    Git whitespace checks Passed

    The sanitized real-runtime transcript records:

    Created owned python3 kernel.
    cwd_ok=True; arithmetic=42; status=ok
    ValueError; status=error
    KeyboardInterrupt; status=error
    Restarted owned kernel and reconnected channels.
    state_reset=True; status=ok
    Deleted owned kernel.
    Kernels remaining after cleanup: 0
    Stopped only captured launch PID 1205744.
    

    Both reply/idle orderings were observed. Evidence is outside the worktree: runtime transcript, full changed-file gate output, and check details.

    Execution remains disabled in production composition until trusted endpoint configuration is supplied. Phase #211 persistence/lifecycle and broader workspace validation, #212 UI, and #213 MCP remain deferred. Binary kernel frames are unsupported and cause an explicit disconnect outcome.

    Remaining gates: independent checker review and resolution or disposition of the reported check failures. No push, PR, merge, browser, dev server, T3 installation/restart, release, or live-userdata writes were performed.

  3. tannerpolley commented on Oct 28, 2026

    @tannerpolley
    OwnerAuthor

    T3 Code closeout: done

    Issue: #210 Notebooks 1/4: notebook service, Jupyter Server transport and contracts
    Thread: thread:delegated-task:command%3Amcp%3A3431d214-908d-4cc4-995e-02bcea9a397c%3Adelegate-task%3Anotebooks-208-210-implement-20261028
    Model: gpt-6.1-sol
    Branch: issue-210-notebooks-1-4-notebook-service-jupyter
    Completed: 2026-10-28T20:30:11.781Z

    Correction round 1 is committed locally as ac177ebfd4fd1dc127eb1466fac5562d60254bf3. The working tree is clean on the same branch and worktree:

    issue-210-notebooks-1-4-notebook-service-jupyter
    /home/tnnrpolley21/Workspaces/Applications/t3code/.worktrees/issue-210-notebooks-1-4-notebook-service-jupyter

    Each finding has an implementation change and passing regression coverage:

    Finding Disposition
    1. Display ownership across generations Clears message and display ownership on restart, shutdown, and fresh creation. A’s old output stays unchanged when B reuses its display ID.
    2. Oversized output and queue overflow Replaced whole-message receipt with bounded streaming frame admission. Oversized data is discarded while channels drain; bounded output/control storage preserves completion and visibly records loss. Transport tests cover 1 MiB stdout, oversized frames, bursts, fragmented replies, and ping.
    3. Lost kernel ownership after failed acquisition cleanup Records ownership before connection and retains the exact ID after failed DELETE. Both shutdown and finalization retry cleanup.
    4. Cross-notebook blocking Uses per-notebook semaphores. A Deferred-based test confirms A’s interrupt reaches transport while B’s acquisition remains blocked.
    5. Incomplete execution deltas Adds count-reset and execution-provenance deltas. Dispatch-failure coverage verifies reconstruction; clear_output preserves the count.
    6. Project aliases create duplicate owners Canonical root/path aliases share one session and lock, with each project association and path revalidated.
    7. Exact document-byte bound Resets reject over-budget mutations atomically; count updates enforce the bound. Exact-bound and near-bound regressions pass.

    Validation:

    • 40 focused tests passed across notebook service, transport, reducer, and authorization.
    • Contracts package vp run typecheck: passed.
    • Server package vp run typecheck: only the two checker-established baseline MCP SDK import errors.
    • Changed-file vp lint: passed without warnings.
    • vp run check:changed: formatting, lint, GraphQL, and 53 tests passed. Overall failure remains from baseline mobile types and unused-code findings.

    The refreshed real Jupyter run verified arithmetic, bounded 1 MiB stdout, exception handling, interrupt, restart, and state reset. It deleted the owned kernel, confirmed zero kernels remaining, and stopped captured launch PID 1633336.

    Evidence: finding dispositions and check summary, focused tests, changed-file gate, and sanitized runtime transcript.

    Independent recheck remains open. Binary kernel frames remain unsupported; phases #211–213 and baseline failures were left unchanged. No push, PR, merge, additional agent/review, browser, dev server, T3 installation/restart, release, or live-userdata write occurred.

  4. tannerpolley commented on Oct 28, 2026

    @tannerpolley
    OwnerAuthor

    T3 Code closeout: done

    Issue: #210 Notebooks 1/4: notebook service, Jupyter Server transport and contracts
    Thread: thread:delegated-task:command%3Amcp%3A3431d214-908d-4cc4-995e-02bcea9a397c%3Adelegate-task%3Anotebooks-208-210-implement-20261028
    Model: gpt-6.1-sol
    Branch: issue-210-notebooks-1-4-notebook-service-jupyter
    Completed: 2026-10-28T20:47:34.436Z

    Committed the recovery replacement locally as a07f431b924a40ffb01ac4128e08eb81b634ae24. The working tree is clean on the same #210 branch and worktree.

    The replacement gives KernelMessageAdmission sole ownership of bounded envelope extraction, normalized control fields, complete-output admission, and loss accounting. It uses the existing stream-json dependency; no caps, dependencies, or security boundaries changed.

    Deleted the superseded paths:

    • Whole-message buffering and discard in kernelSocket.
    • Full-payload control retention and the 64 KiB disconnect rule.
    • Stream-prefix rewriting and loss attribution through currentId plus one boolean.

    The frame reader now supplies bytes and message boundaries. Required control fields survive oversized content; incomplete output never becomes valid partial output. Loss retains its actual parent ID, with capped accounting and explicit session-level loss when attribution is unavailable. The six previously resolved findings remain covered.

    The replacement’s first behavioral run passed 48 tests across four files, including:

    • 64 KiB source echoes and 64 KiB/9 MiB error replies.
    • Reply and idle in both orders.
    • Content before envelope fields, fragmented JSON, and interleaved ping.
    • Incomplete oversized JSON rejection.
    • A’s late-output flood during B, without truncating B.
    • Bounded delivery and exact normalized control contents.

    Final checks:

    Check Result
    Changed-file lint Passed
    Contracts package typecheck Passed
    Server package typecheck Only the established baseline SDK import errors
    check:changed Format, lint, GraphQL, and 61 tests passed; overall failure remains from established baseline mobile types and unused-code findings

    The refreshed real Jupyter run passed valid 70 KiB source, a 70 KiB error payload, explicit loss reporting for oversized stdout, interrupt, restart, and state reset. Cleanup confirmed zero kernels remaining and stopped captured launch PID 1941520.

    Evidence: recovery rationale and results, falsifying tests, changed-file gate, and sanitized runtime transcript.

    Independent acceptance remains open. Binary frames remain unsupported. No additional review/workers, push, PR, merge, dev server, browser, T3 install/restart, release, or live-userdata writes occurred. No model text changed or eval key was requested.

  5. tannerpolley commented on Oct 28, 2026

    @tannerpolley
    OwnerAuthor

    T3 Code closeout: done

    Issue: #210 Notebooks 1/4: notebook service, Jupyter Server transport and contracts
    Thread: thread:delegated-task:command%3Amcp%3A3431d214-908d-4cc4-995e-02bcea9a397c%3Adelegate-task%3Anotebooks-208-210-implement-20261028
    Model: gpt-6.1-sol
    Branch: issue-210-notebooks-1-4-notebook-service-jupyter
    Completed: 2026-10-28T20:56:18.368Z

    Committed the bounded correction locally as d5739bd76db1f62a947efd27675dfd0f7454eb4a. The same #210 branch and worktree are clean.

    execute_reply.status: "aborted" now passes normalization unchanged. The reducer retains it through the existing non-ok completion accounting and still waits for both reply and idle. The service:

    • Preserves replyStatus: "aborted" in the cell’s execution provenance and execution delta.
    • Uses the existing aborted run outcome.
    • Stops undispatched cells without generating an error output.

    No new internal outcome type or UI behavior was added.

    Both actual frame/admission regressions failed with disconnected before the fix. Afterward, both reply/idle orders pass at the wire and service layers.

    Check Result
    Focused tests 52 passed, four files
    Contracts package typecheck Passed
    Server package typecheck Only the established baseline SDK import errors
    Changed-file lint Passed
    check:changed Format, lint, GraphQL, and 65 tests passed; overall failure remains from established baseline mobile types and unused-code findings

    Evidence: correction details, before-fix failures, focused tests, and changed-file gate.

    Independent checker acceptance remains open. No real Jupyter rerun was needed for this status-only correction; prior runtime evidence is preserved. No push, PR, merge, workers, browser, dev server, T3 changes, or live-userdata writes occurred.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions