Skip to content

fix(ops): reconcile session projections incrementally (#333) - #383

Merged
T-Auto merged 17 commits into
mainfrom
fix/333-complete-incremental
Oct 25, 2026
Merged

T-Auto merged 17 commits into
mainfrom
fix/333-complete-incremental

Conversation

@T-Auto

@T-Auto T-Auto commented Oct 24, 2026 •

Copy link
Copy Markdown
Owner

Closes #333
Closes #369
Closes #382
Refs #359, #386, #387

What was wrong

新建会话会触发 discovery/PTC 对既有 agent 重复组装完整 system prompt;PTC 与 session-shells 又会全量撤销、重建工具定义,制造额外 tools/change 和缓存失效。因此只减少 presentation probe 或只换掉 schema 深拷贝,并不能消除默认组件组合中的发布放大。

The change

保留贡献者的真实提交历史,并在此基础上补齐默认组件组合:

  • 采用 @ccch1mneyyy 的 fix(discovery): avoid reprobing unchanged agents on attach #345(947eb46):discovery 按 live context/session/policy 输入缓存后台判定,覆盖配置异步重启、服务生命周期、并发失效与卸载;空 Native provider 不再发送无效通知。
  • 保留 @ikliml666 的 fix(ptc): re-probe only the agents a change touches #368(5649b39、bf66158、0252333、9145e59)中 PTC 定向探测、definition identity surface 优化,以及 perf(prompt): read visible tool names through the scope view #378(3c3219d)的 name-only view 读取。discovery 选择 fix(discovery): avoid reprobing unchanged agents on attach #345 的失效契约,而非两套缓存直接叠加。
  • PTC 只重建受影响的继承族,保持独立根会话定义不变;合并被后续 pass 取代的请求,跟踪被 PTC 覆盖隐藏的 Native provider 修订,保留父子继承、外部 mask、同层适配器及 next-step SDK 选择语义。
  • session-shells 保留未变化的 Bash 注册与继承限制;共享 jobs/executor 服务更换时显式刷新。
  • OPS 自己的工具变化在宿主 dispatch 入口一次性捕获 scope 归属;同步嵌套的未知外部 mutation 保守失效,不能借用外层 scope。未替换或改写共享工具注册表方法。
  • 补充 same-surface both → ptc、无事件 presentation 翻转、嵌套外部祖先 mask、缓存 shadow 拒绝、16 个独立 Native/PTC 会话的 probe/event 计数与 definition identity 回归。更新双语发现文档与 changelog。

边界:低成本 policy/ownership/view 扫描仍存在,不宣称所有 reconciliation 为 O(1)。相连父子继承族可能一起重建;真正全局或未知外部变化仍保守失效。保留实时 pre-step/执行检查,不使用永久 assembly 缓存。默认关闭的 hide-official 全量优化不在本切片范围内,其安全校验保留。

Validation

Original tested head: 2a9a026. Current refreshed head: fe06fa4 (merged main 662a388; preserved both changelog sections).

npm run typecheck
  passed

node scripts/verify-gate.mjs --skip-install
  native worker unit tests: passed
  native worker rebuild/stage: passed
  Windows IPC payloads: passed
  131 suites passed
  skipped: linux-attributes, linux-shell, tui-host, tui-native (allowed platform/external-checkout skips)
  manifest: 73/59 checks
  staged runtime closure: passed
  npm pack/unpack + packed runtime closure: passed
  win32-x64: gate green

行为级验证:#345 的 14 条增量/生命周期断言通过;曾原样放到 #368 + #378 上对照运行时 8/14 失败。综合回归对每种 Native/PTC presentation 连续创建 16 个独立根会话,断言新增时旧根 probe 为 0、旧 Bash/SDK/discovery 定义身份不变、新 agent probe ≤4、注册表通知 ≤6;独立销毁不重新探测幸存者。新增两条 PTC SDK 回归覆盖相同 surface 的 presentation 切换和同步嵌套外部 mask。既有权限、取消、重叠组件行、Native/PTC 子作用域与打包测试均通过。

  • 未新增依赖,未改版本或 optionalDependencies。
  • 未改面向模型的工具 schema/参数契约。
  • 本机门禁不等于 macOS/Linux 或生产 Desktop GUI 验收;本轮未执行这些环境,不声称已测真实 0.2.1-rc.2 GUI 创建耗时。
  • Original-head PR CI: https://github.com/T-Auto/dsh-ops/actions/runs/40092122145 completed successfully, including Windows, Linux and macOS.
  • Refreshed-head local validation: npm run build, npm run typecheck, and npm run check:size passed (395 files); shells-incremental passed 2/2 assertions. The local shell-execution suite was explicitly skipped before its pinned fixture was available. The refreshed head passed CI required, Windows, Linux and macOS: https://github.com/T-Auto/dsh-ops/actions/runs/40109450303 (pull_request event). The separate append-window and text-only prompt hook fixes are follow-ups, not claimed fixed here.

Environment

Windows 11 x64;Node v24.18.0;仓库锁定的 DSH 0.2.0-rc.2 测试服务;基线 main b963fb2。独立源码工作树,本机当前 Rust worker 和 Bash IPC 重建;使用校验过的固定 Windows Bash 离线载荷。未修改真实 Desktop profile,未进行 npm/GitHub Release 发布。

本 PR 按要求仅提交供审查,不自动合并。

ccch1mneyyy and others added 15 commits October 21, 2026 03:31
PTC and discovery assembled the whole prompt once per tracked agent on
every reconcile, so creating one session paid for every session still
tracked. 38 bundles on Windows x64 grew 264/308/396/475/590/681/748/947
ms across eight session/create calls; with this change the same eight
rounds measure 195/226/270/260/295/329/358/373 ms.

Each agent now memoizes its presentation verdict against the tool names
it publishes and re-probes only when that set changes. reconcile() takes
the agents a change actually touches, and the publish-time snapshot reads
names instead of rebuilding a scope view per tool.

Refs #333, #359
`reconcile` advanced `epoch` on every call, so the passes the new `targets`
argument turns into no-ops still invalidated every published `execute` guard and
every Native shadow. Those then answered POLICY_DENIED for a scope that was still
authoritative, which is why `discovery-composition` lost its combined Native/PTC
checks and `ptc` lost its presentation-change race.

A probe also recorded its surface on the entry before the republish that consumes
it ran. A pass a later reconcile superseded therefore left the next pass reading
that surface as already published, returning early forever; the PTC verdict never
took effect and `native-result` timed out waiting for the Native/PTC projections.

A separate `published` counter now moves only when a pass actually republishes.
`ptc`'s shadows and `discovery`'s guards compare it, because `discovery`'s probe
assembles the prompt and that reconciles other scopes. Probed surfaces stay
pending until the republish commits them.

Verified: `npm run typecheck`, `npm run verify` — 125 of 127 suites pass, the two
remaining are the local-only failures `bash-ipc` and `permissions`, which need the
pinned runtime receipts this checkout does not build and fail identically on
b963fb2.
…napshot

A departure passed an empty target set, which the pass normalized to "no restriction" and then probed every tracked agent on the one pass that has nothing to probe. An empty set is now a probe-free pass: it names nobody to probe while still asking for the republish a departure owes.

The per-publish snapshot now reads tool names through one src/surface.ts helper instead of an identical surfaceOf in each plugin, and both memo keys document that names are the whole key while the presentation verdict also reads the tools:ptc-only section text, so a flip without a name change costs one pass and never a permanent wrong surface.
`surfaceOf` asked `tools.schemas()` for the names it memoizes, and that
projector rebuilds one deep copy of every visible parameter schema per call.
Read the same visible map through `tools.view(scope)` instead, keeping
`schemas()` as a fallback for a runtime that exposes no view, and pair each
name with a `WeakMap` identity for the definition the view holds. A names-only
key returns a stale hit when a scoped registration shadows a global of the same
name, so missing the shadow publishes nothing on the change that owed a
republish. Identity costs one lookup against an object already in hand rather
than the `tools.get()` pairing that would rebuild the whole view per name.
visibleTools (the tooling:shell/file prompt section and the host-shell
denial gate) asked tools.schemas() and kept only the names, paying one
deep copy of every visible definition per assembly: 34.2 ms for 258
tools at the issue's own surface shape on the published 0.2.1-rc.2
runtime, against 0.043 ms through tools.view() (~800x). Cost tracks
nested schema nodes, not payload bytes (811 KB flat = 16.5 ms; 705 KB
nested = 34.2 ms), so the fixture is pinned to the issue's measurement.

visibleNames() reads view().keys() with schemas() as the fallback for a
host whose view is not reachable, so correctness outranks the cost there.

The discovery pre-step assembly is deliberately left alone: it is the
self-correction path for a presentation that flips without the names
moving, and memoizing it there breaks the ptc-sdk projections (#369).

Tests assert the two review gaps as well: a tools/change with no registry
movement reconciles from the discovery probe memo without assembling, and
the denial gate restricts without projecting schemas. Both fail when
reverted.

Stacked on #368: surface.ts and the view machinery come from there.
Thatgfsj
Thatgfsj previously approved these changes Oct 24, 2026

@Thatgfsj Thatgfsj left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

复审无误,批准合并

@T-Auto
T-Auto merged commit 5b1b9a3 into main Oct 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment