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
8 changes: 7 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ on:
push:
branches: [main]
pull_request:
branches: [main]
# A merge queue runs each candidate on a gh-readonly-queue/* ref. Every
# verification job already falls through to the ci-scope outputs when the
# event is not `push`, so they scope themselves here exactly as they do on a
Expand Down Expand Up @@ -138,9 +137,16 @@ jobs:
node scripts/react-parity/verify-boundaries.mjs
- name: Build and validate private React foundations
run: npx nx run-many -t lint test type-tests build --projects=$FOUNDATIONS --parallel=2
- name: Verify isolated LangGraph runtime and types
run: |
npx nx run langgraph:runtime-quality
npx nx run langgraph:runtime-type-tests
npx nx run langgraph:type-tests
- run: npx nx test langgraph --coverage --maxWorkers=2 --reporter=default
- run: npx nx run-many -t test --projects=chat,ag-ui,render,a2ui,telemetry --coverage --parallel=1 --maxWorkers=2
- run: npx nx run-many -t build --projects=$LIBS --configuration=production
- name: Install Chromium for packed runtime consumers
run: npx playwright install --with-deps chromium
- name: Verify emitted boundaries and isolated packages
run: |
node scripts/react-parity/verify-boundaries.mjs --built
Expand Down
2 changes: 1 addition & 1 deletion apps/website/content/docs/langgraph/api/api-docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1033,7 +1033,7 @@
{
"name": "AgentOptions",
"kind": "interface",
"description": "",
"description": "Options for creating a LangGraph-backed agent via agent.",
"properties": [
{
"name": "a2uiClientCapabilities",
Expand Down
91 changes: 69 additions & 22 deletions fixtures/react-parity/README.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,55 @@
# React parity foundations

This directory supports the first migration increment: a reviewed Angular baseline
and four private, empty package scaffolds. It does not provide React components,
state management, or extracted backend runtimes.
This directory records the historical package foundations and the bounded shared
LangGraph runtime proof. Core now exposes framework-free contracts; private Angular
and React packages expose native observation bindings. A fixture-only private
LangGraph session runs through the existing transport and SDK in both bindings.
The existing Angular packages and release group remain the production path.

## Bounded runtime slice

The runtime owns immutable snapshots, request generations, stop/dispose, protected
errors, read-only reconciliation after uncertain failures and fixed function-tool
execution. Angular and
React borrow the app-owned session and observe it through their native lifecycles.
The installed consumers run seven scenarios each: inert mount, text, weather tool
roundtrip, protected error, held partial text and Stop, reuse after Stop, and
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.

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
handshake on Stop. This is not compositor paint or a latency measurement. Production
React StrictMode does not replay development effects; separate native unit tests
exercise that subscription replay. See [runtime/README.md](./runtime/README.md) for
reproduction and [runtime/evidence.json](./runtime/evidence.json) for fresh commands,
counts, source provenance, cleanup assertions and limitations.

The current inventory has **1,451 records**: the historical 1,438 plus eight 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. Fourteen existing export records changed declaration/import text;
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
inventory scope and are checked by their own tests and package gates.

## Reviewed baseline

The current facts were generated from the uncommitted foundation working tree at
The historical foundation facts were generated from the uncommitted working tree at
base HEAD `7e80cebd607f5c605ef1ec81f11e5ebe3324f81b`. The baseline records the four
reviewed configuration changes: CI foundation projects and Angular consumer gate,
the direct semver tooling dependency, workspace lockfile links, and package aliases.
No inventoried API or implementation changed. This follows the main integration
at `a93977ff1e75796336ddd93a882eab2e40f0ca7b`, including v0.2.0 and its package-version
alignment fix. The inventory contains **1,438 records**: 550 public export
alignment fix. The foundation inventory contained **1,438 records**: 550 public export
occurrences (514 distinct local definitions), 102 decorated components in 100
files, 461 non-test source files, 128 package assets, 16 distribution/configuration
files, 12 entry points, 41 cockpit topics, and 128 documentation pages. These
counts cover the 16 existing libraries selected for migration; the four new empty
packages are checked separately by the boundary and packaging gates.
counts cover the 16 existing libraries selected for migration; the four new packages
are checked separately by the boundary and packaging gates. The original empty
scaffold evidence remains in [baseline-evidence.json](./baseline-evidence.json).

The earlier research snapshot at `b1685838069c6b1ec56d5e97a1a01170b26aa125`
had 547 export occurrences and 1,435 records. Integration added `AgentRecovery`,
Expand Down Expand Up @@ -61,16 +92,17 @@ an Angular fix or dependency update changes the migration baseline.

## Private package boundaries

| Current private scaffold | Intended responsibility |
| Current private package | Intended responsibility |
| --- | --- |
| `@threadplane/core` | Framework-free data, observation, execution and tool contracts |
| `@threadplane/content` | Shared Markdown, JSON, A2UI and rendering data processing |
| `@threadplane/angular` | Native Angular binding and presentation |
| `@threadplane/react` | Native React binding, rendering and presentation |

All four are private version `0.0.0`, with empty entry points. Core, content and
React use plain ESM packaging; Angular uses Angular Package Format (APF). Their
intended responsibilities are not implemented. The source/declaration verifier follows
All four remain private version `0.0.0`. Core contracts and the native observation
bindings are populated; content and presentation entries remain scaffolds. Core,
content and React use plain ESM packaging; Angular uses Angular Package Format (APF).
The source/declaration verifier follows
module edges, including type-only imports, aliases and re-exports. It blocks
framework dependencies in neutral layers, UI dependencies in backend layers,
backend SDKs in framework layers, Angular/React crossover, and optional/testing
Expand All @@ -94,8 +126,9 @@ The final package map is a separate destination, not the implemented topology:
| `@threadplane/telemetry` | Neutral collector; native Angular providers belong to `@threadplane/angular` |

There are no suffixed backend packages or separate React renderer in that map.
The first runtime proof keeps the execution owner and publisher private to the
backend; these foundations do not introduce a general shared store.
The runtime proof keeps the execution owner and publisher private to the backend;
it does not introduce a general shared store. The legacy LangGraph root and tarball
remain Angular. The neutral session is staged only into temporary fixture consumers.
The new tool contract deliberately omits a schema DSL, automatic argument
validation/transformation and validator-to-JSON-Schema conversion. Callers may
supply optional JSON Schema metadata and own any validation in their handlers.
Expand All @@ -105,7 +138,10 @@ transport decoding remain in scope.

```sh
NX_DAEMON=false CI=true npx nx run-many -t lint test type-tests build --projects=core,content,angular,react --parallel=2 --skip-nx-cache
NX_DAEMON=false npx nx run langgraph:runtime-quality --skip-nx-cache
NX_DAEMON=false npx nx run langgraph:runtime-type-tests --skip-nx-cache
NX_DAEMON=false CI=true npx nx run-many -t build --projects=chat,langgraph,ag-ui,render,a2ui,telemetry --configuration=production --parallel=1 --skip-nx-cache
npx playwright install --with-deps chromium
node scripts/react-parity/verify-boundaries.mjs --built
node scripts/react-parity/verify-packages.mjs
node scripts/react-parity/verify-angular-package.mjs
Expand All @@ -116,11 +152,20 @@ paths, README/license inclusion and production exclusions, then imports and
type-checks the tarballs outside workspace aliases with `skipLibCheck: false`.
Its core-only consumer checks all three core exports and rejects extra dependencies.
The separate Angular check packs the one Angular APF entry and proves CLI
compilation/linking with `skipLibCheck: false`. Both inspect consumer module inputs
for unwanted parsers. Installation footprints include actual installed files;
compilation/linking with `skipLibCheck: false`. Both frameworks now run installed
production browser apps with the seven shared scenarios. Inferred native contract
probes reject invalid tool names/arguments/results and deep mutations. The private
runtime's narrow declaration is compiler-generated against installed core declarations,
never hand-written; the staged SDK bundle is fixture-only. Both inspect consumer
module inputs for unwanted parsers. Installation footprints include actual installed files;
lockfile locations also include optional platform packages. The Angular footprint
includes CLI/compiler/build tooling. These measurements prove scaffold packaging
and isolation, not runtime performance, React SSR or shared-runtime correctness.
includes CLI/compiler/build tooling. Footprints, root-import probes and application
bundles measure separate surfaces; they are not runtime performance or SSR evidence.
Test-only imports currently add Nx dependencies on legacy package builds even though
the production graphs remain isolated. CI installs Chromium before the packed checks,
runs the isolated Node runtime targets, and preserves production-build-before-scan
ordering. Scenario-only/config-only changes schedule library verification. Stacked
PRs are supported; pushes and production deployment remain guarded to main.

## Existing Angular regression checks

Expand Down Expand Up @@ -151,7 +196,7 @@ The existing LangGraph stream-manager/agent tests cover cancellation, delivery
generations, queues and staged results. AG-UI interruption, resume-wire and
persistence tests cover recovery and request serialization. Client-tool tests cover
claim/record, cancellation and completed-result reuse. Later migration tasks must
replay these behaviors through the extracted runtime and both bindings.
extend the bounded runtime/binding proof to the remaining migration capabilities.

The parser work test checks linear character processing under duplicate cumulative
argument updates. A single test duration is not a calibrated performance budget.
Expand All @@ -162,24 +207,26 @@ burst streams and repeated agent/thread disposal.

## Maintenance and release

The integrated candidate is `codex/react-support-baseline`. The local maintenance
The foundation candidate is `codex/react-support-baseline`; the runtime candidate is
`codex/shared-runtime-quality`, based on `bdcc22ed31aa94f420077e046e88e1481088d453`.
The local maintenance
branch `codex/angular-maintenance-v0.2` points to released tag `v0.2.0`
(`8daea78d35bfa27513474bd624d0e9495af3cfab`) and retains its released lockfile.
Creating that local branch does not establish an operated release lane: a maintainer
must own the backport/publication workflow before it is used. No Angular facade
currently depends on a new package. Version/tag enforcement, remote maintenance
policy and a tested backport/rollback remain T37 work. The existing release group
is unchanged, and none of the scaffolds is publishable.
is unchanged, and none of the new private packages is publishable.

## Task identifiers

The following task index makes the ownership ledger readable independently of local
research documents. It is a scope map, not evidence that the tasks are complete.
T01/T02 are this foundation increment. The next G1 proof is deliberately limited
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. Renderer reuse and SSR are deferred gates, alongside the broader T01–T39 map.
No runtime proof or parity is claimed by these foundations.
This bounded runtime proof does not establish complete migration parity.

| Task | Scope |
| --- | --- |
Expand Down
18 changes: 3 additions & 15 deletions fixtures/react-parity/consumers/angular/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import * as angular from '@threadplane/angular';
/* PACKAGE_IMPORTS */

@Component({
selector: 'app-root',
standalone: true,
template: '<p>Private Angular scaffold: {{ supportedExportCount }} supported exports.</p>',
})
class App {
readonly supportedExportCount = Object.keys(angular).length /* PACKAGE_EXPORT_COUNT */;
}

bootstrapApplication(App).catch(console.error);
// The owned verifier installs the tarballs, then replaces this entry with
// fixtures/react-parity/runtime/angular-app.ts and the prebuilt private backend.
// Keep package resolution and compilation inside that installed consumer.
84 changes: 84 additions & 0 deletions fixtures/react-parity/runtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Installed native runtime consumers

Run the owned commands from the repository root. On a fresh checkout, install
dependencies, build the private artifacts, and install Playwright Chromium:

```sh
npm ci
npx nx build core
npx nx build content
npx nx build angular
npx nx build react
npx playwright install chromium
```

On Linux CI, use `npx playwright install --with-deps chromium` to install the
browser's system dependencies too. Then run:

```sh
node --test scripts/react-parity/verify-packages.spec.mjs scripts/react-parity/runtime-consumer.spec.mjs scripts/react-parity/verify-angular-package.spec.mjs
node scripts/react-parity/verify-packages.mjs
node scripts/react-parity/verify-angular-package.mjs
```

The verifiers pack and install local tarballs in temporary directories. Core
installs alone with zero implementation dependencies. React installs no Angular
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.

`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. 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,
transitive private declarations, workspace aliases, or core/framework source is
copied. This is not a neutral LangGraph tarball or a new public entry; the existing
LangGraph package root remains Angular during this migration.

The session-owned SDK transport defaults `maxRetries` to `0`, so an ambiguous
failed request is not automatically sent again. A positive
`clientOptions.maxRetries` explicitly opts into SDK retries; a caller-supplied
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 native fixtures expose Send, Tool, Error, Hold and Stop buttons plus text,
status, error, 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.
React uses a Vite production build. Angular uses the existing consumer template's
installed Angular CLI application builder and real APF linking, with output in
`dist/consumer/browser` and input evidence from `dist/consumer/stats.json`.

Both built apps run the same seven browser scenarios in installed Playwright
Chromium: inert mount, successful text, a real local tool handler and exact
two-request result continuation, protected visible server error, held streaming
DOM updates and Stop, reuse after Stop, then unmount/dispose/post-disposal submission.
Five submissions through the component controls make exactly six run requests
(including one tool continuation) and call the handler once. The separate
post-disposal submit attempt resolves aborted without making a request.
Request bodies check the catalog and actual serialized ToolMessage payload.

A small in-process HTTP fixture serves only built artifacts and the expected
LangGraph run route on dynamic port 0. The held response writes an actual SSE
assistant chunk and stays open. The test observes partial DOM text and streaming
delivery before pressing Stop, then awaits the server response-close handshake
and aborted delivery. This proves incremental DOM updates and native request abort in
these installed consumers. Whole-response SSE traces for the other scenarios
do not establish intermediate updates; controlled native DOM unit tests separately
cover publication timing and StrictMode subscription replay (production React
does not replay development StrictMode effects).

These checks make no claims about compositor timing, performance, SSR support,
or complete feature parity. The React development root-import probe, full Vite
app, Angular runtime app, and installation footprint are separate diagnostics.

Page errors and unexpected requests fail verification. Browser contexts,
browsers, held responses, server connections and temporary artifacts are closed
in `finally`, including on assertion failures. No remote deployment, production
product components, or showcase UI is involved.
Loading
Loading