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
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
"mux/member/open",
"mux/member/close",
"session/snapshot",
"session/models",
"session/model/select",
"turn/start",
"turn/steer",
"turn/follow_up",
Expand Down
47 changes: 33 additions & 14 deletions gui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
This directory contains the Product-neutral native HarnessGUI shell accepted by
[GUI-B0 issue #582](https://github.com/zhnt/loushang/issues/582). React and
TypeScript own presentation and UI-local state; Tauri/Rust owns desktop
integration and adapts the accepted read-only App Contract slice. The GUI does not
integration and adapts the accepted App Contract slice. The GUI does not
own Product, Harness, AppService, or AppHost runtimes.

The default B1 launch is deliberately offline. It provides a Product-neutral UI
Expand All @@ -12,11 +12,12 @@ Sessions, isolated per-Session drafts, active Run and Task progress, expandable
Activity details, distinct root/subagent AgentRuns, and read-only ChangeSet
review through a central Quick Look and the Work Dock. Every sample value is
labelled as fixture data. It does not read a repository, start a Python backend,
or request a model. An opt-in B2 Windows launch can attach read-only to an
or request a model. An opt-in B2 Windows launch can attach to an
existing AppHost, install one barriered initial Session snapshot, publish
validated ongoing event rounds with authoritative replacement snapshots, and
reconnect through a fresh snapshot after transport loss or an event gap. It
does not enable any mutation. Further cross-language and real-service work
reconnect through a fresh snapshot after transport loss or an event gap. It can
submit text and interrupt the current execution in that existing Session over
the same authenticated controller connection. Further cross-language and real-service work
remains in C1/B2 as described in the
[engineering plan](../docs/internals/architecture/drafts/gui-engineering-bootstrap-plan.md).

Expand Down Expand Up @@ -57,7 +58,7 @@ executable without producing installers. `dev:fixture-native` and
`build:fixture-native` enable the B1-only Rust invoke/event canary; the command
is absent from the default native build.

## Read-only live launch
## Controlled live launch

The AppHost/desktop launcher may start the built executable with both native
arguments below. Omitting both keeps the offline fixture. Partial, duplicate or
Expand All @@ -72,14 +73,17 @@ The record root and Mux selection are parsed and retained by Rust; the WebView
cannot provide or read them. Native admission still validates the private record
directory and file before authentication. The published payload contains no
attachment ID, controller generation or authentication key. Live snapshots are
visibly labelled read-only; fixture playback, Send, Interrupt, Workspace,
ChangeSet, Tasks and Subagents remain unavailable until their own accepted live
contracts are implemented. Closing the window cooperatively detaches and joins
visibly labelled as AppHost-controlled. Send and Interrupt use controller facts
kept only in Rust; fixture playback, Workspace, ChangeSet, Tasks and Subagents
remain unavailable until their own accepted live contracts are implemented. Closing the window cooperatively detaches and joins
the reader without stopping the shared AppHost. Each connection attempt has a
new epoch. A failed transport or invalid round marks live facts
disconnected/resync-required; the native adapter rereads the private record,
authenticates and attaches again, and the WebView resumes only after a complete
fresh snapshot and membership barrier. Unknown mutations are never replayed.
fresh snapshot and membership barrier. A submit with an uncertain response is
looked up by its stable submission ID after reconnect and is never replayed
automatically. The draft is cleared only after acceptance is known; commands are
blocked until the resulting authoritative event or snapshot advances the Session.

For an opt-in desktop acceptance run, first build the release executable and
then launch an isolated real AppHost plus two real mux/session projections:
Expand All @@ -92,19 +96,34 @@ pnpm --dir gui run accept:live-native
The second command opens a visible HarnessGUI window and keeps the shared
AppHost alive until that window is closed. It also rotates the real local
listener and connection record, and waits for the GUI to reconnect and accept a
fresh authoritative snapshot. Inspect the final connected/read-only labels,
real Session projection, disabled mutation controls and normal/maximized layout,
fresh authoritative snapshot. Inspect the final connected labels, real Session
projection, Send/Interrupt behavior and normal/maximized layout,
then close the window. The launcher verifies the reconnect, that the GUI
released its mux controller, that the AppHost is still accepting, and that an
independent peer Session is still snapshot-readable. Non-secret lifecycle evidence is written under
`gui/test-results/live-apphost-desktop/`; this opt-in helper is not part of the
rapid GUI gate and does not invoke a model.

To exercise the same isolated AppHost with the saved Coding default model and
its existing credential, run the explicit provider acceptance instead:

```text
pnpm --dir gui run accept:live-provider
```

This command resolves the model through the normal layered AI ModelRegistry and
Coding settings; the GUI does not parse `models.json` or receive credentials.
It currently uses no tools, sends one short acceptance prompt, may incur provider
usage, and then leaves the window open for manual conversation. Non-secret
evidence is written under `gui/test-results/live-provider-desktop/`. It is never
part of `check`, CI or another default gate.

The first observed live desktop run is recorded in
[Windows live AppHost acceptance](tests/playback/windows-live-apphost-acceptance.md).
It records the initial read-only projection, ongoing event integration,
disconnect/resynchronization and cooperative desktop-exit lifecycle. Mutation
and Windows display scaling remain outside this slice.
It records the initial projection, ongoing event integration,
disconnect/resynchronization and cooperative desktop-exit lifecycle. The
automated integration check additionally submits through the production desktop
control bridge. Windows display scaling remains outside this slice.

For a standalone offline executable, use `pnpm --dir gui run build:fixture-native`
from the repository root. Do not substitute a plain `cargo build`: that bypasses
Expand Down
19 changes: 10 additions & 9 deletions gui/contracts/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# C1 execution contract probes

Status: **partial C1 contract coverage plus the first B2 read-only native adapter**;
not an accepted full codec or mutable client.
Status: **partial C1 contract coverage plus a bounded B2 existing-Session control adapter**;
not an accepted full codec or general mutable client.

The [contract generation and native connection plan](connection-plan.md) now
records the selected reference inputs, generated candidate DTOs and the exact
Expand All @@ -19,7 +19,7 @@ the value/selection contract and its use by the native-file and authentication
probes. A subsequent [Windows loopback lifecycle experiment](connection-lifecycle-evidence.md)
now composes record admission, authentication, hello, deadlines and cancellation.
The bounded connection implementation is now shared with the Tauri host.
The [read-only attachment experiment](attachment-lifecycle-evidence.md) now
The [attachment experiment](attachment-lifecycle-evidence.md) now
extends the loopback probe through member snapshots and detach; real AppHost
snapshot publication is verified below, while native-window acceptance remains.

Expand All @@ -29,7 +29,7 @@ The four local probe slices are one offline compatibility work item, not four
production integration milestones. Their scope is measured against
[bootstrap plan section 6](../../docs/internals/architecture/drafts/gui-engineering-bootstrap-plan.md#6-appclient-跨语言接入与生命周期).
The default GUI still uses fixtures. A Windows launch with both admitted native
arguments selects the read-only live client; protocol validators now live under
arguments selects the controlled live client; protocol validators now live under
`src-tauri` and the probes consume that same implementation.

| Obligation | Evidence retained | Remaining work before claiming coverage |
Expand All @@ -56,9 +56,10 @@ assertions; do not expand case counts merely to suggest readiness.
obligations required by the first connection. Add reverse encoding evidence,
rather than relying on Python-to-Rust-to-TypeScript projection alone.
3. The bounded B2 connection slice now reaches explicit profile negotiation,
authenticated attachment, a membership-barriered initial snapshot and owned
cleanup. Keep submit/recovery acceptance separate; live Send and Interrupt
remain disabled.
authenticated attachment, a membership-barriered initial snapshot, ongoing
event publication, submit/interrupt control and owned cleanup. Control stays
on the attachment-owning connection. An uncertain submit is queried by stable
submission ID after reconnect and is never sent a second time automatically.

Workspace/ChangeSet integration remains pending its own accepted contracts;
execution connectivity must not silently turn fixture repository data into live
Expand Down Expand Up @@ -212,7 +213,7 @@ Reproduce this offline evidence with `pnpm --dir gui run check:contract`.

## Real AppHost integration follow-up

The first real AppHost/AppService read-only integration and its request-ID fix
The real AppHost/AppService integration, desktop control path and request-ID fix
are documented in [AppHost integration evidence](apphost-integration-evidence.md).
Run `uv run python scripts/gui/check_apphost_integration.py` explicitly on Windows;
this does not enable live GUI publication or add a default gate.
this remains an opt-in GUI integration check and adds no default gate.
47 changes: 36 additions & 11 deletions gui/contracts/apphost-integration-evidence.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Real AppHost read-only integration
# Real AppHost integration

Status: B2 read-only event and resynchronization evidence, updated 2026-09-22.
Status: B2 event, resynchronization and existing-Session control evidence,
updated 2026-09-22.

Run from the repository root on Windows:

Expand All @@ -11,8 +12,9 @@ uv run python scripts/gui/check_apphost_integration.py
This opt-in script constructs the real Coding continuity attempt, AppHost
catalog/runtime, AppService, HostedLocalRuntimeV1, authenticated LocalAppServer,
and real Coding session factory. It uses temporary private connection records,
continuity and session stores. Installed-code admission pins are test-owned;
model streaming is explicitly forbidden and no work is submitted. It does not
continuity and session stores. Installed-code admission pins are test-owned.
The control case uses a deterministic process-local model transport and submits
one prompt; it makes no network provider call. It does not
connect to an existing user application, read user settings, or start a TUI.

The existing Rust connection probe authenticates to that actual server and
Expand All @@ -35,6 +37,15 @@ ordered member/Session identity and one execution snapshot against the real
AppHost. The serialized publication contains neither `attachmentId` nor
`controllerGeneration`; those controller capabilities remain native.

The `control_probe` then uses that same production Rust adapter to attach and
submit on one authenticated connection. AppHost routes the prompt into the real
Coding `AgentSession`; the deterministic assistant stream returns through the
normal execution event and snapshot path. The probe verifies acceptance plus
nonempty event publication. This caught three integration errors that isolated
codecs could not: controller authority is connection-bound, controller
generation is numeric on the wire, and request IDs increase across snapshot,
control and event operations on the connection.

## Integration defect found

The isolated probe previously sent textual request IDs (`attach`, `snapshot-0`,
Expand All @@ -50,8 +61,9 @@ No server contract or runtime implementation was changed to accommodate GUI.

## Limits and next slice

- The native adapter and connected-window lifecycle are accepted for this
read-only slice; display scaling and mutation remain separate work.
- The native adapter, connected-window lifecycle and bounded existing-Session
submit/interrupt path are covered; display scaling and broader mutation remain
separate work.
- It verifies idle snapshots and empty event batches, real controller arbitration, graceful client EOF
cleanup and explicit deployment settlement. It does not prove hard process
termination cleanup or every failed-snapshot/disconnect race in the real host.
Expand All @@ -60,12 +72,25 @@ No server contract or runtime implementation was changed to accommodate GUI.
detach against the real AppHost. The desktop uses that same reader to publish
the barriered initial snapshot and complete validated event rounds. On a
transport failure or rejected round it establishes a fresh connection epoch
and replaces state from a new authoritative snapshot. Submission, approval
and takeover are not added.
- Model-free real Coding sessions do not establish live provider execution.
and replaces state from a new authoritative snapshot. Approval and takeover
are not added. Submit is never automatically replayed; after a response loss,
the adapter queries the stable submission ID on a new attachment.
- The deterministic Coding session proves AgentSession routing and streaming,
not authentication to or behavior of a network AI provider.
- Nonempty contiguous event batches and invalid batches are covered by the scripted
fixture; metadata/content watermark separation is additionally unit tested in Rust.
- This remains an opt-in GUI integration check, not a TUI/Harness default gate.

Next add accepted live mutation contracts independently. Keep live facts
separate from offline fixtures and never infer mutation results across reconnect.
Next record a completed provider-backed desktop run, then add the separate New
Session, approval and attachment contracts. Keep live facts separate from
offline fixtures and never infer mutation results across reconnect.

## Opt-in provider desktop acceptance

`pnpm --dir gui run accept:live-provider` uses the same isolated AppHost and
desktop control bridge but resolves the saved Coding `default_model` through the
standard layered ModelRegistry and settings path. Credentials remain in the AI
runtime; they are not serialized to Rust or the WebView. The helper disables
tools, sends one bounded acceptance prompt, and records only the selected model
identity and lifecycle facts under `gui/test-results/live-provider-desktop/`.
It is intentionally interactive, network-using and outside every default gate.
5 changes: 3 additions & 2 deletions gui/contracts/attachment-lifecycle-evidence.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,5 +98,6 @@ not infer that a consistent live snapshot can be published during concurrent
membership changes from this experiment alone.

The separate [real AppHost integration](apphost-integration-evidence.md) now tests
actual ownership and idle event reads. Next expose the read-only native port with correct
event/barrier and cleanup ownership. Keep fixture UI and live facts separate.
actual ownership, idle event reads and the desktop control path. The native port
now retains control authority on the connection that acquired it, publishes
complete event rounds and owns cleanup. Keep fixture UI and live facts separate.
Loading
Loading