fix(apiproxy): serve history events and projections from one log position
Review found two defects in the previous commit's ordering fix. @pku-xht: `historyStateFor` copied the attached session's events, the handler then awaited `presenterScopeFor`, and only then read the projection baseline off the still-live Session. An append during that await served events cut at N beside a baseline folded to N+1 — one response describing two moments. The same restructure had also moved the baseline read outside the `try`, so a failing snapshot escaped the structured `internal` error. Both awaits now happen before the cut: `historySourceFor` resolves which session serves the read, `presenterScopeFor` ensures the recorded composition, and `historyCutOf` then reads events and baseline adjacently with nothing between them. The whole sequence is back inside the try. The invariant judged any scoped assembly with a chain of one as an unjoined agent, which rejects a legitimate assembly in a standing preset key (that key has no parent of its own). It now gates on `context.agent` — a scope-only read is not an agent and is out of range by construction rather than by a premise about who else calls `assemble` — and asks the roster's own `composedPreset()` instead of introspecting chain length. The advisory warning uses the same relation. Also from review: the `2026-08-05-per-agent-tool-presentation` note still described `presentAs` as per-agent, which standing mounts made false and this branch's own rewording contradicts; the duplicated "process-wide unit table" argument collapses to the Agent Note with pointers from the five copies; a dead `.sort()` before `arrayContaining`; and change-history narration in the tool-cordis README.
This commit is contained in:
@@ -2,5 +2,5 @@
|
||||
# side as of the last confirmed-consistent state. Both languages carry equal authority;
|
||||
# after editing either side, bring the other along and re-record with:
|
||||
# pnpm run verify-translation-pairing --write packages/self-modification/tool-cordis/README.md
|
||||
README.md: 946d96c6f0968be3ecb162c52436f10985836b77
|
||||
README.zh.md: 8f94783f96e3652e27bdddd9cc7f54081f8c04bf
|
||||
README.md: be629ca9be5bff1e6f658f05476e8f2880804e44
|
||||
README.zh.md: 45f3536d3460106c45051093d097729a366eca1a
|
||||
|
||||
@@ -87,4 +87,4 @@ Mounting or unmounting a prompt or tool contribution changes later request prefi
|
||||
- **The sandbox is containment for honest code, not a security boundary** — host-realm helpers on the sandbox global are reachable, so mount code can reach Node; load this plugin as deliberately as you would grant a bash tool (see § Trust stance).
|
||||
- **The `ctx` façade exposes no `effect()`** — mount code cannot register a bespoke disposer; `on`/`provide`/`tools.register` are the supported cleanup paths.
|
||||
- **`vmTimeoutMs` bounds only synchronous evaluation** — an async mount body escapes it; there is no async budget on mount code.
|
||||
- **Temporary Plugins belong to the composition, not to the session that mounted one** — the group fiber and the `dyn-N` table are this row's own, so every agent the row covers shares them: registered inside an agent preset's standing mount, one session's mount is visible in another session's tool catalog and `cordis_inspect what:"temporary"`, and the second mount of an id replaces the first. That matched the host-plane row this package started as (one per process); it becomes observable once several sessions run the same preset concurrently. Per-session temporary plugins would need the group and table keyed by the calling agent.
|
||||
- **Temporary Plugins belong to the composition, not to the session that mounted one** — the group fiber and the `dyn-N` table are this row's own, so every agent the row covers shares them: registered inside an agent preset's standing mount, one session's mount is visible in another session's tool catalog and `cordis_inspect what:"temporary"`, and the second mount of an id replaces the first. Several sessions running one preset concurrently is where that becomes observable. Per-session temporary plugins would need the group and table keyed by the calling agent.
|
||||
|
||||
@@ -87,4 +87,4 @@ Namespace 插件:命名导出 `name`/`inject`/`Config`/`apply`,无默
|
||||
- **沙箱只用于约束诚实代码,并非安全边界**:可以访问沙箱全局变量上的 host realm helper,因此挂载代码可以触达 Node;加载该插件时,应当像授予 bash 工具一样慎重(见 § 信任立场)。
|
||||
- **`ctx` façade 不公开 `effect()`**:挂载代码无法注册定制 disposer;`on`/`provide`/`tools.register` 是受支持的清理路径。
|
||||
- **`vmTimeoutMs` 只限制同步求值**:async 挂载主体可逃出该边界;挂载代码没有 async 预算。
|
||||
- **临时 Plugin 属于组装,而不属于挂载它的那个会话**:group fiber 与 `dyn-N` 表是本行自己的,因此本行覆盖的每个 agent 共享它们——注册在某个 agent preset 的常驻挂载里时,一个会话挂载出来的东西会出现在另一个会话的工具目录和 `cordis_inspect what:"temporary"` 里,同一个 id 的第二次挂载会顶掉第一次。这与本包最初作为宿主平面行的语义一致(每进程一份);只有当多个会话并发运行同一 preset 时才变得可观察。要做到逐会话,需要把 group 与表按调用方 agent 建键。
|
||||
- **临时 Plugin 属于组装,而不属于挂载它的那个会话**:group fiber 与 `dyn-N` 表是本行自己的,因此本行覆盖的每个 agent 共享它们——注册在某个 agent preset 的常驻挂载里时,一个会话挂载出来的东西会出现在另一个会话的工具目录和 `cordis_inspect what:"temporary"` 里,同一个 id 的第二次挂载会顶掉第一次。多个会话并发运行同一 preset 时这一点才变得可观察。要做到逐会话,需要把 group 与表按调用方 agent 建键。
|
||||
|
||||
Reference in New Issue
Block a user