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
24 changes: 16 additions & 8 deletions fixtures/react-parity/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,13 @@ errors, read-only reconciliation after uncertain failures and fixed function-too
execution. The private session also supports explicit fixed-thread history loading
when its transport can read history. The latest checkpoint replaces the transcript;
equal reads preserve identity, failures preserve the prior snapshot, and loaded
tools never execute. Core contracts and native binding implementations are unchanged.
tools never execute. Private snapshots now include broad readonly application
`values`, published atomically with messages. Full root state, history and conclusive
correlated recovery replace the map; unchanged nested data retains identity, and
token-only updates reuse it without traversal. `undefined` is unobserved state and
`{}` an observed empty map. Child/update/custom/live-interrupt envelopes are ignored.
Core contracts are unchanged; native structural signatures preserve the concrete
snapshot extension and tool inference, with the same receiver and lifetime behavior.
Angular and React borrow the app-owned session and observe it through their native
lifecycles. The installed consumers run ten scenarios each: inert mount, explicit
history load, equal refresh, empty replacement, text, weather tool
Expand All @@ -22,8 +28,9 @@ unmount followed by explicit disposal and an aborted post-disposal submission.
Five live component submissions plus one tool continuation produce six exact wire
requests, with one handler invocation and zero page errors or unexpected requests.
The three explicit loads make three history reads and no run requests or handler
calls. This is partial T10 coverage: thread switching, pagination, branching, full
backend state and interrupt resume remain outside this proof.
calls. This is partial T09/T10 coverage: thread switching, pagination, branching,
state writes, application-schema inference and interrupt resume remain outside this
proof. The factory and snapshot extension remain private.

A local HTTP/SSE fixture serves production-built apps and writes real held response
bytes. Browser assertions observe incremental DOM text and a native response-close
Expand All @@ -33,12 +40,12 @@ exercise that subscription replay. See [runtime/README.md](./runtime/README.md)
reproduction and [runtime/evidence.json](./runtime/evidence.json) for fresh commands,
counts, source provenance, cleanup assertions and limitations.

The current inventory has **1,453 records**: the historical 1,438 plus ten private
The current inventory has **1,455 records**: the historical 1,438 plus twelve private
runtime production sources, three testing helpers, a runtime Vitest config and its
type-test config asset. Public export occurrences remain 550 with 514 distinct local
definitions. The original runtime extraction changed fourteen existing export
records' declaration/import text; history loading adds two private sources and
changes no legacy public export records. There are no legacy export-name additions
records' declaration/import text; history loading and values observation each add
two private sources and change no legacy public export records. There are no legacy export-name additions
or removals. Existing task assignments
are preserved; touched extraction/configuration subsets are in progress, not whole
T03–T16 completion. Core and native package contracts remain outside this legacy
Expand Down Expand Up @@ -218,7 +225,7 @@ burst streams and repeated agent/thread disposal.

The foundation branch was `codex/react-support-baseline`; the runtime branch is
`codex/shared-runtime-quality`, based on `bdcc22ed31aa94f420077e046e88e1481088d453`.
The history-loading increment is `codex/langgraph-history-loading`; its verified
The current values increment is `codex/langgraph-state-values`; its verified
base and working-source fingerprint are recorded in `runtime/evidence.json`.
The local maintenance
branch `codex/angular-maintenance-v0.2` points to released tag `v0.2.0`
Expand All @@ -236,7 +243,8 @@ research documents. It is a scope map, not evidence that the tasks are complete.
T01/T02 describe the foundation increment. The current G1 proof is deliberately limited
to shared LangGraph text streaming and fixed function-tool execution with borrowed native
Angular and React bindings: the runtime owns execution while each binding observes
it. Explicit fixed-thread history loading now covers a further subset of T10.
it. Explicit history loading and application-values observation cover further
subsets of T09/T10.
Renderer reuse and SSR are deferred gates, alongside the broader T01–T39 map.
This bounded runtime proof does not establish complete migration parity.

Expand Down
40 changes: 34 additions & 6 deletions fixtures/react-parity/runtime/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,16 @@ or backend SDK; Angular installs no React or backend SDK. Framework/compiler
versions come from the root lockfile. Contract probes compile the installed
public entries with `strict` and `skipLibCheck:false`, standard DOM signals, and
no workspace aliases. Negative probes check names, arguments, results and deep
readonly types directly on each binding's inferred snapshot.
readonly types directly on each binding's inferred snapshot, including broad
backend values without application-schema inference.

