Skip to content

P1086: preserve original identity in retained native readers - #3961

Draft
trissim wants to merge 7 commits into
mainfrom
fix/p1086-retained-native-binding
Draft

trissim wants to merge 7 commits into
mainfrom
fix/p1086-retained-native-binding

Conversation

@trissim

@trissim trissim commented Nov 3, 2026 •

Copy link
Copy Markdown
Contributor

P1086 retained native-reader binding — unfinished source checkpoint

7 commits; 17 files, +664/-90 against main ace761644696d79371cf96b602cb91422c2d7a01. Head: e229515b50ca1eed9bdc1763de45d6fd724444c2. Latest correction: 5 files, +30/-28. The prior source acceptance at 85c6 remains historical; this head needs current judgment and hosted gate evidence.

Before / after

Before: original lookup identity was conflated with copied storage. Pathname fences did not bind the descriptor actually supplying bytes. Later, cut-only failed-acquisition policy left inherited tail/activity reads able to report a missing retained file as no activity.

After:

NativeSessionSnapshot(original session/path + original acquired revision)
SessionFile -> RetainedSessionLocation -> BoundRetainedSession
RuntimeLocation -> PiSessionFile -> RetainedPiSessionFile
NativeTranscript
  opened(): reading fence -> actual acquisition -> descriptor fences -> close
  opening_failed(): rethrow ordinary FileNotFoundError
  RetainedNativeTranscript
    opening_failed(): TranscriptChanged from failed acquisition
    require_opened(): actual descriptor revision + original header

One reader family, ledger and bounded unread index. No compatibility reader, parallel ledger, copied private authority or new exception API.

Hosted-gate correction after source acceptance

The hosted debt-src job on 85c6 failed on the new local import, three new guarded type imports, missing signatures and an optional-value retirement probe. This head imports the existing declarations directly and types the read boundaries/refusals. Two separate cold processes imported the affected modules in threads-first and backend-first order; both exited 0. The suspected import cycle did not occur.

NativeTranscriptCursor now passes the actual ReadLedger to RuntimeLocation; SessionCut retains the acknowledgement policy and writes the same original-coordinate mark. The unread-state forwarding method and its unused type import are deleted. Whole-tree Core src/tests/tools, Toad main a49ba2038 and paired Toad1455/00829c3e were searched: no direct caller of the deleted wrapper remains. Toad still uses the public cursor acknowledgement; its direct cut control already passes a ledger. The path is ThreadViewRead.native -> NativeTranscriptCursor.mark_read -> RuntimeLocation.mark_read -> SessionCut.mark_read -> ReadLedger.mark_transcript, preserving the existing key check, bound runtime, acquisition refusal and cut validation.

Retirement now iterates the intersection of old and current thread keys, so every compared prior value exists; new-thread absence is not re-encoded as another nullable branch. No behavioral control was executed. Evidence: pi-publication-carry/shared-board/p1086-gate-11-*. Hosted checks on the new head are not yet claimed green.

Shared acquisition correction (60653)

The rejected dispositions of 3a84204f1 and 251cfff96a7d remain unwaived. The eight incorrect message-argument calls from the earlier head now use the existing zero-argument TranscriptChanged constructor, with original cause chains preserved.

The latest repair moves the failed-acquisition decision to NativeTranscript.opened, not its cut consumer. Only the actual Path.open call is caught. The base opening_failed rethrows FileNotFoundError, so ordinary unstarted cut/activity behavior remains. The retained override raises TranscriptChanged from that error before inherited _tool_call_times or any other ordinary missing-file handler can translate it into empty history. A missing parent restored before the final pathname fence does not change that refusal.

The redundant missing_cut methods are deleted; ordinary cut still returns MissingSessionCut for ordinary absence. Core src/tests/tools and the existing Toad checkout contain no remaining missing_cut caller. The Toad scan path was verified with its real SessionBody declaration.

