Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
15eb63b
feat(apphost): establish managed deployment storage baseline
zhnt Sep 13, 2026
22ced96
feat(apphost): persist managed mux name reservations
zhnt Sep 13, 2026
ce7ab18
feat(apphost): fence managed service instance generations
zhnt Sep 13, 2026
0b8f33d
feat(hosting): retain exact Linux service exit observations
zhnt Sep 13, 2026
3bcc2f0
feat(hosting): coordinate durable service startup handoff
zhnt Sep 13, 2026
64ad7b0
feat(hosting): own detached Linux service creation
zhnt Sep 13, 2026
d9be5f1
feat(apphost): bind service handoff to durable native identity
zhnt Sep 13, 2026
a2516f8
feat(apphost): separate application preparation from activation
zhnt Sep 13, 2026
415b6b9
feat(apphost): retain managed child application lifetime
zhnt Sep 13, 2026
1e6383c
docs(lmux): record M0 slices 19-96, acceptance plans and ARD-004
zhnt Sep 20, 2026
7147894
fix(harness): create private directory ancestors at 0700
zhnt Sep 20, 2026
b8d6330
docs(lmux): record v2 baseline split in the M0 contract
zhnt Sep 22, 2026
efc205d
docs(lmux): mark the M0 record as a working-tree snapshot
zhnt Sep 22, 2026
0cc6a11
feat(harness): retain descriptor-relative journal IO
zhnt Sep 22, 2026
a22eab9
feat(harness): admit retained transcript writers
zhnt Sep 22, 2026
f80f5c1
feat(harness): bind session blobs to retained roots
zhnt Sep 22, 2026
5d99473
feat(harness): root conversation store IO
zhnt Sep 22, 2026
b9d7939
feat(harness): own transcript writer lifecycles
zhnt Sep 22, 2026
3df6f63
feat(harness): supervise retained exec capture
zhnt Sep 22, 2026
ffb321e
feat(harness): own captured session output
zhnt Sep 22, 2026
6393964
feat(coding): adopt owned session stores
zhnt Sep 22, 2026
40484ea
feat(hosting): retain Linux service observations
zhnt Sep 22, 2026
a707b53
feat(apphost): own managed service state
zhnt Sep 22, 2026
5e7f327
feat(apphost): budget managed runtime storage
zhnt Sep 22, 2026
a807f52
feat(apphost): supervise managed child lifetimes
zhnt Sep 22, 2026
8b3be11
feat(coding): compose managed local applications
zhnt Sep 22, 2026
43c5bf4
feat(harnesstui): project conversation capabilities
zhnt Sep 22, 2026
03c825e
feat(harnesstui): bind managed mux conversations
zhnt Sep 22, 2026
78b5d5c
feat(coding): add managed lmux CLI
zhnt Sep 22, 2026
3e77578
test(coding): validate managed lmux product flows
zhnt Sep 22, 2026
162602e
test(dev): measure managed lmux evidence
zhnt Sep 22, 2026
2ecf52a
docs(architecture): record managed lmux boundaries
zhnt Sep 22, 2026
cf36c02
fix(ci): compact reusable workflow plans
zhnt Sep 22, 2026
295157e
fix(lmux): preserve cross-platform import contracts
zhnt Sep 22, 2026
c2395f4
fix(hosting): typecheck Linux observers cross-platform
zhnt Sep 22, 2026
9222d0f
test(appserver): separate probe and startup budgets
zhnt Sep 22, 2026
c198156
test(appserver): allow cross-platform cleanup scheduling
zhnt Sep 22, 2026
dc14cd6
fix(coding): align SDK and ownership regressions
zhnt Sep 22, 2026
97be515
test(lmux): join concurrent registry transactions
zhnt Sep 22, 2026
6af0ef6
Merge pull request #601 from zhnt/harness/lmux-managed-service
zhnt Sep 22, 2026
212e125
test(appserver): isolate lifecycle ordering budgets
zhnt Sep 22, 2026
b38c35d
fix(harness): tolerate atomic Windows lock initialization
zhnt Sep 22, 2026
0730fd0
test(apphost): reject recycled Windows parent identities
zhnt Sep 22, 2026
fc97742
test(apphost): model Windows process creation times
zhnt Sep 22, 2026
b691f0f
test(hosting): classify unsupported remote handles
zhnt Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
3 changes: 3 additions & 0 deletions docs/en/user-guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ loushang -p "Summarize the current project."

For building terminal UI applications with `loushang.tui`, see [Building TUI Apps](tui.md).

For the Linux background named-Mux development preview, see the [lmux guide](lmux.md),
including storage, reconnection, and upgrade limitations.

### Explicit Hosted Application