`runtime-entry.ts` is development-only composition around private `createSession`,
the production `FetchStreamTransport`, and the real LangGraph SDK. A focused
TypeScript check resolves its public core imports against the installed tarball
declarations, then emits its narrow annotated `AgentSession<FixtureTools>` return
type with an optional fixture `load` capability. Vite bundles the private backend
declarations, then emits its narrow annotated fixture return type. It replaces
the core getter with `Omit<AgentSession<FixtureTools>, 'getSnapshot'>` and a concrete
snapshot getter, avoiding an intersected overload that would hide `values` from
inference; `load` remains optional. Vite bundles the private backend
and SDK into temporary ESM, externalizing
`@threadplane/core` and `@threadplane/core/tools`. Only that JavaScript bundle and
entry declaration are copied into each installed consumer. No private TypeScript,
Expand All @@ -48,6 +51,27 @@ transport owns its retry policy. Canonical updates may replace or remove pending
tool calls for the same assistant message while retaining other messages' calls
and completed results.

The private `LangGraphSnapshot.values` is a broad
`Readonly<Record<string, PlainValue>> | undefined`. It is observed application data,
not a validated application schema. `undefined` means no current values map is
observed; `{}` means a root record was observed with no application fields. Root
`values` and `checkpoints` records, explicit history, and conclusive recovery
correlated to the attempted run replace the whole map, including deleted fields.
`messages` and `__interrupt__` are excluded. Missing history values clear the map
to `undefined`. Child streams, node updates, custom events and live interrupt
envelopes do not replace it.

Messages and values publish together as one owned immutable snapshot. Equal maps
retain identity, changed maps share unchanged nested branches, and token-only
updates reuse the owned map without traversing it. This adds no I/O. Narrow SDK
normalization prevents raw data fields from overriding protocol type/namespace;
`messageMetadata` selects delta text semantics only for actual message events.
The application field remains observable as data. The native bindings infer
the concrete snapshot through structural getter/subscription signatures while
retaining typed tool results, method receivers and borrowed lifetime semantics.
The factory and snapshot extension remain private; state writes, application
schema inference, SSR and package-root cutover remain outside this slice.

The private `LangGraphSession` offers `load({ signal })` only when its transport
supports history reads. Loading is explicit: construction, mount and subscription
perform no I/O. The latest checkpoint authoritatively replaces the transcript,
Expand All @@ -63,12 +87,12 @@ History is observation only: loading never executes pending tools. Execution
deduplication survives a load, while locally authored result provenance is cleared.
Persisted ToolMessage strings remain transcript text rather than becoming typed
handler results, including on later stream replay. This is a fixed-thread history
subset of T10, not thread switching, pagination, branching, full backend state,
subset of T10, not thread switching, pagination, branching, state writes,
interrupt resume, SSR, or a public LangGraph package cutover. Core public contracts
and the native binding implementations are unchanged.
are unchanged; the native signatures now retain the concrete snapshot extension.

The native fixtures expose Load, Send, Tool, Error, Hold and Stop buttons plus text,
transcript, load completion/error, status, tool result, delivery, submission and
transcript, values, load completion/error, status, tool result, delivery, submission and
handler count outputs. A single app-owned
session is created outside component lifetime and outside React's StrictMode
tree; owner buttons perform framework unmount and explicit session disposal.
Expand All @@ -89,6 +113,10 @@ and no run requests or handler calls. Every completed load must leave its visibl
error output empty, so retained text cannot conceal a failed equal refresh. Both
registered handlers increment the same counter if executed. Request bodies check
the catalog and actual serialized ToolMessage payload.
Values assertions distinguish unobserved from empty state, show loaded application
fields, and verify replacement/deletion across root, tool, held and reused runs.
Separate native component tests make four history reads to cover a values-only
refresh with unchanged messages; installed browser scenarios still make three.

A small in-process HTTP fixture serves only built artifacts and the expected
LangGraph run/history routes on dynamic port 0. The held response writes an actual SSE
Expand Down
1 change: 1 addition & 0 deletions fixtures/react-parity/runtime/angular-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ const submit = (input: string) => { submissions += 1; return session.submit(inpu
<output aria-label="Status" data-testid="status">{{ snapshot().status }}</output>
<output aria-label="Text" data-testid="text">{{ view().text }}</output>
<output aria-label="Transcript" data-testid="transcript">{{ view().transcript }}</output>
<output aria-label="Application values" data-testid="values">{{ view().values }}</output>
<output aria-label="Loads finished" data-testid="loads-finished">{{ loadsFinished() }}</output>
<output aria-label="Load error" data-testid="load-error">{{ loadError() }}</output>
<output aria-label="Error" data-testid="error">{{ view().error }}</output>
Expand Down
Loading
Loading