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
@@ -1,7 +1,7 @@
# lmux shared conversation capability projection

Status: accepted implementation slice after three-perspective design review;
implementation and its code review pending.
Status: implemented and accepted; final goal-wide review completed on
2026-09-22 with no unresolved P0/P1/P2 finding.
Authority: implementation plan under the accepted
[lmux design](../drafts/lmux-managed-service-design.md#63-复用单元完整-harnesstui-会话视图不只是-tui-控件).

Expand Down Expand Up @@ -114,4 +114,16 @@ and an explicit unavailable entry; no additional authorization is inferred.
Interaction: split approval details, approve and deny, preserving their different
presentation-receipt requirements. Lifecycle: same-binding eligibility changes
invalidate prior observations, not merely attachment replacement. These local
design findings are resolved above; runtime and final goal acceptance remain open.
design findings are resolved above.

## Final acceptance

The implementation now projects the closed operation matrix through the shared
conversation state, keeps Embedded fallback behavior, and derives Hosted help,
suggestions and action eligibility from the same current binding facts. Runtime
tests cover same-binding invalidation, approval detail/approve/deny distinctions,
stale receipts, attachment and Session replacement, and unsupported image/Product
operations. The final lmux/G18 suite (1256 passed, 4 skipped) and AppHost suite
(2746 passed, 12 skipped) passed with AppHost/Harness Ruff and mypy. This accepts
the projection slice inside the local Linux lmux profile; it adds no image
transport, Product authority, GUI, or remote connection capability.
75 changes: 64 additions & 11 deletions docs/internals/architecture/apphost/lmux-contract-m0.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,15 @@
- ID: `LMUX-M0`
- Authority: normative — accepted limited Linux managed-profile contract
- Design status: accepted
- Review status: three-perspective slice reviews passed through recovery/close and shared deferred input; final goal-wide review pending
- Implementation status: partial — managed CLI preview, Linux launch/lifetime, owned transcripts, discovery, exact-instance connections, close and shared Markdown/action/input binding; full M3/M4 acceptance pending
- Review status: accepted — final architecture, lifecycle/security and Product/acceptance review completed on 2026-09-22 with no unresolved P0/P1/P2 finding
- Implementation status: complete for the accepted limited Linux managed-profile M0–M4 scope; the managed CLI remains a preview product surface
- Owner: AppHost managed deployment; sibling changes remain sibling-owned
- Tracking objective: active Linux lmux goal, branch `harness/lmux-managed-service`
- Evidence scope: this document is a working-tree snapshot of an in-flight goal.
Its per-slice implementation and pass records describe the authoring working
tree, not this commit's tree. Most referenced implementation
(`apphost.managed.*`, `transcript/writer_lease.py`, `journal/_rooted_io.py`,
`coding/cli/lmux*.py`, `appserver/managed_mux.py`) and the G18 reevaluation
tooling were still uncommitted when this snapshot was taken, so those claims
cannot be reproduced from this commit alone. Treat `已实现`/`已接线`/`passed`
below as working-tree observations until the matching code slice lands.
- Tracking objective: [#607](https://github.com/zhnt/loushang/issues/607), lmux M3/M4 acceptance closure
- Evidence scope: sections 1–96 are the chronological implementation record and
retain their then-current wording. Section 97 is the final status and evidence
index for the delivered implementation. Earlier “pending”, “partial” and
working-tree qualifications are historical observations, not the current
acceptance status.

## 1. 本地基线与推进记录

Expand Down Expand Up @@ -4700,3 +4697,59 @@ unchanged from that wheel. Independent review confirms that CLI only presents
and inspects the original operation, obtains confirmation and revalidates exact
identity through the existing creation owner. Durable history and authorization
remain in AppHost. Retain the exact seven-file group and boundary scans.

## 97. M0–M4 正式验收收口(2026-09-22)

[#607](https://github.com/zhnt/loushang/issues/607) 只关闭既有 Linux 本地
managed profile 的验收缺口,没有增加协议、权限、远程/SSH 能力或新 Product。
正式 restore 在第 22 个样本稳定暴露的 `startup_failed` 已定位为 registry
数据库目录的描述符关闭处于“已保留、尚未确认”短窗口时,启动 fence 将同一
目录的 `cleanup_pending` 当成持久债务。修复仍由原 `_ManagedMuxFence`、原
journal 和原期限保管操作:先精确释放已经进入的 lifecycle fence;lifecycle
fence 有任何清理债立即失败;仅对数据库目录的瞬时关闭窗口让出一次、最多
10 ms;再次观察到债务、未知释放、关闭或期限耗尽均 fail closed。未重建 owner,
未重放已经产生效果的操作,也未放宽 registry、Session 或认证准入。

最终冻结来源为 `16c482e551859db89346b49c9a548adb128535c3`,wheel 为
`.artifacts/lmux-acceptance-607-v4/loushang-0.1.0-py3-none-any.whl`,SHA-256
`ca27bba3f76c46ff1825c2c9419617bf2d4807ebe431c6f3e2c39f2654cf90f3`。
两个新正式 campaign 均为单进程不间断采集,没有 checkpoint、pause 或 resume:

| case | report | 完整性 | verdict |
| --- | --- | --- | --- |
| `managed-product-first-use` | `.artifacts/lmux-acceptance-607-v4/formal-first-use/report.json`(SHA-256 `5da32135…`) | 44/44 valid;4 warmup + 40 measured | pass |
| `managed-product-history-restore` | `.artifacts/lmux-acceptance-607-v4/formal-history-restore/report.json`(SHA-256 `cbf45823…`) | 44/44 valid;4 warmup + 40 measured | pass |

两侧 source commit 与 wheel 哈希完全相同,三套 CPython 3.11.15 隔离安装的
依赖、入口和来源核验通过。first-use 覆盖首条回复、审批待办/详情/批准后唯一
工具效果、中断后 producer 结算及下一轮唯一回复;restore 覆盖 128 轮历史、
旧代精确停止、换代启动、完整历史帧及新代精确停止。两者都跨过此前的固定
失败点,并保留原实例、Session、终端和外层 owner 的结算门禁。

既有 `managed-mux` 和 `managed-product-history-warm` 报告没有改写或重采;
其 ARD-004 重评文件分别绑定原报告 SHA-256 `d6e243ef…` 与 `446af8f1…`,
verdict 均为 pass。它们明确记录 `claims.is_new_measurement=false`、
`claims.is_performance_acceptance=false`:结论只表示按已接受的 25% 稳定性 /
30% 回归判据未检出超限回归,不证明无回归,也不能检出 30% 以下回归。新正式
first-use/restore 报告同样不构成性能提升声明。

最终回归门禁:lmux/G18 开发集 1256 passed、4 skipped;AppHost 全套
2746 passed、12 skipped;AppHost 与 Harness 的 Ruff、mypy 全部通过。
定向 managed mux 创建/恢复/关闭组 107 passed。新增反例覆盖 lifecycle fence
与 database transaction 两种争用源、瞬时关闭结算、持续清理债只等待一次、
未知释放不重试、原期限不续期;只读快照测试也先等待已有异步诊断写入完成,
不再把合法后台写入误报为查询副作用。

最终三视角结论:

- 架构:AppHost/AppService 仍持有部署与生命周期 authority,Coding 与
Harnesstui 只做组合和呈现;没有新增反向依赖、跨层授权或 RPC 内持锁。
- 生命周期与安全:原 owner、原身份、原 deadline、精确 stop 和未知清理
fail-closed 均保留;一次有界让步不能跨越持续债务或未知 release。
- Product 与验收:安装入口、无目标只读探测、跨 cwd 重连、审批、断连/中断、
历史恢复和完整清理均由既有真实 PTY/installed 证据及本轮正式报告覆盖;
诊断记录没有被冒充为正式样本。

因此 M0–M4 在本文限定的 Linux 本地 managed profile 内验收完成,未留
P0/P1/P2。上文 “Shared data-root admission delta” 仍是独立候选安全合同,
不属于 lmux 验收结果,也不因本节获得实现或接受状态。
17 changes: 14 additions & 3 deletions docs/internals/architecture/apphost/lmux-live-probe-plan.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# lmux 无目标连接:公共只读探测接线

状态:公共 operation 首版及 CLI 接线已实现,定向验证/复核中,尚未验收。补足既有 managed-service 设计中的
“多候选中唯一在线 Mux 自动进入”,不替代完整交付验收。
状态:已实现并验收(2026-09-22)。补足既有 managed-service 设计中的
“多候选中唯一在线 Mux 自动进入”;最终完整交付验收见
[M0 合同 §97](lmux-contract-m0.md#97-m0m4-正式验收收口2026-09-22)。

## 边界

Expand Down Expand Up @@ -82,4 +83,14 @@ revision 恰增加一,其余完整 state 不变。停止、身份变化、其
- 首项耗尽期限后后续服务零原生准入;取消 prepare/close waiter 不丢原
任务;全部值已产生但末项 close 失败仍禁止进入选择器或最终 Runner。
- 最终认证失败不换目标;新旧入口、单候选流程和非 TTY 前置拒绝不回退。
- 设计/实现复核后,再以真实安装环境验证额外认证的首用成本。
- 真实安装环境已验证额外认证的首用成本;结果受 ARD-004 判定范围约束。

## 最终验收记录

公共 probe、CLI 两阶段清理及最终重新认证已进入正式安装证据。单候选从
不同 cwd 重连、同服务多 Mux 共用认证、多候选/pending/unknown 不误选、
候选变化、期限耗尽、取消与 close 失回执、最终认证失败不改选均有回归覆盖。
正式 first-use 与 history restore 各 44/44 valid 并通过比较;AppHost 全套
2746 passed、12 skipped,AppHost/Harness Ruff 与 mypy 通过。最终复核确认
probe 仍只返回只读事实,不 attach、不启动、不恢复、不修改登记,也不把
`authenticated_present` 当成控制权或未来在线保证。
39 changes: 39 additions & 0 deletions docs/internals/architecture/apphost/lmux-managed-output-capture.md
Original file line number Diff line number Diff line change
Expand Up @@ -4147,3 +4147,42 @@ first-use 尚无正式 A/A(建议新合同生效后再启动,避免白跑一
**V10 影响:** 三个阻塞中的两个(长历史、managed-mux)在新合同下有有效结论;
剩余 ① restore 的 `startup_failed`(已交产品侧)② first-use 尚无正式 A/A
(建议在新合同生效后启动,避免再跑一次注定 inconclusive 的采集)。

### 110900 M3/M4 最终收口:restore 缺陷修复,first-use 与 restore 正式通过

本节是 [#607](https://github.com/zhnt/loushang/issues/607) 的最终状态,覆盖并
关闭 110815 所列两个剩余阻塞;前述失败报告及其当时结论保持原样。

restore 在第 22 个样本出现的 `startup_failed` 已复现到 Product:另一原生
操作正在完成 registry 数据库目录的描述符关闭时,`_ManagedMuxFence` 取得
lifecycle fence 后会遇到 database `busy`,随后把该短窗口误判为持久清理债。
修复先由原 owner 精确释放已进入的 fence,并只允许数据库目录关闭结算一次、
最多 10 ms;持续债务、lifecycle fence 债务、未知 release、关闭和 deadline
仍立即失败。回归先在旧提交稳定失败,修复后覆盖 fence/transaction 两个
争用源;持续 cleanup 只观察一次让步后仍失败,不存在无限重试或第二 owner。

最终 wheel:`.artifacts/lmux-acceptance-607-v4/loushang-0.1.0-py3-none-any.whl`,
SHA-256 `ca27bba3f76c46ff1825c2c9419617bf2d4807ebe431c6f3e2c39f2654cf90f3`,
source commit `16c482e551859db89346b49c9a548adb128535c3`。A/B 两侧及 observer
均为独立 CPython 3.11.15 安装,依赖锁、入口、origin、源提交与 wheel 字节
核验通过。

- `.artifacts/lmux-acceptance-607-v4/formal-first-use/report.json`:
`complete-record-only`,44/44 valid(4 warmup + 40 measured),comparison
pass;单进程连续采集,无 checkpoint/resume/pause。
- `.artifacts/lmux-acceptance-607-v4/formal-history-restore/report.json`:
同为 44/44 valid 和 pass,跨过旧固定失败点;每个样本保留旧/新代精确
identity、完整历史、终端、stop 和外层 owner 结算证据。

110815 已发布的两个 ARD-004 重评继续有效:`managed-mux` 与长历史 warm
均为 pass,且 `claims.is_new_measurement=false`、
`claims.is_performance_acceptance=false`。不得把判据变更写成重采或证明无
回归;30% 以下的回归仍不可检出。新 first-use/restore A/A 也只验证测量
稳定性与同 wheel 等价性,不是性能提升声明。

最终回归:lmux/G18 1256 passed、4 skipped;AppHost 2746 passed、12 skipped;
定向 managed mux 107 passed;AppHost/Harness Ruff 与 mypy 全绿。架构、
生命周期/安全、Product/验收三视角无未解决 P0/P1/P2。安装入口、跨 cwd
重连、只读 probe、审批、真实 PTY 断连/中断、历史换代、精确 stop 和清理
门禁均由正式或既有冻结安装证据覆盖;诊断 `valid=false` 记录没有被升级为
正式样本。M0–M4 在限定 Linux 本地 managed profile 内验收完成。
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# LMUX M4 Linux 性能验收增量

状态:部分子项已局部评审并开展诊断采集;正式配对验收和完整三视角
评审尚未完成,不构成性能结论。实际通过项、失败样本和待办见
[推进记录](lmux-managed-output-capture.md),下文候选指标不等于验收通过。
状态:accepted(2026-09-22)。`managed-mux`、首次 Product 使用、长历史
warm 与换代 restore 的正式 A/A 证据均已取得有效 pass,完整三视角评审无
未解决 P0/P1/P2。该结论关闭 M4 测量与回归资格门禁,不宣称性能提升;
ARD-004 的 30% 以下回归不可检出限制继续适用。历史失败、诊断和实施过程见
[推进记录](lmux-managed-output-capture.md)。

## 已取得冻结安装功能诊断:运行中真实 PTY 突然断连

Expand Down Expand Up @@ -414,3 +416,28 @@ outer预算必须按串行阶段上界核算,覆盖原600秒seed、认证、
seed/连接结算、旧canonical未完成即重启、start关闭失败、错误服务/同代身份、
新旧摘要不一致、跨代回执串用、错误累计起点及任意stop/outer失败,均不得
晋级正式样本或checkpoint。仍沿用原20对与失败保留规则。

## 最终 M4 验收记录(2026-09-22)

冻结提交 `16c482e551859db89346b49c9a548adb128535c3` 和 wheel SHA-256
`ca27bba3f76c46ff1825c2c9419617bf2d4807ebe431c6f3e2c39f2654cf90f3`
完成两个新的不间断 A/A campaign:

- `managed-product-first-use`:44/44 valid(4 warmup + 40 measured),
comparison pass;八个冻结指标、三个 fresh 子场景、至少四个真实终端、
唯一工具效果、producer 结算和 exact stop 均通过 validator。
- `managed-product-history-restore`:44/44 valid(4 warmup + 40 measured),
comparison pass;每个样本均验证 128 轮/256 消息历史、旧代停止、不同
native identity 的新代启动、完整恢复帧和新代停止。

原 `managed-mux` 与 `managed-product-history-warm` campaign 由 ARD-004
只读工具重评为 pass;重评文件绑定原 report SHA-256,不改原数据,并声明
其不是新测量或独立性能验收。全部 verdict 的含义均是“在接受的统计合同下
未检出超过 30% 的回归”。它们不支持“没有回归”、低于该阈值的量化结论或
相对其他版本的提速声明。

先前 restore 的 `startup_failed` 报告保持原样。产品根因是共享 registry
目录描述符的瞬时关闭窗口与启动 fence 争用;窄修复只允许原 owner 在原
deadline 内让出一次最多 10 ms,持续/未知清理债仍失败。修复后的正式采集
跨过原固定失败点并完成全部样本。最终测试与三视角结果见
[M0 合同 §97](lmux-contract-m0.md#97-m0m4-正式验收收口2026-09-22)。
15 changes: 13 additions & 2 deletions src/loushang/apphost/managed/mux_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ async def _acquire_permission(self, deadline: float) -> None:
return
except ManagedStorageError as error:
if (error.code != "busy" or self._exit_attempted
or journal._fence.cleanup_pending or journal._database.cleanup_pending):
or journal._fence.cleanup_pending):
raise
# No check_*/ADMIT/CAS/Session effect has occurred. Release
# this exact read context; never retry an uncertain release.
Expand All @@ -638,11 +638,22 @@ async def _acquire_permission(self, deadline: float) -> None:
self._exit_attempted = True
self._context.__exit__(None, None, None)
self._entered = False
if journal._fence.cleanup_pending or journal._database.cleanup_pending:
if journal._fence.cleanup_pending:
raise ManagedStorageError("unavailable") from None
self._context = None
self._discard_permission()
self._exit_attempted = False # Prior read's release is confirmed.
if journal._database.cleanup_pending:
# Another native operation may be between retaining and
# confirming one descriptor close. Yield once, but never
# wait through persistent or unknown database cleanup debt.
await asyncio.sleep(min(0.01, max(0.0, deadline - monotonic())))
_check_deadline(deadline)
if self._closed or self._exit_attempted:
raise ManagedStorageError("closed")
if journal._fence.cleanup_pending or journal._database.cleanup_pending:
raise
continue
_check_deadline(deadline)
await asyncio.sleep(min(0.01, max(0.0, deadline - monotonic())))

Expand Down
Loading
Loading