Repository navigation
fix(ops): reconcile session projections incrementally (#333) - #383
Merged
Merged
Conversation
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.
…efresh # Conflicts: # docs/CHANGELOG.md
This was referenced Oct 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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
保留贡献者的真实提交历史,并在此基础上补齐默认组件组合:
边界:低成本 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).
行为级验证:#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 子作用域与打包测试均通过。
npm run build,npm run typecheck, andnpm run check:sizepassed (395 files);shells-incrementalpassed 2/2 assertions. The local shell-execution suite was explicitly skipped before its pinned fixture was available. The refreshed head passedCI 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 按要求仅提交供审查,不自动合并。