`loushang-hosted` is an opt-in foreground stdio server for an application
Expand Down
164 changes: 164 additions & 0 deletions docs/en/user-guide/lmux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Linux lmux preview

English | [中文](../../zh-CN/user-guide/lmux.md)

This guide describes the current development branch, not completed delivery
acceptance. The `lmux` command it documents was still uncommitted when this
guide landed, so a build from this commit has no `lmux` entrypoint yet; treat
the commands below as the intended interface, not a shipped one. Check `lmux --help` against your installed version. Automatic
background services currently target Linux only; GUI and cross-machine access
are not included. Managed scratch quotas, full Harnesstui parity, and final
installed/disconnection/performance acceptance remain in progress.

## Create and reconnect

Run `lmux new -s dev` in your workspace. It starts or reuses the workspace
service, creates an empty named Mux, and opens the terminal. Use
`/new cwd Work` for the first Session Tab, `/resume` to discover existing
sessions, and `/help` for supported operations. An empty Mux does not call a model.

`/detach` leaves the client without stopping the service. After reconnecting
over SSH to the same machine, run `lmux attach -t dev` from any directory.
Names are global within the machine/user namespace; no `server:mux` prefix
is needed. Multiple Muxes in one workspace share a service, and a Mux may
contain multiple Session Tabs. Another controller is not displaced; attach
may report busy until the previous connection releases its authority.

Attach never restarts an offline service implicitly; use `lmux start -t dev`.
A new instance is allowed only after the previous instance is proven cleanly
stopped. Crashes or insufficient cleanup evidence are refused; start does not
bypass those checks.
Accepted work belongs to the background service rather than the SSH terminal.
This is not protection against reboot, crashes, or host policies that terminate
user processes. An admitted restart restores durable Mux/Session state, not running work or
requests whose replies were lost.

Bare `lmux` creates `main` in cwd when no Mux name reservation exists;
untargeted `lmux attach` reports not_found in that case. When the entire namespace
has exactly one Mux reservation, and it belongs to Coding and is recorded as
committed with neither a stop request nor a clean stop, both commands directly
attempt an authenticated connection. For multiple candidates, a bounded,
read-only probe authenticates each eligible service and reads exact Mux IDs;
it never attaches or requests control. A sole confirmed Mux is selected only
when no candidate is unknown and the candidate set remains unchanged.
Otherwise, the selector shows the frozen observations: `n` advances a page,
`r` returns to the first page, and `f` explicitly refreshes and probes again.
Paging performs no new probe. Probe connections close before final attachment,
which authenticates again against the selected instance and Mux ID.
Recorded state does not prove availability:
a failed connection does not restart the service or choose another target.
Pending reservations are not treated as an empty list.
Terminal commands require TTY stdin and stdout; piped prompts are
not supported.

### Recover an interrupted creation

Before reserving a name, `new` (including bare `lmux`) prints a JSON
`planned_creation` with exact `serviceId` and `operationId`. This is **not** a
success receipt or proof that the reservation committed. `lmux ls` also reports
`creationOperationId` for retained reservations.

```bash
lmux create-status --server SERVICE_ID --operation OPERATION_ID
lmux create --server SERVICE_ID --operation OPERATION_ID --continue --yes
```

Replace both IDs with the original values; service aliases are not accepted.
`create-status`, and `create` without `--continue`, only read recorded facts:
they do not connect, start, issue permission, or resend creation. `unknown`
(exit 1) does not mean the original request had no effect. `created` is a
historical receipt, not proof that the Mux is still open or online.

Explicit `--continue` confirms the original name/workspace/operation and may
start or reuse that same service, then sends at most one idempotent create RPC.
It does not allocate a replacement operation, delete a reservation, or attach
automatically. Non-TTY continuation requires `--yes`. A known receipt needs no
RPC; otherwise, after successful continuation use `lmux attach -t NAME`.
The existing clean-stop and recovery checks still apply. A prior-instance
permission without sufficient durable creation history is refused, not guessed
safe to replay. Closed/released operations cannot reclaim a reused name.
Repeating `new -s NAME` remains a conflict, not a recovery action.

## Start ahead of time and inspect

```bash
lmux server start --name build --workspace /absolute/path/to/project
lmux status
lmux status --server build
lmux logs --server build --limit 20
```

Replace the example path with an existing workspace. Server start is scriptable
and creates neither a Mux nor a Session. The optional alias is separate from
Mux names. Repeating the same alias/workspace reuses the service; a different
workspace or a second alias for the same service conflicts rather than rebinds.
Successful startup returns exact service and instance IDs.

For an explicit, time-limited diagnostic request, use
`lmux server start --trace-for 60` (1–3600 seconds). The duration starts when
the command is prepared, not when startup finishes. Only a newly started
instance can apply this request; reusing a service never renews or replaces its
trace. Trace contains bounded timing aggregates and fixed problem codes, not
prompts, replies, tool bodies, or credentials.