The descriptor/header checks and before/after reading fences remain. Cut, committed-output cut, imported-source prefix, header/publication-context reads, tail, forward and reverse use opened. Tail/reverse retain the acquired descriptor rather than reopen. Relevant inherited consumers include team/order.last_activity -> runtime.history_source -> retained transcript.last_tool_call and PiSessionFile.saved_model -> self.transcript.tail.

Original identity and authority

Original session/path/entry/request joins remain original. Read keys, cuts, inode marks and positions preserve original coordinates; IO and watches use physical retained storage. Snapshot binding requires the complete original extent and acquired revision. ReadLedger does not resolve original keys through today's filesystem.

ReplyRead retains its bound runtime through preparation, scan and completion, preserving the 32-record allowance, cancellation, append-prefix reuse and revision fences. Conflicting bindings for one logical key are refused.

Retained members remain non-resumable and refuse selection, launch arguments, new sessions, fork and compaction. They have no writable native sidecars and are excluded from live tool watches. Actual native publication still requires qualified original journal/prelaunch/sidecar/SQL and writable-runtime evidence.

Controls: authored, not executed

The existing real-file failed-acquisition control is shared across four consumers: cut, nonzero cursor acknowledgement, inherited last-tool activity and saved-model lookup. It opens the bound journal during construction, removes its real parent for the second open, restores it before unwinding, and requires TranscriptChanged with the FileNotFoundError cause and no mark mutation. Only the foreign Path.open boundary is intercepted, not product readers or revision methods.

Together with six descriptor directory-ABA cases, unbound cut refusal and ordinary absence, there are 12 correction cases. Ordinary unstarted coverage now also requires UnrecordedEventTime from last_tool_call. No test assertion was weakened. Existing original-copy, inode/marks/unread, recreated original alias and physical-watch controls remain.

No pytest/control execution by Carry. Necessary affected paths remain test_native_transcript, test_thread_unread, test_view_unread, test_watched and test_transcript_pages. No additional app/native/capture/provider/agent lane was launched. Source tracing and diff-check are not claimed as executed controls.

Delivery and limits

The source was rebased onto ace7616 and the correction appended to the same PR. Logs and source diff: pi-publication-carry/shared-board/p1086-opening-09-*; prior constructor evidence remains p1086-constructor-08-*. git diff --check passed. Earlier parsing/import/schema results remain earlier-head evidence, not new-head execution.

P1086/native/UI/resource acceptance remains open: the selected original dataset lacks its original JSONL journal and complete historical peak/timing evidence. Original-native, Salvage, configured-native READ AND EDIT and P1088 holds remain. No failed/UNKNOWN input or tool operation was replayed, no original was reconstructed or disposed, and no source verdict substitutes for those missing answers.

Assumed: qualified selected-copy provenance; original keys from declared producers; one coherent physical binding per logical key in a read snapshot. Copied data grants no native launch/write authority.

@trissim
trissim force-pushed the fix/p1086-retained-native-binding branch 2 times, most recently from 220098b to 5e4f4ab Compare November 3, 2026 22:08
@github-actions

github-actions Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

debt-src at e229515 passes.

Warn-only, never blocks (6)
src/agent_comms/session_file.py: LintFindings +1
src/agent_comms/view_unread.py: LintFindings +1
src/agent_comms/session_file.py: Unformatted +1
found LintFindings:src/agent_comms/session_file.py at src/agent_comms/session_file.py:3 (I001 [*] Import block is un-sorted or un-formatted)
found LintFindings:src/agent_comms/view_unread.py at src/agent_comms/view_unread.py:110 (E501 Line too long (113 > 100)) src/agent_comms/view_unread.py:111 (E501 Line too long (108 > 100))
found Unformatted:src/agent_comms/session_file.py at src/agent_comms/session_file.py:1 (Black would reformat this file)

@trissim
trissim force-pushed the fix/p1086-retained-native-binding branch 3 times, most recently from 3a84204 to 251cfff Compare November 4, 2026 01:45
@trissim
trissim force-pushed the fix/p1086-retained-native-binding branch from 251cfff to 85c6f60 Compare November 4, 2026 02:03
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.

1 participant