The JSON result separates `service_ready` from `trace.status`: `applied` records
historical configuration, not a guarantee of future writes; `expired` means
that configuration's deadline has passed; `not_applied_reused_instance` means
this request did not configure the reused instance; `not_confirmed` means no
matching fact was confirmed within the startup budget.
`observation_failed` reports a separate safe `errorCode` if observation fails;
the already authenticated service/instance result is preserved. `deadlineMs`
uses this machine's monotonic clock, not Unix time. With a trace request,
only `applied` returns exit code 0; other trace outcomes return 1 even if the
service is ready. Trace failure does not stop a ready service.

`lmux ls` lists Mux reservations. Untargeted `status` also includes services
without Muxes. Status is explicitly `recorded_only` / `not_probed`, not a live
health check. Logs are bounded lifecycle tails, not complete history or
conversation content. Diagnostics never start a service.

## Detach, close, or stop

- `/detach`: leave this client; retain the service and sessions.
- `lmux close -t dev`: confirm closure of one Mux and its active members;
persistent Session history is retained.
- `lmux stop --server build`: confirm stopping the service and affecting all
Muxes it hosts. Exact service IDs are also accepted.
- `lmux stop --all`: confirm a frozen target set in this namespace, not all
Loushang processes on the machine.

Noninteractive close/stop requires `--yes`; it does not force-kill or bypass
cleanup. Stop without a target does not guess from cwd. Preserve the operation
ID and follow-up command printed for incomplete closes. Historical close
reconciliation still requires an exact service ID, not an alias.

## Storage and preview upgrades

Management state and bounded lifecycle logs default to
`~/.loushang/lmux/machines/<machine>/`, partitioned by service ID. Targeted
status reports paths. Credentials and runtime control use a separate private
platform runtime namespace; `LOUSHANG_RUNTIME_DIR` overrides that root.
Do not treat live runtime control as disposable cache.
Durable admission witnesses also live under `$LOUSHANG_HOME/state/managed-deployments/`
(defaulting beneath `~/.loushang/state/`); they retain deployment identity and initialization records
and are not disposable cache either.

Instance scratch defaults to the service's `tmp/<instance-id>` directory,
with an explicit `LOUSHANG_TMPDIR` taking precedence. This does not yet impose
a disk quota on all tool output. Sessions retain their existing policy,
defaulting to `$LOUSHANG_HOME/data/sessions`; cwd and user_home are discovery
scopes, not separate default write stores.

`LOUSHANG_HOME` defaults to `~/.loushang`. Reconnect using the same user,
machine, and root overrides. Switching roots is not a way to bypass cleanup
or restart an uncertain old instance.

The current development Registry format is **14**. Older preview formats
are rejected without automatic migration. Do not delete state, locks, or
runtime records, or edit version numbers to bypass this refusal. Retain the
old state, use a matching old version to manage its service, and wait for an
explicit upgrade procedure. The legacy `loushang-mux` explicit-argument entry
remains separate and is not automatically imported or adopted.

See the [lmux contract record](../../internals/architecture/apphost/lmux-contract-m0.md)
for development and acceptance status.
11 changes: 11 additions & 0 deletions docs/internals/architecture/apphost/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
[G14 Foreground Stdio](../appserver/foreground-stdio-hosted-app-g14.md) ·
[G15 Foreground Hosted TUI Design](foreground-hosted-tui-g15.md) ·
[G17 Explicit Hosted Session Workflow](hosted-session-workflow-g17.md) ·
[lmux Managed Contract M0](lmux-contract-m0.md) ·
[ARD-004 A/A Stability Gate vs Interactive Metric Scale (accepted)](decisions/accepted/ARD-004-aa-stability-gate-vs-interactive-metric-scale.md) ·
[Hosted Product Runtime V1 Plan](../drafts/hosted-product-runtime-v1-plan.md)

## Status
Expand Down Expand Up @@ -48,6 +50,15 @@ and a later packaging decision.

## Current

The accepted [lmux M0 contract](lmux-contract-m0.md) adds an optional Linux
managed-deployment Target and shared-client/view boundaries. Pure identity,
handoff-state, stop-evidence and layout values, a Linux private-file owner and
SQLite name reservations and clean-instance lifecycle coordination are implemented
in `apphost.managed`; native service
control, managed discovery/connection coordination, Session writer
admission and the installed `lmux` entry remain unactivated. This does not
change the existing foreground or explicit G16 lifecycle.

A0.1 supplies immutable standard-library contracts and exact validation for:

- Product and profile descriptors;
Expand Down
Loading
Loading